[odb-api] 05/21: upstream 0.17.1

Alastair McKinstry mckinstry at moszumanska.debian.org
Wed Aug 30 06:42:49 UTC 2017


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

mckinstry pushed a commit to branch debian/master
in repository odb-api.

commit 357a55fb675188f87ea71230172c4c3fa2ce3309
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Tue Aug 29 13:50:19 2017 +0100

    upstream 0.17.1
---
 CMakeLists.txt                                     |    14 +-
 VERSION.cmake                                      |     2 +-
 cmake/VERSION.cmake                                |     4 +-
 .../GreatCMakeCookOff/CheckCXX11Features.cmake     |     4 +-
 cmake/ecbuild_add_persistent.cmake                 |     4 +-
 cmake/ecbuild_add_resources.cmake                  |     7 +
 cmake/ecbuild_check_c_source_return.cmake          |    14 +-
 cmake/ecbuild_check_compiler.cmake                 |     4 +
 cmake/ecbuild_check_cxx11.cmake                    |     2 +-
 cmake/ecbuild_check_cxx_source_return.cmake        |    10 +-
 cmake/ecbuild_check_fortran_source_return.cmake    |     6 +-
 cmake/ecbuild_check_functions.cmake                |     2 +
 cmake/ecbuild_check_os.cmake                       |     1 +
 cmake/ecbuild_config.h.in                          |     2 +
 cmake/ecbuild_find_fortranlibs.cmake               |     4 +-
 cmake/ecbuild_find_package.cmake                   |     6 +-
 cmake/ecbuild_system.cmake                         |     1 +
 cmake/ecbuild_try_run.cmake                        |   200 +
 cmake/ecbuild_use_package.cmake                    |    58 +-
 cmake/fortran_features/CheckFortranFeatures.cmake  |     4 +-
 cmake/sg.pl                                        |     5 +-
 ecbuild/cmake/VERSION.cmake                        |     4 +-
 .../GreatCMakeCookOff/CheckCXX11Features.cmake     |     4 +-
 ecbuild/cmake/ecbuild_add_persistent.cmake         |     4 +-
 ecbuild/cmake/ecbuild_add_resources.cmake          |     7 +
 ecbuild/cmake/ecbuild_check_c_source_return.cmake  |    14 +-
 ecbuild/cmake/ecbuild_check_compiler.cmake         |     4 +
 ecbuild/cmake/ecbuild_check_cxx11.cmake            |     2 +-
 .../cmake/ecbuild_check_cxx_source_return.cmake    |    10 +-
 .../ecbuild_check_fortran_source_return.cmake      |     6 +-
 ecbuild/cmake/ecbuild_check_functions.cmake        |     2 +
 ecbuild/cmake/ecbuild_check_os.cmake               |     1 +
 ecbuild/cmake/ecbuild_config.h.in                  |     2 +
 ecbuild/cmake/ecbuild_find_fortranlibs.cmake       |     4 +-
 ecbuild/cmake/ecbuild_find_package.cmake           |     6 +-
 ecbuild/cmake/ecbuild_system.cmake                 |     1 +
 ecbuild/cmake/ecbuild_try_run.cmake                |   200 +
 ecbuild/cmake/ecbuild_use_package.cmake            |    58 +-
 .../fortran_features/CheckFortranFeatures.cmake    |     4 +-
 ecbuild/cmake/sg.pl                                |     5 +-
 ecbuild/doc/upload.py                              |     5 +-
 ecbuild/examples/cpp-bundle-nested/CMakeLists.txt  |    14 +
 ecbuild/examples/cpp-bundle-nested/VERSION.cmake   |     1 +
 .../examples/cpp-bundle-nested/bar/CMakeLists.txt  |    39 +
 .../examples/cpp-bundle-nested/bar/VERSION.cmake   |     1 +
 ecbuild/examples/cpp-bundle-nested/bar/bar.c       |     5 +
 ecbuild/examples/cpp-bundle-nested/bar/bar.h       |     6 +
 .../cpp-bundle-nested/bar/foo/CMakeLists.txt       |    37 +
 .../cpp-bundle-nested/bar/foo/VERSION.cmake        |     1 +
 ecbuild/examples/cpp-bundle-nested/bar/foo/foo.c   |     3 +
 ecbuild/examples/cpp-bundle-nested/bar/foo/foo.h   |     6 +
 ecbuild/examples/cpp-bundle-nested/bar/foo/main.cc |     9 +
 ecbuild/examples/cpp-bundle-nested/bar/foo/test.cc |    12 +
 ecbuild/examples/cpp-bundle-nested/bar/main.cc     |    12 +
 ecbuild/examples/cpp-bundle-nested/bar/test.cc     |    12 +
 .../examples/cpp-bundle-nested/baz/CMakeLists.txt  |    39 +
 .../examples/cpp-bundle-nested/baz/VERSION.cmake   |     1 +
 ecbuild/examples/cpp-bundle-nested/baz/baz.c       |     5 +
 ecbuild/examples/cpp-bundle-nested/baz/baz.h       |     6 +
 ecbuild/examples/cpp-bundle-nested/baz/main.cc     |    12 +
 ecbuild/examples/cpp-bundle-nested/baz/test.cc     |    12 +
 ecbuild/examples/cxx11/CMakeLists.txt              |    32 +
 ecbuild/examples/cxx11/README.md                   |     6 +
 ecbuild/examples/cxx11/VERSION.cmake               |     1 +
 ecbuild/examples/cxx11/compute.cc                  |    29 +
 ecbuild/share/ecbuild/cmake/VERSION.cmake          |     4 +-
 .../GreatCMakeCookOff/CheckCXX11Features.cmake     |     4 +-
 .../ecbuild/cmake/ecbuild_add_persistent.cmake     |     4 +-
 .../ecbuild/cmake/ecbuild_add_resources.cmake      |     7 +
 .../cmake/ecbuild_check_c_source_return.cmake      |    14 +-
 .../ecbuild/cmake/ecbuild_check_compiler.cmake     |     4 +
 .../share/ecbuild/cmake/ecbuild_check_cxx11.cmake  |     2 +-
 .../cmake/ecbuild_check_cxx_source_return.cmake    |    10 +-
 .../ecbuild_check_fortran_source_return.cmake      |     6 +-
 .../ecbuild/cmake/ecbuild_check_functions.cmake    |     2 +
 ecbuild/share/ecbuild/cmake/ecbuild_check_os.cmake |     1 +
 ecbuild/share/ecbuild/cmake/ecbuild_config.h.in    |     2 +
 .../ecbuild/cmake/ecbuild_find_fortranlibs.cmake   |     4 +-
 .../share/ecbuild/cmake/ecbuild_find_package.cmake |     6 +-
 ecbuild/share/ecbuild/cmake/ecbuild_system.cmake   |     1 +
 ecbuild/share/ecbuild/cmake/ecbuild_try_run.cmake  |   200 +
 .../share/ecbuild/cmake/ecbuild_use_package.cmake  |    58 +-
 .../fortran_features/CheckFortranFeatures.cmake    |     4 +-
 ecbuild/share/ecbuild/cmake/sg.pl                  |     5 +-
 .../share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake |    87 +
 .../share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake  |    87 +
 .../ecbuild/toolchains/ecmwf-XC30-Intel.cmake      |    87 +
 eckit/CMakeLists.txt                               |    24 +-
 eckit/TODO                                         |     3 -
 eckit/VERSION.cmake                                |     2 +-
 eckit/eckit.sublime-project                        |    71 +-
 eckit/regressions/CMakeLists.txt                   |     4 +-
 eckit/regressions/ECKIT-166.cc                     |    29 +
 eckit/regressions/ECKIT-166.sh.in                  |    15 +
 eckit/regressions/ECKIT-175.cc                     |     1 -
 eckit/regressions/ECKIT-221.cc                     |    55 +
 eckit/regressions/ECKIT-221.sh.in                  |    41 +
 eckit/src/CMakeLists.txt                           |     2 -
 eckit/src/eckit/CMakeLists.txt                     |    28 +-
 eckit/src/eckit/config/Configuration.cc            |   172 +-
 eckit/src/eckit/config/Configuration.h             |    37 +-
 eckit/src/eckit/config/Configured.h                |     6 +
 eckit/src/eckit/config/JSONConfiguration.cc        |    73 -
 eckit/src/eckit/config/JSONConfiguration.h         |    95 +-
 eckit/src/eckit/config/LibEcKit.cc                 |    25 +-
 eckit/src/eckit/config/LibEcKit.h                  |    16 +-
 eckit/src/eckit/config/LocalConfiguration.cc       |    87 +-
 eckit/src/eckit/config/LocalConfiguration.h        |    17 +-
 eckit/src/eckit/config/Parametrisation.h           |     6 +
 eckit/src/eckit/config/Resource.cc                 |    27 -
 eckit/src/eckit/config/Resource.h                  |   123 +-
 eckit/src/eckit/config/ResourceBase.cc             |    45 +-
 eckit/src/eckit/config/ResourceBase.h              |    72 +
 eckit/src/eckit/config/YAMLConfiguration.cc        |    79 +
 eckit/src/eckit/config/YAMLConfiguration.h         |    52 +
 eckit/src/eckit/container/BloomFilter.cc           |    96 +
 eckit/src/eckit/container/BloomFilter.h            |    81 +
 eckit/src/eckit/container/CacheManager.h           |    19 +-
 eckit/src/eckit/container/Trie.cc                  |   166 +
 eckit/src/eckit/container/Trie.h                   |    80 +
 eckit/src/eckit/exception/Exceptions.cc            |    57 +-
 eckit/src/eckit/exception/Exceptions.h             |     5 +-
 eckit/src/eckit/filesystem/LocalPathName.cc        |    67 +-
 eckit/src/eckit/filesystem/LocalPathName.h         |     5 +
 eckit/src/eckit/filesystem/PathExpander.cc         |   153 +
 eckit/src/eckit/filesystem/PathExpander.h          |    54 +
 eckit/src/eckit/io/AIOHandle.cc                    |     6 +-
 eckit/src/eckit/io/Buffer.h                        |    66 +-
 eckit/src/eckit/io/DataHandle.cc                   |     8 +-
 eckit/src/eckit/io/DataHandle.h                    |     4 +-
 eckit/src/eckit/io/FileDescHandle.cc               |    31 +-
 eckit/src/eckit/io/FileDescHandle.h                |     9 +-
 eckit/src/eckit/io/Pipeline.cc                     |   161 +
 eckit/src/eckit/io/Pipeline.h                      |    84 +
 eckit/src/eckit/io/StdPipe.cc                      |    17 +-
 eckit/src/eckit/io/StdPipe.h                       |    17 +-
 eckit/src/eckit/log/CodeLocation.cc                |     4 +-
 eckit/src/eckit/memory/Counted.h                   |     3 -
 eckit/src/eckit/memory/MemoryPool.cc               |     9 +-
 eckit/src/eckit/memory/Padded.h                    |    10 +-
 eckit/src/eckit/mpi/Comm.cc                        |    87 +-
 eckit/src/eckit/mpi/Comm.h                         |    38 +
 eckit/src/eckit/mpi/Parallel.cc                    |    66 +
 eckit/src/eckit/mpi/Parallel.h                     |     7 +
 eckit/src/eckit/mpi/ParallelRequest.h              |     3 +
 eckit/src/eckit/mpi/ParallelStatus.h               |     3 +
 eckit/src/eckit/mpi/Serial.cc                      |    38 +-
 eckit/src/eckit/mpi/Serial.h                       |     4 +
 eckit/src/eckit/parser/JSON.cc                     |    44 +-
 eckit/src/eckit/parser/JSONParser.cc               |   272 +-
 eckit/src/eckit/parser/JSONParser.h                |    25 +-
 eckit/src/eckit/parser/ObjectParser.cc             |   311 +
 eckit/src/eckit/parser/ObjectParser.h              |    59 +
 eckit/src/eckit/parser/StreamParser.cc             |    50 +-
 eckit/src/eckit/parser/StreamParser.h              |     6 +
 eckit/src/eckit/parser/StringTools.cc              |    33 +-
 eckit/src/eckit/parser/StringTools.h               |    11 +-
 eckit/src/eckit/parser/YAMLParser.cc               |   720 +
 eckit/src/eckit/parser/YAMLParser.h                |    91 +
 eckit/src/eckit/runtime/Application.cc             |     2 +-
 eckit/src/eckit/runtime/Main.cc                    |    11 +-
 eckit/src/eckit/runtime/Main.h                     |    16 +-
 eckit/src/eckit/system/Library.cc                  |    30 +
 eckit/src/eckit/system/Library.h                   |    33 +-
 eckit/src/eckit/testing/CommSetup.h                |    46 +
 eckit/src/eckit/testing/Setup.h                    |     9 +-
 eckit/src/eckit/thread/ThreadControler.cc          |     2 +-
 eckit/src/eckit/types/Date.cc                      |    10 +-
 eckit/src/eckit/types/FloatCompare.cc              |     2 +
 eckit/src/eckit/types/Fraction.cc                  |   205 +-
 eckit/src/eckit/types/Fraction.h                   |   360 +-
 eckit/src/eckit/utils/Hash.h                       |     2 +
 eckit/src/eckit/utils/MD5.cc                       |     4 +
 eckit/src/eckit/utils/MD5.h                        |    37 +-
 eckit/src/eckit/utils/Regex.cc                     |    21 +-
 eckit/src/eckit/utils/Regex.h                      |     7 +-
 eckit/src/eckit/utils/Translator.cc                |    25 +-
 eckit/src/eckit/utils/Translator.h                 |     4 +
 eckit/src/eckit/value/DateTimeContent.cc           |   110 +
 eckit/src/eckit/value/DateTimeContent.h            |   112 +
 eckit/src/eckit/value/TimeContent.cc               |   110 +
 eckit/src/eckit/value/TimeContent.h                |   112 +
 eckit/src/eckit/value/Value.cc                     |    14 +
 eckit/src/eckit/value/Value.h                      |   136 +-
 eckit/src/experimental/CMakeLists.txt              |     1 -
 eckit/src/tests/CMakeLists.txt                     |    21 -
 eckit/src/tests/config/CMakeLists.txt              |    11 -
 eckit/src/tests/config/test_config.cc              |   128 -
 eckit/src/tests/config/test_resource.cc            |   125 -
 eckit/src/tests/container/CMakeLists.txt           |    24 -
 eckit/src/tests/filesystem/CMakeLists.txt          |    22 -
 eckit/src/tests/filesystem/test_localpathname.cc   |   199 -
 eckit/src/tests/log/test_log_channels.cc           |   180 -
 eckit/src/tests/mpi/eckit_test_mpi.cc              |   556 -
 eckit/src/tests/mpi/eckit_test_mpi_addcomm.cc      |    28 -
 eckit/src/tests/parser/CMakeLists.txt              |    14 -
 eckit/src/tests/system/test_system.cc              |    92 -
 eckit/src/tests/types/test_fraction.cc             |   149 -
 eckit/src/tests/utils/test_string_tools.cc         |   183 -
 eckit/src/tests/value/test_value.cc                |  2624 --
 eckit/src/tests/value/test_value_properties.cc     |   119 -
 eckit/tests/CMakeLists.txt                         |    25 +
 eckit/tests/config/CMakeLists.txt                  |    10 +
 eckit/tests/config/test_configuration.cc           |   287 +
 eckit/tests/config/test_resource.cc                |   113 +
 eckit/tests/container/CMakeLists.txt               |    34 +
 .../tests/container/benchmark_densemap.cc          |     0
 eckit/tests/container/test_bloomfilter.cc          |    41 +
 eckit/{src => }/tests/container/test_btree.cc      |     0
 eckit/{src => }/tests/container/test_cache_lru.cc  |     0
 eckit/{src => }/tests/container/test_densemap.cc   |     0
 .../tests/container/test_sharedmemarray.cc         |     0
 eckit/tests/container/test_trie.cc                 |   250 +
 .../tests => tests/experimental}/CMakeLists.txt    |     0
 .../experimental}/singleton/CMakeLists.txt         |     0
 .../experimental}/singleton/TestBuilder1.cc        |     0
 .../experimental}/singleton/TestBuilder2.cc        |     0
 .../experimental}/singleton/TestFactory.cc         |     0
 .../experimental}/singleton/TestFactory.h          |     0
 .../experimental}/singleton/test_singleton.cc      |     0
 eckit/tests/filesystem/CMakeLists.txt              |    35 +
 eckit/{src => }/tests/filesystem/test_aiohandle.cc |     0
 eckit/tests/filesystem/test_localpathname.cc       |   256 +
 .../{src => }/tests/filesystem/test_multihandle.cc |     0
 eckit/tests/filesystem/test_pathexpander.cc        |    53 +
 .../tests/filesystem/test_restarthandle.cc         |     0
 eckit/{src => }/tests/geometry/CMakeLists.txt      |     0
 eckit/{src => }/tests/geometry/test_kdtree.cc      |     0
 eckit/{src => }/tests/io/CMakeLists.txt            |     0
 eckit/{src => }/tests/io/test_datablob.cc          |     0
 eckit/{src => }/tests/io/test_filepool.cc          |     0
 eckit/{src => }/tests/large_file/CMakeLists.txt    |     0
 .../{src => }/tests/large_file/test_large_file.cc  |     0
 eckit/{src => }/tests/linalg/CMakeLists.txt        |     0
 eckit/{src => }/tests/linalg/test_la_factory.cc    |     0
 eckit/{src => }/tests/linalg/test_la_linalg.cc     |     0
 eckit/{src => }/tests/linalg/test_la_sparse.cc     |     0
 eckit/{src => }/tests/linalg/test_la_streaming.cc  |     0
 eckit/{src => }/tests/linalg/util.h                |     0
 eckit/{src => }/tests/log/CMakeLists.txt           |     0
 eckit/{src => }/tests/log/test_colour.cc           |     0
 eckit/{src => }/tests/log/test_log.cc              |     0
 eckit/{src => }/tests/log/test_log_callback.cc     |     0
 eckit/tests/log/test_log_channels.cc               |   181 +
 eckit/{src => }/tests/log/test_log_threads.cc      |     0
 .../{src => }/tests/log/test_log_user_channels.cc  |     0
 eckit/{src => }/tests/maths/CMakeLists.txt         |     0
 eckit/{src => }/tests/maths/test_eigen.cc          |     0
 eckit/{src => }/tests/maths/test_matrix.cc         |     0
 eckit/{src => }/tests/memory/CMakeLists.txt        |     0
 eckit/{src => }/tests/memory/test_counted.cc       |     0
 eckit/{src => }/tests/memory/test_factory.cc       |     0
 eckit/{src => }/tests/memory/test_scoped_ptr.cc    |     0
 eckit/{src => }/tests/memory/test_shared_ptr.cc    |     0
 eckit/{src => }/tests/memory_map/CMakeLists.txt    |     0
 .../{src => }/tests/memory_map/test_memory_map.cc  |     0
 eckit/{src => }/tests/mpi/CMakeLists.txt           |     0
 eckit/tests/mpi/eckit_test_mpi.cc                  |   575 +
 eckit/tests/mpi/eckit_test_mpi_addcomm.cc          |    31 +
 eckit/{src => }/tests/option/CMakeLists.txt        |     0
 .../tests/option/eckit_test_option_cmdargs.cc      |     0
 .../tests/option/eckit_test_option_factory.cc      |     0
 eckit/tests/parser/2.1.yaml                        |     3 +
 eckit/tests/parser/2.10.yaml                       |     8 +
 eckit/tests/parser/2.11.yaml                       |     9 +
 eckit/tests/parser/2.12.yaml                       |     9 +
 eckit/tests/parser/2.13.yaml                       |     4 +
 eckit/tests/parser/2.14.yaml                       |     4 +
 eckit/tests/parser/2.15.yaml                       |     8 +
 eckit/tests/parser/2.16.yaml                       |     8 +
 eckit/tests/parser/2.17.yaml                       |     7 +
 eckit/tests/parser/2.18.yaml                       |     7 +
 eckit/tests/parser/2.19.yaml                       |     5 +
 eckit/tests/parser/2.2.yaml                        |     3 +
 eckit/tests/parser/2.20.yaml                       |     6 +
 eckit/tests/parser/2.21.yaml                       |     4 +
 eckit/tests/parser/2.22.yaml                       |     4 +
 eckit/tests/parser/2.23.yaml                       |    13 +
 eckit/tests/parser/2.24.yaml                       |    14 +
 eckit/tests/parser/2.25.yaml                       |     7 +
 eckit/tests/parser/2.26.yaml                       |     7 +
 eckit/tests/parser/2.27.yaml                       |    29 +
 eckit/tests/parser/2.28.yaml                       |    26 +
 eckit/tests/parser/2.3.yaml                        |     8 +
 eckit/tests/parser/2.4.yaml                        |     8 +
 eckit/tests/parser/2.5.yaml                        |     3 +
 eckit/tests/parser/2.6.yaml                        |     5 +
 eckit/tests/parser/2.7.yaml                        |    10 +
 eckit/tests/parser/2.8.yaml                        |    10 +
 eckit/tests/parser/2.9.yaml                        |     8 +
 eckit/tests/parser/CMakeLists.txt                  |    29 +
 eckit/tests/parser/cfg.1.yaml                      |     6 +
 eckit/{src => }/tests/parser/test_json.cc          |     0
 eckit/{src => }/tests/parser/test_json_metadata.cc |     0
 eckit/{src => }/tests/parser/test_stream_parser.cc |     0
 eckit/tests/parser/test_yaml.cc                    |   323 +
 eckit/{src => }/tests/runtime/CMakeLists.txt       |     0
 eckit/{src => }/tests/runtime/boost_auto_param.h   |     0
 eckit/{src => }/tests/runtime/test_context.cc      |     0
 eckit/{src => }/tests/runtime/test_producer.cc     |     0
 eckit/{src => }/tests/serialisation/CMakeLists.txt |     0
 .../tests/serialisation/test_file_stream.cc        |     0
 .../tests/serialisation/test_streamable.cc         |     0
 eckit/{src => }/tests/system/CMakeLists.txt        |     0
 eckit/tests/system/test_system.cc                  |    97 +
 eckit/{src => }/tests/thread/CMakeLists.txt        |     0
 eckit/{src => }/tests/thread/test_mutex.cc         |     0
 eckit/{src => }/tests/types/CMakeLists.txt         |     0
 .../tests/types/test-double-compare-speed.cc       |     0
 eckit/{src => }/tests/types/test_cache.cc          |     0
 eckit/{src => }/tests/types/test_doublecompare.cc  |     0
 eckit/{src => }/tests/types/test_fixedstring.cc    |     0
 eckit/{src => }/tests/types/test_floatcompare.cc   |     0
 eckit/tests/types/test_fraction.cc                 |   160 +
 eckit/{src => }/tests/types/test_print_vector.cc   |     0
 eckit/{src => }/tests/types/test_uuid.cc           |     0
 eckit/{src => }/tests/utils/CMakeLists.txt         |     0
 eckit/{src => }/tests/utils/hash-performance.cc    |     0
 eckit/{src => }/tests/utils/test_md4.cc            |     0
 eckit/{src => }/tests/utils/test_md5.cc            |     0
 eckit/{src => }/tests/utils/test_rendezvoushash.cc |     0
 eckit/{src => }/tests/utils/test_sha1.cc           |     0
 eckit/tests/utils/test_string_tools.cc             |   199 +
 eckit/{src => }/tests/utils/test_tokenizer.cc      |     0
 eckit/{src => }/tests/utils/test_translator.cc     |     0
 eckit/{src => }/tests/utils/test_xxhash.cc         |     0
 eckit/{src => }/tests/value/AnyKeyParams.cc        |     0
 eckit/{src => }/tests/value/AnyKeyParams.h         |     0
 eckit/{src => }/tests/value/CMakeLists.txt         |     0
 eckit/tests/value/test_value.cc                    |  2624 ++
 eckit/{src => }/tests/value/test_value_params.cc   |     0
 eckit/tests/value/test_value_properties.cc         |   119 +
 metkit/CMakeLists.txt                              |     4 +-
 metkit/VERSION.cmake                               |     2 +-
 metkit/bamboo/INTEL-env.sh                         |     1 +
 metkit/etc/language.json                           |    50 +-
 metkit/etc/param.json                              | 37828 +++++++++----------
 metkit/metkit.sublime-project                      |    35 +-
 metkit/src/metkit/MarsLanguage.cc                  |   183 +-
 metkit/src/metkit/MarsLanguage.h                   |    10 +-
 metkit/src/metkit/MarsParser.h                     |     4 +-
 metkit/src/metkit/MarsRequest.h                    |    16 +
 metkit/src/metkit/config/LibMetkit.cc              |     6 +-
 metkit/src/metkit/types/Type.cc                    |    12 +
 metkit/src/metkit/types/Type.h                     |     2 +
 metkit/src/metkit/types/TypeEnum.cc                |     2 +-
 metkit/src/metkit/types/TypeParam.cc               |   280 +-
 metkit/src/metkit/types/TypeParam.h                |     4 +-
 metkit/src/tests/CMakeLists.txt                    |     5 +
 odb-tools/.gitignore                               |     8 +
 odb-tools/CMakeLists.txt                           |    93 +
 odb-tools/VERSION.cmake                            |     1 +
 odb-tools/bamboo/CLANG-env.sh                      |    10 +
 odb-tools/bamboo/INTEL-env.sh                      |    11 +
 odb-tools/bamboo/env.sh                            |     4 +
 odb-tools/bamboo/flags.cmake                       |     1 +
 odb-tools/src/CMakeLists.txt                       |    16 +
 .../src/odb_api => odb-tools/src}/migrator/2oda    |     0
 odb-tools/src/migrator/CMakeLists.txt              |   112 +
 odb-tools/src/migrator/FakeODBIterator.cc          |   160 +
 odb-tools/src/migrator/FakeODBIterator.h           |    96 +
 odb-tools/src/migrator/ImportODBTool.cc            |   207 +
 odb-tools/src/migrator/ImportODBTool.h             |    66 +
 .../odb_api => odb-tools/src}/migrator/Makefile    |     0
 .../src}/migrator/Makefile.old                     |     0
 .../src}/migrator/MigrateHandler.cc                |     0
 .../src}/migrator/MigrateHandler.h                 |     0
 odb-tools/src/migrator/MigratorTool.cc             |   144 +
 .../src}/migrator/MigratorTool.h                   |     0
 odb-tools/src/migrator/ODB2ODATool.cc              |   139 +
 .../src}/migrator/ODB2ODATool.h                    |     0
 odb-tools/src/migrator/ODBIterator.cc              |   253 +
 odb-tools/src/migrator/ODBIterator.h               |    97 +
 .../src}/migrator/ODBMigratorModule.cc             |     0
 .../src}/migrator/ODBMigratorModule.h              |     0
 .../src}/migrator/Odb2_to_odb1_era.f90             |     0
 odb-tools/src/migrator/OldODBReader.h              |    25 +
 odb-tools/src/migrator/ReptypeGenIterator.cc       |   234 +
 .../src}/migrator/ReptypeGenIterator.h             |     0
 .../src}/migrator/TSQLReader.cc                    |     0
 .../src}/migrator/TSQLReader.h                     |     0
 .../src/odb_api => odb-tools/src}/migrator/all     |     0
 .../odb_api => odb-tools/src}/migrator/diurnal.f90 |     0
 odb-tools/src/migrator/migrator_api.cc             |    38 +
 .../src}/migrator/migrator_api.h                   |     0
 .../odb_api => odb-tools/src}/migrator/odb1.f90    |     0
 .../odb_api => odb-tools/src}/migrator/odb2.f90    |     0
 .../src}/migrator/odb2_flag_definitions.f90        |     0
 odb-tools/src/migrator/odb2oda.cc                  |    66 +
 .../odb_api => odb-tools/src}/migrator/odbdump.h   |     0
 .../odb_api => odb-tools/src}/migrator/pyodbdump.i |     0
 .../src}/migrator/pyodbdump_example.py             |     0
 .../src}/migrator/solar_elevation.f90              |     0
 .../src}/migrator/solar_elevation.sc               |     0
 .../src}/migrator/test_migrator.ecml               |     0
 odb-tools/src/odb2_to_odb1/CMakeLists.txt          |    27 +
 .../src}/odb2_to_odb1/Odb2Odb1.cc                  |     0
 .../src}/odb2_to_odb1/Odb2Odb1.h                   |     0
 .../src}/odb2_to_odb1/Odb2Odb1Main.cc              |     0
 .../src}/odb2_to_odb1/mpi_wrapper.F90              |     0
 .../odb_api => odb-tools/src}/odb2_to_odb1/mpif.h  |     0
 odb-tools/src/odb2_to_odb1/odb_wrapper.F90         |   753 +
 odb-tools/src/odb2_to_odb1/odbi.F90                |   286 +
 odb-tools/src/tests/CMakeLists.txt                 |    74 +
 odb-tools/src/tests/test_import_odb.sh             |    41 +
 odb-tools/src/tests/test_import_odb_dispatching.sh |    40 +
 .../src}/tests/test_odb2_to_odb1.sh                |     0
 odb/.gitignore                                     |     1 +
 odb/CMakeLists.txt                                 |   152 +
 odb/README                                         |    44 +
 odb/VERSION.cmake                                  |     1 +
 odb/cmake/CMakeLists.txt                           |     8 +
 odb/cmake/odb_add_schema.cmake                     |   137 +
 odb/cmake/odb_create_glue.cmake                    |    57 +
 odb/cmake/odb_create_static_stub.cmake             |    28 +
 odb/cmake/odb_generate_table_names.py              |    84 +
 odb/cmake/odb_link_schemas.cmake                   |    72 +
 odb/cmake/odb_set_environment.cmake                |    50 +
 odb/odb-import.cmake.in                            |    15 +
 odb/share/CMakeLists.txt                           |     3 +
 odb/share/odb/DUMMY/DUMMY.IOASSIGN                 |     5 +
 odb/share/odb/DUMMY/DUMMY.dd                       |    11 +
 odb/share/odb/DUMMY/DUMMY.sch                      |     8 +
 odb/share/odb/an_depar.cmap                        |     4 +
 odb/share/odb/date.cmap                            |     5 +
 odb/share/odb/dir.cmap                             |     3 +
 odb/share/odb/fg_depar.cmap                        |     4 +
 odb/share/odb/modoro.cmap                          |     4 +
 odb/share/odb/obstype.cmap                         |     3 +
 odb/share/odb/oldwind.cmap                         |     3 +
 odb/share/odb/press.cmap                           |     3 +
 odb/share/odb/press_hpa.cmap                       |     5 +
 odb/share/odb/procid.cmap                          |     3 +
 odb/share/odb/ps.cmap                              |     3 +
 odb/share/odb/ps_hpa.cmap                          |     4 +
 odb/share/odb/rtablel_2031                         |    34 +
 odb/share/odb/rtablel_2047                         |    50 +
 odb/share/odb/rtablel_2063                         |    66 +
 odb/share/odb/rtablel_2095                         |    98 +
 odb/share/odb/rtablel_21023                        |  1026 +
 odb/share/odb/rtablel_21151                        |  1154 +
 odb/share/odb/rtablel_2127                         |   130 +
 odb/share/odb/rtablel_21279                        |  1282 +
 odb/share/odb/rtablel_2159                         |   162 +
 odb/share/odb/rtablel_22047                        |  2050 +
 odb/share/odb/rtablel_2215                         |   218 +
 odb/share/odb/rtablel_2255                         |   258 +
 odb/share/odb/rtablel_2319                         |   322 +
 odb/share/odb/rtablel_2399                         |   402 +
 odb/share/odb/rtablel_2511                         |   514 +
 odb/share/odb/rtablel_2639                         |   642 +
 odb/share/odb/rtablel_2799                         |   802 +
 odb/share/odb/stalt.cmap                           |     3 +
 odb/share/odb/status.cmap                          |     4 +
 odb/share/odb/t.cmap                               |     3 +
 odb/share/odb/t2m.cmap                             |     3 +
 odb/share/odb/target.cmap                          |     3 +
 odb/share/odb/tbr.cmap                             |     3 +
 odb/share/odb/tcelsius.cmap                        |     4 +
 odb/share/odb/tfahrenheit.cmap                     |     5 +
 odb/share/odb/time.cmap                            |     4 +
 odb/share/odb/tslot.cmap                           |     3 +
 odb/share/odb/wind.cmap                            |     3 +
 odb/src/CMakeLists.txt                             |    39 +
 odb/src/aux/CMakeLists.txt                         |   118 +
 odb/src/aux/binio.c                                |   174 +
 odb/src/aux/bits.c                                 |   511 +
 odb/src/aux/cardinality.c                          |   270 +
 odb/src/aux/cma_attach.c                           |    94 +
 odb/src/aux/cma_bin_file.c                         |    39 +
 odb/src/aux/cma_bin_info.c                         |    22 +
 odb/src/aux/cma_byteswap.c                         |    37 +
 odb/src/aux/cma_close.c                            |   127 +
 odb/src/aux/cma_debug.c                            |    10 +
 odb/src/aux/cma_detach.c                           |    59 +
 odb/src/aux/cma_filesize.c                         |    20 +
 odb/src/aux/cma_flpcheck.c                         |   398 +
 odb/src/aux/cma_flperr.F90                         |   111 +
 odb/src/aux/cma_get_concat.c                       |    28 +
 odb/src/aux/cma_get_concat_byname.c                |    12 +
 odb/src/aux/cma_get_ddrs.c                         |    67 +
 odb/src/aux/cma_get_report.c                       |    58 +
 odb/src/aux/cma_info.c                             |   286 +
 odb/src/aux/cma_is_packed.c                        |    24 +
 odb/src/aux/cma_on_mrfs.c                          |    23 +
 odb/src/aux/cma_open.c                             |   605 +
 odb/src/aux/cma_prt_stat.F90                       |   126 +
 odb/src/aux/cma_read.c                             |     9 +
 odb/src/aux/cma_readb.c                            |     9 +
 odb/src/aux/cma_readc.c                            |    12 +
 odb/src/aux/cma_readf.c                            |     9 +
 odb/src/aux/cma_readi.c                            |     9 +
 odb/src/aux/cma_rewind.c                           |    80 +
 odb/src/aux/cma_seek.c                             |     9 +
 odb/src/aux/cma_seekb.c                            |     9 +
 odb/src/aux/cma_seekf.c                            |     9 +
 odb/src/aux/cma_seeki.c                            |     9 +
 odb/src/aux/cma_stat.c                             |    12 +
 odb/src/aux/cma_wrapup.c                           |    27 +
 odb/src/aux/cma_write.c                            |     9 +
 odb/src/aux/cma_writeb.c                           |     9 +
 odb/src/aux/cma_writec.c                           |    11 +
 odb/src/aux/cma_writef.c                           |     9 +
 odb/src/aux/cma_writei.c                           |     9 +
 odb/src/aux/codb2netcdf.F90                        |    67 +
 odb/src/aux/codb_netcdf.c                          |   774 +
 odb/src/aux/dca.c                                  |  1574 +
 odb/src/aux/ds.c                                   |   489 +
 odb/src/aux/dtnum.c                                |   100 +
 odb/src/aux/f_odb_layer.F90                        |   248 +
 odb/src/aux/fileutil.c                             |   101 +
 odb/src/aux/generic.c                              |  1616 +
 odb/src/aux/history.c                              |   209 +
 odb/src/aux/idx.c                                  |  2031 +
 odb/src/aux/info.c                                 |  2474 ++
 odb/src/aux/ioassign_hash.c                        |    48 +
 odb/src/aux/ioassign_read.c                        |   421 +
 odb/src/aux/ioassign_write.c                       |    50 +
 odb/src/aux/ioconcat.c                             |    31 +
 odb/src/aux/iocopy.c                               |    48 +
 odb/src/aux/iogetattr.c                            |   220 +
 odb/src/aux/iogetsize.c                            |    91 +
 odb/src/aux/ioknowncmd.c                           |   162 +
 odb/src/aux/ioprealloc.c                           |   108 +
 odb/src/aux/iosetbuf.c                             |    65 +
 odb/src/aux/iostrdup.c                             |   405 +
 odb/src/aux/iostuff_init.c                         |   135 +
 odb/src/aux/iotimes.c                              |    79 +
 odb/src/aux/lzw.c                                  |   391 +
 odb/src/aux/magicwords.c                           |   166 +
 odb/src/aux/md5sub.c                               |   504 +
 odb/src/aux/memmap.c                               |    95 +
 odb/src/aux/memory.c                               |   581 +
 odb/src/aux/newio.c                                |  1955 +
 odb/src/aux/odb2mysql.c                            |   131 +
 odb/src/aux/odbcrc.c                               |   166 +
 odb/src/aux/odbcs_conf.c                           |   491 +
 odb/src/aux/odbcs_error.c                          |    96 +
 odb/src/aux/odbcs_signal.c                         |   101 +
 odb/src/aux/odbcs_wrappers.c                       |   482 +
 odb/src/aux/odbdump.c                              |   490 +
 odb/src/aux/odbi_client.c                          |  1579 +
 odb/src/aux/odbi_common.c                          |   385 +
 odb/src/aux/odbi_direct.c                          |  1341 +
 odb/src/aux/odbi_server.c                          |   708 +
 odb/src/aux/odbi_shared.c                          |   310 +
 odb/src/aux/odbsql.c                               |   563 +
 odb/src/aux/pcma.c                                 |   305 +
 odb/src/aux/pcma_1.c                               |   575 +
 odb/src/aux/pcma_11to19.c                          |   510 +
 odb/src/aux/pcma_2.c                               |   412 +
 odb/src/aux/pcma_21to29.c                          |   442 +
 odb/src/aux/pcma_255.c                             |    48 +
 odb/src/aux/pcma_3.c                               |   146 +
 odb/src/aux/pcma_31to39.c                          |   468 +
 odb/src/aux/pcma_4.c                               |   722 +
 odb/src/aux/pcma_5.c                               |   547 +
 odb/src/aux/pcma_9.c                               |   320 +
 odb/src/aux/pcma_mdis.c                            |    26 +
 odb/src/aux/qtar_sub.c                             |   848 +
 odb/src/aux/result.c                               |  3486 ++
 odb/src/aux/runcmd.c                               |    87 +
 odb/src/aux/simul.c                                |   305 +
 odb/src/aux/swapbytes.c                            |   120 +
 odb/src/aux/upcma.c                                |   638 +
 odb/src/aux/util.c                                 |   252 +
 odb/src/aux/util_ccode.c                           |   148 +
 odb/src/aux/util_filehandler.c                     |   102 +
 odb/src/aux/util_iobuf.c                           |   147 +
 odb/src/aux/util_stat.c                            |    47 +
 odb/src/aux/vpack_bits.c                           |   333 +
 odb/src/compiler/CMakeLists.txt                    |    25 +
 odb/src/compiler/cmd.c                             |    38 +
 odb/src/compiler/copyfile.c                        |   106 +
 odb/src/compiler/defines.c                         |   109 +
 odb/src/compiler/genc.c                            |  5912 +++
 odb/src/compiler/lex.l                             |  1127 +
 odb/src/compiler/list.c                            |   219 +
 odb/src/compiler/odb98.c                           |  2121 ++
 odb/src/compiler/regex.c                           |   101 +
 odb/src/compiler/tree.c                            |  6005 +++
 odb/src/compiler/yacc.y                            |  3302 ++
 odb/src/ddl.CCMA/CCMA.ddl                          |     3 +
 odb/src/ddl.CCMA/CCMA.dep                          |   139 +
 odb/src/ddl.CCMA/CMakeLists.txt                    |   427 +
 odb/src/ddl.CCMA/adjust_ccma_distribid.sql         |     1 +
 odb/src/ddl.CCMA/adjust_seqnos.sql                 |     1 +
 odb/src/ddl.CCMA/aeolus.h                          |     1 +
 odb/src/ddl.CCMA/ak_resat_averaging_kernel.sql     |     1 +
 odb/src/ddl.CCMA/alloc.h                           |     1 +
 odb/src/ddl.CCMA/allsky.h                          |     1 +
 odb/src/ddl.CCMA/amv.sql                           |     1 +
 odb/src/ddl.CCMA/amv2.sql                          |     1 +
 odb/src/ddl.CCMA/amv_flag.sql                      |     1 +
 odb/src/ddl.CCMA/amv_flag2.sql                     |     1 +
 odb/src/ddl.CCMA/auxiliary.h                       |     1 +
 odb/src/ddl.CCMA/bits.h                            |     1 +
 odb/src/ddl.CCMA/body.h                            |     1 +
 odb/src/ddl.CCMA/caifc1.sql                        |     1 +
 odb/src/ddl.CCMA/camelo_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/camelo_robody.sql                 |     1 +
 odb/src/ddl.CCMA/canaco_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/canaco_robhdr_ccma.sql            |     1 +
 odb/src/ddl.CCMA/canaco_robody.sql                 |     1 +
 odb/src/ddl.CCMA/cancer_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/cancer_robody.sql                 |     1 +
 odb/src/ddl.CCMA/cantik_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/cantik_robody.sql                 |     1 +
 odb/src/ddl.CCMA/carcfo.sql                        |     1 +
 odb/src/ddl.CCMA/castor.sql                        |     1 +
 odb/src/ddl.CCMA/caviso_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/caviso_robody.sql                 |     1 +
 odb/src/ddl.CCMA/cavodk_robhdr.sql                 |     1 +
 odb/src/ddl.CCMA/cavodk_robody.sql                 |     1 +
 odb/src/ddl.CCMA/cdrhook.h                         |     1 +
 odb/src/ddl.CCMA/cloud_sink.h                      |     1 +
 odb/src/ddl.CCMA/cma.h                             |     1 +
 odb/src/ddl.CCMA/collocated_imager_information.h   |     1 +
 odb/src/ddl.CCMA/conv.h                            |     1 +
 odb/src/ddl.CCMA/conv_hdr.sql                      |     1 +
 odb/src/ddl.CCMA/data_radar_station.sql            |     1 +
 odb/src/ddl.CCMA/date_time.sql                     |     1 +
 odb/src/ddl.CCMA/dca.h                             |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_allsky_body.sql     |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_body.sql            |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_gbrad.sql           |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_hdr.sql             |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_raingg.sql          |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_update_1.sql        |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_update_2.sql        |     1 +
 odb/src/ddl.CCMA/ecmwf_matchup_update_3.sql        |     1 +
 odb/src/ddl.CCMA/ecmwf_matchupsink.sql             |     1 +
 odb/src/ddl.CCMA/ecset.sql                         |     1 +
 odb/src/ddl.CCMA/ecstdlib.h                        |     1 +
 odb/src/ddl.CCMA/ensemble.h                        |     1 +
 odb/src/ddl.CCMA/errstat.h                         |     1 +
 odb/src/ddl.CCMA/exp_info_1.sql                    |     1 +
 odb/src/ddl.CCMA/fc_sens_obs.sql                   |     1 +
 odb/src/ddl.CCMA/fcq_robhdr_0.sql                  |     1 +
 odb/src/ddl.CCMA/fcq_robhdr_1.sql                  |     1 +
 odb/src/ddl.CCMA/fcq_robhdr_2.sql                  |     1 +
 odb/src/ddl.CCMA/fcq_robody_0.sql                  |     1 +
 odb/src/ddl.CCMA/fcq_robody_1.sql                  |     1 +
 odb/src/ddl.CCMA/fcq_robody_2.sql                  |     1 +
 odb/src/ddl.CCMA/fix_date_and_time.sql             |     1 +
 odb/src/ddl.CCMA/fixresatlen.sql                   |     1 +
 odb/src/ddl.CCMA/forecast_diagnostic.h             |     1 +
 odb/src/ddl.CCMA/funcs.h                           |     1 +
 odb/src/ddl.CCMA/gather4poolmask.sql               |     1 +
 odb/src/ddl.CCMA/gather4poolmask_counts.sql        |     1 +
 odb/src/ddl.CCMA/gbrad.h                           |     1 +
 odb/src/ddl.CCMA/gbrad_body_rr.sql                 |     1 +
 odb/src/ddl.CCMA/gbrad_rr.sql                      |     1 +
 odb/src/ddl.CCMA/get_soe_resat.sql                 |     1 +
 odb/src/ddl.CCMA/getgbradid.sql                    |     1 +
 odb/src/ddl.CCMA/getlimbid.sql                     |     1 +
 odb/src/ddl.CCMA/getsatid.sql                      |     1 +
 odb/src/ddl.CCMA/getsatid_resat.sql                |     1 +
 odb/src/ddl.CCMA/getsatobid.sql                    |     1 +
 odb/src/ddl.CCMA/getsfcobsid.sql                   |     1 +
 odb/src/ddl.CCMA/global_enkf_1.sql                 |     1 +
 odb/src/ddl.CCMA/global_enkf_10.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_100.sql               |     1 +
 odb/src/ddl.CCMA/global_enkf_105.sql               |     1 +
 odb/src/ddl.CCMA/global_enkf_110.sql               |     1 +
 odb/src/ddl.CCMA/global_enkf_115.sql               |     1 +
 odb/src/ddl.CCMA/global_enkf_120.sql               |     1 +
 odb/src/ddl.CCMA/global_enkf_15.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_2.sql                 |     1 +
 odb/src/ddl.CCMA/global_enkf_20.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_25.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_3.sql                 |     1 +
 odb/src/ddl.CCMA/global_enkf_30.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_35.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_4.sql                 |     1 +
 odb/src/ddl.CCMA/global_enkf_40.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_45.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_5.sql                 |     1 +
 odb/src/ddl.CCMA/global_enkf_50.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_55.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_60.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_65.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_70.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_75.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_80.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_85.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_90.sql                |     1 +
 odb/src/ddl.CCMA/global_enkf_95.sql                |     1 +
 odb/src/ddl.CCMA/gnssro.h                          |     1 +
 odb/src/ddl.CCMA/hdr.h                             |     1 +
 odb/src/ddl.CCMA/hop_canari_conv.sql               |     1 +
 odb/src/ddl.CCMA/hop_canari_robhdr.sql             |     1 +
 odb/src/ddl.CCMA/hop_canari_robody.sql             |     1 +
 odb/src/ddl.CCMA/hretr_canari_robody.sql           |     1 +
 odb/src/ddl.CCMA/hretr_canari_satbody.sql          |     1 +
 odb/src/ddl.CCMA/idx.h                             |     1 +
 odb/src/ddl.CCMA/info.h                            |     1 +
 odb/src/ddl.CCMA/limb.h                            |     1 +
 odb/src/ddl.CCMA/magicwords.h                      |     1 +
 odb/src/ddl.CCMA/manda_gene_body.sql               |     1 +
 odb/src/ddl.CCMA/manda_gene_hdr.sql                |     1 +
 odb/src/ddl.CCMA/manda_laelalo.sql                 |     1 +
 odb/src/ddl.CCMA/matchup_allsky_body.sql           |     1 +
 odb/src/ddl.CCMA/matchup_atovs_pred.sql            |     1 +
 odb/src/ddl.CCMA/matchup_body.sql                  |     1 +
 odb/src/ddl.CCMA/matchup_gbrad.sql                 |     1 +
 odb/src/ddl.CCMA/matchup_hdr.sql                   |     1 +
 odb/src/ddl.CCMA/matchup_raingg.sql                |     1 +
 odb/src/ddl.CCMA/matchup_sensorlist.sql            |     1 +
 odb/src/ddl.CCMA/matchup_update_1.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_10.sql             |     1 +
 odb/src/ddl.CCMA/matchup_update_2.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_3.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_4.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_5.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_6.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_7.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_8.sql              |     1 +
 odb/src/ddl.CCMA/matchup_update_9.sql              |     1 +
 odb/src/ddl.CCMA/matchupsink.sql                   |     1 +
 odb/src/ddl.CCMA/mdi.h                             |     1 +
 odb/src/ddl.CCMA/mkglobstab.sql                    |     1 +
 odb/src/ddl.CCMA/mkglobstab_gpsro.sql              |     1 +
 odb/src/ddl.CCMA/mobhdrca_obsort.sql               |     1 +
 odb/src/ddl.CCMA/modsurf.h                         |     1 +
 odb/src/ddl.CCMA/namecfg.h                         |     1 +
 odb/src/ddl.CCMA/obatabs_robhdr.sql                |     1 +
 odb/src/ddl.CCMA/obs_boxes.sql                     |     1 +
 odb/src/ddl.CCMA/obsdist.sql                       |     1 +
 odb/src/ddl.CCMA/obsdist_allsky.sql                |     1 +
 odb/src/ddl.CCMA/obsdist_allsky_body.sql           |     1 +
 odb/src/ddl.CCMA/obsdist_auxiliary.sql             |     1 +
 odb/src/ddl.CCMA/obsdist_auxiliary_body.sql        |     1 +
 odb/src/ddl.CCMA/obsdist_body.sql                  |     1 +
 odb/src/ddl.CCMA/obsdist_errstat.sql               |     1 +
 odb/src/ddl.CCMA/obsdist_gbrad.sql                 |     1 +
 odb/src/ddl.CCMA/obsdist_gbrad_body.sql            |     1 +
 odb/src/ddl.CCMA/obsdist_hdr.sql                   |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2allsky_body.sql       |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2auxiliary_body.sql    |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2body.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2gbrad_body.sql        |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2radar_body.sql        |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2radiance_body.sql     |     1 +
 odb/src/ddl.CCMA/obsdist_hdr2raingg_body.sql       |     1 +
 .../obsdist_hdr2resat_averaging_kernel.sql         |     1 +
 odb/src/ddl.CCMA/obsdist_index.sql                 |     1 +
 odb/src/ddl.CCMA/obsdist_index2hdr.sql             |     1 +
 odb/src/ddl.CCMA/obsdist_limb.sql                  |     1 +
 odb/src/ddl.CCMA/obsdist_modsurf.sql               |     1 +
 odb/src/ddl.CCMA/obsdist_poolno.sql                |     1 +
 odb/src/ddl.CCMA/obsdist_radar.sql                 |     1 +
 odb/src/ddl.CCMA/obsdist_radar_body.sql            |     1 +
 odb/src/ddl.CCMA/obsdist_radar_station.sql         |     1 +
 odb/src/ddl.CCMA/obsdist_radiance.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_radiance_body.sql         |     1 +
 odb/src/ddl.CCMA/obsdist_raingg.sql                |     1 +
 odb/src/ddl.CCMA/obsdist_raingg_body.sql           |     1 +
 odb/src/ddl.CCMA/obsdist_resat.sql                 |     1 +
 .../ddl.CCMA/obsdist_resat_averaging_kernel.sql    |     1 +
 odb/src/ddl.CCMA/obsdist_sat.sql                   |     1 +
 odb/src/ddl.CCMA/obsdist_satob.sql                 |     1 +
 odb/src/ddl.CCMA/obsdist_update_1.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_10.sql             |     1 +
 odb/src/ddl.CCMA/obsdist_update_2.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_3.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_4.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_5.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_6.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_7.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_8.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_update_9.sql              |     1 +
 odb/src/ddl.CCMA/obsdist_windows.sql               |     1 +
 odb/src/ddl.CCMA/obshor.sql                        |     1 +
 odb/src/ddl.CCMA/obsort_gnssro_body.sql            |     1 +
 odb/src/ddl.CCMA/obsort_hdr2allsky_body.sql        |     1 +
 odb/src/ddl.CCMA/obsort_hdr2auxiliary_body.sql     |     1 +
 odb/src/ddl.CCMA/obsort_hdr2gbrad_body.sql         |     1 +
 odb/src/ddl.CCMA/obsort_hdr2gnssro_body.sql        |     1 +
 odb/src/ddl.CCMA/obsort_hdr2radar_body.sql         |     1 +
 odb/src/ddl.CCMA/obsort_hdr2raingg_body.sql        |     1 +
 odb/src/ddl.CCMA/obsort_hdr2scatt_body.sql         |     1 +
 odb/src/ddl.CCMA/obsortca_auxiliary.sql            |     1 +
 odb/src/ddl.CCMA/obsortca_body.sql                 |     1 +
 odb/src/ddl.CCMA/obsortca_errstat.sql              |     1 +
 odb/src/ddl.CCMA/obsortca_hdr.sql                  |     1 +
 odb/src/ddl.CCMA/obsortca_hdr2auxiliary_body.sql   |     1 +
 odb/src/ddl.CCMA/obsortca_hdr2body.sql             |     1 +
 odb/src/ddl.CCMA/obsortca_index.sql                |     1 +
 odb/src/ddl.CCMA/obsortca_update_1.sql             |     1 +
 odb/src/ddl.CCMA/obsortca_update_2.sql             |     1 +
 odb/src/ddl.CCMA/obsortca_update_3.sql             |     1 +
 odb/src/ddl.CCMA/obstype.h                         |     1 +
 odb/src/ddl.CCMA/odb.h                             |     1 +
 odb/src/ddl.CCMA/odb98.flags                       |     1 +
 odb/src/ddl.CCMA/odb_info.sql                      |     1 +
 odb/src/ddl.CCMA/odb_macros.h                      |     1 +
 odb/src/ddl.CCMA/odbcrc.h                          |     1 +
 odb/src/ddl.CCMA/odbmd5.h                          |     1 +
 odb/src/ddl.CCMA/pcma_extern.h                     |     1 +
 odb/src/ddl.CCMA/poolmask_1.sql                    |     1 +
 odb/src/ddl.CCMA/poolmask_2.sql                    |     1 +
 odb/src/ddl.CCMA/ppcode.h                          |     1 +
 odb/src/ddl.CCMA/privpub.h                         |     1 +
 odb/src/ddl.CCMA/prtdpst_robhdr.sql                |     1 +
 odb/src/ddl.CCMA/prtdpst_robody.sql                |     1 +
 odb/src/ddl.CCMA/radar.h                           |     1 +
 odb/src/ddl.CCMA/radar_station.h                   |     1 +
 odb/src/ddl.CCMA/radiance.h                        |     1 +
 odb/src/ddl.CCMA/raingg.h                          |     1 +
 odb/src/ddl.CCMA/raingg_body_rr.sql                |     1 +
 odb/src/ddl.CCMA/raingg_rr.sql                     |     1 +
 odb/src/ddl.CCMA/resat.h                           |     1 +
 odb/src/ddl.CCMA/revmatchup_body.sql               |     1 +
 odb/src/ddl.CCMA/revmatchup_hdr.sql                |     1 +
 odb/src/ddl.CCMA/robhdr.sql                        |     1 +
 odb/src/ddl.CCMA/robhdr_gbrad_get_rr.sql           |     1 +
 odb/src/ddl.CCMA/robhdr_gbrad_put_rr.sql           |     1 +
 odb/src/ddl.CCMA/robhdr_grid_distribute.sql        |     1 +
 odb/src/ddl.CCMA/robhdr_rad.sql                    |     1 +
 odb/src/ddl.CCMA/robhdr_raingg_get_rr.sql          |     1 +
 odb/src/ddl.CCMA/robhdr_raingg_put_rr.sql          |     1 +
 odb/src/ddl.CCMA/robhdr_screen.sql                 |     1 +
 odb/src/ddl.CCMA/robhdr_screen_conv.sql            |     1 +
 odb/src/ddl.CCMA/robhdr_tc.sql                     |     1 +
 odb/src/ddl.CCMA/robhdrca_obsort.sql               |     1 +
 odb/src/ddl.CCMA/robody.sql                        |     1 +
 odb/src/ddl.CCMA/robody_gbrad_get_rr.sql           |     1 +
 odb/src/ddl.CCMA/robody_gbrad_put_rr.sql           |     1 +
 odb/src/ddl.CCMA/robody_rad.sql                    |     1 +
 odb/src/ddl.CCMA/robody_raingg_get_rr.sql          |     1 +
 odb/src/ddl.CCMA/robody_raingg_put_rr.sql          |     1 +
 odb/src/ddl.CCMA/robody_tc.sql                     |     1 +
 odb/src/ddl.CCMA/robody_traj.sql                   |     1 +
 odb/src/ddl.CCMA/sat.h                             |     1 +
 odb/src/ddl.CCMA/sat_aeolus.sql                    |     1 +
 odb/src/ddl.CCMA/sat_atovs.sql                     |     1 +
 odb/src/ddl.CCMA/sat_gpsro.sql                     |     1 +
 odb/src/ddl.CCMA/sat_lrad.sql                      |     1 +
 odb/src/ddl.CCMA/sat_radar.sql                     |     1 +
 odb/src/ddl.CCMA/sat_satob.sql                     |     1 +
 odb/src/ddl.CCMA/sat_ssmi.sql                      |     1 +
 odb/src/ddl.CCMA/satbody_allsky.sql                |     1 +
 odb/src/ddl.CCMA/satbody_atovs.sql                 |     1 +
 odb/src/ddl.CCMA/satbody_gpsro.sql                 |     1 +
 odb/src/ddl.CCMA/satbody_radar.sql                 |     1 +
 odb/src/ddl.CCMA/sathdr_cloud_sink.sql             |     1 +
 odb/src/ddl.CCMA/sathdr_radar.sql                  |     1 +
 odb/src/ddl.CCMA/satob.h                           |     1 +
 odb/src/ddl.CCMA/scatt.h                           |     1 +
 odb/src/ddl.CCMA/scatt.sql                         |     1 +
 odb/src/ddl.CCMA/scatt_flag.sql                    |     1 +
 odb/src/ddl.CCMA/sensor.h                          |     1 +
 odb/src/ddl.CCMA/set_active.sql                    |     1 +
 odb/src/ddl.CCMA/set_active_smos.sql               |     1 +
 odb/src/ddl.CCMA/setup_tovscv.sql                  |     1 +
 odb/src/ddl.CCMA/setup_tovscv_cloud_sink.sql       |     1 +
 odb/src/ddl.CCMA/small.sql                         |     1 +
 odb/src/ddl.CCMA/smos.h                            |     1 +
 odb/src/ddl.CCMA/ssmi1d.h                          |     1 +
 odb/src/ddl.CCMA/stat_obs_1.sql                    |     1 +
 odb/src/ddl.CCMA/sugoms.sql                        |     1 +
 odb/src/ddl.CCMA/suobarea.sql                      |     1 +
 odb/src/ddl.CCMA/suobarea_limb.sql                 |     1 +
 odb/src/ddl.CCMA/suobarea_sat.sql                  |     1 +
 odb/src/ddl.CCMA/suobarea_satob.sql                |     1 +
 odb/src/ddl.CCMA/suobarea_scatt.sql                |     1 +
 odb/src/ddl.CCMA/suobsaddr.sql                     |     1 +
 odb/src/ddl.CCMA/suobscor_robhdr.sql               |     1 +
 odb/src/ddl.CCMA/suobscor_robody.sql               |     1 +
 odb/src/ddl.CCMA/surfbody_feedback.h               |     1 +
 odb/src/ddl.CCMA/suvarbc_robhdr_0.sql              |     1 +
 odb/src/ddl.CCMA/suvarbc_robody_0.sql              |     1 +
 odb/src/ddl.CCMA/swapbytes.h                       |     1 +
 odb/src/ddl.CCMA/time_info.sql                     |     1 +
 odb/src/ddl.CCMA/time_numtsl.sql                   |     1 +
 odb/src/ddl.CCMA/tslot.sql                         |     1 +
 odb/src/ddl.CCMA/type_definitions.h                |     1 +
 odb/src/ddl.CCMA/update.h                          |     1 +
 odb/src/ddl.CCMA/update_desc_1.sql                 |     1 +
 odb/src/ddl.CCMA/update_desc_2.sql                 |     1 +
 odb/src/ddl.CCMA/update_enkf_links.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_1.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_10.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_100.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_101.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_102.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_103.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_104.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_105.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_106.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_107.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_108.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_109.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_11.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_110.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_111.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_112.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_113.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_114.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_115.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_116.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_117.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_118.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_119.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_12.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_120.sql             |     1 +
 odb/src/ddl.CCMA/update_hprior_13.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_14.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_15.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_16.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_17.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_18.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_19.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_2.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_20.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_21.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_22.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_23.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_24.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_25.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_26.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_27.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_28.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_29.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_3.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_30.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_31.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_32.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_33.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_34.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_35.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_36.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_37.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_38.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_39.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_4.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_40.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_41.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_42.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_43.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_44.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_45.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_46.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_47.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_48.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_49.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_5.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_50.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_51.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_52.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_53.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_54.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_55.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_56.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_57.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_58.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_59.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_6.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_60.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_61.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_62.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_63.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_64.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_65.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_66.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_67.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_68.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_69.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_7.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_70.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_71.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_72.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_73.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_74.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_75.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_76.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_77.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_78.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_79.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_8.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_80.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_81.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_82.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_83.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_84.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_85.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_86.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_87.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_88.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_89.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_9.sql               |     1 +
 odb/src/ddl.CCMA/update_hprior_90.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_91.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_92.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_93.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_94.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_95.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_96.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_97.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_98.sql              |     1 +
 odb/src/ddl.CCMA/update_hprior_99.sql              |     1 +
 odb/src/ddl.CCMA/varbc_allsky_robhdr.sql           |     1 +
 odb/src/ddl.CCMA/varbc_allsky_robody.sql           |     1 +
 odb/src/ddl.CCMA/varbc_gbrad_robhdr.sql            |     1 +
 odb/src/ddl.CCMA/varbc_gbrad_robody.sql            |     1 +
 odb/src/ddl.CCMA/varbc_rad_robhdr.sql              |     1 +
 odb/src/ddl.CCMA/varbc_rad_robody.sql              |     1 +
 odb/src/ddl.CCMA/varbc_setup_robhdr.sql            |     1 +
 odb/src/ddl.CCMA/varbc_setup_robody.sql            |     1 +
 odb/src/ddl.CCMA/varbc_sfcobs_robhdr.sql           |     1 +
 odb/src/ddl.CCMA/varbc_sfcobs_robody.sql           |     1 +
 odb/src/ddl.CCMA/varbc_tcwv_robhdr.sql             |     1 +
 odb/src/ddl.CCMA/varbc_tcwv_robody.sql             |     1 +
 odb/src/ddl.CCMA/varbc_to3_robhdr.sql              |     1 +
 odb/src/ddl.CCMA/varbc_to3_robody.sql              |     1 +
 odb/src/ddl.CCMA/varno.h                           |     1 +
 odb/src/ddl.CCMA/vertco_type.h                     |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/CMakeLists.txt        |    44 +
 odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.ddl  |   113 +
 odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.dep  |    18 +
 odb/src/ddl.COUNTRYRSTRHBIAS/aeolus.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/alloc.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/allsky.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/auxiliary.h           |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/bits.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/body.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/cdrhook.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/cloud_sink.h          |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/cma.h                 |     1 +
 .../collocated_imager_information.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/conv.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhbody.sql  |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhhdr.sql   |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/dca.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/ecstdlib.h            |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/ensemble.h            |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/errstat.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/forecast_diagnostic.h |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/funcs.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/gbrad.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/gnssro.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/hdr.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/idx.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/info.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/limb.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/magicwords.h          |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/mdi.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/modsurf.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/namecfg.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/obstype.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/odb.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/odb_macros.h          |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/odbcrc.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/odbmd5.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/pcma_extern.h         |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/ppcode.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/privpub.h             |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/radar.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/radar_station.h       |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/radiance.h            |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/raingg.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/resat.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/sat.h                 |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/satob.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/scatt.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/sensor.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/smos.h                |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/ssmi1d.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/surfbody_feedback.h   |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/swapbytes.h           |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/type_definitions.h    |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/update.h              |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/varno.h               |     1 +
 odb/src/ddl.COUNTRYRSTRHBIAS/vertco_type.h         |     1 +
 odb/src/ddl.ECMA/CMakeLists.txt                    |   597 +
 odb/src/ddl.ECMA/ECMA.ddl                          |     3 +
 odb/src/ddl.ECMA/ECMA.dep                          |   272 +
 odb/src/ddl.ECMA/adjust_distribid.sql              |     1 +
 odb/src/ddl.ECMA/aeolus.h                          |     1 +
 odb/src/ddl.ECMA/aeolus_auxmet_update_hdrflag.sql  |     1 +
 odb/src/ddl.ECMA/airep_flight_phase_robhdr.sql     |     1 +
 odb/src/ddl.ECMA/airep_flight_phase_robody.sql     |     1 +
 odb/src/ddl.ECMA/airs.sql                          |     1 +
 odb/src/ddl.ECMA/airs_flag.sql                     |     1 +
 odb/src/ddl.ECMA/ak_resat_averaging_kernel.sql     |     1 +
 odb/src/ddl.ECMA/alloc.h                           |     1 +
 odb/src/ddl.ECMA/allsky.h                          |     1 +
 odb/src/ddl.ECMA/allsky_update_links.sql           |     1 +
 odb/src/ddl.ECMA/amv.sql                           |     1 +
 odb/src/ddl.ECMA/amv2.sql                          |     1 +
 odb/src/ddl.ECMA/amv_flag.sql                      |     1 +
 odb/src/ddl.ECMA/amv_flag2.sql                     |     1 +
 odb/src/ddl.ECMA/ascatsm_robhdr_1.sql              |     1 +
 odb/src/ddl.ECMA/ascatsm_robody_1.sql              |     1 +
 odb/src/ddl.ECMA/auxiliary.h                       |     1 +
 odb/src/ddl.ECMA/averaging_smos.sql                |     1 +
 odb/src/ddl.ECMA/bator_hdr_1.sql                   |     1 +
 odb/src/ddl.ECMA/bator_hdr_2.sql                   |     1 +
 odb/src/ddl.ECMA/bator_hdr_3.sql                   |     1 +
 odb/src/ddl.ECMA/bator_hdr_4.sql                   |     1 +
 odb/src/ddl.ECMA/bator_hdr_5.sql                   |     1 +
 odb/src/ddl.ECMA/bator_hdr_6.sql                   |     1 +
 odb/src/ddl.ECMA/bits.h                            |     1 +
 odb/src/ddl.ECMA/black_robhdr_1.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_10.sql               |     1 +
 odb/src/ddl.ECMA/black_robhdr_2.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_3.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_4.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_7.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_8.sql                |     1 +
 odb/src/ddl.ECMA/black_robhdr_9.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_1.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_10.sql               |     1 +
 odb/src/ddl.ECMA/black_robody_2.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_3.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_4.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_7.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_8.sql                |     1 +
 odb/src/ddl.ECMA/black_robody_9.sql                |     1 +
 odb/src/ddl.ECMA/body.h                            |     1 +
 odb/src/ddl.ECMA/btemdup_robhdr_1.sql              |     1 +
 odb/src/ddl.ECMA/caifc1.sql                        |     1 +
 odb/src/ddl.ECMA/camelo_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/camelo_robody.sql                 |     1 +
 odb/src/ddl.ECMA/canaco_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/canaco_robody.sql                 |     1 +
 odb/src/ddl.ECMA/cancer_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/cancer_robody.sql                 |     1 +
 odb/src/ddl.ECMA/cantik_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/cantik_robody.sql                 |     1 +
 odb/src/ddl.ECMA/carcfo.sql                        |     1 +
 odb/src/ddl.ECMA/caredo_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/caredo_robody.sql                 |     1 +
 odb/src/ddl.ECMA/castor.sql                        |     1 +
 odb/src/ddl.ECMA/caviso_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/caviso_robody.sql                 |     1 +
 odb/src/ddl.ECMA/cavodk_robhdr.sql                 |     1 +
 odb/src/ddl.ECMA/cavodk_robody.sql                 |     1 +
 odb/src/ddl.ECMA/cdrhook.h                         |     1 +
 odb/src/ddl.ECMA/check_linksdb.sql                 |     1 +
 odb/src/ddl.ECMA/cloud_sink.h                      |     1 +
 odb/src/ddl.ECMA/cma.h                             |     1 +
 odb/src/ddl.ECMA/collocated_imager_information.h   |     1 +
 odb/src/ddl.ECMA/conv.h                            |     1 +
 odb/src/ddl.ECMA/conv_hdr.sql                      |     1 +
 odb/src/ddl.ECMA/conv_update_links.sql             |     1 +
 odb/src/ddl.ECMA/conventional_robhdr_1.sql         |     1 +
 odb/src/ddl.ECMA/conventional_robody_1.sql         |     1 +
 odb/src/ddl.ECMA/count_orbit.sql                   |     1 +
 odb/src/ddl.ECMA/count_scanpos.sql                 |     1 +
 odb/src/ddl.ECMA/cycle_biasprep_robhdr.sql         |     1 +
 odb/src/ddl.ECMA/cycle_biasprep_robody.sql         |     1 +
 odb/src/ddl.ECMA/cycle_biasprep_sathdr.sql         |     1 +
 odb/src/ddl.ECMA/cycle_biasprep_satpred.sql        |     1 +
 odb/src/ddl.ECMA/data_radar_station.sql            |     1 +
 odb/src/ddl.ECMA/date_time.sql                     |     1 +
 odb/src/ddl.ECMA/dca.h                             |     1 +
 odb/src/ddl.ECMA/decis_convbody_1.sql              |     1 +
 odb/src/ddl.ECMA/decis_convbody_2.sql              |     1 +
 odb/src/ddl.ECMA/decis_robhdr_1.sql                |     1 +
 odb/src/ddl.ECMA/decis_robhdr_2.sql                |     1 +
 odb/src/ddl.ECMA/decis_robhdr_3.sql                |     1 +
 odb/src/ddl.ECMA/decis_robhdr_4.sql                |     1 +
 odb/src/ddl.ECMA/decis_robody_1.sql                |     1 +
 odb/src/ddl.ECMA/decis_robody_2.sql                |     1 +
 odb/src/ddl.ECMA/decis_robody_3.sql                |     1 +
 odb/src/ddl.ECMA/decis_robody_4.sql                |     1 +
 odb/src/ddl.ECMA/discard_dep_1.sql                 |     1 +
 odb/src/ddl.ECMA/discard_dep_2.sql                 |     1 +
 odb/src/ddl.ECMA/dmsprainy.sql                     |     1 +
 odb/src/ddl.ECMA/ecma_body_4_psbias.sql            |     1 +
 odb/src/ddl.ECMA/ecma_body_4_rstrhbias.sql         |     1 +
 odb/src/ddl.ECMA/ecma_hdr_4_psbias.sql             |     1 +
 odb/src/ddl.ECMA/ecma_hdr_4_rstrhbias.sql          |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_allsky_body.sql     |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_body.sql            |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_gbrad.sql           |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_hdr.sql             |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_raingg.sql          |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_update_1.sql        |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_update_2.sql        |     1 +
 odb/src/ddl.ECMA/ecmwf_matchup_update_3.sql        |     1 +
 odb/src/ddl.ECMA/ecmwf_matchupsink.sql             |     1 +
 odb/src/ddl.ECMA/ecset.sql                         |     1 +
 odb/src/ddl.ECMA/ecstdlib.h                        |     1 +
 odb/src/ddl.ECMA/emiskf_amsua.sql                  |     1 +
 odb/src/ddl.ECMA/emiskf_amsub.sql                  |     1 +
 odb/src/ddl.ECMA/emiskf_atms.sql                   |     1 +
 odb/src/ddl.ECMA/emiskf_mhs.sql                    |     1 +
 odb/src/ddl.ECMA/emiskf_mwts2.sql                  |     1 +
 odb/src/ddl.ECMA/ensemble.h                        |     1 +
 odb/src/ddl.ECMA/errstat.h                         |     1 +
 odb/src/ddl.ECMA/exp_info_1.sql                    |     1 +
 odb/src/ddl.ECMA/fcq_robhdr_0.sql                  |     1 +
 odb/src/ddl.ECMA/fcq_robhdr_1.sql                  |     1 +
 odb/src/ddl.ECMA/fcq_robhdr_2.sql                  |     1 +
 odb/src/ddl.ECMA/fcq_robody_0.sql                  |     1 +
 odb/src/ddl.ECMA/fcq_robody_1.sql                  |     1 +
 odb/src/ddl.ECMA/fcq_robody_2.sql                  |     1 +
 odb/src/ddl.ECMA/fix_date_and_time.sql             |     1 +
 odb/src/ddl.ECMA/fixresatlen.sql                   |     1 +
 odb/src/ddl.ECMA/flago_mobhdr.sql                  |     1 +
 odb/src/ddl.ECMA/flago_mobody.sql                  |     1 +
 odb/src/ddl.ECMA/forecast_diagnostic.h             |     1 +
 odb/src/ddl.ECMA/funcs.h                           |     1 +
 odb/src/ddl.ECMA/gather4poolmask.sql               |     1 +
 odb/src/ddl.ECMA/gather4poolmask_counts.sql        |     1 +
 odb/src/ddl.ECMA/gbrad.h                           |     1 +
 odb/src/ddl.ECMA/gbrad_body_rr.sql                 |     1 +
 odb/src/ddl.ECMA/gbrad_rr.sql                      |     1 +
 odb/src/ddl.ECMA/gbrad_update_links.sql            |     1 +
 odb/src/ddl.ECMA/get_soe_resat.sql                 |     1 +
 odb/src/ddl.ECMA/getairepid.sql                    |     1 +
 odb/src/ddl.ECMA/getgbradid.sql                    |     1 +
 odb/src/ddl.ECMA/getlimbid.sql                     |     1 +
 odb/src/ddl.ECMA/getsatid.sql                      |     1 +
 odb/src/ddl.ECMA/getsatid_resat.sql                |     1 +
 odb/src/ddl.ECMA/getsatobid.sql                    |     1 +
 odb/src/ddl.ECMA/getsfcobsid.sql                   |     1 +
 odb/src/ddl.ECMA/gnssro.h                          |     1 +
 odb/src/ddl.ECMA/gnssro_update_links.sql           |     1 +
 odb/src/ddl.ECMA/gpsro_2.sql                       |     1 +
 odb/src/ddl.ECMA/hdr.h                             |     1 +
 odb/src/ddl.ECMA/hdr_update_links.sql              |     1 +
 odb/src/ddl.ECMA/hop_canari_conv.sql               |     1 +
 odb/src/ddl.ECMA/hop_canari_robhdr.sql             |     1 +
 odb/src/ddl.ECMA/hop_canari_robody.sql             |     1 +
 odb/src/ddl.ECMA/hretr_canari_robody.sql           |     1 +
 odb/src/ddl.ECMA/hretr_canari_satbody.sql          |     1 +
 odb/src/ddl.ECMA/idx.h                             |     1 +
 odb/src/ddl.ECMA/info.h                            |     1 +
 odb/src/ddl.ECMA/init_update_1.sql                 |     1 +
 odb/src/ddl.ECMA/init_update_2.sql                 |     1 +
 odb/src/ddl.ECMA/init_update_3.sql                 |     1 +
 odb/src/ddl.ECMA/level1cgeos_robhdr_1.sql          |     1 +
 odb/src/ddl.ECMA/level1cgeos_robody_1.sql          |     1 +
 odb/src/ddl.ECMA/limb.h                            |     1 +
 odb/src/ddl.ECMA/links_aeolus_hdr.sql              |     1 +
 odb/src/ddl.ECMA/links_auxiliary.sql               |     1 +
 odb/src/ddl.ECMA/links_body.sql                    |     1 +
 odb/src/ddl.ECMA/links_ensemble.sql                |     1 +
 odb/src/ddl.ECMA/links_gbrad.sql                   |     1 +
 odb/src/ddl.ECMA/links_modsurf.sql                 |     1 +
 odb/src/ddl.ECMA/links_raingg.sql                  |     1 +
 odb/src/ddl.ECMA/links_sat.sql                     |     1 +
 odb/src/ddl.ECMA/links_surfbody_feedback.sql       |     1 +
 odb/src/ddl.ECMA/magicwords.h                      |     1 +
 odb/src/ddl.ECMA/manda_gene_body.sql               |     1 +
 odb/src/ddl.ECMA/manda_gene_hdr.sql                |     1 +
 odb/src/ddl.ECMA/manda_laelalo.sql                 |     1 +
 odb/src/ddl.ECMA/map_ssmi_rain_ssmi.sql            |     1 +
 odb/src/ddl.ECMA/matchup_allsky_body.sql           |     1 +
 odb/src/ddl.ECMA/matchup_atovs_pred.sql            |     1 +
 odb/src/ddl.ECMA/matchup_body.sql                  |     1 +
 odb/src/ddl.ECMA/matchup_gbrad.sql                 |     1 +
 odb/src/ddl.ECMA/matchup_hdr.sql                   |     1 +
 odb/src/ddl.ECMA/matchup_procid.sql                |     1 +
 odb/src/ddl.ECMA/matchup_raingg.sql                |     1 +
 odb/src/ddl.ECMA/matchup_update_1.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_10.sql             |     1 +
 odb/src/ddl.ECMA/matchup_update_2.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_3.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_4.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_5.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_6.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_7.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_8.sql              |     1 +
 odb/src/ddl.ECMA/matchup_update_9.sql              |     1 +
 odb/src/ddl.ECMA/matchupsink.sql                   |     1 +
 odb/src/ddl.ECMA/max_values.sql                    |     1 +
 odb/src/ddl.ECMA/mdi.h                             |     1 +
 odb/src/ddl.ECMA/mkglobstab.sql                    |     1 +
 odb/src/ddl.ECMA/mkglobstab_gpsro.sql              |     1 +
 odb/src/ddl.ECMA/mobhdr_obsort.sql                 |     1 +
 odb/src/ddl.ECMA/mobhdrca_obsort.sql               |     1 +
 odb/src/ddl.ECMA/modsurf.h                         |     1 +
 odb/src/ddl.ECMA/nak_resat_averaging_kernel.sql    |     1 +
 odb/src/ddl.ECMA/namecfg.h                         |     1 +
 odb/src/ddl.ECMA/nesdis_get.sql                    |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_10.sql           |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_11.sql           |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_2.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_3.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_4.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_5.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_6.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_7.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_8.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robhdr_9.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_10.sql           |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_11.sql           |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_3.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_4.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_5.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_8.sql            |     1 +
 odb/src/ddl.ECMA/new_thinn_robody_9.sql            |     1 +
 odb/src/ddl.ECMA/obatabs_robhdr.sql                |     1 +
 odb/src/ddl.ECMA/obs_boxes.sql                     |     1 +
 odb/src/ddl.ECMA/obscount_1.sql                    |     1 +
 odb/src/ddl.ECMA/obscount_2.sql                    |     1 +
 odb/src/ddl.ECMA/obsdist.sql                       |     1 +
 odb/src/ddl.ECMA/obsdist_allsky.sql                |     1 +
 odb/src/ddl.ECMA/obsdist_allsky_body.sql           |     1 +
 odb/src/ddl.ECMA/obsdist_auxiliary.sql             |     1 +
 odb/src/ddl.ECMA/obsdist_auxiliary_body.sql        |     1 +
 odb/src/ddl.ECMA/obsdist_body.sql                  |     1 +
 odb/src/ddl.ECMA/obsdist_errstat.sql               |     1 +
 odb/src/ddl.ECMA/obsdist_gbrad.sql                 |     1 +
 odb/src/ddl.ECMA/obsdist_gbrad_body.sql            |     1 +
 odb/src/ddl.ECMA/obsdist_hdr.sql                   |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2allsky_body.sql       |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2auxiliary_body.sql    |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2body.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2gbrad_body.sql        |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2radar_body.sql        |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2radiance_body.sql     |     1 +
 odb/src/ddl.ECMA/obsdist_hdr2raingg_body.sql       |     1 +
 .../obsdist_hdr2resat_averaging_kernel.sql         |     1 +
 odb/src/ddl.ECMA/obsdist_index.sql                 |     1 +
 odb/src/ddl.ECMA/obsdist_index2hdr.sql             |     1 +
 odb/src/ddl.ECMA/obsdist_limb.sql                  |     1 +
 odb/src/ddl.ECMA/obsdist_modsurf.sql               |     1 +
 odb/src/ddl.ECMA/obsdist_poolno.sql                |     1 +
 odb/src/ddl.ECMA/obsdist_radar.sql                 |     1 +
 odb/src/ddl.ECMA/obsdist_radar_body.sql            |     1 +
 odb/src/ddl.ECMA/obsdist_radar_station.sql         |     1 +
 odb/src/ddl.ECMA/obsdist_radiance.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_radiance_body.sql         |     1 +
 odb/src/ddl.ECMA/obsdist_raingg.sql                |     1 +
 odb/src/ddl.ECMA/obsdist_raingg_body.sql           |     1 +
 odb/src/ddl.ECMA/obsdist_resat.sql                 |     1 +
 .../ddl.ECMA/obsdist_resat_averaging_kernel.sql    |     1 +
 odb/src/ddl.ECMA/obsdist_sat.sql                   |     1 +
 odb/src/ddl.ECMA/obsdist_satob.sql                 |     1 +
 odb/src/ddl.ECMA/obsdist_scatt.sql                 |     1 +
 odb/src/ddl.ECMA/obsdist_scatt_body.sql            |     1 +
 odb/src/ddl.ECMA/obsdist_smos.sql                  |     1 +
 odb/src/ddl.ECMA/obsdist_ssmi.sql                  |     1 +
 odb/src/ddl.ECMA/obsdist_ssmi_body.sql             |     1 +
 odb/src/ddl.ECMA/obsdist_update_1.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_10.sql             |     1 +
 odb/src/ddl.ECMA/obsdist_update_2.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_3.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_4.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_5.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_6.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_7.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_8.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_update_9.sql              |     1 +
 odb/src/ddl.ECMA/obsdist_windows.sql               |     1 +
 odb/src/ddl.ECMA/obshor.sql                        |     1 +
 odb/src/ddl.ECMA/obsort_allsky.sql                 |     1 +
 odb/src/ddl.ECMA/obsort_allsky_body.sql            |     1 +
 odb/src/ddl.ECMA/obsort_auxiliary.sql              |     1 +
 odb/src/ddl.ECMA/obsort_body.sql                   |     1 +
 odb/src/ddl.ECMA/obsort_cloud_sink.sql             |     1 +
 .../obsort_collocated_imager_information.sql       |     1 +
 odb/src/ddl.ECMA/obsort_conv.sql                   |     1 +
 odb/src/ddl.ECMA/obsort_conv_body.sql              |     1 +
 odb/src/ddl.ECMA/obsort_errstat.sql                |     1 +
 odb/src/ddl.ECMA/obsort_gbrad.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_gbrad_body.sql             |     1 +
 odb/src/ddl.ECMA/obsort_gnssro.sql                 |     1 +
 odb/src/ddl.ECMA/obsort_gnssro_body.sql            |     1 +
 odb/src/ddl.ECMA/obsort_hdr.sql                    |     1 +
 odb/src/ddl.ECMA/obsort_hdr2allsky_body.sql        |     1 +
 odb/src/ddl.ECMA/obsort_hdr2auxiliary_body.sql     |     1 +
 odb/src/ddl.ECMA/obsort_hdr2body.sql               |     1 +
 odb/src/ddl.ECMA/obsort_hdr2conv_body.sql          |     1 +
 odb/src/ddl.ECMA/obsort_hdr2gbrad_body.sql         |     1 +
 odb/src/ddl.ECMA/obsort_hdr2gnssro_body.sql        |     1 +
 odb/src/ddl.ECMA/obsort_hdr2radar_body.sql         |     1 +
 odb/src/ddl.ECMA/obsort_hdr2radiance_body.sql      |     1 +
 odb/src/ddl.ECMA/obsort_hdr2raingg_body.sql        |     1 +
 odb/src/ddl.ECMA/obsort_hdr2scatt_body.sql         |     1 +
 odb/src/ddl.ECMA/obsort_index.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_limb.sql                   |     1 +
 odb/src/ddl.ECMA/obsort_modsurf.sql                |     1 +
 odb/src/ddl.ECMA/obsort_radar.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_radar_body.sql             |     1 +
 odb/src/ddl.ECMA/obsort_radar_station.sql          |     1 +
 odb/src/ddl.ECMA/obsort_radiance.sql               |     1 +
 odb/src/ddl.ECMA/obsort_radiance_body.sql          |     1 +
 odb/src/ddl.ECMA/obsort_raingg.sql                 |     1 +
 odb/src/ddl.ECMA/obsort_raingg_body.sql            |     1 +
 odb/src/ddl.ECMA/obsort_resat.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_resat_averaging_kernel.sql |     1 +
 odb/src/ddl.ECMA/obsort_sat.sql                    |     1 +
 odb/src/ddl.ECMA/obsort_satob.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_scatt.sql                  |     1 +
 odb/src/ddl.ECMA/obsort_scatt_body.sql             |     1 +
 odb/src/ddl.ECMA/obsort_smos.sql                   |     1 +
 odb/src/ddl.ECMA/obsort_ssmi.sql                   |     1 +
 odb/src/ddl.ECMA/obsort_ssmi_body.sql              |     1 +
 odb/src/ddl.ECMA/obsort_update_1.sql               |     1 +
 odb/src/ddl.ECMA/obsort_update_2.sql               |     1 +
 odb/src/ddl.ECMA/obsort_update_3.sql               |     1 +
 odb/src/ddl.ECMA/obsortca_auxiliary.sql            |     1 +
 odb/src/ddl.ECMA/obsortca_body.sql                 |     1 +
 odb/src/ddl.ECMA/obsortca_errstat.sql              |     1 +
 odb/src/ddl.ECMA/obsortca_hdr.sql                  |     1 +
 odb/src/ddl.ECMA/obsortca_hdr2auxiliary_body.sql   |     1 +
 odb/src/ddl.ECMA/obsortca_hdr2body.sql             |     1 +
 odb/src/ddl.ECMA/obsortca_index.sql                |     1 +
 odb/src/ddl.ECMA/obsortca_update_1.sql             |     1 +
 odb/src/ddl.ECMA/obsortca_update_2.sql             |     1 +
 odb/src/ddl.ECMA/obsortca_update_3.sql             |     1 +
 odb/src/ddl.ECMA/obstat.sql                        |     1 +
 odb/src/ddl.ECMA/obstat_conv.sql                   |     1 +
 odb/src/ddl.ECMA/obstat_fcdep.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_fcdep_gpsro.sql            |     1 +
 odb/src/ddl.ECMA/obstat_geos.sql                   |     1 +
 odb/src/ddl.ECMA/obstat_gpsro.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_mwimg.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_radar.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_resat.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_satob.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_scatt.sql                  |     1 +
 odb/src/ddl.ECMA/obstat_smos.sql                   |     1 +
 odb/src/ddl.ECMA/obstat_smos_land.sql              |     1 +
 odb/src/ddl.ECMA/obstat_tovs.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_1.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_10.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_11.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_12.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_13.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_14.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_15.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_16.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_17.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_18.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_19.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_2.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_20.sql                   |     1 +
 odb/src/ddl.ECMA/obstatfc_3.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_4.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_5.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_6.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_7.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_8.sql                    |     1 +
 odb/src/ddl.ECMA/obstatfc_9.sql                    |     1 +
 odb/src/ddl.ECMA/obstype.h                         |     1 +
 odb/src/ddl.ECMA/odb.h                             |     1 +
 odb/src/ddl.ECMA/odb2ee_aeolus_auxmet.sql          |     1 +
 odb/src/ddl.ECMA/odb98.flags                       |     1 +
 odb/src/ddl.ECMA/odb_info.sql                      |     1 +
 odb/src/ddl.ECMA/odb_macros.h                      |     1 +
 odb/src/ddl.ECMA/odbcrc.h                          |     1 +
 odb/src/ddl.ECMA/odbmd5.h                          |     1 +
 odb/src/ddl.ECMA/ozone_robhdr_1.sql                |     1 +
 odb/src/ddl.ECMA/ozone_robody_1.sql                |     1 +
 odb/src/ddl.ECMA/pcma_extern.h                     |     1 +
 odb/src/ddl.ECMA/pertobs_corr_robhdr.sql           |     1 +
 odb/src/ddl.ECMA/pertobs_corr_robody.sql           |     1 +
 odb/src/ddl.ECMA/pertobs_uncorr_robhdr.sql         |     1 +
 odb/src/ddl.ECMA/pertobs_uncorr_robody.sql         |     1 +
 odb/src/ddl.ECMA/poolmask_1.sql                    |     1 +
 odb/src/ddl.ECMA/poolmask_2.sql                    |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_2.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_3.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_4.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_5.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_6.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_7.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_8.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robhdr_9.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_2.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_3.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_4.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_5.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_6.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_7.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_8.sql           |     1 +
 odb/src/ddl.ECMA/post_thinn_robody_9.sql           |     1 +
 odb/src/ddl.ECMA/ppcode.h                          |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_10.sql           |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_11.sql           |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_2.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_3.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_4.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_5.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_6.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_7.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_8.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robhdr_9.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_10.sql           |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_11.sql           |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_2.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_3.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_4.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_5.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_6.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_7.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_8.sql            |     1 +
 odb/src/ddl.ECMA/pre_thinn_robody_9.sql            |     1 +
 odb/src/ddl.ECMA/privpub.h                         |     1 +
 odb/src/ddl.ECMA/prtdpst_robhdr.sql                |     1 +
 odb/src/ddl.ECMA/prtdpst_robody.sql                |     1 +
 odb/src/ddl.ECMA/radar.h                           |     1 +
 odb/src/ddl.ECMA/radar_station.h                   |     1 +
 odb/src/ddl.ECMA/radiance.h                        |     1 +
 odb/src/ddl.ECMA/radiance_averaging.sql            |     1 +
 odb/src/ddl.ECMA/radiance_update_links.sql         |     1 +
 odb/src/ddl.ECMA/raingg.h                          |     1 +
 odb/src/ddl.ECMA/raingg_body_rr.sql                |     1 +
 odb/src/ddl.ECMA/raingg_rr.sql                     |     1 +
 odb/src/ddl.ECMA/ralt.sql                          |     1 +
 odb/src/ddl.ECMA/ralt_wam.sql                      |     1 +
 odb/src/ddl.ECMA/redun_robhdr_1.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_2.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_3.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_4.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_5.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_6.sql                |     1 +
 odb/src/ddl.ECMA/redun_robhdr_7.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_1.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_2.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_3.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_4.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_5.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_6.sql                |     1 +
 odb/src/ddl.ECMA/redun_robody_7.sql                |     1 +
 odb/src/ddl.ECMA/reini_body.sql                    |     1 +
 odb/src/ddl.ECMA/reini_hdr.sql                     |     1 +
 odb/src/ddl.ECMA/reprod_seqno_1.sql                |     1 +
 odb/src/ddl.ECMA/reprod_seqno_2.sql                |     1 +
 odb/src/ddl.ECMA/reprod_seqno_3.sql                |     1 +
 odb/src/ddl.ECMA/reprod_seqno_4.sql                |     1 +
 odb/src/ddl.ECMA/resat.h                           |     1 +
 odb/src/ddl.ECMA/resat_update_links.sql            |     1 +
 odb/src/ddl.ECMA/revmatchup_body.sql               |     1 +
 odb/src/ddl.ECMA/revmatchup_hdr.sql                |     1 +
 odb/src/ddl.ECMA/robhdr.sql                        |     1 +
 odb/src/ddl.ECMA/robhdr_gbrad_get_rr.sql           |     1 +
 odb/src/ddl.ECMA/robhdr_gbrad_put_rr.sql           |     1 +
 odb/src/ddl.ECMA/robhdr_gp_get_ssmi.sql            |     1 +
 odb/src/ddl.ECMA/robhdr_grid_distribute.sql        |     1 +
 odb/src/ddl.ECMA/robhdr_mwave_count_smos.sql       |     1 +
 odb/src/ddl.ECMA/robhdr_mwave_process_smos.sql     |     1 +
 odb/src/ddl.ECMA/robhdr_mwave_update_smos.sql      |     1 +
 odb/src/ddl.ECMA/robhdr_obsort.sql                 |     1 +
 odb/src/ddl.ECMA/robhdr_rad.sql                    |     1 +
 odb/src/ddl.ECMA/robhdr_raingg_get_rr.sql          |     1 +
 odb/src/ddl.ECMA/robhdr_raingg_put_rr.sql          |     1 +
 odb/src/ddl.ECMA/robhdr_screen.sql                 |     1 +
 odb/src/ddl.ECMA/robhdr_screen_conv.sql            |     1 +
 odb/src/ddl.ECMA/robhdr_tc.sql                     |     1 +
 odb/src/ddl.ECMA/robhdrca_obsort.sql               |     1 +
 odb/src/ddl.ECMA/robody.sql                        |     1 +
 odb/src/ddl.ECMA/robody_gbrad_get_rr.sql           |     1 +
 odb/src/ddl.ECMA/robody_gbrad_put_rr.sql           |     1 +
 odb/src/ddl.ECMA/robody_gp_get_ssmi.sql            |     1 +
 odb/src/ddl.ECMA/robody_mwave_process_smos.sql     |     1 +
 odb/src/ddl.ECMA/robody_mwave_update_smos.sql      |     1 +
 odb/src/ddl.ECMA/robody_rad.sql                    |     1 +
 odb/src/ddl.ECMA/robody_raingg_get_rr.sql          |     1 +
 odb/src/ddl.ECMA/robody_raingg_put_rr.sql          |     1 +
 odb/src/ddl.ECMA/robody_screen.sql                 |     1 +
 odb/src/ddl.ECMA/robody_smos_sekf.sql              |     1 +
 odb/src/ddl.ECMA/robody_tc.sql                     |     1 +
 odb/src/ddl.ECMA/robody_traj.sql                   |     1 +
 odb/src/ddl.ECMA/sat.h                             |     1 +
 odb/src/ddl.ECMA/sat_aeolusl2c.sql                 |     1 +
 odb/src/ddl.ECMA/sat_atovs.sql                     |     1 +
 odb/src/ddl.ECMA/sat_gpsro.sql                     |     1 +
 odb/src/ddl.ECMA/sat_lrad.sql                      |     1 +
 odb/src/ddl.ECMA/sat_satob.sql                     |     1 +
 odb/src/ddl.ECMA/sat_smos.sql                      |     1 +
 odb/src/ddl.ECMA/sat_ssmi.sql                      |     1 +
 odb/src/ddl.ECMA/sat_update_links.sql              |     1 +
 odb/src/ddl.ECMA/satbody_allsky.sql                |     1 +
 odb/src/ddl.ECMA/satbody_atovs.sql                 |     1 +
 odb/src/ddl.ECMA/satbody_gpsro.sql                 |     1 +
 odb/src/ddl.ECMA/satbody_radar.sql                 |     1 +
 odb/src/ddl.ECMA/satbody_scat.sql                  |     1 +
 odb/src/ddl.ECMA/satbody_screen_atovs.sql          |     1 +
 odb/src/ddl.ECMA/satellite_identifier_list.sql     |     1 +
 odb/src/ddl.ECMA/sathdr_cloud_sink.sql             |     1 +
 odb/src/ddl.ECMA/sathdr_limb.sql                   |     1 +
 odb/src/ddl.ECMA/sathdr_ozone.sql                  |     1 +
 odb/src/ddl.ECMA/sathdr_radar.sql                  |     1 +
 odb/src/ddl.ECMA/sathdr_satob.sql                  |     1 +
 odb/src/ddl.ECMA/sathdr_scat.sql                   |     1 +
 odb/src/ddl.ECMA/sathdr_screen_aeolus_auxmet.sql   |     1 +
 odb/src/ddl.ECMA/sathdr_screen_atovs.sql           |     1 +
 odb/src/ddl.ECMA/sathdr_screen_cloud_sink.sql      |     1 +
 odb/src/ddl.ECMA/sathdr_screen_gpsro.sql           |     1 +
 odb/src/ddl.ECMA/sathdr_screen_lrad.sql            |     1 +
 odb/src/ddl.ECMA/sathdr_screen_resat.sql           |     1 +
 odb/src/ddl.ECMA/sathdr_screen_satob.sql           |     1 +
 odb/src/ddl.ECMA/satob.h                           |     1 +
 odb/src/ddl.ECMA/satob_robhdr_1.sql                |     1 +
 odb/src/ddl.ECMA/satob_robody_1.sql                |     1 +
 odb/src/ddl.ECMA/scat_robhdr_1.sql                 |     1 +
 odb/src/ddl.ECMA/scat_robody_1.sql                 |     1 +
 odb/src/ddl.ECMA/scatt.h                           |     1 +
 odb/src/ddl.ECMA/scatt.sql                         |     1 +
 odb/src/ddl.ECMA/scatt_flag.sql                    |     1 +
 odb/src/ddl.ECMA/scatt_update_links.sql            |     1 +
 odb/src/ddl.ECMA/screen_robhdr_1.sql               |     1 +
 odb/src/ddl.ECMA/screen_robhdr_2.sql               |     1 +
 odb/src/ddl.ECMA/screen_robhdr_3.sql               |     1 +
 odb/src/ddl.ECMA/screen_robody_1.sql               |     1 +
 odb/src/ddl.ECMA/screen_robody_2.sql               |     1 +
 odb/src/ddl.ECMA/screen_robody_3.sql               |     1 +
 odb/src/ddl.ECMA/sensor.h                          |     1 +
 odb/src/ddl.ECMA/set_active.sql                    |     1 +
 odb/src/ddl.ECMA/set_active_smos.sql               |     1 +
 odb/src/ddl.ECMA/setup_tovscv.sql                  |     1 +
 odb/src/ddl.ECMA/setup_tovscv_cloud_sink.sql       |     1 +
 odb/src/ddl.ECMA/size_hdr.sql                      |     1 +
 odb/src/ddl.ECMA/small.sql                         |     1 +
 odb/src/ddl.ECMA/smos.h                            |     1 +
 odb/src/ddl.ECMA/ssa_robhdr_2m.sql                 |     1 +
 odb/src/ddl.ECMA/ssa_robhdr_snow.sql               |     1 +
 odb/src/ddl.ECMA/ssa_robody_2m.sql                 |     1 +
 odb/src/ddl.ECMA/ssa_robody_snow.sql               |     1 +
 odb/src/ddl.ECMA/ssafb_surfbody_2m.sql             |     1 +
 odb/src/ddl.ECMA/ssafb_surfbody_snow.sql           |     1 +
 odb/src/ddl.ECMA/ssmi1d.h                          |     1 +
 odb/src/ddl.ECMA/stat_obs_1.sql                    |     1 +
 odb/src/ddl.ECMA/stat_obs_2.sql                    |     1 +
 odb/src/ddl.ECMA/stat_obs_3.sql                    |     1 +
 odb/src/ddl.ECMA/store_enda.sql                    |     1 +
 odb/src/ddl.ECMA/sufger_allsky.sql                 |     1 +
 odb/src/ddl.ECMA/sufger_allsky_body.sql            |     1 +
 odb/src/ddl.ECMA/sufger_robhdr_1.sql               |     1 +
 odb/src/ddl.ECMA/sufger_robody_1.sql               |     1 +
 odb/src/ddl.ECMA/sufger_sat.sql                    |     1 +
 odb/src/ddl.ECMA/sugoms.sql                        |     1 +
 odb/src/ddl.ECMA/suobarea.sql                      |     1 +
 odb/src/ddl.ECMA/suobarea_limb.sql                 |     1 +
 odb/src/ddl.ECMA/suobarea_sat.sql                  |     1 +
 odb/src/ddl.ECMA/suobarea_satob.sql                |     1 +
 odb/src/ddl.ECMA/suobarea_scatt.sql                |     1 +
 odb/src/ddl.ECMA/suobsaddr.sql                     |     1 +
 odb/src/ddl.ECMA/surfbody_feedback.h               |     1 +
 odb/src/ddl.ECMA/suvarbc_robhdr_0.sql              |     1 +
 odb/src/ddl.ECMA/suvarbc_robody_0.sql              |     1 +
 odb/src/ddl.ECMA/swapbytes.h                       |     1 +
 odb/src/ddl.ECMA/tcwv.sql                          |     1 +
 odb/src/ddl.ECMA/time_info.sql                     |     1 +
 odb/src/ddl.ECMA/time_numtsl.sql                   |     1 +
 odb/src/ddl.ECMA/tovsrtovs_robody_1.sql            |     1 +
 odb/src/ddl.ECMA/tslot.sql                         |     1 +
 odb/src/ddl.ECMA/type_definitions.h                |     1 +
 odb/src/ddl.ECMA/update.h                          |     1 +
 odb/src/ddl.ECMA/update_body_3.sql                 |     1 +
 odb/src/ddl.ECMA/update_desc_1.sql                 |     1 +
 odb/src/ddl.ECMA/update_desc_2.sql                 |     1 +
 odb/src/ddl.ECMA/update_fcdiag_links.sql           |     1 +
 odb/src/ddl.ECMA/update_hdr_1.sql                  |     1 +
 odb/src/ddl.ECMA/update_hdr_2.sql                  |     1 +
 odb/src/ddl.ECMA/update_hdr_3.sql                  |     1 +
 odb/src/ddl.ECMA/update_links_allsky.sql           |     1 +
 odb/src/ddl.ECMA/update_links_auxiliary.sql        |     1 +
 odb/src/ddl.ECMA/update_links_gbrad.sql            |     1 +
 odb/src/ddl.ECMA/update_links_radiance.sql         |     1 +
 odb/src/ddl.ECMA/update_links_raingg.sql           |     1 +
 odb/src/ddl.ECMA/update_links_ssmi.sql             |     1 +
 odb/src/ddl.ECMA/update_modstep.sql                |     1 +
 odb/src/ddl.ECMA/varbc_airep_robhdr.sql            |     1 +
 odb/src/ddl.ECMA/varbc_airep_robody.sql            |     1 +
 odb/src/ddl.ECMA/varbc_allsky_robhdr.sql           |     1 +
 odb/src/ddl.ECMA/varbc_allsky_robody.sql           |     1 +
 odb/src/ddl.ECMA/varbc_gbrad_robhdr.sql            |     1 +
 odb/src/ddl.ECMA/varbc_gbrad_robody.sql            |     1 +
 odb/src/ddl.ECMA/varbc_mode_hist_robhdr.sql        |     1 +
 odb/src/ddl.ECMA/varbc_mode_hist_robody.sql        |     1 +
 odb/src/ddl.ECMA/varbc_rad_robhdr.sql              |     1 +
 odb/src/ddl.ECMA/varbc_rad_robody.sql              |     1 +
 odb/src/ddl.ECMA/varbc_setup_robhdr.sql            |     1 +
 odb/src/ddl.ECMA/varbc_setup_robody.sql            |     1 +
 odb/src/ddl.ECMA/varbc_sfcobs_robhdr.sql           |     1 +
 odb/src/ddl.ECMA/varbc_sfcobs_robody.sql           |     1 +
 odb/src/ddl.ECMA/varbc_tcwv_robhdr.sql             |     1 +
 odb/src/ddl.ECMA/varbc_tcwv_robody.sql             |     1 +
 odb/src/ddl.ECMA/varbc_to3_robhdr.sql              |     1 +
 odb/src/ddl.ECMA/varbc_to3_robody.sql              |     1 +
 odb/src/ddl.ECMA/varno.h                           |     1 +
 odb/src/ddl.ECMA/vertco_type.h                     |     1 +
 odb/src/ddl.ERACOUNTRYTTABLE11/CMakeLists.txt      |     5 +
 .../ddl.ERACOUNTRYTTABLE11/ERACOUNTRYTTABLE11.ddl  |    34 +
 odb/src/ddl.ERACOUNTRYTTABLE11/table11_hdr.sql     |    22 +
 odb/src/ddl.ERACOUNTRYTTABLE12/CMakeLists.txt      |     5 +
 .../ddl.ERACOUNTRYTTABLE12/ERACOUNTRYTTABLE12.ddl  |    29 +
 odb/src/ddl.ERACOUNTRYTTABLE12/table12_hdr.sql     |    10 +
 odb/src/ddl.MTOCOMP/CMakeLists.txt                 |    34 +
 odb/src/ddl.MTOCOMP/MTOCOMP.ddl                    |   196 +
 odb/src/ddl.MTOCOMP/alloc.h                        |     1 +
 odb/src/ddl.MTOCOMP/bits.h                         |     1 +
 odb/src/ddl.MTOCOMP/cdrhook.h                      |     1 +
 odb/src/ddl.MTOCOMP/cma.h                          |     1 +
 odb/src/ddl.MTOCOMP/dca.h                          |     1 +
 odb/src/ddl.MTOCOMP/ecstdlib.h                     |     1 +
 odb/src/ddl.MTOCOMP/funcs.h                        |     1 +
 odb/src/ddl.MTOCOMP/idx.h                          |     1 +
 odb/src/ddl.MTOCOMP/info.h                         |     1 +
 odb/src/ddl.MTOCOMP/magicwords.h                   |     1 +
 odb/src/ddl.MTOCOMP/mdi.h                          |     1 +
 odb/src/ddl.MTOCOMP/namecfg.h                      |     1 +
 odb/src/ddl.MTOCOMP/obstype.h                      |     1 +
 odb/src/ddl.MTOCOMP/odb.h                          |     1 +
 odb/src/ddl.MTOCOMP/odb98.flags                    |     1 +
 odb/src/ddl.MTOCOMP/odb_macros.h                   |     1 +
 odb/src/ddl.MTOCOMP/odbcrc.h                       |     1 +
 odb/src/ddl.MTOCOMP/odbmd5.h                       |     1 +
 odb/src/ddl.MTOCOMP/pcma_extern.h                  |     1 +
 odb/src/ddl.MTOCOMP/ppcode.h                       |     1 +
 odb/src/ddl.MTOCOMP/privpub.h                      |     1 +
 odb/src/ddl.MTOCOMP/sensor.h                       |     1 +
 odb/src/ddl.MTOCOMP/swapbytes.h                    |     1 +
 odb/src/ddl.MTOCOMP/varno.h                        |     1 +
 odb/src/ddl.MTOCOMP/vertco_type.h                  |     1 +
 odb/src/ddl.PSBIAS/CMakeLists.txt                  |    12 +
 odb/src/ddl.PSBIAS/PSBIAS.ddl                      |   366 +
 odb/src/ddl.PSBIAS/PSBIAS.flags                    |    29 +
 odb/src/ddl.PSBIAS/psbias_compress_method_0.sql    |    21 +
 odb/src/ddl.PSBIAS/psbias_compress_method_1a.sql   |    18 +
 odb/src/ddl.PSBIAS/psbias_compress_method_1b.sql   |    10 +
 odb/src/ddl.PSBIAS/psbiasbody.sql                  |    30 +
 odb/src/ddl.PSBIAS/psbiasbody_maintenance.sql      |    29 +
 odb/src/ddl.PSBIAS/psbiashdr.sql                   |    37 +
 odb/src/ddl.PSBIAS/psbiashdr_maintenance.sql       |    37 +
 odb/src/ddl.RSTBIAS/CMakeLists.txt                 |    45 +
 odb/src/ddl.RSTBIAS/RSTBIAS.ddl                    |    40 +
 odb/src/ddl.RSTBIAS/RSTBIAS.dep                    |    18 +
 odb/src/ddl.RSTBIAS/aeolus.h                       |     1 +
 odb/src/ddl.RSTBIAS/alloc.h                        |     1 +
 odb/src/ddl.RSTBIAS/allsky.h                       |     1 +
 odb/src/ddl.RSTBIAS/auxiliary.h                    |     1 +
 odb/src/ddl.RSTBIAS/bits.h                         |     1 +
 odb/src/ddl.RSTBIAS/body.h                         |     1 +
 odb/src/ddl.RSTBIAS/cdrhook.h                      |     1 +
 odb/src/ddl.RSTBIAS/cloud_sink.h                   |     1 +
 odb/src/ddl.RSTBIAS/cma.h                          |     1 +
 .../ddl.RSTBIAS/collocated_imager_information.h    |     1 +
 odb/src/ddl.RSTBIAS/conv.h                         |     1 +
 odb/src/ddl.RSTBIAS/dca.h                          |     1 +
 odb/src/ddl.RSTBIAS/ecstdlib.h                     |     1 +
 odb/src/ddl.RSTBIAS/ensemble.h                     |     1 +
 odb/src/ddl.RSTBIAS/errstat.h                      |     1 +
 odb/src/ddl.RSTBIAS/forecast_diagnostic.h          |     1 +
 odb/src/ddl.RSTBIAS/funcs.h                        |     1 +
 odb/src/ddl.RSTBIAS/gbrad.h                        |     1 +
 odb/src/ddl.RSTBIAS/gnssro.h                       |     1 +
 odb/src/ddl.RSTBIAS/hdr.h                          |     1 +
 odb/src/ddl.RSTBIAS/idx.h                          |     1 +
 odb/src/ddl.RSTBIAS/info.h                         |     1 +
 odb/src/ddl.RSTBIAS/limb.h                         |     1 +
 odb/src/ddl.RSTBIAS/magicwords.h                   |     1 +
 odb/src/ddl.RSTBIAS/mdi.h                          |     1 +
 odb/src/ddl.RSTBIAS/modsurf.h                      |     1 +
 odb/src/ddl.RSTBIAS/namecfg.h                      |     1 +
 odb/src/ddl.RSTBIAS/obstype.h                      |     1 +
 odb/src/ddl.RSTBIAS/odb.h                          |     1 +
 odb/src/ddl.RSTBIAS/odb_macros.h                   |     1 +
 odb/src/ddl.RSTBIAS/odbcrc.h                       |     1 +
 odb/src/ddl.RSTBIAS/odbmd5.h                       |     1 +
 odb/src/ddl.RSTBIAS/pcma_extern.h                  |     1 +
 odb/src/ddl.RSTBIAS/ppcode.h                       |     1 +
 odb/src/ddl.RSTBIAS/privpub.h                      |     1 +
 odb/src/ddl.RSTBIAS/radar.h                        |     1 +
 odb/src/ddl.RSTBIAS/radar_station.h                |     1 +
 odb/src/ddl.RSTBIAS/radiance.h                     |     1 +
 odb/src/ddl.RSTBIAS/raingg.h                       |     1 +
 odb/src/ddl.RSTBIAS/resat.h                        |     1 +
 odb/src/ddl.RSTBIAS/rstbody.sql                    |     1 +
 odb/src/ddl.RSTBIAS/rsthdr.sql                     |     1 +
 odb/src/ddl.RSTBIAS/sat.h                          |     1 +
 odb/src/ddl.RSTBIAS/satob.h                        |     1 +
 odb/src/ddl.RSTBIAS/scatt.h                        |     1 +
 odb/src/ddl.RSTBIAS/sensor.h                       |     1 +
 odb/src/ddl.RSTBIAS/smos.h                         |     1 +
 odb/src/ddl.RSTBIAS/ssmi1d.h                       |     1 +
 odb/src/ddl.RSTBIAS/surfbody_feedback.h            |     1 +
 odb/src/ddl.RSTBIAS/swapbytes.h                    |     1 +
 odb/src/ddl.RSTBIAS/type_definitions.h             |     1 +
 odb/src/ddl.RSTBIAS/update.h                       |     1 +
 odb/src/ddl.RSTBIAS/varno.h                        |     1 +
 odb/src/ddl.RSTBIAS/vertco_type.h                  |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/CMakeLists.txt      |    45 +
 .../ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.ddl  |   102 +
 .../ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.dep  |    18 +
 odb/src/ddl.SONDETYPERSTRHBIAS/aeolus.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/alloc.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/allsky.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/auxiliary.h         |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/bits.h              |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/body.h              |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/cdrhook.h           |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/cloud_sink.h        |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/cma.h               |     1 +
 .../collocated_imager_information.h                |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/conv.h              |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/dca.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/ecstdlib.h          |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/ensemble.h          |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/errstat.h           |     1 +
 .../ddl.SONDETYPERSTRHBIAS/forecast_diagnostic.h   |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/funcs.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/gbrad.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/gnssro.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/hdr.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/idx.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/info.h              |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/limb.h              |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/magicwords.h        |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/mdi.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/modsurf.h           |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/namecfg.h           |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/obstype.h           |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/odb.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/odb_macros.h        |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/odbcrc.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/odbmd5.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/pcma_extern.h       |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/ppcode.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/privpub.h           |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/radar.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/radar_station.h     |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/radiance.h          |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/raingg.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/resat.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/sat.h               |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/satob.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/scatt.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/sensor.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/smos.h              |     1 +
 .../ddl.SONDETYPERSTRHBIAS/sondetyperstrhbody.sql  |     1 +
 .../ddl.SONDETYPERSTRHBIAS/sondetyperstrhhdr.sql   |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/ssmi1d.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/surfbody_feedback.h |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/swapbytes.h         |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/type_definitions.h  |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/update.h            |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/varno.h             |     1 +
 odb/src/ddl.SONDETYPERSTRHBIAS/vertco_type.h       |     1 +
 odb/src/ddl.SONDETYPES/CMakeLists.txt              |     5 +
 odb/src/ddl.SONDETYPES/SONDETYPES.ddl              |    26 +
 odb/src/ddl.SONDETYPES/sondehdr.sql                |    14 +
 odb/src/ddl/BUFRBASE.ddl                           |    82 +
 odb/src/ddl/BUFRBASE.dep                           |    11 +
 odb/src/ddl/CMakeLists.txt                         |     4 +
 odb/src/ddl/PRESCREEN.ddl                          |    79 +
 odb/src/ddl/PRESCREEN.dep                          |    14 +
 odb/src/ddl/adjust_ccma_distribid.sql              |    15 +
 odb/src/ddl/adjust_distribid.sql                   |    15 +
 odb/src/ddl/adjust_seqnos.sql                      |    11 +
 odb/src/ddl/aeolus.h                               |    50 +
 odb/src/ddl/aeolus_auxmet_update_hdrflag.sql       |    10 +
 odb/src/ddl/airep_flight_phase_robhdr.sql          |    23 +
 odb/src/ddl/airep_flight_phase_robody.sql          |    18 +
 odb/src/ddl/airs.sql                               |    13 +
 odb/src/ddl/airs_flag.sql                          |    14 +
 odb/src/ddl/ak_resat_averaging_kernel.sql          |    22 +
 odb/src/ddl/alloc.h                                |     1 +
 odb/src/ddl/allsky.h                               |    55 +
 odb/src/ddl/allsky_update_links.sql                |    13 +
 odb/src/ddl/amv.sql                                |    18 +
 odb/src/ddl/amv2.sql                               |    10 +
 odb/src/ddl/amv_flag.sql                           |    22 +
 odb/src/ddl/amv_flag2.sql                          |    12 +
 odb/src/ddl/ascatsm_robhdr_1.sql                   |    33 +
 odb/src/ddl/ascatsm_robody_1.sql                   |    41 +
 odb/src/ddl/auxiliary.h                            |    18 +
 odb/src/ddl/averaging_smos.sql                     |    27 +
 odb/src/ddl/bator_hdr_1.sql                        |     4 +
 odb/src/ddl/bator_hdr_2.sql                        |     4 +
 odb/src/ddl/bator_hdr_3.sql                        |     4 +
 odb/src/ddl/bator_hdr_4.sql                        |     4 +
 odb/src/ddl/bator_hdr_5.sql                        |     4 +
 odb/src/ddl/bator_hdr_6.sql                        |     4 +
 odb/src/ddl/bits.h                                 |     1 +
 odb/src/ddl/black_robhdr_1.sql                     |    40 +
 odb/src/ddl/black_robhdr_10.sql                    |    39 +
 odb/src/ddl/black_robhdr_2.sql                     |    49 +
 odb/src/ddl/black_robhdr_3.sql                     |    45 +
 odb/src/ddl/black_robhdr_4.sql                     |    53 +
 odb/src/ddl/black_robhdr_7.sql                     |    55 +
 odb/src/ddl/black_robhdr_8.sql                     |    46 +
 odb/src/ddl/black_robhdr_9.sql                     |    38 +
 odb/src/ddl/black_robody_1.sql                     |    30 +
 odb/src/ddl/black_robody_10.sql                    |    28 +
 odb/src/ddl/black_robody_2.sql                     |    30 +
 odb/src/ddl/black_robody_3.sql                     |    30 +
 odb/src/ddl/black_robody_4.sql                     |    32 +
 odb/src/ddl/black_robody_7.sql                     |    31 +
 odb/src/ddl/black_robody_8.sql                     |    30 +
 odb/src/ddl/black_robody_9.sql                     |    31 +
 odb/src/ddl/body.h                                 |    52 +
 odb/src/ddl/btemdup_robhdr_1.sql                   |    33 +
 odb/src/ddl/caifc1.sql                             |    15 +
 odb/src/ddl/camelo_robhdr.sql                      |    21 +
 odb/src/ddl/camelo_robody.sql                      |    23 +
 odb/src/ddl/canaco_robhdr.sql                      |    24 +
 odb/src/ddl/canaco_robhdr_ccma.sql                 |    20 +
 odb/src/ddl/canaco_robody.sql                      |    27 +
 odb/src/ddl/cancer_robhdr.sql                      |    21 +
 odb/src/ddl/cancer_robody.sql                      |    25 +
 odb/src/ddl/cantik_robhdr.sql                      |    15 +
 odb/src/ddl/cantik_robody.sql                      |    16 +
 odb/src/ddl/carcfo.sql                             |    14 +
 odb/src/ddl/caredo_robhdr.sql                      |    21 +
 odb/src/ddl/caredo_robody.sql                      |    14 +
 odb/src/ddl/castor.sql                             |    15 +
 odb/src/ddl/caviso_robhdr.sql                      |    25 +
 odb/src/ddl/caviso_robody.sql                      |    26 +
 odb/src/ddl/cavodk_robhdr.sql                      |    19 +
 odb/src/ddl/cavodk_robody.sql                      |    22 +
 odb/src/ddl/cdrhook.h                              |     1 +
 odb/src/ddl/check_linksdb.sql                      |    12 +
 odb/src/ddl/cloud_sink.h                           |    15 +
 odb/src/ddl/cma.h                                  |   226 +
 odb/src/ddl/collocated_imager_information.h        |    46 +
 odb/src/ddl/conv.h                                 |    23 +
 odb/src/ddl/conv_hdr.sql                           |    21 +
 odb/src/ddl/conv_update_links.sql                  |    13 +
 odb/src/ddl/conventional_robhdr_1.sql              |    35 +
 odb/src/ddl/conventional_robody_1.sql              |    41 +
 odb/src/ddl/count_orbit.sql                        |    15 +
 odb/src/ddl/count_scanpos.sql                      |    18 +
 odb/src/ddl/countryrstrhbody.sql                   |    21 +
 odb/src/ddl/countryrstrhhdr.sql                    |    32 +
 odb/src/ddl/cycle_biasprep_robhdr.sql              |     8 +
 odb/src/ddl/cycle_biasprep_robody.sql              |     6 +
 odb/src/ddl/cycle_biasprep_sathdr.sql              |     6 +
 odb/src/ddl/cycle_biasprep_satpred.sql             |    16 +
 odb/src/ddl/data_radar_station.sql                 |    13 +
 odb/src/ddl/date_time.sql                          |    12 +
 odb/src/ddl/dca.h                                  |     1 +
 odb/src/ddl/decis_convbody_1.sql                   |    21 +
 odb/src/ddl/decis_convbody_2.sql                   |    21 +
 odb/src/ddl/decis_robhdr_1.sql                     |    33 +
 odb/src/ddl/decis_robhdr_2.sql                     |    34 +
 odb/src/ddl/decis_robhdr_3.sql                     |    27 +
 odb/src/ddl/decis_robhdr_4.sql                     |    33 +
 odb/src/ddl/decis_robody_1.sql                     |    28 +
 odb/src/ddl/decis_robody_2.sql                     |    33 +
 odb/src/ddl/decis_robody_3.sql                     |    23 +
 odb/src/ddl/decis_robody_4.sql                     |    24 +
 odb/src/ddl/discard_dep_1.sql                      |    16 +
 odb/src/ddl/discard_dep_2.sql                      |    16 +
 odb/src/ddl/dmsprainy.sql                          |    16 +
 odb/src/ddl/ecma_body_4_psbias.sql                 |    20 +
 odb/src/ddl/ecma_body_4_rstrhbias.sql              |    18 +
 odb/src/ddl/ecma_hdr_4_psbias.sql                  |    14 +
 odb/src/ddl/ecma_hdr_4_rstrhbias.sql               |    14 +
 odb/src/ddl/ecmwf_matchup_allsky_body.sql          |    34 +
 odb/src/ddl/ecmwf_matchup_body.sql                 |    33 +
 odb/src/ddl/ecmwf_matchup_gbrad.sql                |    23 +
 odb/src/ddl/ecmwf_matchup_hdr.sql                  |    27 +
 odb/src/ddl/ecmwf_matchup_raingg.sql               |    22 +
 odb/src/ddl/ecmwf_matchup_update_1.sql             |    28 +
 odb/src/ddl/ecmwf_matchup_update_2.sql             |    28 +
 odb/src/ddl/ecmwf_matchup_update_3.sql             |    28 +
 odb/src/ddl/ecmwf_matchupsink.sql                  |    30 +
 odb/src/ddl/ecset.sql                              |    24 +
 odb/src/ddl/ecstdlib.h                             |     1 +
 odb/src/ddl/emiskf_amsua.sql                       |    27 +
 odb/src/ddl/emiskf_amsub.sql                       |    27 +
 odb/src/ddl/emiskf_atms.sql                        |    27 +
 odb/src/ddl/emiskf_mhs.sql                         |    27 +
 odb/src/ddl/emiskf_mwts2.sql                       |    27 +
 odb/src/ddl/ensemble.h                             |    52 +
 odb/src/ddl/errstat.h                              |    18 +
 odb/src/ddl/exp_info_1.sql                         |     7 +
 odb/src/ddl/fc_sens_obs.sql                        |    11 +
 odb/src/ddl/fcq_robhdr_0.sql                       |    13 +
 odb/src/ddl/fcq_robhdr_1.sql                       |    10 +
 odb/src/ddl/fcq_robhdr_2.sql                       |    10 +
 odb/src/ddl/fcq_robody_0.sql                       |    12 +
 odb/src/ddl/fcq_robody_1.sql                       |     9 +
 odb/src/ddl/fcq_robody_2.sql                       |     9 +
 odb/src/ddl/fix_date_and_time.sql                  |     9 +
 odb/src/ddl/fixresatlen.sql                        |    12 +
 odb/src/ddl/flago_mobhdr.sql                       |    15 +
 odb/src/ddl/flago_mobody.sql                       |    14 +
 odb/src/ddl/forecast_diagnostic.h                  |    17 +
 odb/src/ddl/funcs.h                                |     1 +
 odb/src/ddl/gather4poolmask.sql                    |    15 +
 odb/src/ddl/gather4poolmask_counts.sql             |    16 +
 odb/src/ddl/gbrad.h                                |    14 +
 odb/src/ddl/gbrad_body_rr.sql                      |    21 +
 odb/src/ddl/gbrad_rr.sql                           |    19 +
 odb/src/ddl/gbrad_update_links.sql                 |    13 +
 odb/src/ddl/get_soe_resat.sql                      |    24 +
 odb/src/ddl/getairepid.sql                         |    17 +
 odb/src/ddl/getgbradid.sql                         |    14 +
 odb/src/ddl/getlimbid.sql                          |    14 +
 odb/src/ddl/getsatid.sql                           |    14 +
 odb/src/ddl/getsatid_resat.sql                     |    14 +
 odb/src/ddl/getsatobid.sql                         |    19 +
 odb/src/ddl/getsfcobsid.sql                        |    19 +
 odb/src/ddl/global_enkf_1.sql                      |    45 +
 odb/src/ddl/global_enkf_10.sql                     |    45 +
 odb/src/ddl/global_enkf_100.sql                    |    45 +
 odb/src/ddl/global_enkf_105.sql                    |    45 +
 odb/src/ddl/global_enkf_110.sql                    |    45 +
 odb/src/ddl/global_enkf_115.sql                    |    45 +
 odb/src/ddl/global_enkf_120.sql                    |    45 +
 odb/src/ddl/global_enkf_15.sql                     |    45 +
 odb/src/ddl/global_enkf_2.sql                      |    45 +
 odb/src/ddl/global_enkf_20.sql                     |    45 +
 odb/src/ddl/global_enkf_25.sql                     |    45 +
 odb/src/ddl/global_enkf_3.sql                      |    45 +
 odb/src/ddl/global_enkf_30.sql                     |    45 +
 odb/src/ddl/global_enkf_35.sql                     |    45 +
 odb/src/ddl/global_enkf_4.sql                      |    45 +
 odb/src/ddl/global_enkf_40.sql                     |    45 +
 odb/src/ddl/global_enkf_45.sql                     |    45 +
 odb/src/ddl/global_enkf_5.sql                      |    45 +
 odb/src/ddl/global_enkf_50.sql                     |    45 +
 odb/src/ddl/global_enkf_55.sql                     |    45 +
 odb/src/ddl/global_enkf_60.sql                     |    45 +
 odb/src/ddl/global_enkf_65.sql                     |    45 +
 odb/src/ddl/global_enkf_70.sql                     |    45 +
 odb/src/ddl/global_enkf_75.sql                     |    45 +
 odb/src/ddl/global_enkf_80.sql                     |    45 +
 odb/src/ddl/global_enkf_85.sql                     |    45 +
 odb/src/ddl/global_enkf_90.sql                     |    45 +
 odb/src/ddl/global_enkf_95.sql                     |    45 +
 odb/src/ddl/gnssro.h                               |    24 +
 odb/src/ddl/gnssro_update_links.sql                |    13 +
 odb/src/ddl/gpsro.sql                              |    11 +
 odb/src/ddl/gpsro_2.sql                            |    15 +
 odb/src/ddl/gpsro_flag.sql                         |    14 +
 odb/src/ddl/hdr.h                                  |    76 +
 odb/src/ddl/hdr_update_links.sql                   |    13 +
 odb/src/ddl/hop_canari_conv.sql                    |    18 +
 odb/src/ddl/hop_canari_robhdr.sql                  |    20 +
 odb/src/ddl/hop_canari_robody.sql                  |    25 +
 odb/src/ddl/hretr_canari_robody.sql                |    21 +
 odb/src/ddl/hretr_canari_satbody.sql               |    22 +
 odb/src/ddl/idx.h                                  |     1 +
 odb/src/ddl/info.h                                 |     1 +
 odb/src/ddl/init_update_1.sql                      |    12 +
 odb/src/ddl/init_update_2.sql                      |    12 +
 odb/src/ddl/init_update_3.sql                      |    12 +
 odb/src/ddl/level1cgeos_robhdr_1.sql               |    31 +
 odb/src/ddl/level1cgeos_robody_1.sql               |    35 +
 odb/src/ddl/limb.h                                 |    13 +
 odb/src/ddl/links_aeolus_hdr.sql                   |    12 +
 odb/src/ddl/links_auxiliary.sql                    |    12 +
 odb/src/ddl/links_body.sql                         |    16 +
 odb/src/ddl/links_ensemble.sql                     |    13 +
 odb/src/ddl/links_gbrad.sql                        |    13 +
 odb/src/ddl/links_modsurf.sql                      |    12 +
 odb/src/ddl/links_raingg.sql                       |    13 +
 odb/src/ddl/links_sat.sql                          |    16 +
 odb/src/ddl/links_surfbody_feedback.sql            |    12 +
 odb/src/ddl/magicwords.h                           |     1 +
 odb/src/ddl/manda_gene_body.sql                    |     8 +
 odb/src/ddl/manda_gene_hdr.sql                     |    11 +
 odb/src/ddl/manda_laelalo.sql                      |     5 +
 odb/src/ddl/map_ssmi_rain_ssmi.sql                 |    17 +
 odb/src/ddl/matchup_allsky_body.sql                |    29 +
 odb/src/ddl/matchup_atovs_pred.sql                 |    26 +
 odb/src/ddl/matchup_body.sql                       |    28 +
 odb/src/ddl/matchup_gbrad.sql                      |    21 +
 odb/src/ddl/matchup_hdr.sql                        |    22 +
 odb/src/ddl/matchup_procid.sql                     |    11 +
 odb/src/ddl/matchup_raingg.sql                     |    21 +
 odb/src/ddl/matchup_sensorlist.sql                 |    19 +
 odb/src/ddl/matchup_update_1.sql                   |    23 +
 odb/src/ddl/matchup_update_10.sql                  |    19 +
 odb/src/ddl/matchup_update_2.sql                   |    23 +
 odb/src/ddl/matchup_update_3.sql                   |    23 +
 odb/src/ddl/matchup_update_4.sql                   |    19 +
 odb/src/ddl/matchup_update_5.sql                   |    19 +
 odb/src/ddl/matchup_update_6.sql                   |    19 +
 odb/src/ddl/matchup_update_7.sql                   |    19 +
 odb/src/ddl/matchup_update_8.sql                   |    19 +
 odb/src/ddl/matchup_update_9.sql                   |    19 +
 odb/src/ddl/matchupsink.sql                        |    26 +
 odb/src/ddl/max_values.sql                         |    13 +
 odb/src/ddl/mdi.h                                  |     1 +
 odb/src/ddl/mkglobstab.sql                         |    21 +
 odb/src/ddl/mkglobstab_gpsro.sql                   |    15 +
 odb/src/ddl/mobhdr_obsort.sql                      |    27 +
 odb/src/ddl/mobhdrca_obsort.sql                    |    24 +
 odb/src/ddl/modsurf.h                              |    18 +
 odb/src/ddl/nak_resat_averaging_kernel.sql         |    17 +
 odb/src/ddl/namecfg.h                              |    15 +
 odb/src/ddl/nesdis_get.sql                         |    21 +
 odb/src/ddl/new_thinn_robhdr_10.sql                |    30 +
 odb/src/ddl/new_thinn_robhdr_11.sql                |    28 +
 odb/src/ddl/new_thinn_robhdr_2.sql                 |    39 +
 odb/src/ddl/new_thinn_robhdr_3.sql                 |    35 +
 odb/src/ddl/new_thinn_robhdr_4.sql                 |    39 +
 odb/src/ddl/new_thinn_robhdr_5.sql                 |    40 +
 odb/src/ddl/new_thinn_robhdr_6.sql                 |    36 +
 odb/src/ddl/new_thinn_robhdr_7.sql                 |    32 +
 odb/src/ddl/new_thinn_robhdr_8.sql                 |    37 +
 odb/src/ddl/new_thinn_robhdr_9.sql                 |    33 +
 odb/src/ddl/new_thinn_robody_10.sql                |    20 +
 odb/src/ddl/new_thinn_robody_11.sql                |    18 +
 odb/src/ddl/new_thinn_robody_3.sql                 |    25 +
 odb/src/ddl/new_thinn_robody_4.sql                 |    26 +
 odb/src/ddl/new_thinn_robody_5.sql                 |    24 +
 odb/src/ddl/new_thinn_robody_8.sql                 |    26 +
 odb/src/ddl/new_thinn_robody_9.sql                 |    20 +
 odb/src/ddl/obatabs_robhdr.sql                     |    24 +
 odb/src/ddl/obs_boxes.sql                          |    12 +
 odb/src/ddl/obscount_1.sql                         |    14 +
 odb/src/ddl/obscount_2.sql                         |    13 +
 odb/src/ddl/obsdist.sql                            |    13 +
 odb/src/ddl/obsdist_allsky.sql                     |    30 +
 odb/src/ddl/obsdist_allsky_body.sql                |    30 +
 odb/src/ddl/obsdist_auxiliary.sql                  |    26 +
 odb/src/ddl/obsdist_auxiliary_body.sql             |    28 +
 odb/src/ddl/obsdist_body.sql                       |    26 +
 odb/src/ddl/obsdist_errstat.sql                    |    26 +
 odb/src/ddl/obsdist_gbrad.sql                      |    31 +
 odb/src/ddl/obsdist_gbrad_body.sql                 |    30 +
 odb/src/ddl/obsdist_hdr.sql                        |    25 +
 odb/src/ddl/obsdist_hdr2allsky_body.sql            |    31 +
 odb/src/ddl/obsdist_hdr2auxiliary_body.sql         |    27 +
 odb/src/ddl/obsdist_hdr2body.sql                   |    25 +
 odb/src/ddl/obsdist_hdr2gbrad_body.sql             |    32 +
 odb/src/ddl/obsdist_hdr2radar_body.sql             |    29 +
 odb/src/ddl/obsdist_hdr2radiance_body.sql          |    29 +
 odb/src/ddl/obsdist_hdr2raingg_body.sql            |    32 +
 odb/src/ddl/obsdist_hdr2resat_averaging_kernel.sql |    44 +
 odb/src/ddl/obsdist_index.sql                      |    25 +
 odb/src/ddl/obsdist_index2hdr.sql                  |    25 +
 odb/src/ddl/obsdist_limb.sql                       |    29 +
 odb/src/ddl/obsdist_modsurf.sql                    |    26 +
 odb/src/ddl/obsdist_poolno.sql                     |    21 +
 odb/src/ddl/obsdist_radar.sql                      |    29 +
 odb/src/ddl/obsdist_radar_body.sql                 |    29 +
 odb/src/ddl/obsdist_radar_station.sql              |    29 +
 odb/src/ddl/obsdist_radiance.sql                   |    30 +
 odb/src/ddl/obsdist_radiance_body.sql              |    30 +
 odb/src/ddl/obsdist_raingg.sql                     |    31 +
 odb/src/ddl/obsdist_raingg_body.sql                |    30 +
 odb/src/ddl/obsdist_resat.sql                      |    30 +
 odb/src/ddl/obsdist_resat_averaging_kernel.sql     |    29 +
 odb/src/ddl/obsdist_sat.sql                        |    26 +
 odb/src/ddl/obsdist_satob.sql                      |    29 +
 odb/src/ddl/obsdist_scatt.sql                      |    29 +
 odb/src/ddl/obsdist_scatt_body.sql                 |    30 +
 odb/src/ddl/obsdist_smos.sql                       |    30 +
 odb/src/ddl/obsdist_ssmi.sql                       |    30 +
 odb/src/ddl/obsdist_ssmi_body.sql                  |    30 +
 odb/src/ddl/obsdist_update_1.sql                   |    25 +
 odb/src/ddl/obsdist_update_10.sql                  |    25 +
 odb/src/ddl/obsdist_update_2.sql                   |    25 +
 odb/src/ddl/obsdist_update_3.sql                   |    25 +
 odb/src/ddl/obsdist_update_4.sql                   |    25 +
 odb/src/ddl/obsdist_update_5.sql                   |    25 +
 odb/src/ddl/obsdist_update_6.sql                   |    25 +
 odb/src/ddl/obsdist_update_7.sql                   |    25 +
 odb/src/ddl/obsdist_update_8.sql                   |    25 +
 odb/src/ddl/obsdist_update_9.sql                   |    25 +
 odb/src/ddl/obsdist_windows.sql                    |    13 +
 odb/src/ddl/obshor.sql                             |    23 +
 odb/src/ddl/obsort_allsky.sql                      |    24 +
 odb/src/ddl/obsort_allsky_body.sql                 |    23 +
 odb/src/ddl/obsort_auxiliary.sql                   |    21 +
 odb/src/ddl/obsort_body.sql                        |    20 +
 odb/src/ddl/obsort_cloud_sink.sql                  |    24 +
 .../ddl/obsort_collocated_imager_information.sql   |    26 +
 odb/src/ddl/obsort_conv.sql                        |    25 +
 odb/src/ddl/obsort_conv_body.sql                   |    22 +
 odb/src/ddl/obsort_errstat.sql                     |    20 +
 odb/src/ddl/obsort_gbrad.sql                       |    24 +
 odb/src/ddl/obsort_gbrad_body.sql                  |    23 +
 odb/src/ddl/obsort_gnssro.sql                      |    24 +
 odb/src/ddl/obsort_gnssro_body.sql                 |    23 +
 odb/src/ddl/obsort_hdr.sql                         |    19 +
 odb/src/ddl/obsort_hdr2allsky_body.sql             |    24 +
 odb/src/ddl/obsort_hdr2auxiliary_body.sql          |    19 +
 odb/src/ddl/obsort_hdr2body.sql                    |    19 +
 odb/src/ddl/obsort_hdr2conv_body.sql               |    24 +
 odb/src/ddl/obsort_hdr2gbrad_body.sql              |    24 +
 odb/src/ddl/obsort_hdr2gnssro_body.sql             |    24 +
 odb/src/ddl/obsort_hdr2radar_body.sql              |    21 +
 odb/src/ddl/obsort_hdr2radiance_body.sql           |    25 +
 odb/src/ddl/obsort_hdr2raingg_body.sql             |    25 +
 odb/src/ddl/obsort_hdr2ralt_body.sql               |    24 +
 odb/src/ddl/obsort_hdr2resat_averaging_kernel.sql  |    38 +
 odb/src/ddl/obsort_hdr2scatt_body.sql              |    24 +
 odb/src/ddl/obsort_index.sql                       |    19 +
 odb/src/ddl/obsort_limb.sql                        |    23 +
 odb/src/ddl/obsort_modsurf.sql                     |    20 +
 odb/src/ddl/obsort_radar.sql                       |    23 +
 odb/src/ddl/obsort_radar_body.sql                  |    22 +
 odb/src/ddl/obsort_radar_station.sql               |    23 +
 odb/src/ddl/obsort_radiance.sql                    |    24 +
 odb/src/ddl/obsort_radiance_body.sql               |    23 +
 odb/src/ddl/obsort_raingg.sql                      |    25 +
 odb/src/ddl/obsort_raingg_body.sql                 |    24 +
 odb/src/ddl/obsort_ralt.sql                        |    23 +
 odb/src/ddl/obsort_resat.sql                       |    24 +
 odb/src/ddl/obsort_resat_averaging_kernel.sql      |    23 +
 odb/src/ddl/obsort_sat.sql                         |    20 +
 odb/src/ddl/obsort_satob.sql                       |    23 +
 odb/src/ddl/obsort_scatt.sql                       |    23 +
 odb/src/ddl/obsort_scatt_body.sql                  |    22 +
 odb/src/ddl/obsort_smos.sql                        |    26 +
 odb/src/ddl/obsort_ssmi.sql                        |    24 +
 odb/src/ddl/obsort_ssmi_body.sql                   |    23 +
 odb/src/ddl/obsort_update.sql                      |    18 +
 odb/src/ddl/obsort_update_1.sql                    |    21 +
 odb/src/ddl/obsort_update_2.sql                    |    21 +
 odb/src/ddl/obsort_update_3.sql                    |    21 +
 odb/src/ddl/obsortca_auxiliary.sql                 |    24 +
 odb/src/ddl/obsortca_body.sql                      |    21 +
 odb/src/ddl/obsortca_errstat.sql                   |    21 +
 odb/src/ddl/obsortca_hdr.sql                       |    20 +
 odb/src/ddl/obsortca_hdr2auxiliary_body.sql        |    22 +
 odb/src/ddl/obsortca_hdr2body.sql                  |    21 +
 odb/src/ddl/obsortca_index.sql                     |    20 +
 odb/src/ddl/obsortca_update_1.sql                  |    21 +
 odb/src/ddl/obsortca_update_2.sql                  |    21 +
 odb/src/ddl/obsortca_update_3.sql                  |    21 +
 odb/src/ddl/obstat.sql                             |    41 +
 odb/src/ddl/obstat_conv.sql                        |    41 +
 odb/src/ddl/obstat_fcdep.sql                       |    43 +
 odb/src/ddl/obstat_fcdep_gpsro.sql                 |    42 +
 odb/src/ddl/obstat_geos.sql                        |    41 +
 odb/src/ddl/obstat_gpsro.sql                       |    42 +
 odb/src/ddl/obstat_mwimg.sql                       |    39 +
 odb/src/ddl/obstat_radar.sql                       |    42 +
 odb/src/ddl/obstat_resat.sql                       |    44 +
 odb/src/ddl/obstat_satob.sql                       |    41 +
 odb/src/ddl/obstat_scatt.sql                       |    40 +
 odb/src/ddl/obstat_smos.sql                        |    39 +
 odb/src/ddl/obstat_smos_land.sql                   |    39 +
 odb/src/ddl/obstat_tovs.sql                        |    40 +
 odb/src/ddl/obstatfc_1.sql                         |    22 +
 odb/src/ddl/obstatfc_10.sql                        |    22 +
 odb/src/ddl/obstatfc_11.sql                        |    22 +
 odb/src/ddl/obstatfc_12.sql                        |    22 +
 odb/src/ddl/obstatfc_13.sql                        |    22 +
 odb/src/ddl/obstatfc_14.sql                        |    22 +
 odb/src/ddl/obstatfc_15.sql                        |    22 +
 odb/src/ddl/obstatfc_16.sql                        |    22 +
 odb/src/ddl/obstatfc_17.sql                        |    22 +
 odb/src/ddl/obstatfc_18.sql                        |    22 +
 odb/src/ddl/obstatfc_19.sql                        |    22 +
 odb/src/ddl/obstatfc_2.sql                         |    22 +
 odb/src/ddl/obstatfc_20.sql                        |    22 +
 odb/src/ddl/obstatfc_3.sql                         |    22 +
 odb/src/ddl/obstatfc_4.sql                         |    22 +
 odb/src/ddl/obstatfc_5.sql                         |    22 +
 odb/src/ddl/obstatfc_6.sql                         |    22 +
 odb/src/ddl/obstatfc_7.sql                         |    22 +
 odb/src/ddl/obstatfc_8.sql                         |    22 +
 odb/src/ddl/obstatfc_9.sql                         |    22 +
 odb/src/ddl/obstype.h                              |    52 +
 odb/src/ddl/odb.h                                  |     1 +
 odb/src/ddl/odb2ee_aeolus_auxmet.sql               |    19 +
 odb/src/ddl/odb98.flags                            |    75 +
 odb/src/ddl/odb_info.sql                           |     4 +
 odb/src/ddl/odb_macros.h                           |     1 +
 odb/src/ddl/odbcrc.h                               |     1 +
 odb/src/ddl/odbmd5.h                               |     1 +
 odb/src/ddl/out_body.sql                           |    22 +
 odb/src/ddl/out_desc.sql                           |    17 +
 odb/src/ddl/out_hdr.sql                            |    17 +
 odb/src/ddl/ozone_robhdr_1.sql                     |    33 +
 odb/src/ddl/ozone_robody_1.sql                     |    37 +
 odb/src/ddl/pcma_extern.h                          |     1 +
 odb/src/ddl/pertobs_corr_robhdr.sql                |    24 +
 odb/src/ddl/pertobs_corr_robody.sql                |    25 +
 odb/src/ddl/pertobs_uncorr_robhdr.sql              |    22 +
 odb/src/ddl/pertobs_uncorr_robody.sql              |    24 +
 odb/src/ddl/poolmask_1.sql                         |    19 +
 odb/src/ddl/poolmask_2.sql                         |    21 +
 odb/src/ddl/post_thinn_robhdr_2.sql                |    37 +
 odb/src/ddl/post_thinn_robhdr_3.sql                |    32 +
 odb/src/ddl/post_thinn_robhdr_4.sql                |    34 +
 odb/src/ddl/post_thinn_robhdr_5.sql                |    35 +
 odb/src/ddl/post_thinn_robhdr_6.sql                |    33 +
 odb/src/ddl/post_thinn_robhdr_7.sql                |    30 +
 odb/src/ddl/post_thinn_robhdr_8.sql                |    34 +
 odb/src/ddl/post_thinn_robhdr_9.sql                |    31 +
 odb/src/ddl/post_thinn_robody_2.sql                |    30 +
 odb/src/ddl/post_thinn_robody_3.sql                |    23 +
 odb/src/ddl/post_thinn_robody_4.sql                |    24 +
 odb/src/ddl/post_thinn_robody_5.sql                |    23 +
 odb/src/ddl/post_thinn_robody_6.sql                |    25 +
 odb/src/ddl/post_thinn_robody_7.sql                |    23 +
 odb/src/ddl/post_thinn_robody_8.sql                |    26 +
 odb/src/ddl/post_thinn_robody_9.sql                |    23 +
 odb/src/ddl/ppcode.h                               |    15 +
 odb/src/ddl/pre_thinn_robhdr_10.sql                |    30 +
 odb/src/ddl/pre_thinn_robhdr_11.sql                |    28 +
 odb/src/ddl/pre_thinn_robhdr_2.sql                 |    41 +
 odb/src/ddl/pre_thinn_robhdr_3.sql                 |    35 +
 odb/src/ddl/pre_thinn_robhdr_4.sql                 |    37 +
 odb/src/ddl/pre_thinn_robhdr_5.sql                 |    38 +
 odb/src/ddl/pre_thinn_robhdr_6.sql                 |    36 +
 odb/src/ddl/pre_thinn_robhdr_7.sql                 |    32 +
 odb/src/ddl/pre_thinn_robhdr_8.sql                 |    36 +
 odb/src/ddl/pre_thinn_robhdr_9.sql                 |    33 +
 odb/src/ddl/pre_thinn_robody_10.sql                |    22 +
 odb/src/ddl/pre_thinn_robody_11.sql                |    20 +
 odb/src/ddl/pre_thinn_robody_2.sql                 |    32 +
 odb/src/ddl/pre_thinn_robody_3.sql                 |    24 +
 odb/src/ddl/pre_thinn_robody_4.sql                 |    24 +
 odb/src/ddl/pre_thinn_robody_5.sql                 |    23 +
 odb/src/ddl/pre_thinn_robody_6.sql                 |    25 +
 odb/src/ddl/pre_thinn_robody_7.sql                 |    24 +
 odb/src/ddl/pre_thinn_robody_8.sql                 |    26 +
 odb/src/ddl/pre_thinn_robody_9.sql                 |    25 +
 odb/src/ddl/privpub.h                              |     1 +
 odb/src/ddl/prtdpst_robhdr.sql                     |    16 +
 odb/src/ddl/prtdpst_robody.sql                     |    11 +
 odb/src/ddl/radar.h                                |    29 +
 odb/src/ddl/radar_station.h                        |    14 +
 odb/src/ddl/radiance.h                             |    53 +
 odb/src/ddl/radiance_averaging.sql                 |    53 +
 odb/src/ddl/radiance_update_links.sql              |    13 +
 odb/src/ddl/raingg.h                               |    14 +
 odb/src/ddl/raingg_body_rr.sql                     |    21 +
 odb/src/ddl/raingg_rr.sql                          |    19 +
 odb/src/ddl/ralt.sql                               |     9 +
 odb/src/ddl/ralt_wam.sql                           |    31 +
 odb/src/ddl/redun_robhdr_1.sql                     |    31 +
 odb/src/ddl/redun_robhdr_2.sql                     |    19 +
 odb/src/ddl/redun_robhdr_3.sql                     |    32 +
 odb/src/ddl/redun_robhdr_4.sql                     |    31 +
 odb/src/ddl/redun_robhdr_5.sql                     |    31 +
 odb/src/ddl/redun_robhdr_6.sql                     |    34 +
 odb/src/ddl/redun_robhdr_7.sql                     |    26 +
 odb/src/ddl/redun_robody_1.sql                     |    23 +
 odb/src/ddl/redun_robody_2.sql                     |    21 +
 odb/src/ddl/redun_robody_3.sql                     |    20 +
 odb/src/ddl/redun_robody_4.sql                     |    21 +
 odb/src/ddl/redun_robody_5.sql                     |    19 +
 odb/src/ddl/redun_robody_6.sql                     |    25 +
 odb/src/ddl/redun_robody_7.sql                     |    23 +
 odb/src/ddl/reini_body.sql                         |    15 +
 odb/src/ddl/reini_hdr.sql                          |    13 +
 odb/src/ddl/reprod_seqno_1.sql                     |    20 +
 odb/src/ddl/reprod_seqno_2.sql                     |    20 +
 odb/src/ddl/reprod_seqno_3.sql                     |    21 +
 odb/src/ddl/reprod_seqno_4.sql                     |    20 +
 odb/src/ddl/resat.h                                |    38 +
 odb/src/ddl/resat_update_links.sql                 |    13 +
 odb/src/ddl/revmatchup_body.sql                    |    26 +
 odb/src/ddl/revmatchup_hdr.sql                     |    18 +
 odb/src/ddl/robhdr.sql                             |    48 +
 odb/src/ddl/robhdr_gbrad_get_rr.sql                |    22 +
 odb/src/ddl/robhdr_gbrad_put_rr.sql                |    21 +
 odb/src/ddl/robhdr_gp_get_ssmi.sql                 |    22 +
 odb/src/ddl/robhdr_grid_distribute.sql             |    21 +
 odb/src/ddl/robhdr_mwave_count_smos.sql            |    15 +
 odb/src/ddl/robhdr_mwave_process_smos.sql          |    20 +
 odb/src/ddl/robhdr_mwave_update_smos.sql           |    18 +
 odb/src/ddl/robhdr_obsort.sql                      |    21 +
 odb/src/ddl/robhdr_rad.sql                         |    35 +
 odb/src/ddl/robhdr_raingg_get_rr.sql               |    20 +
 odb/src/ddl/robhdr_raingg_put_rr.sql               |    19 +
 odb/src/ddl/robhdr_screen.sql                      |    42 +
 odb/src/ddl/robhdr_screen_conv.sql                 |    16 +
 odb/src/ddl/robhdr_tc.sql                          |    23 +
 odb/src/ddl/robhdrca_obsort.sql                    |    18 +
 odb/src/ddl/robody.sql                             |    56 +
 odb/src/ddl/robody_gbrad_get_rr.sql                |    24 +
 odb/src/ddl/robody_gbrad_put_rr.sql                |    28 +
 odb/src/ddl/robody_gp_get_ssmi.sql                 |    24 +
 odb/src/ddl/robody_mwave_process_smos.sql          |    16 +
 odb/src/ddl/robody_mwave_update_smos.sql           |    20 +
 odb/src/ddl/robody_rad.sql                         |    51 +
 odb/src/ddl/robody_raingg_get_rr.sql               |    23 +
 odb/src/ddl/robody_raingg_put_rr.sql               |    28 +
 odb/src/ddl/robody_screen.sql                      |    36 +
 odb/src/ddl/robody_smos_sekf.sql                   |    31 +
 odb/src/ddl/robody_tc.sql                          |    22 +
 odb/src/ddl/robody_traj.sql                        |    41 +
 odb/src/ddl/rstbody.sql                            |    11 +
 odb/src/ddl/rsthdr.sql                             |     8 +
 odb/src/ddl/sat.h                                  |    30 +
 odb/src/ddl/sat_aeolus.sql                         |    18 +
 odb/src/ddl/sat_aeolusl2c.sql                      |    30 +
 odb/src/ddl/sat_atovs.sql                          |    65 +
 odb/src/ddl/sat_gpsro.sql                          |    22 +
 odb/src/ddl/sat_lrad.sql                           |    26 +
 odb/src/ddl/sat_radar.sql                          |    12 +
 odb/src/ddl/sat_satob.sql                          |    36 +
 odb/src/ddl/sat_smos.sql                           |    24 +
 odb/src/ddl/sat_ssmi.sql                           |    60 +
 odb/src/ddl/sat_update_links.sql                   |    13 +
 odb/src/ddl/satbody_allsky.sql                     |    31 +
 odb/src/ddl/satbody_atovs.sql                      |    37 +
 odb/src/ddl/satbody_gpsro.sql                      |    24 +
 odb/src/ddl/satbody_radar.sql                      |    24 +
 odb/src/ddl/satbody_scat.sql                       |    32 +
 odb/src/ddl/satbody_screen_atovs.sql               |    32 +
 odb/src/ddl/satellite_identifier_list.sql          |    14 +
 odb/src/ddl/sathdr_cloud_sink.sql                  |    26 +
 odb/src/ddl/sathdr_limb.sql                        |    21 +
 odb/src/ddl/sathdr_ozone.sql                       |    33 +
 odb/src/ddl/sathdr_radar.sql                       |    24 +
 odb/src/ddl/sathdr_satob.sql                       |    22 +
 odb/src/ddl/sathdr_scat.sql                        |    19 +
 odb/src/ddl/sathdr_screen_aeolus_auxmet.sql        |    32 +
 odb/src/ddl/sathdr_screen_aeolus_hdr.sql           |    19 +
 odb/src/ddl/sathdr_screen_atovs.sql                |    61 +
 odb/src/ddl/sathdr_screen_cloud_sink.sql           |    23 +
 odb/src/ddl/sathdr_screen_gpsro.sql                |    16 +
 odb/src/ddl/sathdr_screen_lrad.sql                 |    23 +
 odb/src/ddl/sathdr_screen_resat.sql                |    14 +
 odb/src/ddl/sathdr_screen_satob.sql                |    40 +
 odb/src/ddl/satob.h                                |    41 +
 odb/src/ddl/satob_robhdr_1.sql                     |    29 +
 odb/src/ddl/satob_robody_1.sql                     |    35 +
 odb/src/ddl/scat_robhdr_1.sql                      |    34 +
 odb/src/ddl/scat_robody_1.sql                      |    41 +
 odb/src/ddl/scatt.h                                |    30 +
 odb/src/ddl/scatt.sql                              |     9 +
 odb/src/ddl/scatt_flag.sql                         |    12 +
 odb/src/ddl/scatt_update_links.sql                 |    13 +
 odb/src/ddl/screen_robhdr_1.sql                    |    21 +
 odb/src/ddl/screen_robhdr_2.sql                    |    26 +
 odb/src/ddl/screen_robhdr_3.sql                    |    22 +
 odb/src/ddl/screen_robody_1.sql                    |    20 +
 odb/src/ddl/screen_robody_2.sql                    |    23 +
 odb/src/ddl/screen_robody_3.sql                    |    20 +
 odb/src/ddl/sensor.h                               |    19 +
 odb/src/ddl/set_active.sql                         |    18 +
 odb/src/ddl/set_active_smos.sql                    |    18 +
 odb/src/ddl/setup_tovscv.sql                       |    27 +
 odb/src/ddl/setup_tovscv_cloud_sink.sql            |    21 +
 odb/src/ddl/size_hdr.sql                           |    11 +
 odb/src/ddl/small.sql                              |     4 +
 odb/src/ddl/smos.h                                 |    22 +
 odb/src/ddl/sondetyperstrhbody.sql                 |    21 +
 odb/src/ddl/sondetyperstrhhdr.sql                  |    14 +
 odb/src/ddl/ssa_robhdr_2m.sql                      |    20 +
 odb/src/ddl/ssa_robhdr_snow.sql                    |    19 +
 odb/src/ddl/ssa_robody_2m.sql                      |    24 +
 odb/src/ddl/ssa_robody_snow.sql                    |    21 +
 odb/src/ddl/ssafb_surfbody_2m.sql                  |    23 +
 odb/src/ddl/ssafb_surfbody_snow.sql                |    23 +
 odb/src/ddl/ssmi1d.h                               |    53 +
 odb/src/ddl/stat_obs_1.sql                         |     8 +
 odb/src/ddl/stat_obs_2.sql                         |     7 +
 odb/src/ddl/stat_obs_3.sql                         |    10 +
 odb/src/ddl/store_enda.sql                         |    27 +
 odb/src/ddl/sufger_allsky.sql                      |    22 +
 odb/src/ddl/sufger_allsky_body.sql                 |    19 +
 odb/src/ddl/sufger_robhdr_1.sql                    |    25 +
 odb/src/ddl/sufger_robody_1.sql                    |    28 +
 odb/src/ddl/sufger_sat.sql                         |    20 +
 odb/src/ddl/sugoms.sql                             |    12 +
 odb/src/ddl/suobarea.sql                           |    22 +
 odb/src/ddl/suobarea_limb.sql                      |    17 +
 odb/src/ddl/suobarea_sat.sql                       |    22 +
 odb/src/ddl/suobarea_satob.sql                     |    22 +
 odb/src/ddl/suobarea_scatt.sql                     |    21 +
 odb/src/ddl/suobsaddr.sql                          |    24 +
 odb/src/ddl/suobsbias_robhdr_0.sql                 |     0
 odb/src/ddl/suobsbias_robody_0.sql                 |     0
 odb/src/ddl/suobscor_robhdr.sql                    |    24 +
 odb/src/ddl/suobscor_robody.sql                    |    19 +
 odb/src/ddl/surfbody_feedback.h                    |    14 +
 odb/src/ddl/suvarbc_robhdh_0.sql                   |     0
 odb/src/ddl/suvarbc_robhdr_0.sql                   |    17 +
 odb/src/ddl/suvarbc_robody_0.sql                   |    16 +
 odb/src/ddl/swapbytes.h                            |     1 +
 odb/src/ddl/tcwv.sql                               |    15 +
 odb/src/ddl/time_info.sql                          |     8 +
 odb/src/ddl/time_numtsl.sql                        |     7 +
 odb/src/ddl/tovsrtovs_robody_1.sql                 |    36 +
 odb/src/ddl/tslot.sql                              |    12 +
 odb/src/ddl/type_definitions.h                     |   209 +
 odb/src/ddl/update.h                               |    16 +
 odb/src/ddl/update_body_3.sql                      |    18 +
 odb/src/ddl/update_desc_1.sql                      |    12 +
 odb/src/ddl/update_desc_2.sql                      |    12 +
 odb/src/ddl/update_enkf_links.sql                  |    14 +
 odb/src/ddl/update_fcdiag_links.sql                |    13 +
 odb/src/ddl/update_hdr_1.sql                       |    14 +
 odb/src/ddl/update_hdr_2.sql                       |    14 +
 odb/src/ddl/update_hdr_3.sql                       |    15 +
 odb/src/ddl/update_hprior_1.sql                    |    23 +
 odb/src/ddl/update_hprior_10.sql                   |    23 +
 odb/src/ddl/update_hprior_100.sql                  |    23 +
 odb/src/ddl/update_hprior_101.sql                  |    23 +
 odb/src/ddl/update_hprior_102.sql                  |    23 +
 odb/src/ddl/update_hprior_103.sql                  |    23 +
 odb/src/ddl/update_hprior_104.sql                  |    23 +
 odb/src/ddl/update_hprior_105.sql                  |    23 +
 odb/src/ddl/update_hprior_106.sql                  |    23 +
 odb/src/ddl/update_hprior_107.sql                  |    23 +
 odb/src/ddl/update_hprior_108.sql                  |    23 +
 odb/src/ddl/update_hprior_109.sql                  |    23 +
 odb/src/ddl/update_hprior_11.sql                   |    23 +
 odb/src/ddl/update_hprior_110.sql                  |    23 +
 odb/src/ddl/update_hprior_111.sql                  |    23 +
 odb/src/ddl/update_hprior_112.sql                  |    23 +
 odb/src/ddl/update_hprior_113.sql                  |    23 +
 odb/src/ddl/update_hprior_114.sql                  |    23 +
 odb/src/ddl/update_hprior_115.sql                  |    23 +
 odb/src/ddl/update_hprior_116.sql                  |    23 +
 odb/src/ddl/update_hprior_117.sql                  |    23 +
 odb/src/ddl/update_hprior_118.sql                  |    23 +
 odb/src/ddl/update_hprior_119.sql                  |    23 +
 odb/src/ddl/update_hprior_12.sql                   |    23 +
 odb/src/ddl/update_hprior_120.sql                  |    23 +
 odb/src/ddl/update_hprior_13.sql                   |    23 +
 odb/src/ddl/update_hprior_14.sql                   |    23 +
 odb/src/ddl/update_hprior_15.sql                   |    23 +
 odb/src/ddl/update_hprior_16.sql                   |    23 +
 odb/src/ddl/update_hprior_17.sql                   |    23 +
 odb/src/ddl/update_hprior_18.sql                   |    23 +
 odb/src/ddl/update_hprior_19.sql                   |    23 +
 odb/src/ddl/update_hprior_2.sql                    |    23 +
 odb/src/ddl/update_hprior_20.sql                   |    23 +
 odb/src/ddl/update_hprior_21.sql                   |    23 +
 odb/src/ddl/update_hprior_22.sql                   |    23 +
 odb/src/ddl/update_hprior_23.sql                   |    23 +
 odb/src/ddl/update_hprior_24.sql                   |    23 +
 odb/src/ddl/update_hprior_25.sql                   |    23 +
 odb/src/ddl/update_hprior_26.sql                   |    23 +
 odb/src/ddl/update_hprior_27.sql                   |    23 +
 odb/src/ddl/update_hprior_28.sql                   |    23 +
 odb/src/ddl/update_hprior_29.sql                   |    23 +
 odb/src/ddl/update_hprior_3.sql                    |    23 +
 odb/src/ddl/update_hprior_30.sql                   |    23 +
 odb/src/ddl/update_hprior_31.sql                   |    23 +
 odb/src/ddl/update_hprior_32.sql                   |    23 +
 odb/src/ddl/update_hprior_33.sql                   |    23 +
 odb/src/ddl/update_hprior_34.sql                   |    23 +
 odb/src/ddl/update_hprior_35.sql                   |    23 +
 odb/src/ddl/update_hprior_36.sql                   |    23 +
 odb/src/ddl/update_hprior_37.sql                   |    23 +
 odb/src/ddl/update_hprior_38.sql                   |    23 +
 odb/src/ddl/update_hprior_39.sql                   |    23 +
 odb/src/ddl/update_hprior_4.sql                    |    23 +
 odb/src/ddl/update_hprior_40.sql                   |    23 +
 odb/src/ddl/update_hprior_41.sql                   |    23 +
 odb/src/ddl/update_hprior_42.sql                   |    23 +
 odb/src/ddl/update_hprior_43.sql                   |    23 +
 odb/src/ddl/update_hprior_44.sql                   |    23 +
 odb/src/ddl/update_hprior_45.sql                   |    23 +
 odb/src/ddl/update_hprior_46.sql                   |    23 +
 odb/src/ddl/update_hprior_47.sql                   |    23 +
 odb/src/ddl/update_hprior_48.sql                   |    23 +
 odb/src/ddl/update_hprior_49.sql                   |    23 +
 odb/src/ddl/update_hprior_5.sql                    |    23 +
 odb/src/ddl/update_hprior_50.sql                   |    23 +
 odb/src/ddl/update_hprior_51.sql                   |    23 +
 odb/src/ddl/update_hprior_52.sql                   |    23 +
 odb/src/ddl/update_hprior_53.sql                   |    23 +
 odb/src/ddl/update_hprior_54.sql                   |    23 +
 odb/src/ddl/update_hprior_55.sql                   |    23 +
 odb/src/ddl/update_hprior_56.sql                   |    23 +
 odb/src/ddl/update_hprior_57.sql                   |    23 +
 odb/src/ddl/update_hprior_58.sql                   |    23 +
 odb/src/ddl/update_hprior_59.sql                   |    23 +
 odb/src/ddl/update_hprior_6.sql                    |    23 +
 odb/src/ddl/update_hprior_60.sql                   |    23 +
 odb/src/ddl/update_hprior_61.sql                   |    23 +
 odb/src/ddl/update_hprior_62.sql                   |    23 +
 odb/src/ddl/update_hprior_63.sql                   |    23 +
 odb/src/ddl/update_hprior_64.sql                   |    23 +
 odb/src/ddl/update_hprior_65.sql                   |    23 +
 odb/src/ddl/update_hprior_66.sql                   |    23 +
 odb/src/ddl/update_hprior_67.sql                   |    23 +
 odb/src/ddl/update_hprior_68.sql                   |    23 +
 odb/src/ddl/update_hprior_69.sql                   |    23 +
 odb/src/ddl/update_hprior_7.sql                    |    23 +
 odb/src/ddl/update_hprior_70.sql                   |    23 +
 odb/src/ddl/update_hprior_71.sql                   |    23 +
 odb/src/ddl/update_hprior_72.sql                   |    23 +
 odb/src/ddl/update_hprior_73.sql                   |    23 +
 odb/src/ddl/update_hprior_74.sql                   |    23 +
 odb/src/ddl/update_hprior_75.sql                   |    23 +
 odb/src/ddl/update_hprior_76.sql                   |    23 +
 odb/src/ddl/update_hprior_77.sql                   |    23 +
 odb/src/ddl/update_hprior_78.sql                   |    23 +
 odb/src/ddl/update_hprior_79.sql                   |    23 +
 odb/src/ddl/update_hprior_8.sql                    |    23 +
 odb/src/ddl/update_hprior_80.sql                   |    23 +
 odb/src/ddl/update_hprior_81.sql                   |    23 +
 odb/src/ddl/update_hprior_82.sql                   |    23 +
 odb/src/ddl/update_hprior_83.sql                   |    23 +
 odb/src/ddl/update_hprior_84.sql                   |    23 +
 odb/src/ddl/update_hprior_85.sql                   |    23 +
 odb/src/ddl/update_hprior_86.sql                   |    23 +
 odb/src/ddl/update_hprior_87.sql                   |    23 +
 odb/src/ddl/update_hprior_88.sql                   |    23 +
 odb/src/ddl/update_hprior_89.sql                   |    23 +
 odb/src/ddl/update_hprior_9.sql                    |    23 +
 odb/src/ddl/update_hprior_90.sql                   |    23 +
 odb/src/ddl/update_hprior_91.sql                   |    23 +
 odb/src/ddl/update_hprior_92.sql                   |    23 +
 odb/src/ddl/update_hprior_93.sql                   |    23 +
 odb/src/ddl/update_hprior_94.sql                   |    23 +
 odb/src/ddl/update_hprior_95.sql                   |    23 +
 odb/src/ddl/update_hprior_96.sql                   |    23 +
 odb/src/ddl/update_hprior_97.sql                   |    23 +
 odb/src/ddl/update_hprior_98.sql                   |    23 +
 odb/src/ddl/update_hprior_99.sql                   |    23 +
 odb/src/ddl/update_links_allsky.sql                |    12 +
 odb/src/ddl/update_links_auxiliary.sql             |    12 +
 odb/src/ddl/update_links_gbrad.sql                 |    13 +
 odb/src/ddl/update_links_radiance.sql              |    14 +
 odb/src/ddl/update_links_raingg.sql                |    13 +
 odb/src/ddl/update_links_ssmi.sql                  |    12 +
 odb/src/ddl/update_modstep.sql                     |    12 +
 odb/src/ddl/varbc_airep_robhdr.sql                 |    15 +
 odb/src/ddl/varbc_airep_robody.sql                 |    14 +
 odb/src/ddl/varbc_allsky_robhdr.sql                |    14 +
 odb/src/ddl/varbc_allsky_robody.sql                |    14 +
 odb/src/ddl/varbc_gbrad_robhdr.sql                 |    14 +
 odb/src/ddl/varbc_gbrad_robody.sql                 |    13 +
 odb/src/ddl/varbc_mode_hist_robhdr.sql             |    12 +
 odb/src/ddl/varbc_mode_hist_robody.sql             |    14 +
 odb/src/ddl/varbc_rad_robhdr.sql                   |    15 +
 odb/src/ddl/varbc_rad_robody.sql                   |    14 +
 odb/src/ddl/varbc_setup_robhdr.sql                 |    12 +
 odb/src/ddl/varbc_setup_robody.sql                 |    12 +
 odb/src/ddl/varbc_sfcobs_robhdr.sql                |    18 +
 odb/src/ddl/varbc_sfcobs_robody.sql                |    23 +
 odb/src/ddl/varbc_tcwv_robhdr.sql                  |    14 +
 odb/src/ddl/varbc_tcwv_robody.sql                  |    14 +
 odb/src/ddl/varbc_to3_robhdr.sql                   |    16 +
 odb/src/ddl/varbc_to3_robody.sql                   |    15 +
 odb/src/ddl/varno.h                                |   156 +
 odb/src/ddl/vertco_type.h                          |    17 +
 odb/src/ddl/xcheck.sql                             |    13 +
 odb/src/extras/CMakeLists.txt                      |     4 +
 odb/src/extras/ec/CMakeLists.txt                   |    15 +
 odb/src/extras/ec/eclib.h                          |   558 +
 odb/src/extras/ec/eclib_c.c                        |    30 +
 odb/src/extras/ec/error.c                          |   119 +
 odb/src/extras/ec/julian.h                         |   219 +
 odb/src/extras/ec/julian_lib.c                     |   794 +
 odb/src/extras/ec/myhdr.h                          |    46 +
 odb/src/extras/emos/CMakeLists.txt                 |    22 +
 odb/src/extras/emos/bufrgrib.h                     |    23 +
 odb/src/extras/emos/fileRead.h                     |    73 +
 odb/src/extras/emos/fort2c.h                       |    98 +
 odb/src/extras/emos/pbio.c                         |  1324 +
 odb/src/extras/emos/readprod.c                     |   846 +
 odb/src/extras/emos/sizeRoutines.h                 |    18 +
 odb/src/extras/ifsaux/CMakeLists.txt               |   129 +
 odb/src/extras/ifsaux/include/cargs.h              |    59 +
 odb/src/extras/ifsaux/include/crc.h                |    35 +
 odb/src/extras/ifsaux/include/dr_hook_util.h       |     7 +
 odb/src/extras/ifsaux/include/dr_hook_util_multi.h |     7 +
 odb/src/extras/ifsaux/include/drhook.h             |   175 +
 odb/src/extras/ifsaux/include/ecsort_shared.h      |   681 +
 odb/src/extras/ifsaux/include/getstatm.h           |    31 +
 odb/src/extras/ifsaux/include/intercept_alloc.h    |    50 +
 odb/src/extras/ifsaux/include/raise.h              |    33 +
 odb/src/extras/ifsaux/include/user_clock.h         |    49 +
 odb/src/extras/ifsaux/module/.parkind1.F90.un~     |   Bin 0 -> 1070 bytes
 odb/src/extras/ifsaux/module/dr_hook_watch_mod.F90 |   365 +
 odb/src/extras/ifsaux/module/ecsort_mix.F90        |   330 +
 odb/src/extras/ifsaux/module/f90_unix_env.F90      |     9 +
 odb/src/extras/ifsaux/module/f90_unix_io.F90       |     9 +
 odb/src/extras/ifsaux/module/f90_unix_proc.F90     |     9 +
 odb/src/extras/ifsaux/module/local_trafos.F90      |   120 +
 odb/src/extras/ifsaux/module/mpi4to8.F90           |     6 +
 odb/src/extras/ifsaux/module/mpi4to8_m.F90         |  3300 ++
 odb/src/extras/ifsaux/module/mpi4to8_s.F90         |   708 +
 odb/src/extras/ifsaux/module/mpl_abort_mod.F90     |    48 +
 odb/src/extras/ifsaux/module/mpl_allgather_mod.F90 |    79 +
 .../extras/ifsaux/module/mpl_allgatherv_mod.F90    |   667 +
 odb/src/extras/ifsaux/module/mpl_allreduce_mod.F90 |   514 +
 odb/src/extras/ifsaux/module/mpl_alltoallv_mod.F90 |   327 +
 odb/src/extras/ifsaux/module/mpl_arg_mod.F90       |   189 +
 odb/src/extras/ifsaux/module/mpl_barrier_mod.F90   |   101 +
 odb/src/extras/ifsaux/module/mpl_broadcast_mod.F90 |   836 +
 .../extras/ifsaux/module/mpl_buffer_method_mod.F90 |   137 +
 odb/src/extras/ifsaux/module/mpl_close_mod.F90     |   107 +
 .../extras/ifsaux/module/mpl_comm_create_mod.F90   |    59 +
 odb/src/extras/ifsaux/module/mpl_data_module.F90   |    71 +
 odb/src/extras/ifsaux/module/mpl_end_mod.F90       |   112 +
 odb/src/extras/ifsaux/module/mpl_gatherv_mod.F90   |   495 +
 odb/src/extras/ifsaux/module/mpl_groups.F90        |   138 +
 odb/src/extras/ifsaux/module/mpl_init_mod.F90      |   347 +
 odb/src/extras/ifsaux/module/mpl_ioinit_mod.F90    |   128 +
 .../extras/ifsaux/module/mpl_locomm_create_mod.F90 |    85 +
 odb/src/extras/ifsaux/module/mpl_message_mod.F90   |   100 +
 odb/src/extras/ifsaux/module/mpl_module.F90        |    44 +
 odb/src/extras/ifsaux/module/mpl_mpif.F90          |     3 +
 odb/src/extras/ifsaux/module/mpl_mygatherv_mod.F90 |    41 +
 odb/src/extras/ifsaux/module/mpl_myrank_mod.F90    |    80 +
 odb/src/extras/ifsaux/module/mpl_nproc_mod.F90     |    52 +
 odb/src/extras/ifsaux/module/mpl_open_mod.F90      |   128 +
 odb/src/extras/ifsaux/module/mpl_probe_mod.F90     |   133 +
 odb/src/extras/ifsaux/module/mpl_read_mod.F90      |   319 +
 odb/src/extras/ifsaux/module/mpl_recv_mod.F90      |   993 +
 odb/src/extras/ifsaux/module/mpl_scatterv_mod.F90  |   297 +
 odb/src/extras/ifsaux/module/mpl_send_mod.F90      |   866 +
 .../extras/ifsaux/module/mpl_setdflt_comm_mod.F90  |    74 +
 .../extras/ifsaux/module/mpl_tour_table_mod.F90    |    50 +
 odb/src/extras/ifsaux/module/mpl_wait_mod.F90      |   494 +
 odb/src/extras/ifsaux/module/mpl_write_mod.F90     |   321 +
 odb/src/extras/ifsaux/module/oml_mod.F90           |   297 +
 odb/src/extras/ifsaux/module/parkind1.F90          |    39 +
 odb/src/extras/ifsaux/module/parkind2.F90          |    22 +
 odb/src/extras/ifsaux/module/sdl_mod.F90           |   134 +
 odb/src/extras/ifsaux/module/strhandler_mod.F90    |   212 +
 odb/src/extras/ifsaux/module/yomabrt.F90           |    10 +
 odb/src/extras/ifsaux/module/yomerrtrap.F90        |    15 +
 odb/src/extras/ifsaux/module/yomgstats.F90         |   123 +
 odb/src/extras/ifsaux/module/yomhook.F90           |   106 +
 odb/src/extras/ifsaux/module/yomhookstack.F90      |    18 +
 odb/src/extras/ifsaux/module/yomlun_ifsaux.F90     |    20 +
 odb/src/extras/ifsaux/module/yommpi.F90            |    19 +
 odb/src/extras/ifsaux/parallel/cmpl_binding.F90    |   129 +
 odb/src/extras/ifsaux/parallel/coml_binding.F90    |   111 +
 odb/src/extras/ifsaux/support/abor1.F90            |    55 +
 odb/src/extras/ifsaux/support/cargs.c              |   256 +
 odb/src/extras/ifsaux/support/cdrhookinit.F90      |    15 +
 odb/src/extras/ifsaux/support/clock.F              |    26 +
 odb/src/extras/ifsaux/support/convin.F90           |     7 +
 odb/src/extras/ifsaux/support/convout.F90          |     7 +
 odb/src/extras/ifsaux/support/cptime.F             |    40 +
 odb/src/extras/ifsaux/support/crc.c                |   171 +
 odb/src/extras/ifsaux/support/dr_hook_procinfo.F90 |     8 +
 odb/src/extras/ifsaux/support/dr_hook_prt.F90      |    13 +
 odb/src/extras/ifsaux/support/dr_hook_util.F90     |   171 +
 .../extras/ifsaux/support/dr_hook_util_multi.F90   |    33 +
 odb/src/extras/ifsaux/support/drhook.c             |  4201 ++
 odb/src/extras/ifsaux/support/endian.c             |   116 +
 odb/src/extras/ifsaux/support/env.c                |   249 +
 odb/src/extras/ifsaux/support/gstats.F90           |   397 +
 odb/src/extras/ifsaux/support/mpe_locking.c        |    27 +
 odb/src/extras/ifsaux/support/my_sync.c            |     8 +
 odb/src/extras/ifsaux/support/timef.F              |    61 +
 odb/src/extras/ifsaux/support/user_clock.F90       |    76 +
 odb/src/extras/ifsaux/utilities/addrdiff.c         |    15 +
 odb/src/extras/ifsaux/utilities/countingsort.c     |   366 +
 odb/src/extras/ifsaux/utilities/ecqsort.c          |   509 +
 odb/src/extras/ifsaux/utilities/fnecsx.c           |   388 +
 odb/src/extras/ifsaux/utilities/gentrbk.F90        |    41 +
 .../extras/ifsaux/utilities/get_max_threads.F90    |     8 +
 .../extras/ifsaux/utilities/get_num_threads.F90    |     8 +
 odb/src/extras/ifsaux/utilities/get_thread_id.F90  |     8 +
 odb/src/extras/ifsaux/utilities/getcurheap.c       |   617 +
 odb/src/extras/ifsaux/utilities/getheapstat.F90    |    85 +
 odb/src/extras/ifsaux/utilities/gethwm.c           |   108 +
 odb/src/extras/ifsaux/utilities/getmemstat.F90     |    60 +
 odb/src/extras/ifsaux/utilities/getmemvals.F90     |    35 +
 odb/src/extras/ifsaux/utilities/getpag.c           |    36 +
 odb/src/extras/ifsaux/utilities/getrss.c           |    83 +
 odb/src/extras/ifsaux/utilities/getstackusage.c    |     5 +
 odb/src/extras/ifsaux/utilities/getstatm.c         |    35 +
 odb/src/extras/ifsaux/utilities/getstk.c           |   102 +
 odb/src/extras/ifsaux/utilities/gnomesort.c        |   175 +
 odb/src/extras/ifsaux/utilities/iusrcl.F           |    83 +
 odb/src/extras/ifsaux/utilities/jsort.F            |    84 +
 odb/src/extras/ifsaux/utilities/linuxtrbk.c        |   295 +
 odb/src/extras/ifsaux/utilities/rsort32.c          |   459 +
 odb/src/extras/ifsaux/utilities/rsort64.c          |   248 +
 odb/src/extras/mpi_serial/CMakeLists.txt           |    64 +
 odb/src/extras/mpi_serial/mpi_abort.F              |     6 +
 odb/src/extras/mpi_serial/mpi_allgatherv.F         |     3 +
 odb/src/extras/mpi_serial/mpi_allreduce.F          |     3 +
 odb/src/extras/mpi_serial/mpi_alltoallv.F          |     4 +
 odb/src/extras/mpi_serial/mpi_barrier.F            |     3 +
 odb/src/extras/mpi_serial/mpi_bcast.F              |     3 +
 odb/src/extras/mpi_serial/mpi_bsend.F              |     4 +
 odb/src/extras/mpi_serial/mpi_buffer_attach.F      |     4 +
 odb/src/extras/mpi_serial/mpi_buffer_detach.F      |     3 +
 odb/src/extras/mpi_serial/mpi_cart_coords.F        |     4 +
 odb/src/extras/mpi_serial/mpi_cart_create.F        |     4 +
 odb/src/extras/mpi_serial/mpi_cart_rank.F          |     4 +
 odb/src/extras/mpi_serial/mpi_cart_sub.F           |     4 +
 odb/src/extras/mpi_serial/mpi_comm_create.F        |     6 +
 odb/src/extras/mpi_serial/mpi_comm_group.F         |     5 +
 odb/src/extras/mpi_serial/mpi_comm_rank.F          |     5 +
 odb/src/extras/mpi_serial/mpi_comm_size.F          |     5 +
 odb/src/extras/mpi_serial/mpi_comm_split.F         |     4 +
 odb/src/extras/mpi_serial/mpi_end.F                |     4 +
 odb/src/extras/mpi_serial/mpi_error_string.F       |     4 +
 odb/src/extras/mpi_serial/mpi_finalize.F           |     4 +
 odb/src/extras/mpi_serial/mpi_finalized.F          |     6 +
 odb/src/extras/mpi_serial/mpi_gather.F             |     3 +
 odb/src/extras/mpi_serial/mpi_gatherv.F            |     3 +
 odb/src/extras/mpi_serial/mpi_get_count.F          |     4 +
 odb/src/extras/mpi_serial/mpi_group_incl.F         |     5 +
 odb/src/extras/mpi_serial/mpi_ibsend.F             |     4 +
 odb/src/extras/mpi_serial/mpi_init.F               |     4 +
 odb/src/extras/mpi_serial/mpi_initialized.F        |    34 +
 odb/src/extras/mpi_serial/mpi_iprobe.F             |     4 +
 odb/src/extras/mpi_serial/mpi_irecv.F              |     4 +
 odb/src/extras/mpi_serial/mpi_isend.F              |     4 +
 odb/src/extras/mpi_serial/mpi_probe.F              |     4 +
 odb/src/extras/mpi_serial/mpi_recv.F               |     4 +
 odb/src/extras/mpi_serial/mpi_scatterv.F           |     4 +
 odb/src/extras/mpi_serial/mpi_send.F               |     4 +
 odb/src/extras/mpi_serial/mpi_ssend.F              |     4 +
 odb/src/extras/mpi_serial/mpi_wait.F               |     3 +
 odb/src/extras/mpi_serial/mpi_waitall.F            |     4 +
 odb/src/extras/mpi_serial/mpif.h                   |   221 +
 odb/src/extras/mpi_serial/mpif.h.necsx.BoM         |   511 +
 odb/src/extras/mpi_serial/mpif.h.necsx5.CSCS       |   512 +
 odb/src/extras/mpi_serial/tracecalls.c             |    20 +
 odb/src/extras/mpi_serial/vpp_abort.F              |     3 +
 odb/src/extras/mpi_serial/vpp_barrier.F            |     3 +
 odb/src/extras/mpi_serial/vpp_sempost.c            |     3 +
 odb/src/extras/mpi_serial/vpp_semwait.c            |     4 +
 odb/src/include/CMakeLists.txt                     |    65 +
 odb/src/include/alloc.h                            |   273 +
 odb/src/include/bits.h                             |    95 +
 odb/src/include/cdrhook.h                          |    51 +
 odb/src/include/cma_read.h                         |   177 +
 odb/src/include/cma_seek.h                         |   103 +
 odb/src/include/cma_write.h                        |   120 +
 odb/src/include/cmaio.h                            |   295 +
 odb/src/include/codb.h                             |   549 +
 odb/src/include/codb_netcdf.h                      |   126 +
 odb/src/include/dca.h                              |   140 +
 odb/src/include/defs.h                             |   654 +
 odb/src/include/ecstdlib.h                         |    11 +
 odb/src/include/evaluate.h                         |   161 +
 odb/src/include/fodb.h                             |  1388 +
 odb/src/include/fodbmp.h                           |   272 +
 odb/src/include/fodbmp1.h                          |   241 +
 odb/src/include/fodbmp2.h                          |   172 +
 odb/src/include/fodbutil.h                         |   809 +
 odb/src/include/fortint.h                          |    25 +
 odb/src/include/funcs.h                            |   715 +
 odb/src/include/history.h                          |    18 +
 odb/src/include/idx.h                              |   234 +
 odb/src/include/info.h                             |   292 +
 odb/src/include/ioassign.h                         |    62 +
 odb/src/include/iostuff.h                          |   177 +
 odb/src/include/lzw.h                              |   383 +
 odb/src/include/magicwords.h                       |    88 +
 odb/src/include/memmap.h                           |    55 +
 odb/src/include/mr2d_hdr.h                         |   115 +
 odb/src/include/mysql.h                            |     6 +
 odb/src/include/newio.h                            |    66 +
 odb/src/include/node.h                             |    19 +
 odb/src/include/odb.h                              |  2169 ++
 odb/src/include/odb_ioprof.h                       |    16 +
 odb/src/include/odb_macros.h                       |  1145 +
 odb/src/include/odbcrc.h                           |    24 +
 odb/src/include/odbcs.h                            |   151 +
 odb/src/include/odbcsdefs.h                        |    20 +
 odb/src/include/odbcstags.h                        |    37 +
 odb/src/include/odbdump.h                          |    37 +
 odb/src/include/odbi.h                             |   207 +
 odb/src/include/odbi_cs.h                          |   132 +
 odb/src/include/odbi_direct.h                      |   132 +
 odb/src/include/odbi_struct.h                      |    85 +
 odb/src/include/odbmd5.h                           |    26 +
 odb/src/include/pcma.h                             |   426 +
 odb/src/include/pcma_extern.h                      |   194 +
 odb/src/include/privpub.h                          |   636 +
 odb/src/include/qtar.h                             |    19 +
 odb/src/include/regcache.h                         |    68 +
 odb/src/include/result.h                           |   134 +
 odb/src/include/setodbcs.h                         |    37 +
 odb/src/include/static.h                           |    96 +
 odb/src/include/swapbytes.h                        |    52 +
 odb/src/include/symtab.h                           |    28 +
 odb/src/include/vparam.h                           |    12 +
 odb/src/interface/append_num.h                     |    11 +
 odb/src/interface/apply_poolmasking.h              |    13 +
 odb/src/interface/bsslzr_odb.h                     |     8 +
 odb/src/interface/ckeysort.h                       |    16 +
 odb/src/interface/create_iomap.h                   |    12 +
 odb/src/interface/create_statid.h                  |     8 +
 odb/src/interface/fodb_checkviewreg.h              |    10 +
 odb/src/interface/fwrite_iomap.h                   |     8 +
 odb/src/interface/gauaw_odb.h                      |     7 +
 odb/src/interface/iolockdb.h                       |     5 +
 odb/src/interface/lnkdb.h                          |     7 +
 odb/src/interface/lnkdb2.h                         |    10 +
 odb/src/interface/msgpass_loaddata.h               |     8 +
 odb/src/interface/msgpass_loadobs.h                |     8 +
 odb/src/interface/msgpass_storedata.h              |     8 +
 odb/src/interface/msgpass_storeobs.h               |     8 +
 odb/src/interface/rlnkdb.h                         |     9 +
 odb/src/interface/rlnkdb2.h                        |    12 +
 odb/src/interface/uniquenumdb.h                    |    11 +
 odb/src/lib/CMakeLists.txt                         |    83 +
 odb/src/lib/Codb_set_entrypoint.c                  |     4 +
 odb/src/lib/Ctxprint.F90                           |     9 +
 odb/src/lib/Dummies.c                              |   385 +
 odb/src/lib/Dummyprofile_newio.c                   |    20 +
 odb/src/lib/ae_dump.c                              |   188 +
 odb/src/lib/aggr.c                                 |  1232 +
 odb/src/lib/alist.c                                |    60 +
 odb/src/lib/append_num.F90                         |    29 +
 odb/src/lib/apply_poolmasking.F90                  |   330 +
 odb/src/lib/bsslzr_odb.F90                         |    97 +
 odb/src/lib/ckeysort.F90                           |    49 +
 odb/src/lib/cmdbkeys.c                             |   748 +
 odb/src/lib/codb.c                                 |  3239 ++
 odb/src/lib/codb_distribute.F90                    |    54 +
 odb/src/lib/codb_truename.c                        |    36 +
 odb/src/lib/cread_iomap.c                          |   127 +
 odb/src/lib/create_iomap.F90                       |   110 +
 odb/src/lib/create_statid.F90                      |    13 +
 odb/src/lib/ctransfer.c                            |    25 +
 odb/src/lib/ctx.c                                  |   295 +
 odb/src/lib/datastream.F90                         |    60 +
 odb/src/lib/dynlink.c                              |  1019 +
 odb/src/lib/eq_regions.c                           |  1701 +
 odb/src/lib/errtrap.c                              |   441 +
 odb/src/lib/evaluate.c                             |  1451 +
 odb/src/lib/fodb_checkviewreg.F90                  |    33 +
 odb/src/lib/fodb_propagate_env.F90                 |   124 +
 odb/src/lib/forfunc.c                              |   334 +
 odb/src/lib/funcs.c                                |   482 +
 odb/src/lib/fwrite_iomap.F90                       |   168 +
 odb/src/lib/gauaw_odb.F90                          |   141 +
 odb/src/lib/hashing.c                              |   359 +
 odb/src/lib/infile.c                               |    68 +
 odb/src/lib/init_region.c                          |    40 +
 odb/src/lib/inside.c                               |  1125 +
 odb/src/lib/iolockdb.F90                           |    11 +
 odb/src/lib/lnkdb.F90                              |    41 +
 odb/src/lib/lnkdb2.F90                             |    33 +
 odb/src/lib/msgpass_loaddata.F90                   |   757 +
 odb/src/lib/msgpass_loadobs.F90                    |   418 +
 odb/src/lib/msgpass_storedata.F90                  |   769 +
 odb/src/lib/msgpass_storeobs.F90                   |   464 +
 odb/src/lib/odb_array_dump.F90                     |   115 +
 odb/src/lib/orlist.c                               |   324 +
 odb/src/lib/peinfo.c                               |   152 +
 odb/src/lib/poolmasking.c                          |   515 +
 odb/src/lib/poolreg.c                              |   113 +
 odb/src/lib/prt.c                                  |   473 +
 odb/src/lib/random_odb.c                           |    57 +
 odb/src/lib/rgg_regions.c                          |   258 +
 odb/src/lib/rlnkdb.F90                             |    42 +
 odb/src/lib/rlnkdb2.F90                            |    33 +
 odb/src/lib/rot.c                                  |   184 +
 odb/src/lib/rsort32_odb.c                          |   344 +
 odb/src/lib/savelist.c                             |   115 +
 odb/src/lib/setup_sort.c                           |   133 +
 odb/src/lib/solar.c                                |   163 +
 odb/src/lib/stack.c                                |   114 +
 odb/src/lib/static.c                               |   182 +
 odb/src/lib/symtab.c                               |   245 +
 odb/src/lib/tracing.c                              |   532 +
 odb/src/lib/twindow.c                              |   433 +
 odb/src/lib/uniquenumdb.F90                        |    49 +
 odb/src/lib/var.c                                  |   462 +
 odb/src/lib/vecloops.c                             |   602 +
 odb/src/lib/version.c                              |    94 +
 odb/src/lib/wildcard.c                             |   213 +
 odb/src/lib/write_ddl.c                            |   164 +
 odb/src/module/.odb_module.F90.un~                 |   Bin 0 -> 1969 bytes
 odb/src/module/CMakeLists.txt                      |    21 +
 odb/src/module/odb.F90                             |  2338 ++
 odb/src/module/odb_module.F90                      |    22 +
 odb/src/module/odb_module8.F90                     |  4484 +++
 odb/src/module/odbgetput.F90                       |   345 +
 odb/src/module/odbio_msgpass.F90                   |  1395 +
 odb/src/module/odbiomap.F90                        |   106 +
 odb/src/module/odbmap_reportype.F90                |   458 +
 odb/src/module/odbmp.F90                           |   380 +
 odb/src/module/odbnetcdf.F90                       |   500 +
 odb/src/module/odbprint.F90                        |  1014 +
 odb/src/module/odbshared.F90                       |   678 +
 odb/src/module/odbsort.F90                         |     4 +
 odb/src/module/odbstat.F90                         |   127 +
 odb/src/module/odbutil.F90                         |   842 +
 odb/src/module/stackdb.F90                         |   119 +
 odb/src/module/str.F90                             |     4 +
 odb/src/p4sync                                     |   198 +
 odb/src/scripts/.odb_deprecated.sh                 |    25 +
 odb/src/scripts/.odb_serial_wrapper.sh.in          |    19 +
 odb/src/scripts/CMakeLists.txt                     |    88 +
 odb/src/scripts/DEPRECATED                         |    14 +
 odb/src/scripts/askodb                             |   938 +
 odb/src/scripts/check_links                        |    84 +
 odb/src/scripts/create_index                       |   141 +
 odb/src/scripts/create_ioassign                    |   351 +
 odb/src/scripts/create_odbglue                     |    92 +
 odb/src/scripts/create_static_stubb                |   165 +
 odb/src/scripts/dcafix                             |    78 +
 odb/src/scripts/dcafix.pl                          |    96 +
 odb/src/scripts/dcagen                             |   453 +
 odb/src/scripts/dcaquick                           |   160 +
 odb/src/scripts/dd2ddl                             |    70 +
 odb/src/scripts/ddl2flags.pl                       |    90 +
 odb/src/scripts/latlon_rad                         |    47 +
 odb/src/scripts/latlonrad                          |     1 +
 odb/src/scripts/makegp.ksh                         |   259 +
 odb/src/scripts/newodb                             |    53 +
 odb/src/scripts/odb1to4                            |   170 +
 odb/src/scripts/odb2netcdf                         |   302 +
 odb/src/scripts/odb4to1                            |   127 +
 odb/src/scripts/odb_1to4                           |     1 +
 odb/src/scripts/odb_4to1                           |     1 +
 odb/src/scripts/odb_cat                            |     1 +
 odb/src/scripts/odb_compress                       |     1 +
 odb/src/scripts/odb_count                          |     1 +
 odb/src/scripts/odb_diff                           |     1 +
 odb/src/scripts/odb_dump                           |     1 +
 odb/src/scripts/odb_dup                            |     1 +
 odb/src/scripts/odb_gnuplot                        |     1 +
 odb/src/scripts/odb_header                         |     1 +
 odb/src/scripts/odb_less                           |     1 +
 odb/src/scripts/odb_ls                             |     1 +
 odb/src/scripts/odb_merge                          |     1 +
 odb/src/scripts/odb_more                           |     1 +
 odb/src/scripts/odb_prune                          |     1 +
 odb/src/scripts/odb_qsub                           |     1 +
 odb/src/scripts/odb_set                            |     1 +
 odb/src/scripts/odb_split                          |     1 +
 odb/src/scripts/odb_tar                            |     1 +
 odb/src/scripts/odb_to_request                     |     1 +
 odb/src/scripts/odb_viewer                         |     1 +
 odb/src/scripts/odb_xyplot                         |     1 +
 odb/src/scripts/odbc++                             |     1 +
 odb/src/scripts/odbcat                             |     1 +
 odb/src/scripts/odbcc                              |   166 +
 odb/src/scripts/odbclean                           |    69 +
 odb/src/scripts/odbcomp                            |   326 +
 odb/src/scripts/odbcompress                        |   317 +
 odb/src/scripts/odbcount                           |     1 +
 odb/src/scripts/odbdiff                            |   339 +
 odb/src/scripts/odbdump                            |     1 +
 odb/src/scripts/odbdump.ksh                        |   122 +
 odb/src/scripts/odbdup                             |   431 +
 odb/src/scripts/odbf90                             |   124 +
 odb/src/scripts/odbf90mp                           |     1 +
 odb/src/scripts/odbgnuplot                         |   354 +
 odb/src/scripts/odbgunzip                          |     1 +
 odb/src/scripts/odbgzip                            |   119 +
 odb/src/scripts/odbheader                          |     1 +
 odb/src/scripts/odbi_proxy                         |   108 +
 odb/src/scripts/odbi_show_server                   |    82 +
 odb/src/scripts/odbi_start_server                  |    89 +
 odb/src/scripts/odbi_stop_server                   |   104 +
 odb/src/scripts/odbless                            |   321 +
 odb/src/scripts/odblink                            |    74 +
 odb/src/scripts/odbls                              |   322 +
 odb/src/scripts/odbmerge                           |     1 +
 odb/src/scripts/odbmore                            |     1 +
 odb/src/scripts/odbprune                           |   181 +
 odb/src/scripts/odbqsub                            |   142 +
 odb/src/scripts/odbset                             |     1 +
 odb/src/scripts/odbsql                             |   972 +
 odb/src/scripts/odbsqlmp.pl                        |   236 +
 odb/src/scripts/odbtar                             |   224 +
 odb/src/scripts/odbviewer                          |   900 +
 odb/src/scripts/odbvlink                           |   110 +
 odb/src/scripts/odbxyplot                          |   185 +
 odb/src/scripts/run_viewer                         |   127 +
 odb/src/scripts/shp2txt.pl                         |   195 +
 odb/src/scripts/test_arch                          |    98 +
 odb/src/scripts/use_odb.csh.in                     |    38 +
 odb/src/scripts/use_odb.sh.in                      |    39 +
 odb/src/scripts/where_fiddle.pl                    |    32 +
 odb/src/tools/CMakeLists.txt                       |    68 +
 odb/src/tools/Create_index.F90                     |   208 +
 odb/src/tools/DEPRECATED                           |     1 +
 odb/src/tools/Fodbsql.F90                          |    12 +
 odb/src/tools/Fscheduler.F90                       |   294 +
 odb/src/tools/Odbcompress.F90                      |   408 +
 odb/src/tools/Odbdiff.F90                          |   647 +
 odb/src/tools/Odbgnuplot.F90                       |   345 +
 odb/src/tools/Odbless.F90                          |   343 +
 odb/src/tools/b4.c                                 |   719 +
 odb/src/tools/dcagen.c                             |  1302 +
 odb/src/tools/dd2ddl.c                             |   394 +
 odb/src/tools/hcat.c                               |   722 +
 odb/src/tools/ioassign.c                           |   510 +
 odb/src/tools/mr2d_create.c                        |   282 +
 odb/src/tools/mr2d_split.c                         |   272 +
 odb/src/tools/mysort.c                             |   469 +
 odb/src/tools/odb2rgg.c                            |   306 +
 odb/src/tools/odbcksum.c                           |    75 +
 odb/src/tools/odbdump_main.c                       |   403 +
 odb/src/tools/odbfiletime.c                        |    53 +
 odb/src/tools/odbi_client_main.c                   |     7 +
 odb/src/tools/odbi_direct_main.c                   |   586 +
 odb/src/tools/odbi_host.c                          |    48 +
 odb/src/tools/odbi_server_main.c                   |   235 +
 odb/src/tools/odbmd5sum.c                          |    45 +
 odb/src/tools/odbversion.c                         |    39 +
 odb/src/tools/pcma_main.c                          |   375 +
 odb/src/tools/qtar.c                               |    70 +
 odb/src/tools/scheduler.c                          |   110 +
 odb/src/tools/typebits.c                           |   110 +
 odb/src/tools/world2odb.c                          |   571 +
 odb/tests/CMakeLists.txt                           |    55 +
 odb/tests/DB.ddl                                   |    23 +
 odb/tests/createdb.F90                             |    14 +
 odb/tests/createdb.out                             |     2 +
 odb/tests/createdb.sh                              |    36 +
 odb/tests/populate.F90                             |    82 +
 odb/tests/populate.out                             |     6 +
 odb/tests/populate.sh                              |    17 +
 odb/tests/querydata.F90                            |    47 +
 odb/tests/querydata1.sql                           |     1 +
 odb/tests/querydata2.sql                           |     1 +
 odb_api/CMakeLists.txt                             |    18 +-
 odb_api/VERSION.cmake                              |     2 +-
 odb_api/project_summary.cmake                      |     4 -
 odb_api/src/CMakeLists.txt                         |     2 -
 odb_api/src/ecml/misc/DynamicParametrisation.cc    |    11 +
 odb_api/src/ecml/misc/DynamicParametrisation.h     |     9 +
 .../src/fortran/legacy_fortran_api_examples.f90    |     2 +-
 odb_api/src/odb_api/CMakeLists.txt                 |     2 +
 odb_api/src/odb_api/LibOdbApi.cc                   |    50 +
 odb_api/src/odb_api/LibOdbApi.h                    |    44 +
 odb_api/src/odb_api/ODBAPIVersion.cc               |     1 +
 odb_api/src/odb_api/SQLInteractiveSession.h        |     6 +-
 odb_api/src/odb_api/SQLParser.cc                   |     7 +-
 odb_api/src/odb_api/migrator/CMakeLists.txt        |    84 -
 odb_api/src/odb_api/migrator/FakeODBIterator.cc    |   160 -
 odb_api/src/odb_api/migrator/FakeODBIterator.h     |    96 -
 odb_api/src/odb_api/migrator/ImportODBTool.cc      |   207 -
 odb_api/src/odb_api/migrator/ImportODBTool.h       |    66 -
 odb_api/src/odb_api/migrator/MigratorTool.cc       |   144 -
 odb_api/src/odb_api/migrator/ODB2ODATool.cc        |   139 -
 odb_api/src/odb_api/migrator/ODBIterator.cc        |   250 -
 odb_api/src/odb_api/migrator/ODBIterator.h         |    86 -
 odb_api/src/odb_api/migrator/OldODBReader.h        |    25 -
 odb_api/src/odb_api/migrator/ReptypeGenIterator.cc |   234 -
 odb_api/src/odb_api/migrator/migrator_api.cc       |    38 -
 odb_api/src/odb_api/migrator/odb2oda.cc            |    66 -
 odb_api/src/odb_api/odb2_to_odb1/CMakeLists.txt    |    19 -
 odb_api/src/odb_api/odb2_to_odb1/odb_wrapper.F90   |   753 -
 odb_api/src/odb_api/odb2_to_odb1/odbi.F90          |   286 -
 odb_api/src/odb_api/tools/CMakeLists.txt           |     2 -
 odb_api/src/odb_api/tools/ODA2RequestTool.cc       |     3 +-
 odb_api/src/odb_api_config.h.in                    |     2 +
 odb_api/tests/CMakeLists.txt                       |    57 +-
 .../dhshome/data/partitions_info_test_stage.txt    |     0
 .../data/partitions_info_test_stage.txt.files      |     0
 odb_tools/.gitignore                               |     8 +
 odb_tools/CMakeLists.txt                           |    93 +
 odb_tools/VERSION.cmake                            |     1 +
 odb_tools/bamboo/CLANG-env.sh                      |    10 +
 odb_tools/bamboo/INTEL-env.sh                      |    11 +
 odb_tools/bamboo/env.sh                            |     4 +
 odb_tools/bamboo/flags.cmake                       |     1 +
 odb_tools/src/CMakeLists.txt                       |    16 +
 .../src/odb_api => odb_tools/src}/migrator/2oda    |     0
 odb_tools/src/migrator/CMakeLists.txt              |   112 +
 odb_tools/src/migrator/FakeODBIterator.cc          |   160 +
 odb_tools/src/migrator/FakeODBIterator.h           |    96 +
 odb_tools/src/migrator/ImportODBTool.cc            |   207 +
 odb_tools/src/migrator/ImportODBTool.h             |    66 +
 .../odb_api => odb_tools/src}/migrator/Makefile    |     0
 .../src}/migrator/Makefile.old                     |     0
 .../src}/migrator/MigrateHandler.cc                |     0
 .../src}/migrator/MigrateHandler.h                 |     0
 odb_tools/src/migrator/MigratorTool.cc             |   144 +
 .../src}/migrator/MigratorTool.h                   |     0
 odb_tools/src/migrator/ODB2ODATool.cc              |   139 +
 .../src}/migrator/ODB2ODATool.h                    |     0
 odb_tools/src/migrator/ODBIterator.cc              |   253 +
 odb_tools/src/migrator/ODBIterator.h               |    97 +
 .../src}/migrator/ODBMigratorModule.cc             |     0
 .../src}/migrator/ODBMigratorModule.h              |     0
 .../src}/migrator/Odb2_to_odb1_era.f90             |     0
 odb_tools/src/migrator/OldODBReader.h              |    25 +
 odb_tools/src/migrator/ReptypeGenIterator.cc       |   234 +
 .../src}/migrator/ReptypeGenIterator.h             |     0
 .../src}/migrator/TSQLReader.cc                    |     0
 .../src}/migrator/TSQLReader.h                     |     0
 .../src/odb_api => odb_tools/src}/migrator/all     |     0
 .../odb_api => odb_tools/src}/migrator/diurnal.f90 |     0
 odb_tools/src/migrator/migrator_api.cc             |    38 +
 .../src}/migrator/migrator_api.h                   |     0
 .../odb_api => odb_tools/src}/migrator/odb1.f90    |     0
 .../odb_api => odb_tools/src}/migrator/odb2.f90    |     0
 .../src}/migrator/odb2_flag_definitions.f90        |     0
 odb_tools/src/migrator/odb2oda.cc                  |    66 +
 .../odb_api => odb_tools/src}/migrator/odbdump.h   |     0
 .../odb_api => odb_tools/src}/migrator/pyodbdump.i |     0
 .../src}/migrator/pyodbdump_example.py             |     0
 .../src}/migrator/solar_elevation.f90              |     0
 .../src}/migrator/solar_elevation.sc               |     0
 .../src}/migrator/test_migrator.ecml               |     0
 odb_tools/src/odb2_to_odb1/CMakeLists.txt          |    27 +
 .../src}/odb2_to_odb1/Odb2Odb1.cc                  |     0
 .../src}/odb2_to_odb1/Odb2Odb1.h                   |     0
 .../src}/odb2_to_odb1/Odb2Odb1Main.cc              |     0
 .../src}/odb2_to_odb1/mpi_wrapper.F90              |     0
 .../odb_api => odb_tools/src}/odb2_to_odb1/mpif.h  |     0
 odb_tools/src/odb2_to_odb1/odb_wrapper.F90         |   753 +
 odb_tools/src/odb2_to_odb1/odbi.F90                |   286 +
 odb_tools/src/tests/CMakeLists.txt                 |    74 +
 odb_tools/src/tests/test_import_odb.sh             |    41 +
 odb_tools/src/tests/test_import_odb_dispatching.sh |    40 +
 .../src}/tests/test_odb2_to_odb1.sh                |     0
 share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake     |    87 +
 share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake      |    87 +
 share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake    |    87 +
 3194 files changed, 228534 insertions(+), 28160 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08014df..4083555 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,9 +6,15 @@ include( ecbuild_bundle )
 project( odb_api_bundle C CXX )
 
 ecbuild_bundle_initialize()
-ecbuild_bundle( PROJECT ecbuild  STASH "ecsdk/ecbuild"    BRANCH  2.7.0 )
-ecbuild_bundle( PROJECT eckit    STASH "ecsdk/eckit"      BRANCH  0.16.3 )
-ecbuild_bundle( PROJECT metkit   STASH "ecsdk/metkit"     BRANCH  0.5.2 )
-ecbuild_bundle( PROJECT odb_api  STASH "odb/odb_api"      BRANCH  0.17.0 )
+ecbuild_bundle( PROJECT ecbuild        STASH "ecsdk/ecbuild"      TAG  2.7.1 )
+ecbuild_bundle( PROJECT eckit          STASH "ecsdk/eckit"        TAG  0.17.0 )
+ecbuild_bundle( PROJECT metkit         STASH "ecsdk/metkit"       TAG  0.6.0 )
+ecbuild_bundle( PROJECT odb_api        STASH "odb/odb_api"        TAG 0.17.1 )
+
+if( ENABLE_ODB )
+ecbuild_bundle( PROJECT odb            STASH "odb/odb"            TAG 1.0.6 )
+ecbuild_bundle( PROJECT odb_tools      STASH "odb/odb-tools"      TAG 0.17.1 )
+endif()
+
 ecbuild_bundle_finalize()
 
diff --git a/VERSION.cmake b/VERSION.cmake
index be758bf..26bfa3d 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -1 +1 @@
-set(${PROJECT_NAME}_VERSION_STR "0.17.0")
+set(${PROJECT_NAME}_VERSION_STR "0.17.1")
diff --git a/cmake/VERSION.cmake b/cmake/VERSION.cmake
index a95e4a9..af2b0d2 100644
--- a/cmake/VERSION.cmake
+++ b/cmake/VERSION.cmake
@@ -1,7 +1,7 @@
 set( ECBUILD_MAJOR_VERSION "2" )
 set( ECBUILD_MINOR_VERSION "7" )
-set( ECBUILD_PATCH_VERSION "0" )
+set( ECBUILD_PATCH_VERSION "1" )
 
-set( ECBUILD_VERSION_STR  "2.7.0" )
+set( ECBUILD_VERSION_STR  "2.7.1" )
 
 set( ECBUILD_MACRO_VERSION "${ECBUILD_VERSION_STR}" )
diff --git a/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake b/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
index 593b62f..fafcd23 100644
--- a/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
+++ b/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
@@ -44,7 +44,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -52,7 +52,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/cmake/ecbuild_add_persistent.cmake b/cmake/ecbuild_add_persistent.cmake
index e5a875b..40d7ad2 100644
--- a/cmake/ecbuild_add_persistent.cmake
+++ b/cmake/ecbuild_add_persistent.cmake
@@ -60,6 +60,8 @@ macro( ecbuild_add_persistent )
     ecbuild_critical("The call to ecbuild_add_persistent() doesn't specify the FILES.")
   endif()
 
+  ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${_PAR_FILES}" )
+
   foreach( file ${_PAR_FILES} )
 
     get_filename_component( _file_dir    ${file} PATH )
@@ -71,7 +73,7 @@ macro( ecbuild_add_persistent )
       set( file ${_file_dir}/${_file_we} )
     endif()
 
-    # ecbuild_debug_var(file)
+    ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${file}.b with namespace ${_PAR_NAMESPACE} from ${file}.h in ${CMAKE_CURRENT_BINARY_DIR}/${_file_dir}" )
 
     add_custom_command( OUTPUT  ${file}.b
                         COMMAND ${PERL_EXECUTABLE} ${sg_perl} ${CMAKE_CURRENT_SOURCE_DIR}/${file}.h
diff --git a/cmake/ecbuild_add_resources.cmake b/cmake/ecbuild_add_resources.cmake
index 2dfaa5e..51b1e68 100644
--- a/cmake/ecbuild_add_resources.cmake
+++ b/cmake/ecbuild_add_resources.cmake
@@ -51,6 +51,13 @@
 #   list of regular expressions to match files and directories to exclude when
 #   packaging
 #
+# Note
+# ----
+#
+# All file and directory names are also *partially matched*. To ensure that
+# only the exact file or directory name is matched at the end of the path add
+# a ``$`` at the end and quote the name.
+#
 ##############################################################################
 
 macro( ecbuild_add_resources )
diff --git a/cmake/ecbuild_check_c_source_return.cmake b/cmake/ecbuild_check_c_source_return.cmake
index 38d89f7..b92042b 100644
--- a/cmake/ecbuild_check_c_source_return.cmake
+++ b/cmake/ecbuild_check_c_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .c file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -95,12 +95,12 @@ macro( ecbuild_check_c_source_return SOURCE )
     
         # write the source file
     
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
@@ -114,6 +114,10 @@ macro( ecbuild_check_c_source_return SOURCE )
           set( ${_PAR_VAR}_EXITCODE 1 )
         endif()
     
+        ecbuild_debug_var( ${_PAR_VAR}_EXITCODE )
+        ecbuild_debug_var( ${_PAR_VAR}_COMPILED )
+        ecbuild_debug_var( compile_OUTPUT )
+        ecbuild_debug_var( run_OUTPUT )
         # if the return value was 0 then it worked
         if("${${_PAR_VAR}_EXITCODE}" EQUAL 0)
     
diff --git a/cmake/ecbuild_check_compiler.cmake b/cmake/ecbuild_check_compiler.cmake
index 197f0b5..dd09c0f 100644
--- a/cmake/ecbuild_check_compiler.cmake
+++ b/cmake/ecbuild_check_compiler.cmake
@@ -95,6 +95,10 @@ if( CMAKE_CXX_COMPILER_LOADED AND ENABLE_OS_TESTS )
     ecbuild_cache_check_cxx_source_compiles( "#include <sstream>\nint main() { std::stringstream s; }"
 	  EC_HAVE_CXX_SSTREAM )
 
+    # test c++ __int128
+    ecbuild_cache_check_cxx_source_compiles( "int main(){ __int128 i = 0; return 0;}\n"
+      EC_HAVE_CXX_INT_128 )
+
 endif()
 
 ############################################################################################
diff --git a/cmake/ecbuild_check_cxx11.cmake b/cmake/ecbuild_check_cxx11.cmake
index d2f9629..a7b551c 100644
--- a/cmake/ecbuild_check_cxx11.cmake
+++ b/cmake/ecbuild_check_cxx11.cmake
@@ -58,7 +58,7 @@ function( ecbuild_check_cxx11 )
   cxx11_find_all_features( ALL_FEATURES ) # list all available features to check
 
   # Save CXX flags
-  set( CXX_FLAGS_SNASHOT ${CMAKE_CXX_FLAGS} )
+  set( CXX_FLAGS_SNAPSHOT ${CMAKE_CXX_FLAGS} )
 
   # Add C++11 flags
   include( ${ECBUILD_MACROS_DIR}/ecbuild_get_cxx11_flags.cmake )
diff --git a/cmake/ecbuild_check_cxx_source_return.cmake b/cmake/ecbuild_check_cxx_source_return.cmake
index 7270540..5b4b478 100644
--- a/cmake/ecbuild_check_cxx_source_return.cmake
+++ b/cmake/ecbuild_check_cxx_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .cxx file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -96,12 +96,12 @@ macro( ecbuild_check_cxx_source_return SOURCE )
 
         # write the source file
 
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx" "${SOURCE}\n" )
 
         ecbuild_debug( "${_msg}" )
-        try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
+        ecbuild_try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
diff --git a/cmake/ecbuild_check_fortran_source_return.cmake b/cmake/ecbuild_check_fortran_source_return.cmake
index 92168b9..f8ccf05 100644
--- a/cmake/ecbuild_check_fortran_source_return.cmake
+++ b/cmake/ecbuild_check_fortran_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .f file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -98,7 +98,7 @@ macro( ecbuild_check_fortran_source_return SOURCE )
         file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
           ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
diff --git a/cmake/ecbuild_check_functions.cmake b/cmake/ecbuild_check_functions.cmake
index 59fbd3a..30d8013 100644
--- a/cmake/ecbuild_check_functions.cmake
+++ b/cmake/ecbuild_check_functions.cmake
@@ -122,6 +122,8 @@ if( ENABLE_OS_FUNCTIONS_TEST )
     ecbuild_cache_check_c_source_compiles( "#include <sys/types.h>\n#include <pwd.h>\nint main(){ struct passwd p; char line[1024]; int n = getpwnam_r(\"user\",&p,line,sizeof(line),0); }\n" EC_HAVE_GETPWNAM_R )
     # test for readdir_r
     ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; struct dirent **result; int i = readdir_r(dirp, entry, result); }\n" EC_HAVE_READDIR_R )
+    # test for d_type in dirent.h
+    ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; if(entry->d_type) { dirp = 0; } }\n" EC_HAVE_DIRENT_D_TYPE )
     # test for gethostbyname_r
     ecbuild_cache_check_c_source_compiles( "#include <netdb.h>\nint main(){ const char *name; struct hostent *ret; char *buf; struct hostent **result; size_t buflen; int *h_errnop; int i = gethostbyname_r(name,ret,buf,buflen,result,h_errnop); }\n" EC_HAVE_GETHOSTBYNAME_R )
 
diff --git a/cmake/ecbuild_check_os.cmake b/cmake/ecbuild_check_os.cmake
index d2af403..aaf2f79 100644
--- a/cmake/ecbuild_check_os.cmake
+++ b/cmake/ecbuild_check_os.cmake
@@ -44,6 +44,7 @@ if( ENABLE_OS_TYPES_TEST )
 
   set( EC_SIZEOF_PTR ${CMAKE_SIZEOF_VOID_P} )
   ecbuild_cache_var( EC_SIZEOF_PTR )
+
   ecbuild_cache_check_type_size( char           EC_SIZEOF_CHAR        )
   ecbuild_cache_check_type_size( short          EC_SIZEOF_SHORT       )
   ecbuild_cache_check_type_size( int            EC_SIZEOF_INT         )
diff --git a/cmake/ecbuild_config.h.in b/cmake/ecbuild_config.h.in
index a7d7d75..1774847 100644
--- a/cmake/ecbuild_config.h.in
+++ b/cmake/ecbuild_config.h.in
@@ -122,6 +122,7 @@
 #cmakedefine EC_HAVE_GETPWUID_R
 #cmakedefine EC_HAVE_GETPWNAM_R
 #cmakedefine EC_HAVE_READDIR_R
+#cmakedefine EC_HAVE_DIRENT_D_TYPE
 #cmakedefine EC_HAVE_GETHOSTBYNAME_R
 
 /* --- compiler __attribute__ support --- */
@@ -146,6 +147,7 @@
 
 #cmakedefine EC_HAVE_CXXABI_H
 #cmakedefine EC_HAVE_CXX_BOOL
+#cmakedefine EC_HAVE_CXX_INT_128
 
 #cmakedefine EC_HAVE_CXX_SSTREAM
 
diff --git a/cmake/ecbuild_find_fortranlibs.cmake b/cmake/ecbuild_find_fortranlibs.cmake
index 905d020..ac7cf25 100644
--- a/cmake/ecbuild_find_fortranlibs.cmake
+++ b/cmake/ecbuild_find_fortranlibs.cmake
@@ -30,6 +30,8 @@
 
 macro( ecbuild_find_fortranlibs )
 
+  ecbuild_deprecate( "ecbuild_find_fortranlibs is deprecated and will be removed in an upcoming ecBuild release" )
+
   # parse parameters
 
   set( options REQUIRED )
@@ -39,7 +41,7 @@ macro( ecbuild_find_fortranlibs )
   cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
 
   if(_PAR_UNPARSED_ARGUMENTS)
-    ecbuild_critical("Unknown keywords given to ecbuild_find_python(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
+    ecbuild_critical("Unknown keywords given to ecbuild_find_fortranlibs(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
   endif()
 
   if( NOT FORTRANLIBS_FOUND ) # don't repeat search
diff --git a/cmake/ecbuild_find_package.cmake b/cmake/ecbuild_find_package.cmake
index 71be044..b69741e 100644
--- a/cmake/ecbuild_find_package.cmake
+++ b/cmake/ecbuild_find_package.cmake
@@ -193,8 +193,8 @@ macro( ecbuild_find_package )
 
   # search user defined paths first
 
-  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR )
-    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
+  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR OR ${_PAR_NAME}_BINARY_DIR )
+    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}, ${_PAR_NAME}_BINARY_DIR=${${_PAR_NAME}_BINARY_DIR}")
 
     # 1) search using CONFIG mode -- try to locate a configuration file provided by the package (package-config.cmake)
 
@@ -203,7 +203,7 @@ macro( ecbuild_find_package )
       ecbuild_debug("ecbuild_find_package(${_PAR_NAME}):    using hints ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
       find_package( ${_PAR_NAME} ${_${pkgUPPER}_version} NO_MODULE ${_find_quiet}
         COMPONENTS ${_PAR_COMPONENTS}
-        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR}
+        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR} ${${_PAR_NAME}_BINARY_DIR}
         NO_DEFAULT_PATH )
     endif()
 
diff --git a/cmake/ecbuild_system.cmake b/cmake/ecbuild_system.cmake
index 16c0299..b3a6c6b 100644
--- a/cmake/ecbuild_system.cmake
+++ b/cmake/ecbuild_system.cmake
@@ -163,6 +163,7 @@ if( PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME )
     include( ecbuild_list_add_pattern )
     include( ecbuild_list_exclude_pattern )
 
+    include( ecbuild_try_run )
     include( ecbuild_check_c_source_return )
     include( ecbuild_check_cxx_source_return )
     include( ecbuild_check_cxx11 )
diff --git a/cmake/ecbuild_try_run.cmake b/cmake/ecbuild_try_run.cmake
new file mode 100644
index 0000000..854f1d1
--- /dev/null
+++ b/cmake/ecbuild_try_run.cmake
@@ -0,0 +1,200 @@
+# (C) Copyright 1996-2017 ECMWF.
+#
+# This software is licensed under the terms of the Apache Licence Version 2.0
+# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+# In applying this licence, ECMWF does not waive the privileges and immunities
+# granted to it by virtue of its status as an intergovernmental organisation
+# nor does it submit to any jurisdiction.
+
+##############################################################################
+#.rst:
+#
+# ecbuild_try_run
+# ===============
+#
+# Try compiling and then running some code. ::
+#
+#   ecbuild_try_run( <run_result_var> <compile_result_var>
+#                    <bindir> <srcfile>
+#                    [ CMAKE_FLAGS <flag> [ <flag> ... ] ]
+#                    [ COMPILE_DEFINITIONS <def> [ <def> ... ] ]
+#                    [ LINK_LIBRARIES <lib> [ <lib> ... ] ]
+#                    [ COMPILE_OUTPUT_VARIABLE <var> ]
+#                    [ RUN_OUTPUT_VARIABLE <var> ]
+#                    [ OUTPUT_VARIABLE <var> ]
+#                    [ ARGS <arg> [ <arg> ... ] ] )
+#
+# Try compiling a ``<srcfile>``.  Returns ``TRUE`` or ``FALSE`` for success
+# or failure in ``<compile_result_var>``.  If the compile succeeded, runs the
+# executable and returns its exit code in ``<run_result_var>``.  If the
+# executable was built, but failed to run, then ``<run_result_var>`` will be
+# set to ``FAILED_TO_RUN``.  See the CMake ``try_compile`` command for
+# information on how the test project is constructed to build the source file.
+#
+# Options
+# -------
+#
+# CMAKE_FLAGS : optional
+#   Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to
+#   the ``cmake`` command-line used to drive the test build.
+#
+#   The example in CMake's ``try_compile`` shows how values for variables
+#   ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES``
+#   are used.
+#
+# COMPILE_DEFINITIONS : optional
+#   Specify ``-Ddefinition`` arguments to pass to ``add_definitions``
+#   in the generated test project.
+#
+# COMPILE_OUTPUT_VARIABLE : optional
+#   Report the compile step build output in a given variable.
+#
+# LINK_LIBRARIES : optional
+#   Specify libraries to be linked in the generated project.
+#   The list of libraries may refer to system libraries and to
+#   Imported Targets from the calling project.
+#
+#   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
+#   given to the ``CMAKE_FLAGS`` option will be ignored.
+#
+# OUTPUT_VARIABLE : optional
+#   Report the compile build output and the output from running the executable
+#   in the given variable.  This option exists for legacy reasons.  Prefer
+#   ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead.
+#
+# RUN_OUTPUT_VARIABLE : optional
+#   Report the output from running the executable in a given variable.
+#
+# Other Behavior Settings
+# -----------------------
+#
+# Set the ``CMAKE_TRY_COMPILE_CONFIGURATION`` variable to choose
+# a build configuration.
+#
+# Behavior when Cross Compiling
+# -----------------------------
+#
+# When cross compiling, the executable compiled in the first step
+# usually cannot be run on the build host.  The ``try_run`` command checks
+# the ``CMAKE_CROSSCOMPILING`` variable to detect whether CMake is in
+# cross-compiling mode.  If that is the case, it will still try to compile
+# the executable, but it will not try to run the executable unless the
+# ``CMAKE_CROSSCOMPILING_EMULATOR`` variable is set.  Instead it will create
+# cache variables which must be filled by the user or by presetting them in
+# some CMake script file to the values the executable would have produced if
+# it had been run on its actual target platform. These cache entries are:
+#
+# ``<RUN_RESULT_VAR>``
+#   Exit code if the executable were to be run on the target platform.
+#
+# ``<RUN_RESULT_VAR>__TRYRUN_OUTPUT``
+#   Output from stdout and stderr if the executable were to be run on
+#   the target platform.  This is created only if the
+#   ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` option was used.
+#
+# In order to make cross compiling your project easier, use ``try_run``
+# only if really required.  If you use ``try_run``, use the
+# ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really
+# required.  Using them will require that when cross-compiling, the cache
+# variables will have to be set manually to the output of the executable.
+# You can also "guard" the calls to ``try_run`` with an ``if`` block checking
+# the ``CMAKE_CROSSCOMPILING`` variable and provide an easy-to-preset
+# alternative for this case.
+#
+##############################################################################
+
+# This is an API compatible version of try_run which ignores output on stderr
+
+if( CMAKE_VERSION VERSION_LESS 2.8.12 )
+
+ecbuild_deprecate( "ecbuild_try_run falls back to try_run on CMake < 2.8.12 (ECBUILD-341)" )
+
+macro( ecbuild_try_run )
+  try_run( ${ARGV} )
+endmacro()
+
+else()
+
+function( ecbuild_try_run RUN_RESULT_VAR COMPILE_RESULT_VAR BINDIR SRCFILE )
+
+  set( options )
+  set( single_value_args COMPILE_OUTPUT_VARIABLE RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE )
+  set( multi_value_args  CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES ARGS )
+
+  cmake_parse_arguments( _p "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
+
+  if( _p_UNPARSED_ARGUMENTS )
+    ecbuild_critical("Unknown keywords given to ecbuild_try_run(): \"${_p_UNPARSED_ARGUMENTS}\"")
+  endif()
+
+  # Build argument list for try_compile
+  foreach( _opt CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES  )
+    if( _p_${_opt} )
+      list( APPEND _opts ${_opt} "${_p_${_opt}}" )
+    endif()
+  endforeach()
+
+  ecbuild_debug( "ecbuild_try_run: Compiling ${SRCFILE} in ${BINDIR}" )
+  try_compile( _compile_res ${BINDIR} ${SRCFILE}
+               OUTPUT_VARIABLE _compile_out
+               COPY_FILE ${SRCFILE}.bin COPY_FILE_ERROR _compile_err
+               ${_opts} )
+
+  if( _compile_out )
+    ecbuild_debug( "ecbuild_try_run: compilation output"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_out}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+  if( _compile_err )
+    ecbuild_debug( "ecbuild_try_run: compilation errors"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_err}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+
+  # FIXME: how do we handle cross compilation mode? (CMAKE_CROSSCOMPILING)
+
+  if( _compile_res )
+
+    ecbuild_debug( "ecbuild_try_run: Running ${SRCFILE}.bin in ${BINDIR}" )
+    execute_process( COMMAND ${SRCFILE}.bin WORKING_DIRECTORY ${BINDIR}
+                     RESULT_VARIABLE _run_res
+                     OUTPUT_VARIABLE _run_out ERROR_VARIABLE _run_err )
+
+    if( _p_RUN_OUTPUT_VARIABLE )
+      set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} )
+    endif()
+    if( _run_out )
+      ecbuild_debug( "ecbuild_try_run: run output"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_out}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+    if( _run_err )
+      ecbuild_debug( "ecbuild_try_run: run errors"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_err}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+
+  else()
+    set( ${RUN_RESULT_VAR} "FAILED_TO_RUN" PARENT_SCOPE )
+    ecbuild_debug( "ecbuild_try_run: Compilation of ${SRCFILE} in ${BINDIR} failed!" )
+  endif()
+
+  set( ${COMPILE_RESULT_VAR} ${_compile_res} PARENT_SCOPE )
+  set( ${RUN_RESULT_VAR} ${_run_res} PARENT_SCOPE )
+  if( _p_COMPILE_OUTPUT_VARIABLE )
+    set( ${_p_COMPILE_OUTPUT_VARIABLE} ${_compile_out} PARENT_SCOPE )
+  endif()
+  if( _p_RUN_OUTPUT_VARIABLE )
+    set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} PARENT_SCOPE )
+  endif()
+  if( _p_OUTPUT_VARIABLE )
+    set( ${_p_OUTPUT_VARIABLE} "${_compile_out}\n${_run_out}" PARENT_SCOPE )
+  endif()
+
+endfunction()
+
+endif()
diff --git a/cmake/ecbuild_use_package.cmake b/cmake/ecbuild_use_package.cmake
index d54e459..43546f8 100644
--- a/cmake/ecbuild_use_package.cmake
+++ b/cmake/ecbuild_use_package.cmake
@@ -162,7 +162,6 @@ macro( ecbuild_use_package )
 
   # check if was already added as subproject ...
 
-  set( _just_added 0 )
   set( _do_version_check 0 )
   set( _source_description "" )
 
@@ -170,10 +169,8 @@ macro( ecbuild_use_package )
 
   if( NOT _ecbuild_project_${pkgUPPER} EQUAL "-1" )
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 1 )
   else()
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was not previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 0 )
   endif()
 
   # solve capitalization issues
@@ -185,26 +182,31 @@ macro( ecbuild_use_package )
     set( ${_p_PROJECT}_FOUND 1 )
   endif()
 
-  # Case 1) project was NOT previously added as subproject and is NOT already FOUND
+  # Case 1) project exists as subproject
 
-  if( NOT ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ )
+  if( DEFINED ${pkgUPPER}_subproj_dir_ )
 
-    # check if SUBPROJDIR is set
+    # check version is acceptable
+    set( _do_version_check 1 )
+
+    # Case 1a) project was already found
+
+    if( ${pkgUPPER}_FOUND )
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1a) project was already added as subproject, check version is acceptable")
 
-    if( DEFINED ${pkgUPPER}_subproj_dir_ )
+      set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
 
-      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1) project was NOT previously added as subproject and is NOT already FOUND")
+    # Case 1b) project was not already found
+
+    else()
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1b) project is NOT already FOUND and exists as subproject")
 
-      # check version is acceptable
-      set( _just_added 1 )
-      set( _do_version_check 1 )
       set( _source_description "sub-project ${_p_PROJECT} (sources)" )
 
       # add as a subproject
 
-      set( ${pkgUPPER}_subproj_dir_ ${${pkgUPPER}_subproj_dir_} CACHE PATH "Path to ${_p_PROJECT} source directory" )
-      mark_as_advanced( ${pkgUPPER}_subproj_dir_ )
-
       set( ECBUILD_PROJECTS ${ECBUILD_PROJECTS} ${_p_PROJECT} CACHE INTERNAL "" )
 
       ecbuild_debug("ecbuild_use_package(${_p_PROJECT}):    ${_p_PROJECT} found in subdirectory ${${pkgUPPER}_subproj_dir_}")
@@ -221,27 +223,12 @@ macro( ecbuild_use_package )
 
   endif()
 
-  # Case 2) project was already added as subproject, so is already FOUND -- BUT must check version acceptable
-
-  if( ${pkgUPPER}_previous_subproj_ )
-
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project was already added as subproject, check version is acceptable")
-
-    if( NOT ${pkgUPPER}_FOUND )
-      ecbuild_critical( "${_p_PROJECT} was already included as sub-project but ${pkgUPPER}_FOUND isn't set -- this is likely a BUG in ecbuild" )
-    endif()
-
-    # check version is acceptable
-    set( _do_version_check 1 )
-    set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
-
-  endif()
-
-  # Case 3) project was NOT added as subproject, but is FOUND -- so it was previously found as a binary ( either build or install tree )
+  # Case 2) project does NOT exist as subproject, but is FOUND
+  #   it was previously found as a binary ( either build or install tree )
 
-  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ AND NOT _just_added )
+  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_subproj_dir_ )
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project was NOT previously added as subproject, but is FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project does NOT exist as subproject, but is FOUND")
 
     # check version is acceptable
     set( _do_version_check 1 )
@@ -255,7 +242,6 @@ macro( ecbuild_use_package )
   # ecbuild_debug_var( _p_VERSION )
   # ecbuild_debug_var( ${pkgUPPER}_VERSION )
   # ecbuild_debug_var( ${_p_PROJECT}_VERSION )
-  # ecbuild_debug_var( _just_added )
   # ecbuild_debug_var( _do_version_check )
   # ecbuild_debug_var( _source_description )
   # ecbuild_debug_var( ${pkgUPPER}_FOUND )
@@ -275,7 +261,7 @@ macro( ecbuild_use_package )
     endif()
   endif()
 
-  # Case 4) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
+  # Case 3) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
   #         so try to find precompiled binaries or a build tree
 
   if( ${pkgUPPER}_FOUND )
@@ -289,7 +275,7 @@ macro( ecbuild_use_package )
                             PURPOSE "${_p_PURPOSE}" )
   else()
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 4) project has NOT been added as a subproject and is NOT already FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project does NOT exist as subproject and is NOT already FOUND")
 
     set( _opts )
     if( _p_VERSION )
diff --git a/cmake/fortran_features/CheckFortranFeatures.cmake b/cmake/fortran_features/CheckFortranFeatures.cmake
index 992964f..f9fd6e1 100644
--- a/cmake/fortran_features/CheckFortranFeatures.cmake
+++ b/cmake/fortran_features/CheckFortranFeatures.cmake
@@ -25,7 +25,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -33,7 +33,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/cmake/sg.pl b/cmake/sg.pl
index f8c8e31..c856ef3 100755
--- a/cmake/sg.pl
+++ b/cmake/sg.pl
@@ -1,5 +1,4 @@
-#!/usr/bin/perl
-#!/usr/local/share/perl56
+#!/usr/bin/env perl
 
 # (C) Copyright 1996-2017 ECMWF.
 # 
@@ -569,5 +568,3 @@ sub template {
 	return $self->{template} ? @{$self->{template}} : ();
 }
 1;
-
-
diff --git a/ecbuild/cmake/VERSION.cmake b/ecbuild/cmake/VERSION.cmake
index a95e4a9..af2b0d2 100644
--- a/ecbuild/cmake/VERSION.cmake
+++ b/ecbuild/cmake/VERSION.cmake
@@ -1,7 +1,7 @@
 set( ECBUILD_MAJOR_VERSION "2" )
 set( ECBUILD_MINOR_VERSION "7" )
-set( ECBUILD_PATCH_VERSION "0" )
+set( ECBUILD_PATCH_VERSION "1" )
 
-set( ECBUILD_VERSION_STR  "2.7.0" )
+set( ECBUILD_VERSION_STR  "2.7.1" )
 
 set( ECBUILD_MACRO_VERSION "${ECBUILD_VERSION_STR}" )
diff --git a/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake b/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
index 593b62f..fafcd23 100644
--- a/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
+++ b/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
@@ -44,7 +44,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -52,7 +52,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/ecbuild/cmake/ecbuild_add_persistent.cmake b/ecbuild/cmake/ecbuild_add_persistent.cmake
index e5a875b..40d7ad2 100644
--- a/ecbuild/cmake/ecbuild_add_persistent.cmake
+++ b/ecbuild/cmake/ecbuild_add_persistent.cmake
@@ -60,6 +60,8 @@ macro( ecbuild_add_persistent )
     ecbuild_critical("The call to ecbuild_add_persistent() doesn't specify the FILES.")
   endif()
 
+  ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${_PAR_FILES}" )
+
   foreach( file ${_PAR_FILES} )
 
     get_filename_component( _file_dir    ${file} PATH )
@@ -71,7 +73,7 @@ macro( ecbuild_add_persistent )
       set( file ${_file_dir}/${_file_we} )
     endif()
 
-    # ecbuild_debug_var(file)
+    ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${file}.b with namespace ${_PAR_NAMESPACE} from ${file}.h in ${CMAKE_CURRENT_BINARY_DIR}/${_file_dir}" )
 
     add_custom_command( OUTPUT  ${file}.b
                         COMMAND ${PERL_EXECUTABLE} ${sg_perl} ${CMAKE_CURRENT_SOURCE_DIR}/${file}.h
diff --git a/ecbuild/cmake/ecbuild_add_resources.cmake b/ecbuild/cmake/ecbuild_add_resources.cmake
index 2dfaa5e..51b1e68 100644
--- a/ecbuild/cmake/ecbuild_add_resources.cmake
+++ b/ecbuild/cmake/ecbuild_add_resources.cmake
@@ -51,6 +51,13 @@
 #   list of regular expressions to match files and directories to exclude when
 #   packaging
 #
+# Note
+# ----
+#
+# All file and directory names are also *partially matched*. To ensure that
+# only the exact file or directory name is matched at the end of the path add
+# a ``$`` at the end and quote the name.
+#
 ##############################################################################
 
 macro( ecbuild_add_resources )
diff --git a/ecbuild/cmake/ecbuild_check_c_source_return.cmake b/ecbuild/cmake/ecbuild_check_c_source_return.cmake
index 38d89f7..b92042b 100644
--- a/ecbuild/cmake/ecbuild_check_c_source_return.cmake
+++ b/ecbuild/cmake/ecbuild_check_c_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .c file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -95,12 +95,12 @@ macro( ecbuild_check_c_source_return SOURCE )
     
         # write the source file
     
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
@@ -114,6 +114,10 @@ macro( ecbuild_check_c_source_return SOURCE )
           set( ${_PAR_VAR}_EXITCODE 1 )
         endif()
     
+        ecbuild_debug_var( ${_PAR_VAR}_EXITCODE )
+        ecbuild_debug_var( ${_PAR_VAR}_COMPILED )
+        ecbuild_debug_var( compile_OUTPUT )
+        ecbuild_debug_var( run_OUTPUT )
         # if the return value was 0 then it worked
         if("${${_PAR_VAR}_EXITCODE}" EQUAL 0)
     
diff --git a/ecbuild/cmake/ecbuild_check_compiler.cmake b/ecbuild/cmake/ecbuild_check_compiler.cmake
index 197f0b5..dd09c0f 100644
--- a/ecbuild/cmake/ecbuild_check_compiler.cmake
+++ b/ecbuild/cmake/ecbuild_check_compiler.cmake
@@ -95,6 +95,10 @@ if( CMAKE_CXX_COMPILER_LOADED AND ENABLE_OS_TESTS )
     ecbuild_cache_check_cxx_source_compiles( "#include <sstream>\nint main() { std::stringstream s; }"
 	  EC_HAVE_CXX_SSTREAM )
 
+    # test c++ __int128
+    ecbuild_cache_check_cxx_source_compiles( "int main(){ __int128 i = 0; return 0;}\n"
+      EC_HAVE_CXX_INT_128 )
+
 endif()
 
 ############################################################################################
diff --git a/ecbuild/cmake/ecbuild_check_cxx11.cmake b/ecbuild/cmake/ecbuild_check_cxx11.cmake
index d2f9629..a7b551c 100644
--- a/ecbuild/cmake/ecbuild_check_cxx11.cmake
+++ b/ecbuild/cmake/ecbuild_check_cxx11.cmake
@@ -58,7 +58,7 @@ function( ecbuild_check_cxx11 )
   cxx11_find_all_features( ALL_FEATURES ) # list all available features to check
 
   # Save CXX flags
-  set( CXX_FLAGS_SNASHOT ${CMAKE_CXX_FLAGS} )
+  set( CXX_FLAGS_SNAPSHOT ${CMAKE_CXX_FLAGS} )
 
   # Add C++11 flags
   include( ${ECBUILD_MACROS_DIR}/ecbuild_get_cxx11_flags.cmake )
diff --git a/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake b/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
index 7270540..5b4b478 100644
--- a/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
+++ b/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .cxx file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -96,12 +96,12 @@ macro( ecbuild_check_cxx_source_return SOURCE )
 
         # write the source file
 
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx" "${SOURCE}\n" )
 
         ecbuild_debug( "${_msg}" )
-        try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
+        ecbuild_try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
diff --git a/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake b/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
index 92168b9..f8ccf05 100644
--- a/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
+++ b/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .f file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -98,7 +98,7 @@ macro( ecbuild_check_fortran_source_return SOURCE )
         file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
           ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
diff --git a/ecbuild/cmake/ecbuild_check_functions.cmake b/ecbuild/cmake/ecbuild_check_functions.cmake
index 59fbd3a..30d8013 100644
--- a/ecbuild/cmake/ecbuild_check_functions.cmake
+++ b/ecbuild/cmake/ecbuild_check_functions.cmake
@@ -122,6 +122,8 @@ if( ENABLE_OS_FUNCTIONS_TEST )
     ecbuild_cache_check_c_source_compiles( "#include <sys/types.h>\n#include <pwd.h>\nint main(){ struct passwd p; char line[1024]; int n = getpwnam_r(\"user\",&p,line,sizeof(line),0); }\n" EC_HAVE_GETPWNAM_R )
     # test for readdir_r
     ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; struct dirent **result; int i = readdir_r(dirp, entry, result); }\n" EC_HAVE_READDIR_R )
+    # test for d_type in dirent.h
+    ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; if(entry->d_type) { dirp = 0; } }\n" EC_HAVE_DIRENT_D_TYPE )
     # test for gethostbyname_r
     ecbuild_cache_check_c_source_compiles( "#include <netdb.h>\nint main(){ const char *name; struct hostent *ret; char *buf; struct hostent **result; size_t buflen; int *h_errnop; int i = gethostbyname_r(name,ret,buf,buflen,result,h_errnop); }\n" EC_HAVE_GETHOSTBYNAME_R )
 
diff --git a/ecbuild/cmake/ecbuild_check_os.cmake b/ecbuild/cmake/ecbuild_check_os.cmake
index d2af403..aaf2f79 100644
--- a/ecbuild/cmake/ecbuild_check_os.cmake
+++ b/ecbuild/cmake/ecbuild_check_os.cmake
@@ -44,6 +44,7 @@ if( ENABLE_OS_TYPES_TEST )
 
   set( EC_SIZEOF_PTR ${CMAKE_SIZEOF_VOID_P} )
   ecbuild_cache_var( EC_SIZEOF_PTR )
+
   ecbuild_cache_check_type_size( char           EC_SIZEOF_CHAR        )
   ecbuild_cache_check_type_size( short          EC_SIZEOF_SHORT       )
   ecbuild_cache_check_type_size( int            EC_SIZEOF_INT         )
diff --git a/ecbuild/cmake/ecbuild_config.h.in b/ecbuild/cmake/ecbuild_config.h.in
index a7d7d75..1774847 100644
--- a/ecbuild/cmake/ecbuild_config.h.in
+++ b/ecbuild/cmake/ecbuild_config.h.in
@@ -122,6 +122,7 @@
 #cmakedefine EC_HAVE_GETPWUID_R
 #cmakedefine EC_HAVE_GETPWNAM_R
 #cmakedefine EC_HAVE_READDIR_R
+#cmakedefine EC_HAVE_DIRENT_D_TYPE
 #cmakedefine EC_HAVE_GETHOSTBYNAME_R
 
 /* --- compiler __attribute__ support --- */
@@ -146,6 +147,7 @@
 
 #cmakedefine EC_HAVE_CXXABI_H
 #cmakedefine EC_HAVE_CXX_BOOL
+#cmakedefine EC_HAVE_CXX_INT_128
 
 #cmakedefine EC_HAVE_CXX_SSTREAM
 
diff --git a/ecbuild/cmake/ecbuild_find_fortranlibs.cmake b/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
index 905d020..ac7cf25 100644
--- a/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
+++ b/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
@@ -30,6 +30,8 @@
 
 macro( ecbuild_find_fortranlibs )
 
+  ecbuild_deprecate( "ecbuild_find_fortranlibs is deprecated and will be removed in an upcoming ecBuild release" )
+
   # parse parameters
 
   set( options REQUIRED )
@@ -39,7 +41,7 @@ macro( ecbuild_find_fortranlibs )
   cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
 
   if(_PAR_UNPARSED_ARGUMENTS)
-    ecbuild_critical("Unknown keywords given to ecbuild_find_python(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
+    ecbuild_critical("Unknown keywords given to ecbuild_find_fortranlibs(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
   endif()
 
   if( NOT FORTRANLIBS_FOUND ) # don't repeat search
diff --git a/ecbuild/cmake/ecbuild_find_package.cmake b/ecbuild/cmake/ecbuild_find_package.cmake
index 71be044..b69741e 100644
--- a/ecbuild/cmake/ecbuild_find_package.cmake
+++ b/ecbuild/cmake/ecbuild_find_package.cmake
@@ -193,8 +193,8 @@ macro( ecbuild_find_package )
 
   # search user defined paths first
 
-  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR )
-    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
+  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR OR ${_PAR_NAME}_BINARY_DIR )
+    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}, ${_PAR_NAME}_BINARY_DIR=${${_PAR_NAME}_BINARY_DIR}")
 
     # 1) search using CONFIG mode -- try to locate a configuration file provided by the package (package-config.cmake)
 
@@ -203,7 +203,7 @@ macro( ecbuild_find_package )
       ecbuild_debug("ecbuild_find_package(${_PAR_NAME}):    using hints ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
       find_package( ${_PAR_NAME} ${_${pkgUPPER}_version} NO_MODULE ${_find_quiet}
         COMPONENTS ${_PAR_COMPONENTS}
-        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR}
+        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR} ${${_PAR_NAME}_BINARY_DIR}
         NO_DEFAULT_PATH )
     endif()
 
diff --git a/ecbuild/cmake/ecbuild_system.cmake b/ecbuild/cmake/ecbuild_system.cmake
index 16c0299..b3a6c6b 100644
--- a/ecbuild/cmake/ecbuild_system.cmake
+++ b/ecbuild/cmake/ecbuild_system.cmake
@@ -163,6 +163,7 @@ if( PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME )
     include( ecbuild_list_add_pattern )
     include( ecbuild_list_exclude_pattern )
 
+    include( ecbuild_try_run )
     include( ecbuild_check_c_source_return )
     include( ecbuild_check_cxx_source_return )
     include( ecbuild_check_cxx11 )
diff --git a/ecbuild/cmake/ecbuild_try_run.cmake b/ecbuild/cmake/ecbuild_try_run.cmake
new file mode 100644
index 0000000..854f1d1
--- /dev/null
+++ b/ecbuild/cmake/ecbuild_try_run.cmake
@@ -0,0 +1,200 @@
+# (C) Copyright 1996-2017 ECMWF.
+#
+# This software is licensed under the terms of the Apache Licence Version 2.0
+# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+# In applying this licence, ECMWF does not waive the privileges and immunities
+# granted to it by virtue of its status as an intergovernmental organisation
+# nor does it submit to any jurisdiction.
+
+##############################################################################
+#.rst:
+#
+# ecbuild_try_run
+# ===============
+#
+# Try compiling and then running some code. ::
+#
+#   ecbuild_try_run( <run_result_var> <compile_result_var>
+#                    <bindir> <srcfile>
+#                    [ CMAKE_FLAGS <flag> [ <flag> ... ] ]
+#                    [ COMPILE_DEFINITIONS <def> [ <def> ... ] ]
+#                    [ LINK_LIBRARIES <lib> [ <lib> ... ] ]
+#                    [ COMPILE_OUTPUT_VARIABLE <var> ]
+#                    [ RUN_OUTPUT_VARIABLE <var> ]
+#                    [ OUTPUT_VARIABLE <var> ]
+#                    [ ARGS <arg> [ <arg> ... ] ] )
+#
+# Try compiling a ``<srcfile>``.  Returns ``TRUE`` or ``FALSE`` for success
+# or failure in ``<compile_result_var>``.  If the compile succeeded, runs the
+# executable and returns its exit code in ``<run_result_var>``.  If the
+# executable was built, but failed to run, then ``<run_result_var>`` will be
+# set to ``FAILED_TO_RUN``.  See the CMake ``try_compile`` command for
+# information on how the test project is constructed to build the source file.
+#
+# Options
+# -------
+#
+# CMAKE_FLAGS : optional
+#   Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to
+#   the ``cmake`` command-line used to drive the test build.
+#
+#   The example in CMake's ``try_compile`` shows how values for variables
+#   ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES``
+#   are used.
+#
+# COMPILE_DEFINITIONS : optional
+#   Specify ``-Ddefinition`` arguments to pass to ``add_definitions``
+#   in the generated test project.
+#
+# COMPILE_OUTPUT_VARIABLE : optional
+#   Report the compile step build output in a given variable.
+#
+# LINK_LIBRARIES : optional
+#   Specify libraries to be linked in the generated project.
+#   The list of libraries may refer to system libraries and to
+#   Imported Targets from the calling project.
+#
+#   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
+#   given to the ``CMAKE_FLAGS`` option will be ignored.
+#
+# OUTPUT_VARIABLE : optional
+#   Report the compile build output and the output from running the executable
+#   in the given variable.  This option exists for legacy reasons.  Prefer
+#   ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead.
+#
+# RUN_OUTPUT_VARIABLE : optional
+#   Report the output from running the executable in a given variable.
+#
+# Other Behavior Settings
+# -----------------------
+#
+# Set the ``CMAKE_TRY_COMPILE_CONFIGURATION`` variable to choose
+# a build configuration.
+#
+# Behavior when Cross Compiling
+# -----------------------------
+#
+# When cross compiling, the executable compiled in the first step
+# usually cannot be run on the build host.  The ``try_run`` command checks
+# the ``CMAKE_CROSSCOMPILING`` variable to detect whether CMake is in
+# cross-compiling mode.  If that is the case, it will still try to compile
+# the executable, but it will not try to run the executable unless the
+# ``CMAKE_CROSSCOMPILING_EMULATOR`` variable is set.  Instead it will create
+# cache variables which must be filled by the user or by presetting them in
+# some CMake script file to the values the executable would have produced if
+# it had been run on its actual target platform. These cache entries are:
+#
+# ``<RUN_RESULT_VAR>``
+#   Exit code if the executable were to be run on the target platform.
+#
+# ``<RUN_RESULT_VAR>__TRYRUN_OUTPUT``
+#   Output from stdout and stderr if the executable were to be run on
+#   the target platform.  This is created only if the
+#   ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` option was used.
+#
+# In order to make cross compiling your project easier, use ``try_run``
+# only if really required.  If you use ``try_run``, use the
+# ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really
+# required.  Using them will require that when cross-compiling, the cache
+# variables will have to be set manually to the output of the executable.
+# You can also "guard" the calls to ``try_run`` with an ``if`` block checking
+# the ``CMAKE_CROSSCOMPILING`` variable and provide an easy-to-preset
+# alternative for this case.
+#
+##############################################################################
+
+# This is an API compatible version of try_run which ignores output on stderr
+
+if( CMAKE_VERSION VERSION_LESS 2.8.12 )
+
+ecbuild_deprecate( "ecbuild_try_run falls back to try_run on CMake < 2.8.12 (ECBUILD-341)" )
+
+macro( ecbuild_try_run )
+  try_run( ${ARGV} )
+endmacro()
+
+else()
+
+function( ecbuild_try_run RUN_RESULT_VAR COMPILE_RESULT_VAR BINDIR SRCFILE )
+
+  set( options )
+  set( single_value_args COMPILE_OUTPUT_VARIABLE RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE )
+  set( multi_value_args  CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES ARGS )
+
+  cmake_parse_arguments( _p "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
+
+  if( _p_UNPARSED_ARGUMENTS )
+    ecbuild_critical("Unknown keywords given to ecbuild_try_run(): \"${_p_UNPARSED_ARGUMENTS}\"")
+  endif()
+
+  # Build argument list for try_compile
+  foreach( _opt CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES  )
+    if( _p_${_opt} )
+      list( APPEND _opts ${_opt} "${_p_${_opt}}" )
+    endif()
+  endforeach()
+
+  ecbuild_debug( "ecbuild_try_run: Compiling ${SRCFILE} in ${BINDIR}" )
+  try_compile( _compile_res ${BINDIR} ${SRCFILE}
+               OUTPUT_VARIABLE _compile_out
+               COPY_FILE ${SRCFILE}.bin COPY_FILE_ERROR _compile_err
+               ${_opts} )
+
+  if( _compile_out )
+    ecbuild_debug( "ecbuild_try_run: compilation output"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_out}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+  if( _compile_err )
+    ecbuild_debug( "ecbuild_try_run: compilation errors"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_err}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+
+  # FIXME: how do we handle cross compilation mode? (CMAKE_CROSSCOMPILING)
+
+  if( _compile_res )
+
+    ecbuild_debug( "ecbuild_try_run: Running ${SRCFILE}.bin in ${BINDIR}" )
+    execute_process( COMMAND ${SRCFILE}.bin WORKING_DIRECTORY ${BINDIR}
+                     RESULT_VARIABLE _run_res
+                     OUTPUT_VARIABLE _run_out ERROR_VARIABLE _run_err )
+
+    if( _p_RUN_OUTPUT_VARIABLE )
+      set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} )
+    endif()
+    if( _run_out )
+      ecbuild_debug( "ecbuild_try_run: run output"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_out}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+    if( _run_err )
+      ecbuild_debug( "ecbuild_try_run: run errors"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_err}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+
+  else()
+    set( ${RUN_RESULT_VAR} "FAILED_TO_RUN" PARENT_SCOPE )
+    ecbuild_debug( "ecbuild_try_run: Compilation of ${SRCFILE} in ${BINDIR} failed!" )
+  endif()
+
+  set( ${COMPILE_RESULT_VAR} ${_compile_res} PARENT_SCOPE )
+  set( ${RUN_RESULT_VAR} ${_run_res} PARENT_SCOPE )
+  if( _p_COMPILE_OUTPUT_VARIABLE )
+    set( ${_p_COMPILE_OUTPUT_VARIABLE} ${_compile_out} PARENT_SCOPE )
+  endif()
+  if( _p_RUN_OUTPUT_VARIABLE )
+    set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} PARENT_SCOPE )
+  endif()
+  if( _p_OUTPUT_VARIABLE )
+    set( ${_p_OUTPUT_VARIABLE} "${_compile_out}\n${_run_out}" PARENT_SCOPE )
+  endif()
+
+endfunction()
+
+endif()
diff --git a/ecbuild/cmake/ecbuild_use_package.cmake b/ecbuild/cmake/ecbuild_use_package.cmake
index d54e459..43546f8 100644
--- a/ecbuild/cmake/ecbuild_use_package.cmake
+++ b/ecbuild/cmake/ecbuild_use_package.cmake
@@ -162,7 +162,6 @@ macro( ecbuild_use_package )
 
   # check if was already added as subproject ...
 
-  set( _just_added 0 )
   set( _do_version_check 0 )
   set( _source_description "" )
 
@@ -170,10 +169,8 @@ macro( ecbuild_use_package )
 
   if( NOT _ecbuild_project_${pkgUPPER} EQUAL "-1" )
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 1 )
   else()
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was not previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 0 )
   endif()
 
   # solve capitalization issues
@@ -185,26 +182,31 @@ macro( ecbuild_use_package )
     set( ${_p_PROJECT}_FOUND 1 )
   endif()
 
-  # Case 1) project was NOT previously added as subproject and is NOT already FOUND
+  # Case 1) project exists as subproject
 
-  if( NOT ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ )
+  if( DEFINED ${pkgUPPER}_subproj_dir_ )
 
-    # check if SUBPROJDIR is set
+    # check version is acceptable
+    set( _do_version_check 1 )
+
+    # Case 1a) project was already found
+
+    if( ${pkgUPPER}_FOUND )
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1a) project was already added as subproject, check version is acceptable")
 
-    if( DEFINED ${pkgUPPER}_subproj_dir_ )
+      set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
 
-      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1) project was NOT previously added as subproject and is NOT already FOUND")
+    # Case 1b) project was not already found
+
+    else()
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1b) project is NOT already FOUND and exists as subproject")
 
-      # check version is acceptable
-      set( _just_added 1 )
-      set( _do_version_check 1 )
       set( _source_description "sub-project ${_p_PROJECT} (sources)" )
 
       # add as a subproject
 
-      set( ${pkgUPPER}_subproj_dir_ ${${pkgUPPER}_subproj_dir_} CACHE PATH "Path to ${_p_PROJECT} source directory" )
-      mark_as_advanced( ${pkgUPPER}_subproj_dir_ )
-
       set( ECBUILD_PROJECTS ${ECBUILD_PROJECTS} ${_p_PROJECT} CACHE INTERNAL "" )
 
       ecbuild_debug("ecbuild_use_package(${_p_PROJECT}):    ${_p_PROJECT} found in subdirectory ${${pkgUPPER}_subproj_dir_}")
@@ -221,27 +223,12 @@ macro( ecbuild_use_package )
 
   endif()
 
-  # Case 2) project was already added as subproject, so is already FOUND -- BUT must check version acceptable
-
-  if( ${pkgUPPER}_previous_subproj_ )
-
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project was already added as subproject, check version is acceptable")
-
-    if( NOT ${pkgUPPER}_FOUND )
-      ecbuild_critical( "${_p_PROJECT} was already included as sub-project but ${pkgUPPER}_FOUND isn't set -- this is likely a BUG in ecbuild" )
-    endif()
-
-    # check version is acceptable
-    set( _do_version_check 1 )
-    set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
-
-  endif()
-
-  # Case 3) project was NOT added as subproject, but is FOUND -- so it was previously found as a binary ( either build or install tree )
+  # Case 2) project does NOT exist as subproject, but is FOUND
+  #   it was previously found as a binary ( either build or install tree )
 
-  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ AND NOT _just_added )
+  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_subproj_dir_ )
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project was NOT previously added as subproject, but is FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project does NOT exist as subproject, but is FOUND")
 
     # check version is acceptable
     set( _do_version_check 1 )
@@ -255,7 +242,6 @@ macro( ecbuild_use_package )
   # ecbuild_debug_var( _p_VERSION )
   # ecbuild_debug_var( ${pkgUPPER}_VERSION )
   # ecbuild_debug_var( ${_p_PROJECT}_VERSION )
-  # ecbuild_debug_var( _just_added )
   # ecbuild_debug_var( _do_version_check )
   # ecbuild_debug_var( _source_description )
   # ecbuild_debug_var( ${pkgUPPER}_FOUND )
@@ -275,7 +261,7 @@ macro( ecbuild_use_package )
     endif()
   endif()
 
-  # Case 4) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
+  # Case 3) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
   #         so try to find precompiled binaries or a build tree
 
   if( ${pkgUPPER}_FOUND )
@@ -289,7 +275,7 @@ macro( ecbuild_use_package )
                             PURPOSE "${_p_PURPOSE}" )
   else()
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 4) project has NOT been added as a subproject and is NOT already FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project does NOT exist as subproject and is NOT already FOUND")
 
     set( _opts )
     if( _p_VERSION )
diff --git a/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake b/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
index 992964f..f9fd6e1 100644
--- a/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
+++ b/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
@@ -25,7 +25,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -33,7 +33,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/ecbuild/cmake/sg.pl b/ecbuild/cmake/sg.pl
index f8c8e31..c856ef3 100755
--- a/ecbuild/cmake/sg.pl
+++ b/ecbuild/cmake/sg.pl
@@ -1,5 +1,4 @@
-#!/usr/bin/perl
-#!/usr/local/share/perl56
+#!/usr/bin/env perl
 
 # (C) Copyright 1996-2017 ECMWF.
 # 
@@ -569,5 +568,3 @@ sub template {
 	return $self->{template} ? @{$self->{template}} : ();
 }
 1;
-
-
diff --git a/ecbuild/doc/upload.py b/ecbuild/doc/upload.py
index b246d10..19ec80a 100644
--- a/ecbuild/doc/upload.py
+++ b/ecbuild/doc/upload.py
@@ -16,7 +16,10 @@ import requests
 from rst2confluence import confluence
 
 API_URL = 'https://software.ecmwf.int/wiki/rest/api/content'
-AUTH = (environ['USER'], environ['CONFLUENCE_PASSWORD'])
+if 'USER' in environ and 'CONFLUENCE_PASSWORD' in environ:
+    AUTH = (environ['USER'], environ['CONFLUENCE_PASSWORD'])
+else:
+    AUTH = None
 
 log = logging.getLogger('upload')
 log.setLevel(logging.DEBUG)
diff --git a/ecbuild/examples/cpp-bundle-nested/CMakeLists.txt b/ecbuild/examples/cpp-bundle-nested/CMakeLists.txt
new file mode 100644
index 0000000..d786074
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required( VERSION 2.8.4 FATAL_ERROR )
+
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake" )
+
+include( ecbuild_bundle )
+
+project( cpp_bundle_nested C CXX )
+
+ecbuild_bundle_initialize()
+
+ecbuild_bundle( PROJECT bar )
+ecbuild_bundle( PROJECT baz )
+
+ecbuild_bundle_finalize()
diff --git a/ecbuild/examples/cpp-bundle-nested/VERSION.cmake b/ecbuild/examples/cpp-bundle-nested/VERSION.cmake
new file mode 100644
index 0000000..caf4027
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "0.10.0")
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/CMakeLists.txt b/ecbuild/examples/cpp-bundle-nested/bar/CMakeLists.txt
new file mode 100644
index 0000000..0a0459d
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required( VERSION 2.8.12 FATAL_ERROR )
+
+project( bar C CXX )
+
+set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 2.7 )
+
+### open project
+
+ecbuild_declare_project()
+
+### targets
+
+ecbuild_bundle( PROJECT foo )
+
+ecbuild_add_library( TARGET            bar
+                     PRIVATE_INCLUDES  ${FOO_INCLUDE_DIRS}
+                     LIBS              foo
+                     SOURCES           bar.h bar.c )
+
+ecbuild_add_executable(
+    TARGET     master_bar
+    SOURCES    main.cc
+    INCLUDES   ${FOO_INCLUDE_DIRS}
+    LIBS       bar
+)
+
+ecbuild_add_test(
+    TARGET     test_bar
+    SOURCES    test.cc
+    LIBS       bar
+)
+
+ecbuild_install_project( NAME ${PROJECT_NAME} )
+
+ecbuild_print_summary()
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/VERSION.cmake b/ecbuild/examples/cpp-bundle-nested/bar/VERSION.cmake
new file mode 100644
index 0000000..e0959dc
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "1.0.0" )
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/bar.c b/ecbuild/examples/cpp-bundle-nested/bar/bar.c
new file mode 100644
index 0000000..22420fe
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/bar.c
@@ -0,0 +1,5 @@
+#include "foo.h"
+
+int bar() {
+  return foo() * foo();
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/bar.h b/ecbuild/examples/cpp-bundle-nested/bar/bar.h
new file mode 100644
index 0000000..bcffbba
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/bar.h
@@ -0,0 +1,6 @@
+#ifndef bar_h
+#define bar_h
+
+int bar();
+
+#endif
\ No newline at end of file
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/CMakeLists.txt b/ecbuild/examples/cpp-bundle-nested/bar/foo/CMakeLists.txt
new file mode 100644
index 0000000..17e8c61
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/CMakeLists.txt
@@ -0,0 +1,37 @@
+cmake_minimum_required( VERSION 2.8.12 FATAL_ERROR )
+
+project( foo )
+
+set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 2.7 )
+
+### open project
+
+ecbuild_declare_project()
+
+### targets
+
+set( FOO_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} )
+
+ecbuild_add_library(TARGET            foo
+                    SOURCES           foo.h foo.c
+                    PRIVATE_INCLUDES  ${FOO_INCLUDE_DIRS} )
+
+ecbuild_add_executable(
+    TARGET      master_foo
+    SOURCES     main.cc
+    LIBS        foo
+    INCLUDES    ${FOO_INCLUDE_DIRS}  )
+
+ecbuild_add_test(
+    TARGET      test_foo
+    SOURCES     test.cc
+    LIBS        foo
+    INCLUDES    ${FOO_INCLUDE_DIRS}  )
+
+ecbuild_install_project( NAME ${PROJECT_NAME} )
+
+ecbuild_print_summary()
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/VERSION.cmake b/ecbuild/examples/cpp-bundle-nested/bar/foo/VERSION.cmake
new file mode 100644
index 0000000..e0959dc
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "1.0.0" )
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.c b/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.c
new file mode 100644
index 0000000..632d9ba
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.c
@@ -0,0 +1,3 @@
+int foo() {
+  return 42;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.h b/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.h
new file mode 100644
index 0000000..6b68dbb
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/foo.h
@@ -0,0 +1,6 @@
+#ifndef foo_h
+#define foo_h
+
+int foo();
+
+#endif
\ No newline at end of file
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/main.cc b/ecbuild/examples/cpp-bundle-nested/bar/foo/main.cc
new file mode 100644
index 0000000..2ce7bc2
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/main.cc
@@ -0,0 +1,9 @@
+#include <iostream>
+
+extern "C" {
+#include "foo.h"
+}
+
+int main() {
+  std::cout << "foo is " << foo() << std::endl;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/foo/test.cc b/ecbuild/examples/cpp-bundle-nested/bar/foo/test.cc
new file mode 100644
index 0000000..6162005
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/foo/test.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+
+extern "C" {
+#include "foo.h"
+}
+
+int main() {
+  if( foo() == 42)
+    std::cout << "ok" << std::endl;
+  else
+    std::cout << "failed" << std::endl;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/main.cc b/ecbuild/examples/cpp-bundle-nested/bar/main.cc
new file mode 100644
index 0000000..7bc4d15
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/main.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+
+extern "C" {
+#include "foo.h"
+#include "bar.h"
+}
+
+int main()
+{
+  std::cout << "foo is " << foo() << std::endl;
+  std::cout << "bar is " << bar() << std::endl;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/bar/test.cc b/ecbuild/examples/cpp-bundle-nested/bar/test.cc
new file mode 100644
index 0000000..244347f
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/bar/test.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+
+extern "C" {
+#include "bar.h"
+}
+
+int main() {
+  if( bar() == 42*42 )
+    std::cout << "ok" << std::endl;
+  else
+    std::cout << "failed" << std::endl;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/CMakeLists.txt b/ecbuild/examples/cpp-bundle-nested/baz/CMakeLists.txt
new file mode 100644
index 0000000..fcf6afa
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required( VERSION 2.8.12 FATAL_ERROR )
+
+project( baz C CXX )
+
+set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 2.7 )
+
+### open project
+
+ecbuild_declare_project()
+
+### targets
+
+ecbuild_use_package( PROJECT foo REQUIRED )
+
+ecbuild_add_library( TARGET            baz
+                     SOURCES           baz.h baz.c
+                     PRIVATE_INCLUDES  ${FOO_INCLUDE_DIRS}
+                     LIBS              foo )
+
+ecbuild_add_executable(
+    TARGET     master_baz
+    SOURCES    main.cc
+    INCLUDES   ${FOO_INCLUDE_DIRS}
+    LIBS       baz
+)
+
+ecbuild_add_test(
+    TARGET     test_baz
+    SOURCES    test.cc
+    LIBS       baz
+)
+
+ecbuild_install_project( NAME ${PROJECT_NAME} )
+
+ecbuild_print_summary()
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/VERSION.cmake b/ecbuild/examples/cpp-bundle-nested/baz/VERSION.cmake
new file mode 100644
index 0000000..e0959dc
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "1.0.0" )
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/baz.c b/ecbuild/examples/cpp-bundle-nested/baz/baz.c
new file mode 100644
index 0000000..83677b1
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/baz.c
@@ -0,0 +1,5 @@
+#include "foo.h"
+
+int baz() {
+  return foo() * foo() * foo();
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/baz.h b/ecbuild/examples/cpp-bundle-nested/baz/baz.h
new file mode 100644
index 0000000..f56fd6c
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/baz.h
@@ -0,0 +1,6 @@
+#ifndef baz_h
+#define baz_h
+
+int baz();
+
+#endif
\ No newline at end of file
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/main.cc b/ecbuild/examples/cpp-bundle-nested/baz/main.cc
new file mode 100644
index 0000000..2f8d580
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/main.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+
+extern "C" {
+#include "foo.h"
+#include "baz.h"
+}
+
+int main()
+{
+  std::cout << "foo is " << foo() << std::endl;
+  std::cout << "baz is " << baz() << std::endl;
+}
diff --git a/ecbuild/examples/cpp-bundle-nested/baz/test.cc b/ecbuild/examples/cpp-bundle-nested/baz/test.cc
new file mode 100644
index 0000000..b73ccd2
--- /dev/null
+++ b/ecbuild/examples/cpp-bundle-nested/baz/test.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+
+extern "C" {
+#include "baz.h"
+}
+
+int main() {
+  if( baz() == 42*42*42 )
+    std::cout << "ok" << std::endl;
+  else
+    std::cout << "failed" << std::endl;
+}
diff --git a/ecbuild/examples/cxx11/CMakeLists.txt b/ecbuild/examples/cxx11/CMakeLists.txt
new file mode 100644
index 0000000..24c3093
--- /dev/null
+++ b/ecbuild/examples/cxx11/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required( VERSION 2.8.12 FATAL_ERROR )
+
+project( cxx11 CXX )
+
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake" )
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 1.9 )
+
+### open project
+
+ecbuild_declare_project()
+
+### definitions
+
+ecbuild_add_cxx11_flags()
+
+### targets
+
+ecbuild_add_executable( TARGET compute
+                        SOURCES compute.cc )
+
+### pkgconfig exports
+
+ecbuild_pkgconfig()
+
+### finalize project
+
+ecbuild_install_project( NAME ${PROJECT_NAME} )
+
+ecbuild_print_summary()
diff --git a/ecbuild/examples/cxx11/README.md b/ecbuild/examples/cxx11/README.md
new file mode 100644
index 0000000..6cdebe6
--- /dev/null
+++ b/ecbuild/examples/cxx11/README.md
@@ -0,0 +1,6 @@
+Simple example demonstrating the use of C++11 features with a fallback.
+
+Usage:
+=====
+
+ecbuild examples/cxx11
diff --git a/ecbuild/examples/cxx11/VERSION.cmake b/ecbuild/examples/cxx11/VERSION.cmake
new file mode 100644
index 0000000..498f79e
--- /dev/null
+++ b/ecbuild/examples/cxx11/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "0.0.1")
diff --git a/ecbuild/examples/cxx11/compute.cc b/ecbuild/examples/cxx11/compute.cc
new file mode 100644
index 0000000..18b8099
--- /dev/null
+++ b/ecbuild/examples/cxx11/compute.cc
@@ -0,0 +1,29 @@
+#include <iostream>
+
+#if __cplusplus > 199711L
+
+#pragma message "C++11 enabled"
+#include <unordered_set>
+#define __set std::unordered_set<int>
+
+#else
+
+#pragma message "C++11 disabled"
+#include <set>
+#define __set std::set<int>
+
+#endif
+
+int main() {
+
+  __set s;
+
+  s.insert(7);
+  s.insert(5);
+  s.insert(3);
+
+  for(__set::const_iterator it = s.begin(); it != s.end(); ++it)
+    std::cout << *it << std::endl;
+
+  return 0;
+}
diff --git a/ecbuild/share/ecbuild/cmake/VERSION.cmake b/ecbuild/share/ecbuild/cmake/VERSION.cmake
index a95e4a9..af2b0d2 100644
--- a/ecbuild/share/ecbuild/cmake/VERSION.cmake
+++ b/ecbuild/share/ecbuild/cmake/VERSION.cmake
@@ -1,7 +1,7 @@
 set( ECBUILD_MAJOR_VERSION "2" )
 set( ECBUILD_MINOR_VERSION "7" )
-set( ECBUILD_PATCH_VERSION "0" )
+set( ECBUILD_PATCH_VERSION "1" )
 
-set( ECBUILD_VERSION_STR  "2.7.0" )
+set( ECBUILD_VERSION_STR  "2.7.1" )
 
 set( ECBUILD_MACRO_VERSION "${ECBUILD_VERSION_STR}" )
diff --git a/ecbuild/share/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake b/ecbuild/share/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
index 593b62f..fafcd23 100644
--- a/ecbuild/share/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
+++ b/ecbuild/share/ecbuild/cmake/contrib/GreatCMakeCookOff/CheckCXX11Features.cmake
@@ -44,7 +44,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -52,7 +52,7 @@ MACRO(cxx11_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_add_persistent.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_add_persistent.cmake
index e5a875b..40d7ad2 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_add_persistent.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_add_persistent.cmake
@@ -60,6 +60,8 @@ macro( ecbuild_add_persistent )
     ecbuild_critical("The call to ecbuild_add_persistent() doesn't specify the FILES.")
   endif()
 
+  ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${_PAR_FILES}" )
+
   foreach( file ${_PAR_FILES} )
 
     get_filename_component( _file_dir    ${file} PATH )
@@ -71,7 +73,7 @@ macro( ecbuild_add_persistent )
       set( file ${_file_dir}/${_file_we} )
     endif()
 
-    # ecbuild_debug_var(file)
+    ecbuild_debug( "ecbuild_add_persistent: adding persistent layer for ${file}.b with namespace ${_PAR_NAMESPACE} from ${file}.h in ${CMAKE_CURRENT_BINARY_DIR}/${_file_dir}" )
 
     add_custom_command( OUTPUT  ${file}.b
                         COMMAND ${PERL_EXECUTABLE} ${sg_perl} ${CMAKE_CURRENT_SOURCE_DIR}/${file}.h
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_add_resources.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_add_resources.cmake
index 2dfaa5e..51b1e68 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_add_resources.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_add_resources.cmake
@@ -51,6 +51,13 @@
 #   list of regular expressions to match files and directories to exclude when
 #   packaging
 #
+# Note
+# ----
+#
+# All file and directory names are also *partially matched*. To ensure that
+# only the exact file or directory name is matched at the end of the path add
+# a ``$`` at the end and quote the name.
+#
 ##############################################################################
 
 macro( ecbuild_add_resources )
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_c_source_return.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_c_source_return.cmake
index 38d89f7..b92042b 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_c_source_return.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_c_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .c file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -95,12 +95,12 @@ macro( ecbuild_check_c_source_return SOURCE )
     
         # write the source file
     
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.c
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCSource/test_${_PAR_VAR}.c
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
@@ -114,6 +114,10 @@ macro( ecbuild_check_c_source_return SOURCE )
           set( ${_PAR_VAR}_EXITCODE 1 )
         endif()
     
+        ecbuild_debug_var( ${_PAR_VAR}_EXITCODE )
+        ecbuild_debug_var( ${_PAR_VAR}_COMPILED )
+        ecbuild_debug_var( compile_OUTPUT )
+        ecbuild_debug_var( run_OUTPUT )
         # if the return value was 0 then it worked
         if("${${_PAR_VAR}_EXITCODE}" EQUAL 0)
     
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_compiler.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_compiler.cmake
index 197f0b5..dd09c0f 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_compiler.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_compiler.cmake
@@ -95,6 +95,10 @@ if( CMAKE_CXX_COMPILER_LOADED AND ENABLE_OS_TESTS )
     ecbuild_cache_check_cxx_source_compiles( "#include <sstream>\nint main() { std::stringstream s; }"
 	  EC_HAVE_CXX_SSTREAM )
 
+    # test c++ __int128
+    ecbuild_cache_check_cxx_source_compiles( "int main(){ __int128 i = 0; return 0;}\n"
+      EC_HAVE_CXX_INT_128 )
+
 endif()
 
 ############################################################################################
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx11.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx11.cmake
index d2f9629..a7b551c 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx11.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx11.cmake
@@ -58,7 +58,7 @@ function( ecbuild_check_cxx11 )
   cxx11_find_all_features( ALL_FEATURES ) # list all available features to check
 
   # Save CXX flags
-  set( CXX_FLAGS_SNASHOT ${CMAKE_CXX_FLAGS} )
+  set( CXX_FLAGS_SNAPSHOT ${CMAKE_CXX_FLAGS} )
 
   # Add C++11 flags
   include( ${ECBUILD_MACROS_DIR}/ecbuild_get_cxx11_flags.cmake )
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
index 7270540..5b4b478 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_cxx_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .cxx file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -96,12 +96,12 @@ macro( ecbuild_check_cxx_source_return SOURCE )
 
         # write the source file
 
-        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx" "${SOURCE}\n" )
+        file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx" "${SOURCE}\n" )
 
         ecbuild_debug( "${_msg}" )
-        try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
+        ecbuild_try_run( ${_p_VAR}_EXITCODE ${_p_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
-          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_p_VAR}.cxx
+          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckCXXSource/test_${_p_VAR}.cxx
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
           CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
           -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
index 92168b9..f8ccf05 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_fortran_source_return.cmake
@@ -43,8 +43,8 @@
 # -----
 #
 # This will write the given source to a .f file and compile and run it with
-# try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is set to
-# the output of the successful run in the CMake cache.
+# ecbuild_try_run. If successful, ``${VAR}`` is set to 1 and ``${OUTPUT}`` is
+# set to the output of the successful run in the CMake cache.
 #
 # The check will not run if ``${VAR}`` is defined (e.g. from ecBuild cache).
 #
@@ -98,7 +98,7 @@ macro( ecbuild_check_fortran_source_return SOURCE )
         file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90" "${SOURCE}\n" )
 
         ecbuild_debug( "Performing Test ${_PAR_VAR}" )
-        try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
+        ecbuild_try_run( ${_PAR_VAR}_EXITCODE ${_PAR_VAR}_COMPILED
           ${CMAKE_BINARY_DIR}
           ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_${_PAR_VAR}.F90
           COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_functions.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_functions.cmake
index 59fbd3a..30d8013 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_functions.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_functions.cmake
@@ -122,6 +122,8 @@ if( ENABLE_OS_FUNCTIONS_TEST )
     ecbuild_cache_check_c_source_compiles( "#include <sys/types.h>\n#include <pwd.h>\nint main(){ struct passwd p; char line[1024]; int n = getpwnam_r(\"user\",&p,line,sizeof(line),0); }\n" EC_HAVE_GETPWNAM_R )
     # test for readdir_r
     ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; struct dirent **result; int i = readdir_r(dirp, entry, result); }\n" EC_HAVE_READDIR_R )
+    # test for d_type in dirent.h
+    ecbuild_cache_check_c_source_compiles( "#include <dirent.h>\nint main(){ DIR *dirp; struct dirent *entry; if(entry->d_type) { dirp = 0; } }\n" EC_HAVE_DIRENT_D_TYPE )
     # test for gethostbyname_r
     ecbuild_cache_check_c_source_compiles( "#include <netdb.h>\nint main(){ const char *name; struct hostent *ret; char *buf; struct hostent **result; size_t buflen; int *h_errnop; int i = gethostbyname_r(name,ret,buf,buflen,result,h_errnop); }\n" EC_HAVE_GETHOSTBYNAME_R )
 
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_check_os.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_check_os.cmake
index d2af403..aaf2f79 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_check_os.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_check_os.cmake
@@ -44,6 +44,7 @@ if( ENABLE_OS_TYPES_TEST )
 
   set( EC_SIZEOF_PTR ${CMAKE_SIZEOF_VOID_P} )
   ecbuild_cache_var( EC_SIZEOF_PTR )
+
   ecbuild_cache_check_type_size( char           EC_SIZEOF_CHAR        )
   ecbuild_cache_check_type_size( short          EC_SIZEOF_SHORT       )
   ecbuild_cache_check_type_size( int            EC_SIZEOF_INT         )
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_config.h.in b/ecbuild/share/ecbuild/cmake/ecbuild_config.h.in
index a7d7d75..1774847 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_config.h.in
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_config.h.in
@@ -122,6 +122,7 @@
 #cmakedefine EC_HAVE_GETPWUID_R
 #cmakedefine EC_HAVE_GETPWNAM_R
 #cmakedefine EC_HAVE_READDIR_R
+#cmakedefine EC_HAVE_DIRENT_D_TYPE
 #cmakedefine EC_HAVE_GETHOSTBYNAME_R
 
 /* --- compiler __attribute__ support --- */
@@ -146,6 +147,7 @@
 
 #cmakedefine EC_HAVE_CXXABI_H
 #cmakedefine EC_HAVE_CXX_BOOL
+#cmakedefine EC_HAVE_CXX_INT_128
 
 #cmakedefine EC_HAVE_CXX_SSTREAM
 
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_find_fortranlibs.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
index 905d020..ac7cf25 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_find_fortranlibs.cmake
@@ -30,6 +30,8 @@
 
 macro( ecbuild_find_fortranlibs )
 
+  ecbuild_deprecate( "ecbuild_find_fortranlibs is deprecated and will be removed in an upcoming ecBuild release" )
+
   # parse parameters
 
   set( options REQUIRED )
@@ -39,7 +41,7 @@ macro( ecbuild_find_fortranlibs )
   cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
 
   if(_PAR_UNPARSED_ARGUMENTS)
-    ecbuild_critical("Unknown keywords given to ecbuild_find_python(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
+    ecbuild_critical("Unknown keywords given to ecbuild_find_fortranlibs(): \"${_PAR_UNPARSED_ARGUMENTS}\"")
   endif()
 
   if( NOT FORTRANLIBS_FOUND ) # don't repeat search
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_find_package.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_find_package.cmake
index 71be044..b69741e 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_find_package.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_find_package.cmake
@@ -193,8 +193,8 @@ macro( ecbuild_find_package )
 
   # search user defined paths first
 
-  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR )
-    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
+  if( ${_PAR_NAME}_PATH OR ${pkgUPPER}_PATH OR ${_PAR_NAME}_DIR OR ${_PAR_NAME}_BINARY_DIR )
+    ecbuild_debug("ecbuild_find_package(${_PAR_NAME}): ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}, ${_PAR_NAME}_BINARY_DIR=${${_PAR_NAME}_BINARY_DIR}")
 
     # 1) search using CONFIG mode -- try to locate a configuration file provided by the package (package-config.cmake)
 
@@ -203,7 +203,7 @@ macro( ecbuild_find_package )
       ecbuild_debug("ecbuild_find_package(${_PAR_NAME}):    using hints ${pkgUPPER}_PATH=${${pkgUPPER}_PATH}, ${_PAR_NAME}_PATH=${${_PAR_NAME}_PATH}, ${_PAR_NAME}_DIR=${${_PAR_NAME}_DIR}")
       find_package( ${_PAR_NAME} ${_${pkgUPPER}_version} NO_MODULE ${_find_quiet}
         COMPONENTS ${_PAR_COMPONENTS}
-        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR}
+        HINTS ${${pkgUPPER}_PATH} ${${_PAR_NAME}_PATH} ${${_PAR_NAME}_DIR} ${${_PAR_NAME}_BINARY_DIR}
         NO_DEFAULT_PATH )
     endif()
 
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_system.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_system.cmake
index 16c0299..b3a6c6b 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_system.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_system.cmake
@@ -163,6 +163,7 @@ if( PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME )
     include( ecbuild_list_add_pattern )
     include( ecbuild_list_exclude_pattern )
 
+    include( ecbuild_try_run )
     include( ecbuild_check_c_source_return )
     include( ecbuild_check_cxx_source_return )
     include( ecbuild_check_cxx11 )
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_try_run.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_try_run.cmake
new file mode 100644
index 0000000..854f1d1
--- /dev/null
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_try_run.cmake
@@ -0,0 +1,200 @@
+# (C) Copyright 1996-2017 ECMWF.
+#
+# This software is licensed under the terms of the Apache Licence Version 2.0
+# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+# In applying this licence, ECMWF does not waive the privileges and immunities
+# granted to it by virtue of its status as an intergovernmental organisation
+# nor does it submit to any jurisdiction.
+
+##############################################################################
+#.rst:
+#
+# ecbuild_try_run
+# ===============
+#
+# Try compiling and then running some code. ::
+#
+#   ecbuild_try_run( <run_result_var> <compile_result_var>
+#                    <bindir> <srcfile>
+#                    [ CMAKE_FLAGS <flag> [ <flag> ... ] ]
+#                    [ COMPILE_DEFINITIONS <def> [ <def> ... ] ]
+#                    [ LINK_LIBRARIES <lib> [ <lib> ... ] ]
+#                    [ COMPILE_OUTPUT_VARIABLE <var> ]
+#                    [ RUN_OUTPUT_VARIABLE <var> ]
+#                    [ OUTPUT_VARIABLE <var> ]
+#                    [ ARGS <arg> [ <arg> ... ] ] )
+#
+# Try compiling a ``<srcfile>``.  Returns ``TRUE`` or ``FALSE`` for success
+# or failure in ``<compile_result_var>``.  If the compile succeeded, runs the
+# executable and returns its exit code in ``<run_result_var>``.  If the
+# executable was built, but failed to run, then ``<run_result_var>`` will be
+# set to ``FAILED_TO_RUN``.  See the CMake ``try_compile`` command for
+# information on how the test project is constructed to build the source file.
+#
+# Options
+# -------
+#
+# CMAKE_FLAGS : optional
+#   Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to
+#   the ``cmake`` command-line used to drive the test build.
+#
+#   The example in CMake's ``try_compile`` shows how values for variables
+#   ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES``
+#   are used.
+#
+# COMPILE_DEFINITIONS : optional
+#   Specify ``-Ddefinition`` arguments to pass to ``add_definitions``
+#   in the generated test project.
+#
+# COMPILE_OUTPUT_VARIABLE : optional
+#   Report the compile step build output in a given variable.
+#
+# LINK_LIBRARIES : optional
+#   Specify libraries to be linked in the generated project.
+#   The list of libraries may refer to system libraries and to
+#   Imported Targets from the calling project.
+#
+#   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
+#   given to the ``CMAKE_FLAGS`` option will be ignored.
+#
+# OUTPUT_VARIABLE : optional
+#   Report the compile build output and the output from running the executable
+#   in the given variable.  This option exists for legacy reasons.  Prefer
+#   ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead.
+#
+# RUN_OUTPUT_VARIABLE : optional
+#   Report the output from running the executable in a given variable.
+#
+# Other Behavior Settings
+# -----------------------
+#
+# Set the ``CMAKE_TRY_COMPILE_CONFIGURATION`` variable to choose
+# a build configuration.
+#
+# Behavior when Cross Compiling
+# -----------------------------
+#
+# When cross compiling, the executable compiled in the first step
+# usually cannot be run on the build host.  The ``try_run`` command checks
+# the ``CMAKE_CROSSCOMPILING`` variable to detect whether CMake is in
+# cross-compiling mode.  If that is the case, it will still try to compile
+# the executable, but it will not try to run the executable unless the
+# ``CMAKE_CROSSCOMPILING_EMULATOR`` variable is set.  Instead it will create
+# cache variables which must be filled by the user or by presetting them in
+# some CMake script file to the values the executable would have produced if
+# it had been run on its actual target platform. These cache entries are:
+#
+# ``<RUN_RESULT_VAR>``
+#   Exit code if the executable were to be run on the target platform.
+#
+# ``<RUN_RESULT_VAR>__TRYRUN_OUTPUT``
+#   Output from stdout and stderr if the executable were to be run on
+#   the target platform.  This is created only if the
+#   ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` option was used.
+#
+# In order to make cross compiling your project easier, use ``try_run``
+# only if really required.  If you use ``try_run``, use the
+# ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really
+# required.  Using them will require that when cross-compiling, the cache
+# variables will have to be set manually to the output of the executable.
+# You can also "guard" the calls to ``try_run`` with an ``if`` block checking
+# the ``CMAKE_CROSSCOMPILING`` variable and provide an easy-to-preset
+# alternative for this case.
+#
+##############################################################################
+
+# This is an API compatible version of try_run which ignores output on stderr
+
+if( CMAKE_VERSION VERSION_LESS 2.8.12 )
+
+ecbuild_deprecate( "ecbuild_try_run falls back to try_run on CMake < 2.8.12 (ECBUILD-341)" )
+
+macro( ecbuild_try_run )
+  try_run( ${ARGV} )
+endmacro()
+
+else()
+
+function( ecbuild_try_run RUN_RESULT_VAR COMPILE_RESULT_VAR BINDIR SRCFILE )
+
+  set( options )
+  set( single_value_args COMPILE_OUTPUT_VARIABLE RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE )
+  set( multi_value_args  CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES ARGS )
+
+  cmake_parse_arguments( _p "${options}" "${single_value_args}" "${multi_value_args}"  ${_FIRST_ARG} ${ARGN} )
+
+  if( _p_UNPARSED_ARGUMENTS )
+    ecbuild_critical("Unknown keywords given to ecbuild_try_run(): \"${_p_UNPARSED_ARGUMENTS}\"")
+  endif()
+
+  # Build argument list for try_compile
+  foreach( _opt CMAKE_FLAGS COMPILE_DEFINITIONS LINK_LIBRARIES  )
+    if( _p_${_opt} )
+      list( APPEND _opts ${_opt} "${_p_${_opt}}" )
+    endif()
+  endforeach()
+
+  ecbuild_debug( "ecbuild_try_run: Compiling ${SRCFILE} in ${BINDIR}" )
+  try_compile( _compile_res ${BINDIR} ${SRCFILE}
+               OUTPUT_VARIABLE _compile_out
+               COPY_FILE ${SRCFILE}.bin COPY_FILE_ERROR _compile_err
+               ${_opts} )
+
+  if( _compile_out )
+    ecbuild_debug( "ecbuild_try_run: compilation output"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_out}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+  if( _compile_err )
+    ecbuild_debug( "ecbuild_try_run: compilation errors"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+      "\n${_compile_err}"
+      "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+  endif()
+
+  # FIXME: how do we handle cross compilation mode? (CMAKE_CROSSCOMPILING)
+
+  if( _compile_res )
+
+    ecbuild_debug( "ecbuild_try_run: Running ${SRCFILE}.bin in ${BINDIR}" )
+    execute_process( COMMAND ${SRCFILE}.bin WORKING_DIRECTORY ${BINDIR}
+                     RESULT_VARIABLE _run_res
+                     OUTPUT_VARIABLE _run_out ERROR_VARIABLE _run_err )
+
+    if( _p_RUN_OUTPUT_VARIABLE )
+      set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} )
+    endif()
+    if( _run_out )
+      ecbuild_debug( "ecbuild_try_run: run output"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_out}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+    if( _run_err )
+      ecbuild_debug( "ecbuild_try_run: run errors"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+        "\n${_run_err}"
+        "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
+    endif()
+
+  else()
+    set( ${RUN_RESULT_VAR} "FAILED_TO_RUN" PARENT_SCOPE )
+    ecbuild_debug( "ecbuild_try_run: Compilation of ${SRCFILE} in ${BINDIR} failed!" )
+  endif()
+
+  set( ${COMPILE_RESULT_VAR} ${_compile_res} PARENT_SCOPE )
+  set( ${RUN_RESULT_VAR} ${_run_res} PARENT_SCOPE )
+  if( _p_COMPILE_OUTPUT_VARIABLE )
+    set( ${_p_COMPILE_OUTPUT_VARIABLE} ${_compile_out} PARENT_SCOPE )
+  endif()
+  if( _p_RUN_OUTPUT_VARIABLE )
+    set( ${_p_RUN_OUTPUT_VARIABLE} ${_run_out} PARENT_SCOPE )
+  endif()
+  if( _p_OUTPUT_VARIABLE )
+    set( ${_p_OUTPUT_VARIABLE} "${_compile_out}\n${_run_out}" PARENT_SCOPE )
+  endif()
+
+endfunction()
+
+endif()
diff --git a/ecbuild/share/ecbuild/cmake/ecbuild_use_package.cmake b/ecbuild/share/ecbuild/cmake/ecbuild_use_package.cmake
index d54e459..43546f8 100644
--- a/ecbuild/share/ecbuild/cmake/ecbuild_use_package.cmake
+++ b/ecbuild/share/ecbuild/cmake/ecbuild_use_package.cmake
@@ -162,7 +162,6 @@ macro( ecbuild_use_package )
 
   # check if was already added as subproject ...
 
-  set( _just_added 0 )
   set( _do_version_check 0 )
   set( _source_description "" )
 
@@ -170,10 +169,8 @@ macro( ecbuild_use_package )
 
   if( NOT _ecbuild_project_${pkgUPPER} EQUAL "-1" )
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 1 )
   else()
     ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): ${_p_PROJECT} was not previously added as a subproject")
-    set( ${pkgUPPER}_previous_subproj_ 0 )
   endif()
 
   # solve capitalization issues
@@ -185,26 +182,31 @@ macro( ecbuild_use_package )
     set( ${_p_PROJECT}_FOUND 1 )
   endif()
 
-  # Case 1) project was NOT previously added as subproject and is NOT already FOUND
+  # Case 1) project exists as subproject
 
-  if( NOT ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ )
+  if( DEFINED ${pkgUPPER}_subproj_dir_ )
 
-    # check if SUBPROJDIR is set
+    # check version is acceptable
+    set( _do_version_check 1 )
+
+    # Case 1a) project was already found
+
+    if( ${pkgUPPER}_FOUND )
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1a) project was already added as subproject, check version is acceptable")
 
-    if( DEFINED ${pkgUPPER}_subproj_dir_ )
+      set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
 
-      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1) project was NOT previously added as subproject and is NOT already FOUND")
+    # Case 1b) project was not already found
+
+    else()
+
+      ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 1b) project is NOT already FOUND and exists as subproject")
 
-      # check version is acceptable
-      set( _just_added 1 )
-      set( _do_version_check 1 )
       set( _source_description "sub-project ${_p_PROJECT} (sources)" )
 
       # add as a subproject
 
-      set( ${pkgUPPER}_subproj_dir_ ${${pkgUPPER}_subproj_dir_} CACHE PATH "Path to ${_p_PROJECT} source directory" )
-      mark_as_advanced( ${pkgUPPER}_subproj_dir_ )
-
       set( ECBUILD_PROJECTS ${ECBUILD_PROJECTS} ${_p_PROJECT} CACHE INTERNAL "" )
 
       ecbuild_debug("ecbuild_use_package(${_p_PROJECT}):    ${_p_PROJECT} found in subdirectory ${${pkgUPPER}_subproj_dir_}")
@@ -221,27 +223,12 @@ macro( ecbuild_use_package )
 
   endif()
 
-  # Case 2) project was already added as subproject, so is already FOUND -- BUT must check version acceptable
-
-  if( ${pkgUPPER}_previous_subproj_ )
-
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project was already added as subproject, check version is acceptable")
-
-    if( NOT ${pkgUPPER}_FOUND )
-      ecbuild_critical( "${_p_PROJECT} was already included as sub-project but ${pkgUPPER}_FOUND isn't set -- this is likely a BUG in ecbuild" )
-    endif()
-
-    # check version is acceptable
-    set( _do_version_check 1 )
-    set( _source_description "already existing sub-project ${_p_PROJECT} (sources)" )
-
-  endif()
-
-  # Case 3) project was NOT added as subproject, but is FOUND -- so it was previously found as a binary ( either build or install tree )
+  # Case 2) project does NOT exist as subproject, but is FOUND
+  #   it was previously found as a binary ( either build or install tree )
 
-  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_previous_subproj_ AND NOT _just_added )
+  if( ${pkgUPPER}_FOUND AND NOT ${pkgUPPER}_subproj_dir_ )
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project was NOT previously added as subproject, but is FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 2) project does NOT exist as subproject, but is FOUND")
 
     # check version is acceptable
     set( _do_version_check 1 )
@@ -255,7 +242,6 @@ macro( ecbuild_use_package )
   # ecbuild_debug_var( _p_VERSION )
   # ecbuild_debug_var( ${pkgUPPER}_VERSION )
   # ecbuild_debug_var( ${_p_PROJECT}_VERSION )
-  # ecbuild_debug_var( _just_added )
   # ecbuild_debug_var( _do_version_check )
   # ecbuild_debug_var( _source_description )
   # ecbuild_debug_var( ${pkgUPPER}_FOUND )
@@ -275,7 +261,7 @@ macro( ecbuild_use_package )
     endif()
   endif()
 
-  # Case 4) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
+  # Case 3) is NOT FOUND so far, NOT as sub-project (now or before), and NOT as binary neither
   #         so try to find precompiled binaries or a build tree
 
   if( ${pkgUPPER}_FOUND )
@@ -289,7 +275,7 @@ macro( ecbuild_use_package )
                             PURPOSE "${_p_PURPOSE}" )
   else()
 
-    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 4) project has NOT been added as a subproject and is NOT already FOUND")
+    ecbuild_debug("ecbuild_use_package(${_p_PROJECT}): 3) project does NOT exist as subproject and is NOT already FOUND")
 
     set( _opts )
     if( _p_VERSION )
diff --git a/ecbuild/share/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake b/ecbuild/share/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
index 992964f..f9fd6e1 100644
--- a/ecbuild/share/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
+++ b/ecbuild/share/ecbuild/cmake/fortran_features/CheckFortranFeatures.cmake
@@ -25,7 +25,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
       ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
     ELSE (CROSS_COMPILING)
-      try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+      ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
           "${_bindir}" "${_SRCFILE}")
       IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
         SET(${RESULT_VAR} TRUE)
@@ -33,7 +33,7 @@ MACRO(fortran_check_single_feature FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
         SET(${RESULT_VAR} FALSE)
       ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
       IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
-        try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
+        ecbuild_try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
             "${_bindir}_fail" "${_SRCFILE_FAIL}")
         IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
           SET(${RESULT_VAR} TRUE)
diff --git a/ecbuild/share/ecbuild/cmake/sg.pl b/ecbuild/share/ecbuild/cmake/sg.pl
index f8c8e31..c856ef3 100755
--- a/ecbuild/share/ecbuild/cmake/sg.pl
+++ b/ecbuild/share/ecbuild/cmake/sg.pl
@@ -1,5 +1,4 @@
-#!/usr/bin/perl
-#!/usr/local/share/perl56
+#!/usr/bin/env perl
 
 # (C) Copyright 1996-2017 ECMWF.
 # 
@@ -569,5 +568,3 @@ sub template {
 	return $self->{template} ? @{$self->{template}} : ();
 }
 1;
-
-
diff --git a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
index e3ef29c..be3ed8f 100644
--- a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
+++ b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 8 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )
diff --git a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
index 84dbd7b..5acd12e 100644
--- a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
+++ b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 16 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )
diff --git a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
index a890886..8e6b41d 100644
--- a/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
+++ b/ecbuild/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 16 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )
diff --git a/eckit/CMakeLists.txt b/eckit/CMakeLists.txt
index 9ed8656..5961f34 100644
--- a/eckit/CMakeLists.txt
+++ b/eckit/CMakeLists.txt
@@ -24,6 +24,12 @@ ecbuild_declare_project()
 ###############################################################################
 # some variables/options of this project
 
+### C++11 compiler flag
+
+ecbuild_add_option( FEATURE CXX11
+                    DEFAULT OFF
+                    DESCRIPTION "Use C++11 compiler flag" )
+
 ### Experimental features
 
 ecbuild_add_option( FEATURE EXPERIMENTAL
@@ -50,9 +56,8 @@ ecbuild_add_option( FEATURE EIGEN
                     REQUIRED_PACKAGES Eigen3 )
 
 set_package_properties( Eigen3 PROPERTIES
-                        TYPE RECOMMENDED
                         DESCRIPTION "C++ template library for linear algebra"
-                        PURPOSE "Dense and sparse matrix operations" )
+                      )
 
 if( ENABLE_EIGEN )
     # TODO: we should add here a test that we can compile Eigen without problems
@@ -69,8 +74,7 @@ ecbuild_add_option( FEATURE ARMADILLO
 
 set_package_properties( Armadillo PROPERTIES
                         DESCRIPTION "C++ linear algebra"
-                        TYPE RECOMMENDED
-                        PURPOSE "Dense matrix operations" )
+                      )
 
 ### LAPACK
 
@@ -82,8 +86,6 @@ ecbuild_add_option( FEATURE LAPACK
 
 ecbuild_add_option( FEATURE SSL
                     DESCRIPTION "OpenSSL support"
-                    TYPE RECOMMENDED
-                    PURPOSE "OpenSSL provides crypto and hashing algorithms including SHA1"
                     REQUIRED_PACKAGES OpenSSL )
 
 ecbuild_info("OpenSSL ${OPENSSL_FOUND} ${OPENSSL_VERSION} : libs ${OPENSSL_LIBRARIES} incs ${OPENSSL_INCLUDE_DIR}")
@@ -92,7 +94,6 @@ ecbuild_info("OpenSSL ${OPENSSL_FOUND} ${OPENSSL_VERSION} : libs ${OPENSSL_LIBRA
 
 ecbuild_add_option( FEATURE XXHASH
                     DESCRIPTION "Use xxHash for non-crypto hashing in data integrity checks"
-                    PURPOSE     "xxHash support"
                     REQUIRED_PACKAGES "PROJECT xxHash" )
 
 ecbuild_info("xxHash ${XXHASH_FOUND}  : libs ${XXHASH_LIBRARIES} incs ${XXHASH_INCLUDE_DIRS}")
@@ -137,6 +138,10 @@ find_package( Threads REQUIRED )
 
 find_package( Curses REQUIRED )
 
+### c math library, needed when including "math.h"
+
+find_package( CMath )
+
 ###############################################################################
 # checks
 
@@ -191,10 +196,15 @@ if( HAVE_EIGEN )
     include_directories( ${EIGEN3_INCLUDE_DIR} )
 endif()
 
+if( HAVE_CXX11 )
+    ecbuild_add_cxx11_flags()
+endif()
+
 add_subdirectory( bamboo )
 add_subdirectory( contrib )
 add_subdirectory( doc )
 add_subdirectory( src )
+add_subdirectory( tests )
 add_subdirectory( regressions )
 
 ecbuild_add_resources( TARGET ${PROJECT_NAME}_top_files SOURCES
diff --git a/eckit/TODO b/eckit/TODO
index 883c556..1cbb3ef 100644
--- a/eckit/TODO
+++ b/eckit/TODO
@@ -1,10 +1,7 @@
 TODO
 
- - remove architecture dependent headers
  - add control of behavior on Exception
      - output on constructor
      - backtrace on contructor
      - abort on constructor
      - abort on double exception
-
- - Allow finer control on logging format ( eg [%time][%pid] message )
diff --git a/eckit/VERSION.cmake b/eckit/VERSION.cmake
index c9c3fa3..b719131 100644
--- a/eckit/VERSION.cmake
+++ b/eckit/VERSION.cmake
@@ -1 +1 @@
-set( ${PROJECT_NAME}_VERSION_STR  "0.16.3")
+set( ${PROJECT_NAME}_VERSION_STR  "0.17.0")
diff --git a/eckit/eckit.sublime-project b/eckit/eckit.sublime-project
index 168c355..ff453ce 100644
--- a/eckit/eckit.sublime-project
+++ b/eckit/eckit.sublime-project
@@ -1,29 +1,60 @@
 {
+	"SublimeLinter":
+	{
+		"linters":
+		{
+			"cpplint":
+			{
+				"filter": "-whitespace/line_length,-whitespace/blank_line,-runtime/references"
+			}
+		}
+	},
+	"build_systems":
+	[
+		{
+			"file_regex": "([/\\w\\-\\.]+):(\\d+):(\\d+:)?",
+			"name": "eckit",
+			"shell_cmd": "make",
+			"syntax": "Packages/CMakeBuilder/Syntax/Make.sublime-syntax",
+			"variants":
+			[
+				{
+					"name": "clean",
+					"shell_cmd": "make clean"
+				}
+			],
+			"working_dir": "${project_path}/../../build/eckit"
+		},
+		{
+			"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
+			"name": "Anaconda Python Builder",
+			"selector": "source.python",
+			"shell_cmd": "\"python\" -u \"$file\""
+		}
+	],
 	"folders":
 	[
 		{
-            "file_exclude_patterns": [".tags", ".tags_sorted_by_file", ".gemtags","CMakeLists.txt.user*"],
+			"file_exclude_patterns":
+			[
+				".tags",
+				".tags_sorted_by_file",
+				".gemtags",
+				"CMakeLists.txt.user*"
+			],
 			"follow_symlinks": true,
 			"path": "."
 		}
 	],
-	"build_systems": [
-        {
-            "working_dir": "${project_path}/../../build/eckit",
-            "cmd": [
-                "make"
-            ],
-            "file_regex": "([/\\w\\-\\.]+):(\\d+):(\\d+:)?",
-            "name": "ecbuild"
-        }
-    ],
-    "SublimeLinter":
-    {
-        "linters":
-        {
-            "cpplint": {
-                "filter": "-whitespace/line_length,-whitespace/blank_line,-runtime/references"
-            },
-        }
-    }
+	"settings":
+	{
+		"cmake":
+		{
+			"build_folder": "${project_path}/../../build/eckit",
+			"command_line_overrides":
+			{
+				"DEVELOPER_MODE": 1
+			}
+		}
+	}
 }
diff --git a/eckit/regressions/CMakeLists.txt b/eckit/regressions/CMakeLists.txt
index 8e18b8e..ebe8dff 100644
--- a/eckit/regressions/CMakeLists.txt
+++ b/eckit/regressions/CMakeLists.txt
@@ -1,4 +1,4 @@
-list( APPEND regressions ECKIT-175 )
+list( APPEND regressions ECKIT-175 ECKIT-221 ECKIT-166 )
 
 foreach( r ${regressions} )
 
@@ -8,7 +8,7 @@ foreach( r ${regressions} )
     NOINSTALL
     TARGET   ${r}.x
     SOURCES  ${r}.cc
-    LIBS     eckit )
+    LIBS     eckit_mpi eckit )
 
   ecbuild_add_test(
     TYPE     SCRIPT
diff --git a/eckit/regressions/ECKIT-166.cc b/eckit/regressions/ECKIT-166.cc
new file mode 100644
index 0000000..73d3274
--- /dev/null
+++ b/eckit/regressions/ECKIT-166.cc
@@ -0,0 +1,29 @@
+/*
+
+BUG ECKIT-166
+=============
+
+*/
+
+#include <iostream>
+#include "eckit/runtime/Main.h"
+#include "eckit/mpi/Comm.h"
+
+using namespace eckit;
+
+void run(int argc, char **argv) {
+
+  Main::initialise(argc,argv);
+
+  // This should initialise MPI automatically
+  if( mpi::comm().rank() == 0 )
+    std::cout << "mpi::comm().size() = " << mpi::comm().size() << std::endl;
+
+}
+
+int main(int argc, char **argv) {
+  std::cout << "begin of main" << std::endl;
+  run(argc,argv);
+  std::cout << "end of main" << std::endl;
+  return 0;
+}
diff --git a/eckit/regressions/ECKIT-166.sh.in b/eckit/regressions/ECKIT-166.sh.in
new file mode 100755
index 0000000..de8755f
--- /dev/null
+++ b/eckit/regressions/ECKIT-166.sh.in
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -eux
+
+cd @CMAKE_CURRENT_BINARY_DIR@
+
+exe="./ECKIT-166.x"
+
+if [ "@ECKIT_HAVE_MPI@" == "1" ]; then
+
+  @MPIEXEC@ -np 1 $exe
+
+fi
+
+echo "OK"
diff --git a/eckit/regressions/ECKIT-175.cc b/eckit/regressions/ECKIT-175.cc
index bbb67de..a79a33c 100644
--- a/eckit/regressions/ECKIT-175.cc
+++ b/eckit/regressions/ECKIT-175.cc
@@ -1,4 +1,3 @@
-
 /*
 
 BUG ECKIT-175
diff --git a/eckit/regressions/ECKIT-221.cc b/eckit/regressions/ECKIT-221.cc
new file mode 100644
index 0000000..fbacbb4
--- /dev/null
+++ b/eckit/regressions/ECKIT-221.cc
@@ -0,0 +1,55 @@
+/*
+
+FEATURE ECKIT-221
+=================
+
+    Test broadcasting of file, read on one processor
+
+*/
+
+#include <map>
+#include <cstdlib>
+#include <iostream>
+
+#include "eckit/memory/ScopedPtr.h"
+#include "eckit/io/DataHandle.h"
+#include "eckit/mpi/Comm.h"
+#include "eckit/utils/Translator.h"
+#include "eckit/runtime/Tool.h"
+
+using namespace eckit;
+
+class MyTool : public Tool {
+public:
+
+    MyTool(int argc, char **argv) : Tool(argc,argv) {}
+
+    virtual ~MyTool() {
+        mpi::finaliseAllComms();
+    }
+
+    virtual void run() {
+
+        PathName filename(argv()[1]);
+
+        SharedBuffer buffer = mpi::comm().broadcastFile(filename, 0);
+
+        PathName out = filename + "." + Translator<size_t, std::string>()(mpi::comm().rank());
+
+        ScopedPtr<DataHandle> dh ( out.fileHandle() ); AutoClose closer(*dh);
+        dh->openForWrite(buffer.size());
+        dh->write(buffer, buffer.size());
+    }
+
+};
+
+int main(int argc, char **argv) {
+
+    if( argc != 2 ) {
+        std::cout << "Usage: " << argv[0] << " <file>" << std::endl;
+        return -1;
+    }
+
+    MyTool tool(argc,argv);
+    return tool.start();
+}
diff --git a/eckit/regressions/ECKIT-221.sh.in b/eckit/regressions/ECKIT-221.sh.in
new file mode 100755
index 0000000..44d5a16
--- /dev/null
+++ b/eckit/regressions/ECKIT-221.sh.in
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+set -eux
+
+cd @CMAKE_CURRENT_BINARY_DIR@
+
+exe="./ECKIT-221.x"
+
+fname="file1.txt"
+str="abc123"
+
+### Case 1 - Serial
+
+function create_file {
+  rm -f $fname*
+  echo "$str" >> $fname
+  echo "$str" >> $fname
+  echo "$str" >> $fname
+}
+
+create_file
+
+$exe "$fname"
+
+cmp "$fname" "$fname.0"
+
+### Case 2 - Parallel
+
+if [ "@ECKIT_HAVE_MPI@" == "1" ]; then
+
+  create_file
+
+  @MPIEXEC@ -np 4 $exe "$fname"
+
+  for i in 0 1 2 3; do
+    cmp "$fname" "$fname.$i"
+  done
+
+fi
+
+echo "OK"
diff --git a/eckit/src/CMakeLists.txt b/eckit/src/CMakeLists.txt
index 1b95c3d..c6e401b 100644
--- a/eckit/src/CMakeLists.txt
+++ b/eckit/src/CMakeLists.txt
@@ -15,5 +15,3 @@ if( HAVE_EXPERIMENTAL )
 endif()
 
 add_subdirectory( apps )
-
-add_subdirectory( tests )
diff --git a/eckit/src/eckit/CMakeLists.txt b/eckit/src/eckit/CMakeLists.txt
index 531c53c..437bdbc 100644
--- a/eckit/src/eckit/CMakeLists.txt
+++ b/eckit/src/eckit/CMakeLists.txt
@@ -21,6 +21,10 @@ list( APPEND eckit_container_srcs
 
 container/BTree.h
 container/BTree.cc
+container/Trie.h
+container/Trie.cc
+container/BloomFilter.h
+container/BloomFilter.cc
 
 container/Cache.h
 container/CacheLRU.h
@@ -153,6 +157,8 @@ io/TCPSocketHandle.h
 io/TCPSocketHandle.cc
 io/TeeHandle.h
 io/TeeHandle.cc
+io/Pipeline.h
+io/Pipeline.cc
 io/HandleHolder.h
 io/HandleHolder.cc
 io/cluster/ClusterDisks.h
@@ -166,6 +172,8 @@ io/cluster/NodeInfo.cc )
 
 list( APPEND eckit_filesystem_srcs
 filesystem/FileSystemSize.h
+filesystem/PathExpander.h
+filesystem/PathExpander.cc
 filesystem/PathName.h
 filesystem/PathName.cc
 filesystem/BasePathNameT.h
@@ -221,7 +229,6 @@ config/Configured.cc
 config/Configured.h
 config/EtcTable.cc
 config/EtcTable.h
-config/JSONConfiguration.cc
 config/JSONConfiguration.h
 config/LibEcKit.cc
 config/LibEcKit.h
@@ -229,10 +236,12 @@ config/LocalConfiguration.cc
 config/LocalConfiguration.h
 config/Parametrisation.h
 config/Resource.h
-config/Resource.cc
+config/ResourceBase.h
 config/ResourceBase.cc
 config/ResourceMgr.cc
 config/ResourceMgr.h
+config/YAMLConfiguration.cc
+config/YAMLConfiguration.h
 )
 
 list( APPEND eckit_runtime_srcs
@@ -377,8 +386,12 @@ parser/Tokenizer.h
 parser/Tokenizer.cc
 parser/JSON.h
 parser/JSON.cc
+parser/ObjectParser.h
+parser/ObjectParser.cc
 parser/JSONParser.h
 parser/JSONParser.cc
+parser/YAMLParser.h
+parser/YAMLParser.cc
 parser/JSONDataBlob.h
 parser/JSONDataBlob.cc
 parser/JSONMetadata.h
@@ -393,6 +406,10 @@ value/Content.h
 value/Content.cc
 value/DateContent.h
 value/DateContent.cc
+value/TimeContent.h
+value/TimeContent.cc
+value/DateTimeContent.h
+value/DateTimeContent.cc
 value/DispatchParams.h
 value/DoubleContent.h
 value/DoubleContent.cc
@@ -616,6 +633,8 @@ endforeach()
 list( APPEND eckit_templates
 					container/CacheLRU.cc
                     container/BTree.cc
+                    container/Trie.cc
+                    container/BloomFilter.cc
                     container/MappedArray.cc
                     container/SharedMemArray.cc
                     container/bsptree/BSPNode.cc
@@ -623,7 +642,6 @@ list( APPEND eckit_templates
 					container/sptree/SPNode.cc
 					filesystem/BasePathNameT.cc
 					io/FileBase.cc
-					config/Resource.cc
 					runtime/PipeHandler.cc
 					serialisation/Reanimator.cc
 					transaction/TxnLog.cc
@@ -668,9 +686,11 @@ ecbuild_add_library(TARGET eckit
                         ${OPENSSL_LIBRARIES}
                         ${XXHASH_LIBRARIES}
                         ${AIO_LIBRARIES}
+                        ${CMATH_LIBRARIES}
                         ${CMAKE_THREAD_LIBS_INIT}
                         ${CMAKE_DL_LIBS}
-                        ${ECKIT_SYSTEM_EXTRA_LIBS} )
+                        ${ECKIT_SYSTEM_EXTRA_LIBS}
+                   LINKER_LANGUAGE CXX )
 
 ### sub-directories
 
diff --git a/eckit/src/eckit/config/Configuration.cc b/eckit/src/eckit/config/Configuration.cc
index 067409d..e085390 100644
--- a/eckit/src/eckit/config/Configuration.cc
+++ b/eckit/src/eckit/config/Configuration.cc
@@ -17,6 +17,7 @@
 #include "eckit/config/Configuration.h"
 #include "eckit/parser/Tokenizer.h"
 #include "eckit/exception/Exceptions.h"
+#include "eckit/parser/JSON.h"
 
 namespace eckit {
 
@@ -75,18 +76,13 @@ eckit::Value Configuration::lookUp(const std::string &s, bool &found) const {
 
     eckit::Value result = root_;
 
-    // std::cout << "Configuration::lookUp root=" << result << std::endl;
     for (size_t i = 0; i < path.size(); i++) {
         const std::string &key = path[i];
         if (!result.contains(key)) {
             found = false;
             return result;
         }
-        // std::cout << "Configuration::lookUp key=" << key  << std::endl;
-
         result = result[key];
-        // std::cout << "Configuration::lookUp key=" << result  << std::endl;
-
     }
 
     found = true;
@@ -126,6 +122,17 @@ bool Configuration::get(const std::string &name, bool &value) const {
     return found;
 }
 
+bool Configuration::get(const std::string &name, int &value) const {
+    bool found = false;
+    eckit::Value v = lookUp(name, found);
+    if (found) {
+        long result(v);
+        ASSERT(int(result) == result);
+        value = result;
+    }
+    return found;
+}
+
 bool Configuration::get(const std::string &name, long &value) const {
     bool found = false;
     eckit::Value v = lookUp(name, found);
@@ -135,6 +142,24 @@ bool Configuration::get(const std::string &name, long &value) const {
     return found;
 }
 
+bool Configuration::get(const std::string &name, size_t &value) const {
+    bool found = false;
+    eckit::Value v = lookUp(name, found);
+    if (found) {
+        value = size_t(v);
+    }
+    return found;
+}
+
+bool Configuration::get(const std::string &name, float &value) const {
+    bool found = false;
+    eckit::Value v = lookUp(name, found);
+    if (found) {
+        value = double(v);
+    }
+    return found;
+}
+
 bool Configuration::get(const std::string &name, double &value) const {
     bool found = false;
     eckit::Value v = lookUp(name, found);
@@ -144,10 +169,19 @@ bool Configuration::get(const std::string &name, double &value) const {
     return found;
 }
 
-bool Configuration::get(const std::string &name, LocalConfiguration& value) const {
-    bool found = has(name);
-    if(found) {
-        value = LocalConfiguration(*this, name);
+bool Configuration::get(const std::string &name, std::vector<int> &value) const {
+    bool found = false;
+    eckit::Value v = lookUp(name, found);
+    if (found) {
+        ASSERT(v.isList());
+        value.clear();
+        int i = 0;
+        while (v.contains(i)) {
+            long result(v[i]);
+            ASSERT(int(result) == result);
+            value.push_back(result);
+            i++;
+        }
     }
     return found;
 }
@@ -167,8 +201,22 @@ bool Configuration::get(const std::string &name, std::vector<long> &value) const
     return found;
 }
 
+bool Configuration::get(const std::string &name, std::vector<size_t> &value) const {
+    bool found = false;
+    eckit::Value v = lookUp(name, found);
+    if (found) {
+        ASSERT(v.isList());
+        value.clear();
+        int i = 0;
+        while (v.contains(i)) {
+            value.push_back(v[i]);
+            i++;
+        }
+    }
+    return found;
+}
 
-bool Configuration::get(const std::string &name, std::vector<LocalConfiguration> &value) const {
+bool Configuration::get(const std::string &name, std::vector<float> &value) const {
     bool found = false;
     eckit::Value v = lookUp(name, found);
     if (found) {
@@ -176,7 +224,7 @@ bool Configuration::get(const std::string &name, std::vector<LocalConfiguration>
         value.clear();
         int i = 0;
         while (v.contains(i)) {
-            value.push_back(LocalConfiguration(v[i], separator_));
+            value.push_back(double(v[i]));
             i++;
         }
     }
@@ -213,11 +261,25 @@ bool Configuration::get(const std::string &name, std::vector<std::string> &value
     return found;
 }
 
-bool Configuration::get(const std::string &name, size_t &value) const {
+bool Configuration::get(const std::string &name, LocalConfiguration& value) const {
+    bool found = has(name);
+    if(found) {
+        value = LocalConfiguration(*this, name);
+    }
+    return found;
+}
+
+bool Configuration::get(const std::string &name, std::vector<LocalConfiguration> &value) const {
     bool found = false;
     eckit::Value v = lookUp(name, found);
     if (found) {
-        value = long(v);
+        ASSERT(v.isList());
+        value.clear();
+        int i = 0;
+        while (v.contains(i)) {
+            value.push_back(LocalConfiguration(v[i], separator_));
+            i++;
+        }
     }
     return found;
 }
@@ -238,9 +300,8 @@ bool Configuration::getBool(const std::string &name) const {
 }
 
 int Configuration::getInt(const std::string &name) const {
-    long result;
+    int result;
     _get(name, result);
-    ASSERT(int(result) == result);
     return result;
 }
 
@@ -257,9 +318,8 @@ size_t Configuration::getUnsigned(const std::string &name) const {
 }
 
 float Configuration::getFloat(const std::string &name) const {
-    double result;
+    float result;
     _get(name, result);
-    ASSERT(float(result) == result);
     return result;
 }
 
@@ -278,13 +338,7 @@ std::string Configuration::getString(const std::string &name) const {
 
 std::vector<int> Configuration::getIntVector(const std::string &name) const {
     std::vector<int> result;
-    std::vector<long> tmp;
-    _get(name, tmp);
-    result.reserve(tmp.size());
-    for(size_t i = 0; i < tmp.size(); i++) {
-        ASSERT(int(tmp[i]) == tmp[i]);
-        result.push_back(tmp[i]);
-    }
+    _get(name, result);
     return result;
 }
 
@@ -296,25 +350,13 @@ std::vector<long> Configuration::getLongVector(const std::string &name) const {
 
 std::vector<size_t> Configuration::getUnsignedVector(const std::string &name) const {
     std::vector<size_t> result;
-    std::vector<long> tmp;
-    _get(name, tmp);
-    result.reserve(tmp.size());
-    for(size_t i = 0; i < tmp.size(); i++) {
-        ASSERT(tmp[i] >= 0);
-        result.push_back(tmp[i]);
-    }
+    _get(name, result);
     return result;
 }
 
 std::vector<float> Configuration::getFloatVector(const std::string &name) const {
-     std::vector<float> result;
-    std::vector<long> tmp;
-    _get(name, tmp);
-    result.reserve(tmp.size());
-    for(size_t i = 0; i < tmp.size(); i++) {
-        ASSERT(float(tmp[i]) == tmp[i]);
-        result.push_back(tmp[i]);
-    }
+    std::vector<float> result;
+    _get(name, result);
     return result;
 }
 
@@ -356,9 +398,8 @@ bool Configuration::getBool(const std::string &name, const bool& defaultVal) con
 }
 
 int Configuration::getInt (const std::string &name, const int& defaultVal) const {
-    long result;
-    _getWithDefault(name, result, long(defaultVal));
-    ASSERT(int(result) == result);
+    int result;
+    _getWithDefault(name, result, defaultVal);
     return result;
 }
 
@@ -375,9 +416,8 @@ size_t Configuration::getUnsigned(const std::string &name, const size_t& default
 }
 
 float Configuration::getFloat(const std::string &name, const float& defaultVal) const {
-    double result;
-    _getWithDefault(name, result, double(defaultVal));
-    ASSERT(float(result) == result);
+    float result;
+    _getWithDefault(name, result, defaultVal);
     return result;
 }
 
@@ -393,6 +433,48 @@ std::string Configuration::getString(const std::string &name, const std::string&
     return result;
 }
 
+std::vector<int> Configuration::getIntVector(const std::string &name, const std::vector<int>& defaultValue) const {
+    std::vector<int> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+std::vector<long> Configuration::getLongVector(const std::string &name, const std::vector<long>& defaultValue) const {
+    std::vector<long> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+std::vector<size_t> Configuration::getUnsignedVector(const std::string &name, const std::vector<size_t>& defaultValue) const {
+    std::vector<size_t> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+std::vector<float> Configuration::getFloatVector(const std::string &name, const std::vector<float>& defaultValue) const {
+    std::vector<float> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+std::vector<double> Configuration::getDoubleVector(const std::string &name, const std::vector<double>& defaultValue) const {
+    std::vector<double> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+std::vector<std::string> Configuration::getStringVector(const std::string &name, const std::vector<std::string>& defaultValue) const {
+    std::vector<std::string> result;
+    _getWithDefault(name, result, defaultValue);
+    return result;
+}
+
+void Configuration::json( JSON& s ) const
+{
+    s << root_;
+}
+
+
 //----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
diff --git a/eckit/src/eckit/config/Configuration.h b/eckit/src/eckit/config/Configuration.h
index b4848f5..000160c 100644
--- a/eckit/src/eckit/config/Configuration.h
+++ b/eckit/src/eckit/config/Configuration.h
@@ -26,6 +26,7 @@ namespace eckit {
 //----------------------------------------------------------------------------------------------------------------------
 
 class LocalConfiguration;
+class JSON;
 
 class Configuration : public Parametrisation {
 
@@ -35,6 +36,10 @@ class Configuration : public Parametrisation {
 
 public: // methods
 
+    // -- Destructor
+
+    virtual ~Configuration();
+
     // Fast access, will throw an exception
 
     bool getBool(const std::string &name) const;
@@ -45,6 +50,13 @@ public: // methods
     double getDouble(const std::string &name) const;
     std::string getString(const std::string &name) const;
 
+    std::vector<int> getIntVector(const std::string &name) const;
+    std::vector<long> getLongVector(const std::string &name) const;
+    std::vector<size_t> getUnsignedVector(const std::string &name) const;
+    std::vector<float> getFloatVector(const std::string &name) const;
+    std::vector<double> getDoubleVector(const std::string &name) const;
+    std::vector<std::string> getStringVector(const std::string &name) const;
+
     // Access with default in case of falure
 
     bool getBool(const std::string &name, const bool& defaultValue) const;
@@ -55,13 +67,12 @@ public: // methods
     double getDouble(const std::string &name, const double& defaultValue) const;
     std::string getString(const std::string &name, const std::string& defaultValue) const;
 
-
-    std::vector<int> getIntVector(const std::string &name) const;
-    std::vector<long> getLongVector(const std::string &name) const;
-    std::vector<size_t> getUnsignedVector(const std::string &name) const;
-    std::vector<float> getFloatVector(const std::string &name) const;
-    std::vector<double> getDoubleVector(const std::string &name) const;
-    std::vector<std::string> getStringVector(const std::string &name) const;
+    std::vector<int> getIntVector(const std::string &name, const std::vector<int>& defaultValue) const;
+    std::vector<long> getLongVector(const std::string &name, const std::vector<long>& defaultValue) const;
+    std::vector<size_t> getUnsignedVector(const std::string &name, const std::vector<size_t>& defaultValue) const;
+    std::vector<float> getFloatVector(const std::string &name, const std::vector<float>& defaultValue) const;
+    std::vector<double> getDoubleVector(const std::string &name, const std::vector<double>& defaultValue) const;
+    std::vector<std::string> getStringVector(const std::string &name, const std::vector<std::string>& defaultValue) const;
 
     // Access to LocalConfiguration
 
@@ -77,13 +88,18 @@ public: // methods
 
     virtual bool get(const std::string &name, std::string &value) const;
     virtual bool get(const std::string &name, bool &value) const;
+    virtual bool get(const std::string &name, int &value) const;
     virtual bool get(const std::string &name, long &value) const;
+    virtual bool get(const std::string &name, size_t &value) const;
+    virtual bool get(const std::string &name, float &value) const;
     virtual bool get(const std::string &name, double &value) const;
 
+    virtual bool get(const std::string &name, std::vector<int> &value) const;
     virtual bool get(const std::string &name, std::vector<long> &value) const;
+    virtual bool get(const std::string &name, std::vector<size_t> &value) const;
+    virtual bool get(const std::string &name, std::vector<float> &value) const;
     virtual bool get(const std::string &name, std::vector<double> &value) const;
     virtual bool get(const std::string &name, std::vector<std::string> &value) const;
-    virtual bool get(const std::string &name, size_t &value) const;
 
     bool get(const std::string &name, std::vector<LocalConfiguration>&) const;
     bool get(const std::string &name, LocalConfiguration&) const;
@@ -101,8 +117,6 @@ protected: // methods
 
     Configuration &operator=(const Configuration &);
 
-    virtual ~Configuration();
-
     Value lookUp(const std::string&) const;
     Value lookUp(const std::string &, bool &) const;
 
@@ -115,6 +129,9 @@ protected: // members
 
 private: // methods
 
+    void json(JSON& s) const;
+    friend JSON& operator<<(JSON& s, const Configuration& v) { v.json(s); return s; }
+
     template <class T>
     void _get(const std::string&, T&) const;
 
diff --git a/eckit/src/eckit/config/Configured.h b/eckit/src/eckit/config/Configured.h
index bfbea13..cc9ae99 100644
--- a/eckit/src/eckit/config/Configured.h
+++ b/eckit/src/eckit/config/Configured.h
@@ -48,13 +48,19 @@ class Configured {
 
     virtual Configured& set(const std::string &name, const std::string &value) = 0;
     virtual Configured& set(const std::string &name, const char *value) = 0;
+    virtual Configured& set(const std::string &name, float value) = 0;
     virtual Configured& set(const std::string &name, double value) = 0;
+    virtual Configured& set(const std::string &name, int value) = 0;
     virtual Configured& set(const std::string &name, long value) = 0;
     virtual Configured& set(const std::string &name, bool value) = 0;
     virtual Configured& set(const std::string& name, size_t value) = 0;
 
+    virtual Configured& set(const std::string& name, const std::vector<int>& value) = 0;
     virtual Configured& set(const std::string& name, const std::vector<long>& value) = 0;
+    virtual Configured& set(const std::string& name, const std::vector<size_t>& value) = 0;
+    virtual Configured& set(const std::string& name, const std::vector<float>& value) = 0;
     virtual Configured& set(const std::string& name, const std::vector<double>& value) = 0;
+    virtual Configured& set(const std::string& name, const std::vector<std::string>& value) = 0;
 
 // -- Overridden methods
     // None
diff --git a/eckit/src/eckit/config/JSONConfiguration.cc b/eckit/src/eckit/config/JSONConfiguration.cc
deleted file mode 100644
index 7bb2622..0000000
--- a/eckit/src/eckit/config/JSONConfiguration.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-/// @author Baudouin Raoult
-/// @date Jul 2015
-
-#include "eckit/config/JSONConfiguration.h"
-
-
-// #include <iostream>
-// #include <limits>
-// #include "eckit/filesystem/PathName.h"
-#include "eckit/parser/JSONParser.h"
-// #include "mir/util/Parser.h"
-// #include "eckit/parser/Tokenizer.h"
-
-
-namespace eckit {
-
-static Value root(std::istream &in) {
-    ASSERT(in);
-    eckit::JSONParser parser(in);
-    Value root = parser.parse();
-    return root;
-}
-
-
-static Value root(const std::string &path) {
-    std::ifstream in(path.c_str());
-    if(!in)
-        throw eckit::CantOpenFile(path);
-    return root(in);
-}
-
-
-static Value root(Stream& in) {
-    std::string val;
-    in.next(val);
-    std::istringstream iss(val);
-    return root(iss);
-}
-
-
-JSONConfiguration::JSONConfiguration(const eckit::PathName &path, char separator):
-    Configuration(root(path), separator),
-    path_(path) {
-}
-
-JSONConfiguration::JSONConfiguration(std::istream &in, char separator):
-    Configuration(root(in), separator),
-    path_("<istream>") {
-}
-
-JSONConfiguration::JSONConfiguration(Stream& in, char separator)
-    : Configuration(root(in), separator),
-      path_("<Stream>") {}
-
-JSONConfiguration::~JSONConfiguration() {
-}
-
-void JSONConfiguration::print(std::ostream &out) const {
-    out << "JSONConfiguration[path=" << path_ << ", root=" << root_ << "]";
-}
-
-} // namespace eckit
-
diff --git a/eckit/src/eckit/config/JSONConfiguration.h b/eckit/src/eckit/config/JSONConfiguration.h
index 3daef61..54a72c9 100644
--- a/eckit/src/eckit/config/JSONConfiguration.h
+++ b/eckit/src/eckit/config/JSONConfiguration.h
@@ -15,102 +15,13 @@
 #ifndef eckit_JSONConfiguration_H
 #define eckit_JSONConfiguration_H
 
-#include "eckit/config/Configuration.h"
+#warning eckit::JSONConfiguration is deprecated in favour of eckit::YAMLConfiguration found in header "eckit/config/YAMLConfiguration.h", as a drop-in replacement.
 
+#include "eckit/config/YAMLConfiguration.h"
 
 namespace eckit {
 
-class PathName;
-class Stream;
-
-class JSONConfiguration : public Configuration {
-  public:
-
-    // -- Exceptions
-    // None
-
-    // -- Contructors
-
-    JSONConfiguration(const eckit::PathName &path, char separator = '.');
-    JSONConfiguration(std::istream &, char separator = '.');
-    JSONConfiguration(Stream&, char separator = '.');
-
-    virtual ~JSONConfiguration(); // Change to virtual if base class
-
-    // -- Convertors
-    // None
-
-    // -- Operators
-    // None
-
-    // -- Methods
-
-
-    // -- Overridden methods
-
-
-    // -- Class members
-    // None
-
-    // -- Class methods
-
-
-  protected:
-
-
-    // -- Destructor
-
-    // -- Members
-    // None
-
-    // -- Methods
-
-    // void print(ostream&) const; // Change to virtual if base class
-
-    // -- Overridden methods
-    // None
-
-    // -- Class members
-    // None
-
-    // -- Class methods
-    // None
-
-  private:
-
-    // No copy allowed
-
-    JSONConfiguration(const JSONConfiguration &);
-    JSONConfiguration &operator=(const JSONConfiguration &);
-
-    // Make private so no one modifies it
-
-    // -- Members
-
-    std::string path_;
-
-
-    // -- Methods
-
-
-    // -- Overridden methods
-
-    // From MIRParametrisation
-    virtual void print(std::ostream &) const;
-
-    // -- Class members
-    // None
-
-    // -- Class methods
-    // None
-
-    // -- Friends
-
-    //friend ostream& operator<<(ostream& s,const JSONConfiguration& p)
-    //  { p.print(s); return s; }
-
-};
-
+typedef YAMLConfiguration JSONConfiguration;
 
 } // namespace eckit
 #endif
diff --git a/eckit/src/eckit/config/LibEcKit.cc b/eckit/src/eckit/config/LibEcKit.cc
index ff2d189..ff67710 100644
--- a/eckit/src/eckit/config/LibEcKit.cc
+++ b/eckit/src/eckit/config/LibEcKit.cc
@@ -12,26 +12,45 @@
 /// @author Tiago Quintino
 /// @date   August 2016
 
+#include <stdlib.h>
+
 #include <algorithm>
 #include <string>
 
 #include "eckit/config/LibEcKit.h"
 
 #include "eckit/eckit_version.h"
+#include "eckit/thread/AutoLock.h"
 
 namespace eckit {
 
 //----------------------------------------------------------------------------------------------------------------------
 
-static LibEcKit libeckit;
+REGISTER_LIBRARY(LibEcKit);
 
-LibEcKit::LibEcKit() : Library("eckit") {}
+LibEcKit::LibEcKit() :
+    Library("eckit"),
+    abort_handler_(&(::abort))
+{
+}
 
-const LibEcKit& LibEcKit::instance()
+LibEcKit& LibEcKit::instance()
 {
+    static LibEcKit libeckit;
     return libeckit;
 }
 
+void LibEcKit::setAbortHandler(abort_handler_t h)
+{
+    AutoLock<LibEcKit> lock(*this);
+    if(h) { abort_handler_ = h; }
+}
+
+void LibEcKit::abort()
+{
+    abort_handler_();
+}
+
 const void* LibEcKit::addr() const { return this; }
 
 std::string LibEcKit::version() const { return eckit_version_str(); }
diff --git a/eckit/src/eckit/config/LibEcKit.h b/eckit/src/eckit/config/LibEcKit.h
index 3ecc7d0..f515a33 100644
--- a/eckit/src/eckit/config/LibEcKit.h
+++ b/eckit/src/eckit/config/LibEcKit.h
@@ -21,14 +21,21 @@ namespace eckit {
 
 //----------------------------------------------------------------------------------------------------------------------
 
+typedef void (*abort_handler_t)();
+
 class LibEcKit : public eckit::system::Library {
-public:
+
+public: // methods
 
     LibEcKit();
 
-    static const LibEcKit& instance();
+    static LibEcKit& instance();
+
+    void setAbortHandler(abort_handler_t h);
 
-protected:
+    void abort();
+
+protected: // methods
 
     const void* addr() const;
 
@@ -36,6 +43,9 @@ protected:
 
     virtual std::string gitsha1(unsigned int count) const;
 
+private: // members
+
+    abort_handler_t abort_handler_;
 };
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/config/LocalConfiguration.cc b/eckit/src/eckit/config/LocalConfiguration.cc
index f66e474..bce5259 100644
--- a/eckit/src/eckit/config/LocalConfiguration.cc
+++ b/eckit/src/eckit/config/LocalConfiguration.cc
@@ -44,7 +44,7 @@ void LocalConfiguration::print(std::ostream &out) const {
     out << "]";
 }
 
-void LocalConfiguration::set(const std::vector<std::string> &path, size_t i, eckit::Value &root, const eckit::Value &value)  {
+void LocalConfiguration::setValue(const std::vector<std::string> &path, size_t i, eckit::Value &root, const eckit::Value &value)  {
     if (root.shared()) {
         // std::cout << "Clone " << root << std::endl;
         root = root.clone();
@@ -62,10 +62,10 @@ void LocalConfiguration::set(const std::vector<std::string> &path, size_t i, eck
     }
 
     eckit::Value &r = root.element(path[i]);
-    set(path, i + 1, r, value);
+    setValue(path, i + 1, r, value);
 }
 
-void LocalConfiguration::set(const std::string &s, const eckit::Value &value) {
+void LocalConfiguration::setValue(const std::string &s, const eckit::Value &value) {
 
     // std::cout << "---- " << s << " => " << value << std::endl;
 
@@ -73,38 +73,57 @@ void LocalConfiguration::set(const std::string &s, const eckit::Value &value) {
     std::vector<std::string> path;
     parse(s, path);
 
-    set(path, 0, root_, value);
+    setValue(path, 0, root_, value);
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string &s, int value)  {
+    setValue(s, eckit::Value(value));
+    return *this;
 }
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, long value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
     return *this;
 }
 
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, const char *value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
     return *this;
 }
 
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, const std::string &value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
+    return *this;
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string &s, float value)  {
+    setValue(s, eckit::Value(value));
     return *this;
 }
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, double value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
     return *this;
 }
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, bool value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
     return *this;
 }
 
 LocalConfiguration& LocalConfiguration::set(const std::string &s, size_t value)  {
-    set(s, eckit::Value(value));
+    setValue(s, eckit::Value(value));
+    return *this;
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vector<int>& value) {
+    ValueList values;
+    for (std::vector<int>::const_iterator v = value.begin(); v != value.end(); ++v) {
+        values.push_back(eckit::Value(*v));
+    }
+    setValue(s, values);
     return *this;
 }
 
@@ -113,7 +132,26 @@ LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vec
     for (std::vector<long>::const_iterator v = value.begin(); v != value.end(); ++v) {
         values.push_back(eckit::Value(*v));
     }
-    set(s, values);
+    setValue(s, values);
+    return *this;
+}
+
+
+LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vector<size_t>& value) {
+    ValueList values;
+    for (std::vector<size_t>::const_iterator v = value.begin(); v != value.end(); ++v) {
+        values.push_back(eckit::Value(*v));
+    }
+    setValue(s, values);
+    return *this;
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vector<float>& value) {
+    ValueList values;
+    for (std::vector<float>::const_iterator v = value.begin(); v != value.end(); ++v) {
+        values.push_back(eckit::Value(*v));
+    }
+    setValue(s, values);
     return *this;
 }
 
@@ -122,10 +160,35 @@ LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vec
     for (std::vector<double>::const_iterator v = value.begin(); v != value.end(); ++v) {
         values.push_back(eckit::Value(*v));
     }
-    set(s, values);
+    setValue(s, values);
+    return *this;
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vector<std::string>& value) {
+    ValueList values;
+    for (std::vector<std::string>::const_iterator v = value.begin(); v != value.end(); ++v) {
+        values.push_back(eckit::Value(*v));
+    }
+    setValue(s, values);
     return *this;
 }
 
+
+LocalConfiguration& LocalConfiguration::set(const std::string &s, const LocalConfiguration& value)  {
+    setValue(s, value.root_);
+    return *this;
+}
+
+LocalConfiguration& LocalConfiguration::set(const std::string& s, const std::vector<LocalConfiguration>& value) {
+    ValueList values;
+    for (std::vector<LocalConfiguration>::const_iterator v = value.begin(); v != value.end(); ++v) {
+        values.push_back(v->root_);
+    }
+    setValue(s, values);
+    return *this;
+}
+
+
 //----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
diff --git a/eckit/src/eckit/config/LocalConfiguration.h b/eckit/src/eckit/config/LocalConfiguration.h
index 95b11db..e94df63 100644
--- a/eckit/src/eckit/config/LocalConfiguration.h
+++ b/eckit/src/eckit/config/LocalConfiguration.h
@@ -41,13 +41,22 @@ public: // methods
 
     LocalConfiguration& set(const std::string &name, const std::string &value);
     LocalConfiguration& set(const std::string &name, const char *value);
-    LocalConfiguration& set(const std::string &name, double value);
-    LocalConfiguration& set(const std::string &name, long value);
     LocalConfiguration& set(const std::string &name, bool value);
+    LocalConfiguration& set(const std::string &name, int value);
+    LocalConfiguration& set(const std::string &name, long value);
     LocalConfiguration& set(const std::string& name, size_t value);
+    LocalConfiguration& set(const std::string &name, float value);
+    LocalConfiguration& set(const std::string &name, double value);
 
+    LocalConfiguration& set(const std::string& name, const std::vector<int>& value);
     LocalConfiguration& set(const std::string& name, const std::vector<long>& value);
+    LocalConfiguration& set(const std::string& name, const std::vector<size_t>& value);
+    LocalConfiguration& set(const std::string& name, const std::vector<float>& value);
     LocalConfiguration& set(const std::string& name, const std::vector<double>& value);
+    LocalConfiguration& set(const std::string& name, const std::vector<std::string>& value);
+
+    LocalConfiguration& set(const std::string& name, const LocalConfiguration& value);
+    LocalConfiguration& set(const std::string& name, const std::vector<LocalConfiguration>& value);
 
 protected:
 
@@ -60,8 +69,8 @@ protected:
 
 private:
 
-    void set(const std::vector<std::string> &path, size_t i, Value &root, const Value &value);
-    void set(const std::string &s, const Value &value);
+    void setValue(const std::vector<std::string> &path, size_t i, Value &root, const Value &value);
+    void setValue(const std::string &s, const Value &value);
 
 };
 
diff --git a/eckit/src/eckit/config/Parametrisation.h b/eckit/src/eckit/config/Parametrisation.h
index 9ef2535..0a4e7be 100644
--- a/eckit/src/eckit/config/Parametrisation.h
+++ b/eckit/src/eckit/config/Parametrisation.h
@@ -32,12 +32,18 @@ public: // methods
 
     virtual bool get(const std::string& name, std::string& value) const = 0;
     virtual bool get(const std::string& name, bool& value) const = 0;
+    virtual bool get(const std::string& name, int& value) const = 0;
     virtual bool get(const std::string& name, long& value) const = 0;
     virtual bool get(const std::string& name, size_t& value) const = 0;
+    virtual bool get(const std::string& name, float& value) const = 0;
     virtual bool get(const std::string& name, double& value) const = 0;
 
+    virtual bool get(const std::string& name, std::vector<int>& value) const = 0;
     virtual bool get(const std::string& name, std::vector<long>& value) const = 0;
+    virtual bool get(const std::string& name, std::vector<size_t>& value) const = 0;
+    virtual bool get(const std::string& name, std::vector<float>& value) const = 0;
     virtual bool get(const std::string& name, std::vector<double>& value) const = 0;
+    virtual bool get(const std::string& name, std::vector<std::string>& value) const = 0;
 
 };
 
diff --git a/eckit/src/eckit/config/Resource.cc b/eckit/src/eckit/config/Resource.cc
deleted file mode 100755
index 4a73987..0000000
--- a/eckit/src/eckit/config/Resource.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (C) Copyright 1996-2012 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-
-#include "eckit/config/Resource.h"
-#include "eckit/utils/Translator.h"
-#include "eckit/parser/Tokenizer.h"
-
-namespace eckit {
-template<class T> void Resource<T>::setValue(const std::string& s)
-{
-    value_ = Translator<std::string, T>()(s);
-}
-
-template<class T> std::string Resource<T>::getValue() const
-{
-    return Translator<T, std::string>()(value_);
-}
-
-} // namespace
diff --git a/eckit/src/eckit/config/Resource.h b/eckit/src/eckit/config/Resource.h
index 22440b5..7d4aee7 100644
--- a/eckit/src/eckit/config/Resource.h
+++ b/eckit/src/eckit/config/Resource.h
@@ -8,7 +8,6 @@
  * does it submit to any jurisdiction.
  */
 
-/// @file Log.h
 /// @author Baudouin Raoult
 /// @author Tiago Quintino
 /// @date May 1996
@@ -18,104 +17,106 @@
 
 #include <string>
 
-#include "eckit/memory/NonCopyable.h"
-#include "eckit/utils/Translator.h"
+#include "eckit/config/ResourceBase.h"
 
 namespace eckit {
 
-class Configurable;
-class Url;
 
-class ResourceBase : private NonCopyable {
-public:
+//----------------------------------------------------------------------------------------------------------------------
 
-// -- Contructors
-
-    ResourceBase(Configurable* owner, const std::string& str);
+template<class T>
+class Resource : public ResourceBase {
 
-// -- Destructor
+public: // methods
 
-    virtual ~ResourceBase();
+    // Standalone
 
-// -- Methods
+    Resource(const std::string& str, const T& value):
+        ResourceBase(0, str),     value_(value) {}
 
-    void reset()            { inited_ = false;   }
-    void dump(std::ostream&) const;
-    void html(std::ostream&, Url&);
+    // Part of a configurable
 
-    std::string name() const;
+    Resource(Configurable* owner, const std::string& str, const T& value):
+        ResourceBase(owner, str), value_(value) {}
 
-protected:
+    Resource(const std::string& str,const std::string& value, bool):
+        ResourceBase(0,str),     value_(eckit::Translator<std::string,T>()(value)) {}
 
-// -- Methods
+// -- Convertors
 
-    void init();
+    operator const T&()  const { const_cast<Resource<T>*>(this)->init(); return value_; }
 
-private:
+private: // members
 
-// -- Members
+    T value_;
 
-    bool           inited_;
-    Configurable*  owner_;
-    std::string         name_;        // In the config file
-    std::string         environment_; // In the environment variables
-    std::string         options_;     // For the command line options
+    // From ResourceBase
 
-// -- Methods
+    virtual void setValue(const std::string& s)
+    {
+        value_ = Translator<std::string, T>()(s);
+    }
 
-    virtual void setValue(const std::string&) = 0;
-    virtual std::string getValue() const      = 0;
+    virtual std::string getValue() const
+    {
+        return Translator<T, std::string>()(value_);
+    }
 
 };
 
+template<class T>
+std::ostream& operator<<(std::ostream& os, const Resource<T>& r) {
+    os << static_cast<const T&>(r);
+    return os;
+}
 
+//----------------------------------------------------------------------------------------------------------------------
 
 
-template<class T> class Resource : public ResourceBase {
-public:
+template<class T, class LIB>
+class LibResource : public ResourceBase {
 
-// -- Contructors
+public: // methods
 
-    // Standalone
+    LibResource(const std::string& str, const T& value) : ResourceBase(0, str), value_(value) {}
 
-    Resource(const std::string& str, const T& value):
-        ResourceBase(0, str),     value_(value) {}
+    operator const T&()  const { const_cast<LibResource<T,LIB>*>(this)->init(); return value_; }
 
-    // Part of a configurable
-
-    Resource(Configurable* owner, const std::string& str, const T& value):
-        ResourceBase(owner, str), value_(value) {}
-
-    Resource(const std::string& str,const std::string& value, bool):
-        ResourceBase(0,str),     value_(eckit::Translator<std::string,T>()(value)) {}
+    friend std::ostream& operator<< (std::ostream& os, const LibResource<T,LIB>& r) {
+        os << static_cast<const T&>(r);
+        return os;
+    }
 
-// -- Convertors
+private: // members
 
-    operator const T&()  const { const_cast<Resource<T>*>(this)->init(); return value_;        }
-
-private:
+    T value_;
 
-// -- Members
+    // From ResourceBase
 
-    T value_;
+    virtual void setValue(const std::string& s)
+    {
+        value_ = Translator<std::string, T>()(s);
+    }
 
-// -- Overridden methods
+    virtual std::string getValue() const
+    {
+        return Translator<T, std::string>()(value_);
+    }
 
-    // From ResourceBase
+    virtual bool setFromConfigFile() {
 
-    virtual void setValue(const std::string&);
-    virtual std::string getValue() const;
+        std::string value;
 
+        if(LIB::instance().configuration().get(name(), value)) {
+            setValue(value);
+            return true;
+        }
+        return false;
+    }
 };
 
-template<class T>
-std::ostream& operator<<(std::ostream& os, const Resource<T>& r) {
-    os << static_cast<const T&>(r);
-    return os;
-}
-
-}
+//----------------------------------------------------------------------------------------------------------------------
 
-#include "eckit/config/Resource.cc"
+} // namespace eckit
 
 #endif
diff --git a/eckit/src/eckit/config/ResourceBase.cc b/eckit/src/eckit/config/ResourceBase.cc
index f86d3d4..218f96c 100644
--- a/eckit/src/eckit/config/ResourceBase.cc
+++ b/eckit/src/eckit/config/ResourceBase.cc
@@ -17,8 +17,8 @@
 namespace eckit {
 
 ResourceBase::ResourceBase(Configurable* owner, const std::string& str):
-    inited_(false),
-    owner_(owner)
+    owner_(owner),
+    inited_(false)
 {
     if (owner_) owner_->add(this);
 
@@ -30,10 +30,9 @@ ResourceBase::ResourceBase(Configurable* owner, const std::string& str):
         char   x  = *p;
         int len   = 0;
 
-        switch (x)
-        {
-        case '$': s = &environment_; break;
-        case '-': s = &options_;     break;
+        switch (x) {
+            case '$': s = &environment_; break;
+            case '-': s = &options_;     break;
         }
 
         *s = p;
@@ -56,6 +55,24 @@ ResourceBase::~ResourceBase()
     if (owner_) owner_->remove(this);
 }
 
+bool ResourceBase::setFromConfigFile()
+{
+    bool found = false;
+
+    std::string s;
+
+    if (owner_)
+        found = ResourceMgr::lookUp(owner_->kind(), owner_->name(), name_, s);
+    else
+        found = ResourceMgr::lookUp("", "", name_, s);
+
+    if (found) {
+        setValue(s);
+    }
+
+    return found;
+}
+
 void ResourceBase::init()
 {
     if (inited_) return;
@@ -93,18 +110,10 @@ void ResourceBase::init()
 
     if (name_ != "")
     {
-        bool found = false;
-        std::string s;
-
-        if (owner_)
-            found = ResourceMgr::lookUp(owner_->kind(), owner_->name(), name_, s);
-        else
-            found = ResourceMgr::lookUp("", "", name_, s);
-
-        if (found) setValue(s);
-
-        inited_ = true;
-        return;
+        if(setFromConfigFile()) {
+            inited_ = true;
+            return;
+        }
     }
 
     // Else use default. This is done in Resource
diff --git a/eckit/src/eckit/config/ResourceBase.h b/eckit/src/eckit/config/ResourceBase.h
new file mode 100644
index 0000000..f6f1d60
--- /dev/null
+++ b/eckit/src/eckit/config/ResourceBase.h
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Baudouin Raoult
+/// @author Tiago Quintino
+/// @date May 1996
+
+#ifndef eckit_config_ResourceBase_h
+#define eckit_config_ResourceBase_h
+
+#include <string>
+
+#include "eckit/memory/NonCopyable.h"
+#include "eckit/utils/Translator.h"
+#include "eckit/parser/Tokenizer.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class Configurable;
+class Url;
+
+class ResourceBase : private NonCopyable {
+
+public: // methods
+
+    ResourceBase(Configurable* owner, const std::string& str);
+
+    virtual ~ResourceBase();
+
+    void reset() { inited_ = false; }
+    void dump(std::ostream&) const;
+    void html(std::ostream&, Url&);
+
+    std::string name() const;
+
+protected: // methods
+
+    void init();
+
+    virtual bool setFromConfigFile();
+
+private: // members
+
+    Configurable*       owner_;
+
+    std::string         name_;        // In the config file
+    std::string         environment_; // In the environment variables
+    std::string         options_;     // For the command line options
+
+    bool                inited_;
+
+private: // methods
+
+    virtual void setValue(const std::string&) = 0;
+    virtual std::string getValue() const      = 0;
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/config/YAMLConfiguration.cc b/eckit/src/eckit/config/YAMLConfiguration.cc
new file mode 100644
index 0000000..68216a4
--- /dev/null
+++ b/eckit/src/eckit/config/YAMLConfiguration.cc
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Baudouin Raoult
+/// @date Jul 2015
+
+#include "eckit/config/YAMLConfiguration.h"
+#include "eckit/parser/YAMLParser.h"
+
+namespace eckit {
+
+static Value root(std::istream &in) {
+    ASSERT(in);
+    eckit::YAMLParser parser(in);
+    Value root = parser.parse();
+    return root;
+}
+
+
+static Value root(const std::string &path) {
+    std::ifstream in(path.c_str());
+    if(!in)
+        throw eckit::CantOpenFile(path);
+    return root(in);
+}
+
+static Value root(Stream& in) {
+    std::string val;
+    in.next(val);
+    std::istringstream iss(val);
+    return root(iss);
+}
+
+static Value root_from_string(const std::string &str) {
+    std::istringstream in(str);
+    return root(in);
+}
+
+YAMLConfiguration::YAMLConfiguration(const PathName &path, char separator):
+    Configuration(root(path), separator),
+    path_(path) {
+}
+
+YAMLConfiguration::YAMLConfiguration(std::istream &in, char separator):
+    Configuration(root(in), separator),
+    path_("<istream>") {
+}
+
+YAMLConfiguration::YAMLConfiguration(Stream& in, char separator):
+    Configuration(root(in), separator),
+    path_("<Stream>") {
+}
+
+YAMLConfiguration::YAMLConfiguration(const std::string& str, char separator):
+    Configuration(root_from_string(str), separator),
+    path_("<string>") {
+}
+
+YAMLConfiguration::YAMLConfiguration(const SharedBuffer& buffer, char separator):
+    Configuration(root_from_string(buffer.str()), separator),
+    path_("<Buffer>") {
+}
+
+YAMLConfiguration::~YAMLConfiguration() {
+}
+
+void YAMLConfiguration::print(std::ostream &out) const {
+    out << "YAMLConfiguration[path=" << path_ << ", root=" << root_ << "]";
+}
+
+} // namespace eckit
+
diff --git a/eckit/src/eckit/config/YAMLConfiguration.h b/eckit/src/eckit/config/YAMLConfiguration.h
new file mode 100644
index 0000000..995fc03
--- /dev/null
+++ b/eckit/src/eckit/config/YAMLConfiguration.h
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Baudouin Raoult
+/// @date JUl 2015
+
+
+#ifndef eckit_YAMLConfiguration_H
+#define eckit_YAMLConfiguration_H
+
+#include "eckit/config/Configuration.h"
+#include "eckit/io/Buffer.h"
+#include "eckit/memory/NonCopyable.h"
+
+namespace eckit {
+
+class PathName;
+class Stream;
+
+class YAMLConfiguration :
+        public Configuration,
+        private eckit::NonCopyable {
+
+public:
+
+    YAMLConfiguration(const PathName &path, char separator = '.');
+    YAMLConfiguration(std::istream &, char separator = '.');
+    YAMLConfiguration(Stream&, char separator = '.');
+    YAMLConfiguration(const std::string&, char separator = '.');
+    YAMLConfiguration(const SharedBuffer&, char separator = '.');
+
+    virtual ~YAMLConfiguration();
+
+private: // members
+
+    std::string path_;
+
+    virtual void print(std::ostream &) const;
+
+};
+
+} // namespace eckit
+
+#endif
+
diff --git a/eckit/src/eckit/container/BloomFilter.cc b/eckit/src/eckit/container/BloomFilter.cc
new file mode 100755
index 0000000..6788d08
--- /dev/null
+++ b/eckit/src/eckit/container/BloomFilter.cc
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+
+#include "eckit/container/BloomFilter.h"
+#include "eckit/exception/Exceptions.h"
+#include "eckit/utils/MD5.h"
+
+#include <string>
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+
+template <typename T>
+BloomFilter<T>::BloomFilter(size_t size) :
+    size_(size),
+    entries_(0),
+    data_(elementCount(size), 0) {}
+
+
+template <typename T>
+BloomFilter<T>::~BloomFilter() {}
+
+
+template <typename T>
+bool BloomFilter<T>::empty() const {
+    return (entries_ == 0);
+}
+
+
+template <typename T>
+void BloomFilter<T>::insert(const T& value) {
+
+    size_t bit_index = index(value);
+    size_t elem = bit_index / sizeof(data_type);
+    size_t offset = bit_index % sizeof(data_type);
+
+    data_[elem] |= (data_type(1) << offset);
+    entries_++;
+}
+
+
+template <typename T>
+bool BloomFilter<T>::contains(const T& value) const {
+
+    size_t bit_index = index(value);
+    size_t elem = bit_index / sizeof(data_type);
+    size_t offset = bit_index % sizeof(data_type);
+
+    return !((data_[elem] & (data_type(1) << offset)) == 0);
+}
+
+
+template <typename T>
+void BloomFilter<T>::print(std::ostream& s) const {
+    s << "BloomFilter(size=" << size_ << ",entries=" << entries_ << ")";
+}
+
+
+template<typename T>
+size_t BloomFilter<T>::elementCount(size_t nbits) {
+    return (nbits == 0) ? 0 : ((nbits - 1) / sizeof(data_type)) + 1;
+}
+
+
+template<typename T>
+size_t BloomFilter<T>::index(const T& value) const {
+
+    // n.b. We could use any other hash, but MD5 is already in here.
+
+    MD5 md5;
+    unsigned char md5_buf[16];
+    md5.add(value);
+    md5.numericalDigest(md5_buf);
+
+    // Take the modules incrementally
+
+    size_t idx = 0;
+    for (size_t i = 0; i < sizeof(md5_buf); i++)
+        idx = ((idx * 256) + md5_buf[i]) % size_;
+
+    return idx;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/container/BloomFilter.h b/eckit/src/eckit/container/BloomFilter.h
new file mode 100755
index 0000000..a6c9bbb
--- /dev/null
+++ b/eckit/src/eckit/container/BloomFilter.h
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @file trie.h
+/// @author Baudouin Raoult
+/// @author Simon Smart
+/// @date March 2017
+
+
+#ifndef eckit_containers_BloomFilter_H
+#define eckit_containers_BloomFilter_H
+
+#include "eckit/memory/NonCopyable.h"
+
+#include <vector>
+#include <ostream>
+
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+template <typename T>
+class BloomFilter : private NonCopyable {
+
+public: // types
+
+    typedef unsigned long long data_type;
+
+public: // methods
+
+    BloomFilter(size_t size);
+    ~BloomFilter();
+
+    bool empty() const;
+    void insert(const T& value);
+    bool contains(const T& value) const;
+
+protected: // methods
+
+	void print(std::ostream&) const; 	
+
+private: // members
+
+    static size_t elementCount(size_t nbits);
+
+    /// Which bit should we be considering?
+    size_t index(const T& value) const;
+
+private: // members
+
+    size_t size_;
+    size_t entries_;
+
+    // n.b. We don't use std::vector<bool>, as it doesn't behave like a std::vector.
+    //      Better to be explicit
+
+    std::vector<data_type> data_;
+
+private: // friends
+
+    friend std::ostream& operator<<(std::ostream& s, const BloomFilter<T>& p) {
+        p.print(s); return s;
+    }
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+
+#include "BloomFilter.cc"
+
+#endif // eckit_containers_BloomFilter_H
diff --git a/eckit/src/eckit/container/CacheManager.h b/eckit/src/eckit/container/CacheManager.h
index d0468ff..0c27bd3 100644
--- a/eckit/src/eckit/container/CacheManager.h
+++ b/eckit/src/eckit/container/CacheManager.h
@@ -29,6 +29,9 @@
 #include "eckit/os/AutoUmask.h"
 #include "eckit/filesystem/PathName.h"
 #include "eckit/memory/NonCopyable.h"
+#include "eckit/parser/Tokenizer.h"
+#include "eckit/parser/StringTools.h"
+#include "eckit/filesystem/PathExpander.h"
 
 namespace eckit {
 
@@ -100,10 +103,24 @@ template<class Traits>
 CacheManager<Traits>::CacheManager(const std::string& loaderName, const std::string& roots, bool throwOnCacheMiss) :
     CacheManagerBase(loaderName),
     throwOnCacheMiss_(throwOnCacheMiss) {
+
     eckit::Tokenizer parse(":");
     std::vector<std::string> v;
     parse(roots, v);
-    std::copy(v.begin(), v.end(), std::back_inserter(roots_));
+
+    for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i) {
+
+        std::string path = *i;
+
+        // entries with e.g. {CWDFS}/cache will be expanded with PathExpander factory CWDFS
+
+        StringList vl = StringTools::listVariables(path);
+        for(StringList::const_iterator var = vl.begin(); var != vl.end(); ++var) {
+            path = PathExpander::expand(*var, path);
+        }
+
+        roots_.push_back(path);
+    }
 
     Log::debug<LibEcKit>() << "CacheManager roots " << roots_ << std::endl;
 
diff --git a/eckit/src/eckit/container/Trie.cc b/eckit/src/eckit/container/Trie.cc
new file mode 100755
index 0000000..2a609be
--- /dev/null
+++ b/eckit/src/eckit/container/Trie.cc
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+
+#include "eckit/container/Trie.h"
+#include "eckit/exception/Exceptions.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+
+template<class T>
+Trie<T>::Trie() :
+    from_(0),
+    set_(0),
+    kids_(0) {}
+
+
+template<class T>
+Trie<T>::~Trie() {
+
+    for (size_t i = 0; i < kids_.size(); i++) {
+        if (kids_[i])
+            delete(kids_[i]);
+	}
+}
+
+template<class T>
+void Trie<T>::insert(const std::string& key, T value)
+{
+	const char* k = key.c_str();
+    Trie<T>* x = find((unsigned char*)k, true);
+    x->value_ = value;
+    x->set_ = true;
+}
+
+template<class T>
+void Trie<T>::remove(const std::string& key) {
+    const char* k = key.c_str();
+    remove((unsigned char*)k);
+}
+
+template<class T>
+T* Trie<T>::find(const std::string& key) const
+{
+	const char* k = key.c_str();
+    Trie<T>* x = const_cast<Trie<T>*>(this)->find((unsigned char*)k, false);
+    return (x && x->set_) ? &x->value_ : 0;
+}
+
+template<class T>
+bool Trie<T>::contains(const std::string& key) const {
+    return find(key) != 0;
+}
+
+template<class T>
+bool Trie<T>::remove(const unsigned char* key)
+{
+	if(*key == 0) { 
+        set_ = 0;
+        return (kids_.size() == 0); // Remove me if size if 0
+	}
+
+    int pos = int(*key) - int(from_);
+
+    if( pos >= 0 && pos  < int(kids_.size()) && kids_[pos])
+        if(kids_[pos]->remove(key+1))
+        {
+            delete kids_[pos];
+            kids_[pos] = 0;
+
+			// May be we should shrink the list here
+
+            for (size_t i = 0; i < kids_.size(); i++)
+                if(kids_[i] != 0)
+                    return false;
+
+            // Delete me if I am not also a value
+            kids_.clear();
+            return !set_;
+		}
+
+	return false;
+}
+
+template<class T>
+Trie<T>* Trie<T>::find(const unsigned char* key, bool make)
+{
+	if(*key == 0) 
+		return this;
+
+    int pos = int(*key) - int(from_);
+
+    if( pos >= 0 && pos  < int(kids_.size()) && kids_[pos])
+        return kids_[pos]->find(key+1, make);
+
+	if(make) {
+
+        // If outside of range, we need to expand the storage vector.
+        if(pos < 0 || pos >= int(kids_.size())) {
+
+			int from = 0;
+
+            size_t sz;
+            if(kids_.empty()) // First in
+			{
+                sz = 1;
+				from_ = *key;
+			}
+			else if(pos<0)  // Insert before
+			{ 
+                sz = kids_.size() - pos;
+                from_  = *key;
+				from   = -pos;
+			}
+			else // Insert after
+			{
+                sz = pos+1;
+            }
+
+            std::vector<Trie<T>*> kids(sz, 0);
+            std::copy(kids_.begin(), kids_.end(), kids.begin()+from);
+
+			kids_ = kids;
+			pos = int(*key) - int(from_);
+		}
+
+
+        ASSERT(kids_[pos] == 0);
+        Trie<T>* k = new Trie<T>;
+        kids_[pos] = k;
+        return k->find(key+1, make);
+	}
+
+	return 0;
+}
+
+template<class T>
+void Trie<T>::print(std::ostream& s) const
+{
+    if (set_)
+        s << "(" << value_ << ")";
+
+    for (size_t i = 0; i < kids_.size(); i++) {
+		if(kids_[i])
+		{
+			s << (unsigned char)(from_ + i) << ' ';
+			kids_[i]->print(s);
+        }
+    }
+
+    if (kids_.empty())
+        s << std::endl;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/container/Trie.h b/eckit/src/eckit/container/Trie.h
new file mode 100755
index 0000000..44aa8ea
--- /dev/null
+++ b/eckit/src/eckit/container/Trie.h
@@ -0,0 +1,80 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @file trie.h
+/// @author Baudouin Raoult
+/// @author Simon Smart
+/// @date March 2017
+
+
+#ifndef eckit_containers_Trie_H
+#define eckit_containers_Trie_H
+
+#include "eckit/memory/NonCopyable.h"
+#include "eckit/memory/ScopedPtr.h"
+
+#include <vector>
+#include <ostream>
+
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+template<class T>
+class Trie : private NonCopyable {
+
+public: // methods
+
+    Trie();
+    ~Trie();
+
+    bool empty() const { return kids_.empty() && !set_; }
+
+    void insert(const std::string& key, T value);
+    void remove(const std::string& key);
+    bool contains(const std::string& key) const;
+    T*   find(const std::string& key) const;
+
+protected: // methods
+
+	void print(std::ostream&) const; 	
+
+private: // members
+
+    Trie<T>* find(const unsigned char*, bool);
+
+    bool remove(const unsigned char* key);
+
+private: // members
+
+	unsigned short   from_;
+
+    /// Do we have a value in the value_ (or is just uninintialised POD/default constructed).
+    bool set_;
+
+    std::vector<Trie<T>*> kids_;
+    T value_;
+
+private: // friends
+
+    friend std::ostream& operator<<(std::ostream& s, const Trie<T>& p) {
+        p.print(s); return s;
+    }
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+
+#include "Trie.cc"
+
+#endif // eckit_containers_Trie_H
diff --git a/eckit/src/eckit/exception/Exceptions.cc b/eckit/src/eckit/exception/Exceptions.cc
index bafc655..9c8759c 100644
--- a/eckit/src/eckit/exception/Exceptions.cc
+++ b/eckit/src/eckit/exception/Exceptions.cc
@@ -11,17 +11,17 @@
 #include <unistd.h>
 #include <signal.h>
 
+#include "eckit/config/LibEcKit.h"
 #include "eckit/exception/Exceptions.h"
 #include "eckit/thread/ThreadSingleton.h"
 #include "eckit/runtime/Main.h"
 
 #include "eckit/os/BackTrace.h"
 
-//-----------------------------------------------------------------------------
 
 namespace eckit {
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 static Exception*& first()
 {
@@ -35,8 +35,7 @@ Exception::Exception():  next_(first())
 
     callStack_ = BackTrace::dump();
 
-
-    if(::getenv("LIBECKIT_DEBUG_EXCEPTION_DUMPS_BACKTRACE")) {
+    if(::getenv("ECKIT_EXCEPTION_DUMPS_BACKTRACE")) {
         std::cerr << "Exception dumping backtrace: " << callStack_ << std::endl;
     }
 }
@@ -74,11 +73,13 @@ Exception::Exception(const std::string& w, const CodeLocation& location):
 {
     callStack_ = BackTrace::dump();
 
-    if(::getenv("LIBECKIT_DEBUG_EXCEPTION_DUMPS_BACKTRACE")) {
+    if(::getenv("ECKIT_EXCEPTION_DUMPS_BACKTRACE")) {
         std::cerr << "Exception dumping backtrace: " << callStack_ << std::endl;
     }
 
-    Log::error() << "Exception: " << w << location_ << std::endl;
+    if(! ::getenv("ECKIT_EXCEPTION_IS_SILENT")) {
+        Log::error() << "Exception: " << w << " " << location_ << std::endl;
+    }
 
 #if 0
     if(next_) {
@@ -198,12 +199,13 @@ AssertionFailed::AssertionFailed(const std::string& w):
 {
     Log::status() << what() << std::endl;
 
-    // if(Main::instance().assertAborts())
-    // {
-        std::cout << what() << std::endl;
-        std::cout << BackTrace::dump() << std::endl;
-    //     Main::instance().abort();
-    // }
+    std::cout << what() << std::endl;
+    std::cout << BackTrace::dump() << std::endl;
+
+     if(::getenv("ECKIT_ASSERT_ABORTS"))
+     {
+         LibEcKit::instance().abort();
+     }
 }
 
 AssertionFailed::AssertionFailed(const std::string& msg, const CodeLocation& loc)
@@ -216,12 +218,13 @@ AssertionFailed::AssertionFailed(const std::string& msg, const CodeLocation& loc
     reason(s.str());
     Log::status() << what() << std::endl;
 
-    // if(Main::instance().assertAborts())
-    // {
-        std::cout << what() << std::endl;
-        std::cout << BackTrace::dump() << std::endl;
-    //     Main::instance().abort();
-    // }
+    std::cout << what() << std::endl;
+    std::cout << BackTrace::dump() << std::endl;
+
+    if(::getenv("ECKIT_ASSERT_ABORTS"))
+    {
+        LibEcKit::instance().abort();
+    }
 }
 
 AssertionFailed::AssertionFailed(const char* msg, const CodeLocation& loc)
@@ -234,12 +237,13 @@ AssertionFailed::AssertionFailed(const char* msg, const CodeLocation& loc)
     reason(s.str());
     Log::status() << what() << std::endl;
 
-    //if(Main::instance().assertAborts())
-    //{
-        std::cout << what() << std::endl;
-        std::cout << BackTrace::dump() << std::endl;
-        //Main::instance().abort();
-    //}
+    std::cout << what() << std::endl;
+    std::cout << BackTrace::dump() << std::endl;
+
+    if(::getenv("ECKIT_ASSERT_ABORTS"))
+    {
+        LibEcKit::instance().abort();
+    }
 }
 
 BadParameter::BadParameter(const std::string& w):
@@ -320,6 +324,11 @@ Abort::Abort(const std::string& r):
 {
 }
 
+Abort::Abort( const std::string& r, const CodeLocation& loc ):
+    Exception(std::string("Abort: ") + r, loc)
+{
+}
+
 Retry::Retry(const std::string& r):
     Exception(std::string("Retry: ") + r)
 {
diff --git a/eckit/src/eckit/exception/Exceptions.h b/eckit/src/eckit/exception/Exceptions.h
index aa1838f..4bfdcb6 100644
--- a/eckit/src/eckit/exception/Exceptions.h
+++ b/eckit/src/eckit/exception/Exceptions.h
@@ -41,7 +41,7 @@ public: // methods
 
     /// Destructor
     /// @throws nothing
-    ~Exception() throw();
+    virtual ~Exception() throw();
 
     virtual const char *what() const throw() {  return what_.c_str(); }
     virtual bool retryOnServer() const        { return false; }
@@ -147,7 +147,8 @@ public:
 
 class Abort : public Exception {
 public:
-    Abort(const std::string&);
+    Abort( const std::string& );
+    Abort( const std::string&, const CodeLocation& );
 };
 
 class Cancel : public Exception {
diff --git a/eckit/src/eckit/filesystem/LocalPathName.cc b/eckit/src/eckit/filesystem/LocalPathName.cc
index 127ba9e..9167a04 100644
--- a/eckit/src/eckit/filesystem/LocalPathName.cc
+++ b/eckit/src/eckit/filesystem/LocalPathName.cc
@@ -560,6 +560,50 @@ void LocalPathName::match(const LocalPathName& root,std::vector<LocalPathName>&
 
 }
 
+LocalPathName LocalPathName::relativePath(const LocalPathName& other) const {
+
+    ASSERT(path_.size() && path_[0] == '/'); // ensure this path is absolute
+    ASSERT(other.path_.size() && other.path_[0] == '/'); // ensure other path is absolute
+
+    eckit::Tokenizer tokens("/");
+
+    std::vector<std::string> s1;
+    tokens(path_, s1);
+
+    std::vector<std::string> s2;
+    tokens(other.path_, s2);
+
+    // find common token
+    std::vector<std::string>::const_iterator i = s1.begin();
+    std::vector<std::string>::const_iterator j = s2.begin();
+    for(; i != s1.end() && j != s2.end(); ++i, ++j) {
+//        std::cout << "comparing " << *i << " " << *j << std::endl;
+        if(*i != *j) {
+            break;
+        }
+    }
+
+    std::string result;
+    const char* p = 0;
+
+    for(std::vector<std::string>::const_iterator r = j; r != s2.end(); ++r) {
+        if(p) result += p;
+        result += "..";
+        p = "/";
+    }
+
+    for(std::vector<std::string>::const_iterator r = i; r != s1.end(); ++r) {
+        if(p) result += p;
+        result += *r;
+        p = "/";
+    }
+
+    if(result.empty()) { result = "."; }
+
+    return result;
+}
+
+
 void LocalPathName::children(std::vector<LocalPathName>& files,std::vector<LocalPathName>& directories)
 	const
 {
@@ -598,16 +642,23 @@ void LocalPathName::children(std::vector<LocalPathName>& files,std::vector<Local
 				continue;
 
 		LocalPathName full = *this + "/" + e->d_name;
+
+#if defined(EC_HAVE_DIRENT_D_TYPE)
+        if(e->d_type == DT_DIR)
+            directories.push_back(full);
+        else
+            files.push_back(full);
+#else
         Stat::Struct info;
         if(Stat::stat(full.c_str(),&info) == 0)
-		{
-			if(S_ISDIR(info.st_mode))
-				directories.push_back(full);
-			else
-				files.push_back(full);
-		}
-		else Log::error() << "Cannot stat " << full << Log::syserr << std::endl;
-
+        {
+            if(S_ISDIR(info.st_mode))
+                directories.push_back(full);
+            else
+                files.push_back(full);
+        }
+        else Log::error() << "Cannot stat " << full << Log::syserr << std::endl;
+#endif
 	}
 }
 
diff --git a/eckit/src/eckit/filesystem/LocalPathName.h b/eckit/src/eckit/filesystem/LocalPathName.h
index 4dd6a78..318222f 100644
--- a/eckit/src/eckit/filesystem/LocalPathName.h
+++ b/eckit/src/eckit/filesystem/LocalPathName.h
@@ -121,6 +121,11 @@ public:
 
 // Methods
 
+    /// @returns a relative filepath to path to an optional start directory.
+    /// This is a pure path computation, no filesystem is accessed to confirm the existence or nature of path
+    /// @pre both paths need to be absolute paths, i.e starting with "/"
+    LocalPathName relativePath(const LocalPathName& other) const;
+
     /// Directory part of the path
     /// @return directory part of the path
     LocalPathName dirName() const;
diff --git a/eckit/src/eckit/filesystem/PathExpander.cc b/eckit/src/eckit/filesystem/PathExpander.cc
new file mode 100644
index 0000000..1089bd6
--- /dev/null
+++ b/eckit/src/eckit/filesystem/PathExpander.cc
@@ -0,0 +1,153 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "eckit/filesystem/PathExpander.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/filesystem/LocalPathName.h"
+
+#include "eckit/parser/StringTools.h"
+
+#include "eckit/thread/AutoLock.h"
+#include "eckit/thread/Once.h"
+#include "eckit/thread/Mutex.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+static pthread_once_t once  = PTHREAD_ONCE_INIT;
+static eckit::Mutex* local_mutex = 0;
+
+static void init() {
+    local_mutex = new eckit::Mutex();
+}
+
+typedef std::map<std::string, PathExpander*> PathExpanderMap;
+
+struct PathExpanderRegistry {
+
+    static PathExpanderRegistry& instance() {
+        static PathExpanderRegistry reg;
+        return reg;
+    }
+
+    PathExpanderMap map_;
+
+    PathExpanderMap& map() { return map_; }
+
+    const PathExpander& lookup(const std::string& name) {
+
+        pthread_once(&once, init);
+        eckit::AutoLock<eckit::Mutex> lock(local_mutex);
+
+        PathExpanderMap& m = PathExpanderRegistry::instance().map();
+
+        PathExpanderMap::const_iterator j = m.find(name);
+
+        // eckit::Log::info() << "Looking for PathExpander '" << name << "'" << std::endl;
+
+        if (j == m.end()) {
+            eckit::Log::error() << "No PathExpander found with name '" << name << "'" << std::endl;
+            eckit::Log::error() << "Registered libraries are:" << std::endl;
+            for (j = m.begin() ; j != m.end() ; ++j)
+                eckit::Log::error() << "   " << (*j).first << std::endl;
+            throw eckit::UserError(std::string("No PathExpander found with name ") + name);
+        }
+
+        ASSERT(j->second);
+
+        return *(j->second);
+    }
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+
+std::string PathExpander::expand(const std::string& key, const std::string& path)
+{
+    return PathExpanderRegistry::instance().lookup(key).expand(path);
+}
+
+
+PathExpander::PathExpander(const std::string& name):
+        name_(name)
+{
+    pthread_once(&once, init);
+    eckit::AutoLock<eckit::Mutex> lock(local_mutex);
+
+    PathExpanderMap& m = PathExpanderRegistry::instance().map();
+
+    ASSERT(m.find(name) == m.end());
+    m[name] = this;
+}
+
+PathExpander::~PathExpander() {
+}
+
+void PathExpander::print(std::ostream& s) const
+{
+    s << "PathExpander[" << name_ << "]";
+}
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class CWDFS : public PathExpander {
+public:
+
+    CWDFS(const std::string& name) : PathExpander(name) {}
+
+    virtual std::string expand(const std::string& path) const {
+
+        LocalPathName mnt = LocalPathName::cwd().mountPoint();
+
+        StringDict m;
+        m["CWDFS"] = std::string(mnt);
+
+        std::string newpath = StringTools::substitute(path, m);
+
+//        std::cout << "Path expansion " << path << " --> " << newpath << std::endl;
+
+        return newpath;
+    }
+
+};
+
+static CWDFS cwdfs("CWDFS");
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class CWD : public PathExpander {
+public:
+
+    CWD(const std::string& name) : PathExpander(name) {}
+
+    virtual std::string expand(const std::string& path) const {
+
+        LocalPathName mnt = LocalPathName::cwd();
+
+        StringDict m;
+        m["CWD"] = std::string(mnt);
+
+        std::string newpath = StringTools::substitute(path, m);
+
+//        std::cout << "Path expansion " << path << " --> " << newpath << std::endl;
+
+        return newpath;
+    }
+
+};
+
+static CWD cwd("CWD");
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/filesystem/PathExpander.h b/eckit/src/eckit/filesystem/PathExpander.h
new file mode 100644
index 0000000..3af499b
--- /dev/null
+++ b/eckit/src/eckit/filesystem/PathExpander.h
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Tiago Quintino
+/// @date   June 2017
+
+#ifndef eckit_PathExpander_h
+#define eckit_PathExpander_h
+
+#include <string>
+#include <map>
+
+#include "eckit/memory/NonCopyable.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class PathExpander : private eckit::NonCopyable {
+
+public: // methods
+
+    static std::string expand(const std::string& key, const std::string& path);
+
+    virtual std::string expand(const std::string& path) const = 0;
+
+protected: // methods
+
+    PathExpander(const std::string&);
+
+    virtual ~PathExpander();
+
+    virtual void print(std::ostream&) const;
+
+private: // members
+
+    std::string name_;
+
+    friend std::ostream& operator<<(std::ostream& s,const PathExpander& p) { p.print(s); return s; }
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/io/AIOHandle.cc b/eckit/src/eckit/io/AIOHandle.cc
index ddb8ba6..2ee13b0 100644
--- a/eckit/src/eckit/io/AIOHandle.cc
+++ b/eckit/src/eckit/io/AIOHandle.cc
@@ -63,14 +63,14 @@ Length AIOHandle::openForRead() {
 
 void AIOHandle::openForWrite(const Length&) {
     used_ = 0;
-    SYSCALL( fd_ = ::open(path_.localPath(), O_WRONLY | O_CREAT | O_TRUNC, 0777));
+    SYSCALL2( fd_ = ::open(path_.localPath(), O_WRONLY | O_CREAT | O_TRUNC, 0777), path_);
     pos_ = 0;
 }
 
 void AIOHandle::openForAppend(const Length& length) {
     used_ = 0;
-    SYSCALL( fd_  = ::open(path_.localPath(), O_WRONLY | O_CREAT | O_APPEND, 0777));
-    SYSCALL( pos_ = ::lseek(fd_, 0, SEEK_CUR) );
+    SYSCALL2( fd_  = ::open(path_.localPath(), O_WRONLY | O_CREAT | O_APPEND, 0777), path_);
+    SYSCALL2( pos_ = ::lseek(fd_, 0, SEEK_CUR), path_ );
 }
 
 long AIOHandle::read(void* buffer, long length) {
diff --git a/eckit/src/eckit/io/Buffer.h b/eckit/src/eckit/io/Buffer.h
index 7f8fa57..03163c3 100644
--- a/eckit/src/eckit/io/Buffer.h
+++ b/eckit/src/eckit/io/Buffer.h
@@ -17,8 +17,7 @@
 
 #include "eckit/eckit.h"
 
-#include "eckit/memory/NonCopyable.h"
-
+#include "eckit/memory/Counted.h"
 
 namespace eckit {
 
@@ -26,7 +25,7 @@ namespace eckit {
 
 // A simple class to implement buffers
 
-class Buffer : private NonCopyable {
+class Buffer : public eckit::Counted {
 
 public: // methods
 
@@ -39,12 +38,14 @@ public: // methods
 
     ~Buffer();
 
-    operator char*()                 { return (char*)buffer_; }
-    operator const char*() const     { return (char*)buffer_; }
+    operator char*()                 { return static_cast<char*>(buffer_); }
+    operator const char*() const     { return static_cast<const char*>(buffer_); }
 
     operator void*()                 { return buffer_; }
     operator const void*() const     { return buffer_; }
 
+    void* data() { return buffer_; }
+
     size_t size() const		 { return size_; }
 
     void resize(size_t size);
@@ -70,6 +71,61 @@ private: // members
 
 //----------------------------------------------------------------------------------------------------------------------
 
+/// A buffer that can be shared and is thread-safe
+/// Note that this buffer, once shared should be for read-only shared-access (at the moment)
+/// because access is not controlled by locking, only allocation and deallocation
+
+class SharedBuffer {
+
+public: // methods
+
+    SharedBuffer(size_t size) : buffer_(new Buffer(size)) {
+        buffer_->attach();
+    }
+
+    /// @note Takes ownership of the buffer
+    SharedBuffer(Buffer* b) {
+        ASSERT(b);
+        buffer_ = b;
+        buffer_->attach();
+    }
+
+    ~SharedBuffer() {
+        buffer_->detach();
+    }
+
+    SharedBuffer(const SharedBuffer& s) : buffer_(s.buffer_) {
+        buffer_->attach();
+    }
+
+    SharedBuffer& operator=(const SharedBuffer& s) {
+        if(buffer_) { buffer_->detach(); }
+        buffer_ = s.buffer_;
+        buffer_->attach();
+        return *this;
+    }
+
+    operator void*()                 { return *buffer_; }
+    operator const void*() const     { return *buffer_; }
+
+    size_t size() const              { return buffer_->size(); }
+
+    /// Careful, use str() to convert the contents of a buffer to a string
+    /// and don't rely on the contents to be null terminated
+
+    std::string str() const { return std::string(*buffer_, size()); }
+
+    operator const Buffer&() const { return *buffer_; }
+    operator Buffer&() { return *buffer_; }
+
+private:
+
+    Buffer* buffer_;
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
 } // namespace eckit
 
 #endif
diff --git a/eckit/src/eckit/io/DataHandle.cc b/eckit/src/eckit/io/DataHandle.cc
index ce642f8..e9edb92 100644
--- a/eckit/src/eckit/io/DataHandle.cc
+++ b/eckit/src/eckit/io/DataHandle.cc
@@ -97,7 +97,7 @@ void DataHandle::flush()
     throw NotImplemented(os.str(), Here());
 }
 
-Length DataHandle::saveInto(DataHandle& other,TransferWatcher& watcher)
+Length DataHandle::saveInto(DataHandle& other,TransferWatcher& watcher, bool dblBufferOK)
 {
     static const bool moverTransfer = Resource<bool>("-mover;moverTransfer",0);
 
@@ -116,7 +116,7 @@ Length DataHandle::saveInto(DataHandle& other,TransferWatcher& watcher)
 
     static const bool doubleBuffer = Resource<bool>("doubleBuffer",0);
 
-    if(doubleBuffer)
+    if(doubleBuffer && dblBufferOK)
     {
         static const long bufsize = Resource<long>("doubleBufferSize",10*1024*1024/20);
         static const long count   = Resource<long>("doubleBufferCount",20);
@@ -210,10 +210,10 @@ Length DataHandle::saveInto(DataHandle& other,TransferWatcher& watcher)
     }
 }
 
-Length DataHandle::saveInto(const PathName& path,TransferWatcher& w)
+Length DataHandle::saveInto(const PathName& path,TransferWatcher& w, bool dblBufferOK)
 {
     std::auto_ptr<DataHandle> file(path.fileHandle());
-    return saveInto(*file,w);
+    return saveInto(*file,w,dblBufferOK);
 }
 
 Length DataHandle::copyTo(DataHandle& other) {
diff --git a/eckit/src/eckit/io/DataHandle.h b/eckit/src/eckit/io/DataHandle.h
index e112a07..b319d77 100644
--- a/eckit/src/eckit/io/DataHandle.h
+++ b/eckit/src/eckit/io/DataHandle.h
@@ -78,9 +78,9 @@ public:
 
 	// Save into an other datahandle
 
-	virtual Length saveInto(DataHandle&, TransferWatcher& = TransferWatcher::dummy());
+	virtual Length saveInto(DataHandle&, TransferWatcher& = TransferWatcher::dummy(), bool dblBufferOK = true);
 
-	Length saveInto(const PathName&, TransferWatcher& = TransferWatcher::dummy()); // Save into a file
+	Length saveInto(const PathName&, TransferWatcher& = TransferWatcher::dummy(), bool dblBufferOK = true); // Save into a file
 
     /// Quiet version of saveInto. Does not support progess, restart and double buffering
     Length copyTo(DataHandle&);
diff --git a/eckit/src/eckit/io/FileDescHandle.cc b/eckit/src/eckit/io/FileDescHandle.cc
index e0c8e72..1e9e74b 100644
--- a/eckit/src/eckit/io/FileDescHandle.cc
+++ b/eckit/src/eckit/io/FileDescHandle.cc
@@ -28,13 +28,17 @@ void FileDescHandle::encode(Stream& s) const
     NOTIMP;
 }
 
-FileDescHandle::FileDescHandle(int fd):
-    fd_(fd)
+FileDescHandle::FileDescHandle(int fd, bool close):
+    fd_(fd),
+    close_(close)
 {
 }
 
 FileDescHandle::~FileDescHandle()
 {
+    if (fd_ != -1) {
+        close();
+    }
 }
 
 Length FileDescHandle::openForRead()
@@ -50,34 +54,41 @@ void FileDescHandle::openForAppend(const Length&)
 {
 }
 
-long FileDescHandle::read(void* buffer,long length)
+long FileDescHandle::read(void* buffer, long length)
 {
-    return ::read(fd_,buffer,length);
+    return ::read(fd_, buffer, length);
 }
 
-long FileDescHandle::write(const void* buffer,long length)
+long FileDescHandle::write(const void* buffer, long length)
 {
-    return ::write(fd_,buffer,length);
+    return ::write(fd_, buffer, length);
 }
 
 void FileDescHandle::close()
 {
-    // May be we should close fd_ here ?
+    if (close_ && (fd_ != -1)) {
+        SYSCALL(::close(fd_));
+        fd_ = -1;
+    }
 }
 
 Offset FileDescHandle::position()
 {
-    return ::lseek(fd_, 0, SEEK_CUR);
+    off_t pos;
+    SYSCALL(pos = ::lseek(fd_, 0, SEEK_CUR));
+    return pos;
 }
 
 Offset FileDescHandle::seek(const Offset& o)
 {
-    return ::lseek(fd_, o, SEEK_SET);
+    off_t pos;
+    SYSCALL(pos = ::lseek(fd_, o, SEEK_SET));
+    return pos;
 }
 
 void FileDescHandle::skip(const Length& l)
 {
-    ::lseek(fd_, l, SEEK_CUR);
+    SYSCALL(::lseek(fd_, l, SEEK_CUR));
 }
 
 //-----------------------------------------------------------------------------
diff --git a/eckit/src/eckit/io/FileDescHandle.h b/eckit/src/eckit/io/FileDescHandle.h
index fa1e103..c0d92c7 100644
--- a/eckit/src/eckit/io/FileDescHandle.h
+++ b/eckit/src/eckit/io/FileDescHandle.h
@@ -1,9 +1,9 @@
 /*
  * (C) Copyright 1996-2017 ECMWF.
- * 
+ *
  * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
  * granted to it by virtue of its status as an intergovernmental organisation nor
  * does it submit to any jurisdiction.
  */
@@ -27,7 +27,7 @@ public:
 
 // -- Contructors
 
-	FileDescHandle(int);
+	FileDescHandle(int, bool close = false);
 
 // -- Destructor
 
@@ -62,6 +62,7 @@ private:
 // -- Members
 
 	int fd_;
+    bool close_;
 
 // -- Class members
 
diff --git a/eckit/src/eckit/io/Pipeline.cc b/eckit/src/eckit/io/Pipeline.cc
new file mode 100644
index 0000000..0968d1c
--- /dev/null
+++ b/eckit/src/eckit/io/Pipeline.cc
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <unistd.h>
+
+#include "eckit/thread/AutoLock.h"
+#include "eckit/io/Buffer.h"
+#include "eckit/log/Bytes.h"
+#include "eckit/io/Pipeline.h"
+#include "eckit/log/Log.h"
+#include "eckit/thread/MutexCond.h"
+#include "eckit/log/Progress.h"
+#include "eckit/thread/Thread.h"
+#include "eckit/thread/ThreadControler.h"
+#include "eckit/log/Timer.h"
+#include "eckit/io/FileDescHandle.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+
+class PipelineReader : public Thread {
+    Pipeline&     owner_;
+    DataHandle&   out_;
+    DataHandle&   in_;
+
+public:
+    PipelineReader(Pipeline& owner_, DataHandle& in, DataHandle& out);
+    virtual void run();
+};
+
+
+PipelineReader::PipelineReader(Pipeline& owner, DataHandle& in, DataHandle& out):
+    owner_(owner), in_(in), out_(out) {}
+
+void PipelineReader::run() {
+    try {
+        in_.saveInto(out_, owner_.watcher_);
+    }
+    catch (std::exception& e) {
+        owner_.error(e.what());
+    }
+}
+
+
+class PipelineExecutor : public Thread {
+    Pipeline&     owner_;
+    DataHandle&   out_;
+    DataHandle&   in_;
+
+public:
+    PipelineExecutor(Pipeline& owner_, DataHandle& in, DataHandle& out);
+    virtual void run();
+};
+
+PipelineExecutor::PipelineExecutor(Pipeline& owner, DataHandle& in, DataHandle& out):
+    owner_(owner), in_(in), out_(out) {}
+
+
+
+void PipelineExecutor::run() {
+    try {
+        owner_.execute(in_, out_);
+    }
+    catch (std::exception& e) {
+        owner_.error(e.what());
+    }
+}
+
+Pipeline::Pipeline(TransferWatcher& watcher):
+
+    error_(false),
+    watcher_(watcher)
+{
+}
+
+Pipeline::~Pipeline()
+{
+}
+
+inline void Pipeline::error(const std::string& why)
+{
+    AutoLock<Mutex> lock(mutex_);
+    error_ = true;
+    why_   = why;
+}
+
+inline bool Pipeline::error()
+{
+    AutoLock<Mutex> lock(mutex_);
+    return error_;
+}
+
+Length Pipeline::copy(DataHandle& in, DataHandle& out)
+{
+
+    int reader[2];
+    SYSCALL(::pipe(reader));
+
+    FileDescHandle reader_out(reader[1], true);
+    FileDescHandle reader_in(reader[0], true);
+
+
+    int process[2];
+    SYSCALL(::pipe(process));
+
+    FileDescHandle process_out(process[1], true);
+    FileDescHandle process_in(process[0], true);
+
+
+    ThreadControler thread1(new PipelineReader(*this, in, reader_out), false);
+    thread1.start();
+
+    ThreadControler thread2(new PipelineExecutor(*this, reader_in, process_out), false);
+    thread2.start();
+
+    Length total = 0;
+
+    try {
+        total = process_in.saveInto(out, watcher_);
+    }
+    catch (std::exception& e) {
+        error(e.what());
+    }
+
+    try {
+        thread1.wait();
+    }
+    catch (std::exception& e) {
+        error(e.what());
+    }
+
+    try {
+        thread2.wait();
+    }
+    catch (std::exception& e) {
+        error(e.what());
+    }
+
+    if (error_) {
+        throw SeriousBug(why_);
+    }
+
+    return total;
+}
+
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
+
diff --git a/eckit/src/eckit/io/Pipeline.h b/eckit/src/eckit/io/Pipeline.h
new file mode 100644
index 0000000..13be409
--- /dev/null
+++ b/eckit/src/eckit/io/Pipeline.h
@@ -0,0 +1,84 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+// File Pipeline.h
+// Baudouin Raoult - ECMWF Feb 97
+
+#ifndef eckit_Pipeline_h
+#define eckit_Pipeline_h
+
+#include "eckit/io/DataHandle.h"
+#include "eckit/io/Length.h"
+#include "eckit/memory/NonCopyable.h"
+#include "eckit/thread/Mutex.h"
+#include "eckit/io/TransferWatcher.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+class Pipeline : private NonCopyable {
+public:
+
+// -- Contructors
+
+	Pipeline(TransferWatcher& = TransferWatcher::dummy());
+
+// -- Destructor
+
+	virtual ~Pipeline();
+
+// -- Methods
+
+	Length copy(DataHandle&,DataHandle&);
+
+	bool   error();
+    void   error(const std::string&);
+	void   restart(RestartTransfer&);
+
+
+private:
+
+    virtual void execute(DataHandle& in,DataHandle& out) = 0;
+
+
+private: // members
+
+	Mutex  mutex_;
+
+    long   count_;
+	long   bufSize_;
+
+	Length inBytes_;
+	Length outBytes_;
+
+	bool error_;
+    std::string why_;
+
+    bool restart_;
+
+	Offset restartFrom_;
+	TransferWatcher& watcher_;
+
+// -- Friends
+
+    friend class PipelineExecutor;
+    friend class PipelineReader;
+
+};
+
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/io/StdPipe.cc b/eckit/src/eckit/io/StdPipe.cc
index 9cc0d0e..82cf98f 100644
--- a/eckit/src/eckit/io/StdPipe.cc
+++ b/eckit/src/eckit/io/StdPipe.cc
@@ -11,16 +11,13 @@
 #include "eckit/exception/Exceptions.h"
 #include "eckit/io/StdPipe.h"
 
-
-//-----------------------------------------------------------------------------
-
 namespace eckit {
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 StdPipe::StdPipe(const std::string& name,const std::string& mode)
 {
-	file_ = popen(name.c_str(),mode.c_str());
+	file_ = ::popen(name.c_str(),mode.c_str());
 
 	if(file_ == 0)
 		throw CantOpenFile(name);
@@ -28,12 +25,14 @@ StdPipe::StdPipe(const std::string& name,const std::string& mode)
 
 StdPipe::~StdPipe()
 {
-	if(file_)
-		if(pclose(file_))
-			throw FailedSystemCall("pclose");
+    if (file_) {
+        if (::pclose(file_) == -1) {
+            throw FailedSystemCall("pclose");
+        }
+    }
 }
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
 
diff --git a/eckit/src/eckit/io/StdPipe.h b/eckit/src/eckit/io/StdPipe.h
index d4731b8..5d753da 100644
--- a/eckit/src/eckit/io/StdPipe.h
+++ b/eckit/src/eckit/io/StdPipe.h
@@ -8,24 +8,18 @@
  * does it submit to any jurisdiction.
  */
 
-// File StdPipe.h
-// Baudouin Raoult - ECMWF Jun 96
+/// @author Baudouin Raoult
 
-#ifndef eckit_StdPipe_h
-#define eckit_StdPipe_h
+#ifndef eckit_io_StdPipe_h
+#define eckit_io_StdPipe_h
 
 #include <stdio.h>
 #include <string>
 
 
-//-----------------------------------------------------------------------------
-
 namespace eckit {
 
-//-----------------------------------------------------------------------------
-
-
-// Simple wrapper around a stdio file
+//----------------------------------------------------------------------------------------------------------------------
 
 class StdPipe {
 public:
@@ -55,8 +49,7 @@ private:
 
 };
 
-
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
 
diff --git a/eckit/src/eckit/log/CodeLocation.cc b/eckit/src/eckit/log/CodeLocation.cc
index a3afe71..f17cdd7 100644
--- a/eckit/src/eckit/log/CodeLocation.cc
+++ b/eckit/src/eckit/log/CodeLocation.cc
@@ -25,13 +25,13 @@ std::string CodeLocation::asString() const {
 }
 
 CodeLocation::operator bool() const {
-    return file_ != 0;
+    return file_ && ::strlen(file_);
 }
 
 void CodeLocation::print(std::ostream& os) const {
     if ( file_ ) {
         os << " (" << file_ << " +" << line_;
-        if ( strlen(func_) )
+        if ( ::strlen(func_) )
             os << " " << func_;
         os << ")";
     }
diff --git a/eckit/src/eckit/memory/Counted.h b/eckit/src/eckit/memory/Counted.h
index 457db50..d55cef9 100644
--- a/eckit/src/eckit/memory/Counted.h
+++ b/eckit/src/eckit/memory/Counted.h
@@ -94,9 +94,6 @@ public:
 
     virtual ~Counted();
 
-//  void *operator new(size_t s)  { return MemoryPool::fastAllocate(s);}
-//  void operator delete(void* p) { MemoryPool::fastDeallocate(p);     }
-
 private: // members
 
     mutable size_t count_;
diff --git a/eckit/src/eckit/memory/MemoryPool.cc b/eckit/src/eckit/memory/MemoryPool.cc
index 1330ce9..8d23ac3 100644
--- a/eckit/src/eckit/memory/MemoryPool.cc
+++ b/eckit/src/eckit/memory/MemoryPool.cc
@@ -11,8 +11,9 @@
 #include <unistd.h>
 #include <pthread.h>
 
-#include "eckit/log/Bytes.h"
+#include "eckit/config/LibEcKit.h"
 #include "eckit/exception/Exceptions.h"
+#include "eckit/log/Bytes.h"
 #include "eckit/memory/MemoryPool.h"
 
 
@@ -224,8 +225,8 @@ void MemoryPool::largeDeallocate(void* addr)
 
 	if(!(m->check() && m->inUse())) {
         std::cerr << "deallocating a bad block" << std::endl;
-		abort();
-	}
+        LibEcKit::instance().abort();
+    }
 
 //	std::cout << "Releasing " << m->size_ << std::endl;
 	m->inUse(false);
@@ -346,7 +347,7 @@ void MemoryPool::fastDeallocate(void *p,MemPool& pool)
 	}
 
     std::cerr << Here() << std::endl;
-	abort();
+    LibEcKit::instance().abort();
 }
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/memory/Padded.h b/eckit/src/eckit/memory/Padded.h
index a7d72bb..1f88422 100644
--- a/eckit/src/eckit/memory/Padded.h
+++ b/eckit/src/eckit/memory/Padded.h
@@ -1,9 +1,9 @@
 /*
  * (C) Copyright 1996-2017 ECMWF.
- * 
+ *
  * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
  * granted to it by virtue of its status as an intergovernmental organisation nor
  * does it submit to any jurisdiction.
  */
@@ -26,14 +26,14 @@ template<class T,int size>
 class Padded : public T {
 private:
 
-	// Add the padding 
+	// Add the padding
 
     enum {
 			align_ = size,
 			osize_ = sizeof(T)
 	};
 
-	char padding_[((osize_+align_-1)/align_)*align_ - osize_];
+	char padding_[((size_t(osize_)+size_t(align_)-1)/align_)*align_ - osize_];
 };
 
 
diff --git a/eckit/src/eckit/mpi/Comm.cc b/eckit/src/eckit/mpi/Comm.cc
index aa0214d..cfe43b4 100644
--- a/eckit/src/eckit/mpi/Comm.cc
+++ b/eckit/src/eckit/mpi/Comm.cc
@@ -22,6 +22,10 @@ namespace mpi {
 
 //----------------------------------------------------------------------------------------------------------------------
 
+// Uncomment following line to reintroduce ECKIT-166 bug.
+// #define REPRODUCE_ECKIT_166
+// TODO: Delete the code below guareded by "#ifdef REPRODUCE_ECKIT_166"
+
 class Environment {
 public:
 
@@ -85,6 +89,14 @@ public:
         return false;
     }
 
+    void finaliseAllComms() {
+        std::map<std::string, Comm*>::iterator itr = communicators.begin();
+        for(; itr != communicators.end(); ++itr) {
+            delete itr->second;
+        }
+        communicators.clear();
+    }
+
     Comm& getComm(const char* name = 0) {
 
         AutoLock<Mutex> lock(mutex_);
@@ -127,6 +139,7 @@ public:
         communicators[name] = pComm;
     }
 
+#ifdef REPRODUCE_ECKIT_166
     CommFactory& getFactory(const std::string& name) {
 
         AutoLock<Mutex> lock(mutex_);
@@ -153,6 +166,7 @@ public:
         AutoLock<Mutex> lock(mutex_);
         factories.erase(name);
     }
+#endif
 
     Environment() : default_(0) {}
 
@@ -160,43 +174,92 @@ public:
 
         AutoLock<Mutex> lock(mutex_);
 
-        if(default_) {
-            for(std::map<std::string,Comm*>::iterator itr = communicators.begin() ; itr != communicators.end() ; ++itr) {
-                delete itr->second;
-            }
-            default_ = 0;
-        }
+        finaliseAllComms();
+        default_ = 0;
     }
 
     Comm* default_;
 
     std::map<std::string, Comm*> communicators;
 
+#ifdef REPRODUCE_ECKIT_166
     std::map<std::string, CommFactory*> factories;
+#endif
 
     eckit::Mutex mutex_;
 };
 
 //----------------------------------------------------------------------------------------------------------------------
 
+class CommFactories {
+public:
+
+  void registFactory(const std::string& name, CommFactory* f) {
+      AutoLock<Mutex> lock(mutex_);
+      ASSERT(factories.find(name) == factories.end());
+      factories[name] = f;
+  }
+
+  void unregistFactory(const std::string& name) {
+      AutoLock<Mutex> lock(mutex_);
+      factories.erase(name);
+  }
+  
+  CommFactory& getFactory(const std::string& name) {
+
+      AutoLock<Mutex> lock(mutex_);
+
+      std::map<std::string, CommFactory *>::const_iterator j = factories.find(name);
+
+      if (j != factories.end()) { return *(j->second); }
+
+      eckit::Log::error() << "No CommFactory for [" << name << "]" << std::endl;
+      eckit::Log::error() << "CommFactories are:" << std::endl;
+      for (j = factories.begin() ; j != factories.end() ; ++j)
+          eckit::Log::error() << "   " << (*j).first << std::endl;
+
+      throw eckit::SeriousBug(std::string("No CommFactory called ") + name);
+  }
+  
+  static CommFactories& instance() { 
+    static CommFactories obj;
+    return obj;
+  }
+ 
+private:
+  
+  CommFactories() {}
+   
+  std::map<std::string, CommFactory*> factories;
+  eckit::Mutex mutex_;
+};
+
+#ifdef REPRODUCE_ECKIT_166
+#define CommFactories Environment
+#endif
+
 CommFactory::CommFactory(const std::string &name):
     name_(name) {
-    Environment::instance().registFactory(name, this);
+    CommFactories::instance().registFactory(name, this);
 }
 
 CommFactory::~CommFactory() {
-    Environment::instance().unregistFactory(name_);
+    CommFactories::instance().unregistFactory(name_);
 }
 
 Comm* CommFactory::build(const std::string& name) {
-    return Environment::instance().getFactory(name).make();
+    return CommFactories::instance().getFactory(name).make();
 }
 
 Comm*CommFactory::build(const std::string& name, int comm)
 {
-    return Environment::instance().getFactory(name).make(comm);
+    return CommFactories::instance().getFactory(name).make(comm);
 }
 
+#ifdef REPRODUCE_ECKIT_166
+#undef CommFactories
+#endif
+
 //----------------------------------------------------------------------------------------------------------------------
 
 Comm::Comm() {
@@ -225,6 +288,10 @@ bool hasComm(const char* name) {
     return Environment::instance().hasComm(name);
 }
 
+void finaliseAllComms() {
+    return Environment::instance().finaliseAllComms();
+}
+
 //----------------------------------------------------------------------------------------------------------------------
 
 } // namespace mpi
diff --git a/eckit/src/eckit/mpi/Comm.h b/eckit/src/eckit/mpi/Comm.h
index e10f6cb..e224f35 100644
--- a/eckit/src/eckit/mpi/Comm.h
+++ b/eckit/src/eckit/mpi/Comm.h
@@ -18,6 +18,8 @@
 
 #include "eckit/exception/Exceptions.h"
 #include "eckit/memory/NonCopyable.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/io/Buffer.h"
 
 #include "eckit/mpi/Buffer.h"
 #include "eckit/mpi/DataType.h"
@@ -44,6 +46,14 @@ void addComm(const char* name, int comm);
 /// Check if a communicator is registered
 bool hasComm(const char* name);
 
+/// Finalises all the comms that are registered
+///
+/// @note This should not be necessary to be called, since all singletong Comms finalise themselves on destruction
+///       when application shutsdown. Currently there is a bug in OpenMPI on MacOSX (see ECKIT-166) that implies
+///       that MPI_Finalize must be called explicitly before exiting main(). This is the only current reason to use
+///       this function.
+void finaliseAllComms();
+
 //----------------------------------------------------------------------------------------------------------------------
 
 class Comm : private eckit::NonCopyable {
@@ -256,6 +266,17 @@ public:  // methods
     void send(T& sendbuf, int dest, int tag) const;
 
     ///
+    /// Blocking send, until message recieved
+    ///
+
+    template <typename T>
+    void synchronisedSend(T* sendbuf, size_t count, int dest, int tag) const;
+
+    template <typename T>
+    void synchronisedSend(T& sendbuf, int dest, int tag) const;
+
+
+    ///
     /// Non-blocking send
     ///
 
@@ -272,7 +293,11 @@ public:  // methods
     template <typename T>
     void allToAll(const std::vector< std::vector<T> >& sendvec, std::vector< std::vector<T> >& recvvec) const;
 
+    ///
+    /// Read file on one rank, and broadcast
+    ///
 
+    virtual eckit::SharedBuffer broadcastFile( const eckit::PathName& filepath, size_t root ) const = 0;
 
     /// @brief The communicator
     virtual int communicator() const = 0;
@@ -314,6 +339,8 @@ public:  // methods
 
       virtual void send(const void* send, size_t count, Data::Code datatype, int dest, int tag) const = 0;
 
+      virtual void synchronisedSend(const void* send, size_t count, Data::Code datatype, int dest, int tag) const = 0;
+
       virtual Request iReceive(void* recv, size_t count, Data::Code datatype, int source, int tag) const = 0;
 
       virtual Request iSend(const void* send, size_t count, Data::Code datatype, int dest, int tag) const = 0;
@@ -739,6 +766,17 @@ void eckit::mpi::Comm::send(T& sendbuf, int dest, int tag) const {
     send(&sendbuf, 1, Data::Type<T>::code(), dest, tag);
 }
 
+template <typename T>
+void eckit::mpi::Comm::synchronisedSend(T* sendbuf, size_t count, int dest, int tag) const {
+    synchronisedSend(sendbuf, count, Data::Type<T>::code(), dest, tag);
+}
+
+template <typename T>
+void eckit::mpi::Comm::synchronisedSend(T& sendbuf, int dest, int tag) const {
+    synchronisedSend(&sendbuf, 1, Data::Type<T>::code(), dest, tag);
+}
+
+
 ///
 /// Non-blocking send
 ///
diff --git a/eckit/src/eckit/mpi/Parallel.cc b/eckit/src/eckit/mpi/Parallel.cc
index 4612e16..eced260 100644
--- a/eckit/src/eckit/mpi/Parallel.cc
+++ b/eckit/src/eckit/mpi/Parallel.cc
@@ -10,6 +10,8 @@
 
 #include "eckit/mpi/Parallel.h"
 
+#include <errno.h>
+#include <unistd.h>
 #include <limits>
 #include <sstream>
 
@@ -20,6 +22,9 @@
 #include "eckit/runtime/Main.h"
 #include "eckit/thread/AutoLock.h"
 #include "eckit/thread/Mutex.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/io/DataHandle.h"
+#include "eckit/memory/ScopedPtr.h"
 
 namespace eckit {
 namespace mpi {
@@ -403,6 +408,15 @@ void Parallel::send(const void* send, size_t count, Data::Code type, int dest, i
     MPI_CALL( MPI_Send(const_cast<void*>(send), int(count), mpitype, dest, tag, comm_) );
 }
 
+void Parallel::synchronisedSend(const void* send, size_t count, Data::Code type, int dest, int tag) const
+{
+    ASSERT(count  < size_t(std::numeric_limits<int>::max()));
+
+    MPI_Datatype mpitype = toType(type);
+
+    MPI_CALL( MPI_Ssend(const_cast<void*>(send), int(count), mpitype, dest, tag, comm_) );
+}
+
 Request Parallel::iReceive(void* recv, size_t count, Data::Code type, int source, int tag) const
 {
     ASSERT(count  < size_t(std::numeric_limits<int>::max()));
@@ -454,6 +468,58 @@ int Parallel::communicator() const {
     return MPI_Comm_c2f(comm_);
 }
 
+eckit::SharedBuffer Parallel::broadcastFile( const PathName& filepath, size_t root ) const {
+
+    ASSERT( root < size() );
+
+    bool isRoot = rank() == root;
+
+    eckit::Buffer* buffer;
+
+    struct BFileOp {
+        int     err_;
+        size_t  len_;
+    } op = {0,0};
+
+    errno = 0;
+
+    if(isRoot) {
+        try {
+            eckit::ScopedPtr<DataHandle> dh( filepath.fileHandle() );
+
+            op.len_ = dh->openForRead(); AutoClose closer(*dh);
+            buffer = new eckit::Buffer(op.len_);
+            dh->read(buffer->data(), op.len_);
+
+            if(filepath.isDir()) { op.err_ = EISDIR; }
+
+        } catch (Exception& e) {
+            op.err_ = errno;
+            op.len_ = -1;
+        }
+    }
+
+    broadcast(&op, sizeof(op), Data::BYTE, root);
+
+    errno = op.err_;  // set errno to ensure consistent error messages across MPI tasks
+
+    if(op.err_) {
+        throw CantOpenFile( filepath );
+    }
+
+    if(not op.len_) {
+        throw ShortFile( filepath );
+    }
+
+    if(!isRoot) {
+        buffer = new eckit::Buffer(op.len_);
+    }
+
+    broadcast(*buffer, op.len_, Data::BYTE, root);
+
+    return eckit::SharedBuffer(buffer);
+}
+
 CommBuilder<Parallel> ParallelBuilder("parallel");
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/mpi/Parallel.h b/eckit/src/eckit/mpi/Parallel.h
index bdc257a..41813cb 100644
--- a/eckit/src/eckit/mpi/Parallel.h
+++ b/eckit/src/eckit/mpi/Parallel.h
@@ -11,6 +11,9 @@
 #ifndef eckit_mpi_Parallel_h
 #define eckit_mpi_Parallel_h
 
+#define OMPI_SKIP_MPICXX 1
+#define MPICH_SKIP_MPICXX 1
+
 #include <mpi.h>
 
 #include "eckit/mpi/Comm.h"
@@ -83,10 +86,14 @@ protected:  // methods
 
     virtual void send(const void* send, size_t count, Data::Code type, int dest, int tag) const;
 
+    virtual void synchronisedSend(const void* send, size_t count, Data::Code type, int dest, int tag) const;
+
     virtual Request iReceive(void* recv, size_t count, Data::Code type, int source, int tag) const;
 
     virtual Request iSend(const void* send, size_t count, Data::Code type, int dest, int tag) const;
 
+    virtual eckit::SharedBuffer broadcastFile( const eckit::PathName& filepath, size_t root ) const;
+
     virtual void print(std::ostream&) const;
 
     virtual Status status() const    { return createStatus(); }
diff --git a/eckit/src/eckit/mpi/ParallelRequest.h b/eckit/src/eckit/mpi/ParallelRequest.h
index 5865cf5..0953f28 100644
--- a/eckit/src/eckit/mpi/ParallelRequest.h
+++ b/eckit/src/eckit/mpi/ParallelRequest.h
@@ -11,6 +11,9 @@
 #ifndef eckit_mpi_ParallelRequest_h
 #define eckit_mpi_ParallelRequest_h
 
+#define OMPI_SKIP_MPICXX 1
+#define MPICH_SKIP_MPICXX 1
+
 #include <mpi.h>
 
 #include "eckit/mpi/Request.h"
diff --git a/eckit/src/eckit/mpi/ParallelStatus.h b/eckit/src/eckit/mpi/ParallelStatus.h
index 5604594..14034b6 100644
--- a/eckit/src/eckit/mpi/ParallelStatus.h
+++ b/eckit/src/eckit/mpi/ParallelStatus.h
@@ -11,6 +11,9 @@
 #ifndef eckit_mpi_ParallelStatus_h
 #define eckit_mpi_ParallelStatus_h
 
+#define OMPI_SKIP_MPICXX 1
+#define MPICH_SKIP_MPICXX 1
+
 #include <mpi.h>
 
 #include "eckit/mpi/Status.h"
diff --git a/eckit/src/eckit/mpi/Serial.cc b/eckit/src/eckit/mpi/Serial.cc
index 61ebe7c..eec3054 100644
--- a/eckit/src/eckit/mpi/Serial.cc
+++ b/eckit/src/eckit/mpi/Serial.cc
@@ -10,6 +10,7 @@
 
 #include "eckit/mpi/Serial.h"
 
+#include <errno.h>
 #include <unistd.h>
 #include <limits>
 #include <deque>
@@ -21,6 +22,9 @@
 #include "eckit/thread/AutoLock.h"
 #include "eckit/thread/Mutex.h"
 #include "eckit/maths/Functions.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/memory/ScopedPtr.h"
+#include "eckit/io/DataHandle.h"
 
 namespace eckit {
 namespace mpi {
@@ -154,7 +158,9 @@ void Serial::barrier() const {
 }
 
 void Serial::abort(int) const {
-    throw Abort("MPI Abort called");
+    // Don't use std::abort as it would raise SIGABRT.
+    // MPI_Abort also does not raise SIGABRT
+    std::exit(EXIT_FAILURE);
 }
 
 Status Serial::wait(Request& req) const {
@@ -286,6 +292,13 @@ void Serial::send(const void* send, size_t count, Data::Code type, int dest, int
     SerialSendReceive::instance().addSend( Request( new SendRequest(send,count,type,tag) ) );
 }
 
+void Serial::synchronisedSend(const void* send, size_t count, Data::Code type, int dest, int tag) const
+{
+    // TODO: see if this is good enough
+    AutoLock<SerialSendReceive> lock(SerialSendReceive::instance());
+    SerialSendReceive::instance().addSend( Request( new SendRequest(send,count,type,tag) ) );
+}
+
 Request Serial::iReceive(void* recv, size_t count, Data::Code type, int source, int tag) const {
     AutoLock<SerialRequestPool> lock(SerialRequestPool::instance());
     return SerialRequestPool::instance().createReceiveRequest(recv,count,type,tag);
@@ -313,6 +326,29 @@ int Serial::communicator() const {
     return 0;
 }
 
+eckit::SharedBuffer Serial::broadcastFile( const PathName& filepath, size_t ) const {
+
+    eckit::Buffer* buffer;
+
+    eckit::ScopedPtr<DataHandle> dh( filepath.fileHandle() );
+
+    Length len = dh->openForRead(); AutoClose closer(*dh);
+    buffer = new eckit::Buffer(len);
+    dh->read(buffer->data(), len);
+
+    if(not len) {
+        throw ShortFile( filepath );
+    }
+
+    if(filepath.isDir()) {
+        errno = EISDIR;
+        throw CantOpenFile( filepath );
+    }
+
+    return eckit::SharedBuffer(buffer);
+}
+
+
 CommBuilder<Serial> SerialBuilder("serial");
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/mpi/Serial.h b/eckit/src/eckit/mpi/Serial.h
index 38f1b9d..70f7d5b 100644
--- a/eckit/src/eckit/mpi/Serial.h
+++ b/eckit/src/eckit/mpi/Serial.h
@@ -80,10 +80,14 @@ protected:  // methods
 
     virtual void send(const void* send, size_t count, Data::Code type, int dest, int tag) const;
 
+    virtual void synchronisedSend(const void* send, size_t count, Data::Code type, int dest, int tag) const;
+
     virtual Request iReceive(void* recv, size_t count, Data::Code type, int source, int tag) const;
 
     virtual Request iSend(const void* send, size_t count, Data::Code type, int dest, int tag) const;
 
+    virtual eckit::SharedBuffer broadcastFile( const eckit::PathName& filepath, size_t root ) const;
+
     virtual void print(std::ostream&) const;
 
     virtual Status status() const    { return createStatus(); }
diff --git a/eckit/src/eckit/parser/JSON.cc b/eckit/src/eckit/parser/JSON.cc
index 71d5349..4f80fe0 100644
--- a/eckit/src/eckit/parser/JSON.cc
+++ b/eckit/src/eckit/parser/JSON.cc
@@ -127,19 +127,27 @@ JSON& JSON::endList()
     return *this;
 }
 
-JSON& JSON::operator<<(const char* s)
+JSON& JSON::operator<<(bool n)
 {
     null_ = false;
     sep();
-    encode(out_, s);
+    out_ << (n ? "true": "false");
     return *this;
 }
 
-JSON& JSON::operator<<(const std::string& s)
+JSON& JSON::operator<<(char n)
 {
     null_ = false;
     sep();
-    encode(out_, s.c_str());
+    out_ << '"' << n << '"';
+    return *this;
+}
+
+JSON& JSON::operator<<(unsigned char n)
+{
+    null_ = false;
+    sep();
+    out_ << '"' << n << '"';
     return *this;
 }
 
@@ -159,23 +167,23 @@ JSON& JSON::operator<<(unsigned int n)
     return *this;
 }
 
-JSON& JSON::operator<<(char n)
+JSON& JSON::operator<<(long n)
 {
     null_ = false;
     sep();
-    out_ << '"' << n << '"';
+    out_ << n;
     return *this;
 }
 
-JSON& JSON::operator<<(bool n)
+JSON& JSON::operator<<(unsigned long n)
 {
     null_ = false;
     sep();
-    out_ << (n ? "true": "false");
+    out_ << n;
     return *this;
 }
 
-JSON& JSON::operator<<(long n)
+JSON& JSON::operator<<(long long n)
 {
     null_ = false;
     sep();
@@ -183,7 +191,7 @@ JSON& JSON::operator<<(long n)
     return *this;
 }
 
-JSON& JSON::operator<<(unsigned long n)
+JSON& JSON::operator<<(unsigned long long n)
 {
     null_ = false;
     sep();
@@ -191,7 +199,7 @@ JSON& JSON::operator<<(unsigned long n)
     return *this;
 }
 
-JSON& JSON::operator<<(long long n)
+JSON& JSON::operator<<(float n)
 {
     null_ = false;
     sep();
@@ -199,7 +207,7 @@ JSON& JSON::operator<<(long long n)
     return *this;
 }
 
-JSON& JSON::operator<<(unsigned long long n)
+JSON& JSON::operator<<(double n)
 {
     null_ = false;
     sep();
@@ -207,11 +215,19 @@ JSON& JSON::operator<<(unsigned long long n)
     return *this;
 }
 
-JSON& JSON::operator<<(double n)
+JSON& JSON::operator<<(const std::string& s)
 {
     null_ = false;
     sep();
-    out_ << n;
+    encode(out_, s.c_str());
+    return *this;
+}
+
+JSON& JSON::operator<<(const char* s)
+{
+    null_ = false;
+    sep();
+    encode(out_, s);
     return *this;
 }
 
diff --git a/eckit/src/eckit/parser/JSONParser.cc b/eckit/src/eckit/parser/JSONParser.cc
index 0b243bc..6c4cc7c 100644
--- a/eckit/src/eckit/parser/JSONParser.cc
+++ b/eckit/src/eckit/parser/JSONParser.cc
@@ -19,277 +19,29 @@
 
 namespace eckit {
 
-//----------------------------------------------------------------------------------------------------------------------
-
-Value JSONParser::parseTrue()
-{
-    consume("true");
-    return Value(true);
-}
-
-Value JSONParser::parseFalse()
-{
-    consume("false");
-    return Value(false);
-}
-
-Value JSONParser::parseNull()
-{
-    consume("null");
-    return Value();
-}
-
-Value JSONParser::parseNumber()
-{
-    bool real = false;
-    std::string s;
-    char c = next();
-    if(c == '-') {
-        s += c;
-        c = next();
-    }
-
-    switch(c) {
-    case '0': s += c; break;
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-        s += c;
-        while(isdigit(peek())) {
-            s += next();
-        }
-        break;
-    default:
-        throw StreamParser::Error(std::string("JSONTokenizer::parseNumber invalid char '") + c + "'");
-        break;
-    }
-
-    if(peek() == '.') {
-        real = true;
-        s += next();
-        c = next();
-        if(!isdigit(c))
-            throw StreamParser::Error(std::string("JSONTokenizer::parseNumber invalid char '") + c + "'");
-        s += c;
-        while(isdigit(peek())) {
-            s += next();
-        }
-    }
-
-
-    c = peek();
-    if(c == 'e' || c == 'E') {
-        real = true;
-        s += next();
-
-        c = next();
-        if(c == '-' || c == '+')
-        {
-            s += c;
-            c = next();
-        }
-
-        if(!isdigit(c))
-            throw StreamParser::Error(std::string("JSONTokenizer::parseNumber invalid char '") + c + "'");
-        s += c;
-        while(isdigit(peek())) {
-            s += next();
-        }
-
-    }
-
-    if(real) {
-        double d = Translator<std::string,double>()(s);
-        return Value(d);
-    }
-    else
-    {
-        long long d = Translator<std::string,long long>()(s);
-        return Value(d);
-    }
-}
-
-Value JSONParser::parseString()
-{
-    consume('"');
-    std::string s;
-    for(;;)
-    {
-        char c = next(true);
-        if(c == '\\')
-        {
-            c = next(true);
-            switch(c) {
-
-            case '"':
-                s += '"';
-                break;
-
-            case '\\':
-                s += '\\';
-                break;
-
-            case '/':
-                s += '/';
-                break;
-
-            case 'b':
-                s += '\b';
-                break;
-
-            case 'f':
-                s += '\f';
-                break;
-
-            case 'n':
-                s += '\n';
-                break;
-
-            case 'r':
-                s += '\r';
-                break;
 
-            case 't':
-                s += '\t';
-                break;
-
-            case 'u':
-                throw StreamParser::Error(std::string("JSONTokenizer::parseString \\uXXXX format not supported"));
-                break;
-            default:
-                throw StreamParser::Error(std::string("JSONTokenizer::parseString invalid \\ char '") + c + "'");
-                break;
-            }
-        }
-        else
-        {
-            if(c == '"')
-            {
-                return Value(s);
-            }
-            s += c;
-        }
-
-    }
-
-}
-
-void JSONParser::parseKeyValue(std::map<Value,Value>& m)
+JSONParser::JSONParser(std::istream &in):
+    ObjectParser(in, false)
 {
-    Value k = parseString();
-    consume(':');
-    Value v = parseValue();
-
-    m[k] = v;
 }
 
-Value JSONParser::parseObject()
-{
-    consume("{");
-    char c = peek();
-    if(c == '}')
-    {
-        consume(c);
-        return Value::makeMap();
-    }
-
-    std::map<Value,Value> m;
-
-    for(;;) {
-
-        parseKeyValue(m);
-
-        char c = peek();
-        if(c == '}')
-        {
-            consume(c);
-            return Value::makeMap(m);
-        }
-
-        consume(',');
-
-    }
+Value JSONParser::decodeFile(const PathName& path) {
+    std::ifstream in(std::string(path).c_str());
+    if (!in)
+        throw eckit::CantOpenFile(path);
+    return JSONParser(in).parse();
 }
 
-Value JSONParser::parseArray()
-{
-    consume("[");
-    char c = peek();
-    if(c == ']')
-    {
-        consume(c);
-        //cout << "JSONTokenizer::parseArray <== " << std::endl;;
-        return Value::makeList();
-    }
-
-    std::vector<Value> l;
-    for(;;) {
-
-        l.push_back(parseValue());
-
-        char c = peek();
-        if(c == ']')
-        {
-            consume(c);
-            //cout << "JSONTokenizer::parseArray <== " << std::endl;;
-            return Value::makeList(l);
-        }
-
-        consume(',');
-
-    }
+Value JSONParser::decodeString(const std::string& str) {
+    std::istringstream in(str);
+    return JSONParser(in).parse();
 }
 
+//----------------------------------------------------------------------------------------------------------------------
 
 Value JSONParser::parseValue()
 {
-    char c = peek();
-    switch(c)
-    {
-
-    case 't': return parseTrue(); break;
-    case 'f': return parseFalse(); break;
-    case 'n': return parseNull(); break;
-    case '{': return parseObject(); break;
-    case '[': return parseArray(); break;
-    case '\"': return parseString(); break;
-
-    case '-': return parseNumber(); break;
-    case '0': return parseNumber(); break;
-    case '1': return parseNumber(); break;
-    case '2': return parseNumber(); break;
-    case '3': return parseNumber(); break;
-    case '4': return parseNumber(); break;
-    case '5': return parseNumber(); break;
-    case '6': return parseNumber(); break;
-    case '7': return parseNumber(); break;
-    case '8': return parseNumber(); break;
-    case '9': return parseNumber(); break;
-
-    default:
-        throw StreamParser::Error(std::string("JSONTokenizer::parseValue unexpected char '") + c + "'");
-        break;
-    }
-}
-
-JSONParser::JSONParser(std::istream &in, bool comments ) : StreamParser(in,comments)
-{
-}
-
-Value JSONParser::parse()
-{
-    Value v = parseValue();
-    char c = peek();
-    if(c != 0)
-        throw StreamParser::Error(std::string("JSONTokenizer::parse extra char '") + c + "'");
-    return v;
-
+   return parseJSON();
 }
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/parser/JSONParser.h b/eckit/src/eckit/parser/JSONParser.h
index cfb623f..2f5e2ef 100644
--- a/eckit/src/eckit/parser/JSONParser.h
+++ b/eckit/src/eckit/parser/JSONParser.h
@@ -14,37 +14,28 @@
 #ifndef eckit_JSONParser_h
 #define eckit_JSONParser_h
 
-#include "eckit/parser/StreamParser.h"
-#include "eckit/types/Types.h"
-#include "eckit/value/Value.h"
+#include "eckit/parser/ObjectParser.h"
 
 namespace eckit {
 
 //----------------------------------------------------------------------------------------------------------------------
 
-class JSONParser : public StreamParser {
+class JSONParser : public ObjectParser {
 
 public: // methods
 
-    JSONParser(std::istream& in, bool comments = false);
+    JSONParser(std::istream& in);
 
-    Value parse();
+    static Value decodeFile(const PathName& path);
+    static Value decodeString(const std::string& str);
 
-private: // methods
+private:
 
-    Value parseTrue();
-    Value parseFalse();
-    Value parseNull();
-    Value parseValue();
-    Value parseObject();
-    Value parseArray();
-    Value parseString();
-    Value parseNumber();
-
-    void parseKeyValue(std::map<Value, Value> &);
+    virtual Value parseValue();
 
 };
 
+
 //----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
diff --git a/eckit/src/eckit/parser/ObjectParser.cc b/eckit/src/eckit/parser/ObjectParser.cc
new file mode 100644
index 0000000..c60f50d
--- /dev/null
+++ b/eckit/src/eckit/parser/ObjectParser.cc
@@ -0,0 +1,311 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @file   ObjectParser.h
+/// @author Baudouin Raoult
+/// @author Tiago Quintino
+/// @date   Jun 2012
+
+#include "eckit/value/Value.h"
+#include "eckit/parser/ObjectParser.h"
+#include "eckit/utils/Translator.h"
+
+namespace eckit {
+
+
+ObjectParser::~ObjectParser() {
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+Value ObjectParser::parseTrue()
+{
+    consume("true");
+    return Value(true);
+}
+
+Value ObjectParser::parseFalse()
+{
+    consume("false");
+    return Value(false);
+}
+
+Value ObjectParser::parseNull()
+{
+    consume("null");
+    return Value();
+}
+
+Value ObjectParser::parseNumber()
+{
+    bool real = false;
+    bool string = false;
+
+    std::string s;
+    char c = next();
+    if (c == '-') {
+        s += c;
+        c = next();
+    }
+
+    switch (c) {
+    case '0': s += c; break;
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+        s += c;
+        while (isdigit(peek())) {
+            s += next();
+        }
+        break;
+    default:
+        throw StreamParser::Error(std::string("ObjectParser::parseNumber invalid char '") + c + "'");
+        break;
+    }
+
+    if (peek() == '.') {
+        real = true;
+        s += next();
+        c = next();
+        if (!isdigit(c))
+            throw StreamParser::Error(std::string("ObjectParser::parseNumber invalid char '") + c + "'");
+        s += c;
+        while (isdigit(peek())) {
+            s += next();
+        }
+    }
+
+
+    c = peek();
+    if (c == 'e' || c == 'E') {
+        real = true;
+        s += next();
+
+        c = next();
+        if (c == '-' || c == '+')
+        {
+            s += c;
+            c = next();
+        }
+
+        if (!isdigit(c))
+            throw StreamParser::Error(std::string("ObjectParser::parseNumber invalid char '") + c + "'");
+        s += c;
+        while (isdigit(peek())) {
+            s += next();
+        }
+
+    }
+
+    if (string) {
+        return Value(s);
+    }
+
+    if (real) {
+        double d = Translator<std::string, double>()(s);
+        return Value(d);
+    }
+    else
+    {
+        long long d = Translator<std::string, long long>()(s);
+        return Value(d);
+    }
+}
+
+Value ObjectParser::parseString(char quote)
+{
+    consume(quote);
+    std::string s;
+    for (;;)
+    {
+        char c = next(true);
+        if (c == '\\')
+        {
+            c = next(true);
+            switch (c) {
+
+            case '\\':
+                s += '\\';
+                break;
+
+            case '/':
+                s += '/';
+                break;
+
+            case 'b':
+                s += '\b';
+                break;
+
+            case 'f':
+                s += '\f';
+                break;
+
+            case 'n':
+                s += '\n';
+                break;
+
+            case 'r':
+                s += '\r';
+                break;
+
+            case 't':
+                s += '\t';
+                break;
+
+            case 'u':
+                throw StreamParser::Error(std::string("ObjectParser::parseString \\uXXXX format not supported"));
+                break;
+
+            default:
+                if (c == quote) {
+                    s += c;
+                }
+                else {
+                    throw StreamParser::Error(std::string("ObjectParser::parseString invalid escaped char '") + c + "'");
+                }
+                break;
+            }
+        }
+        else
+        {
+            if (c == quote)
+            {
+                return Value(s);
+            }
+            s += c;
+        }
+
+    }
+
+}
+
+void ObjectParser::parseKeyValue(std::map<Value, Value>& m)
+{
+    Value k = parseString();
+    consume(':');
+    Value v = parseValue();
+
+    m[k] = v;
+}
+
+Value ObjectParser::parseObject()
+{
+    consume("{");
+    char c = peek();
+    if (c == '}')
+    {
+        consume(c);
+        return Value::makeMap();
+    }
+
+    std::map<Value, Value> m;
+
+    for (;;) {
+
+        parseKeyValue(m);
+
+        char c = peek();
+        if (c == '}')
+        {
+            consume(c);
+            return Value::makeMap(m);
+        }
+
+        consume(',');
+
+    }
+}
+
+Value ObjectParser::parseArray()
+{
+    consume("[");
+    char c = peek();
+    if (c == ']')
+    {
+        consume(c);
+        //cout << "ObjectParser::parseArray <== " << std::endl;;
+        return Value::makeList();
+    }
+
+    std::vector<Value> l;
+    for (;;) {
+
+        l.push_back(parseValue());
+
+        char c = peek();
+        if (c == ']')
+        {
+            consume(c);
+            //cout << "ObjectParser::parseArray <== " << std::endl;;
+            return Value::makeList(l);
+        }
+
+        consume(',');
+
+    }
+}
+
+
+Value ObjectParser::parseJSON()
+{
+    char c = peek();
+    switch (c)
+    {
+
+    case 't': return parseTrue(); break;
+    case 'f': return parseFalse(); break;
+    case 'n': return parseNull(); break;
+    case '{': return parseObject(); break;
+    case '[': return parseArray(); break;
+    case '\"': return parseString(); break;
+
+    case '-': return parseNumber(); break;
+    case '0': return parseNumber(); break;
+    case '1': return parseNumber(); break;
+    case '2': return parseNumber(); break;
+    case '3': return parseNumber(); break;
+    case '4': return parseNumber(); break;
+    case '5': return parseNumber(); break;
+    case '6': return parseNumber(); break;
+    case '7': return parseNumber(); break;
+    case '8': return parseNumber(); break;
+    case '9': return parseNumber(); break;
+
+    default:
+        throw StreamParser::Error(std::string("YAMLParser::parseValue unexpected char '") + c + "'");
+        break;
+    }
+}
+
+
+ObjectParser::ObjectParser(std::istream &in, bool comments):
+    StreamParser(in, comments)
+{
+}
+
+Value ObjectParser::parse()
+{
+    Value v = parseValue();
+    char c = peek();
+    if (c != 0)
+        throw StreamParser::Error(std::string("ObjectParser::parse extra char '") + c + "'");
+    return v;
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/parser/ObjectParser.h b/eckit/src/eckit/parser/ObjectParser.h
new file mode 100644
index 0000000..101d063
--- /dev/null
+++ b/eckit/src/eckit/parser/ObjectParser.h
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Baudouin Raoult
+/// @date Jun 2012
+
+#ifndef eckit_ObjectParser_h
+#define eckit_ObjectParser_h
+
+#include "eckit/parser/StreamParser.h"
+#include "eckit/types/Types.h"
+#include "eckit/value/Value.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class ObjectParser : public StreamParser {
+
+public: // methods
+
+    virtual ~ObjectParser();
+
+    virtual Value parse();
+
+protected:
+
+    ObjectParser(std::istream& in, bool comments);
+
+protected: // methods
+
+    virtual Value parseTrue();
+    virtual Value parseFalse();
+    virtual Value parseNull();
+    virtual Value parseValue() = 0;
+    virtual Value parseObject();
+    virtual Value parseArray();
+    virtual Value parseString(char quote='"');
+    virtual Value parseNumber();
+
+    virtual Value parseJSON();
+
+    virtual void parseKeyValue(std::map<Value, Value> &);
+
+};
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/parser/StreamParser.cc b/eckit/src/eckit/parser/StreamParser.cc
index ce5e218..006022b 100644
--- a/eckit/src/eckit/parser/StreamParser.cc
+++ b/eckit/src/eckit/parser/StreamParser.cc
@@ -25,6 +25,7 @@ namespace eckit {
 
 StreamParser::StreamParser(std::istream &in, bool comments, const char* comment) :
     line_(0),
+    pos_(0),
     in_(in),
     comments_(comments)
 {
@@ -33,21 +34,45 @@ StreamParser::StreamParser(std::istream &in, bool comments, const char* comment)
     }
 }
 
+char StreamParser::_get() {
+    char c = 0;
+    in_.get(c);
+    pos_++;
+    if (c == '\n') {
+        line_++;
+        pos_ = 0;
+    }
+    return c;
+}
+
+
+char StreamParser::_peek() {
+    return in_.peek();
+}
+
+bool StreamParser::_eof() {
+    return in_.eof();
+}
+
+void StreamParser::putback(char c) {
+    in_.putback(c);
+}
+
 char StreamParser::peek(bool spaces)
 {
     for (;;)
     {
-        char c = in_.peek();
+        char c = _peek();
 
-        if (in_.eof())
+        if (_eof())
             return 0;
 
         if (comments_ && comment_.find(c) != comment_.end())
         {
-            while (in_.peek() != '\n' && !in_.eof()) {
-                in_.get(c);
+            while (_peek() != '\n' && !_eof()) {
+                c = _get();
             }
-            if (in_.eof()) {
+            if (_eof()) {
                 return 0;
             }
             return peek(spaces);
@@ -60,8 +85,7 @@ char StreamParser::peek(bool spaces)
         }
         else {
 //            std::cout << "skip(" << c << ")" << std::endl;
-            in_.get(c);
-            if (c == '\n') { line_++; }
+            c = _get();
         }
     }
 }
@@ -71,18 +95,16 @@ char StreamParser::next(bool spaces)
     char c;
     for (;;)
     {
-        in_.get(c);
-        if (in_.eof())
+        c = _get();
+        if (_eof())
             throw StreamParser::Error(std::string("StreamParser::next reached eof"));
 
-        if (c == '\n') { line_++; }
-
         if (comments_ && comment_.find(c) != comment_.end())
         {
-            while (in_.peek() != '\n' && !in_.eof()) {
-                in_.get(c);
+            while (_peek() != '\n' && !_eof()) {
+                c = _get();
             }
-            if (in_.eof()) {
+            if (_eof()) {
                 throw StreamParser::Error(std::string("StreamParser::next reached eof"));
             }
             return next(spaces);
diff --git a/eckit/src/eckit/parser/StreamParser.h b/eckit/src/eckit/parser/StreamParser.h
index 92142ce..52efe12 100644
--- a/eckit/src/eckit/parser/StreamParser.h
+++ b/eckit/src/eckit/parser/StreamParser.h
@@ -44,10 +44,12 @@ public: // methods
     void consume(const char*);
 
     void expect(const char*);
+    void putback(char);
 
 protected: // members
 
     size_t line_;
+    size_t pos_;
 
 private: // members
 
@@ -56,6 +58,10 @@ private: // members
     bool comments_;
     std::set<char> comment_;
 
+    char _get();
+    char _peek();
+    bool _eof();
+
 };
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/parser/StringTools.cc b/eckit/src/eckit/parser/StringTools.cc
index 662bfd6..12af4f0 100644
--- a/eckit/src/eckit/parser/StringTools.cc
+++ b/eckit/src/eckit/parser/StringTools.cc
@@ -14,11 +14,10 @@
 #include "eckit/parser/StringTools.h"
 #include "eckit/parser/Tokenizer.h"
 
-//-----------------------------------------------------------------------------
 
 namespace eckit {
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 
 std::string StringTools::substitute(const std::string& s,const std::map<std::string,std::string>& m)
@@ -77,7 +76,12 @@ std::string StringTools::substitute(const std::string& s,const std::map<std::str
     return result;
 }
 
-std::vector<std::string> StringTools::substituteVariables(const std::string & s)
+std::vector<std::string> StringTools::substituteVariables(const std::string& s)
+{
+    return listVariables(s);
+}
+
+std::vector<std::string> StringTools::listVariables(const std::string& s)
 {
     std::vector<std::string> result;
     size_t len = s.length();
@@ -213,7 +217,7 @@ std::string StringTools::join(const std::string &delimiter, const std::vector<st
 
 bool StringTools::startsWith(const std::string& str, const std::string& substr)
 {
-    if( ! substr.size() || str.size() < substr.size() )
+    if(substr.empty() || str.size() < substr.size() )
         return false;
 
     for( std::string::size_type i = 0; i < substr.size();  ++i )
@@ -223,7 +227,26 @@ bool StringTools::startsWith(const std::string& str, const std::string& substr)
     return true;
 }
 
-//-----------------------------------------------------------------------------
+bool StringTools::beginsWith(const std::string& str, const std::string& substr)
+{
+    return startsWith(str, substr);
+}
+
+bool StringTools::endsWith(const std::string& str, const std::string& substr)
+{
+    if(substr.empty() || str.size() < substr.size())
+        return false;
+
+    std::string::const_reverse_iterator rj = str.rbegin();
+    for(std::string::const_reverse_iterator ri = substr.rbegin(); ri != substr.rend(); ++ri, ++rj) {
+        if(*ri != *rj )
+            return false;
+    }
+
+    return true;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
 
diff --git a/eckit/src/eckit/parser/StringTools.h b/eckit/src/eckit/parser/StringTools.h
index 8d2b261..2a94bfc 100644
--- a/eckit/src/eckit/parser/StringTools.h
+++ b/eckit/src/eckit/parser/StringTools.h
@@ -19,19 +19,22 @@
 
 #include "eckit/memory/NonCopyable.h"
 
-//-----------------------------------------------------------------------------
 
 namespace eckit {
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 
 class StringTools : private NonCopyable {
 public:
 
     static std::string substitute(const std::string&, const std::map<std::string, std::string>&);
+
+    /// @deprecated Use extract variables
     static std::vector<std::string>  substituteVariables( const std::string& );
 
+    static std::vector<std::string>  listVariables(const std::string&);
+
 	static std::string upper(const std::string &);
 	static std::string lower(const std::string &);
 
@@ -50,6 +53,8 @@ public:
                                                  std::vector<std::string>::const_iterator end);
 
     static bool startsWith( const std::string& str, const std::string& substr );
+    static bool beginsWith( const std::string& str, const std::string& substr );
+    static bool endsWith( const std::string& str, const std::string& substr );
 
 private:
 
@@ -58,7 +63,7 @@ private:
 };
 
 
-//-----------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------------------------
 
 } // namespace eckit
 
diff --git a/eckit/src/eckit/parser/YAMLParser.cc b/eckit/src/eckit/parser/YAMLParser.cc
new file mode 100644
index 0000000..88a20d4
--- /dev/null
+++ b/eckit/src/eckit/parser/YAMLParser.cc
@@ -0,0 +1,720 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @file   YAMLParser.h
+/// @author Baudouin Raoult
+/// @author Tiago Quintino
+/// @date   Jun 2012
+
+#include "eckit/value/Value.h"
+#include "eckit/parser/YAMLParser.h"
+#include "eckit/utils/Translator.h"
+#include "eckit/memory/Counted.h"
+#include "eckit/utils/Regex.h"
+#include "eckit/types/Time.h"
+
+namespace eckit {
+
+
+struct YAMLItem : public Counted {
+
+    long indent_;
+    Value value_;
+
+
+    virtual void print(std::ostream& s) const = 0;
+
+    virtual Value value(YAMLParser& parser) const = 0;
+
+    virtual Value parse(YAMLParser& parser) const {
+        attach(); // Don't get deleted
+        Value v = value(parser);
+        detach();
+        return v;
+    }
+
+    YAMLItem(long indent = 0, const Value& value = Value()):
+        indent_(indent),
+        value_(value) {}
+
+    virtual ~YAMLItem() {};
+
+    friend std::ostream& operator<<(std::ostream& s, const YAMLItem& item)
+    { item.print(s); return s;}
+
+
+    virtual bool isStartDocument() const { return false; }
+    virtual bool isEndDocument() const { return false; }
+    virtual bool isEOF() const { return false; }
+
+};
+
+
+struct YAMLItemEOF : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemEOF";
+    }
+
+    virtual Value value(YAMLParser& parser) const  {
+        return Value();
+    }
+
+    YAMLItemEOF(): YAMLItem(-1) {}
+    virtual bool isEOF() const { return true; }
+
+
+};
+
+
+struct YAMLItemStartDocument : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemStartDocument";
+    }
+
+
+    Value value(YAMLParser& parser) const {
+        std::vector<Value> l;
+
+        bool more = true;
+        while (more) {
+
+            l.push_back(parser.parseValue());
+
+            for (;;) {
+                const YAMLItem& next = parser.peekItem();
+                if (next.isEOF()) {
+                    more = false;
+                    break;
+                }
+
+                if (!next.isEndDocument()) {
+                    break;
+                }
+
+                parser.nextItem();
+            }
+
+        }
+
+        if (l.size() == 1) {
+            return l[0];
+        }
+
+        return Value::makeList(l);
+
+    }
+
+
+    YAMLItemStartDocument(): YAMLItem(-1) {}
+
+
+    virtual bool isStartDocument() const { return true; }
+
+};
+
+
+
+struct YAMLItemValue : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemValue[value=" << value_ << ", indent=" << indent_ << "]";
+    }
+
+    virtual Value value(YAMLParser& parser) const  {
+        return value_;
+    }
+
+    YAMLItemValue(size_t indent, const Value& value): YAMLItem(indent, value) {}
+
+};
+
+struct YAMLItemAnchor : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemAnchor[value=" << value_ << ", indent=" << indent_ << "]";
+    }
+
+    virtual Value value(YAMLParser& parser) const  {
+        Value v = parser.nextItem().value(parser);
+        parser.anchor(value_, v);
+        return v;
+    }
+
+    YAMLItemAnchor(size_t indent, const Value& value): YAMLItem(indent, value) {}
+
+};
+
+struct YAMLItemReference : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemReference[value=" << value_ << ", indent=" << indent_ << "]";
+    }
+
+    virtual Value value(YAMLParser& parser) const  {
+        return parser.anchor(value_);
+    }
+
+    YAMLItemReference(size_t indent, const Value& value): YAMLItem(indent, value) {}
+
+};
+
+struct YAMLItemKey : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemKey[value=" << value_ << ", indent=" << indent_ << "]";
+    }
+
+    YAMLItemKey(const YAMLItem& item): YAMLItem(item.indent_, item.value_) {
+        item.detach();
+        std::string v(value_);
+        ASSERT(v.size());
+        value_ = v.substr(0, v.size() - 1);
+    }
+
+    Value value(YAMLParser& parser) const {
+        std::map<Value, Value> m;
+
+
+        const YAMLItem* key = this;
+
+        bool more = true;
+        while (more) {
+
+
+            const YAMLItem& next = parser.peekItem();
+
+            if (next.indent_ == key->indent_) {
+                // Special case
+                m[key->value_] = Value(); // null
+                key = &parser.nextItem();
+                ASSERT(dynamic_cast<const YAMLItemKey*>(key));
+                continue;
+            }
+
+            if (next.indent_ < key->indent_) {
+                // Special case
+                m[key->value_] = Value(); // null
+                more = false;
+                continue;
+            }
+
+            if (next.indent_ > key->indent_) {
+                m[key->value_] = parser.nextItem().parse(parser);
+            }
+
+            const YAMLItem& peek = parser.peekItem();
+
+            if (peek.indent_ < key->indent_) {
+                more = false;
+                continue;
+            }
+
+            if (peek.indent_ == key->indent_) {
+                key = &parser.nextItem();
+                ASSERT(dynamic_cast<const YAMLItemKey*>(key));
+                continue;
+            }
+
+            std::ostringstream oss;
+            oss << "Invalid sequence " << *key << " then " << next << " then " << peek << std::endl;
+            throw eckit::SeriousBug(oss.str());
+
+        }
+
+        return Value::makeMap(m);
+
+    }
+
+};
+
+
+
+struct YAMLItemEntry : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemEntry[indent=" << indent_ << "]";
+    }
+
+    YAMLItemEntry(size_t indent): YAMLItem(indent) {}
+
+    Value value(YAMLParser& parser) const {
+        std::vector<Value> l;
+
+        bool more = true;
+        while (more) {
+
+            const YAMLItem& next = parser.peekItem();
+
+            if (next.indent_ == indent_) {
+                // Special case
+                l.push_back(Value()); // null
+                const YAMLItem* advance = &parser.nextItem();
+                ASSERT(dynamic_cast<const YAMLItemEntry*>(advance));
+                continue;
+            }
+
+            if (next.indent_ < indent_) {
+                // Special case
+                l.push_back(Value()); // null
+                more = false;
+                continue;
+            }
+
+            if (next.indent_ > indent_) {
+                l.push_back(parser.nextItem().parse(parser));
+            }
+
+            const YAMLItem& peek = parser.peekItem();
+
+            if (peek.indent_ < indent_) {
+                more = false;
+                continue;
+            }
+
+            if (peek.indent_ == indent_) {
+                const YAMLItem* advance = &parser.nextItem();
+                ASSERT(dynamic_cast<const YAMLItemEntry*>(advance));
+                continue;
+            }
+
+            std::ostringstream oss;
+            oss << "Invalid sequence " << *this << " then " << next << " then " << peek << std::endl;
+            throw eckit::SeriousBug(oss.str());
+
+
+        }
+
+        return Value::makeList(l);
+
+    }
+
+};
+
+
+
+struct YAMLItemEndDocument : public YAMLItem {
+
+    virtual void print(std::ostream& s) const {
+        s << "YAMLItemEndDocument";
+    }
+
+    virtual Value value(YAMLParser& parser) const  {
+        return Value();
+    }
+
+    YAMLItemEndDocument(): YAMLItem(-1) {}
+
+
+    virtual bool isEndDocument() const { return true; }
+
+};
+
+
+
+
+YAMLParser::YAMLParser(std::istream &in):
+    ObjectParser(in, true),
+    last_(0) {
+    stop_.push_back(0);
+    comma_.push_back(0);
+    colon_.push_back(0);
+
+}
+
+YAMLParser::~YAMLParser() {
+    for (std::deque<YAMLItem*>::iterator j = items_.begin(); j != items_.end(); ++j) {
+        (*j)->detach();
+    }
+    if (last_) {
+        last_->detach();
+    }
+}
+
+Value YAMLParser::decodeFile(const PathName& path) {
+    std::ifstream in(std::string(path).c_str());
+    if (!in)
+        throw eckit::CantOpenFile(path);
+    return YAMLParser(in).parse();
+}
+
+Value YAMLParser::decodeString(const std::string& str) {
+    std::istringstream in(str);
+    return YAMLParser(in).parse();
+}
+
+Value YAMLParser::parseString(char quote) {
+    bool ignore;
+    return parseStringOrNumber(ignore);
+}
+
+
+Value YAMLParser::parseNumber() {
+    bool ignore;
+    return parseStringOrNumber(ignore);
+}
+
+
+
+static Value toValue(const std::string& s)
+{
+
+    static Regex real("^[-+]?[0-9]+\\.?[0-9]+([eE][-+]?[0-9]+)?$", false, true);
+    static Regex integer("^[-+]?[0-9]+$", false, true);
+    static Regex hex("^0x[0-9a-zA-Z]+$", false, true);
+    static Regex octal("^0[0-9]+$", false, true);
+    static Regex time("[0-9]+:[0-9]+:[0-9]+$", false, true);
+
+    /*
+    if (time.match(s)) {
+        return Value(Time(s));
+    }
+    */
+
+    if (octal.match(s)) {
+        return Value(strtol(s.c_str(), 0, 0));
+    }
+
+    if (hex.match(s)) {
+        return Value(strtol(s.c_str(), 0, 0));
+    }
+
+    if (integer.match(s)) {
+        long long d = Translator<std::string, long long>()(s);
+        return Value(d);
+    }
+
+    if (real.match(s))
+    {
+        double d = Translator<std::string, double>()(s);
+        return Value(d);
+    }
+
+    if (s == "null") {
+        return Value();
+    }
+
+    if (s == "false") {
+        return Value(false);
+    }
+
+    if (s == "true") {
+        return Value(true);
+    }
+
+    return Value(s);
+}
+
+
+std::string YAMLParser::nextWord() {
+    std::string word;
+    char c = peek(true);
+
+    while (!(::isspace(c) || c == 0 || c == '\n')) {
+        word += next();
+        c = peek(true);
+    }
+
+    return word;
+}
+
+Value YAMLParser::consumeJSON(char ket) {
+    stop_.push_back(ket);
+    comma_.push_back(',');
+    colon_.push_back(':');
+    Value v = parseJSON();
+    stop_.pop_back();
+    comma_.pop_back();
+    colon_.pop_back();
+    return v;
+}
+
+
+size_t YAMLParser::consumeChars(char which) {
+    char c = peek(true);
+    size_t cnt = 0;
+
+    while (c == which) {
+        consume(which);
+        c = peek(true);
+        cnt++;
+    }
+
+    if(c == ' ' || c == '\n'){
+        return cnt;
+    }
+
+    while(cnt-- > 0) {
+        putback(which);
+    }
+    return 0;
+ }
+
+bool YAMLParser::endOfToken(char c) {
+    return (c == '\n' || c == 0 || c == stop_.back() || c == comma_.back() || c == colon_.back());
+}
+
+Value YAMLParser::parseStringOrNumber(bool& isKey) {
+
+    bool multi = false;
+    bool folded = false;
+    bool string = false;
+    char c = peek();
+
+    if (c == '"' || c == '\"') {
+        return ObjectParser::parseString(c);
+    }
+
+    if (c == '|') {
+        consume('|');
+        multi = true;
+        string = true;
+    }
+
+    if (c == '>') {
+        consume('>');
+        folded = true;
+        string = true;
+    }
+
+
+    c = peek();
+    size_t indent = pos_;
+    size_t line = line_;
+
+    std::string result;
+
+    bool was_indented;
+
+    while (pos_ >= indent) {
+
+        size_t start = pos_;
+        bool add_cr = (folded && (pos_ != indent)) || multi || was_indented;
+        bool add_indent = (folded && (pos_ != indent)) || multi;
+        std::string s;
+        size_t last = 0;
+        size_t i = 0;
+
+        bool colon = (c == ':');
+
+        isKey = false;
+
+        while (!endOfToken(c)) {
+            char p = next(true);
+            s += p;
+            if (!::isspace(p)) {
+                last = i;
+            }
+            c = peek(true);
+            i++;
+
+            // std::cout << "++++ " << s << " " << colon << " " << (endOfToken(c) || c == ' ') << std::endl;
+
+            if (colon && (endOfToken(c) || c == ' ')) {
+                isKey = true;
+                break;
+            }
+
+            colon = (c == ':');
+        }
+
+        if (result.size()) {
+            if (add_cr) {
+                for (size_t i = line ; i < line_ ; i++) {
+                    result += '\n';
+                }
+            }
+            else {
+                result += ' ';
+            }
+        }
+
+        if (add_indent) {
+            for (size_t i = indent ; i < start; i++) {
+                result += ' ';
+            }
+        }
+
+        result += s.substr(0, last + 1);
+        line = line_;
+
+        if (isKey) {
+            return Value(result);
+        }
+
+
+        c = peek();
+
+        if (endOfToken(c)) {
+            break;
+        }
+
+        was_indented = add_indent;
+    }
+
+    if (string) {
+        for (size_t i = line ; i < line_ ; i++) {
+            result += '\n';
+        }
+        return Value(result);
+    }
+
+    return toValue(result);
+}
+
+void YAMLParser::loadItem()
+{
+
+    if (!items_.empty()) {
+        return;
+    }
+
+    char c = peek();
+
+    size_t indent = pos_;
+
+    YAMLItem* item = 0;
+    std::string key;
+    size_t cnt = 0;
+    bool isKey = false;
+
+
+    switch (c)
+    {
+
+    case 0:
+        item = new YAMLItemEOF();
+        break;
+
+    case '{':
+        item = new YAMLItemValue(indent, consumeJSON('}'));
+        break;
+
+    case '[':
+        item = new YAMLItemValue(indent, consumeJSON(']'));
+        break;
+
+    case '\"':
+        item = new YAMLItemValue(indent, parseString());
+        break;
+
+    case '-':
+
+        cnt = consumeChars('-');
+
+        switch (cnt) {
+        case 1:
+            item = new YAMLItemEntry(indent);
+            break;
+
+        case 3:
+            item = new YAMLItemStartDocument();
+            break;
+
+        default:
+            while (cnt--) { putback('-');}
+            item = new YAMLItemValue(indent, parseStringOrNumber(isKey));
+            break;
+        }
+
+        break;
+
+    case '.':
+
+        cnt = consumeChars('.');
+
+        switch (cnt) {
+
+        case 3:
+            item = new YAMLItemEndDocument();
+            break;
+
+        default:
+            while (cnt--) { putback('.');}
+            item = new YAMLItemValue(indent, parseStringOrNumber(isKey));
+            break;
+        }
+
+        break;
+
+    case '&':
+        consume('&');
+        item = new YAMLItemAnchor(indent, nextWord());
+        break;
+
+    case '*':
+        consume('*');
+        item = new YAMLItemReference(indent, nextWord());
+        break;
+
+    default:
+        item = new YAMLItemValue(indent, parseStringOrNumber(isKey));
+        break;
+
+    }
+
+    ASSERT(item);
+
+    if (isKey) {
+        std::string v(item->value_);
+
+        if (v.size() && v[v.size() - 1] == ':') {
+            item = new YAMLItemKey(*item);
+        }
+    }
+
+    // std::cout << "item -> " << (*item) << std::endl;
+
+    item->attach();
+    items_.push_back(item);
+
+}
+
+void YAMLParser::anchor(const Value& key, const Value& value) {
+    anchors_[key] = value;
+}
+
+Value YAMLParser::anchor(const Value& key) const {
+    std::map<Value, Value>::const_iterator j = anchors_.find(key);
+    ASSERT(j != anchors_.end());
+    return (*j).second;
+}
+
+const YAMLItem& YAMLParser::nextItem() {
+    loadItem();
+    ASSERT(!items_.empty());
+
+    if (last_) {
+        last_->detach();
+    }
+
+    last_ = items_.front();
+    last_->attach();
+
+    items_.pop_front();
+
+    return *last_;
+}
+
+const YAMLItem& YAMLParser::peekItem() {
+    loadItem();
+    ASSERT(!items_.empty());
+    return *items_.front();
+}
+
+Value YAMLParser::parseValue() {
+    return nextItem().parse(*this);
+}
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/parser/YAMLParser.h b/eckit/src/eckit/parser/YAMLParser.h
new file mode 100644
index 0000000..64483e8
--- /dev/null
+++ b/eckit/src/eckit/parser/YAMLParser.h
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Baudouin Raoult
+/// @date Jun 2012
+
+#ifndef eckit_YAMLParser_h
+#define eckit_YAMLParser_h
+
+#include <deque>
+
+#include "eckit/parser/ObjectParser.h"
+
+namespace eckit {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+
+struct YAMLItem;
+
+class YAMLParser : public ObjectParser {
+
+
+
+public: // methods
+
+    YAMLParser(std::istream & in);
+    virtual ~YAMLParser();
+
+    static Value decodeFile(const PathName & path);
+    static Value decodeString(const std::string & str);
+
+private:
+
+    std::deque<YAMLItem*> items_;
+    YAMLItem* last_;
+
+    std::vector<char> stop_;
+    std::vector<char> comma_;
+    std::vector<char> colon_;
+
+    std::map<Value, Value> anchors_;
+
+private:
+
+    void loadItem();
+    const YAMLItem& nextItem();
+    const YAMLItem& peekItem();
+
+    std::string nextWord();
+    size_t consumeChars(char);
+    Value consumeJSON(char);
+
+
+    std::string nextToken(size_t& spaces, size_t& lines);
+
+    bool endOfToken(char);
+
+    virtual Value parseValue();
+
+    virtual Value parseString(char quote='"');
+    virtual Value parseNumber();
+
+    Value parseStringOrNumber(bool& isKey);
+
+
+    void anchor(const Value& key, const Value& value);
+    Value anchor(const Value& key) const;
+
+    friend struct YAMLItemKey;
+    friend struct YAMLItemEntry;
+    friend struct YAMLItemStartDocument;
+    friend struct YAMLItemEndDocument;
+    friend struct YAMLItemAnchor;
+    friend struct YAMLItemReference;
+
+};
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/runtime/Application.cc b/eckit/src/eckit/runtime/Application.cc
index fc44eea..a0b59ad 100644
--- a/eckit/src/eckit/runtime/Application.cc
+++ b/eckit/src/eckit/runtime/Application.cc
@@ -124,7 +124,7 @@ void Application::start() {
     } catch (std::exception& e) {
         status = 1;
         Log::error() << "** " << e.what() << " Caught in " << Here() << std::endl;
-        Log::error() << "** Exception is terminates " << displayName_ << std::endl;
+        Log::error() << "** Exception terminates " << displayName_ << std::endl;
     }
 
     Log::info() << "** End of " << displayName_ << " (" << argv(0) << ")  **" << std::endl;
diff --git a/eckit/src/eckit/runtime/Main.cc b/eckit/src/eckit/runtime/Main.cc
index 13ec75e..b0b6f80 100644
--- a/eckit/src/eckit/runtime/Main.cc
+++ b/eckit/src/eckit/runtime/Main.cc
@@ -9,6 +9,7 @@
 */
 
 #include <unistd.h>
+#include <stdlib.h>
 
 #include "eckit/bases/Loader.h"
 #include "eckit/filesystem/LocalPathName.h"
@@ -142,10 +143,14 @@ std::string Main::hostname()
     return hostname;
 }
 
-std::string Main::name() const {
+const std::string& Main::name() const {
     return name_;
 }
 
+const std::string& Main::displayName() const {
+    return displayName_;
+}
+
 bool Main::ready() {
     return instance_ != 0;
 }
@@ -161,6 +166,10 @@ void Main::initialise(int argc, char** argv, const char* homeenv) {
     }
 }
 
+bool Main::debug() const {
+    return debug_;
+}
+
 LogTarget* Main::createInfoLogTarget() const {
     return createDefaultLogTarget();
 }
diff --git a/eckit/src/eckit/runtime/Main.h b/eckit/src/eckit/runtime/Main.h
index b8156d2..d91a949 100644
--- a/eckit/src/eckit/runtime/Main.h
+++ b/eckit/src/eckit/runtime/Main.h
@@ -20,8 +20,6 @@ namespace eckit {
 
 //----------------------------------------------------------------------------------------------------------------------
 
-typedef void (*abort_handler_t)();
-
 class LogStream;
 class PathName;
 
@@ -52,7 +50,12 @@ public: // methods
 
     // From Configurable
 
-    virtual std::string name() const;
+    /// Name of the program as called from the command-line
+    virtual const std::string& name() const;
+
+    /// Name to display in logs. Default is name(), but can be configured
+    /// differently.
+    virtual const std::string& displayName() const;
 
     /// Ensure that there exits a Main object. This is to be used
     /// For unit tests and fortran bindinds only
@@ -61,6 +64,10 @@ public: // methods
     // To be used before main() to check if the instance is ready
     static bool ready();
 
+    // Check if debugging was set to on (either through environment variable "DEBUG=1",
+    // or command-line argument "--debug" or "-debug".
+    virtual bool debug() const;
+
     /// Channel handling
 
     virtual LogTarget* createInfoLogTarget() const;
@@ -85,9 +92,10 @@ private: // members
 
     std::string  home_; ///< path to the home, may be redefined so not necessarily the same as environment variable HOME
 
-    friend class Log;
     bool debug_;
 
+    friend class Log;
+
 };
 
 //----------------------------------------------------------------------------------------------------------------------
diff --git a/eckit/src/eckit/system/Library.cc b/eckit/src/eckit/system/Library.cc
index 9c60030..84a5c01 100644
--- a/eckit/src/eckit/system/Library.cc
+++ b/eckit/src/eckit/system/Library.cc
@@ -19,6 +19,8 @@
 #include "eckit/system/Library.h"
 
 #include "eckit/exception/Exceptions.h"
+#include "eckit/config/Resource.h"
+#include "eckit/config/YAMLConfiguration.h"
 #include "eckit/log/Log.h"
 #include "eckit/log/OStreamTarget.h"
 #include "eckit/log/PrefixTarget.h"
@@ -179,6 +181,14 @@ std::string Library::home() const
     return home_; // may return empty string (meaning not set)
 }
 
+std::string Library::libraryHome() const {
+    std::string h = home();
+    if (!h.empty()) {
+        return h;
+    }
+    return prefixDirectory();
+}
+
 void Library::libraryHome(const std::string& home)
 {
     eckit::AutoLock<Mutex> lock(mutex_);
@@ -213,6 +223,26 @@ Channel& Library::debugChannel() const
     return *debugChannel_;
 }
 
+const Configuration& Library::configuration() const
+{
+    eckit::AutoLock<Mutex> lock(mutex_);
+
+    if(configuration_) return *configuration_;
+
+    std::string s = "$" + prefix_ + "_CONFIG_PATH";
+    std::string p = "~" + name_ + "/etc/" + name_ + "/config.yaml";
+
+    eckit::PathName cfgpath = eckit::Resource<eckit::PathName>(s.c_str(), p.c_str());
+
+    eckit::Configuration* cfg = cfgpath.exists() ?
+                                    new eckit::YAMLConfiguration(cfgpath) :
+                                    new eckit::YAMLConfiguration(std::string(""));
+
+    configuration_.reset(cfg);
+
+    return *configuration_;
+}
+
 std::string Library::expandPath(const std::string& p) const {
 
     std::string s = "~" + name_;
diff --git a/eckit/src/eckit/system/Library.h b/eckit/src/eckit/system/Library.h
index ed6b67c..c72c63a 100644
--- a/eckit/src/eckit/system/Library.h
+++ b/eckit/src/eckit/system/Library.h
@@ -22,6 +22,7 @@
 #include "eckit/memory/NonCopyable.h"
 #include "eckit/memory/ScopedPtr.h"
 #include "eckit/thread/Mutex.h"
+#include "eckit/config/Configuration.h"
 
 namespace eckit {
 
@@ -44,22 +45,24 @@ public: // methods
 
     virtual std::string prefixDirectory() const;
 
+    virtual std::string libraryHome() const;
+
     virtual void libraryHome(const std::string&);
 
     virtual std::string expandPath(const std::string& path) const;
 
-//    virtual LocalPathName bin() const;
-//    virtual LocalPathName lib() const;
-//    virtual LocalPathName share() const;
-//    virtual LocalPathName etc() const;
-
     std::string libraryPath() const;
 
     virtual std::string version() const = 0;
+
     virtual std::string gitsha1(unsigned int count = 40) const = 0;
 
+    virtual bool debug() const { return debug_; }
+
     virtual Channel& debugChannel() const;
 
+    virtual const Configuration& configuration() const;
+
 public: // class methods
 
     static std::vector<std::string> list();
@@ -68,6 +71,9 @@ public: // class methods
     static bool exists(const std::string& name);
     static const Library& lookup(const std::string& name);
 
+    void lock()   { mutex_.lock(); }
+    void unlock() { mutex_.unlock(); }
+
 protected: // methods
 
     virtual std::string home() const;
@@ -97,8 +103,25 @@ private: // members
 
     mutable eckit::ScopedPtr<eckit::Channel> debugChannel_;
 
+    mutable eckit::ScopedPtr<eckit::Configuration> configuration_;
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+template <class T>
+struct LibraryRegistration {
+    LibraryRegistration() {
+        T::instance();
+    }
 };
 
+#define REGISTER_LIBRARY(X)                             \
+static eckit::system::LibraryRegistration<X> libregist; \
+void force_link_library_register_##X(void*) {           \
+    force_link_library_register_##X(&libregist);        \
+}
+
 //----------------------------------------------------------------------------------------------------------------------
 
 } // namespace system
diff --git a/eckit/src/eckit/testing/CommSetup.h b/eckit/src/eckit/testing/CommSetup.h
new file mode 100644
index 0000000..26c394a
--- /dev/null
+++ b/eckit/src/eckit/testing/CommSetup.h
@@ -0,0 +1,46 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @file   Setup.h
+/// @author Baudouin Raoult
+/// @author Tiago Quintino
+/// @date   May 2017
+
+#ifndef eckit_testing_CommSetup_h
+#define eckit_testing_CommSetup_h
+
+#include "eckit/runtime/Main.h"
+#include "eckit/mpi/Comm.h"
+
+namespace eckit {
+namespace testing {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+/// A special Setup for parallel tests because MPI needs to be explicitly finalised on the MacOSX (see ECKIT-166)
+/// If we solve that this class should disappear and use Setup directly
+
+struct CommSetup {
+    CommSetup() {
+        eckit::Main::initialise(boost::unit_test::framework::master_test_suite().argc,
+                                boost::unit_test::framework::master_test_suite().argv);
+    }
+
+    ~CommSetup() {
+        eckit::mpi::finaliseAllComms();
+    }
+ };
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace testing
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/testing/Setup.h b/eckit/src/eckit/testing/Setup.h
index f7c69ec..fb6fe21 100644
--- a/eckit/src/eckit/testing/Setup.h
+++ b/eckit/src/eckit/testing/Setup.h
@@ -30,7 +30,14 @@ struct Setup {
 
 //        eckit::Main::instance().assertDumps(false);
     }
-};
+ };
+
+//----------------------------------------------------------------------------------------------------------------------
+
+struct CommSetup : public Setup {
+    CommSetup() : Setup() {
+    }
+ };
 
 //----------------------------------------------------------------------------------------------------------------------
 
diff --git a/eckit/src/eckit/thread/ThreadControler.cc b/eckit/src/eckit/thread/ThreadControler.cc
index 3458ff6..167293c 100644
--- a/eckit/src/eckit/thread/ThreadControler.cc
+++ b/eckit/src/eckit/thread/ThreadControler.cc
@@ -106,7 +106,7 @@ void ThreadControler::execute()
     }
     catch(std::exception& e) {
         Log::error() << "** " << e.what() << " Caught in "   << Here() << std::endl;
-        Log::error() << "** Exception is terminates thread " << pthread_self() << std::endl;
+        Log::error() << "** Exception terminates thread " << pthread_self() << std::endl;
     }
 
     if(proc->autodel_)
diff --git a/eckit/src/eckit/types/Date.cc b/eckit/src/eckit/types/Date.cc
index 422100c..5f18d77 100644
--- a/eckit/src/eckit/types/Date.cc
+++ b/eckit/src/eckit/types/Date.cc
@@ -233,16 +233,16 @@ long Date::dateToJulian(long ddate)
 
 	long month,day,year;
 
-	year = ddate / 10000;
+    // Negative dates are relative to today
+    if(ddate <= 0)
+        return today() + ddate;
+
+    year = ddate / 10000;
 	ddate %= 10000;
 	month  = ddate / 100;
 	ddate %= 100;
 	day = ddate;
 
-	// Negative dates are relative to today
-	if(ddate <= 0)
-		return today() + ddate;
-
 	if(year < 100)
 	{
 //		throw SeriousBug("Please, use 4 digits dates... 2000 is near");
diff --git a/eckit/src/eckit/types/FloatCompare.cc b/eckit/src/eckit/types/FloatCompare.cc
index 5e473b3..634e5d9 100644
--- a/eckit/src/eckit/types/FloatCompare.cc
+++ b/eckit/src/eckit/types/FloatCompare.cc
@@ -1,3 +1,5 @@
+//#include <cmath>
+
 #include <math.h>
 #include <limits>
 #include <sys/types.h>
diff --git a/eckit/src/eckit/types/Fraction.cc b/eckit/src/eckit/types/Fraction.cc
index 8dce2ef..30581d1 100644
--- a/eckit/src/eckit/types/Fraction.cc
+++ b/eckit/src/eckit/types/Fraction.cc
@@ -12,21 +12,25 @@
 #include "eckit/exception/Exceptions.h"
 #include "eckit/parser/Tokenizer.h"
 #include "eckit/utils/Translator.h"
+#include "eckit/serialisation/Stream.h"
+#include "eckit/utils/MD5.h"
 
 #include <limits>
 #include <cmath>
 
+
 //-----------------------------------------------------------------------------
 
 namespace eckit {
 
-const long long max = std::sqrt(std::numeric_limits<long long>::max());
+const Fraction::value_type MAX_DENOM = std::sqrt(std::numeric_limits<Fraction::value_type>::max());
+// const Fraction::value_type MAX_DENOM = std::numeric_limits<Fraction::value_type>::max() >> 1;
 
 
-static long long gcd(long long a, long long b) {
+static Fraction::value_type gcd(Fraction::value_type a, Fraction::value_type b) {
     while (b != 0)
     {
-        long long r = a % b;
+        Fraction::value_type r = a % b;
         a = b;
         b = r;
     }
@@ -35,11 +39,11 @@ static long long gcd(long long a, long long b) {
 
 //-----------------------------------------------------------------------------
 
-Fraction::Fraction(long long top, long long bottom) {
+Fraction::Fraction(value_type top, value_type bottom) {
 
     ASSERT(bottom != 0);
 
-    long long sign = 1;
+    value_type sign = 1;
     if (top < 0) {
         top = -top;
         sign = -sign;
@@ -50,26 +54,29 @@ Fraction::Fraction(long long top, long long bottom) {
         sign = -sign;
     }
 
-    long long g = gcd(top, bottom);
-    top_ = sign * top / g;
-    bottom_ = bottom / g;
-}
+    value_type g = gcd(top, bottom);
+    top =  top / g;
+    bottom = bottom / g;
 
+    top_ = sign * top;
+    bottom_ = bottom;
+
+}
 
 Fraction::Fraction(double x) {
-    long long sign = 1;
+    value_type sign = 1;
     if (x < 0) {
         sign = -sign;
         x = -x;
     }
 
-    long long m00 = 1, m11 = 1, m01 = 0, m10 = 0;
-    long long a = x;
-    long long t2 = m10 * a + m11;
+    value_type m00 = 1, m11 = 1, m01 = 0, m10 = 0;
+    value_type a = x;
+    value_type t2 = m10 * a + m11;
 
-    while (t2 <= max) {
+    while (t2 <= MAX_DENOM) {
 
-        long long t1  = m00 * a + m01;
+        value_type t1  = m00 * a + m01;
         m01 = m00;
         m00 = t1;
 
@@ -82,7 +89,7 @@ Fraction::Fraction(double x) {
 
         x = 1.0 / (x - a);
 
-        if (x > std::numeric_limits<long long>::max()) {
+        if (x > std::numeric_limits<value_type>::max()) {
             break;
         }
 
@@ -90,8 +97,23 @@ Fraction::Fraction(double x) {
         t2 = m10 * a + m11;
     }
 
-    top_ = sign * m00;
-    bottom_ = m10;
+    while (m10 >= MAX_DENOM || m00 >= MAX_DENOM) {
+        m00 >>= 1;
+        m10 >>= 1;
+    }
+
+    value_type top = m00;
+    value_type bottom = m10;
+
+    value_type g = gcd(top, bottom);
+    top =  top / g;
+    bottom = bottom / g;
+
+    top_ = sign * top;
+    bottom_ = bottom;
+
+
+
 
 }
 
@@ -102,10 +124,13 @@ Fraction::Fraction(const std::string& s) {
     parse(s, v);
     if (v.size() > 1) {
         ASSERT(v.size() == 2);
-        static Translator<std::string, long long> s2l;
+        static Translator<std::string, value_type> s2l;
         Fraction f(s2l(v[0]), s2l(v[1]));
         top_ = f.top_;
         bottom_ = f.bottom_;
+
+
+
         return;
     }
 
@@ -114,6 +139,7 @@ Fraction::Fraction(const std::string& s) {
     top_ = f.top_;
     bottom_ = f.bottom_;
 
+
 }
 
 Fraction::Fraction(const char* c) {
@@ -123,7 +149,6 @@ Fraction::Fraction(const char* c) {
     bottom_ = f.bottom_;
 }
 
-
 void Fraction::print(std::ostream& out) const {
     if (bottom_ == 1) {
         out << top_;
@@ -133,16 +158,150 @@ void Fraction::print(std::ostream& out) const {
     }
 }
 
-Fraction::operator long long() const {
+Fraction::operator value_type() const {
     if (bottom_ == 1) {
         return top_;
     }
     std::ostringstream oss;
-    oss << "Cannot convert fraction " << *this << " to integer";
+    oss << "Cannot convert fraction " << *this << " (" << double(*this) << ") to integer";
     throw eckit::SeriousBug(oss.str());
 }
 
-//-----------------------------------------------------------------------------
+void Fraction::hash(MD5& md5) const {
+    md5 << top_;
+    md5 << bottom_;
+}
+
+
+void Fraction::encode(Stream& s) const {
+    s << top_;
+    s << bottom_;
+}
+
+void Fraction::decode(Stream& s) {
+    s >> top_;
+    s >> bottom_;
+}
+
+//======================================
+
+
+inline Fraction::value_type mul(bool& overflow, Fraction::value_type a, Fraction::value_type b) {
+    if (b > 0 && (a > std::numeric_limits<Fraction::value_type>::max() / b)) {
+        overflow = true;
+    }
+    return a * b;
+}
+
+inline Fraction::value_type add(bool& overflow, Fraction::value_type a, Fraction::value_type b) {
+
+    if (a >= 0 && b >= 0 && (a > std::numeric_limits<Fraction::value_type>::max() - b)) {
+        overflow = true;
+    }
+
+    if (a <= 0 && b <= 0 && (-a > std::numeric_limits<Fraction::value_type>::max() + b)) {
+        overflow = true;
+    }
+
+    return a + b;
+}
+
+inline Fraction::value_type sub(bool& overflow, Fraction::value_type a, Fraction::value_type b) {
+    return add(overflow, a, -b);
+}
+
+Fraction Fraction::operator+(const Fraction& other) const {
+    bool overflow = false;
+    Fraction result = Fraction(
+                          add(overflow,
+                              mul(overflow, top_, other.bottom_),
+                              mul(overflow, bottom_, other.top_)),
+                          mul(overflow, bottom_, other.bottom_));
+    if (overflow) {
+        result = Fraction(double(*this) + double(other));
+    }
+    return result;
+}
+
+Fraction Fraction::operator-(const Fraction& other) const {
+    bool overflow = false;
+    Fraction result = Fraction(
+                          sub(overflow,
+                              mul(overflow, top_, other.bottom_),
+                              mul(overflow, bottom_, other.top_)),
+                          mul(overflow, bottom_, other.bottom_));
+    if (overflow) {
+        result = Fraction(double(*this) - double(other));
+    }
+    return result;
+}
+
+Fraction Fraction::operator/(const Fraction& other) const {
+    bool overflow = false;
+    Fraction result =  Fraction(mul(overflow, top_, other.bottom_),
+                                mul(overflow, bottom_, other.top_));
+    if (overflow) {
+        result = Fraction(double(*this) / double(other));
+    }
+    return result;
+
+}
+
+Fraction Fraction::operator*(const Fraction& other) const {
+    bool overflow = false;
+    Fraction result = Fraction(mul(overflow, top_, other.top_),
+                               mul(overflow, bottom_, other.bottom_));
+    if (overflow) {
+        result = Fraction(double(*this) * double(other));
+    }
+    return result;
+}
+
+bool Fraction::operator==(const Fraction& other) const {
+    // Assumes canonical form
+    return top_ == other.top_ && bottom_ == other.bottom_;
+}
+
+bool Fraction::operator!=(const Fraction& other) const {
+    return !(*this == other);
+}
+
+bool Fraction::operator<(const Fraction& other) const {
+    bool overflow = false;
+    bool result = mul(overflow, top_, other.bottom_) < mul(overflow, other.top_, bottom_);
+    if (overflow) {
+        return double(*this) < double(other);
+    }
+    return result;
+}
+
+bool Fraction::operator<=(const Fraction& other) const {
+    bool overflow = false;
+    bool result = mul(overflow, top_, other.bottom_) <= mul(overflow, other.top_, bottom_);
+    if (overflow) {
+        return double(*this) <= double(other);
+    }
+    return result;
+}
+
+bool Fraction::operator>(const Fraction& other) const {
+    bool overflow = false;
+    bool result = mul(overflow, top_, other.bottom_) > mul(overflow, other.top_, bottom_);
+    if (overflow) {
+        return double(*this) > double(other);
+    }
+    return result;
+}
+
+bool Fraction::operator>=(const Fraction& other) const {
+    bool overflow = false;
+    bool result = mul(overflow, top_, other.bottom_) >= mul(overflow, other.top_, bottom_);
+    if (overflow) {
+        return double(*this) < double(other);
+    }
+    return result;
+}
+
 
 } // namespace eckit
 
diff --git a/eckit/src/eckit/types/Fraction.h b/eckit/src/eckit/types/Fraction.h
index 3e6ff59..2a08748 100644
--- a/eckit/src/eckit/types/Fraction.h
+++ b/eckit/src/eckit/types/Fraction.h
@@ -15,258 +15,282 @@
 #define eckit_Fraction_h
 
 #include <string>
+#include "eckit/exception/Exceptions.h"
+#include <limits>
+#include "eckit/types/FloatCompare.h"
+
 
 //-----------------------------------------------------------------------------
 
 namespace eckit {
 
+class MD5;
+class Stream;
+
 //-----------------------------------------------------------------------------
 
 
 class Fraction {
-private:
-
-	Fraction(long long top, long long bottom, bool): top_(top), bottom_(bottom) {}
+public:
+    typedef long long value_type;
 
+    // typedef __int128 value_type;
 
 public: // methods
 
+
 // -- Contructors
 
-	Fraction(): top_(0), bottom_(1) {}
+    Fraction(): top_(0), bottom_(1) {}
+
+    // template<class T>
+    // explicit Fraction(T top): top_(top), bottom_(1) {}
+
+    Fraction(value_type top, value_type bottom);
 
-	template<class T>
-	Fraction(T top): top_(top), bottom_(1) {}
+    explicit Fraction(double n);
+    explicit Fraction(int n): top_(n), bottom_(1) {}
+    explicit Fraction(short n): top_(n), bottom_(1) {}
+    explicit Fraction(long n): top_(n), bottom_(1) {}
+    explicit Fraction(long long n): top_(n), bottom_(1) {}
 
-	Fraction(long long top, long long bottom);
+    explicit Fraction(unsigned int n): top_(n), bottom_(1) {}
+    explicit Fraction(unsigned short n): top_(n), bottom_(1) {}
+    explicit Fraction(unsigned long n): top_(n), bottom_(1) {}
+    explicit Fraction(unsigned long long n): top_(n), bottom_(1) {}
 
-	Fraction(double);
-	Fraction(const std::string&);
-	Fraction(const char*);
+    // Fraction(const Fraction& other):
+    //     top_(other.top_), bottom_(other.bottom_) {}
+
+    explicit Fraction(const std::string&);
+    explicit Fraction(const char*);
+
+    bool integer() const {
+        return bottom_ == 1;
+    }
 
 public: // operators
 
-	operator double() const {
-		return double(top_) / double(bottom_);
-	}
+    operator double() const {
+        return double(top_) / double(bottom_);
+    }
+
+    operator value_type() const;
+
+    Fraction operator-()  const {
+        return Fraction(-top_, bottom_);
+    }
+
+    value_type integralPart() const {
+        return top_ / bottom_;
+    }
+
+    Fraction decimalPart() const {
+        return *this - integralPart();
+    }
+
+    Fraction operator+(const Fraction& other) const;
+
+    Fraction operator-(const Fraction& other) const;
+
+    Fraction operator/(const Fraction& other) const;
+
+    Fraction operator*(const Fraction& other) const;
+
+    bool operator==(const Fraction& other) const;
+
+    bool operator<(const Fraction& other) const;
+
+    bool operator<=(const Fraction& other) const;
+
+    bool operator!=(const Fraction& other) const;
+
+    bool operator>(const Fraction& other) const;
 
-	operator long long() const;
+    bool operator>=(const Fraction& other) const;
 
-	Fraction operator-()  const {
-		return Fraction(-top_, bottom_, true);
-	}
+    Fraction& operator+=(const Fraction& other) {
+        *this = (*this) + other;
+        return *this;
+    }
 
+    Fraction& operator-=(const Fraction& other) {
+        *this = (*this) - other;
+        return *this;
+    }
+
+    Fraction& operator/=(const Fraction& other) {
+        *this = (*this) / other;
+        return *this;
+    }
+
+    Fraction& operator*=(const Fraction& other) {
+        *this = (*this) * other;
+        return *this;
+    }
+
+    template<class T>
+    Fraction operator+(T other) const {
+        return *this + Fraction(other);
+    }
+
+    template<class T>
+    Fraction operator-(T other) const {
+        return *this - Fraction(other);
+    }
+
+    template<class T>
+    Fraction operator/(T other) const {
+        return *this / Fraction(other);
+    }
+
+    template<class T>
+    Fraction operator*(T other) const {
+        return *this * Fraction(other);
+    }
+
+    //====================================
+
+    template<class T>
+    bool operator==(T other) const {
+        return *this == Fraction(other);
+    }
+
+    template<class T>
+    bool operator<(T other) const {
+        return *this < Fraction(other);
+    }
+
+    template<class T>
+    bool operator<=(T other) const {
+        return *this <= Fraction(other);
+    }
+
+    template<class T>
+    bool operator!=(T other) const {
+        return *this != Fraction(other);
+    }
+
+    template<class T>
+    bool operator>(T other) const {
+        return *this > Fraction(other);
+    }
+
+    template<class T>
+    bool operator>=(T other) const {
+        return *this >= Fraction(other);
+    }
+
+    template<class T>
+    Fraction& operator+=(T other) {
+        return (*this) += Fraction(other);
+    }
+
+    template<class T>
+    Fraction& operator-=(T other) {
+        return (*this) -= Fraction(other);
+    }
+
+    template<class T>
+    Fraction& operator/=(T other) {
+        return (*this) /= Fraction(other);
+    }
+
+    template<class T>
+    Fraction& operator*=(T other) {
+        return (*this) *= Fraction(other);
+    }
+
+    void hash(eckit::MD5&) const;
 
-	Fraction operator+(const Fraction& other) const {
-		return Fraction(top_ * other.bottom_ + bottom_ * other.top_,
-		                bottom_ * other.bottom_);
-	}
-
-	Fraction operator-(const Fraction& other) const {
-		return Fraction(top_ * other.bottom_ - bottom_ * other.top_,
-		                bottom_ * other.bottom_);
-	}
-
-	Fraction operator/(const Fraction& other) const {
-		return Fraction(top_ * other.bottom_, bottom_ * other.top_);
-	}
-
-	Fraction operator*(const Fraction& other) const {
-		return Fraction(top_ * other.top_, bottom_ * other.bottom_);
-	}
-
-	bool operator==(const Fraction& other) const {
-		return top_ == other.top_ && bottom_ == other.bottom_;
-	}
-
-	bool operator<(const Fraction& other) const {
-		return top_ * other.bottom_ < bottom_ * other.top_;
-	}
-
-	bool operator<=(const Fraction& other) const {
-		return top_ * other.bottom_ <= bottom_ * other.top_;
-	}
-
-	bool operator!=(const Fraction& other) const {
-		return top_ * other.bottom_ != bottom_ * other.top_;
-	}
-
-	bool operator>(const Fraction& other) const {
-		return top_ * other.bottom_ > bottom_ * other.top_;
-	}
-
-	bool operator>=(const Fraction& other) const {
-		return top_ * other.bottom_ >= bottom_ * other.top_;
-	}
-
-	Fraction& operator+=(const Fraction& other) {
-		*this = (*this) + other;
-		return *this;
-	}
-
-	Fraction& operator-=(const Fraction& other) {
-		*this = (*this) - other;
-		return *this;
-	}
-
-	Fraction& operator/=(const Fraction& other) {
-		*this = (*this) / other;
-		return *this;
-	}
-
-	Fraction& operator*=(const Fraction& other) {
-		*this = (*this) * other;
-		return *this;
-	}
-
-	template<class T>
-	Fraction operator+(T other) const {
-		return *this + Fraction(other);
-	}
-
-	template<class T>
-	Fraction operator-(T other) const {
-		return *this - Fraction(other);
-	}
-
-	template<class T>
-	Fraction operator/(T other) const {
-		return *this / Fraction(other);
-	}
-
-	template<class T>
-	Fraction operator*(T other) const {
-		return *this * Fraction(other);
-	}
-
-
-	template<class T>
-	bool operator==(T other) const {
-		return *this == Fraction(other);
-	}
-
-	template<class T>
-	bool operator<(T other) const {
-		return *this < Fraction(other);
-	}
-
-	template<class T>
-	bool operator<=(T other) const {
-		return *this <= Fraction(other);
-	}
-
-	template<class T>
-	bool operator!=(T other) const {
-		return *this != Fraction(other);
-	}
-
-	template<class T>
-	bool operator>(T other) const {
-		return *this > Fraction(other);
-	}
-
-	template<class T>
-	bool operator>=(T other) const {
-		return *this >= Fraction(other);
-	}
-
-	template<class T>
-	Fraction& operator+=(T other) {
-		return (*this) += Fraction(other);
-	}
-
-	template<class T>
-	Fraction& operator-=(T other) {
-		return (*this) -= Fraction(other);
-	}
-
-	template<class T>
-	Fraction& operator/=(T other) {
-		return (*this) /= Fraction(other);
-	}
-
-	template<class T>
-	Fraction& operator*=(T other) {
-		return (*this) *= Fraction(other);
-	}
-
 private: // members
 
-	long long top_;
-	long long bottom_;
+    value_type top_;
+    value_type bottom_;
 
-	void print(std::ostream& out) const;
+    void print(std::ostream& out) const;
+    void encode(Stream& out) const;
+    void decode(Stream& out);
 
 
-	friend std::ostream& operator<<(std::ostream& s, const Fraction& x) {
-		x.print(s);
-		return s;
-	}
+    friend std::ostream& operator<<(std::ostream& s, const Fraction& x) {
+        x.print(s);
+        return s;
+    }
 
+    friend Stream& operator<<(Stream& s, const Fraction& x) {
+        x.encode(s);
+        return s;
+    }
+
+    friend Stream& operator>>(Stream& s, Fraction& x) {
+        x.decode(s);
+        return s;
+    }
 
 };
 
 template<class T>
 Fraction operator+(T n, const Fraction& f)
 {
-	return Fraction(n) + f;
+    // static_assert(std::is_same<T, long long>::value,"some meaningful error message");
+    return Fraction(n) + f;
 }
 
 template<class T>
 Fraction operator-(T n, const Fraction& f)
 {
-	return Fraction(n) - f;
+    return Fraction(n) - f;
 }
 
 template<class T>
 Fraction operator/(T n, const Fraction& f)
 {
-	return Fraction(n) / f;
+    return Fraction(n) / f;
 }
 
 template<class T>
 Fraction operator*(T n, const Fraction& f)
 {
-	return Fraction(n) * f;
+    return Fraction(n) * f;
 }
 
 template<class T>
 bool operator==(T n, const Fraction& f)
 {
-	return Fraction(n) == f;
+    return Fraction(n) == f;
 }
 
 template<class T>
 bool operator<(T n, const Fraction& f)
 {
-	return Fraction(n) < f;
+    return Fraction(n) < f;
 }
 
 template<class T>
 bool operator<=(T n, const Fraction& f)
 {
-	return Fraction(n) <= f;
+    return Fraction(n) <= f;
 }
 
 template<class T>
 bool operator!=(T n, const Fraction& f)
 {
-	return Fraction(n) != f;
+    return Fraction(n) != f;
 }
 
 template<class T>
 bool operator>(T n, const Fraction& f)
 {
-	return Fraction(n) > f;
+    return Fraction(n) > f;
 }
 
 template<class T>
 bool operator>=(T n, const Fraction& f)
 {
-	return Fraction(n) >= f;
+    return Fraction(n) >= f;
 }
 
-
 //-----------------------------------------------------------------------------
 
 } // namespace eckit
diff --git a/eckit/src/eckit/utils/Hash.h b/eckit/src/eckit/utils/Hash.h
index 1e801a2..7d01d23 100644
--- a/eckit/src/eckit/utils/Hash.h
+++ b/eckit/src/eckit/utils/Hash.h
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string>
+#include <cstring>
 
 #include "eckit/memory/NonCopyable.h"
 
@@ -65,6 +66,7 @@ public:  // methods
   void add(const void* x, long size) { update(x, size); }
 
   void add(const std::string& x) { update(x.c_str(), x.size()); }
+  void add(const char* x) { update(x, std::strlen(x)); }
 
   template<class T>
   Hash& operator<<(const T& x) { add(x); return *this; }
diff --git a/eckit/src/eckit/utils/MD5.cc b/eckit/src/eckit/utils/MD5.cc
index d1b7fa4..89ecdb3 100644
--- a/eckit/src/eckit/utils/MD5.cc
+++ b/eckit/src/eckit/utils/MD5.cc
@@ -356,6 +356,10 @@ MD5::digest_t MD5::digest() const {
     return digest_;
 }
 
+void MD5::numericalDigest(unsigned char out[MD5_DIGEST_LENGTH]) const {
+    MD5::Final(&out[0], &s_);
+}
+
 namespace  {
     HashBuilder<MD5> builder("MD5");
 }
diff --git a/eckit/src/eckit/utils/MD5.h b/eckit/src/eckit/utils/MD5.h
index 14504eb..6d29f48 100644
--- a/eckit/src/eckit/utils/MD5.h
+++ b/eckit/src/eckit/utils/MD5.h
@@ -40,9 +40,44 @@ public:  // types
 
   virtual digest_t digest() const;
 
+  // Due to C++ name lookup rules, the base class interface needs to be
+  // replicated here to be able to add the template overload, which would
+  // otherwise shadow those methods.
+
+  void add(char x){ update(&x, sizeof(x)); }
+  void add(unsigned char x){ update(&x, sizeof(x)); }
+
+  void add(bool x){ update(&x, sizeof(x)); }
+
+  void add(int x){ update(&x, sizeof(x)); }
+  void add(unsigned int x){ update(&x, sizeof(x)); }
+
+  void add(short x){ update(&x, sizeof(x)); }
+  void add(unsigned short x){ update(&x, sizeof(x)); }
+
+  void add(long x){ update(&x, sizeof(x)); }
+  void add(unsigned long x){ update(&x, sizeof(x)); }
+
+  void add(long long x){ update(&x, sizeof(x)); }
+  void add(unsigned long long x){ update(&x, sizeof(x)); }
+
+  void add(float x){ update(&x, sizeof(x)); }
+  void add(double x){ update(&x, sizeof(x)); }
+
+  void add(const void* x, long size) { update(x, size); }
+
+  void add(const std::string& x) { update(x.c_str(), x.size()); }
+  void add(const char* x) { update(x, std::strlen(x)); }
+
+  // for generic objects
+  template<class T>
+  void add(const T& x) { x.hash(*this); }
+
   template<class T>
   MD5& operator<<(const T& x) { add(x); return *this; }
 
+  void numericalDigest(unsigned char out[MD5_DIGEST_LENGTH]) const;
+
 private: // members
 
   mutable digest_t digest_;  ///< cached digest
@@ -73,4 +108,4 @@ private: // members
 
 }  // end namespace eckit
 
-#endif
\ No newline at end of file
+#endif
diff --git a/eckit/src/eckit/utils/Regex.cc b/eckit/src/eckit/utils/Regex.cc
index 5aee4fa..436575d 100644
--- a/eckit/src/eckit/utils/Regex.cc
+++ b/eckit/src/eckit/utils/Regex.cc
@@ -1,9 +1,9 @@
 /*
  * (C) Copyright 1996-2017 ECMWF.
- * 
+ *
  * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
  * granted to it by virtue of its status as an intergovernmental organisation nor
  * does it submit to any jurisdiction.
  */
@@ -20,8 +20,9 @@ namespace eckit {
 
 //-----------------------------------------------------------------------------
 
-Regex::Regex(const std::string& s,bool shell):
-	str_(s)
+Regex::Regex(const std::string& s,bool shell, bool extended):
+	str_(s),
+	extended_(extended)
 {
 	//Log::debug() << "Regex " << str_ << std::endl;
 	if(shell) {
@@ -51,7 +52,7 @@ Regex::Regex(const std::string& s,bool shell):
 				re[j++] = '\\';
 				re[j++] = '.';
 				break;
-			
+
 			case '[':
 				re[j++] = '['; i++;
 				while(i < s.length() && s[i] != ']')
@@ -85,7 +86,7 @@ void Regex::print(std::ostream& s) const
 }
 
 bool Regex::match(const std::string& s) const
-{ 
+{
 	regmatch_t pm;
 	//Log::debug() << "Match " << s << " with " << str_ << " -> " << (regexec(&re_,s.c_str(),1,&pm,0) == 0) << std::endl;
 	return regexec(&re_,s.c_str(),1,&pm,0) == 0;
@@ -93,7 +94,7 @@ bool Regex::match(const std::string& s) const
 
 void Regex::compile(const char* p)
 {
-	int n = regcomp(&re_,p,0);
+	int n = regcomp(&re_, p, extended_ ? REG_EXTENDED : 0);
 	if(n)
 	{
 		char buf[1024];
@@ -103,7 +104,8 @@ void Regex::compile(const char* p)
 }
 
 Regex::Regex(const Regex& other):
-	str_(other.str_)
+	str_(other.str_),
+	extended_(other.extended_)
 {
 	compile(str_.c_str());
 }
@@ -112,6 +114,7 @@ Regex& Regex::operator=(const Regex& other)
 {
 	regfree(&re_);
 	str_ = other.str_;
+	extended_ = other.extended_;
 	compile(str_.c_str());
 	return *this;
 }
diff --git a/eckit/src/eckit/utils/Regex.h b/eckit/src/eckit/utils/Regex.h
index 9c9149c..011252b 100644
--- a/eckit/src/eckit/utils/Regex.h
+++ b/eckit/src/eckit/utils/Regex.h
@@ -30,7 +30,7 @@ public:
 
 // -- Contructors
 
-	Regex(const std::string& = ".*",bool shell = false);
+	Regex(const std::string& = ".*",bool shell = false, bool extended=false);
 	Regex(const Regex&);
 
 	~Regex();
@@ -42,17 +42,18 @@ public:
 	bool match(const std::string& s) const;
 
 	operator const std::string&() const  { return str_; }
-    
+
 	bool operator==(const Regex& other) const { return str_ == other.str_; }
 
 protected: // methods
 
-	void print(std::ostream&) const; 
+	void print(std::ostream&) const;
 
 private: // members
 
 	std::string str_;
 	regex_t re_;
+	bool extended_;
 
 private: // methods
 
diff --git a/eckit/src/eckit/utils/Translator.cc b/eckit/src/eckit/utils/Translator.cc
index 43a464e..c12b279 100644
--- a/eckit/src/eckit/utils/Translator.cc
+++ b/eckit/src/eckit/utils/Translator.cc
@@ -58,7 +58,7 @@ bool Translator<std::string,bool>::operator()(const std::string& s)
     if(s == "yes"|| s == "on"  || s == "true")  return true;
 
     // Catter for ints
-    return atoi(s.c_str());
+    return atoi(s.c_str()); // 0 is returned on non-conversion
 }
 
 std::string Translator<int,std::string>::operator()(int value)
@@ -143,6 +143,29 @@ double Translator<std::string,double>::operator()(const std::string& s)
     //    return atof(s.c_str());
 }
 
+float Translator<std::string,float>::operator()(const std::string& s)
+{
+    char* pend;
+    errno = 0;
+
+    float f = ::strtof( s.c_str(), &pend );
+
+//    ECKIT_DEBUG_VAR( d );
+//    ECKIT_DEBUG_VAR( s );
+//    ECKIT_DEBUG_VAR( s.size() );
+//    ECKIT_DEBUG_VAR( pend - s.c_str() );
+//    ECKIT_DEBUG_VAR( errno );
+
+    if( s.empty() || s[0] == ' ' || static_cast<size_t>(pend - s.c_str()) != s.size() || (errno != 0) )
+    {
+        throw BadParameter( "Bad conversion from std::string '" + s + "' to float" , Here() );
+    }
+
+    return f;
+
+    //    return atof(s.c_str());
+}
+
 unsigned long Translator<std::string,unsigned long>::operator()(const std::string& s)
 {
     char *more;
diff --git a/eckit/src/eckit/utils/Translator.h b/eckit/src/eckit/utils/Translator.h
index 3d0a92f..21fc574 100644
--- a/eckit/src/eckit/utils/Translator.h
+++ b/eckit/src/eckit/utils/Translator.h
@@ -68,6 +68,10 @@ struct Translator<std::string,double>
     { double   operator()(const std::string&); };
 
 template<>
+struct Translator<std::string,float>
+    { float operator()(const std::string&); };
+
+template<>
 struct Translator<long,std::string>
     { std::string operator()(long);          };
 
diff --git a/eckit/src/eckit/value/DateTimeContent.cc b/eckit/src/eckit/value/DateTimeContent.cc
new file mode 100644
index 0000000..f1043f4
--- /dev/null
+++ b/eckit/src/eckit/value/DateTimeContent.cc
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+
+#include "eckit/value/DateTimeContent.h"
+#include "eckit/value/NumberContent.h"
+#include "eckit/parser/JSON.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+ClassSpec DateTimeContent::classSpec_ = {&Content::classSpec(),"DateTimeContent",};
+Reanimator<DateTimeContent> DateTimeContent::reanimator_;
+
+DateTimeContent::DateTimeContent(const DateTime& d):
+    value_(d)
+{
+}
+
+DateTimeContent::DateTimeContent(Stream& s):
+	Content(s)
+{
+	std::string dd;
+	s >> dd;
+    value_ = DateTime(dd);
+}
+
+void DateTimeContent::encode(Stream& s) const
+{
+	Content::encode(s);
+    std::string dd = value_;
+	s << dd;
+}
+
+DateTimeContent::~DateTimeContent()
+{
+}
+
+Content* DateTimeContent::clone() const {
+    return new DateTimeContent(value_);
+}
+
+void DateTimeContent::print(std::ostream& s) const
+{
+    s << value_;
+}
+
+void DateTimeContent::json(JSON& s) const
+{
+    s << std::string(value_);
+}
+
+int DateTimeContent::compare(const Content& other) const
+{
+	return -other.compareDateTime(*this);
+}
+
+int DateTimeContent::compareDateTime(const DateTimeContent& other) const
+{
+    if(value_ < other.value_)
+		return -1;
+    else if(value_ == other.value_)
+		return 1;
+
+	return 0;
+}
+
+void DateTimeContent::value(DateTime& d) const
+{
+    d = value_;
+}
+
+Content* DateTimeContent::add(const Content& other) const
+{
+	return other.addDateTime(*this);
+}
+
+Content* DateTimeContent::sub(const Content& other) const
+{
+	return other.subDateTime(*this);
+}
+
+Content* DateTimeContent::mul(const Content& other) const
+{
+    return other.mulDateTime(*this);
+}
+
+Content* DateTimeContent::div(const Content& other) const
+{
+    return other.divDateTime(*this);
+}
+
+Content* DateTimeContent::mod(const Content& other) const
+{
+    return other.modDateTime(*this);
+}
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/value/DateTimeContent.h b/eckit/src/eckit/value/DateTimeContent.h
new file mode 100644
index 0000000..32f5b43
--- /dev/null
+++ b/eckit/src/eckit/value/DateTimeContent.h
@@ -0,0 +1,112 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+// File DateTimeContent.h
+// Manuel Fuentes - ECMWF Jun 97
+
+#ifndef eckit_DateTimeContent_h
+#define eckit_DateTimeContent_h
+
+#include "eckit/value/Content.h"
+#include "eckit/value/Value.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+class DateTimeContent : public Content {
+
+protected:
+
+// -- Constructor
+
+	DateTimeContent(const DateTime&);
+	DateTimeContent(Stream&);
+
+// -- Destructor
+
+	virtual ~DateTimeContent();
+
+// -- Overridden methods
+
+	// -- From Content
+
+    virtual int compare(const Content& other) const;
+
+    virtual void value(bool& n)        const { Content::value(n); }
+    virtual void value(long long& n)   const { Content::value(n); }
+    virtual void value(double& n)      const { Content::value(n); }
+    virtual void value(std::string& n) const { Content::value(n); }
+    virtual void value(Date& n)        const { Content::value(n); }
+    virtual void value(Time& n)        const { Content::value(n); }
+    virtual void value(DateTime& n)    const;
+    virtual void value(ValueList& n)   const { Content::value(n); }
+    virtual void value(ValueMap& n)    const { Content::value(n); }
+
+    virtual int  compareBool(const BoolContent&)            const {return -1; }
+    virtual int  compareNumber(const NumberContent&)        const {return -1; }
+    virtual int  compareDouble(const DoubleContent&)        const {return -1; }
+    virtual int  compareString(const StringContent&)        const {return -1; }
+    virtual int  compareNil(const NilContent&)              const {return -1; }
+    virtual int  compareList(const ListContent&)            const {return -1; }
+    virtual int  compareMap(const MapContent&)              const {return -1; }
+    virtual int  compareDate(const DateContent&)            const {return -1; }
+    virtual int  compareTime(const TimeContent&)            const {return -1; }
+    virtual int  compareDateTime(const DateTimeContent&)    const;
+
+	virtual Content* add(const Content&) const;
+	virtual Content* sub(const Content&) const;
+	virtual Content* mul(const Content&) const;
+	virtual Content* div(const Content&) const;
+    virtual Content* mod(const Content&) const;
+
+	virtual void    print(std::ostream&) const;
+    virtual void   json(JSON&)     const;
+	virtual std::string  typeName() const       { return "DateTime"; }
+	virtual bool    isDate() const         { return true; }
+    virtual Content* clone() const;
+
+    // -- From Streamable
+
+    virtual void encode(Stream&) const;
+    virtual const ReanimatorBase& reanimator() const { return reanimator_; }
+
+// -- Class methods
+
+    static  const ClassSpec&  classSpec()            { return classSpec_;}
+
+private:
+
+	DateTimeContent(const DateTimeContent&);
+	DateTimeContent& operator=(const DateTimeContent&);
+
+// -- Members
+
+    DateTime value_;
+
+// -- Class Members
+
+	static  ClassSpec                classSpec_;
+    static  Reanimator<DateTimeContent>  reanimator_;
+
+// -- Friends
+
+	friend class Reanimator<DateTimeContent>;
+	friend class Value;
+};
+
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/value/TimeContent.cc b/eckit/src/eckit/value/TimeContent.cc
new file mode 100644
index 0000000..d0bd67d
--- /dev/null
+++ b/eckit/src/eckit/value/TimeContent.cc
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+
+#include "eckit/value/TimeContent.h"
+#include "eckit/value/NumberContent.h"
+#include "eckit/parser/JSON.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+ClassSpec TimeContent::classSpec_ = {&Content::classSpec(),"TimeContent",};
+Reanimator<TimeContent> TimeContent::reanimator_;
+
+TimeContent::TimeContent(const Time& d):
+    value_(d)
+{
+}
+
+TimeContent::TimeContent(Stream& s):
+	Content(s)
+{
+	std::string dd;
+	s >> dd;
+    value_ = Time(dd);
+}
+
+void TimeContent::encode(Stream& s) const
+{
+	Content::encode(s);
+    std::string dd = value_;
+	s << dd;
+}
+
+TimeContent::~TimeContent()
+{
+}
+
+Content* TimeContent::clone() const {
+    return new TimeContent(value_);
+}
+
+void TimeContent::print(std::ostream& s) const
+{
+    s << value_;
+}
+
+void TimeContent::json(JSON& s) const
+{
+    s << std::string(value_);
+}
+
+int TimeContent::compare(const Content& other) const
+{
+	return -other.compareTime(*this);
+}
+
+int TimeContent::compareTime(const TimeContent& other) const
+{
+    if(value_ < other.value_)
+		return -1;
+    else if(value_ == other.value_)
+		return 1;
+
+	return 0;
+}
+
+void TimeContent::value(Time& d) const
+{
+    d = value_;
+}
+
+Content* TimeContent::add(const Content& other) const
+{
+	return other.addTime(*this);
+}
+
+Content* TimeContent::sub(const Content& other) const
+{
+	return other.subTime(*this);
+}
+
+Content* TimeContent::mul(const Content& other) const
+{
+    return other.mulTime(*this);
+}
+
+Content* TimeContent::div(const Content& other) const
+{
+    return other.divTime(*this);
+}
+
+Content* TimeContent::mod(const Content& other) const
+{
+    return other.modTime(*this);
+}
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
diff --git a/eckit/src/eckit/value/TimeContent.h b/eckit/src/eckit/value/TimeContent.h
new file mode 100644
index 0000000..d8d9aca
--- /dev/null
+++ b/eckit/src/eckit/value/TimeContent.h
@@ -0,0 +1,112 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+// File TimeContent.h
+// Manuel Fuentes - ECMWF Jun 97
+
+#ifndef eckit_TimeContent_h
+#define eckit_TimeContent_h
+
+#include "eckit/value/Content.h"
+#include "eckit/value/Value.h"
+
+//-----------------------------------------------------------------------------
+
+namespace eckit {
+
+//-----------------------------------------------------------------------------
+
+class TimeContent : public Content {
+
+protected:
+
+// -- Constructor
+
+	TimeContent(const Time&);
+	TimeContent(Stream&);
+
+// -- Destructor
+
+	virtual ~TimeContent();
+
+// -- Overridden methods
+
+	// -- From Content
+
+    virtual int compare(const Content& other) const;
+
+    virtual void value(bool& n)        const { Content::value(n); }
+    virtual void value(long long& n)   const { Content::value(n); }
+    virtual void value(double& n)      const { Content::value(n); }
+    virtual void value(std::string& n) const { Content::value(n); }
+    virtual void value(Date& n)        const { Content::value(n); }
+    virtual void value(Time& n)        const;
+    virtual void value(DateTime& n)    const { Content::value(n); }
+    virtual void value(ValueList& n)   const { Content::value(n); }
+    virtual void value(ValueMap& n)    const { Content::value(n); }
+
+    virtual int  compareBool(const BoolContent&)            const {return -1; }
+    virtual int  compareNumber(const NumberContent&)        const {return -1; }
+    virtual int  compareDouble(const DoubleContent&)        const {return -1; }
+    virtual int  compareString(const StringContent&)        const {return -1; }
+    virtual int  compareNil(const NilContent&)              const {return -1; }
+    virtual int  compareList(const ListContent&)            const {return -1; }
+    virtual int  compareMap(const MapContent&)              const {return -1; }
+    virtual int  compareDate(const DateContent&)            const {return -1; }
+    virtual int  compareTime(const TimeContent&)            const;
+    virtual int  compareDateTime(const DateTimeContent&)    const {return 1; }
+
+	virtual Content* add(const Content&) const;
+	virtual Content* sub(const Content&) const;
+	virtual Content* mul(const Content&) const;
+	virtual Content* div(const Content&) const;
+    virtual Content* mod(const Content&) const;
+
+	virtual void    print(std::ostream&) const;
+    virtual void   json(JSON&)     const;
+	virtual std::string  typeName() const       { return "Time"; }
+	virtual bool    isTime() const         { return true; }
+    virtual Content* clone() const;
+
+    // -- From Streamable
+
+    virtual void encode(Stream&) const;
+    virtual const ReanimatorBase& reanimator() const { return reanimator_; }
+
+// -- Class methods
+
+    static  const ClassSpec&  classSpec()            { return classSpec_;}
+
+private:
+
+	TimeContent(const TimeContent&);
+	TimeContent& operator=(const TimeContent&);
+
+// -- Members
+
+    Time value_;
+
+// -- Class Members
+
+	static  ClassSpec                classSpec_;
+    static  Reanimator<TimeContent>  reanimator_;
+
+// -- Friends
+
+	friend class Reanimator<TimeContent>;
+	friend class Value;
+};
+
+
+//-----------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif
diff --git a/eckit/src/eckit/value/Value.cc b/eckit/src/eckit/value/Value.cc
index ebf0dcc..d0976a4 100644
--- a/eckit/src/eckit/value/Value.cc
+++ b/eckit/src/eckit/value/Value.cc
@@ -10,6 +10,8 @@
 
 
 #include "eckit/value/DateContent.h"
+#include "eckit/value/TimeContent.h"
+#include "eckit/value/DateTimeContent.h"
 #include "eckit/value/ListContent.h"
 #include "eckit/value/NilContent.h"
 #include "eckit/value/NumberContent.h"
@@ -113,6 +115,18 @@ Value::Value(const Date& d):
 	content_->attach();
 }
 
+Value::Value(const Time& d):
+    content_(new TimeContent(d))
+{
+    content_->attach();
+}
+
+Value::Value(const DateTime& d):
+    content_(new DateTimeContent(d))
+{
+    content_->attach();
+}
+
 Value::Value(Stream& s):
     content_(Reanimator<Content>::reanimate(s))
 {
diff --git a/eckit/src/eckit/value/Value.h b/eckit/src/eckit/value/Value.h
index 3b290cc..3bb1323 100644
--- a/eckit/src/eckit/value/Value.h
+++ b/eckit/src/eckit/value/Value.h
@@ -180,12 +180,12 @@ public:
 
 // -- Copy
 
-	Value(const Value&);
-	Value& operator=(const Value&);
+    Value(const Value&);
+    Value& operator=(const Value&);
 
 // -- Destructor
 
-	~Value();
+    ~Value();
 
 // -- Operators
 
@@ -284,8 +284,8 @@ public:
     bool     isTime()     const { return content_->isTime(); }
     bool     isDateTime() const { return content_->isDateTime(); }
 
-    Value	 tail() const;
-    Value	 head() const;
+    Value    tail() const;
+    Value    head() const;
 
     Value    clone() const;
     bool     shared() const; // Ensure that value is not shared
@@ -299,13 +299,14 @@ public:
     static Value makeMap();
     static Value makeMap(const ValueMap&);
 
+
 protected:
 
-	Value(Content*);
+    Value(Content*);
 
 private: // members
 
-	Content* content_;
+    Content* content_;
 
 private: // methods
 
@@ -314,36 +315,137 @@ private: // methods
     void encode(Stream& s) const    { s << *content_; }
 
     friend JSON& operator<<(JSON& s, const Value& v) { v.json(s);  return s; }
-	friend std::ostream& operator<<(std::ostream& s, const Value& v) { v.print(s);  return s; }
-	friend Stream&  operator<<(Stream&  s, const Value& v) { v.encode(s); return s; }
+    friend std::ostream& operator<<(std::ostream& s, const Value& v) { v.print(s);  return s; }
+    friend Stream&  operator<<(Stream&  s, const Value& v) { v.encode(s); return s; }
 
-	friend class Content;
+    friend class Content;
 
 };
 
 //----------------------------------------------------------------------------------------------------------------------
+template< typename T >
+Value toValue(const T& v) {
+    return Value(v);
+}
+
+template < typename T >
+Value toValue( const std::set<T>& l ) {
+    ValueList r;
+    r.reserve(l.size());
+    for (typename std::set<T>::const_iterator j = l.begin(); j != l.end(); ++j) {
+        r.push_back( toValue( *j ) );
+    }
+    return Value::makeList(r);
+}
 
 template < typename T >
-Value makeVectorValue( const std::vector<T>& v )
+Value toValue( const std::list<T>& l )
 {
     ValueList r;
-    r.reserve(v.size());
-    for( size_t i = 0; i < v.size(); ++i )
-        r.push_back( Value(v[i]) );
+    r.reserve(l.size());
+    for (typename std::list<T>::const_iterator j = l.begin(); j != l.end(); ++j) {
+        r.push_back( toValue( *j ) );
+    }
     return Value::makeList(r);
 }
 
+
 template < typename T >
-Value makeVectorValue( const std::list<T>& l )
+Value toValue( const std::vector<T>& l )
 {
     ValueList r;
     r.reserve(l.size());
-    for(typename std::list<T>::const_iterator j = l.begin(); j != l.end(); ++j) {
-        r.push_back( Value( *j ) );
+    for (typename  std::vector<T>::const_iterator j = l.begin(); j != l.end(); ++j) {
+        r.push_back( toValue( *j ) );
     }
     return Value::makeList(r);
 }
 
+
+template < typename T, typename U >
+Value toValue(const std::pair<T, U>& v) {
+    ValueList r;
+    r.push_back( v.first );
+    r.push_back( v.second );
+    return Value::makeList(r);
+}
+
+
+template < typename K, typename V >
+Value toValue(const std::map<K, V>& l) {
+    ValueMap r;
+    for (typename std::map<K, V>::const_iterator j = l.begin(); j != l.end(); ++j) {
+        r[toValue((*j).first)] = toValue((*j).second);
+    }
+    return Value::makeMap(r);
+}
+
+#ifdef __GNUC__
+#define DEPRECATED __attribute__((deprecated))
+#else
+#define DEPRECATED /**/
+#endif
+
+
+template < typename T >
+DEPRECATED
+Value makeVectorValue(const std::vector<T>& v) {
+    return toValue(v);
+}
+
+template < typename T >
+DEPRECATED
+Value makeVectorValue(const std::list<T>& v) {
+    return toValue(v);
+}
+//----------------------------------------------------------------------------------------------------------------------
+
+template< typename T >
+void fromValue(T& v, const Value& value) {
+    v = T(value);
+}
+
+template < typename T >
+void fromValue(std::vector<T>& v, const Value& value) {
+    v.clear();
+    for (size_t i = 0; i < value.size(); ++i) {
+        T tmp;
+        fromValue(tmp, value[i]);
+        v.push_back(tmp);
+    }
+}
+
+
+template < typename T, typename U >
+void fromValue(std::pair<T, U>& v, const Value& value) {
+    ASSERT(value.size() == 2);
+    fromValue(v.first, value[0]);
+    fromValue(v.second, value[1]);
+}
+
+template < typename T >
+void fromValue(std::set<T>& v, const Value& value) {
+    v.clear();
+    for (size_t i = 0; i < value.size(); ++i) {
+        T tmp;
+        fromValue(tmp, value[i]);
+        v.insert(tmp);
+    }
+}
+
+template < typename K, typename V >
+void fromValue(std::map<K, V>& v, const Value& value) {
+    v.clear();
+    Value keys = value.keys();
+    for (size_t i = 0; i < keys.size(); ++i) {
+        Value k = keys[i];
+        K key;
+
+        fromValue(key, k);
+        fromValue(v[key], value[k]);
+    }
+}
+
 //----------------------------------------------------------------------------------------------------------------------
 
 template <> struct VectorPrintSelector<Value> { typedef VectorPrintSimple selector; };
diff --git a/eckit/src/experimental/CMakeLists.txt b/eckit/src/experimental/CMakeLists.txt
index 8af53a0..7d99825 100644
--- a/eckit/src/experimental/CMakeLists.txt
+++ b/eckit/src/experimental/CMakeLists.txt
@@ -10,4 +10,3 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
 include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
 
 add_subdirectory( eckit )
-add_subdirectory( tests )
diff --git a/eckit/src/tests/CMakeLists.txt b/eckit/src/tests/CMakeLists.txt
deleted file mode 100644
index 6035a91..0000000
--- a/eckit/src/tests/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-add_subdirectory( config   )
-add_subdirectory( container )
-add_subdirectory( filesystem )
-add_subdirectory( geometry )
-add_subdirectory( io )
-add_subdirectory( large_file )
-add_subdirectory( linalg )
-add_subdirectory( log )
-add_subdirectory( maths )
-add_subdirectory( memory )
-add_subdirectory( memory_map )
-add_subdirectory( mpi )
-add_subdirectory( option )
-add_subdirectory( parser )
-add_subdirectory( runtime )
-add_subdirectory( serialisation )
-add_subdirectory( thread )
-add_subdirectory( types )
-add_subdirectory( utils )
-add_subdirectory( value )
-add_subdirectory( system )
diff --git a/eckit/src/tests/config/CMakeLists.txt b/eckit/src/tests/config/CMakeLists.txt
deleted file mode 100644
index 9793b0a..0000000
--- a/eckit/src/tests/config/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-ecbuild_add_test( TARGET   eckit_test_config
-                  BOOST
-                  SOURCES  test_config.cc
-                  ENABLED  OFF
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_resource
-                  BOOST
-                  SOURCES  test_resource.cc
-                  ARGS     -integer 100 -listlong 88,99,11,22
-                  LIBS     eckit )
diff --git a/eckit/src/tests/config/test_config.cc b/eckit/src/tests/config/test_config.cc
deleted file mode 100644
index f9c0e00..0000000
--- a/eckit/src/tests/config/test_config.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#define BOOST_TEST_MODULE test_eckit_config
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/log/Log.h"
-#include "eckit/config/Resource.h"
-#include "eckit/config/ResourceMgr.h"
-#include "eckit/types/Types.h"
-
-using namespace std;
-using namespace eckit;
-
-//-----------------------------------------------------------------------------
-// FIXME: re-enable this test
-//-----------------------------------------------------------------------------
-
-namespace eckit_test {}
-
-//-----------------------------------------------------------------------------
-
-using namespace eckit_test;
-
-BOOST_AUTO_TEST_SUITE( test_eckit_config )
-
-BOOST_AUTO_TEST_CASE( test_parse )
-{
-//     ostringstream code;
-
-//     code <<
-//             " a = 1; "                            // assign digit
-//             " b = lolo; "                         // assign string
-//             " "
-// //            " [ if class in [ od , rd ] && stream = oper ]"   // condition with multiple statement
-//             " [ if class = od || rd && stream = oper ]"   // condition with multiple statement
-//             " {  "
-//             "   fdbRoot = \'/tmp/fdb\';  "        // paths
-//             " "
-//             "   c1 = \"4 x 4\"; "                 // double quote
-//             "   [ if date = today ] "             // nested branch
-//             "   {"
-//             "       d = 4; "
-//             "   }"                                // close after semi-colon
-//             "   c2 = '5 x 5'; "                   // single quote
-//             "   cc = lolo popo   gege  ;"         // string with spaces and not quotes 'lolo popo'
-//             "   e = '6'; "
-//             "   e = '66'; "                       // override
-//             "   f : 'fofo'; "                     // assign with :
-//             " }"
-//             " "
-//             " [ if xxx = yyy ] { f = ignored; }"   // branch not visited
-//             " "
-//             " [ if xxx = yyy ] {} || { s = ss } "  // else branch visited
-//             " "
-//             " [ if class = od ] {} "               // empty branch
-//             " "
-//             " [ if class = od || rd ] { t = 22 }"  // double or in branch
-//             " "
-//             " [ if ] { h = here ; }"               // always true
-//             " "
-//             " g = go; "                         // isolated statement
-//             " "
-//             " { } "                             // empty block
-//             " "
-//             " { k = koko; } "                   // stand alone block
-//             " "
-//             " [ function foo ] { m = momo }"    // function definition
-//             " "
-//             " [ call foo ]"                     // function call
-//             " "
-//             " { j = jojo  } "                   // finish assignement with block
-//             " z1 = 11 \n"                       // finish assignement with \n
-//             " z2 = 22 #"                        // finish assignement with #
-//             ;
-
-//     istringstream in(code.str());
-
-//     config::Compiler c(in);
-
-//     config::Script s(c);
-
-// //    s.print( std::cout );
-
-//     StringDict din;
-
-//     din["class"]    = "od";
-//     din["stream"]   = "oper";
-//     din["date"]     = "today";
-
-//     StringDict dout;
-
-//     s.execute(din,dout);
-
-//     for( StringDict::const_iterator i = dout.begin(); i != dout.end(); ++i )
-//         std::cout << i->first << " : " << i->second << std::endl;
-
-//     BOOST_CHECK( dout["a"] == "1" );
-//     BOOST_CHECK( dout["b"] == "lolo" );
-//     BOOST_CHECK( dout["fdbRoot"] == "/tmp/fdb" );
-//     BOOST_CHECK( dout["c1"] == "4 x 4" );
-//     BOOST_CHECK( dout["d"] == "4" );
-//     BOOST_CHECK( dout["c2"] == "5 x 5" );
-//     BOOST_CHECK( dout["cc"] == "lolo popo   gege" );
-//     BOOST_CHECK( dout["e"] == "66" );
-//     BOOST_CHECK( dout["s"] == "ss" );
-//     BOOST_CHECK( dout["t"] == "22" );
-//     BOOST_CHECK( dout["h"] == "here" );
-//     BOOST_CHECK( dout["g"] == "go" );
-//     BOOST_CHECK( dout["k"] == "koko" );
-//     BOOST_CHECK( dout["j"] == "jojo" );
-//     BOOST_CHECK( dout["m"] == "momo" );
-//     BOOST_CHECK( dout["z1"] == "11" );
-//     BOOST_CHECK( dout["z2"] == "22" );
-
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/config/test_resource.cc b/eckit/src/tests/config/test_resource.cc
deleted file mode 100644
index 0e4f10a..0000000
--- a/eckit/src/tests/config/test_resource.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include <cmath>
-
-#define BOOST_TEST_MODULE test_eckit_resource
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/config/Resource.h"
-#include "eckit/config/ResourceMgr.h"
-#include "eckit/log/Bytes.h"
-#include "eckit/log/Log.h"
-#include "eckit/runtime/Tool.h"
-#include "eckit/types/Types.h"
-
-#include "eckit/testing/Setup.h"
-
-using namespace eckit;
-using namespace eckit::testing;
-
-//-----------------------------------------------------------------------------
-
-BOOST_GLOBAL_FIXTURE( Setup );
-
-BOOST_AUTO_TEST_SUITE( test_eckit_resource )
-
-BOOST_AUTO_TEST_CASE( test_default )
-{
-    std::string s = Resource<std::string>("s","some");
-
-    BOOST_CHECK( s == "some" );
-
-    double d = Resource<double>("d", 777.7);
-
-	BOOST_CHECK_CLOSE( d , 777.7, 0.0001 ); // accept 0.0001% tolerance
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_vector_long )
-{
-    std::vector<long> def(3,77);
-    std::vector<long> v = Resource< std::vector<long> >("listlong;-listlong",def);
-
-    BOOST_CHECK_EQUAL( v[0] , 88 );
-    BOOST_CHECK_EQUAL( v[1] , 99 );
-    BOOST_CHECK_EQUAL( v[2] , 11 );
-    BOOST_CHECK_EQUAL( v[3] , 22 );
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_command_line )
-{
-	int myint = Resource<int>("integer;-integer",0);
-	BOOST_CHECK_EQUAL( myint , 100 );
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_environment_var )
-{
-    char v [] = "TEST_ENV_INT=333";
-    putenv(v);
-
-	int intenv = Resource<int>("intEnv;$TEST_ENV_INT",777);
-	BOOST_CHECK_EQUAL( intenv , 333 );
-
-    char foo [] = "FOO=1Mb";
-    putenv(foo);
-
-	long l1 = Resource<long>("$FOO",0);
-	BOOST_CHECK_EQUAL( l1 , 1024*1024 );
-
-	long l2 = Resource<long>("$FOO;-foo",0);
-	BOOST_CHECK_EQUAL( l2 , 1024*1024);
-
-	long l3 = Resource<long>("-foo;$FOO",0);
-	BOOST_CHECK_EQUAL( l3, 1024*1024);
-
-	long l4 = Resource<long>("$FOO;foo;-foo",0);
-	BOOST_CHECK_EQUAL( l4 , 1024*1024);
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_config_file )
-{
-    // FIXME: re-enable this test
-
- //    ostringstream code;
-
- //    code << " buffer = 60 MB " << std::endl
- //         << " b = foo " << std::endl
- //         << " [ if class = od ] { b = bar }" << std::endl;
-
- //    istringstream in(code.str());
-
- //    ResourceMgr::instance().appendConfig(in);
-
- //    StringDict args;
-
- //    args["class"] = "od";
-
-	// std::string bar = Resource<string>("b","none",args);
-
-	// BOOST_CHECK_EQUAL( bar , std::string("bar") );
-
- //    unsigned long long buffer = Resource<unsigned long long>("buffer",0);
-
-	// BOOST_CHECK_EQUAL( buffer , Bytes::MiB(60) );
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE_END()
-
diff --git a/eckit/src/tests/container/CMakeLists.txt b/eckit/src/tests/container/CMakeLists.txt
deleted file mode 100644
index ac2a776..0000000
--- a/eckit/src/tests/container/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-ecbuild_add_test( TARGET   eckit_test_sharedmemarray
-                  BOOST
-                  SOURCES  test_sharedmemarray.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_btree
-                  BOOST
-                  SOURCES  test_btree.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_densemap
-                  BOOST
-                  SOURCES  test_densemap.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_cache_lru
-                  BOOST
-                  SOURCES  test_cache_lru.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_benchmark_densemap
-                  BOOST
-                  SOURCES  benchmark_densemap.cc
-                  LIBS     eckit )
diff --git a/eckit/src/tests/filesystem/CMakeLists.txt b/eckit/src/tests/filesystem/CMakeLists.txt
deleted file mode 100644
index 1247863..0000000
--- a/eckit/src/tests/filesystem/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-# aio system calls are know to fail on the Cray
-# see https://sourceware.org/bugzilla/show_bug.cgi?id=11787
-
-ecbuild_add_test( TARGET      eckit_test_multihandle
-                  SOURCES     test_multihandle.cc
-                  LIBS        eckit )
-
-ecbuild_add_test( TARGET      eckit_test_aiohandle
-                  CONDITION   NOT DEFINED ENV{CRAYOS_VERSION}
-                  SOURCES     test_aiohandle.cc
-                  LIBS        eckit )
-
-ecbuild_add_test( TARGET      eckit_test_localpathname
-                  BOOST
-                  SOURCES     test_localpathname.cc
-                  LIBS        eckit )
-
-
-ecbuild_add_test( TARGET      eckit_test_restarthandle
-                  BOOST
-                  SOURCES     test_restarthandle.cc
-                  LIBS        eckit )
diff --git a/eckit/src/tests/filesystem/test_localpathname.cc b/eckit/src/tests/filesystem/test_localpathname.cc
deleted file mode 100644
index 4600612..0000000
--- a/eckit/src/tests/filesystem/test_localpathname.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#define BOOST_TEST_MODULE test_eckit_filesystem
-
-#include <string>
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/filesystem/LocalPathName.h"
-#include "eckit/filesystem/FileSystemSize.h"
-
-#include "eckit/testing/Setup.h"
-
-using namespace std;
-using namespace eckit;
-using namespace eckit::testing;
-
-BOOST_GLOBAL_FIXTURE(Setup);
-
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE( TestLocalPathName )
-
-BOOST_AUTO_TEST_CASE( test_constructors )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_constructors");
-
-   LocalPathName p;
-   BOOST_CHECK_MESSAGE(p == "/","Expected '/'");
-
-   LocalPathName p1("/fred/bill");
-   BOOST_CHECK_MESSAGE(p1 == "/fred/bill","Expected '/fred/bill' but found " << p);
-
-   LocalPathName p2(p1);
-   BOOST_CHECK_MESSAGE(p1 == p2,"Expected p1 == p2");
-}
-
-BOOST_AUTO_TEST_CASE( test_assignment )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_assignment");
-
-   LocalPathName p;
-   LocalPathName pd;
-   p = pd;
-   BOOST_CHECK_MESSAGE(p == "/","Expected '/'");
-
-   LocalPathName p1("/fred/bill");
-   LocalPathName p2;
-   p2 = p1;
-   BOOST_CHECK_MESSAGE(p2 == "/fred/bill","Expected '/fred/bill' but found " << p);
-
-   LocalPathName p3;
-   p3 = "/fred";
-   BOOST_CHECK_MESSAGE(p3 == "/fred","Expected '/fred'");
-
-   LocalPathName p4;
-   p4 = std::string("/fredd");
-   BOOST_CHECK_MESSAGE(p4 == "/fredd","Expected '/fredd'");
-}
-
-BOOST_AUTO_TEST_CASE( test_operators )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_operators");
-
-   LocalPathName p;
-
-   p += "fred";
-
-   BOOST_CHECK_MESSAGE(p == "/fred","Expected '/fred'  but found " << p);
-
-   p += "/joe/90";
-
-   BOOST_CHECK_MESSAGE(p == "/fred/joe/90","Expected '/fred/joe/90'  but found " << p);
-
-   p += '/';
-
-   BOOST_CHECK_MESSAGE(p == "/fred/joe/90/","Expected '/fred/joe/90/'  but found " << p);
-}
-
-
-BOOST_AUTO_TEST_CASE( test_dir_name )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_dir_name");
-
-   LocalPathName p("/fred/bill");
-   BOOST_CHECK_MESSAGE(p.dirName() == "/fred","Expected dirName to be '/fred' but found " << p.dirName());
-   BOOST_CHECK_MESSAGE(p.fullName() == "/fred/bill","Expected fullName to be '/fred/bill' but found " << p.fullName());
-
-   // when no leading '/' on pathname, we append cwd to path, for fullName()
-   LocalPathName p2("fred");
-   LocalPathName expected = LocalPathName::cwd() + "/" + "fred";
-   BOOST_CHECK_MESSAGE(p2.fullName() == expected,"Expected " << expected << " but found " << p2.fullName());
-}
-
-BOOST_AUTO_TEST_CASE( test_exists )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_exists");
-
-   LocalPathName cwd = LocalPathName::cwd();
-
-   BOOST_CHECK_MESSAGE(cwd.exists(),"Current working directory must exist");
-   BOOST_CHECK_MESSAGE(cwd.isDir(),"Must be a directory");
-
-   LocalPathName acwd = LocalPathName::cwd();
-   BOOST_CHECK_MESSAGE(cwd.sameAs(acwd),"The directories must be the same");
-
-   BOOST_TEST_MESSAGE("cwd " << cwd);
-   BOOST_TEST_MESSAGE("cwd.mountPoint() " << cwd.mountPoint());
-   BOOST_TEST_MESSAGE("cwd.realName() " << cwd.realName());
-   BOOST_TEST_MESSAGE("cwd.node() " << cwd.node());
-   BOOST_TEST_MESSAGE("cwd.path() " << cwd.path());
-   BOOST_TEST_MESSAGE("size " << cwd.size());
-   BOOST_TEST_MESSAGE("lastAccess " << cwd.lastAccess());
-   BOOST_TEST_MESSAGE("lastModified " << cwd.lastModified());
-   BOOST_TEST_MESSAGE("created " << cwd.created());
-}
-
-
-BOOST_AUTO_TEST_CASE( test_basename )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_basename");
-
-   LocalPathName p1;
-   BOOST_CHECK_MESSAGE(p1.baseName(false) == "","Expected empty string  but found " << p1.baseName(false));
-   BOOST_CHECK_MESSAGE(p1.baseName(true) == "","Expected empty string  but found " << p1.baseName(true));
-
-   LocalPathName p2("fred");
-   BOOST_CHECK_MESSAGE(p2.baseName(false) == "fred","Expected 'fred' but found " << p2.baseName(false));
-   BOOST_CHECK_MESSAGE(p2.baseName(true) == "fred","Expected 'fred' but found " << p2.baseName(true));
-
-   LocalPathName p("/a/made/up/path/that/does/not/exist/file.ok");
-   BOOST_CHECK_MESSAGE(p.baseName(false) == "file","Expected 'file'  but found " << p.baseName(false));
-   BOOST_CHECK_MESSAGE(p.baseName(true) == "file.ok","Expected 'file.ok'  but found " << p.baseName(true));
-}
-
-BOOST_AUTO_TEST_CASE( test_extension )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_extension");
-
-   LocalPathName p1;
-   BOOST_CHECK_MESSAGE(p1.extension() == "", "Expected empty string  but found " << p1.extension());
-
-   LocalPathName p2("fred");
-   BOOST_CHECK_MESSAGE(p2.extension() == "", "Expected empty string  but found " << p2.extension());
-   LocalPathName p3("/path/to/fred");
-   BOOST_CHECK_MESSAGE(p3.extension() == "", "Expected empty string  but found " << p3.extension());
-   LocalPathName p4("/path/with.dot/to/fred");
-   BOOST_CHECK_MESSAGE(p4.extension() == "", "Expected empty string  but found " << p4.extension());
-
-   LocalPathName p5("fred.");
-   BOOST_CHECK_MESSAGE(p5.extension() == ".", "Expected '.'  but found " << p5.extension());
-   LocalPathName p6("/path/to/fred.ext");
-   BOOST_CHECK_MESSAGE(p6.extension() == ".ext", "Expected '.ext'  but found " << p6.extension());
-   LocalPathName p7("/path/with.dot/to/fred.ext");
-   BOOST_CHECK_MESSAGE(p7.extension() == ".ext", "Expected '.ext'  but found " << p7.extension());
-}
-
-BOOST_AUTO_TEST_CASE( test_fileSystemSize )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_fileSystemSize");
-
-   LocalPathName cwd = LocalPathName::cwd();
-   FileSystemSize fs;
-   cwd.fileSystemSize(fs);
-
-   BOOST_TEST_MESSAGE("cwd " << cwd);
-   BOOST_TEST_MESSAGE("fs.available " << fs.available);
-   BOOST_TEST_MESSAGE("fs.total " << fs.total);
-
-   BOOST_CHECK_MESSAGE(fs.available > 0,"Expected file system available  > 0 ");
-   BOOST_CHECK_MESSAGE(fs.total > 0,"Expected file system total  > 0 ");
-}
-
-BOOST_AUTO_TEST_CASE( test_unique )
-{
-   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_unique");
-
-   LocalPathName unique = LocalPathName::unique(LocalPathName::cwd());
-
-   unique.mkdir();
-
-   BOOST_CHECK_MESSAGE(unique.exists(),"Expected '" << unique << "' to exist ");
-
-   unique.rmdir();
-   BOOST_CHECK_MESSAGE(!unique.exists(),"Expected '" << unique << "' to be removed ");
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/log/test_log_channels.cc b/eckit/src/tests/log/test_log_channels.cc
deleted file mode 100644
index 49e12cf..0000000
--- a/eckit/src/tests/log/test_log_channels.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include <csignal>
-#include <cstdlib>
-#include <vector>
-#include <map>
-#include <iostream>
-#include <sstream>
-#include <locale>
-#include <fstream>
-#include <cassert>
-
-#include "eckit/os/BackTrace.h"
-#include "eckit/runtime/Tool.h"
-#include "eckit/filesystem/LocalPathName.h"
-
-#include "eckit/log/Channel.h"
-#include "eckit/log/ColouringTarget.h"
-#include "eckit/log/FileTarget.h"
-#include "eckit/log/CallbackTarget.h"
-#include "eckit/log/WrapperTarget.h"
-#include "eckit/log/OStreamTarget.h"
-
-using namespace std;
-using namespace eckit;
-
-
-#if 1
-    #define DEBUG_H
-    #define DEBUG_(x)
-#else
-    #define DEBUG_H     std::cerr << " DEBUG @ " << __FILE__ << " +" << __LINE__ << std::endl;
-    #define DEBUG_(x)   std::cerr << #x << " : [" << x << "] @ " <<  __FILE__ << " +" << __LINE__ << std::endl;
-#endif
-
-namespace eckit_test {
-
-//----------------------------------------------------------------------------------------------------------------------
-
-/// Example of a wrapper target that capitalizes all output
-
-class CapitalizerTarget : public WrapperTarget {
-public:
-
-    CapitalizerTarget(LogTarget* target) : WrapperTarget(target) {}
-
-private:
-
-    virtual void write(const char* start, const char* end) {
-
-        std::string::size_type length = std::distance(start, end);
-        buffer_.resize(length);
-
-        std::locale loc;
-        const char* p = start;
-        for (std::string::size_type i = 0; i< length; ++i, ++p) {
-          buffer_[i] = std::toupper(*p,loc);
-        }
-
-        target_->write(buffer_.c_str(), buffer_.c_str() + length);
-    }
-
-    virtual void writePrefix(){}
-    virtual void writeSuffix(){}
-
-    void print(std::ostream& s) const { s << "CapitalizerTarget()"; }
-
-    std::string buffer_;
-};
-
-//----------------------------------------------------------------------------------------------------------------------
-
-static void callback_ctxt( void* ctxt, const char* msg )
-{
-    std::cout << "[" << *((int*)ctxt) << "] : -- " << msg << std::endl ;
-}
-
-static void callback_noctxt( void* , const char* msg )
-{
-    std::cout << "[CALLBACK OUT] : -- " << msg << std::endl ;
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-class TestApp : public Tool {
-public:
-
-    TestApp(int argc,char **argv) : Tool(argc,argv) {}
-
-    ~TestApp() {}
-
-    virtual void run()
-    {
-        test_multi_targets();
-        test_multi_colouring();
-    }
-
-    void test_multi_targets() {
-        std::cout << "---> test_multi_targets()" << std::endl;
-
-        int t = 0;
-
-        Channel mychannel;
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        mychannel.addFile("test.txt");
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        std::ofstream of ("test.txt.2");
-        mychannel.addStream(of);
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        mychannel.addStream(std::cout);
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        mychannel.addStream(std::cerr);
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        std::ostringstream oss;
-        mychannel.addStream(oss);
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        mychannel.addCallback(&callback_noctxt,0);
-        mychannel.addCallback(&callback_ctxt, &t);
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        // mychannel.addLogTarget(new CapitalizerTarget(new FileTarget(PathName("capitals.txt"))));
-
-        mychannel << "testing [" << t++ << "]" << std::endl;
-
-        mychannel << "Final test" << std::endl;
-    }
-
-    void test_multi_colouring() {
-#if 0
-        Log::info().setLogTarget(    new ColouringTarget(new OStreamTarget(std::cout), &Colour::green));
-        Log::warning().setLogTarget( new ColouringTarget(new OStreamTarget(std::cerr), &Colour::yellow));
-        Log::error().setLogTarget(   new ColouringTarget(new OStreamTarget(std::cerr), &Colour::red));
-
-        Log::info()    << "Log::info() is green"     << std::endl;
-        Log::warning() << "Log::warning() is yellow" << std::endl;
-        Log::error()   << "Log::error() is red"      << std::endl;
-#endif
-    }
-};
-
-} // namespace eckit_test
-
-//----------------------------------------------------------------------------------------------------------------------
-
-void on_signal_dumpbacktrace(int signum)
-{
-    printf("Caught signal %d\n",signum);
-    std::cerr << BackTrace::dump() << std::endl;
-    ::abort();
-}
-
-int main(int argc,char **argv)
-{
-    signal(SIGSEGV, on_signal_dumpbacktrace );
-
-    eckit_test::TestApp app(argc,argv);
-    return app.start();
-}
-
diff --git a/eckit/src/tests/mpi/eckit_test_mpi.cc b/eckit/src/tests/mpi/eckit_test_mpi.cc
deleted file mode 100644
index b8202f8..0000000
--- a/eckit/src/tests/mpi/eckit_test_mpi.cc
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include "eckit/log/Log.h"
-#include "eckit/types/Types.h"
-#include "eckit/mpi/Comm.h"
-
-#define BOOST_TEST_MODULE eckit_test_mpi
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/testing/Setup.h"
-
-//----------------------------------------------------------------------------------------------------------------------
-
-// Teach boost how to write a std::vector<T>
-namespace boost {
-
-template <typename T>
-inline boost::wrap_stringstream& operator<<(boost::wrap_stringstream& wrapped, std::vector<T> const& v)
-{
-    wrapped << '[';
-    for (int j=0; j<v.size(); ++j) {
-        wrapped << (j!=0 ? "," : "") << v[j];
-    }
-    return wrapped << ']';
-}
-
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-using namespace eckit;
-using namespace eckit::testing;
-
-BOOST_GLOBAL_FIXTURE( Setup );
-
-BOOST_AUTO_TEST_CASE( test_rank_size )
-{
-    BOOST_CHECK_NO_THROW( mpi::comm().size() );
-    BOOST_CHECK_NO_THROW( mpi::comm().rank() );
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_broadcast )
-{
-  size_t root = 0;
-
-  int d[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
-
-  BOOST_TEST_CHECKPOINT("Test value");
-  {
-    float val;
-    if( mpi::comm().rank() == root ) {
-      val = 3.14f;
-    }
-
-    float* pval = &val;
-    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(val, root) );
-    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(pval, pval+1, root) );
-
-    // check results
-    BOOST_CHECK_CLOSE( val, 3.14f, 0.0001 );
-  }
-
-  BOOST_TEST_CHECKPOINT("Test vector");
-  {
-    std::vector<int> data(10);
-    if(mpi::comm().rank() == root) {
-      data.assign(d,d+10);
-    }
-    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(data, root) );
-
-    // check results
-    BOOST_CHECK_EQUAL( data.size(), 10u );
-    BOOST_CHECK_EQUAL_COLLECTIONS(data.begin(),data.end(),d,d+10);
-  }
-
-  BOOST_TEST_CHECKPOINT("Test raw data");
-  {
-    std::vector<int> data(10);
-    if( mpi::comm().rank() == root )
-    {
-      data.assign(d,d+10);
-    }
-
-    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(data.begin(), data.end(), root) );
-
-    // check results
-    BOOST_CHECK_EQUAL_COLLECTIONS(data.begin(), data.end(), d, d+10);
-  }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_gather_scalar )
-{
-    size_t size = mpi::comm().size();
-    size_t rank = mpi::comm().rank();
-
-    std::vector<size_t> recv(size);
-
-    size_t send = 777 + rank;
-
-    size_t root = 0; /* master */
-
-    BOOST_CHECK_NO_THROW( mpi::comm().gather(send, recv, root) );
-
-    if(rank == root) {
-        std::vector<size_t> expected(size);
-        for(size_t j = 0; j < recv.size(); ++j) {
-            expected[j] = 777 + j;
-        }
-
-        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-    }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_gather_nscalars )
-{
-    for(size_t N = 1; N < 10; ++N) {
-
-        size_t size = mpi::comm().size();
-        size_t rank = mpi::comm().rank();
-
-        std::vector<long> recv(size*N);
-
-        std::vector<long> send(N);
-        for(size_t n = 0; n < N; ++n) {
-            send[n] = long(rank*2 + n + 1);
-        }
-
-        std::vector<long> expected(size*N);
-        for(size_t j = 0; j < size; ++j) {
-            for(size_t n = 0; n < N; ++n) {
-                expected[j*N+n] = long(j*2 + n + 1);
-            }
-        }
-
-        size_t root = 0; /* master */
-
-        BOOST_CHECK_NO_THROW( mpi::comm().gather(send, recv, root) );
-
-        if(rank == root) {
-            BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-        }
-
-        std::vector<long> recv2(size*N);
-
-        BOOST_CHECK_NO_THROW( mpi::comm().gather(send.begin(), send.end(), recv2.begin(), recv2.end(), root) );
-
-        if(rank == root) {
-            BOOST_CHECK_EQUAL_COLLECTIONS(recv2.begin(), recv2.end(), expected.begin(), expected.end());
-        }
-    }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_gatherv_equal_stride )
-{
-    size_t root = 0;
-    size_t size = mpi::comm().size();
-    size_t rank = mpi::comm().rank();
-
-    size_t stride = 100;
-
-    std::vector<long> send(stride);
-
-    for(size_t i = 0; i < stride; ++i) {
-        send[i] = long(rank * i);
-    }
-
-    std::vector<long> recv(size * stride);
-
-    std::vector<int> displs(size);
-    std::vector<int> recvcounts(size);
-
-    for(size_t i = 0; i < size; ++i) {
-        displs[i]     = int(i*stride);
-        recvcounts[i] = int(stride);
-    }
-
-    BOOST_CHECK_NO_THROW( mpi::comm().gatherv(send, recv, recvcounts, displs, root) );
-
-    std::vector<long> expected(size * stride);
-    for(size_t i = 0; i < size; ++i) {
-        for(size_t j = 0; j < stride; ++j) {
-            expected[i*stride + j] = long(i*j);
-        }
-    }
-
-    if(rank == root) {
-        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-    }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_gatherv_unequal_stride )
-{
-    size_t root = 0;
-    size_t size = mpi::comm().size();
-    size_t rank = mpi::comm().rank();
-
-    size_t stride = 10 * rank;
-
-    std::vector<long> send(stride);
-
-    for(size_t i = 0; i < stride; ++i) {
-        send[i] = long(rank * i);
-    }
-
-    std::vector<int> displs(size);
-    std::vector<int> recvcounts(size);
-
-    for(size_t i = 0; i < size; ++i) {
-        displs[i]     = int( i ? displs[i-1] + stride : 0 );
-        recvcounts[i] = int(stride);
-    }
-
-    size_t recvsize = size_t( std::accumulate(recvcounts.begin(), recvcounts.end(), 0) );
-
-    std::vector<long> recv(recvsize);
-
-    BOOST_CHECK_NO_THROW( mpi::comm().gatherv(send, recv, recvcounts, displs, root) );
-
-    size_t e = 0;
-    std::vector<long> expected(recvsize);
-    for(size_t i = 0; i < size; ++i) {
-        for(size_t j = 0; j < stride; ++j, ++e) {
-            expected[e] = long(i*j);
-        }
-    }
-
-    if(rank == root) {
-        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-    }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_scatter_scalar )
-{
-    size_t size = mpi::comm().size();
-    std::vector<long> send(size);
-    for(size_t j = 0; j < send.size(); ++j) {
-            send[j] = long(j*j) - 1;
-    }
-
-    long recv = -999;
-
-    size_t root = 0; /* master */
-
-    BOOST_CHECK_NO_THROW( mpi::comm().scatter(send, recv, root) );
-
-    size_t rank = mpi::comm().rank();
-
-    BOOST_CHECK_EQUAL(recv, rank*rank - 1);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_scatter_nscalars )
-{
-    for(size_t N = 1; N < 4; ++N) {
-
-        size_t size = mpi::comm().size();
-        std::vector<long> send(size*N);
-        for(size_t j = 0; j < send.size() / N; ++j) {
-            for(size_t n = 0; n < N; ++n) {
-                send[j*N+n] = long(j*j - n);
-            }
-        }
-
-        std::vector<long> recv(N);
-
-        size_t root = 0; /* master */
-
-        BOOST_CHECK_NO_THROW( mpi::comm().scatter(send, recv, root) );
-
-        size_t rank = mpi::comm().rank();
-
-        // check results
-        std::vector<long> expected (N);
-        for(size_t n = 0; n < N; ++n) {
-            expected[n] = long(rank*rank - n);
-        }
-
-        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-    }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_scatterv )
-{
-     /// TODO
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_allReduce )
-{
-  int d = int(mpi::comm().rank()) + 1;
-
-  std::pair<double,int> v(-d, mpi::comm().rank());
-  std::cout << "v : " << v << std::endl;
-  std::cout << std::flush;
-  mpi::comm().barrier();
-
-  // check results
-  int s=0;
-  int p=1;
-  for( size_t j=0; j<mpi::comm().size(); ++j ) {
-    s += (j+1);
-    p *= (j+1);
-  }
-
-  BOOST_TEST_CHECKPOINT("Testing all_reduce");
-  {
-    int sum;
-    int prod;
-    int max;
-    int min;
-
-    std::pair<double,int> maxloc;
-    std::pair<double,int> minloc;
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, sum,    mpi::sum())   );
-
-    BOOST_CHECK_EQUAL( sum, s );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, prod,   mpi::prod()) );
-
-    BOOST_CHECK_EQUAL( prod, p );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, max,    mpi::max())   );
-
-    BOOST_CHECK_EQUAL( size_t(max), mpi::comm().size() );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, min,    mpi::min())   );
-
-    BOOST_CHECK_EQUAL( min, 1 );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(v, maxloc, mpi::maxloc())   );
-
-    BOOST_CHECK_EQUAL( maxloc.first, -double(1) );
-    BOOST_CHECK_EQUAL( maxloc.second, 0 );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(v, minloc, mpi::minloc())   );
-
-    BOOST_CHECK_EQUAL( minloc.first, -double(mpi::comm().size()) );
-    BOOST_CHECK_EQUAL( size_t(minloc.second), mpi::comm().size()-1 );
-  }
-
-  std::vector<float> arr(5, mpi::comm().rank()+1);
-  std::cout << "arr : " << arr << std::endl;
-
-  std::cout << std::flush;
-  mpi::comm().barrier();
-
-  BOOST_TEST_CHECKPOINT("Testing all_reduce inplace");
-  {
-    int sum = d;
-    int prod = d;
-    int max = d;
-    int min = d;
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(sum, mpi::sum())   );
-    BOOST_CHECK_EQUAL( sum, s );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(prod, mpi::prod()) );
-    BOOST_CHECK_EQUAL( prod, p );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(max, mpi::max())   );
-    BOOST_CHECK_EQUAL( size_t(max), mpi::comm().size() );
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(min, mpi::min())   );
-    BOOST_CHECK_EQUAL( min, 1 );
-
-    std::vector<float> expected;
-
-    expected = std::vector<float>(5, mpi::comm().size());
-    std::vector<float> maxvec = arr;
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(maxvec.begin(), maxvec.end(), mpi::max()) );
-    BOOST_CHECK_EQUAL_COLLECTIONS(maxvec.begin(),maxvec.end(),expected.begin(),expected.end());
-
-    expected = std::vector<float>(5,1);
-    std::vector<float> minvec = arr;
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(minvec.begin(),minvec.end(), mpi::min()) );
-    BOOST_CHECK_EQUAL_COLLECTIONS(minvec.begin(),minvec.end(),expected.begin(),expected.end());
-
-    expected = std::vector<float>(5,s);
-    std::vector<float> sumvec = arr;
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(sumvec.begin(),sumvec.end(), mpi::sum()) );
-    BOOST_CHECK_EQUAL_COLLECTIONS(sumvec.begin(),sumvec.end(),expected.begin(),expected.end());
-
-    expected = std::vector<float>(5,p);
-    std::vector<float> prodvec = arr;
-    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(prodvec.begin(),prodvec.end(), mpi::prod()) );
-    BOOST_CHECK_EQUAL_COLLECTIONS(prodvec.begin(),prodvec.end(),expected.begin(),expected.end());
-  }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_allGather )
-{
-    // Scalar
-
-    int send = mpi::comm().rank();
-    std::vector<int> recv(mpi::comm().size());
-
-    BOOST_CHECK_NO_THROW( mpi::comm().allGather(send, recv.begin(), recv.end()) );
-
-    std::vector<int> expected(mpi::comm().size());
-    for(size_t j = 0; j < expected.size(); ++j) {
-        expected[j] = int(j);
-    }
-
-    BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_allGatherv )
-{
-  std::vector<int> send(mpi::comm().rank(), mpi::comm().rank());
-  mpi::Buffer<int> recv(mpi::comm().size());
-
-  BOOST_CHECK_NO_THROW( mpi::comm().allGatherv(send.begin(), send.end(), recv) );
-
-  // check results
-  std::vector<int> expected;
-  for(size_t j=0; j<mpi::comm().size(); ++j )
-  {
-    for( size_t i=0; i<j; ++i )
-      expected.push_back(j);
-  }
-
-  BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_allToAll )
-{
-  std::vector< std::vector<int> > send(mpi::comm().size(), std::vector<int>(1, mpi::comm().rank()));
-  std::vector< std::vector<int> > recv(mpi::comm().size());
-
-  BOOST_CHECK_NO_THROW( mpi::comm().allToAll(send, recv) );
-
-  // check results
-  std::vector< std::vector<int> > expected(mpi::comm().size());
-  for(size_t j=0; j<mpi::comm().size(); ++j) {
-    expected[j] = std::vector<int>(1,int(j));
-  }
-
-  BOOST_CHECK_EQUAL(recv.size(), expected.size());
-  for (size_t i = 0; i < mpi::comm().size(); ++i) {
-      BOOST_CHECK_EQUAL_COLLECTIONS(recv[i].begin(), recv[i].end(), expected[i].begin(), expected[i].end());
-  }
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_nonblocking_send_receive )
-{
-  mpi::Comm& comm = mpi::comm("world");
-  int tag = 99;
-  mpi::Request sendreq;
-  mpi::Request recvreq;
-  double send;
-  double recv = 1.;
-
-  // Post a receive request
-  if( comm.rank() == comm.size()-1 ) {
-    recvreq = comm.iReceive(recv,0,tag);
-  }
-
-  // Post a send request
-  if( comm.rank() == 0 ) {
-    send = 0.5;
-    sendreq = comm.iSend(send,comm.size()-1,tag);
-  }
-
-  // Wait for receiving to finish
-  if( comm.rank() == comm.size()-1 ) {
-    mpi::Status recvstatus = comm.wait(recvreq);
-    BOOST_CHECK_CLOSE(recv,0.5,1.e-9);
-  }
-  else {
-    BOOST_CHECK_CLOSE(recv,1.,1.e-9);
-  }
-
-  // Wait for sending to finish
-  if( comm.rank() == 0 ) {
-    mpi::Status sendstatus = comm.wait(sendreq);
-  }
-
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_blocking_send_receive )
-{
-  mpi::Comm& comm = mpi::comm("world");
-  int tag = 99;
-  double send1, send2;
-  double recv1 = 1.;
-  double recv2 = 1.;
-
-  // Send1
-  if( comm.rank() == 0 ) {
-    send1 = 0.1;
-    comm.send(send1,comm.size()-1,tag);
-    send1 = 0.; // should not matter, as send() copies to internal mpi buffer
-  }
-
-  // Send2
-  if( comm.rank() == 0 ) {
-    send2 = 0.2;
-    comm.send(send2,comm.size()-1,tag);
-  }
-
-  // Receive1
-  if( comm.rank() == comm.size()-1 ) {
-    mpi::Status status = comm.receive(recv1,0,tag);
-    BOOST_CHECK_CLOSE(recv1,0.1,1.e-9);
-  }
-
-  // Receive2
-  if( comm.rank() == comm.size()-1 ) {
-    mpi::Status status = comm.receive(recv2,0,tag);
-    BOOST_CHECK_CLOSE(recv2,0.2,1.e-9);
-  }
-
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-
-BOOST_AUTO_TEST_CASE( test_allToAllv )
-{
-    // TODO
-}
diff --git a/eckit/src/tests/mpi/eckit_test_mpi_addcomm.cc b/eckit/src/tests/mpi/eckit_test_mpi_addcomm.cc
deleted file mode 100644
index f39ffd8..0000000
--- a/eckit/src/tests/mpi/eckit_test_mpi_addcomm.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include <mpi.h>
-
-#include "eckit/mpi/Comm.h"
-
-int main( int argc, char** argv )
-{
-    MPI_Init(&argc, &argv);
-
-    MPI_Fint fortranComm = MPI_Comm_c2f(MPI_COMM_WORLD);
-
-    eckit::mpi::addComm("fort.1", fortranComm);
-
-    eckit::mpi::setCommDefault("fort.1");
-
-    MPI_Finalize();
-
-    return 0;
-}
diff --git a/eckit/src/tests/parser/CMakeLists.txt b/eckit/src/tests/parser/CMakeLists.txt
deleted file mode 100644
index 9d63fbc..0000000
--- a/eckit/src/tests/parser/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-ecbuild_add_test( TARGET   eckit_test_json
-                  BOOST
-                  SOURCES  test_json.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_json_metadata
-                  BOOST
-                  SOURCES  test_json_metadata.cc
-                  LIBS     eckit )
-
-ecbuild_add_test( TARGET   eckit_test_stream_parser
-                  BOOST
-                  SOURCES  test_stream_parser.cc
-                  LIBS     eckit )
diff --git a/eckit/src/tests/system/test_system.cc b/eckit/src/tests/system/test_system.cc
deleted file mode 100755
index be7cc03..0000000
--- a/eckit/src/tests/system/test_system.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include <iostream>
-#include <cstdlib>
-
-#define BOOST_TEST_MODULE test_eckit_system
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/exception/Exceptions.h"
-
-#include "eckit/system/ResourceUsage.h"
-#include "eckit/system/SystemInfo.h"
-#include "eckit/system/Library.h"
-#include "eckit/filesystem/LocalPathName.h"
-
-#include "eckit/testing/Setup.h"
-
-using namespace eckit;
-using namespace eckit::testing;
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_GLOBAL_FIXTURE(Setup);
-
-BOOST_AUTO_TEST_SUITE( test_eckit_resource_usage )
-
-BOOST_AUTO_TEST_CASE( test_eckit_resource_usage_0 )
-{
-    size_t chunk = 20*1024*1024;
-    for(size_t i = 1; i < 5; ++i) {
-
-        size_t before = system::ResourceUsage().maxResidentSetSize();
-
-        void *m = ::malloc(chunk);
-        ::memset(m,0,chunk);
-
-        size_t after = system::ResourceUsage().maxResidentSetSize();
-
-        ::free(m);
-
-        BOOST_TEST_MESSAGE( "Memory usage " << after );
-
-        BOOST_REQUIRE( before <= after );
-    }
-}
-
-BOOST_AUTO_TEST_CASE( test_eckit_system_info )
-{
-    eckit::LocalPathName execPath;
-    BOOST_CHECK_NO_THROW( execPath = eckit::system::SystemInfo::instance().executablePath() );
-    BOOST_CHECK( std::string(execPath).size() );
-
-    Log::info() << "execPath is " << execPath << std::endl;
-}
-
-BOOST_AUTO_TEST_CASE( test_eckit_system_library )
-{
-    using eckit::system::Library;
-
-    std::vector<std::string> libs = Library::list();
-
-    std::string libpath;
-
-    for(std::vector<std::string>::const_iterator libname = libs.begin(); libname != libs.end(); ++libname ) {
-
-        BOOST_CHECK_NO_THROW( Library::lookup(*libname) );
-
-        const Library& lib = Library::lookup(*libname);
-
-        BOOST_CHECK_NO_THROW( lib.prefixDirectory() );
-
-        Log::info() << "Library " << lib.name() << " @ " << lib.prefixDirectory() << std::endl;
-        Log::info() << lib << std::endl;
-    }
-
-    // this exercises the tilde expansion
-
-    BOOST_CHECK_NO_THROW( LocalPathName("~eckit/etc").exists() );
-    BOOST_CHECK_NO_THROW( LocalPathName("~eckit/etc/eckit/test/test.cfg").exists() );
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
diff --git a/eckit/src/tests/types/test_fraction.cc b/eckit/src/tests/types/test_fraction.cc
deleted file mode 100644
index 06b134c..0000000
--- a/eckit/src/tests/types/test_fraction.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#define BOOST_TEST_MODULE test_eckit_fraction
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/types/Fraction.h"
-
-#include "eckit/testing/Setup.h"
-
-
-using namespace eckit;
-using namespace eckit::testing;
-
-BOOST_GLOBAL_FIXTURE( Setup );
-
-BOOST_AUTO_TEST_SUITE( test_eckit_fraction )
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_fraction )
-{
-    // 0
-
-    BOOST_CHECK_EQUAL( Fraction(0, 1), Fraction() );
-
-    BOOST_CHECK_THROW( Fraction(0, 0), std::exception ); // this prints a backtrace wi Assertion failed
-
-    // negative number
-
-    BOOST_CHECK_EQUAL( Fraction(-1, 2), Fraction(3, -6) );
-
-    // decimals
-
-    BOOST_CHECK_EQUAL( Fraction(0.16), Fraction(16, 100) );
-    BOOST_CHECK_EQUAL( Fraction(0.1616), Fraction(1616, 10000) );
-
-    // 5 / 7
-
-    BOOST_CHECK( Fraction(0.714285) != Fraction(5, 7) );
-
-    BOOST_CHECK( Fraction(0.7142857142) != Fraction(5, 7) );
-
-    BOOST_CHECK_EQUAL( Fraction(0.71428571428),  Fraction(5, 7) );
-    BOOST_CHECK_EQUAL( Fraction(0.714285714285), Fraction(5, 7) );
-    BOOST_CHECK_EQUAL( Fraction(0.714285714286), Fraction(5, 7) );
-
-    BOOST_CHECK_EQUAL( Fraction(0.714285714285714285), Fraction(5, 7) );
-
-    // 1 / 6
-
-    BOOST_CHECK( Fraction(0.166) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.1666) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.16666) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.166666) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.1666666) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.16666666) != Fraction(1, 6) );
-    BOOST_CHECK( Fraction(0.166666666) != Fraction(1, 6) );
-
-    BOOST_CHECK_EQUAL( Fraction(0.16666666666), Fraction(1, 6) );
-    BOOST_CHECK_EQUAL( Fraction(0.166666666666), Fraction(1, 6) );
-    BOOST_CHECK_EQUAL( Fraction(0.1666666666666), Fraction(1, 6) );
-    BOOST_CHECK_EQUAL( Fraction(0.16666666666666), Fraction(1, 6) );
-    BOOST_CHECK_EQUAL( Fraction(0.166666666666666), Fraction(1, 6) );
-    BOOST_CHECK_EQUAL( Fraction(0.1666666666666666), Fraction(1, 6) );
-
-    // 1 / 3
-
-    BOOST_CHECK_EQUAL( Fraction(0.3333333333), Fraction(1, 3) );
-
-    BOOST_CHECK_EQUAL( Fraction(0.3333333333333333), Fraction(1, 3) );
-
-    // 1 / 1
-
-    BOOST_CHECK_EQUAL( Fraction(0.9999999999999999), Fraction(1, 1) );
-    BOOST_CHECK_EQUAL( Fraction(0.9999999999999999), Fraction(10, 10) );
-
-    // 7 / 10..
-
-    BOOST_CHECK_EQUAL( Fraction(0.7), Fraction(7, 10) );
-    BOOST_CHECK_EQUAL( Fraction(0.07), Fraction(7, 100) );
-    BOOST_CHECK_EQUAL( Fraction(0.0000007), Fraction(7, 10000000) );
-
-    // operations
-
-    BOOST_CHECK_EQUAL( Fraction(1, 3) + Fraction(2, 3), Fraction(10, 10) );
-    BOOST_CHECK_EQUAL( Fraction(1, 3) - Fraction(2, 6), Fraction(0, 10) );
-
-    BOOST_CHECK_EQUAL( Fraction(1, 3) * 3, Fraction(1) );
-
-    BOOST_CHECK_EQUAL( -Fraction(1, 3), Fraction(1, -3) );
-
-    BOOST_CHECK_EQUAL( 2 * Fraction(1, 3) , Fraction(2, 3) );
-
-    Fraction a(1, 3);
-    Fraction b(3, 28);
-    BOOST_CHECK_EQUAL(a + b, Fraction(37, 84));
-    BOOST_CHECK_EQUAL(a - b, Fraction(19, 84));
-    BOOST_CHECK_EQUAL(a * b, Fraction(1, 28));
-    BOOST_CHECK_EQUAL(a / b, Fraction(28, 9));
-
-    BOOST_CHECK_EQUAL(a > b, true);
-    BOOST_CHECK_EQUAL(a != b, true);
-    BOOST_CHECK_EQUAL(a < b, false);
-    BOOST_CHECK_EQUAL(a == b, false);
-
-    BOOST_CHECK_EQUAL(Fraction("1/3"), Fraction(1, 3));
-    BOOST_CHECK_EQUAL(double(Fraction("1/3")), 1.0 / 3.0);
-
-    BOOST_CHECK_EQUAL(Fraction("1"), Fraction(1));
-    BOOST_CHECK_EQUAL(Fraction("1.2"), Fraction(12, 10));
-    BOOST_CHECK_EQUAL(Fraction("1e-6"), Fraction(1, 1000000));
-    BOOST_CHECK_EQUAL(Fraction("1e+6"), Fraction(1000000, 1));
-    BOOST_CHECK_EQUAL(Fraction("1.2e+6"), Fraction(1200000, 1));
-
-    {
-        Fraction west(-12), east(1.2), increment(1.2);
-
-        Fraction f(west);
-        while (f < east) {
-            f += increment;
-        }
-        BOOST_CHECK_EQUAL(f, east);
-    }
-
-    {
-        Fraction west("-77"), east("7"), increment("0.7");
-
-        Fraction f(west);
-        while (f < east) {
-            f += increment;
-        }
-        BOOST_CHECK_EQUAL(f, east);
-    }
-
-
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/utils/test_string_tools.cc b/eckit/src/tests/utils/test_string_tools.cc
deleted file mode 100644
index 77c60c0..0000000
--- a/eckit/src/tests/utils/test_string_tools.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include "eckit/log/Log.h"
-#include "eckit/runtime/Tool.h"
-#include "eckit/parser/StringTools.h"
-#include "eckit/types/Types.h"
-
-using namespace std;
-using namespace eckit;
-
-//-----------------------------------------------------------------------------
-
-namespace eckit_test {
-
-//-----------------------------------------------------------------------------
-
-class TestStringTools : public Tool {
-public:
-
-    TestStringTools(int argc,char **argv): Tool(argc,argv) {}
-
-    ~TestStringTools() {}
-
-    virtual void run();
-
-protected:
-    
-    void test_substitute();
-    void test_substituteVariables();
-    void test_startsWith();
-    void test_trim();
-    void test_front_trim();
-    void test_back_trim();
-
-};
-
-//-----------------------------------------------------------------------------
-            
-void TestStringTools::run()
-{
-    test_substitute();
-    test_substituteVariables();
-    test_startsWith();
-    test_trim();
-    test_front_trim();
-    test_back_trim();
-}
-
-void TestStringTools::test_substitute()
-{
-    StringDict m;
-
-    m["class"]  = "od";
-    m["stream"] = "oper";
-
-    string in ( "{class}:none:{stream}" );
-    
-    string out = StringTools::substitute(in,m);
-    
-    ASSERT( out == "od:none:oper" );    
-}
-
-void TestStringTools::test_substituteVariables()
-{
-    string in ( "{class}:none:{stream}" );
-
-    StringList out = StringTools::substituteVariables(in);
-    
-    ASSERT( out.size() == 2 );    
-    ASSERT( out[0] == "class" );    
-    ASSERT( out[1] == "stream" );    
-}
-
-void TestStringTools::test_startsWith()
-{
-    string in ( "_lolo_test" );
-    string s1 ( "_lolo" );
-    string s2 ( "lolo" );
-    string s3 ( "_lolo_test_bigger" );
-
-    ASSERT( !StringTools::startsWith(in,"") );
-    ASSERT(  StringTools::startsWith(in,in) );
-    ASSERT(  StringTools::startsWith(in,s1) );
-    ASSERT(  StringTools::startsWith(in,"_") );
-    ASSERT( !StringTools::startsWith(in,s2) );
-    ASSERT( !StringTools::startsWith(in,s3) );
-}
-
-void TestStringTools::test_trim()
-{
-    string t1 ( "   lolo_test    " );
-    ASSERT(  StringTools::trim(t1) == string("lolo_test") );
-
-    string t2 ( "   lolo_test" );
-    ASSERT(  StringTools::trim(t2) == string("lolo_test") );
-
-    string t3 ( "lolo_test   " );
-    ASSERT(  StringTools::trim(t3) == string("lolo_test") );
-
-    string t4 ( "" );
-    ASSERT(  StringTools::trim(t4) == string("") );
-
-    string t5 ( "nothing_here" );
-    ASSERT(  StringTools::trim(t5) == string("nothing_here") );
-
-    string t6 ( "XXXXXXusefullXXXXX" );
-    ASSERT(  StringTools::trim(t6,"X") == string("usefull") );
-
-    string t7 ( "0000010" );
-    ASSERT(  StringTools::trim(t7,"0") == string("1") );
-}
-
-void TestStringTools::test_front_trim()
-{
-    string t1 ( "   lolo_test    " );
-    ASSERT(  StringTools::front_trim(t1) == string("lolo_test    ") );
-
-    string t2 ( "   lolo_test" );
-    ASSERT(  StringTools::front_trim(t2) == string("lolo_test") );
-
-    string t3 ( "lolo_test   " );
-    ASSERT(  StringTools::front_trim(t3) == string("lolo_test   ") );
-
-    string t4 ( "" );
-    ASSERT(  StringTools::front_trim(t4) == string("") );
-
-    string t5 ( "nothing_here" );
-    ASSERT(  StringTools::front_trim(t5) == string("nothing_here") );
-
-    string t6 ( "XXXXXXusefullXXXXX" );
-    ASSERT(  StringTools::front_trim(t6,"X") == string("usefullXXXXX") );
-
-    string t7 ( "0000010" );
-    ASSERT(  StringTools::front_trim(t7,"0") == string("10") );
-}
-
-void TestStringTools::test_back_trim()
-{
-    string t1 ( "   lolo_test    " );
-
-    Log::info() << StringTools::back_trim(t1) << std::endl;
-
-    ASSERT(  StringTools::back_trim(t1) == string("   lolo_test") );
-
-    string t2 ( "   lolo_test" );
-    ASSERT(  StringTools::back_trim(t2) == string("   lolo_test") );
-
-    string t3 ( "lolo_test   " );
-    ASSERT(  StringTools::back_trim(t3) == string("lolo_test") );
-
-    string t4 ( "" );
-    ASSERT(  StringTools::back_trim(t4) == string("") );
-
-    string t5 ( "nothing_here" );
-    ASSERT(  StringTools::back_trim(t5) == string("nothing_here") );
-
-    string t6 ( "XXXXXXusefullXXXXX" );
-    ASSERT(  StringTools::back_trim(t6,"X") == string("XXXXXXusefull") );
-
-    string t7 ( "0000010" );
-    ASSERT(  StringTools::back_trim(t7,"0") == string("000001") );
-}
-
-//-----------------------------------------------------------------------------
-
-} // namespace eckit_test
-
-//-----------------------------------------------------------------------------
-
-int main(int argc,char **argv)
-{
-    eckit_test::TestStringTools app(argc,argv);
-    return app.start();
-}
-
diff --git a/eckit/src/tests/value/test_value.cc b/eckit/src/tests/value/test_value.cc
deleted file mode 100644
index 67fd893..0000000
--- a/eckit/src/tests/value/test_value.cc
+++ /dev/null
@@ -1,2624 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#define BOOST_TEST_MODULE test_eckit_value
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/value/Value.h"
-
-#include "eckit/testing/Setup.h"
-
-using namespace std;
-using namespace eckit;
-using namespace eckit::testing;
-
-namespace eckit {
-namespace test {
-
-BOOST_GLOBAL_FIXTURE(Setup);
-
-//----------------------------------------------------------------------------------------------------------------------
-
-// eckit::Value offloads its functionality onto various subclasses of eckit::Content, which are
-// internally allocated on the heap and managed by the Value objects. This allows the behaviour to
-// depend on the type of content stored, with a consistent exposed interface.
-//
-// As a result of this, eckit::Value has an extremely thick interface, with potentially NxN possibilities for each
-// action (N possible types of argument, N possible types of content) - e.g. ::as<double>() will happily return a
-// (casted) double if the content type is a long...
-//
-// --> it is not realistic to catch all of this behaviour in the tests.
-
-//----------------------------------------------------------------------------------------------------------------------
-
-namespace {
-
-    // Helper functions, so that we can put operator expressions inside callables that can be passed into
-    // BOOST_CHECK_THROW
-
-    Value ValueAdd(const Value& lhs, const Value& rhs) { return lhs + rhs; }
-    Value ValueSub(const Value& lhs, const Value& rhs) { return lhs - rhs; }
-    Value ValueMul(const Value& lhs, const Value& rhs) { return lhs * rhs; }
-    Value ValueDiv(const Value& lhs, const Value& rhs) { return lhs / rhs; }
-    Value ValueMod(const Value& lhs, const Value& rhs) { return lhs % rhs; }
-
-    Value ValueAddSelf(Value& lhs, const Value& rhs) { return lhs += rhs; }
-    Value ValueSubSelf(Value& lhs, const Value& rhs) { return lhs -= rhs; }
-    Value ValueMulSelf(Value& lhs, const Value& rhs) { return lhs *= rhs; }
-    Value ValueDivSelf(Value& lhs, const Value& rhs) { return lhs /= rhs; }
-    Value ValueModSelf(Value& lhs, const Value& rhs) { return lhs %= rhs; }
-
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-// TODO:
-// - Tests for Stream
-// - Test json, print, encode
-
-
-BOOST_AUTO_TEST_SUITE( test_eckit_value )
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of bools first
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_cast ) {
-    Value val_true(true);
-    Value val_false(false);
-
-    //
-    // Access and conversion of bools
-    //
-
-    BOOST_CHECK_EQUAL(bool(val_true), true);
-    BOOST_CHECK_EQUAL(bool(val_false), false);
-    BOOST_CHECK_EQUAL(val_true.as<bool>(), true);
-    BOOST_CHECK_EQUAL(val_false.as<bool>(), false);
-
-    // Integer type conversions
-    BOOST_CHECK_EQUAL(int(val_true), 1);
-    BOOST_CHECK_EQUAL(int(val_false), 0);
-    BOOST_CHECK_EQUAL(val_true.as<long long>(), 1);
-    BOOST_CHECK_EQUAL(val_false.as<long long>(), 0);
-
-    // For pretty printing
-
-    BOOST_CHECK_EQUAL(std::string(val_true), "true");
-    BOOST_CHECK_EQUAL(std::string(val_false), "false");
-    BOOST_CHECK_EQUAL(val_true.as<std::string>(), "true");
-    BOOST_CHECK_EQUAL(val_false.as<std::string>(), "false");
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl_true(val_true.as<ValueList>());
-    ValueList vl_false = val_false;
-    BOOST_CHECK_EQUAL(vl_true.size(), 1);
-    BOOST_CHECK_EQUAL(vl_false.size(), 1);
-    BOOST_CHECK_EQUAL(vl_true[0].as<bool>(), true);
-    BOOST_CHECK_EQUAL(vl_false[0].as<bool>(), false);
-
-    // And all the invalid conversions
-
-    /// For some reason, Value(bool) happily converts to double...
-    /// BOOST_CHECK_THROW(val_false.as<double>(), BadConversion);
-
-    /// Length/Offset are just integers, so bool-->Offset conversion works...!!!
-    /// BOOST_CHECK_THROW(Length(val_false), BadConversion);
-    /// BOOST_CHECK_THROW(Offset(val_false), BadConversion);
-
-    BOOST_CHECK_THROW(val_false.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val_false.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val_false.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val_false.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_type ) {
-    Value val_true(true);
-    Value val_false(false);
-
-    BOOST_CHECK(val_true.isBool());
-    BOOST_CHECK(val_false.isBool());
-
-    BOOST_CHECK(!val_true.isNil());
-    BOOST_CHECK(!val_true.isNumber());
-    BOOST_CHECK(!val_true.isDouble());
-    BOOST_CHECK(!val_true.isString());
-    BOOST_CHECK(!val_true.isList());
-    BOOST_CHECK(!val_true.isMap());
-    BOOST_CHECK(!val_true.isDate());
-    BOOST_CHECK(!val_true.isTime());
-    BOOST_CHECK(!val_true.isDateTime());
-
-    BOOST_CHECK(!val_false.isNil());
-    BOOST_CHECK(!val_false.isNumber());
-    BOOST_CHECK(!val_false.isDouble());
-    BOOST_CHECK(!val_false.isString());
-    BOOST_CHECK(!val_false.isList());
-    BOOST_CHECK(!val_false.isMap());
-    BOOST_CHECK(!val_false.isDate());
-    BOOST_CHECK(!val_false.isTime());
-    BOOST_CHECK(!val_false.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_comparisons ) {
-    Value val_true1(true);
-    Value val_true2(true);
-    Value val_false1(false);
-    Value val_false2(false);
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-
-    // ************************
-    // WARNING: This logic is inverted from all the other Value types. Should probably be checked.
-    // ************************
-
-    BOOST_CHECK(val_true1.compare(val_true1) == -1);
-    BOOST_CHECK(val_true1.compare(val_true2) == -1);
-    BOOST_CHECK(val_false1.compare(val_false1) == 1);
-    BOOST_CHECK(val_false1.compare(val_false2) == 1);
-
-    BOOST_CHECK(val_true1.compare(val_false1) == 0);
-    BOOST_CHECK(val_false2.compare(val_true2) == 0);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val_true1.compare(Value(1234)) > 0); // Only need 1 integral test, they are all the same.
-    BOOST_CHECK(val_true1.compare(Value(1234.5)) > 0);
-    BOOST_CHECK(val_true1.compare(Value("test str")) > 0);
-    BOOST_CHECK(val_true1.compare(Value(std::string("testing string"))) > 0);
-    BOOST_CHECK(val_true1.compare(Value(ValueMap())) > 0);
-    BOOST_CHECK(val_true1.compare(Value(Date(2016, 3, 30))) > 0);
-    BOOST_CHECK(val_true1.compare(ValueList()) > 0);
-
-    BOOST_CHECK(Value(1234).compare(val_false1) < 0); // Only need 1 integral test, they are all the same.
-    BOOST_CHECK(Value(1234.5).compare(val_false1) < 0);
-    BOOST_CHECK(Value("test str").compare(val_false1) < 0);
-    BOOST_CHECK(Value(std::string("testing string")).compare(val_false1) < 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val_false1) < 0);
-    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val_false1) < 0);
-    BOOST_CHECK(Value(ValueList()).compare(val_false1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_index_operator ) {
-    // No indexing operations should work on a bool...
-
-    Value val_true(true);
-    Value val_false(false);
-
-    BOOST_CHECK_THROW(val_true["idx"], BadOperator);
-    BOOST_CHECK_THROW(val_true[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val_true[123], BadOperator);
-    BOOST_CHECK_THROW(val_true[Value(123)], BadOperator);
-
-    BOOST_CHECK_THROW(val_false["idx"], BadOperator);
-    BOOST_CHECK_THROW(val_false[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val_false[123], BadOperator);
-    BOOST_CHECK_THROW(val_false[Value(123)], BadOperator);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK_THROW(val_true.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val_true.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val_true.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val_true.contains(Value(123)), BadOperator);
-
-    BOOST_CHECK_THROW(val_false.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val_false.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val_false.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val_false.contains(Value(123)), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_add_operator ) {
-    // There are no valid boolean addition operations.
-
-    Value val(true);
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_subtract_operator ) {
-    // There are no valid boolean subtraction operations.
-
-    Value val(true);
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_multiply_operator ) {
-    // There are no valid boolean multiplication operations.
-
-    Value val(true);
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_divide_operator ) {
-    // There are no valid boolean division operations.
-
-    Value val(true);
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_modulo_operator ) {
-    // There are no valid boolean modulo operations.
-
-    Value val(true);
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_bool_head_tail ) {
-    Value val(true);
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of integers next. Note that all integral types are treated identically.
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_cast ) {
-    // Note that _all_ the integer types are stored as a signed long long
-    // --> There are constraints on the size that can be stored
-    Value val_zero(0U);
-    Value val_int(12345);
-    Value val_long(-2147483647);
-
-    // Integer conversions
-
-    BOOST_CHECK_EQUAL(val_zero.as<long long>(), 0);
-    BOOST_CHECK_EQUAL(val_int.as<long long>(), 12345);
-    BOOST_CHECK_EQUAL(val_long.as<long long>(), -2147483647);
-
-    BOOST_CHECK_EQUAL(int(val_zero), 0);
-
-    BOOST_CHECK_EQUAL(int(val_int), 12345);
-    BOOST_CHECK_EQUAL((unsigned int)(val_int), 12345);
-    BOOST_CHECK_EQUAL(short(val_int), 12345);
-    BOOST_CHECK_EQUAL((unsigned short)(val_int), 12345);
-    BOOST_CHECK_EQUAL(long(val_int), 12345);
-    BOOST_CHECK_EQUAL((unsigned long)(val_int), 12345);
-    BOOST_CHECK_EQUAL((long long)(val_int), 12345);
-    BOOST_CHECK_EQUAL((unsigned long long)(val_int), 12345);
-
-    // NOTE that using an unsigned variable does NOT cause the check to fail, unless there is an overflow. The
-    // compiler will assume that everything is fine, and just do a bitwise check...
-    BOOST_CHECK_EQUAL(int(val_long), -2147483647);
-    BOOST_CHECK_EQUAL((unsigned int)(val_long), -2147483647);
-//    BOOST_CHECK(short(val_long) != -2147483647);             // a short ranges [−32767, +32767] so this is always true
-//    BOOST_CHECK((unsigned short)(val_long) != -2147483647);  // unsigned is always positive
-    BOOST_CHECK_EQUAL(long(val_long), -2147483647);
-    BOOST_CHECK_EQUAL((unsigned long)(val_long), -2147483647);
-    BOOST_CHECK_EQUAL((long long)(val_long), -2147483647);
-    BOOST_CHECK_EQUAL((unsigned long long)(val_long), -2147483647);
-
-    // Check boolean conversion
-
-    BOOST_CHECK(!val_zero);
-    BOOST_CHECK(val_int);
-    BOOST_CHECK(val_long);
-    BOOST_CHECK(!val_zero.as<bool>());
-    BOOST_CHECK(val_int.as<bool>());
-    BOOST_CHECK(val_long.as<bool>());
-
-    // Check double conversion
-
-    BOOST_CHECK_CLOSE(double(val_zero), 0.0, 1.0e-6);
-    BOOST_CHECK_CLOSE(double(val_int), 12345.0, 1.0e-6);
-    BOOST_CHECK_CLOSE(double(val_long), -2147483647.0, 1.0e-6);
-    BOOST_CHECK_CLOSE(val_zero.as<double>(), 0.0, 1.0e-6);
-    BOOST_CHECK_CLOSE(val_int.as<double>(), 12345.0, 1.0e-6);
-    BOOST_CHECK_CLOSE(val_long.as<double>(), -2147483647.0, 1.0e-6);
-
-    // Check pretty printing
-
-    BOOST_CHECK_EQUAL(std::string(val_zero), "0");
-    BOOST_CHECK_EQUAL(std::string(val_int), "12345");
-    BOOST_CHECK_EQUAL(std::string(val_long), "-2147483647");
-    BOOST_CHECK_EQUAL(val_zero.as<std::string>(), "0");
-    BOOST_CHECK_EQUAL(val_int.as<std::string>(), "12345");
-    BOOST_CHECK_EQUAL(val_long.as<std::string>(), "-2147483647");
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl(val_int.as<ValueList>());
-    BOOST_CHECK_EQUAL(vl.size(), 1);
-    BOOST_CHECK_EQUAL(vl[0].as<long long>(), 12345);
-
-    // And the conversions to Length/Offset, oooer.
-    // It would be nicer if these didn't work...
-
-    Length len = val_int; // Avoid ambiguities. Gah.
-    Offset off = val_int;
-    BOOST_CHECK_EQUAL(len, Length(12345));
-    BOOST_CHECK_EQUAL(off, Offset(12345));
-
-    // And the invalid conversions
-
-    BOOST_CHECK_THROW(val_int.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val_int.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val_int.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val_int.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_unsigned_overflow ) {
-    // Internally a Value(unsigned long long) is stored as a long long, as with all the other integer types. This should
-    // give very predictable overflow behaviour
-
-    Value val_max(9223372036854775807);
-    Value val_min(-9223372036854775807);
-    Value val_overflow(9223372036854775808U);
-
-    BOOST_CHECK_EQUAL((long long)val_max, 9223372036854775807);
-    BOOST_CHECK_EQUAL((long long)val_min, -9223372036854775807);
-    BOOST_CHECK((unsigned long long)(val_min) != 9223372036854775808U);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_type ) {
-    Value val_int(12345);
-    Value val_long(2147483647);
-    Value val_longlong(-9223372036854775807);
-
-    BOOST_CHECK(val_int.isNumber());
-    BOOST_CHECK(val_long.isNumber());
-    BOOST_CHECK(val_longlong.isNumber());
-
-    BOOST_CHECK(!val_int.isNil());
-    BOOST_CHECK(!val_int.isBool());
-    BOOST_CHECK(!val_int.isDouble());
-    BOOST_CHECK(!val_int.isString());
-    BOOST_CHECK(!val_int.isList());
-    BOOST_CHECK(!val_int.isMap());
-    BOOST_CHECK(!val_int.isDate());
-    BOOST_CHECK(!val_int.isTime());
-    BOOST_CHECK(!val_int.isDateTime());
-
-    BOOST_CHECK(!val_long.isNil());
-    BOOST_CHECK(!val_long.isBool());
-    BOOST_CHECK(!val_long.isDouble());
-    BOOST_CHECK(!val_long.isString());
-    BOOST_CHECK(!val_long.isList());
-    BOOST_CHECK(!val_long.isMap());
-    BOOST_CHECK(!val_long.isDate());
-    BOOST_CHECK(!val_long.isTime());
-    BOOST_CHECK(!val_long.isDateTime());
-
-    BOOST_CHECK(!val_longlong.isNil());
-    BOOST_CHECK(!val_longlong.isBool());
-    BOOST_CHECK(!val_longlong.isDouble());
-    BOOST_CHECK(!val_longlong.isString());
-    BOOST_CHECK(!val_longlong.isList());
-    BOOST_CHECK(!val_longlong.isMap());
-    BOOST_CHECK(!val_longlong.isDate());
-    BOOST_CHECK(!val_longlong.isTime());
-    BOOST_CHECK(!val_longlong.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_comparisons ) {
-    Value val1(1234);
-    Value val2(1234);
-    Value val3(4321);
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-
-    BOOST_CHECK(val1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val2) == 0);
-    BOOST_CHECK(val2.compare(val1) == 0);
-
-    BOOST_CHECK(val1.compare(val3) == -1);
-    BOOST_CHECK(val3.compare(val1) == 1);
-
-    // Check comparisons with floating point values ... these get checked by value
-    Value val_f1(1234.0);
-    Value val_f2(2222.0);
-
-    BOOST_CHECK(val_f1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val_f1) == 0);
-
-    BOOST_CHECK(val1.compare(val_f2) == -1);
-    BOOST_CHECK(val3.compare(val_f2) == 1);
-    BOOST_CHECK(val_f2.compare(val1) == 1);
-    BOOST_CHECK(val_f2.compare(val3) == -1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value("test str")) > 0);
-    BOOST_CHECK(val1.compare(Value(std::string("testing string"))) > 0);
-    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
-    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
-    BOOST_CHECK(val1.compare(ValueList()) > 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value("test str").compare(val1) < 0);
-    BOOST_CHECK(Value(std::string("testing string")).compare(val1) < 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
-    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
-    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_index_operator ) {
-    // No indexing operations should work on an integer...
-
-    Value val(1234);
-
-    BOOST_CHECK_THROW(val["idx"], BadOperator);
-    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val[123], BadOperator);
-    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_add_operator ) {
-    Value val(123);
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAdd(val, 1234).as<long long>(), 1357);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAdd(1234, val).as<long long>(), 1357);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAddSelf(val, 1234).as<long long>(), 1357);;
-    val = Value(123);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_subtract_operator ) {
-    Value val(123);
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueSub(val, 1234).as<long long>(), -1111);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_EQUAL(ValueSub(1234, val).as<long long>(), 1111);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueSubSelf(val, 1234).as<long long>(), -1111);
-    val = Value(123);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_multiply_operator ) {
-    Value val(123);
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueMul(val, 1234).as<long long>(), 151782);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_EQUAL(ValueMul(1234, val).as<long long>(), 151782);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueMulSelf(val, 1234).as<long long>(), 151782);
-    val = Value(123);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_divide_operator ) {
-    Value val(1476);
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueDiv(val, 12).as<long long>(), 123);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_EQUAL(ValueDiv(12, val).as<long long>(), 0);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_EQUAL(ValueDivSelf(val, 12).as<long long>(), 123);
-    val = Value(1476);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_modulo_operator ) {
-    Value val(123);
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_integer_head_tail ) {
-    Value val(12345);
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of doubles
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_cast ) {
-    Value val_zero(0.0);
-    Value val_double(99999999999999999999999999999.9);
-
-    // Double conversions
-
-    BOOST_CHECK_CLOSE(val_zero.as<double>(), 0.0, 1.0e-10);
-    BOOST_CHECK_CLOSE(val_double.as<double>(), 99999999999999999999999999999.9, 1.0e-10);
-
-    BOOST_CHECK_CLOSE(double(val_zero), 0.0, 1.0e-10);
-    BOOST_CHECK_CLOSE(double(val_double), 99999999999999999999999999999.9, 1.0e-10);
-
-    // Check pretty printing
-    /// @note rounding of values for pretty printing
-
-    BOOST_CHECK_EQUAL(std::string(val_zero), "0");
-    BOOST_CHECK_EQUAL(std::string(val_double), "1e+29");
-    BOOST_CHECK_EQUAL(val_zero.as<std::string>(), "0");
-    BOOST_CHECK_EQUAL(val_double.as<std::string>(), "1e+29");
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl(val_double.as<ValueList>());
-    BOOST_CHECK_EQUAL(vl.size(), 1);
-    BOOST_CHECK_CLOSE(vl[0].as<double>(), 99999999999999999999999999999.9, 1.0e-10);
-
-    BOOST_CHECK_THROW(val_double.as<bool>(), BadConversion);
-    BOOST_CHECK_THROW(val_double.as<long long>(), BadConversion);
-    BOOST_CHECK_THROW(val_double.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val_double.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val_double.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val_double.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_type ) {
-    Value val_double(-99999999999999999999999999999.9);
-
-    BOOST_CHECK(val_double.isDouble());
-
-    BOOST_CHECK(!val_double.isNil());
-    BOOST_CHECK(!val_double.isBool());
-    BOOST_CHECK(!val_double.isNumber());
-    BOOST_CHECK(!val_double.isString());
-    BOOST_CHECK(!val_double.isList());
-    BOOST_CHECK(!val_double.isMap());
-    BOOST_CHECK(!val_double.isDate());
-    BOOST_CHECK(!val_double.isTime());
-    BOOST_CHECK(!val_double.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_comparisons ) {
-    Value val1(1234.0);
-    Value val2(1234.0);
-    Value val3(4321.0);
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-
-    BOOST_CHECK(val1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val2) == 0);
-    BOOST_CHECK(val2.compare(val1) == 0);
-
-    BOOST_CHECK(val1.compare(val3) == -1);
-    BOOST_CHECK(val3.compare(val1) == 1);
-
-    // Check comparisons with integer values ... these get checked by value
-    Value val_i1(1234);
-    Value val_i2(2222);
-
-    BOOST_CHECK(val_i1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val_i1) == 0);
-
-    BOOST_CHECK(val1.compare(val_i2) == -1);
-    BOOST_CHECK(val3.compare(val_i2) == 1);
-    BOOST_CHECK(val_i2.compare(val1) == 1);
-    BOOST_CHECK(val_i2.compare(val3) == -1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value("test str")) > 0);
-    BOOST_CHECK(val1.compare(Value(std::string("testing string"))) > 0);
-    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
-    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
-    BOOST_CHECK(val1.compare(ValueList()) > 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value("test str").compare(val1) < 0);
-    BOOST_CHECK(Value(std::string("testing string")).compare(val1) < 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
-    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
-    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_index_operator ) {
-    // No indexing operations should work on a double...
-
-    Value val(1234.45);
-
-    BOOST_CHECK_THROW(val["idx"], BadOperator);
-    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val[123], BadOperator);
-    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_add_operator ) {
-    Value val(123.45);
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueAdd(val, 66.6).as<double>(), 190.05, 1.0e-10);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_CLOSE(ValueAdd(66.6, val).as<double>(), 190.05, 1.0e-10);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueAddSelf(val, 66.6).as<double>(), 190.05, 1.0e-10);
-    val = Value(123.45);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_subtract_operator ) {
-    Value val(123.45);
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueSub(val, 66.6).as<double>(), 56.85, 1.0e-10);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_CLOSE(ValueSub(66.6, val).as<double>(), -56.85, 1.0e-10);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueSubSelf(val, 66.6).as<double>(), 56.85, 1.0e-10);
-    val = Value(123.45);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_multiply_operator ) {
-    Value val(123.45);
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueMul(val, 66.6).as<double>(), 8221.77, 1.0e-10);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_CLOSE(ValueMul(66.6, val).as<double>(), 8221.77, 1.0e-10);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueMulSelf(val, 66.6).as<double>(), 8221.77, 1.0e-10);
-    val = Value(123.45);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_divide_operator ) {
-    Value val(123.45);
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueDiv(val, 66.6).as<double>(), 1.853603604, 1.0e-6);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_CLOSE(ValueDiv(66.6, val).as<double>(), 0.539489671, 1.0e-6);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_CLOSE(ValueDivSelf(val, 66.6).as<double>(), 1.853603604, 1.0e-6);
-    val = Value(123.45);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_modulo_operator ) {
-    Value val(123.45);
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_double_head_tail ) {
-    Value val(123.45);
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of strings
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_cast ) {
-    Value val_null("");
-    Value val_char("test string");
-    Value val_str(std::string("test string 2"));
-
-    // String conversion
-
-    BOOST_CHECK_EQUAL(std::string(val_null), "");
-    BOOST_CHECK_EQUAL(std::string(val_char), "test string");
-    BOOST_CHECK_EQUAL(std::string(val_str), "test string 2");
-
-    BOOST_CHECK_EQUAL(val_null.as<std::string>(), "");
-    BOOST_CHECK_EQUAL(val_char.as<std::string>(), "test string");
-    BOOST_CHECK_EQUAL(val_str.as<std::string>(), "test string 2");
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl(val_str.as<ValueList>());
-    BOOST_CHECK_EQUAL(vl.size(), 1);
-    BOOST_CHECK_EQUAL(vl[0].as<std::string>(), "test string 2");
-
-    // And the invalid conversions
-
-    BOOST_CHECK_THROW(val_str.as<bool>(), BadConversion);
-    /// BOOST_CHECK_THROW(val_str.as<long long>(), BadConversion); // This will return zero, not throw
-    BOOST_CHECK_THROW(val_str.as<double>(), BadParameter); // n.b. BadParameter, not BadConversion
-    BOOST_CHECK_THROW(val_str.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val_str.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val_str.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val_str.as<ValueMap>(), BadConversion);
-
-    BOOST_CHECK_THROW(val_null.as<bool>(), BadConversion);
-    /// BOOST_CHECK_THROW(val_null.as<long long>(), BadConversion); // This will return zero, not throw
-    BOOST_CHECK_THROW(val_null.as<double>(), BadParameter); // n.b. BadParameter, not BadConversion`
-    BOOST_CHECK_THROW(val_null.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val_null.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val_null.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val_null.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_cast_bool ) {
-    // Boolean casting for Value(StringContent) types is a bit complicated, as it allows strings to be used to
-    // represent truthy values, but nothing else
-
-    Value val_true1("true");
-    Value val_true2("on");
-    Value val_true3("yes");
-    Value val_true4("1");
-
-    BOOST_CHECK(bool(val_true1));
-    BOOST_CHECK(bool(val_true2));
-    BOOST_CHECK(bool(val_true3));
-    BOOST_CHECK(bool(val_true4));
-
-    BOOST_CHECK(val_true1.as<bool>());
-    BOOST_CHECK(val_true2.as<bool>());
-    BOOST_CHECK(val_true3.as<bool>());
-    BOOST_CHECK(val_true4.as<bool>());
-
-    Value val_false1("false");
-    Value val_false2("off");
-    Value val_false3("no");
-    Value val_false4("0");
-
-    BOOST_CHECK(!bool(val_false1));
-    BOOST_CHECK(!bool(val_false2));
-    BOOST_CHECK(!bool(val_false3));
-    BOOST_CHECK(!bool(val_false4));
-
-    BOOST_CHECK(!val_false1.as<bool>());
-    BOOST_CHECK(!val_false2.as<bool>());
-    BOOST_CHECK(!val_false3.as<bool>());
-    BOOST_CHECK(!val_false4.as<bool>());
-
-    Value val_other("other");
-
-    BOOST_CHECK_THROW(val_other.as<bool>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_vaule_string_cast_numbers ) {
-    Value val_double("123.45");
-    Value val_int("12345");
-    Value val_other("string");
-
-    // Test conversions to integers
-
-    BOOST_CHECK_EQUAL((int)(val_double), 123);
-    BOOST_CHECK_EQUAL((int)(val_int), 12345);
-
-    BOOST_CHECK_EQUAL(val_double.as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val_int.as<long long>(), 12345);
-
-    /// Integer conversion returns zero, rather than throwing, on no matching input
-    /// BOOST_CHECK_THROW(val_other.as<long long>(), std::exception);
-    BOOST_CHECK_EQUAL(val_other.as<long long>(), 0);
-
-    // Test conversions to doubles
-
-    BOOST_CHECK_CLOSE((double)(val_double), 123.45, 1.0e-10);
-    BOOST_CHECK_CLOSE((double)(val_int), 12345.0, 1.0e-10);
-
-    BOOST_CHECK_CLOSE(val_double.as<double>(), 123.45, 1.0e-10);
-    BOOST_CHECK_CLOSE(val_int.as<double>(), 12345.0, 1.0e-10);
-    BOOST_CHECK_THROW(val_other.as<double>(), BadParameter);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_type ) {
-    Value val_null("");
-    Value val_str("This is a test string");
-
-    BOOST_CHECK(val_null.isString());
-    BOOST_CHECK(val_str.isString());
-
-    BOOST_CHECK(!val_null.isNil());
-    BOOST_CHECK(!val_null.isBool());
-    BOOST_CHECK(!val_null.isNumber());
-    BOOST_CHECK(!val_null.isDouble());
-    BOOST_CHECK(!val_null.isList());
-    BOOST_CHECK(!val_null.isMap());
-    BOOST_CHECK(!val_null.isDate());
-    BOOST_CHECK(!val_null.isTime());
-    BOOST_CHECK(!val_null.isDateTime());
-
-    BOOST_CHECK(!val_str.isNil());
-    BOOST_CHECK(!val_str.isBool());
-    BOOST_CHECK(!val_str.isNumber());
-    BOOST_CHECK(!val_str.isDouble());
-    BOOST_CHECK(!val_str.isList());
-    BOOST_CHECK(!val_str.isMap());
-    BOOST_CHECK(!val_str.isDate());
-    BOOST_CHECK(!val_str.isTime());
-    BOOST_CHECK(!val_str.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_comparisons ) {
-    Value val1("a");
-    Value val2("a");
-    Value val3("b");
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-    // Comparison makes use of strcmp
-
-    BOOST_CHECK(val1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val2) == 0);
-    BOOST_CHECK(val2.compare(val1) == 0);
-
-    BOOST_CHECK(val1.compare(val3) == -1);
-    BOOST_CHECK(val3.compare(val1) == 1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value(123)) < 0);
-    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
-    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
-    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
-    BOOST_CHECK(val1.compare(ValueList()) > 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value(123).compare(val1) > 0);
-    BOOST_CHECK(Value(123.45).compare(val1) > 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
-    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
-    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_index_operator ) {
-    // No indexing operations should work on a string...
-
-    Value val_char("test string 1");
-    Value val_str(std::string("test string 2"));
-
-    BOOST_CHECK_THROW(val_char["idx"], BadOperator);
-    BOOST_CHECK_THROW(val_char[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val_char[123], BadOperator);
-    BOOST_CHECK_THROW(val_char[Value(123)], BadOperator);
-
-    BOOST_CHECK_THROW(val_str["idx"], BadOperator);
-    BOOST_CHECK_THROW(val_str[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val_str[123], BadOperator);
-    BOOST_CHECK_THROW(val_str[Value(123)], BadOperator);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK_THROW(val_char.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val_char.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val_char.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val_char.contains(Value(123)), BadOperator);
-
-    BOOST_CHECK_THROW(val_str.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val_str.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val_str.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val_str.contains(Value(123)), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_add_operator ) {
-    Value val("test string");
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAdd(val, "hi").as<std::string>(), "test stringhi");
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAdd("hi", val), "hitest string");
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_EQUAL(ValueAddSelf(val, "hi").as<std::string>(), "test stringhi");
-    val = Value("test string");
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_subtract_operator ) {
-    Value val("test string");
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_multiply_operator ) {
-    Value val("test string");
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_divide_operator ) {
-    Value val("test string");
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_modulo_operator ) {
-    Value val("test string");
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_string_head_tail ) {
-    Value val("this is a test string");
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of ValueMaps
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_cast ) {
-    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueMap vm;
-    vm[123] = 123;
-    vm["abc"] = "abc";
-    vm[Value(123.45)] = 123.45;
-    vm[Value(true)] = false;
-
-    Value val(vm);
-
-    // Extract the ValueMap
-    // n.b. We cannot compare eqality of ValueMaps, as the internal Values have been copied, and as a result the
-    //      operator== will return false, as it depends only on the memory address of the internal Content.
-
-    BOOST_CHECK_EQUAL(((ValueMap)val)[123].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val.as<ValueMap>()[123].as<long long>(), 123);
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl(val.as<ValueList>());
-    BOOST_CHECK_EQUAL(vl.size(), 1);
-    BOOST_CHECK_EQUAL(vl[0].as<ValueMap>()[123].as<long long>(), 123);
-
-    // And the invalid conversions
-
-    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_type ) {
-    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueMap vm;
-    vm[123] = 123;
-    vm["abc"] = "abc";
-    vm[Value(123.45)] = 123.45;
-    vm[Value(true)] = false;
-
-    Value val(vm);
-
-    BOOST_CHECK(val.isMap());
-
-    BOOST_CHECK(!val.isNil());
-    BOOST_CHECK(!val.isBool());
-    BOOST_CHECK(!val.isNumber());
-    BOOST_CHECK(!val.isDouble());
-    BOOST_CHECK(!val.isString());
-    BOOST_CHECK(!val.isList());
-    BOOST_CHECK(!val.isDate());
-    BOOST_CHECK(!val.isTime());
-    BOOST_CHECK(!val.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_comparisons ) {
-    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueMap vm;
-    vm[123] = 123;
-
-    ValueMap vm2;
-    vm2["abc"] = "abc";
-
-    Value val1(vm);
-    Value val2(vm);
-    Value val3(vm2);
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-    // Comparison makes use of strcmp
-
-    BOOST_CHECK(val1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val2) == 0);
-    BOOST_CHECK(val2.compare(val1) == 0);
-
-    BOOST_CHECK(val1.compare(val3) == 1);
-    BOOST_CHECK(val3.compare(val1) == -1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value(123)) < 0);
-    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
-    BOOST_CHECK(val1.compare(Value(std::string("test string"))) < 0);
-    BOOST_CHECK(val1.compare(ValueList()) < 0);
-    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value(123).compare(val1) > 0);
-    BOOST_CHECK(Value(123.45).compare(val1) > 0);
-    BOOST_CHECK(Value(std::string("test string")).compare(val1) > 0);
-    BOOST_CHECK(Value(ValueList()).compare(val1) > 0);
-
-    /// This is currently correct in MapContent.h
-    /// BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_index_operator ) {
-    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueMap vm;
-    vm[123] = 456;
-    vm["abc"] = "def";
-    vm[Value(123.45)] = 543.21;
-    vm[Value(true)] = false;
-
-    Value val(vm);
-
-    // Check with existent keys of the various types
-
-    BOOST_CHECK_EQUAL(val[123].as<long long>(), 456);
-    BOOST_CHECK_EQUAL(val["abc"].as<std::string>(), "def");
-    BOOST_CHECK_EQUAL(val[std::string("abc")].as<std::string>(), "def");
-
-    /// None of these seem to work with boolean indices
-    /// BOOST_CHECK_EQUAL(val[true].as<bool>(), false);
-
-    BOOST_CHECK_EQUAL(val[Value(123)].as<long long>(), 456);
-    BOOST_CHECK_EQUAL(val[Value("abc")].as<std::string>(), "def");
-    BOOST_CHECK_EQUAL(val[Value(std::string("abc"))].as<std::string>(), "def");
-    BOOST_CHECK_CLOSE(val[Value(123.45)].as<double>(), 543.21, 1.0e-10);
-
-    /// Indexing by Value(bool) doesn't seem to work
-    /// BOOST_CHECK_EQUAL(val[Value(true)].as<bool>(), false);
-
-    // And with values that don't exist
-
-    /// This code should not work!!! const has gone screwey
-    ValueMap vm2;
-    const Value cv(vm2);
-    cv[10];
-    Log::info() << cv << std::endl;
-
-    /// BOOST_CHECK(!cv.contains(10));
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK(val.contains(123));
-    BOOST_CHECK(val.contains("abc"));
-    BOOST_CHECK(val.contains(std::string("abc")));
-    BOOST_CHECK(val.contains(Value(123.45)));
-    /// BOOST_CHECK(val.contains(Value(true)));
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_add_operator ) {
-    // There are no valid ValueMap addition operations.
-
-    ValueMap vm;
-    Value val(vm);
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_subtract_operator ) {
-    // There are no valid ValueMap subtraction operations.
-
-    ValueMap vm;
-    Value val(vm);
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_multiply_operator ) {
-    // There are no valid ValueMap multiplication operations.
-
-    ValueMap vm;
-    Value val(vm);
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_divide_operator ) {
-    // There are no valid ValueMap division operations.
-
-    ValueMap vm;
-    Value val(vm);
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_modulo_operator ) {
-    // There are no valid ValueMap modulo operations.
-
-    ValueMap vm;
-    Value val(vm);
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_map_head_tail ) {
-    ValueMap vm;
-    vm[123] = 456;
-
-    Value val(vm);
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of ValueMaps
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_cast ) {
-    // A ValueMap is just a std::list<Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    vl.push_back(1234.56);
-    vl.push_back(false);
-
-    Value val(vl);
-
-    // Extract the ValueList
-    // n.b. We cannot compare eqality of ValueLists, as the internal Values have been copied, and as a result the
-    //      operator== will return false, as it depends only on the memory address of the internal Content.
-
-    ValueList casted_vl = val;
-    BOOST_CHECK_EQUAL(casted_vl[0].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val.as<ValueList>()[0].as<long long>(), 123);
-
-    // And the invalid conversions
-
-    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<Date>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_type ) {
-    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    vl.push_back(1234.56);
-    vl.push_back(false);
-
-    Value val(vl);
-
-    BOOST_CHECK(val.isList());
-
-    BOOST_CHECK(!val.isNil());
-    BOOST_CHECK(!val.isBool());
-    BOOST_CHECK(!val.isNumber());
-    BOOST_CHECK(!val.isDouble());
-    BOOST_CHECK(!val.isString());
-    BOOST_CHECK(!val.isMap());
-    BOOST_CHECK(!val.isDate());
-    BOOST_CHECK(!val.isTime());
-    BOOST_CHECK(!val.isDateTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_comparisons ) {
-    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueList vl;
-    vl.push_back(123);
-
-    ValueList vl2;
-    vl2.push_back(321);
-
-    Value val1(vl);
-    Value val2(vl);
-    Value val3(vl2);
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-    // Comparison makes use of strcmp
-
-    BOOST_CHECK(val1.compare(val1) == 0);
-    BOOST_CHECK(val1.compare(val2) == 0);
-    BOOST_CHECK(val2.compare(val1) == 0);
-
-    BOOST_CHECK(val1.compare(val3) == -1);
-    BOOST_CHECK(val3.compare(val1) == 1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value(123)) < 0);
-    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
-    BOOST_CHECK(val1.compare(Value(std::string("test string"))) < 0);
-    BOOST_CHECK(val1.compare(ValueMap()) > 0);
-    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value(123).compare(val1) > 0);
-    BOOST_CHECK(Value(123.45).compare(val1) > 0);
-    BOOST_CHECK(Value(std::string("test string")).compare(val1) > 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
-
-    /// This is currently correct in MapContent.h
-    /// BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_index_operator ) {
-    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
-    // it does when wrapped.
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    vl.push_back(1234.56);
-    vl.push_back(false);
-
-    Value val(vl);
-
-    // Check with existent keys of the various types
-
-    BOOST_CHECK_EQUAL(val[0].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val[1].as<std::string>(), "abc");
-    BOOST_CHECK_CLOSE(val[2].as<double>(), 1234.56, 1.0e-10);
-    BOOST_CHECK_EQUAL(val[3].as<bool>(), false);
-
-    BOOST_CHECK_EQUAL(int(val[Value(0)]), 123);
-    BOOST_CHECK_EQUAL(std::string(val[Value(1)]), "abc");
-    BOOST_CHECK_CLOSE(double(val[Value(2)]), 1234.56, 1.0e-10);
-    BOOST_CHECK_EQUAL(bool(val[Value(3)]), false);
-
-    // And with values that don't exist
-
-    BOOST_CHECK_THROW(val[-1], AssertionFailed);
-    BOOST_CHECK_THROW(val[4], AssertionFailed);
-    BOOST_CHECK_THROW(val[Value(-1)], AssertionFailed);
-    BOOST_CHECK_THROW(val[Value(4)], AssertionFailed);
-
-    /// Value(std::string) silently casts to 0, which means this returns val[0] spuriously
-    /// BOOST_CHECK_THROW(val["hello"], AssertionFailed);
-    /// BOOST_CHECK_THROW(val[std::string("hello")], AssertionFailed);
-    /// BOOST_CHECK_THROW(val[Value("hello")], AssertionFailed);
-
-    // Value(bool) automagically converts to a long, so these return elements 1, 0 respectively...
-    // BOOST_CHECK_THROW(val[Value(true)], BadConversion);
-    // BOOST_CHECK_THROW(val[Value(false)], BadConversion);
-
-    BOOST_CHECK_THROW(val[Value(666.66)], BadConversion);
-    BOOST_CHECK_THROW(val[Value(ValueList())], BadConversion);
-    BOOST_CHECK_THROW(val[Value(ValueMap())], BadConversion);
-    BOOST_CHECK_THROW(val[Value(Date(2016, 3, 31))], BadConversion);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK(!val.contains(-1));
-    BOOST_CHECK(val.contains(0));
-    BOOST_CHECK(val.contains(1));
-    BOOST_CHECK(val.contains(2));
-    BOOST_CHECK(val.contains(3));
-    BOOST_CHECK(!val.contains(4));
-
-    BOOST_CHECK(!val.contains(Value(-1)));
-    BOOST_CHECK(val.contains(Value(0)));
-    BOOST_CHECK(val.contains(Value(1)));
-    BOOST_CHECK(val.contains(Value(2)));
-    BOOST_CHECK(val.contains(Value(3)));
-    BOOST_CHECK(!val.contains(Value(4)));
-
-    /// Same oddities as above...
-    /// BOOST_CHECK(!val.contains("hello"));
-    /// BOOST_CHECK(!val.contains(std::string("hello")));
-    /// BOOST_CHECK(!val.contains(Value("hello")));
-
-    BOOST_CHECK_THROW(val.contains(Value(666.66)), BadConversion);
-    BOOST_CHECK_THROW(val.contains(Value(ValueList())), BadConversion);
-    BOOST_CHECK_THROW(val.contains(Value(ValueMap())), BadConversion);
-    BOOST_CHECK_THROW(val.contains(Value(Date(2016, 3, 31))), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_add_operator ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    Value val(vl);
-
-    ValueList vl2;
-    vl2.push_back(true);
-    vl2.push_back(Date(2016, 3, 31));
-    Value val2(vl2);
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-
-    Value tmp1 = val + val2;
-    BOOST_CHECK_EQUAL(tmp1.as<ValueList>().size(), 4);
-    BOOST_CHECK_EQUAL(tmp1[0].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(tmp1[1].as<std::string>(), "abc");
-    BOOST_CHECK_EQUAL(tmp1[2].as<bool>(), true);
-    BOOST_CHECK_EQUAL(tmp1[3].as<Date>(), Date(2016, 3, 31));
-
-    Value tmp2 = val2 + val;
-    BOOST_CHECK_EQUAL(tmp2.as<ValueList>().size(), 4);
-    BOOST_CHECK_EQUAL(tmp2[0].as<bool>(), true);
-    BOOST_CHECK_EQUAL(tmp2[1].as<Date>(), Date(2016, 3, 31));
-    BOOST_CHECK_EQUAL(tmp2[2].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(tmp2[3].as<std::string>(), "abc");
-
-    val += val2;
-    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 4);
-    BOOST_CHECK_EQUAL(val[0].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val[1].as<std::string>(), "abc");
-    BOOST_CHECK_EQUAL(val[2].as<bool>(), true);
-    BOOST_CHECK_EQUAL(val[3].as<Date>(), Date(2016, 3, 31));
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_subtract_operator ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    Value val(vl);
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_multiply_operator ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    Value val(vl);
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_divide_operator ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    Value val(vl);
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_modulo_operator ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    Value val(vl);
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_list_head_tail ) {
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back(666.66);
-    vl.push_back(true);
-    vl.push_back("test str");
-
-    Value val(vl);
-
-    Log::info() << "H" << val << " - " << val.head() << std::endl;
-    BOOST_CHECK_EQUAL(val.head().as<long long>(), 123);
-    Log::info() << "T" << val << " - " << val.tail() << std::endl;
-    /// BOOST_CHECK_EQUAL(val.tail().as<std::string>(), "test str");
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test the behaviour of Dates
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_cast ) {
-    Value val(Date(2016, 3, 31));
-
-    //
-    // Access and conversion
-    //
-
-    Date tmp = val;
-    BOOST_CHECK_EQUAL(tmp, Date(2016, 3, 31));
-    BOOST_CHECK_EQUAL(val.as<Date>(), Date(2016, 3, 31));
-
-    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
-
-    ValueList vl = val;
-    BOOST_CHECK_EQUAL(vl.size(), 1);
-    BOOST_CHECK_EQUAL(vl[0].as<Date>(), Date(2016, 3, 31));
-
-    // And all the invalid conversions
-
-    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
-    BOOST_CHECK_THROW(val.as<ValueMap>(), BadConversion);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_type ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK(val.isDate());
-
-    BOOST_CHECK(!val.isNil());
-    BOOST_CHECK(!val.isBool());
-    BOOST_CHECK(!val.isNumber());
-    BOOST_CHECK(!val.isDouble());
-    BOOST_CHECK(!val.isString());
-    BOOST_CHECK(!val.isList());
-    BOOST_CHECK(!val.isMap());
-    BOOST_CHECK(!val.isDateTime());
-    BOOST_CHECK(!val.isTime());
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_comparisons ) {
-    Value val1(Date(2016, 3, 31));
-    Value val2(Date(2016, 3, 31));
-    Value val3(Date(2016, 4, 30));
-
-    // n.b. These comparisons are designed to define a well defined order between different data types
-    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
-
-    // Check comparisons with same type of data
-    // Comparison makes use of strcmp
-
-    /// Value(Date) compare function is rather broken...
-    /// BOOST_CHECK(val1.compare(val1) == 0);
-    /// BOOST_CHECK(val1.compare(val2) == 0);
-    /// BOOST_CHECK(val2.compare(val1) == 0);
-
-    /// BOOST_CHECK(val1.compare(val3) == -1);
-    BOOST_CHECK(val3.compare(val1) == 1);
-
-    // Check comparisons with other types of data.
-
-    BOOST_CHECK(val1.compare(Value(true)) < 0);
-    BOOST_CHECK(val1.compare(Value(123)) < 0);
-    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
-    BOOST_CHECK(val1.compare(Value("testing")) < 0);
-    /// There is a bug in the ValueMap implementation, so this would fail
-    /// BOOST_CHECK(val1.compare(Value(ValueMap())) < 0);
-    BOOST_CHECK(val1.compare(ValueList()) < 0);
-
-    BOOST_CHECK(Value(true).compare(val1) > 0);
-    BOOST_CHECK(Value(123).compare(val1) > 0);
-    BOOST_CHECK(Value(123.45).compare(val1) > 0);
-    BOOST_CHECK(Value("testing").compare(val1) > 0);
-    BOOST_CHECK(Value(ValueMap()).compare(val1) > 0);
-    BOOST_CHECK(Value(ValueList()).compare(val1) > 0);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_index_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(val["idx"], BadOperator);
-    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
-    BOOST_CHECK_THROW(val[123], BadOperator);
-    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
-
-    // Test the matching contains() function too
-
-    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
-    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
-    BOOST_CHECK_THROW(val.contains(123), BadOperator);
-    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_add_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
-    val = Date(2016, 3, 31);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_subtract_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
-    /// The sign of the following test is wrong. SHOULD be +2
-    BOOST_CHECK_EQUAL(ValueSub(val, Date(2016, 3, 29)).as<long long>(), -2);
-    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
-    /// The sign of the following test is wrong. SHOULD be -2
-    BOOST_CHECK_EQUAL(ValueSub(Date(2016, 3, 29), val).as<long long>(), 2);
-    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
-    /// The sign of the following test is wrong. SHOULD be +2
-    BOOST_CHECK_EQUAL(ValueSubSelf(val, Date(2016, 3, 29)).as<long long>(), -2);
-    val = Date(2016, 3, 31);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_multiply_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_divide_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_modulo_operator ) {
-    Value val(Date(2016, 3, 31));
-
-    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
-
-    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
-    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
-
-    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
-    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_date_head_tail ) {
-    Value val(Date(2016, 3, 31));
-
-    /// BOOST_CHECK_THROW(val.head(), AssertationError);
-    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-//
-// Test list/map helper functions
-//
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_makelist ) {
-    // Test the trivial version
-
-    Value val1 = Value::makeList();
-
-    BOOST_CHECK(val1.isList());
-    BOOST_CHECK_EQUAL(val1.as<ValueList>().size(), 0);
-
-    // Can we wrap an arbitrary ValueList?
-
-    ValueList vl;
-    vl.push_back(123);
-    vl.push_back("abc");
-    vl.push_back(1234.56);
-    vl.push_back(false);
-
-    Value val2 = Value::makeList(vl);
-
-    BOOST_CHECK(val2.isList());
-
-    BOOST_CHECK_EQUAL(val2.as<ValueList>().size(), 4);
-    BOOST_CHECK_EQUAL(val2[0].as<long long>(), 123);
-    BOOST_CHECK_EQUAL(val2[1].as<std::string>(), "abc");
-    BOOST_CHECK_CLOSE(val2[2].as<double>(), 1234.56, 1.0e-10);
-    BOOST_CHECK_EQUAL(val2[3].as<bool>(), false);
-
-    // Applied to a value, it puts the element in first
-
-    Value val3 = Value::makeList(val2);
-
-    BOOST_CHECK(val3.isList());
-
-    BOOST_CHECK_EQUAL(val3.as<ValueList>().size(), 1);
-    BOOST_CHECK(val3[0].isList());
-    BOOST_CHECK_EQUAL(val3[0].as<ValueList>()[0].as<long long>(), 123);
-
-    // This should work with all the things that can cast into values
-
-    Value val4 = Value::makeList(1234);
-
-    BOOST_CHECK(val4.isList());
-    BOOST_CHECK_EQUAL(val4.as<ValueList>().size(), 1);
-    BOOST_CHECK_EQUAL(val4[0].as<long long>(), 1234);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_makemap ) {
-    // Test the trivial version
-
-    Value val1 = Value::makeMap();
-
-    BOOST_CHECK(val1.isMap());
-    BOOST_CHECK_EQUAL(val1.as<ValueMap>().size(), 0);
-
-    // Can we wrap an arbitrary ValueMap?
-
-    ValueMap vm;
-    vm[123] = 456;
-    vm["abc"] = "def";
-    vm[1234.56] = 666.66;
-    vm[true] = false;
-
-    Value val2 = Value::makeMap(vm);
-
-    BOOST_CHECK(val2.isMap());
-
-    BOOST_CHECK_EQUAL(val2.as<ValueMap>().size(), 4);
-    BOOST_CHECK_EQUAL(val2[123].as<long long>(), 456);
-    BOOST_CHECK_EQUAL(val2["abc"].as<std::string>(), "def");
-    BOOST_CHECK_CLOSE(val2[Value(1234.56)].as<double>(), 666.66, 1.0e-10);
-    /// Cannot index using bools
-    /// BOOST_CHECK_EQUAL(val2[3].as<bool>(), false);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_makelist_vector ) {
-    // n.b. This is templated, so will work for a std::vector<T> for any T for which a Value can be constructed.
-
-    std::vector<int> vint;
-    for (int i = 99; i > 0; i -= 11)
-        vint.push_back(i);
-
-    Value val = makeVectorValue(vint);
-
-    BOOST_CHECK(val.isList());
-    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 9);
-    BOOST_CHECK_EQUAL(val[4].as<long long>(), 55);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_makelist_list ) {
-    // n.b. This is templated, so will work for a std::list<T> for any T for which a Value can be constructed.
-
-    std::list<int> lint;
-    for (int i = 99; i > 0; i -= 11)
-        lint.push_back(i);
-
-    Value val = makeVectorValue(lint);
-
-    BOOST_CHECK(val.isList());
-    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 9);
-    BOOST_CHECK_EQUAL(val[4].as<long long>(), 55);
-}
-
-//----------------------------------------------------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_CASE( test_eckit_value_wrapper_types ) {
-    // There are some constructors that have been added for easy conversion, that aren't actually part of the
-    // internal interface
-
-    // Length type
-
-    Value val_length(Length(12345));
-
-    BOOST_CHECK(val_length.isNumber());
-
-    BOOST_CHECK(!val_length.isNil());
-    BOOST_CHECK(!val_length.isBool());
-    BOOST_CHECK(!val_length.isDouble());
-    BOOST_CHECK(!val_length.isString());
-    BOOST_CHECK(!val_length.isList());
-    BOOST_CHECK(!val_length.isMap());
-    BOOST_CHECK(!val_length.isDate());
-    BOOST_CHECK(!val_length.isTime());
-    BOOST_CHECK(!val_length.isDateTime());
-
-    BOOST_CHECK_EQUAL(int(val_length), 12345);
-    BOOST_CHECK_EQUAL(val_length.as<long long>(), 12345);
-
-    // Offset type
-
-    Value val_offset(Offset(54321));
-
-    BOOST_CHECK(val_offset.isNumber());
-
-    BOOST_CHECK(!val_offset.isNil());
-    BOOST_CHECK(!val_offset.isBool());
-    BOOST_CHECK(!val_offset.isDouble());
-    BOOST_CHECK(!val_offset.isString());
-    BOOST_CHECK(!val_offset.isList());
-    BOOST_CHECK(!val_offset.isMap());
-    BOOST_CHECK(!val_offset.isDate());
-    BOOST_CHECK(!val_offset.isTime());
-    BOOST_CHECK(!val_offset.isDateTime());
-
-    BOOST_CHECK_EQUAL(int(val_offset), 54321);
-    BOOST_CHECK_EQUAL(val_offset.as<long long>(), 54321);
-
-    // PathName type
-
-    Value val_pathname(PathName("/usr/bin"));
-
-    BOOST_CHECK(val_pathname.isString());
-
-    BOOST_CHECK(!val_pathname.isNil());
-    BOOST_CHECK(!val_pathname.isBool());
-    BOOST_CHECK(!val_pathname.isDouble());
-    BOOST_CHECK(!val_pathname.isNumber());
-    BOOST_CHECK(!val_pathname.isList());
-    BOOST_CHECK(!val_pathname.isMap());
-    BOOST_CHECK(!val_pathname.isDate());
-    BOOST_CHECK(!val_pathname.isTime());
-    BOOST_CHECK(!val_pathname.isDateTime());
-
-    BOOST_CHECK_EQUAL(std::string(val_pathname), "/usr/bin");
-    BOOST_CHECK_EQUAL(val_pathname.as<std::string>(), "/usr/bin");
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-//----------------------------------------------------------------------------------------------------------------------
-
-} // namespace test
-} // namespace eckit
diff --git a/eckit/src/tests/value/test_value_properties.cc b/eckit/src/tests/value/test_value_properties.cc
deleted file mode 100644
index 1670ff0..0000000
--- a/eckit/src/tests/value/test_value_properties.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * (C) Copyright 1996-2017 ECMWF.
- *
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
- * In applying this licence, ECMWF does not waive the privileges and immunities
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#define BOOST_TEST_MODULE test_eckit_value_properties
-
-#include <limits>
-
-#include "ecbuild/boost_test_framework.h"
-
-#include "eckit/filesystem/PathName.h"
-#include "eckit/io/Length.h"
-#include "eckit/serialisation/FileStream.h"
-#include "eckit/types/Date.h"
-#include "eckit/value/Properties.h"
-
-using namespace std;
-using namespace eckit;
-
-//-----------------------------------------------------------------------------
-
-namespace eckit_test {
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE( test_eckit_value_properties )
-
-BOOST_AUTO_TEST_CASE( test_serialize )
-{
-    BOOST_TEST_MESSAGE("(de)serialize Properties to/from file");
-    PathName filename = PathName::unique( "data" );
-    std::string filepath = filename.asString();
-    Properties p;
-    p.set("bool", true);
-    p.set("int", numeric_limits<int>::max());
-    p.set("unsigned int", numeric_limits<unsigned int>::max());
-    p.set("long long", numeric_limits<long long>::max());
-    p.set("unsigned long long", numeric_limits<unsigned long long>::max());
-    p.set("double", numeric_limits<double>::max());
-    p.set("string", "foo");
-    p.set("Length", Length(42));
-    p.set("Date", Date(2015, 2, 1));
-    // p.set("Time", Time(11, 59, 59));  <-- not implemented
-    // p.set("DateTime", DateTime(Date(1, 2, 2015), Time(11, 59, 59)));  <-- not implemented
-    p.set("PathName", PathName("/var/tmp"));
-    p.set("Vector", ValueList(5, "string"));
-    ValueMap m;
-    m.insert( std::make_pair("int", numeric_limits<int>::max()) );
-    m.insert( std::make_pair("unsigned int", numeric_limits<unsigned int>::max()) );
-    m.insert( std::make_pair("long long", numeric_limits<long long>::max()) );
-    m.insert( std::make_pair("unsigned long long", numeric_limits<unsigned long long>::max()) );
-    m.insert( std::make_pair("double", numeric_limits<double>::max()) );
-    m.insert( std::make_pair("string", "foo") );
-    m.insert( std::make_pair("Length", Length(42)) );
-    m.insert( std::make_pair("PathName", PathName("/var/tmp")) );
-    m.insert( std::make_pair("Vector", ValueList(5, "string")) );
-    p.set("Map", Value(m) );
-
-    Properties pm;
-    pm.set("int",numeric_limits<int>::max());
-    pm.set("unsigned int", numeric_limits<unsigned int>::max());
-    p.set("Nested", pm );
-
-    std::vector<Properties> property_list(2);
-    property_list[0].set("int",numeric_limits<int>::max());
-    property_list[1].set("string","foo");
-    p.set("list", makeVectorValue(property_list) );
-
-    BOOST_TEST_MESSAGE("encoded Properties: " << p);
-    {
-        FileStream sout( filepath.c_str(), "w" );
-        sout << p;
-    }
-    {
-        FileStream sin( filepath.c_str(), "r" );
-        Properties p2(sin);
-        BOOST_TEST_MESSAGE("decoded Properties: " << p2);
-        BOOST_CHECK_EQUAL((bool)p["bool"], (bool)p2["bool"]);
-        BOOST_CHECK_EQUAL(p["int"], p2["int"]);
-        BOOST_CHECK_EQUAL(p["unsigned int"], p2["unsigned int"]);
-        BOOST_CHECK_EQUAL(p["long long"], p2["long long"]);
-        BOOST_CHECK_EQUAL(p["unsigned long long"], p2["unsigned long long"]);
-        BOOST_CHECK_EQUAL(p["double"], p2["double"]);
-        BOOST_CHECK_EQUAL(p["string"], p2["string"]);
-        BOOST_CHECK_EQUAL(p["Length"], p2["Length"]);
-        BOOST_CHECK(p["Date"].compare(p2["Date"])); // FIXME: equality check fails
-        // BOOST_CHECK_EQUAL(p["Time"], p2["Time"]);  <-- not implemented
-        // BOOST_CHECK_EQUAL(p["DateTime"], p2["DateTime"]); <-- not implemented
-        BOOST_CHECK_EQUAL(p["PathName"], p2["PathName"]);
-        BOOST_CHECK_EQUAL(p["Vector"], p2["Vector"]);
-        BOOST_CHECK_EQUAL(p["Map"], p2["Map"]);
-    }
-    if (filename.exists()) filename.unlink();
-
-    Properties access_nested = p.get("Nested");
-
-    eckit::ValueList access_list = p.get("list");
-    BOOST_TEST_MESSAGE("encoded list: " <<  access_list );
-    std::vector<eckit::Properties> access_property_list(access_list.begin(),access_list.end());
-
-    BOOST_TEST_MESSAGE("encoded Nested: " << access_nested);
-    {
-        FileStream sout( filepath.c_str(), "w" );
-        sout << p;
-    }
-
-}
-
-//-----------------------------------------------------------------------------
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace eckit_test
diff --git a/eckit/tests/CMakeLists.txt b/eckit/tests/CMakeLists.txt
new file mode 100644
index 0000000..66b1789
--- /dev/null
+++ b/eckit/tests/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_subdirectory( config   )
+add_subdirectory( container )
+add_subdirectory( filesystem )
+add_subdirectory( geometry )
+add_subdirectory( io )
+add_subdirectory( large_file )
+add_subdirectory( linalg )
+add_subdirectory( log )
+add_subdirectory( maths )
+add_subdirectory( memory )
+add_subdirectory( memory_map )
+add_subdirectory( mpi )
+add_subdirectory( option )
+add_subdirectory( parser )
+add_subdirectory( runtime )
+add_subdirectory( serialisation )
+add_subdirectory( thread )
+add_subdirectory( types )
+add_subdirectory( utils )
+add_subdirectory( value )
+add_subdirectory( system )
+
+if( HAVE_EXPERIMENTAL )
+  add_subdirectory( experimental )
+endif()
diff --git a/eckit/tests/config/CMakeLists.txt b/eckit/tests/config/CMakeLists.txt
new file mode 100644
index 0000000..9635296
--- /dev/null
+++ b/eckit/tests/config/CMakeLists.txt
@@ -0,0 +1,10 @@
+ecbuild_add_test( TARGET   eckit_test_resource
+                  BOOST
+                  SOURCES  test_resource.cc
+                  ARGS     -integer 100 -listlong 88,99,11,22
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_configuration
+                  BOOST
+                  SOURCES  test_configuration.cc
+                  LIBS     eckit )
diff --git a/eckit/tests/config/test_configuration.cc b/eckit/tests/config/test_configuration.cc
new file mode 100644
index 0000000..1d26dff
--- /dev/null
+++ b/eckit/tests/config/test_configuration.cc
@@ -0,0 +1,287 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_configuration
+
+#include "ecbuild/boost_test_framework.h"
+
+#include <fstream>
+
+#include "eckit/log/Log.h"
+#include "eckit/config/LocalConfiguration.h"
+#include "eckit/config/YAMLConfiguration.h"
+#include "eckit/types/Types.h"
+#include "eckit/testing/Setup.h"
+
+namespace eckit {
+namespace test {
+    template<typename T> std::vector<T> make_vector( const T& t1, const T& t2 ) {
+        std::vector<T> result;
+        result.push_back(t1);
+        result.push_back(t2);
+        return result;
+    }
+    template<typename T> std::vector<T> make_vector( const T& t1, const T& t2, const T& t3 ) {
+        std::vector<T> result;
+        result.push_back(t1);
+        result.push_back(t2);
+        result.push_back(t3);
+        return result;
+    }
+}
+}
+
+using namespace std;
+using namespace eckit;
+using namespace eckit::test;
+using namespace eckit::testing;
+
+//-----------------------------------------------------------------------------
+
+BOOST_GLOBAL_FIXTURE( Setup );
+
+BOOST_AUTO_TEST_SUITE( test_eckit_config )
+
+BOOST_AUTO_TEST_CASE( test_configuration_interface )
+{
+    bool                value_bool            = bool(true); 
+    int                 value_int             = int(1);
+    long                value_long            = long(2);
+    size_t              value_size_t          = size_t(3);
+    float               value_float           = float(1.234567);
+    double              value_double          = double(1.2345678912345789123456789);
+    std::string         value_string          = std::string("string");
+    std::vector<int>    value_arr_int         = make_vector(1,2,3);
+    std::vector<long>   value_arr_long        = make_vector(4l,5l);
+    std::vector<size_t> value_arr_size_t      = make_vector(6ul,7ul);
+    std::vector<float>  value_arr_float       = make_vector(1.234567f,2.345678f);
+    std::vector<double> value_arr_double      = make_vector(1.234567,2.345678);
+    std::vector<std::string> value_arr_string = make_vector(std::string("hello"),std::string("world"));
+  
+    bool                      result_bool;
+    int                       result_int;
+    long                      result_long;
+    size_t                    result_size_t;
+    float                     result_float;
+    double                    result_double;
+    std::string               result_string;
+    std::vector<int>          result_arr_int;
+    std::vector<long>         result_arr_long;
+    std::vector<size_t>       result_arr_size_t;
+    std::vector<float>        result_arr_float;
+    std::vector<double>       result_arr_double;
+    std::vector<std::string>  result_arr_string;
+
+    LocalConfiguration local;
+    {
+        local.set("bool",       value_bool      );
+        local.set("int",        value_int       );
+        local.set("long",       value_long      );
+        local.set("size_t",     value_size_t    );
+        local.set("float",      value_float     );
+        local.set("double",     value_double    );
+        local.set("string",     value_string    );
+        local.set("arr_int",    value_arr_int   );
+        local.set("arr_long",   value_arr_long  );
+        local.set("arr_size_t", value_arr_size_t);
+        local.set("arr_float",  value_arr_float );
+        local.set("arr_double", value_arr_double);
+        local.set("arr_string", value_arr_string);
+    }
+    const Configuration& conf = local;
+  
+    BOOST_CHECK( ! conf.get("missing",result_bool)       );
+    BOOST_CHECK( ! conf.get("missing",result_int)        );
+    BOOST_CHECK( ! conf.get("missing",result_long)       );
+    BOOST_CHECK( ! conf.get("missing",result_size_t)     );
+    BOOST_CHECK( ! conf.get("missing",result_float)      );
+    BOOST_CHECK( ! conf.get("missing",result_double)     );
+    BOOST_CHECK( ! conf.get("missing",result_string)     );
+    BOOST_CHECK( ! conf.get("missing",result_arr_int)    );
+    BOOST_CHECK( ! conf.get("missing",result_arr_long)   );
+    BOOST_CHECK( ! conf.get("missing",result_arr_size_t) );
+    BOOST_CHECK( ! conf.get("missing",result_arr_float)  );
+    BOOST_CHECK( ! conf.get("missing",result_arr_double) );
+    BOOST_CHECK( ! conf.get("missing",result_arr_string) );
+  
+    BOOST_CHECK( conf.get("bool",       result_bool)       );
+    BOOST_CHECK( conf.get("int",        result_int)        );
+    BOOST_CHECK( conf.get("long",       result_long)       );
+    BOOST_CHECK( conf.get("size_t",     result_size_t)     );
+    BOOST_CHECK( conf.get("float",      result_float)      );
+    BOOST_CHECK( conf.get("double",     result_double)     );
+    BOOST_CHECK( conf.get("string",     result_string)     );
+    BOOST_CHECK( conf.get("arr_int",    result_arr_int)    );
+    BOOST_CHECK( conf.get("arr_long",   result_arr_long)   );
+    BOOST_CHECK( conf.get("arr_size_t", result_arr_size_t) );
+    BOOST_CHECK( conf.get("arr_float",  result_arr_float)  );
+    BOOST_CHECK( conf.get("arr_double", result_arr_double) );
+    BOOST_CHECK( conf.get("arr_string", result_arr_string) );
+  
+    BOOST_CHECK_EQUAL( result_bool,       value_bool      );
+    BOOST_CHECK_EQUAL( result_int,        value_int       );
+    BOOST_CHECK_EQUAL( result_long,       value_long      );
+    BOOST_CHECK_EQUAL( result_size_t,     value_size_t    );
+    BOOST_CHECK_EQUAL( result_float,      value_float     );
+    BOOST_CHECK_EQUAL( result_double,     value_double    );
+    BOOST_CHECK_EQUAL( result_string,     value_string    );
+    BOOST_CHECK_EQUAL( result_arr_int,    value_arr_int   );
+    BOOST_CHECK_EQUAL( result_arr_long,   value_arr_long  );
+    BOOST_CHECK_EQUAL( result_arr_size_t, value_arr_size_t);
+    BOOST_CHECK_EQUAL( result_arr_float,  value_arr_float );
+    BOOST_CHECK_EQUAL( result_arr_double, value_arr_double);
+    BOOST_CHECK_EQUAL( result_arr_string, value_arr_string);
+
+    BOOST_CHECK_EQUAL( conf.getBool          ("bool"),       value_bool       );
+    BOOST_CHECK_EQUAL( conf.getInt           ("int"),        value_int        );
+    BOOST_CHECK_EQUAL( conf.getLong          ("long"),       value_long       );
+    BOOST_CHECK_EQUAL( conf.getUnsigned      ("size_t"),     value_size_t     );
+    BOOST_CHECK_EQUAL( conf.getFloat         ("float"),      value_float      );
+    BOOST_CHECK_EQUAL( conf.getDouble        ("double"),     value_double     );
+    BOOST_CHECK_EQUAL( conf.getString        ("string"),     value_string     );
+    BOOST_CHECK_EQUAL( conf.getIntVector     ("arr_int"),    value_arr_int    );
+    BOOST_CHECK_EQUAL( conf.getLongVector    ("arr_long"),   value_arr_long   );
+    BOOST_CHECK_EQUAL( conf.getUnsignedVector("arr_size_t"), value_arr_size_t );
+    BOOST_CHECK_EQUAL( conf.getFloatVector   ("arr_float"),  value_arr_float  );
+    BOOST_CHECK_EQUAL( conf.getDoubleVector  ("arr_double"), value_arr_double );
+    BOOST_CHECK_EQUAL( conf.getStringVector  ("arr_string"), value_arr_string );
+
+    // Get throwing
+
+    BOOST_CHECK_THROW( conf.getBool          ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getInt           ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getLong          ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getUnsigned      ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getFloat         ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getDouble        ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getString        ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getIntVector     ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getLongVector    ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getUnsignedVector("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getFloatVector   ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getDoubleVector  ("missing"), eckit::Exception );
+    BOOST_CHECK_THROW( conf.getStringVector  ("missing"), eckit::Exception );
+
+  
+    // Get with default values instead of throwing
+    BOOST_CHECK_EQUAL( conf.getBool          ("missing",value_bool),       value_bool       );
+    BOOST_CHECK_EQUAL( conf.getInt           ("missing",value_int),        value_int        );
+    BOOST_CHECK_EQUAL( conf.getLong          ("missing",value_long),       value_long       );
+    BOOST_CHECK_EQUAL( conf.getUnsigned      ("missing",value_size_t),     value_size_t     );
+    BOOST_CHECK_EQUAL( conf.getFloat         ("missing",value_float),      value_float      );
+    BOOST_CHECK_EQUAL( conf.getDouble        ("missing",value_double),     value_double     );
+    BOOST_CHECK_EQUAL( conf.getString        ("missing",value_string),     value_string     );
+    BOOST_CHECK_EQUAL( conf.getIntVector     ("missing",value_arr_int),    value_arr_int    );
+    BOOST_CHECK_EQUAL( conf.getLongVector    ("missing",value_arr_long),   value_arr_long   );
+    BOOST_CHECK_EQUAL( conf.getUnsignedVector("missing",value_arr_size_t), value_arr_size_t );
+    BOOST_CHECK_EQUAL( conf.getFloatVector   ("missing",value_arr_float ), value_arr_float  );
+    BOOST_CHECK_EQUAL( conf.getDoubleVector  ("missing",value_arr_double), value_arr_double );
+    BOOST_CHECK_EQUAL( conf.getStringVector  ("missing",value_arr_string), value_arr_string );
+
+}
+
+//-----------------------------------------------------------------------------
+
+
+BOOST_AUTO_TEST_CASE( test_json_configuration )
+{
+  PathName jsonpath = "test_json_configuration.json";
+
+  std::string jsonstr(
+    "\n" "{"
+    "\n" "  \"manager\" : { \"name\" : \"Sidonia\" , \"office\" : 1 },"
+    "\n" "  \"staff\" : ["
+    "\n" "    { \"name\" : \"Suske\" , \"office\" : 2 },"
+    "\n" "    { \"name\" : \"Wiske\" , \"office\" : 3 }"
+    "\n" "  ]"
+    "\n" "}"
+    "\n");
+
+  {
+    std::ofstream jsonfile (jsonpath.localPath());
+    jsonfile << jsonstr;
+  }
+
+  YAMLConfiguration conf_from_str(jsonstr);
+  YAMLConfiguration conf(jsonpath);
+  LocalConfiguration manager;
+  std::vector<LocalConfiguration> staff;
+
+  BOOST_CHECK( conf.get("manager",manager) );
+  BOOST_CHECK( conf.get("staff",staff) );
+
+  std::string name;
+  int office;
+
+  BOOST_CHECK( manager.get("name",name) );
+  BOOST_CHECK( manager.get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Sidonia") );
+  BOOST_CHECK_EQUAL( office, 1 );
+
+  BOOST_CHECK( staff[0].get("name",name) );
+  BOOST_CHECK( staff[0].get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Suske") );
+  BOOST_CHECK_EQUAL( office, 2 );
+
+  BOOST_CHECK( staff[1].get("name",name) );
+  BOOST_CHECK( staff[1].get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Wiske") );
+  BOOST_CHECK_EQUAL( office, 3 );
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_local_configuration )
+{
+  LocalConfiguration local;
+  {
+    LocalConfiguration manager;
+    manager.set("name","Sidonia");
+    manager.set("office",1);
+
+    std::vector<LocalConfiguration> staff(2);
+    staff[0].set("name","Suske");
+    staff[1].set("name","Wiske");
+    staff[0].set("office",2);
+    staff[1].set("office",3);
+
+    local.set("manager",manager);
+    local.set("staff",staff);
+  }
+  const Configuration& conf = local;
+
+  LocalConfiguration manager;
+  std::vector<LocalConfiguration> staff;
+
+  BOOST_CHECK( conf.get("manager",manager) );
+  BOOST_CHECK( conf.get("staff",staff) );
+
+  std::string name;
+  int office;
+
+  BOOST_CHECK( manager.get("name",name) );
+  BOOST_CHECK( manager.get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Sidonia") );
+  BOOST_CHECK_EQUAL( office, 1 );
+
+  BOOST_CHECK( staff[0].get("name",name) );
+  BOOST_CHECK( staff[0].get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Suske") );
+  BOOST_CHECK_EQUAL( office, 2 );
+
+  BOOST_CHECK( staff[1].get("name",name) );
+  BOOST_CHECK( staff[1].get("office",office) );
+  BOOST_CHECK_EQUAL( name, std::string("Wiske") );
+  BOOST_CHECK_EQUAL( office, 3 );
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/tests/config/test_resource.cc b/eckit/tests/config/test_resource.cc
new file mode 100644
index 0000000..7948ec3
--- /dev/null
+++ b/eckit/tests/config/test_resource.cc
@@ -0,0 +1,113 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <cmath>
+
+#define BOOST_TEST_MODULE test_eckit_resource
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/config/LibEcKit.h"
+#include "eckit/config/Resource.h"
+#include "eckit/config/ResourceMgr.h"
+#include "eckit/log/Bytes.h"
+#include "eckit/log/Log.h"
+#include "eckit/runtime/Tool.h"
+#include "eckit/types/Types.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace eckit;
+using namespace eckit::testing;
+
+//-----------------------------------------------------------------------------
+
+BOOST_GLOBAL_FIXTURE( Setup );
+
+BOOST_AUTO_TEST_SUITE( test_eckit_resource )
+
+BOOST_AUTO_TEST_CASE( test_default )
+{
+    std::string s = Resource<std::string>("s","some");
+
+    BOOST_CHECK( s == "some" );
+
+    double d = Resource<double>("d", 777.7);
+
+	BOOST_CHECK_CLOSE( d , 777.7, 0.0001 ); // accept 0.0001% tolerance
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_vector_long )
+{
+    std::vector<long> def(3,77);
+    std::vector<long> v = Resource< std::vector<long> >("listlong;-listlong",def);
+
+    BOOST_CHECK_EQUAL( v[0] , 88 );
+    BOOST_CHECK_EQUAL( v[1] , 99 );
+    BOOST_CHECK_EQUAL( v[2] , 11 );
+    BOOST_CHECK_EQUAL( v[3] , 22 );
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_command_line )
+{
+	int myint = Resource<int>("integer;-integer",0);
+	BOOST_CHECK_EQUAL( myint , 100 );
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_environment_var )
+{
+    char v [] = "TEST_ENV_INT=333";
+    putenv(v);
+
+	int intenv = Resource<int>("intEnv;$TEST_ENV_INT",777);
+	BOOST_CHECK_EQUAL( intenv , 333 );
+
+    char foo [] = "FOO=1Mb";
+    putenv(foo);
+
+	long l1 = Resource<long>("$FOO",0);
+	BOOST_CHECK_EQUAL( l1 , 1024*1024 );
+
+	long l2 = Resource<long>("$FOO;-foo",0);
+	BOOST_CHECK_EQUAL( l2 , 1024*1024);
+
+	long l3 = Resource<long>("-foo;$FOO",0);
+	BOOST_CHECK_EQUAL( l3, 1024*1024);
+
+	long l4 = Resource<long>("$FOO;foo;-foo",0);
+	BOOST_CHECK_EQUAL( l4 , 1024*1024);
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_libresource )
+{
+    long i = LibResource<long,LibEcKit>("foo-bar;$FOOBAR", 1024*1024);
+
+    BOOST_CHECK_EQUAL(i , 1024*1024);
+
+
+    char v [] = "TEST_FOOBAZ=fooBAZ";
+    putenv(v);
+    std::string foobaz = LibResource<std::string,LibEcKit>("foo-baz;$TEST_FOOBAZ", "foobazzzzzzz");
+
+    BOOST_CHECK_EQUAL(foobaz, "fooBAZ");
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/eckit/tests/container/CMakeLists.txt b/eckit/tests/container/CMakeLists.txt
new file mode 100644
index 0000000..4493f61
--- /dev/null
+++ b/eckit/tests/container/CMakeLists.txt
@@ -0,0 +1,34 @@
+ecbuild_add_test( TARGET   eckit_test_sharedmemarray
+                  BOOST
+                  SOURCES  test_sharedmemarray.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_btree
+                  BOOST
+                  SOURCES  test_btree.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_bloomfilter
+                  BOOST
+                  SOURCES  test_bloomfilter.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_trie
+                  BOOST
+                  SOURCES  test_trie.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_densemap
+                  BOOST
+                  SOURCES  test_densemap.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_cache_lru
+                  BOOST
+                  SOURCES  test_cache_lru.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_benchmark_densemap
+                  BOOST
+                  SOURCES  benchmark_densemap.cc
+                  LIBS     eckit )
diff --git a/eckit/src/tests/container/benchmark_densemap.cc b/eckit/tests/container/benchmark_densemap.cc
similarity index 100%
rename from eckit/src/tests/container/benchmark_densemap.cc
rename to eckit/tests/container/benchmark_densemap.cc
diff --git a/eckit/tests/container/test_bloomfilter.cc b/eckit/tests/container/test_bloomfilter.cc
new file mode 100755
index 0000000..aa7936c
--- /dev/null
+++ b/eckit/tests/container/test_bloomfilter.cc
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE eckit_test_bloomfilter
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/container/BloomFilter.h"
+
+using namespace std;
+using namespace eckit;
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE( test_eckit_container_bloomfilter )
+
+BOOST_AUTO_TEST_CASE( test_eckit_container_bloomfilter_insert )
+{
+
+    BloomFilter<std::string> f(1024);
+
+    BOOST_CHECK(f.empty());
+    BOOST_CHECK(!f.contains("hello there"));
+    BOOST_CHECK(!f.contains("hello there again"));
+
+    f.insert("hello there");
+
+    BOOST_CHECK(f.contains("hello there"));
+    BOOST_CHECK(!f.contains("hello there again"));
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/container/test_btree.cc b/eckit/tests/container/test_btree.cc
similarity index 100%
rename from eckit/src/tests/container/test_btree.cc
rename to eckit/tests/container/test_btree.cc
diff --git a/eckit/src/tests/container/test_cache_lru.cc b/eckit/tests/container/test_cache_lru.cc
similarity index 100%
rename from eckit/src/tests/container/test_cache_lru.cc
rename to eckit/tests/container/test_cache_lru.cc
diff --git a/eckit/src/tests/container/test_densemap.cc b/eckit/tests/container/test_densemap.cc
similarity index 100%
rename from eckit/src/tests/container/test_densemap.cc
rename to eckit/tests/container/test_densemap.cc
diff --git a/eckit/src/tests/container/test_sharedmemarray.cc b/eckit/tests/container/test_sharedmemarray.cc
similarity index 100%
rename from eckit/src/tests/container/test_sharedmemarray.cc
rename to eckit/tests/container/test_sharedmemarray.cc
diff --git a/eckit/tests/container/test_trie.cc b/eckit/tests/container/test_trie.cc
new file mode 100755
index 0000000..07eec59
--- /dev/null
+++ b/eckit/tests/container/test_trie.cc
@@ -0,0 +1,250 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE eckit_test_trie
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/container/Trie.h"
+#include "eckit/testing/Setup.h"
+#include "eckit/log/Log.h"
+
+using namespace std;
+using namespace eckit;
+using namespace eckit::testing;
+
+//-----------------------------------------------------------------------------
+
+// ii) Test removal
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+BOOST_AUTO_TEST_SUITE( test_eckit_container_trie )
+
+BOOST_AUTO_TEST_CASE( test_trie_insertion )
+{
+    Trie<int> tr;
+
+    BOOST_CHECK(tr.empty());
+
+    tr.insert("a-test-string", 1234);
+
+    BOOST_CHECK(!tr.empty());
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("b-test-string") == 0);
+    BOOST_CHECK(tr.find("a-test-strinh") == 0);
+    BOOST_CHECK(tr.find("a-test-str") == 0);
+    BOOST_CHECK(tr.find("a-test-stringy") == 0);
+
+    // Test something that branches off with a lower character value
+
+    tr.insert("a-different-string", 4321);
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("a-different-string") != 0);
+    BOOST_CHECK(*tr.find("a-different-string") == 4321);
+
+    // Test something that branches off with a higher charachter value
+
+    tr.insert("a-x-string", 666);
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("a-different-string") != 0);
+    BOOST_CHECK(*tr.find("a-different-string") == 4321);
+
+    BOOST_CHECK(tr.find("a-x-string") != 0);
+    BOOST_CHECK(*tr.find("a-x-string") == 666);
+
+    // Test inserting a substring of an existing string
+
+    BOOST_CHECK(tr.find("a-x") == 0);
+
+    tr.insert("a-x", 999);
+
+    BOOST_CHECK(tr.find("a-x-string") != 0);
+    BOOST_CHECK(*tr.find("a-x-string") == 666);
+
+    BOOST_CHECK(tr.find("a-x") != 0);
+    BOOST_CHECK(*tr.find("a-x") == 999);
+
+    // Test weird characters
+
+    tr.insert("a-#$@!%^&*", 9876);
+
+    BOOST_CHECK(tr.find("a-x-string") != 0);
+    BOOST_CHECK(*tr.find("a-x-string") == 666);
+
+    BOOST_CHECK(tr.find("a-#$@!%^&*") != 0);
+    BOOST_CHECK(*tr.find("a-#$@!%^&*") == 9876);
+
+    // Test with strings such that an existing entry is a substring.
+
+    tr.insert("a-test-string-extended", 5678);
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("a-test-string-extended") != 0);
+    BOOST_CHECK(*tr.find("a-test-string-extended") == 5678);
+
+    // Test insert change first character
+
+    tr.insert("b-test-string", 3141);
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("b-test-string") != 0);
+    BOOST_CHECK(*tr.find("b-test-string") == 3141);
+
+    // Test insert change last character
+
+    tr.insert("a-test-strinh", 1413);
+
+    BOOST_CHECK(tr.find("a-test-string") != 0);
+    BOOST_CHECK(*tr.find("a-test-string") == 1234);
+
+    BOOST_CHECK(tr.find("a-test-strinh") != 0);
+    BOOST_CHECK(*tr.find("a-test-strinh") == 1413);
+
+}
+
+BOOST_AUTO_TEST_CASE( test_trie_value_zero )
+{
+    // Just to check that we aren't using the value_ for making any internal decisions
+
+    Trie<int> tr;
+
+    BOOST_CHECK(tr.empty());
+
+    tr.insert("a-str", 0);
+
+    BOOST_CHECK(!tr.empty());
+    BOOST_CHECK(tr.contains("a-str"));
+    BOOST_CHECK(*tr.find("a-str") == 0);
+
+}
+
+BOOST_AUTO_TEST_CASE( test_trie_bools )
+{
+    Trie<bool> tr;
+
+    BOOST_CHECK(tr.empty());
+
+    tr.insert("a-str", false);
+    tr.insert("a-sts", true);
+
+    BOOST_CHECK(!tr.empty());
+
+    BOOST_CHECK(tr.contains("a-str"));
+    BOOST_CHECK(*tr.find("a-str") == false);
+
+    BOOST_CHECK(tr.contains("a-sts"));
+    BOOST_CHECK(*tr.find("a-sts") == true);
+}
+
+BOOST_AUTO_TEST_CASE( test_trie_double )
+{
+    Trie<double> tr;
+
+    BOOST_CHECK(tr.empty());
+
+    tr.insert("a-str", 12.345);
+    tr.insert("a-sts", 5.4321e99);
+
+    BOOST_CHECK(!tr.empty());
+
+    BOOST_CHECK(tr.contains("a-str"));
+    BOOST_CHECK_CLOSE(*tr.find("a-str") , 12.345, 1e-10);
+
+    BOOST_CHECK(tr.contains("a-sts"));
+    BOOST_CHECK_CLOSE(*tr.find("a-sts"), 5.4321e99, 1e-10);
+}
+
+
+BOOST_AUTO_TEST_CASE( test_removal )
+{
+    Trie<int> tr;
+
+    tr.insert("a", 1111);
+    tr.insert("a-string", 2222);
+    tr.insert("a-strinh", 3333);
+    tr.insert("a-string-extended", 4444);
+    tr.insert("a-str", 555);
+
+    BOOST_CHECK(!tr.empty());
+
+    BOOST_CHECK(tr.contains("a"));
+    BOOST_CHECK(tr.contains("a-string"));
+    BOOST_CHECK(tr.contains("a-strinh"));
+    BOOST_CHECK(tr.contains("a-string-extended"));
+    BOOST_CHECK(tr.contains("a-str"));
+
+    tr.remove("a");
+
+    BOOST_CHECK(!tr.empty());
+    BOOST_CHECK(!tr.contains("a"));
+    BOOST_CHECK(tr.contains("a-string"));
+    BOOST_CHECK(tr.contains("a-strinh"));
+    BOOST_CHECK(tr.contains("a-string-extended"));
+    BOOST_CHECK(tr.contains("a-str"));
+
+    // Remove a substring before removing the longer one.
+
+    tr.remove("a-string");
+
+    BOOST_CHECK(!tr.empty());
+    BOOST_CHECK(!tr.contains("a"));
+    BOOST_CHECK(!tr.contains("a-string"));
+    BOOST_CHECK(tr.contains("a-strinh"));
+    BOOST_CHECK(tr.contains("a-string-extended"));
+    BOOST_CHECK(tr.contains("a-str"));
+
+    tr.remove("a-strinh");
+
+    BOOST_CHECK(!tr.empty());
+    BOOST_CHECK(!tr.contains("a"));
+    BOOST_CHECK(!tr.contains("a-string"));
+    BOOST_CHECK(!tr.contains("a-strinh"));
+    BOOST_CHECK(tr.contains("a-string-extended"));
+    BOOST_CHECK(tr.contains("a-str"));
+
+    tr.remove("a-string-extended");
+
+    BOOST_CHECK(!tr.empty());
+    BOOST_CHECK(!tr.contains("a"));
+    BOOST_CHECK(!tr.contains("a-string"));
+    BOOST_CHECK(!tr.contains("a-strinh"));
+    BOOST_CHECK(!tr.contains("a-string-extended"));
+    BOOST_CHECK(tr.contains("a-str"));
+
+    // And this time we remove the shorter one later
+
+    tr.remove("a-str");
+
+    BOOST_CHECK(!tr.contains("a"));
+    BOOST_CHECK(!tr.contains("a-string"));
+    BOOST_CHECK(!tr.contains("a-strinh"));
+    BOOST_CHECK(!tr.contains("a-string-extended"));
+    BOOST_CHECK(!tr.contains("a-str"));
+
+    BOOST_CHECK(tr.empty());
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/experimental/tests/CMakeLists.txt b/eckit/tests/experimental/CMakeLists.txt
similarity index 100%
rename from eckit/src/experimental/tests/CMakeLists.txt
rename to eckit/tests/experimental/CMakeLists.txt
diff --git a/eckit/src/experimental/tests/singleton/CMakeLists.txt b/eckit/tests/experimental/singleton/CMakeLists.txt
similarity index 100%
rename from eckit/src/experimental/tests/singleton/CMakeLists.txt
rename to eckit/tests/experimental/singleton/CMakeLists.txt
diff --git a/eckit/src/experimental/tests/singleton/TestBuilder1.cc b/eckit/tests/experimental/singleton/TestBuilder1.cc
similarity index 100%
rename from eckit/src/experimental/tests/singleton/TestBuilder1.cc
rename to eckit/tests/experimental/singleton/TestBuilder1.cc
diff --git a/eckit/src/experimental/tests/singleton/TestBuilder2.cc b/eckit/tests/experimental/singleton/TestBuilder2.cc
similarity index 100%
rename from eckit/src/experimental/tests/singleton/TestBuilder2.cc
rename to eckit/tests/experimental/singleton/TestBuilder2.cc
diff --git a/eckit/src/experimental/tests/singleton/TestFactory.cc b/eckit/tests/experimental/singleton/TestFactory.cc
similarity index 100%
rename from eckit/src/experimental/tests/singleton/TestFactory.cc
rename to eckit/tests/experimental/singleton/TestFactory.cc
diff --git a/eckit/src/experimental/tests/singleton/TestFactory.h b/eckit/tests/experimental/singleton/TestFactory.h
similarity index 100%
rename from eckit/src/experimental/tests/singleton/TestFactory.h
rename to eckit/tests/experimental/singleton/TestFactory.h
diff --git a/eckit/src/experimental/tests/singleton/test_singleton.cc b/eckit/tests/experimental/singleton/test_singleton.cc
similarity index 100%
rename from eckit/src/experimental/tests/singleton/test_singleton.cc
rename to eckit/tests/experimental/singleton/test_singleton.cc
diff --git a/eckit/tests/filesystem/CMakeLists.txt b/eckit/tests/filesystem/CMakeLists.txt
new file mode 100644
index 0000000..a416d0b
--- /dev/null
+++ b/eckit/tests/filesystem/CMakeLists.txt
@@ -0,0 +1,35 @@
+# aio system calls are know to fail on the Cray
+# see https://sourceware.org/bugzilla/show_bug.cgi?id=11787
+
+ecbuild_add_test( TARGET      eckit_test_multihandle
+                  SOURCES     test_multihandle.cc
+                  LIBS        eckit )
+
+ecbuild_add_test( TARGET      eckit_test_aiohandle
+                  CONDITION   NOT DEFINED ENV{CRAYOS_VERSION}
+                  SOURCES     test_aiohandle.cc
+                  LIBS        eckit )
+
+ecbuild_add_test( TARGET      eckit_test_localpathname
+                  BOOST
+                  SOURCES     test_localpathname.cc
+                  LIBS        eckit )
+
+
+ecbuild_add_test( TARGET      eckit_test_restarthandle
+                  BOOST
+                  SOURCES     test_restarthandle.cc
+                  LIBS        eckit )
+
+ecbuild_add_test( TARGET      eckit_test_pathexpander
+                  BOOST
+                  SOURCES     test_pathexpander.cc
+                  ENVIRONMENT "CURRENT_TEST_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+                  LIBS        eckit )
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tmp/foo)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdir/foo/1)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdir/foo/2)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdir/foo/2/1)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdir/bar)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdir/baz)
diff --git a/eckit/src/tests/filesystem/test_aiohandle.cc b/eckit/tests/filesystem/test_aiohandle.cc
similarity index 100%
rename from eckit/src/tests/filesystem/test_aiohandle.cc
rename to eckit/tests/filesystem/test_aiohandle.cc
diff --git a/eckit/tests/filesystem/test_localpathname.cc b/eckit/tests/filesystem/test_localpathname.cc
new file mode 100644
index 0000000..38a1119
--- /dev/null
+++ b/eckit/tests/filesystem/test_localpathname.cc
@@ -0,0 +1,256 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_filesystem
+
+#include <string>
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/filesystem/LocalPathName.h"
+#include "eckit/filesystem/FileSystemSize.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace std;
+using namespace eckit;
+using namespace eckit::testing;
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE( TestLocalPathName )
+
+BOOST_AUTO_TEST_CASE( test_constructors )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_constructors");
+
+   LocalPathName p;
+   BOOST_CHECK_MESSAGE(p == "/","Expected '/'");
+
+   LocalPathName p1("/fred/bill");
+   BOOST_CHECK_MESSAGE(p1 == "/fred/bill","Expected '/fred/bill' but found " << p);
+
+   LocalPathName p2(p1);
+   BOOST_CHECK_MESSAGE(p1 == p2,"Expected p1 == p2");
+}
+
+BOOST_AUTO_TEST_CASE( test_assignment )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_assignment");
+
+   LocalPathName p;
+   LocalPathName pd;
+   p = pd;
+   BOOST_CHECK_MESSAGE(p == "/","Expected '/'");
+
+   LocalPathName p1("/fred/bill");
+   LocalPathName p2;
+   p2 = p1;
+   BOOST_CHECK_MESSAGE(p2 == "/fred/bill","Expected '/fred/bill' but found " << p);
+
+   LocalPathName p3;
+   p3 = "/fred";
+   BOOST_CHECK_MESSAGE(p3 == "/fred","Expected '/fred'");
+
+   LocalPathName p4;
+   p4 = std::string("/fredd");
+   BOOST_CHECK_MESSAGE(p4 == "/fredd","Expected '/fredd'");
+}
+
+BOOST_AUTO_TEST_CASE( test_operators )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_operators");
+
+   LocalPathName p;
+
+   p += "fred";
+
+   BOOST_CHECK_MESSAGE(p == "/fred","Expected '/fred'  but found " << p);
+
+   p += "/joe/90";
+
+   BOOST_CHECK_MESSAGE(p == "/fred/joe/90","Expected '/fred/joe/90'  but found " << p);
+
+   p += '/';
+
+   BOOST_CHECK_MESSAGE(p == "/fred/joe/90/","Expected '/fred/joe/90/'  but found " << p);
+}
+
+
+BOOST_AUTO_TEST_CASE( test_dir_name )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_dir_name");
+
+   LocalPathName p("/fred/bill");
+   BOOST_CHECK_MESSAGE(p.dirName() == "/fred","Expected dirName to be '/fred' but found " << p.dirName());
+   BOOST_CHECK_MESSAGE(p.fullName() == "/fred/bill","Expected fullName to be '/fred/bill' but found " << p.fullName());
+
+   // when no leading '/' on pathname, we append cwd to path, for fullName()
+   LocalPathName p2("fred");
+   LocalPathName expected = LocalPathName::cwd() + "/" + "fred";
+   BOOST_CHECK_MESSAGE(p2.fullName() == expected,"Expected " << expected << " but found " << p2.fullName());
+}
+
+BOOST_AUTO_TEST_CASE( test_exists )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_exists");
+
+   LocalPathName cwd = LocalPathName::cwd();
+
+   BOOST_CHECK_MESSAGE(cwd.exists(),"Current working directory must exist");
+   BOOST_CHECK_MESSAGE(cwd.isDir(),"Must be a directory");
+
+   LocalPathName acwd = LocalPathName::cwd();
+   BOOST_CHECK_MESSAGE(cwd.sameAs(acwd),"The directories must be the same");
+
+   BOOST_TEST_MESSAGE("cwd " << cwd);
+   BOOST_TEST_MESSAGE("cwd.mountPoint() " << cwd.mountPoint());
+   BOOST_TEST_MESSAGE("cwd.realName() " << cwd.realName());
+   BOOST_TEST_MESSAGE("cwd.node() " << cwd.node());
+   BOOST_TEST_MESSAGE("cwd.path() " << cwd.path());
+   BOOST_TEST_MESSAGE("size " << cwd.size());
+   BOOST_TEST_MESSAGE("lastAccess " << cwd.lastAccess());
+   BOOST_TEST_MESSAGE("lastModified " << cwd.lastModified());
+   BOOST_TEST_MESSAGE("created " << cwd.created());
+}
+
+BOOST_AUTO_TEST_CASE( test_relative_path )
+{
+    LocalPathName foobar ("/foo/bar/1/2");
+    LocalPathName foozing("/foo/zing/3");
+    LocalPathName baz("/baz/koko/4");
+    LocalPathName root("/");
+
+    // shorter relative to longer
+
+    LocalPathName r1 = foozing.relativePath(foobar);
+
+    BOOST_CHECK_EQUAL( r1 , LocalPathName("../../../zing/3") );
+
+    // longer relative to shorter
+
+    LocalPathName r2 = foobar.relativePath(foozing);
+
+    BOOST_CHECK_EQUAL( r2 , LocalPathName("../../bar/1/2") );
+
+    // same relative to same
+
+    LocalPathName r3 = foobar.relativePath(foobar);
+
+    BOOST_CHECK_EQUAL( r3 , LocalPathName(".") );
+
+    // relative to root
+
+    BOOST_CHECK_EQUAL( foobar.relativePath("/") , LocalPathName("foo/bar/1/2") );
+
+    // root relative to path
+
+    BOOST_CHECK_EQUAL( root.relativePath(foobar) , LocalPathName("../../../..") );
+}
+
+BOOST_AUTO_TEST_CASE( test_children )
+{
+    std::set<LocalPathName> reference;
+    reference.insert("testdir/foo");
+    reference.insert("testdir/foo/1");
+    reference.insert("testdir/foo/2");
+    reference.insert("testdir/foo/2/1");
+    reference.insert("testdir/bar");
+    reference.insert("testdir/baz");
+
+    LocalPathName t = LocalPathName::cwd() + "/testdir";
+
+    std::vector<LocalPathName> files;
+    std::vector<LocalPathName> dirs;
+
+    t.children(files, dirs);
+
+    for(std::vector<LocalPathName>::const_iterator d = dirs.begin(); d != dirs.end(); ++d) {
+        LocalPathName r = d->relativePath(LocalPathName::cwd());
+//        std::cout << "relative path " << r << std::endl;
+        BOOST_CHECK(reference.find(r) != reference.end());
+    }
+}
+
+BOOST_AUTO_TEST_CASE( test_basename )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_basename");
+
+   LocalPathName p1;
+   BOOST_CHECK_MESSAGE(p1.baseName(false) == "","Expected empty string  but found " << p1.baseName(false));
+   BOOST_CHECK_MESSAGE(p1.baseName(true) == "","Expected empty string  but found " << p1.baseName(true));
+
+   LocalPathName p2("fred");
+   BOOST_CHECK_MESSAGE(p2.baseName(false) == "fred","Expected 'fred' but found " << p2.baseName(false));
+   BOOST_CHECK_MESSAGE(p2.baseName(true) == "fred","Expected 'fred' but found " << p2.baseName(true));
+
+   LocalPathName p("/a/made/up/path/that/does/not/exist/file.ok");
+   BOOST_CHECK_MESSAGE(p.baseName(false) == "file","Expected 'file'  but found " << p.baseName(false));
+   BOOST_CHECK_MESSAGE(p.baseName(true) == "file.ok","Expected 'file.ok'  but found " << p.baseName(true));
+}
+
+BOOST_AUTO_TEST_CASE( test_extension )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_extension");
+
+   LocalPathName p1;
+   BOOST_CHECK_MESSAGE(p1.extension() == "", "Expected empty string  but found " << p1.extension());
+
+   LocalPathName p2("fred");
+   BOOST_CHECK_MESSAGE(p2.extension() == "", "Expected empty string  but found " << p2.extension());
+   LocalPathName p3("/path/to/fred");
+   BOOST_CHECK_MESSAGE(p3.extension() == "", "Expected empty string  but found " << p3.extension());
+   LocalPathName p4("/path/with.dot/to/fred");
+   BOOST_CHECK_MESSAGE(p4.extension() == "", "Expected empty string  but found " << p4.extension());
+
+   LocalPathName p5("fred.");
+   BOOST_CHECK_MESSAGE(p5.extension() == ".", "Expected '.'  but found " << p5.extension());
+   LocalPathName p6("/path/to/fred.ext");
+   BOOST_CHECK_MESSAGE(p6.extension() == ".ext", "Expected '.ext'  but found " << p6.extension());
+   LocalPathName p7("/path/with.dot/to/fred.ext");
+   BOOST_CHECK_MESSAGE(p7.extension() == ".ext", "Expected '.ext'  but found " << p7.extension());
+}
+
+BOOST_AUTO_TEST_CASE( test_fileSystemSize )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_fileSystemSize");
+
+   LocalPathName cwd = LocalPathName::cwd();
+   FileSystemSize fs;
+   cwd.fileSystemSize(fs);
+
+   BOOST_TEST_MESSAGE("cwd " << cwd);
+   BOOST_TEST_MESSAGE("fs.available " << fs.available);
+   BOOST_TEST_MESSAGE("fs.total " << fs.total);
+
+   BOOST_CHECK_MESSAGE(fs.available > 0,"Expected file system available  > 0 ");
+   BOOST_CHECK_MESSAGE(fs.total > 0,"Expected file system total  > 0 ");
+}
+
+BOOST_AUTO_TEST_CASE( test_unique )
+{
+   BOOST_TEST_MESSAGE("eckit::filesystem:: ...test_unique");
+
+   LocalPathName unique = LocalPathName::unique(LocalPathName::cwd());
+
+   unique.mkdir();
+
+   BOOST_CHECK_MESSAGE(unique.exists(),"Expected '" << unique << "' to exist ");
+
+   unique.rmdir();
+   BOOST_CHECK_MESSAGE(!unique.exists(),"Expected '" << unique << "' to be removed ");
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/filesystem/test_multihandle.cc b/eckit/tests/filesystem/test_multihandle.cc
similarity index 100%
rename from eckit/src/tests/filesystem/test_multihandle.cc
rename to eckit/tests/filesystem/test_multihandle.cc
diff --git a/eckit/tests/filesystem/test_pathexpander.cc b/eckit/tests/filesystem/test_pathexpander.cc
new file mode 100644
index 0000000..c84ac8b
--- /dev/null
+++ b/eckit/tests/filesystem/test_pathexpander.cc
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_pathexpander
+
+#include <string>
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/exception/Exceptions.h"
+#include "eckit/filesystem/LocalPathName.h"
+#include "eckit/filesystem/PathExpander.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace std;
+using namespace eckit;
+using namespace eckit::testing;
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE( TestPathExpander )
+
+BOOST_AUTO_TEST_CASE( test_expands )
+{
+    std::string s = "{CWD}/tmp/foo";
+    std::string r = std::string(::getenv("CURRENT_TEST_DIR")) + std::string("/tmp/foo");
+
+    LocalPathName ps = LocalPathName(PathExpander::expand("CWD", s)).realName();
+    LocalPathName pr = LocalPathName(r).realName();
+
+    BOOST_CHECK_EQUAL(ps.c_str(), pr.c_str());
+}
+
+BOOST_AUTO_TEST_CASE( test_missing_keys )
+{
+    std::string s = "{FOO}/tmp/foo";
+
+    BOOST_CHECK_THROW( PathExpander::expand("FOO", s), eckit::UserError );
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/filesystem/test_restarthandle.cc b/eckit/tests/filesystem/test_restarthandle.cc
similarity index 100%
rename from eckit/src/tests/filesystem/test_restarthandle.cc
rename to eckit/tests/filesystem/test_restarthandle.cc
diff --git a/eckit/src/tests/geometry/CMakeLists.txt b/eckit/tests/geometry/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/geometry/CMakeLists.txt
rename to eckit/tests/geometry/CMakeLists.txt
diff --git a/eckit/src/tests/geometry/test_kdtree.cc b/eckit/tests/geometry/test_kdtree.cc
similarity index 100%
rename from eckit/src/tests/geometry/test_kdtree.cc
rename to eckit/tests/geometry/test_kdtree.cc
diff --git a/eckit/src/tests/io/CMakeLists.txt b/eckit/tests/io/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/io/CMakeLists.txt
rename to eckit/tests/io/CMakeLists.txt
diff --git a/eckit/src/tests/io/test_datablob.cc b/eckit/tests/io/test_datablob.cc
similarity index 100%
rename from eckit/src/tests/io/test_datablob.cc
rename to eckit/tests/io/test_datablob.cc
diff --git a/eckit/src/tests/io/test_filepool.cc b/eckit/tests/io/test_filepool.cc
similarity index 100%
rename from eckit/src/tests/io/test_filepool.cc
rename to eckit/tests/io/test_filepool.cc
diff --git a/eckit/src/tests/large_file/CMakeLists.txt b/eckit/tests/large_file/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/large_file/CMakeLists.txt
rename to eckit/tests/large_file/CMakeLists.txt
diff --git a/eckit/src/tests/large_file/test_large_file.cc b/eckit/tests/large_file/test_large_file.cc
similarity index 100%
rename from eckit/src/tests/large_file/test_large_file.cc
rename to eckit/tests/large_file/test_large_file.cc
diff --git a/eckit/src/tests/linalg/CMakeLists.txt b/eckit/tests/linalg/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/linalg/CMakeLists.txt
rename to eckit/tests/linalg/CMakeLists.txt
diff --git a/eckit/src/tests/linalg/test_la_factory.cc b/eckit/tests/linalg/test_la_factory.cc
similarity index 100%
rename from eckit/src/tests/linalg/test_la_factory.cc
rename to eckit/tests/linalg/test_la_factory.cc
diff --git a/eckit/src/tests/linalg/test_la_linalg.cc b/eckit/tests/linalg/test_la_linalg.cc
similarity index 100%
rename from eckit/src/tests/linalg/test_la_linalg.cc
rename to eckit/tests/linalg/test_la_linalg.cc
diff --git a/eckit/src/tests/linalg/test_la_sparse.cc b/eckit/tests/linalg/test_la_sparse.cc
similarity index 100%
rename from eckit/src/tests/linalg/test_la_sparse.cc
rename to eckit/tests/linalg/test_la_sparse.cc
diff --git a/eckit/src/tests/linalg/test_la_streaming.cc b/eckit/tests/linalg/test_la_streaming.cc
similarity index 100%
rename from eckit/src/tests/linalg/test_la_streaming.cc
rename to eckit/tests/linalg/test_la_streaming.cc
diff --git a/eckit/src/tests/linalg/util.h b/eckit/tests/linalg/util.h
similarity index 100%
rename from eckit/src/tests/linalg/util.h
rename to eckit/tests/linalg/util.h
diff --git a/eckit/src/tests/log/CMakeLists.txt b/eckit/tests/log/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/log/CMakeLists.txt
rename to eckit/tests/log/CMakeLists.txt
diff --git a/eckit/src/tests/log/test_colour.cc b/eckit/tests/log/test_colour.cc
similarity index 100%
rename from eckit/src/tests/log/test_colour.cc
rename to eckit/tests/log/test_colour.cc
diff --git a/eckit/src/tests/log/test_log.cc b/eckit/tests/log/test_log.cc
similarity index 100%
rename from eckit/src/tests/log/test_log.cc
rename to eckit/tests/log/test_log.cc
diff --git a/eckit/src/tests/log/test_log_callback.cc b/eckit/tests/log/test_log_callback.cc
similarity index 100%
rename from eckit/src/tests/log/test_log_callback.cc
rename to eckit/tests/log/test_log_callback.cc
diff --git a/eckit/tests/log/test_log_channels.cc b/eckit/tests/log/test_log_channels.cc
new file mode 100644
index 0000000..1d16326
--- /dev/null
+++ b/eckit/tests/log/test_log_channels.cc
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <csignal>
+#include <cstdlib>
+#include <vector>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <locale>
+#include <fstream>
+#include <cassert>
+
+#include "eckit/config/LibEcKit.h"
+#include "eckit/os/BackTrace.h"
+#include "eckit/runtime/Tool.h"
+#include "eckit/filesystem/LocalPathName.h"
+
+#include "eckit/log/Channel.h"
+#include "eckit/log/ColouringTarget.h"
+#include "eckit/log/FileTarget.h"
+#include "eckit/log/CallbackTarget.h"
+#include "eckit/log/WrapperTarget.h"
+#include "eckit/log/OStreamTarget.h"
+
+using namespace std;
+using namespace eckit;
+
+
+#if 1
+    #define DEBUG_H
+    #define DEBUG_(x)
+#else
+    #define DEBUG_H     std::cerr << " DEBUG @ " << __FILE__ << " +" << __LINE__ << std::endl;
+    #define DEBUG_(x)   std::cerr << #x << " : [" << x << "] @ " <<  __FILE__ << " +" << __LINE__ << std::endl;
+#endif
+
+namespace eckit_test {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+/// Example of a wrapper target that capitalizes all output
+
+class CapitalizerTarget : public WrapperTarget {
+public:
+
+    CapitalizerTarget(LogTarget* target) : WrapperTarget(target) {}
+
+private:
+
+    virtual void write(const char* start, const char* end) {
+
+        std::string::size_type length = std::distance(start, end);
+        buffer_.resize(length);
+
+        std::locale loc;
+        const char* p = start;
+        for (std::string::size_type i = 0; i< length; ++i, ++p) {
+          buffer_[i] = std::toupper(*p,loc);
+        }
+
+        target_->write(buffer_.c_str(), buffer_.c_str() + length);
+    }
+
+    virtual void writePrefix(){}
+    virtual void writeSuffix(){}
+
+    void print(std::ostream& s) const { s << "CapitalizerTarget()"; }
+
+    std::string buffer_;
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+static void callback_ctxt( void* ctxt, const char* msg )
+{
+    std::cout << "[" << *((int*)ctxt) << "] : -- " << msg << std::endl ;
+}
+
+static void callback_noctxt( void* , const char* msg )
+{
+    std::cout << "[CALLBACK OUT] : -- " << msg << std::endl ;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class TestApp : public Tool {
+public:
+
+    TestApp(int argc,char **argv) : Tool(argc,argv) {}
+
+    ~TestApp() {}
+
+    virtual void run()
+    {
+        test_multi_targets();
+        test_multi_colouring();
+    }
+
+    void test_multi_targets() {
+        std::cout << "---> test_multi_targets()" << std::endl;
+
+        int t = 0;
+
+        Channel mychannel;
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        mychannel.addFile("test.txt");
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        std::ofstream of ("test.txt.2");
+        mychannel.addStream(of);
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        mychannel.addStream(std::cout);
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        mychannel.addStream(std::cerr);
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        std::ostringstream oss;
+        mychannel.addStream(oss);
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        mychannel.addCallback(&callback_noctxt,0);
+        mychannel.addCallback(&callback_ctxt, &t);
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        // mychannel.addLogTarget(new CapitalizerTarget(new FileTarget(PathName("capitals.txt"))));
+
+        mychannel << "testing [" << t++ << "]" << std::endl;
+
+        mychannel << "Final test" << std::endl;
+    }
+
+    void test_multi_colouring() {
+#if 0
+        Log::info().setLogTarget(    new ColouringTarget(new OStreamTarget(std::cout), &Colour::green));
+        Log::warning().setLogTarget( new ColouringTarget(new OStreamTarget(std::cerr), &Colour::yellow));
+        Log::error().setLogTarget(   new ColouringTarget(new OStreamTarget(std::cerr), &Colour::red));
+
+        Log::info()    << "Log::info() is green"     << std::endl;
+        Log::warning() << "Log::warning() is yellow" << std::endl;
+        Log::error()   << "Log::error() is red"      << std::endl;
+#endif
+    }
+};
+
+} // namespace eckit_test
+
+//----------------------------------------------------------------------------------------------------------------------
+
+void on_signal_dumpbacktrace(int signum)
+{
+    printf("Caught signal %d\n",signum);
+    std::cerr << BackTrace::dump() << std::endl;
+    eckit::LibEcKit::instance().abort();
+}
+
+int main(int argc,char **argv)
+{
+    signal(SIGSEGV, on_signal_dumpbacktrace );
+
+    eckit_test::TestApp app(argc,argv);
+    return app.start();
+}
+
diff --git a/eckit/src/tests/log/test_log_threads.cc b/eckit/tests/log/test_log_threads.cc
similarity index 100%
rename from eckit/src/tests/log/test_log_threads.cc
rename to eckit/tests/log/test_log_threads.cc
diff --git a/eckit/src/tests/log/test_log_user_channels.cc b/eckit/tests/log/test_log_user_channels.cc
similarity index 100%
rename from eckit/src/tests/log/test_log_user_channels.cc
rename to eckit/tests/log/test_log_user_channels.cc
diff --git a/eckit/src/tests/maths/CMakeLists.txt b/eckit/tests/maths/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/maths/CMakeLists.txt
rename to eckit/tests/maths/CMakeLists.txt
diff --git a/eckit/src/tests/maths/test_eigen.cc b/eckit/tests/maths/test_eigen.cc
similarity index 100%
rename from eckit/src/tests/maths/test_eigen.cc
rename to eckit/tests/maths/test_eigen.cc
diff --git a/eckit/src/tests/maths/test_matrix.cc b/eckit/tests/maths/test_matrix.cc
similarity index 100%
rename from eckit/src/tests/maths/test_matrix.cc
rename to eckit/tests/maths/test_matrix.cc
diff --git a/eckit/src/tests/memory/CMakeLists.txt b/eckit/tests/memory/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/memory/CMakeLists.txt
rename to eckit/tests/memory/CMakeLists.txt
diff --git a/eckit/src/tests/memory/test_counted.cc b/eckit/tests/memory/test_counted.cc
similarity index 100%
rename from eckit/src/tests/memory/test_counted.cc
rename to eckit/tests/memory/test_counted.cc
diff --git a/eckit/src/tests/memory/test_factory.cc b/eckit/tests/memory/test_factory.cc
similarity index 100%
rename from eckit/src/tests/memory/test_factory.cc
rename to eckit/tests/memory/test_factory.cc
diff --git a/eckit/src/tests/memory/test_scoped_ptr.cc b/eckit/tests/memory/test_scoped_ptr.cc
similarity index 100%
rename from eckit/src/tests/memory/test_scoped_ptr.cc
rename to eckit/tests/memory/test_scoped_ptr.cc
diff --git a/eckit/src/tests/memory/test_shared_ptr.cc b/eckit/tests/memory/test_shared_ptr.cc
similarity index 100%
rename from eckit/src/tests/memory/test_shared_ptr.cc
rename to eckit/tests/memory/test_shared_ptr.cc
diff --git a/eckit/src/tests/memory_map/CMakeLists.txt b/eckit/tests/memory_map/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/memory_map/CMakeLists.txt
rename to eckit/tests/memory_map/CMakeLists.txt
diff --git a/eckit/src/tests/memory_map/test_memory_map.cc b/eckit/tests/memory_map/test_memory_map.cc
similarity index 100%
rename from eckit/src/tests/memory_map/test_memory_map.cc
rename to eckit/tests/memory_map/test_memory_map.cc
diff --git a/eckit/src/tests/mpi/CMakeLists.txt b/eckit/tests/mpi/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/mpi/CMakeLists.txt
rename to eckit/tests/mpi/CMakeLists.txt
diff --git a/eckit/tests/mpi/eckit_test_mpi.cc b/eckit/tests/mpi/eckit_test_mpi.cc
new file mode 100644
index 0000000..a9dffac
--- /dev/null
+++ b/eckit/tests/mpi/eckit_test_mpi.cc
@@ -0,0 +1,575 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "eckit/log/Log.h"
+#include "eckit/types/Types.h"
+#include "eckit/mpi/Comm.h"
+#include "eckit/filesystem/LocalPathName.h"
+
+#define BOOST_TEST_MODULE eckit_test_mpi
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/testing/CommSetup.h"
+
+//----------------------------------------------------------------------------------------------------------------------
+
+// Teach boost how to write a std::vector<T>
+namespace boost {
+
+template <typename T>
+inline boost::wrap_stringstream& operator<<(boost::wrap_stringstream& wrapped, std::vector<T> const& v)
+{
+    wrapped << '[';
+    for (int j=0; j<v.size(); ++j) {
+        wrapped << (j!=0 ? "," : "") << v[j];
+    }
+    return wrapped << ']';
+}
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+using namespace eckit;
+using namespace eckit::testing;
+
+BOOST_GLOBAL_FIXTURE( CommSetup );
+
+BOOST_AUTO_TEST_CASE( test_rank_size )
+{
+    BOOST_CHECK_NO_THROW( mpi::comm().size() );
+    BOOST_CHECK_NO_THROW( mpi::comm().rank() );
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_broadcast )
+{
+  size_t root = 0;
+
+  int d[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+  BOOST_TEST_CHECKPOINT("Test value");
+  {
+    float val;
+    if( mpi::comm().rank() == root ) {
+      val = 3.14f;
+    }
+
+    float* pval = &val;
+    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(val, root) );
+    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(pval, pval+1, root) );
+
+    // check results
+    BOOST_CHECK_CLOSE( val, 3.14f, 0.0001 );
+  }
+
+  BOOST_TEST_CHECKPOINT("Test vector");
+  {
+    std::vector<int> data(10);
+    if(mpi::comm().rank() == root) {
+      data.assign(d,d+10);
+    }
+    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(data, root) );
+
+    // check results
+    BOOST_CHECK_EQUAL( data.size(), 10u );
+    BOOST_CHECK_EQUAL_COLLECTIONS(data.begin(),data.end(),d,d+10);
+  }
+
+  BOOST_TEST_CHECKPOINT("Test raw data");
+  {
+    std::vector<int> data(10);
+    if( mpi::comm().rank() == root )
+    {
+      data.assign(d,d+10);
+    }
+
+    BOOST_CHECK_NO_THROW( mpi::comm().broadcast(data.begin(), data.end(), root) );
+
+    // check results
+    BOOST_CHECK_EQUAL_COLLECTIONS(data.begin(), data.end(), d, d+10);
+  }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_gather_scalar )
+{
+    size_t size = mpi::comm().size();
+    size_t rank = mpi::comm().rank();
+
+    std::vector<size_t> recv(size);
+
+    size_t send = 777 + rank;
+
+    size_t root = 0; /* master */
+
+    BOOST_CHECK_NO_THROW( mpi::comm().gather(send, recv, root) );
+
+    if(rank == root) {
+        std::vector<size_t> expected(size);
+        for(size_t j = 0; j < recv.size(); ++j) {
+            expected[j] = 777 + j;
+        }
+
+        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+    }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_gather_nscalars )
+{
+    for(size_t N = 1; N < 10; ++N) {
+
+        size_t size = mpi::comm().size();
+        size_t rank = mpi::comm().rank();
+
+        std::vector<long> recv(size*N);
+
+        std::vector<long> send(N);
+        for(size_t n = 0; n < N; ++n) {
+            send[n] = long(rank*2 + n + 1);
+        }
+
+        std::vector<long> expected(size*N);
+        for(size_t j = 0; j < size; ++j) {
+            for(size_t n = 0; n < N; ++n) {
+                expected[j*N+n] = long(j*2 + n + 1);
+            }
+        }
+
+        size_t root = 0; /* master */
+
+        BOOST_CHECK_NO_THROW( mpi::comm().gather(send, recv, root) );
+
+        if(rank == root) {
+            BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+        }
+
+        std::vector<long> recv2(size*N);
+
+        BOOST_CHECK_NO_THROW( mpi::comm().gather(send.begin(), send.end(), recv2.begin(), recv2.end(), root) );
+
+        if(rank == root) {
+            BOOST_CHECK_EQUAL_COLLECTIONS(recv2.begin(), recv2.end(), expected.begin(), expected.end());
+        }
+    }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_gatherv_equal_stride )
+{
+    size_t root = 0;
+    size_t size = mpi::comm().size();
+    size_t rank = mpi::comm().rank();
+
+    size_t stride = 100;
+
+    std::vector<long> send(stride);
+
+    for(size_t i = 0; i < stride; ++i) {
+        send[i] = long(rank * i);
+    }
+
+    std::vector<long> recv(size * stride);
+
+    std::vector<int> displs(size);
+    std::vector<int> recvcounts(size);
+
+    for(size_t i = 0; i < size; ++i) {
+        displs[i]     = int(i*stride);
+        recvcounts[i] = int(stride);
+    }
+
+    BOOST_CHECK_NO_THROW( mpi::comm().gatherv(send, recv, recvcounts, displs, root) );
+
+    std::vector<long> expected(size * stride);
+    for(size_t i = 0; i < size; ++i) {
+        for(size_t j = 0; j < stride; ++j) {
+            expected[i*stride + j] = long(i*j);
+        }
+    }
+
+    if(rank == root) {
+        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+    }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_gatherv_unequal_stride )
+{
+    size_t root = 0;
+    size_t size = mpi::comm().size();
+    size_t rank = mpi::comm().rank();
+
+    size_t stride = 10 * rank;
+
+    std::vector<long> send(stride);
+
+    for(size_t i = 0; i < stride; ++i) {
+        send[i] = long(rank * i);
+    }
+
+    std::vector<int> displs(size);
+    std::vector<int> recvcounts(size);
+
+    for(size_t i = 0; i < size; ++i) {
+        displs[i]     = int( i ? displs[i-1] + stride : 0 );
+        recvcounts[i] = int(stride);
+    }
+
+    size_t recvsize = size_t( std::accumulate(recvcounts.begin(), recvcounts.end(), 0) );
+
+    std::vector<long> recv(recvsize);
+
+    BOOST_CHECK_NO_THROW( mpi::comm().gatherv(send, recv, recvcounts, displs, root) );
+
+    size_t e = 0;
+    std::vector<long> expected(recvsize);
+    for(size_t i = 0; i < size; ++i) {
+        for(size_t j = 0; j < stride; ++j, ++e) {
+            expected[e] = long(i*j);
+        }
+    }
+
+    if(rank == root) {
+        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+    }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_scatter_scalar )
+{
+    size_t size = mpi::comm().size();
+    std::vector<long> send(size);
+    for(size_t j = 0; j < send.size(); ++j) {
+            send[j] = long(j*j) - 1;
+    }
+
+    long recv = -999;
+
+    size_t root = 0; /* master */
+
+    BOOST_CHECK_NO_THROW( mpi::comm().scatter(send, recv, root) );
+
+    size_t rank = mpi::comm().rank();
+
+    BOOST_CHECK_EQUAL(recv, rank*rank - 1);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_scatter_nscalars )
+{
+    for(size_t N = 1; N < 4; ++N) {
+
+        size_t size = mpi::comm().size();
+        std::vector<long> send(size*N);
+        for(size_t j = 0; j < send.size() / N; ++j) {
+            for(size_t n = 0; n < N; ++n) {
+                send[j*N+n] = long(j*j - n);
+            }
+        }
+
+        std::vector<long> recv(N);
+
+        size_t root = 0; /* master */
+
+        BOOST_CHECK_NO_THROW( mpi::comm().scatter(send, recv, root) );
+
+        size_t rank = mpi::comm().rank();
+
+        // check results
+        std::vector<long> expected (N);
+        for(size_t n = 0; n < N; ++n) {
+            expected[n] = long(rank*rank - n);
+        }
+
+        BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+    }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_scatterv )
+{
+     /// TODO
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_allReduce )
+{
+  int d = int(mpi::comm().rank()) + 1;
+
+  std::pair<double,int> v(-d, mpi::comm().rank());
+  std::cout << "v : " << v << std::endl;
+  std::cout << std::flush;
+  mpi::comm().barrier();
+
+  // check results
+  int s=0;
+  int p=1;
+  for( size_t j=0; j<mpi::comm().size(); ++j ) {
+    s += (j+1);
+    p *= (j+1);
+  }
+
+  BOOST_TEST_CHECKPOINT("Testing all_reduce");
+  {
+    int sum;
+    int prod;
+    int max;
+    int min;
+
+    std::pair<double,int> maxloc;
+    std::pair<double,int> minloc;
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, sum,    mpi::sum())   );
+
+    BOOST_CHECK_EQUAL( sum, s );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, prod,   mpi::prod()) );
+
+    BOOST_CHECK_EQUAL( prod, p );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, max,    mpi::max())   );
+
+    BOOST_CHECK_EQUAL( size_t(max), mpi::comm().size() );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(d, min,    mpi::min())   );
+
+    BOOST_CHECK_EQUAL( min, 1 );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(v, maxloc, mpi::maxloc())   );
+
+    BOOST_CHECK_EQUAL( maxloc.first, -double(1) );
+    BOOST_CHECK_EQUAL( maxloc.second, 0 );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduce(v, minloc, mpi::minloc())   );
+
+    BOOST_CHECK_EQUAL( minloc.first, -double(mpi::comm().size()) );
+    BOOST_CHECK_EQUAL( size_t(minloc.second), mpi::comm().size()-1 );
+  }
+
+  std::vector<float> arr(5, mpi::comm().rank()+1);
+  std::cout << "arr : " << arr << std::endl;
+
+  std::cout << std::flush;
+  mpi::comm().barrier();
+
+  BOOST_TEST_CHECKPOINT("Testing all_reduce inplace");
+  {
+    int sum = d;
+    int prod = d;
+    int max = d;
+    int min = d;
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(sum, mpi::sum())   );
+    BOOST_CHECK_EQUAL( sum, s );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(prod, mpi::prod()) );
+    BOOST_CHECK_EQUAL( prod, p );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(max, mpi::max())   );
+    BOOST_CHECK_EQUAL( size_t(max), mpi::comm().size() );
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(min, mpi::min())   );
+    BOOST_CHECK_EQUAL( min, 1 );
+
+    std::vector<float> expected;
+
+    expected = std::vector<float>(5, mpi::comm().size());
+    std::vector<float> maxvec = arr;
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(maxvec.begin(), maxvec.end(), mpi::max()) );
+    BOOST_CHECK_EQUAL_COLLECTIONS(maxvec.begin(),maxvec.end(),expected.begin(),expected.end());
+
+    expected = std::vector<float>(5,1);
+    std::vector<float> minvec = arr;
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(minvec.begin(),minvec.end(), mpi::min()) );
+    BOOST_CHECK_EQUAL_COLLECTIONS(minvec.begin(),minvec.end(),expected.begin(),expected.end());
+
+    expected = std::vector<float>(5,s);
+    std::vector<float> sumvec = arr;
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(sumvec.begin(),sumvec.end(), mpi::sum()) );
+    BOOST_CHECK_EQUAL_COLLECTIONS(sumvec.begin(),sumvec.end(),expected.begin(),expected.end());
+
+    expected = std::vector<float>(5,p);
+    std::vector<float> prodvec = arr;
+    BOOST_CHECK_NO_THROW( mpi::comm().allReduceInPlace(prodvec.begin(),prodvec.end(), mpi::prod()) );
+    BOOST_CHECK_EQUAL_COLLECTIONS(prodvec.begin(),prodvec.end(),expected.begin(),expected.end());
+  }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_allGather )
+{
+    // Scalar
+
+    int send = mpi::comm().rank();
+    std::vector<int> recv(mpi::comm().size());
+
+    BOOST_CHECK_NO_THROW( mpi::comm().allGather(send, recv.begin(), recv.end()) );
+
+    std::vector<int> expected(mpi::comm().size());
+    for(size_t j = 0; j < expected.size(); ++j) {
+        expected[j] = int(j);
+    }
+
+    BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_allGatherv )
+{
+  std::vector<int> send(mpi::comm().rank(), mpi::comm().rank());
+  mpi::Buffer<int> recv(mpi::comm().size());
+
+  BOOST_CHECK_NO_THROW( mpi::comm().allGatherv(send.begin(), send.end(), recv) );
+
+  // check results
+  std::vector<int> expected;
+  for(size_t j=0; j<mpi::comm().size(); ++j )
+  {
+    for( size_t i=0; i<j; ++i )
+      expected.push_back(j);
+  }
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(recv.begin(), recv.end(), expected.begin(), expected.end());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_allToAll )
+{
+  std::vector< std::vector<int> > send(mpi::comm().size(), std::vector<int>(1, mpi::comm().rank()));
+  std::vector< std::vector<int> > recv(mpi::comm().size());
+
+  BOOST_CHECK_NO_THROW( mpi::comm().allToAll(send, recv) );
+
+  // check results
+  std::vector< std::vector<int> > expected(mpi::comm().size());
+  for(size_t j=0; j<mpi::comm().size(); ++j) {
+    expected[j] = std::vector<int>(1,int(j));
+  }
+
+  BOOST_CHECK_EQUAL(recv.size(), expected.size());
+  for (size_t i = 0; i < mpi::comm().size(); ++i) {
+      BOOST_CHECK_EQUAL_COLLECTIONS(recv[i].begin(), recv[i].end(), expected[i].begin(), expected[i].end());
+  }
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_nonblocking_send_receive )
+{
+  mpi::Comm& comm = mpi::comm("world");
+  int tag = 99;
+  mpi::Request sendreq;
+  mpi::Request recvreq;
+  double send;
+  double recv = 1.;
+
+  // Post a receive request
+  if( comm.rank() == comm.size()-1 ) {
+    recvreq = comm.iReceive(recv,0,tag);
+  }
+
+  // Post a send request
+  if( comm.rank() == 0 ) {
+    send = 0.5;
+    sendreq = comm.iSend(send,comm.size()-1,tag);
+  }
+
+  // Wait for receiving to finish
+  if( comm.rank() == comm.size()-1 ) {
+    mpi::Status recvstatus = comm.wait(recvreq);
+    BOOST_CHECK_CLOSE(recv,0.5,1.e-9);
+  }
+  else {
+    BOOST_CHECK_CLOSE(recv,1.,1.e-9);
+  }
+
+  // Wait for sending to finish
+  if( comm.rank() == 0 ) {
+    mpi::Status sendstatus = comm.wait(sendreq);
+  }
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_blocking_send_receive )
+{
+  mpi::Comm& comm = mpi::comm("world");
+  int tag = 99;
+  double send1, send2;
+  double recv1 = 1.;
+  double recv2 = 1.;
+
+  // Send1
+  if( comm.rank() == 0 ) {
+    send1 = 0.1;
+    comm.send(send1,comm.size()-1,tag);
+    send1 = 0.; // should not matter, as send() copies to internal mpi buffer
+  }
+
+  // Send2
+  if( comm.rank() == 0 ) {
+    send2 = 0.2;
+    comm.send(send2,comm.size()-1,tag);
+  }
+
+  // Receive1
+  if( comm.rank() == comm.size()-1 ) {
+    mpi::Status status = comm.receive(recv1,0,tag);
+    BOOST_CHECK_CLOSE(recv1,0.1,1.e-9);
+  }
+
+  // Receive2
+  if( comm.rank() == comm.size()-1 ) {
+    mpi::Status status = comm.receive(recv2,0,tag);
+    BOOST_CHECK_CLOSE(recv2,0.2,1.e-9);
+  }
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_broadcastFile )
+{
+  mpi::Comm& comm = mpi::comm("world");
+  int root = 0;
+
+  std::string str = "Hello World!\n";
+  LocalPathName path("test_mpi_broadcastFile.txt");
+  if ( comm.rank() == root )
+  {
+    std::ofstream file( path.c_str(), std::ios_base::out );
+    file << str;
+    file.close();
+  }
+
+  BOOST_CHECK_EQUAL( comm.broadcastFile(path, root).str(), str );
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_allToAllv )
+{
+    // TODO
+}
diff --git a/eckit/tests/mpi/eckit_test_mpi_addcomm.cc b/eckit/tests/mpi/eckit_test_mpi_addcomm.cc
new file mode 100644
index 0000000..2e7fa18
--- /dev/null
+++ b/eckit/tests/mpi/eckit_test_mpi_addcomm.cc
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define OMPI_SKIP_MPICXX 1
+#define MPICH_SKIP_MPICXX 1
+
+#include <mpi.h>
+
+#include "eckit/mpi/Comm.h"
+
+int main( int argc, char** argv )
+{
+    MPI_Init(&argc, &argv);
+
+    MPI_Fint fortranComm = MPI_Comm_c2f(MPI_COMM_WORLD);
+
+    eckit::mpi::addComm("fort.1", fortranComm);
+
+    eckit::mpi::setCommDefault("fort.1");
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/eckit/src/tests/option/CMakeLists.txt b/eckit/tests/option/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/option/CMakeLists.txt
rename to eckit/tests/option/CMakeLists.txt
diff --git a/eckit/src/tests/option/eckit_test_option_cmdargs.cc b/eckit/tests/option/eckit_test_option_cmdargs.cc
similarity index 100%
rename from eckit/src/tests/option/eckit_test_option_cmdargs.cc
rename to eckit/tests/option/eckit_test_option_cmdargs.cc
diff --git a/eckit/src/tests/option/eckit_test_option_factory.cc b/eckit/tests/option/eckit_test_option_factory.cc
similarity index 100%
rename from eckit/src/tests/option/eckit_test_option_factory.cc
rename to eckit/tests/option/eckit_test_option_factory.cc
diff --git a/eckit/tests/parser/2.1.yaml b/eckit/tests/parser/2.1.yaml
new file mode 100644
index 0000000..d12e671
--- /dev/null
+++ b/eckit/tests/parser/2.1.yaml
@@ -0,0 +1,3 @@
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
diff --git a/eckit/tests/parser/2.10.yaml b/eckit/tests/parser/2.10.yaml
new file mode 100644
index 0000000..61808f6
--- /dev/null
+++ b/eckit/tests/parser/2.10.yaml
@@ -0,0 +1,8 @@
+---
+hr:
+  - Mark McGwire
+  # Following node labeled SS
+  - &SS Sammy Sosa
+rbi:
+  - *SS # Subsequent occurrence
+  - Ken Griffey
diff --git a/eckit/tests/parser/2.11.yaml b/eckit/tests/parser/2.11.yaml
new file mode 100644
index 0000000..9123ce2
--- /dev/null
+++ b/eckit/tests/parser/2.11.yaml
@@ -0,0 +1,9 @@
+? - Detroit Tigers
+  - Chicago cubs
+:
+  - 2001-07-23
+
+? [ New York Yankees,
+    Atlanta Braves ]
+: [ 2001-07-02, 2001-08-12,
+    2001-08-14 ]
diff --git a/eckit/tests/parser/2.12.yaml b/eckit/tests/parser/2.12.yaml
new file mode 100644
index 0000000..683a3d0
--- /dev/null
+++ b/eckit/tests/parser/2.12.yaml
@@ -0,0 +1,9 @@
+---
+# products purchased
+- item    : Super Hoop
+  quantity: 1
+- item    : Basketball
+  quantity: 4
+- item    : Big Shoes
+  quantity: 1
+
diff --git a/eckit/tests/parser/2.13.yaml b/eckit/tests/parser/2.13.yaml
new file mode 100644
index 0000000..13fb656
--- /dev/null
+++ b/eckit/tests/parser/2.13.yaml
@@ -0,0 +1,4 @@
+# ASCII Art
+--- |
+  \//||\/||
+  // ||  ||__
diff --git a/eckit/tests/parser/2.14.yaml b/eckit/tests/parser/2.14.yaml
new file mode 100644
index 0000000..59943de
--- /dev/null
+++ b/eckit/tests/parser/2.14.yaml
@@ -0,0 +1,4 @@
+---
+  Mark McGwire's
+  year was crippled
+  by a knee injury.
diff --git a/eckit/tests/parser/2.15.yaml b/eckit/tests/parser/2.15.yaml
new file mode 100644
index 0000000..80b89a6
--- /dev/null
+++ b/eckit/tests/parser/2.15.yaml
@@ -0,0 +1,8 @@
+>
+ Sammy Sosa completed another
+ fine season with great stats.
+
+   63 Home Runs
+   0.288 Batting Average
+
+ What a year!
diff --git a/eckit/tests/parser/2.16.yaml b/eckit/tests/parser/2.16.yaml
new file mode 100644
index 0000000..223ec81
--- /dev/null
+++ b/eckit/tests/parser/2.16.yaml
@@ -0,0 +1,8 @@
+name: Mark McGwire
+accomplishment: >
+  Mark set a major league
+  home run record in 1998.
+stats: |
+  65 Home Runs
+  0.278 Batting Average
+
diff --git a/eckit/tests/parser/2.17.yaml b/eckit/tests/parser/2.17.yaml
new file mode 100644
index 0000000..b2870c5
--- /dev/null
+++ b/eckit/tests/parser/2.17.yaml
@@ -0,0 +1,7 @@
+unicode: "Sosa did fine.\u263A"
+control: "\b1998\t1999\t2000\n"
+hexesc:  "\x13\x10 is \r\n"
+
+single: '"Howdy!" he cried.'
+quoted: ' # not a ''comment''.'
+tie-fighter: '|\-*-/|'
diff --git a/eckit/tests/parser/2.18.yaml b/eckit/tests/parser/2.18.yaml
new file mode 100644
index 0000000..0f49d9c
--- /dev/null
+++ b/eckit/tests/parser/2.18.yaml
@@ -0,0 +1,7 @@
+plain:
+  This unquoted scalar
+  spans many lines.
+
+quoted: "So does this
+  quoted scalar.\n"
+
diff --git a/eckit/tests/parser/2.19.yaml b/eckit/tests/parser/2.19.yaml
new file mode 100644
index 0000000..bf69de6
--- /dev/null
+++ b/eckit/tests/parser/2.19.yaml
@@ -0,0 +1,5 @@
+canonical: 12345
+decimal: +12,345
+sexagesimal: 3:25:45
+octal: 014
+hexadecimal: 0xC
diff --git a/eckit/tests/parser/2.2.yaml b/eckit/tests/parser/2.2.yaml
new file mode 100644
index 0000000..7b7ec94
--- /dev/null
+++ b/eckit/tests/parser/2.2.yaml
@@ -0,0 +1,3 @@
+hr:  65    # Home runs
+avg: 0.278 # Batting average
+rbi: 147   # Runs Batted In
diff --git a/eckit/tests/parser/2.20.yaml b/eckit/tests/parser/2.20.yaml
new file mode 100644
index 0000000..1d4897f
--- /dev/null
+++ b/eckit/tests/parser/2.20.yaml
@@ -0,0 +1,6 @@
+canonical: 1.23015e+3
+exponential: 12.3015e+02
+sexagesimal: 20:30.15
+fixed: 1,230.15
+negative infinity: -.inf
+not a number: .NaN
diff --git a/eckit/tests/parser/2.21.yaml b/eckit/tests/parser/2.21.yaml
new file mode 100644
index 0000000..dec6a56
--- /dev/null
+++ b/eckit/tests/parser/2.21.yaml
@@ -0,0 +1,4 @@
+null: ~
+true: y
+false: n
+string: '12345'
diff --git a/eckit/tests/parser/2.22.yaml b/eckit/tests/parser/2.22.yaml
new file mode 100644
index 0000000..aaac185
--- /dev/null
+++ b/eckit/tests/parser/2.22.yaml
@@ -0,0 +1,4 @@
+canonical: 2001-12-15T02:59:43.1Z
+iso8601: 2001-12-14t21:59:43.10-05:00
+spaced: 2001-12-14 21:59:43.10 -5
+date: 2002-12-14
diff --git a/eckit/tests/parser/2.23.yaml b/eckit/tests/parser/2.23.yaml
new file mode 100644
index 0000000..5dbd992
--- /dev/null
+++ b/eckit/tests/parser/2.23.yaml
@@ -0,0 +1,13 @@
+---
+not-date: !!str 2002-04-28
+
+picture: !!binary |
+ R0lGODlhDAAMAIQAAP//9/X
+ 17unp5WZmZgAAAOfn515eXv
+ Pz7Y6OjuDg4J+fn5OTk6enp
+ 56enmleECcgggoBADs=
+
+application specific tag: !something |
+ The semantics of the tag
+ above may be different for
+ different documents.
diff --git a/eckit/tests/parser/2.24.yaml b/eckit/tests/parser/2.24.yaml
new file mode 100644
index 0000000..1180757
--- /dev/null
+++ b/eckit/tests/parser/2.24.yaml
@@ -0,0 +1,14 @@
+%TAG ! tag:clarkevans.com,2002:
+--- !shape
+  # Use the ! handle for presenting
+  # tag:clarkevans.com,2002:circle
+- !circle
+  center: &ORIGIN {x: 73, y: 129}
+  radius: 7
+- !line
+  start: *ORIGIN
+  finish: { x: 89, y: 102 }
+- !label
+  start: *ORIGIN
+  color: 0xFFEEBB
+  text: Pretty vector drawing.
diff --git a/eckit/tests/parser/2.25.yaml b/eckit/tests/parser/2.25.yaml
new file mode 100644
index 0000000..769ac31
--- /dev/null
+++ b/eckit/tests/parser/2.25.yaml
@@ -0,0 +1,7 @@
+# sets are represented as a
+# mapping where each key is
+# associated with the empty string
+--- !!set
+? Mark McGwire
+? Sammy Sosa
+? Ken Griff
diff --git a/eckit/tests/parser/2.26.yaml b/eckit/tests/parser/2.26.yaml
new file mode 100644
index 0000000..3143763
--- /dev/null
+++ b/eckit/tests/parser/2.26.yaml
@@ -0,0 +1,7 @@
+# ordered maps are represented as
+# a sequence of mappings, with
+# each mapping having one key
+--- !!omap
+- Mark McGwire: 65
+- Sammy Sosa: 63
+- Ken Griffy: 58
diff --git a/eckit/tests/parser/2.27.yaml b/eckit/tests/parser/2.27.yaml
new file mode 100644
index 0000000..4625739
--- /dev/null
+++ b/eckit/tests/parser/2.27.yaml
@@ -0,0 +1,29 @@
+--- !<tag:clarkevans.com,2002:invoice>
+invoice: 34843
+date   : 2001-01-23
+bill-to: &id001
+    given  : Chris
+    family : Dumars
+    address:
+        lines: |
+            458 Walkman Dr.
+            Suite #292
+        city    : Royal Oak
+        state   : MI
+        postal  : 48046
+ship-to: *id001
+product:
+    - sku         : BL394D
+      quantity    : 4
+      description : Basketball
+      price       : 450.00
+    - sku         : BL4438H
+      quantity    : 1
+      description : Super Hoop
+      price       : 2392.00
+tax  : 251.42
+total: 4443.52
+comments:
+    Late afternoon is best.
+    Backup contact is Nancy
+    Billsmer @ 338-4338.
diff --git a/eckit/tests/parser/2.28.yaml b/eckit/tests/parser/2.28.yaml
new file mode 100644
index 0000000..a5c8dc8
--- /dev/null
+++ b/eckit/tests/parser/2.28.yaml
@@ -0,0 +1,26 @@
+---
+Time: 2001-11-23 15:01:42 -5
+User: ed
+Warning:
+  This is an error message
+  for the log file
+---
+Time: 2001-11-23 15:02:31 -5
+User: ed
+Warning:
+  A slightly different error
+  message.
+---
+Date: 2001-11-23 15:03:17 -5
+User: ed
+Fatal:
+  Unknown variable "bar"
+Stack:
+  - file: TopClass.py
+    line: 23
+    code: |
+      x = MoreObject("345\n")
+  - file: MoreClass.py
+    line: 58
+    code: |-
+      foo = bar
diff --git a/eckit/tests/parser/2.3.yaml b/eckit/tests/parser/2.3.yaml
new file mode 100644
index 0000000..656d628
--- /dev/null
+++ b/eckit/tests/parser/2.3.yaml
@@ -0,0 +1,8 @@
+american:
+  - Boston Red Sox
+  - Detroit Tigers
+  - New York Yankees
+national:
+  - New York Mets
+  - Chicago Cubs
+  - Atlanta Braves
diff --git a/eckit/tests/parser/2.4.yaml b/eckit/tests/parser/2.4.yaml
new file mode 100644
index 0000000..430f6b3
--- /dev/null
+++ b/eckit/tests/parser/2.4.yaml
@@ -0,0 +1,8 @@
+-
+  name: Mark McGwire
+  hr:   65
+  avg:  0.278
+-
+  name: Sammy Sosa
+  hr:   63
+  avg:  0.288
diff --git a/eckit/tests/parser/2.5.yaml b/eckit/tests/parser/2.5.yaml
new file mode 100644
index 0000000..cdd7770
--- /dev/null
+++ b/eckit/tests/parser/2.5.yaml
@@ -0,0 +1,3 @@
+- [name        , hr, avg  ]
+- [Mark McGwire, 65, 0.278]
+- [Sammy Sosa  , 63, 0.288]
diff --git a/eckit/tests/parser/2.6.yaml b/eckit/tests/parser/2.6.yaml
new file mode 100644
index 0000000..7a957b2
--- /dev/null
+++ b/eckit/tests/parser/2.6.yaml
@@ -0,0 +1,5 @@
+Mark McGwire: {hr: 65, avg: 0.278}
+Sammy Sosa: {
+    hr: 63,
+    avg: 0.288
+  }
diff --git a/eckit/tests/parser/2.7.yaml b/eckit/tests/parser/2.7.yaml
new file mode 100644
index 0000000..bc711d5
--- /dev/null
+++ b/eckit/tests/parser/2.7.yaml
@@ -0,0 +1,10 @@
+# Ranking of 1998 home runs
+---
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+
+# Team ranking
+---
+- Chicago Cubs
+- St Louis Cardinals
diff --git a/eckit/tests/parser/2.8.yaml b/eckit/tests/parser/2.8.yaml
new file mode 100644
index 0000000..05e102d
--- /dev/null
+++ b/eckit/tests/parser/2.8.yaml
@@ -0,0 +1,10 @@
+---
+time: 20:03:20
+player: Sammy Sosa
+action: strike (miss)
+...
+---
+time: 20:03:47
+player: Sammy Sosa
+action: grand slam
+...
diff --git a/eckit/tests/parser/2.9.yaml b/eckit/tests/parser/2.9.yaml
new file mode 100644
index 0000000..e264180
--- /dev/null
+++ b/eckit/tests/parser/2.9.yaml
@@ -0,0 +1,8 @@
+---
+hr: # 1998 hr ranking
+  - Mark McGwire
+  - Sammy Sosa
+rbi:
+  # 1998 rbi ranking
+  - Sammy Sosa
+  - Ken Griffey
diff --git a/eckit/tests/parser/CMakeLists.txt b/eckit/tests/parser/CMakeLists.txt
new file mode 100644
index 0000000..0ffe790
--- /dev/null
+++ b/eckit/tests/parser/CMakeLists.txt
@@ -0,0 +1,29 @@
+ecbuild_add_test( TARGET   eckit_test_json
+                  BOOST
+                  SOURCES  test_json.cc
+                  LIBS     eckit )
+
+list( APPEND yaml 
+2.1.yaml 2.10.yaml 2.11.yaml 2.12.yaml 2.13.yaml 2.14.yaml 2.15.yaml 2.16.yaml 2.17.yaml 2.18.yaml 2.19.yaml 2.2.yaml 2.20.yaml 2.21.yaml 2.22.yaml 2.23.yaml 2.24.yaml 2.25.yaml 2.26.yaml 2.27.yaml 2.28.yaml 2.3.yaml 2.4.yaml 2.5.yaml 2.6.yaml 2.7.yaml 2.8.yaml 2.9.yaml
+cfg.1.yaml
+)
+
+foreach( r ${yaml} )
+   configure_file( ${r} ${CMAKE_CURRENT_BINARY_DIR}/${r} @ONLY )
+endforeach()
+
+
+ecbuild_add_test( TARGET   eckit_test_yaml
+                  BOOST
+                  SOURCES  test_yaml.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_json_metadata
+                  BOOST
+                  SOURCES  test_json_metadata.cc
+                  LIBS     eckit )
+
+ecbuild_add_test( TARGET   eckit_test_stream_parser
+                  BOOST
+                  SOURCES  test_stream_parser.cc
+                  LIBS     eckit )
diff --git a/eckit/tests/parser/cfg.1.yaml b/eckit/tests/parser/cfg.1.yaml
new file mode 100644
index 0000000..b9707c9
--- /dev/null
+++ b/eckit/tests/parser/cfg.1.yaml
@@ -0,0 +1,6 @@
+{
+  "type" : "structured",
+  "yspace" : { "type":"linear", "N":9,  "start":90, "end":-90 },
+  "xspace" : { "type":"linear", "N":16, "start":0,  "end":360, "endpoint": false }
+}
+
diff --git a/eckit/src/tests/parser/test_json.cc b/eckit/tests/parser/test_json.cc
similarity index 100%
rename from eckit/src/tests/parser/test_json.cc
rename to eckit/tests/parser/test_json.cc
diff --git a/eckit/src/tests/parser/test_json_metadata.cc b/eckit/tests/parser/test_json_metadata.cc
similarity index 100%
rename from eckit/src/tests/parser/test_json_metadata.cc
rename to eckit/tests/parser/test_json_metadata.cc
diff --git a/eckit/src/tests/parser/test_stream_parser.cc b/eckit/tests/parser/test_stream_parser.cc
similarity index 100%
rename from eckit/src/tests/parser/test_stream_parser.cc
rename to eckit/tests/parser/test_stream_parser.cc
diff --git a/eckit/tests/parser/test_yaml.cc b/eckit/tests/parser/test_yaml.cc
new file mode 100644
index 0000000..0a26463
--- /dev/null
+++ b/eckit/tests/parser/test_yaml.cc
@@ -0,0 +1,323 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_parser
+
+#include "ecbuild/boost_test_framework.h"
+
+//#include "eckit/log/Log.h"
+#include "eckit/parser/YAMLParser.h"
+#include "eckit/parser/JSON.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace std;
+using namespace eckit;
+
+using namespace eckit::testing;
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+BOOST_AUTO_TEST_SUITE( test_eckit_parser_yaml )
+
+//----------------------------------------------------------------------------------------------------------------------
+
+static std::string toJSON(const Value& v) {
+    std::ostringstream oss;
+    JSON json(oss);
+    json << v;
+    return oss.str();
+}
+
+// BOOST_AUTO_TEST_CASE( test_eckit_yaml_1 ) {
+//     Value v =  YAMLParser::decodeFile("2.1.yaml");
+//     std::cout << "2.1.yaml " << v << std::endl;
+//     std::cout << toJSON(v) << std::endl;
+
+//     BOOST_CHECK( v.isList() );
+//     BOOST_CHECK_EQUAL( v.size(), 3 );
+
+//     BOOST_CHECK_EQUAL( v[0], "Mark McGwire" );
+//     BOOST_CHECK_EQUAL( v[1], "Sammy Sosa" );
+//     BOOST_CHECK_EQUAL( v[2], "Ken Griffey" );
+
+//     // BOOST_CHECK_EQUAL(toJSON(v), "[\"Mark McGwire\",\"Sammy Sosa\",\"Ken Griffey\"]");
+
+// }
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_2 ) {
+    Value v =  YAMLParser::decodeFile("2.2.yaml");
+    std::cout << "2.2.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    BOOST_CHECK( v.isMap() );
+    BOOST_CHECK_EQUAL( v.keys().size(), 3 );
+
+    BOOST_CHECK_EQUAL( v["hr"], Value(65) );
+    BOOST_CHECK_EQUAL( v["avg"], Value(0.278) );
+    BOOST_CHECK_EQUAL( v["rbi"], Value(147) );
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_3 ) {
+    Value v =  YAMLParser::decodeFile("2.3.yaml");
+    std::cout << "2.3.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    BOOST_CHECK( v.isMap() );
+    BOOST_CHECK_EQUAL( v.keys().size(), 2 );
+
+    BOOST_CHECK( v["american"].isList() );
+    BOOST_CHECK_EQUAL( v["american"].size(), 3 );
+
+    BOOST_CHECK( v["national"].isList() );
+    BOOST_CHECK_EQUAL( v["national"].size(), 3 );
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_4 ) {
+    Value v =  YAMLParser::decodeFile("2.4.yaml");
+    std::cout << "2.4.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    BOOST_CHECK( v.isList() );
+    BOOST_CHECK_EQUAL( v.size(), 2 );
+
+    BOOST_CHECK( v[0].isMap() );
+    BOOST_CHECK_EQUAL( v[0].keys().size(), 3 );
+
+    BOOST_CHECK( v[1].isMap() );
+    BOOST_CHECK_EQUAL( v[1].keys().size(), 3 );
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_5 ) {
+    Value v =  YAMLParser::decodeFile("2.5.yaml");
+    std::cout << "2.5.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    BOOST_CHECK( v.isList() );
+    BOOST_CHECK_EQUAL( v.size(), 3 );
+
+    BOOST_CHECK( v[0].isList() );
+    BOOST_CHECK_EQUAL( v[0].size(), 3 );
+
+    BOOST_CHECK( v[1].isList() );
+    BOOST_CHECK_EQUAL( v[1].size(), 3 );
+
+
+    BOOST_CHECK( v[2].isList() );
+    BOOST_CHECK_EQUAL( v[2].size(), 3 );
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_6 ) {
+    Value v =  YAMLParser::decodeFile("2.6.yaml");
+    std::cout << "2.6.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    BOOST_CHECK( v.isMap() );
+    BOOST_CHECK_EQUAL( v.keys().size(), 2 );
+
+    BOOST_CHECK( v["Mark McGwire"].isMap() );
+    BOOST_CHECK_EQUAL( v["Mark McGwire"].keys().size(), 2 );
+
+    BOOST_CHECK( v["Sammy Sosa"].isMap() );
+    BOOST_CHECK_EQUAL( v["Sammy Sosa"].keys().size(), 2 );
+
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_7 ) {
+    Value v =  YAMLParser::decodeFile("2.7.yaml");
+    std::cout << "2.7.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_8 ) {
+    Value v =  YAMLParser::decodeFile("2.8.yaml");
+    std::cout << "2.8.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_9 ) {
+    Value v =  YAMLParser::decodeFile("2.9.yaml");
+    std::cout << "2.9.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_10 ) {
+    Value v =  YAMLParser::decodeFile("2.10.yaml");
+    std::cout << "2.10.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+}
+
+/*
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_11 ) {
+    Value v =  YAMLParser::decodeFile("2.11.yaml");
+    std::cout << "2.11.yaml " << v << std::endl;
+        std::cout << toJSON(v) << std::endl;
+            std::cout << toJSON(v) << std::endl;
+
+}
+*/
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_12 ) {
+    Value v =  YAMLParser::decodeFile("2.12.yaml");
+    std::cout << "2.12.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+/*
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_13 ) {
+    Value v =  YAMLParser::decodeFile("2.13.yaml");
+    std::cout << "2.13.yaml " << v << std::endl;
+        std::cout << toJSON(v) << std::endl;
+}
+*/
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_14 ) {
+    Value v =  YAMLParser::decodeFile("2.14.yaml");
+    std::cout << "2.14.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    std::cout << "----------" << std::endl;
+    std::cout << v << std::endl;
+    std::cout << "----------" << std::endl;
+
+ BOOST_CHECK_EQUAL(v, "Mark McGwire's year was crippled by a knee injury.");
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_15 ) {
+    Value v =  YAMLParser::decodeFile("2.15.yaml");
+    std::cout << "2.15.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+    std::cout << "----------" << std::endl;
+    std::cout << v << std::endl;
+    std::cout << "----------" << std::endl;
+
+    BOOST_CHECK_EQUAL(v,
+                      "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n");
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_16 ) {
+    Value v =  YAMLParser::decodeFile("2.16.yaml");
+    std::cout << "2.16.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+// BOOST_AUTO_TEST_CASE( test_eckit_yaml_17 ) {
+//     Value v =  YAMLParser::decodeFile("2.17.yaml");
+//     std::cout << "2.17.yaml " << v << std::endl;
+//         std::cout << toJSON(v) << std::endl;
+// }
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_18 ) {
+    Value v =  YAMLParser::decodeFile("2.18.yaml");
+    std::cout << "2.18.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_19 ) {
+    Value v =  YAMLParser::decodeFile("2.19.yaml");
+    std::cout << "2.19.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+
+
+    BOOST_CHECK_EQUAL(v["canonical"], Value(12345));
+    // BOOST_CHECK_EQUAL(v["decimal"], Value(12345));
+    // BOOST_CHECK_EQUAL(v["sexagesimal"], Value(12345));
+    BOOST_CHECK_EQUAL(v["octal"], Value(12));
+    BOOST_CHECK_EQUAL(v["hexadecimal"], Value(12));
+
+
+// canonical: 12345
+// decimal: +12,345
+// sexagesimal: 3:25:45
+// octal: 014
+// hexadecimal: 0xC
+
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_20 ) {
+    Value v =  YAMLParser::decodeFile("2.20.yaml");
+    std::cout << "2.20.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_21 ) {
+    Value v =  YAMLParser::decodeFile("2.21.yaml");
+    std::cout << "2.21.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_22 ) {
+    Value v =  YAMLParser::decodeFile("2.22.yaml");
+    std::cout << "2.22.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+
+// BOOST_AUTO_TEST_CASE( test_eckit_yaml_23 ) {
+//     Value v =  YAMLParser::decodeFile("2.23.yaml");
+//     std::cout << "2.23.yaml " << v << std::endl;
+// std::cout << toJSON(v) << std::endl;
+// }
+
+
+
+// BOOST_AUTO_TEST_CASE( test_eckit_yaml_24 ) {
+//     Value v =  YAMLParser::decodeFile("2.24.yaml");
+//     std::cout << "2.24.yaml " << v << std::endl;
+// std::cout << toJSON(v) << std::endl;
+// }
+
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_25 ) {
+    Value v =  YAMLParser::decodeFile("2.25.yaml");
+    std::cout << "2.25.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_26 ) {
+    Value v =  YAMLParser::decodeFile("2.26.yaml");
+    std::cout << "2.26.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+
+BOOST_AUTO_TEST_CASE( test_eckit_yaml_27 ) {
+    Value v =  YAMLParser::decodeFile("2.27.yaml");
+    std::cout << "2.27.yaml " << v << std::endl;
+    std::cout << toJSON(v) << std::endl;
+}
+
+
+// BOOST_AUTO_TEST_CASE( test_eckit_yaml_28 ) {
+//     Value v =  YAMLParser::decodeFile("2.28.yaml");
+//     std::cout << "2.28.yaml " << v << std::endl;
+//     std::cout << toJSON(v) << std::endl;
+// }
+
+ BOOST_AUTO_TEST_CASE( test_eckit_yaml_cfg_1 ) {
+     Value v =  YAMLParser::decodeFile("cfg.1.yaml");
+     std::cout << "cfg.1.yaml " << v << std::endl;
+     std::cout << toJSON(v) << std::endl;
+ }
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/runtime/CMakeLists.txt b/eckit/tests/runtime/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/runtime/CMakeLists.txt
rename to eckit/tests/runtime/CMakeLists.txt
diff --git a/eckit/src/tests/runtime/boost_auto_param.h b/eckit/tests/runtime/boost_auto_param.h
similarity index 100%
rename from eckit/src/tests/runtime/boost_auto_param.h
rename to eckit/tests/runtime/boost_auto_param.h
diff --git a/eckit/src/tests/runtime/test_context.cc b/eckit/tests/runtime/test_context.cc
similarity index 100%
rename from eckit/src/tests/runtime/test_context.cc
rename to eckit/tests/runtime/test_context.cc
diff --git a/eckit/src/tests/runtime/test_producer.cc b/eckit/tests/runtime/test_producer.cc
similarity index 100%
rename from eckit/src/tests/runtime/test_producer.cc
rename to eckit/tests/runtime/test_producer.cc
diff --git a/eckit/src/tests/serialisation/CMakeLists.txt b/eckit/tests/serialisation/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/serialisation/CMakeLists.txt
rename to eckit/tests/serialisation/CMakeLists.txt
diff --git a/eckit/src/tests/serialisation/test_file_stream.cc b/eckit/tests/serialisation/test_file_stream.cc
similarity index 100%
rename from eckit/src/tests/serialisation/test_file_stream.cc
rename to eckit/tests/serialisation/test_file_stream.cc
diff --git a/eckit/src/tests/serialisation/test_streamable.cc b/eckit/tests/serialisation/test_streamable.cc
similarity index 100%
rename from eckit/src/tests/serialisation/test_streamable.cc
rename to eckit/tests/serialisation/test_streamable.cc
diff --git a/eckit/src/tests/system/CMakeLists.txt b/eckit/tests/system/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/system/CMakeLists.txt
rename to eckit/tests/system/CMakeLists.txt
diff --git a/eckit/tests/system/test_system.cc b/eckit/tests/system/test_system.cc
new file mode 100755
index 0000000..e539160
--- /dev/null
+++ b/eckit/tests/system/test_system.cc
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <iostream>
+#include <cstdlib>
+
+#define BOOST_TEST_MODULE test_eckit_system
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/config/LibEcKit.h"
+#include "eckit/exception/Exceptions.h"
+#include "eckit/filesystem/LocalPathName.h"
+#include "eckit/system/ResourceUsage.h"
+#include "eckit/system/SystemInfo.h"
+#include "eckit/system/Library.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace eckit;
+using namespace eckit::testing;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+BOOST_AUTO_TEST_SUITE( test_eckit_resource_usage )
+
+BOOST_AUTO_TEST_CASE( test_eckit_resource_usage_0 )
+{
+    size_t chunk = 20*1024*1024;
+    for(size_t i = 1; i < 5; ++i) {
+
+        size_t before = system::ResourceUsage().maxResidentSetSize();
+
+        void *m = ::malloc(chunk);
+        ::memset(m,0,chunk);
+
+        size_t after = system::ResourceUsage().maxResidentSetSize();
+
+        ::free(m);
+
+        BOOST_TEST_MESSAGE( "Memory usage " << after );
+
+        BOOST_REQUIRE( before <= after );
+    }
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_system_info )
+{
+    eckit::LocalPathName execPath;
+    BOOST_CHECK_NO_THROW( execPath = eckit::system::SystemInfo::instance().executablePath() );
+    BOOST_CHECK( std::string(execPath).size() );
+
+    Log::info() << "execPath is " << execPath << std::endl;
+}
+
+BOOST_AUTO_TEST_CASE( test_eckit_system_library )
+{
+    using eckit::system::Library;
+
+    std::vector<std::string> libs = Library::list();
+
+    std::string libpath;
+
+    for(std::vector<std::string>::const_iterator libname = libs.begin(); libname != libs.end(); ++libname ) {
+
+        BOOST_CHECK_NO_THROW( Library::lookup(*libname) );
+
+        const Library& lib = Library::lookup(*libname);
+
+        BOOST_CHECK_NO_THROW( lib.prefixDirectory() );
+
+        Log::info() << "Library " << lib.name() << " @ " << lib.prefixDirectory() << std::endl;
+        Log::info() << lib << std::endl;
+    }
+
+    // this exercises the tilde expansion
+
+    BOOST_CHECK_NO_THROW( LocalPathName("~eckit/etc").exists() );
+    BOOST_CHECK_NO_THROW( LocalPathName("~eckit/etc/eckit/test/test.cfg").exists() );
+}
+
+BOOST_AUTO_TEST_CASE( test_libeckit )
+{
+    BOOST_CHECK_NO_THROW(LibEcKit::instance().configuration()); // tests an empty configuration
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/eckit/src/tests/thread/CMakeLists.txt b/eckit/tests/thread/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/thread/CMakeLists.txt
rename to eckit/tests/thread/CMakeLists.txt
diff --git a/eckit/src/tests/thread/test_mutex.cc b/eckit/tests/thread/test_mutex.cc
similarity index 100%
rename from eckit/src/tests/thread/test_mutex.cc
rename to eckit/tests/thread/test_mutex.cc
diff --git a/eckit/src/tests/types/CMakeLists.txt b/eckit/tests/types/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/types/CMakeLists.txt
rename to eckit/tests/types/CMakeLists.txt
diff --git a/eckit/src/tests/types/test-double-compare-speed.cc b/eckit/tests/types/test-double-compare-speed.cc
similarity index 100%
rename from eckit/src/tests/types/test-double-compare-speed.cc
rename to eckit/tests/types/test-double-compare-speed.cc
diff --git a/eckit/src/tests/types/test_cache.cc b/eckit/tests/types/test_cache.cc
similarity index 100%
rename from eckit/src/tests/types/test_cache.cc
rename to eckit/tests/types/test_cache.cc
diff --git a/eckit/src/tests/types/test_doublecompare.cc b/eckit/tests/types/test_doublecompare.cc
similarity index 100%
rename from eckit/src/tests/types/test_doublecompare.cc
rename to eckit/tests/types/test_doublecompare.cc
diff --git a/eckit/src/tests/types/test_fixedstring.cc b/eckit/tests/types/test_fixedstring.cc
similarity index 100%
rename from eckit/src/tests/types/test_fixedstring.cc
rename to eckit/tests/types/test_fixedstring.cc
diff --git a/eckit/src/tests/types/test_floatcompare.cc b/eckit/tests/types/test_floatcompare.cc
similarity index 100%
rename from eckit/src/tests/types/test_floatcompare.cc
rename to eckit/tests/types/test_floatcompare.cc
diff --git a/eckit/tests/types/test_fraction.cc b/eckit/tests/types/test_fraction.cc
new file mode 100644
index 0000000..0e55a96
--- /dev/null
+++ b/eckit/tests/types/test_fraction.cc
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_fraction
+#include <cmath>
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/types/Fraction.h"
+
+#include "eckit/testing/Setup.h"
+
+
+using namespace eckit;
+using namespace eckit::testing;
+
+BOOST_GLOBAL_FIXTURE( Setup );
+
+BOOST_AUTO_TEST_SUITE( test_eckit_fraction )
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_fraction )
+{
+    // 0
+
+    BOOST_CHECK_EQUAL( Fraction(0, 1), Fraction() );
+
+    BOOST_CHECK_THROW( Fraction(0, 0), std::exception ); // this prints a backtrace wi Assertion failed
+
+    // negative number
+
+    BOOST_CHECK_EQUAL( Fraction(-1, 2), Fraction(3, -6) );
+
+    // decimals
+
+    BOOST_CHECK_EQUAL( Fraction(0.16), Fraction(16, 100) );
+    BOOST_CHECK_EQUAL( Fraction(0.1616), Fraction(1616, 10000) );
+
+    // 5 / 7
+
+    BOOST_CHECK( Fraction(0.714285) != Fraction(5, 7) );
+
+    BOOST_CHECK( Fraction(0.7142857142) != Fraction(5, 7) );
+
+    BOOST_CHECK_EQUAL( Fraction(0.71428571428),  Fraction(5, 7) );
+    BOOST_CHECK_EQUAL( Fraction(0.714285714285), Fraction(5, 7) );
+    BOOST_CHECK_EQUAL( Fraction(0.714285714286), Fraction(5, 7) );
+
+    BOOST_CHECK_EQUAL( Fraction(0.714285714285714285), Fraction(5, 7) );
+
+    // 1 / 6
+
+    BOOST_CHECK( Fraction(0.166) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.1666) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.16666) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.166666) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.1666666) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.16666666) != Fraction(1, 6) );
+    BOOST_CHECK( Fraction(0.166666666) != Fraction(1, 6) );
+
+    BOOST_CHECK_EQUAL( Fraction(0.16666666666), Fraction(1, 6) );
+    BOOST_CHECK_EQUAL( Fraction(0.166666666666), Fraction(1, 6) );
+    BOOST_CHECK_EQUAL( Fraction(0.1666666666666), Fraction(1, 6) );
+    BOOST_CHECK_EQUAL( Fraction(0.16666666666666), Fraction(1, 6) );
+    BOOST_CHECK_EQUAL( Fraction(0.166666666666666), Fraction(1, 6) );
+    BOOST_CHECK_EQUAL( Fraction(0.1666666666666666), Fraction(1, 6) );
+
+    // 1 / 3
+
+    BOOST_CHECK_EQUAL( Fraction(0.3333333333), Fraction(1, 3) );
+
+    BOOST_CHECK_EQUAL( Fraction(0.3333333333333333), Fraction(1, 3) );
+
+    // 1 / 1
+
+    BOOST_CHECK_EQUAL( Fraction(0.9999999999999999), Fraction(1, 1) );
+    BOOST_CHECK_EQUAL( Fraction(0.9999999999999999), Fraction(10, 10) );
+
+    // 7 / 10..
+
+    BOOST_CHECK_EQUAL( Fraction(0.7), Fraction(7, 10) );
+    BOOST_CHECK_EQUAL( Fraction(0.07), Fraction(7, 100) );
+    BOOST_CHECK_EQUAL( Fraction(0.0000007), Fraction(7, 10000000) );
+
+    // operations
+
+    BOOST_CHECK_EQUAL( Fraction(1, 3) + Fraction(2, 3), Fraction(10, 10) );
+    BOOST_CHECK_EQUAL( Fraction(1, 3) - Fraction(2, 6), Fraction(0, 10) );
+
+    BOOST_CHECK_EQUAL( Fraction(1, 3) * 3, Fraction(1) );
+
+    BOOST_CHECK_EQUAL( -Fraction(1, 3), Fraction(1, -3) );
+
+    BOOST_CHECK_EQUAL( 2 * Fraction(1, 3) , Fraction(2, 3) );
+
+    Fraction a(1, 3);
+    Fraction b(3, 28);
+    BOOST_CHECK_EQUAL(a + b, Fraction(37, 84));
+    BOOST_CHECK_EQUAL(a - b, Fraction(19, 84));
+    BOOST_CHECK_EQUAL(a * b, Fraction(1, 28));
+    BOOST_CHECK_EQUAL(a / b, Fraction(28, 9));
+
+    BOOST_CHECK_EQUAL(a > b, true);
+    BOOST_CHECK_EQUAL(a != b, true);
+    BOOST_CHECK_EQUAL(a < b, false);
+    BOOST_CHECK_EQUAL(a == b, false);
+
+    BOOST_CHECK_EQUAL(Fraction("1/3"), Fraction(1, 3));
+    BOOST_CHECK_EQUAL(double(Fraction("1/3")), 1.0 / 3.0);
+
+    BOOST_CHECK_EQUAL(Fraction("1"), Fraction(1));
+    BOOST_CHECK_EQUAL(Fraction("1.2"), Fraction(12, 10));
+    BOOST_CHECK_EQUAL(Fraction("1e-6"), Fraction(1, 1000000));
+    BOOST_CHECK_EQUAL(Fraction("1e+6"), Fraction(1000000, 1));
+    BOOST_CHECK_EQUAL(Fraction("1.2e+6"), Fraction(1200000, 1));
+
+    BOOST_CHECK_EQUAL(Fraction(M_PI) > Fraction(M_E), true);
+    BOOST_CHECK_EQUAL(Fraction(M_E) > Fraction(M_SQRT2), true);
+
+    std::cout << "pi = " << (M_PI - double(Fraction(M_PI))) << std::endl;
+    std::cout << "e = " << (M_E - double(Fraction(M_E))) << std::endl;
+    std::cout << "sqrt2 = " << (M_SQRT2 - double(Fraction(M_SQRT2))) << std::endl;
+
+    // BOOST_CHECK_EQUAL(Fraction(M_PI), Fraction(1200000, 1));
+    {
+        Fraction west(-12), east(1.2), increment(1.2);
+
+        Fraction f(west);
+        while (f < east) {
+            f += increment;
+        }
+        BOOST_CHECK_EQUAL(f, east);
+    }
+
+    {
+        Fraction west("-77"), east("7"), increment("0.7");
+
+        Fraction f(west);
+        while (f < east) {
+            f += increment;
+        }
+        BOOST_CHECK_EQUAL(f, east);
+    }
+
+    // BOOST_CHECK_EQUAL(Fraction(5, 3).intergralPart(), 1);
+    // BOOST_CHECK_EQUAL(Fraction(5, 3).decimalPart(), Fraction(1, 3));
+
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/eckit/src/tests/types/test_print_vector.cc b/eckit/tests/types/test_print_vector.cc
similarity index 100%
rename from eckit/src/tests/types/test_print_vector.cc
rename to eckit/tests/types/test_print_vector.cc
diff --git a/eckit/src/tests/types/test_uuid.cc b/eckit/tests/types/test_uuid.cc
similarity index 100%
rename from eckit/src/tests/types/test_uuid.cc
rename to eckit/tests/types/test_uuid.cc
diff --git a/eckit/src/tests/utils/CMakeLists.txt b/eckit/tests/utils/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/utils/CMakeLists.txt
rename to eckit/tests/utils/CMakeLists.txt
diff --git a/eckit/src/tests/utils/hash-performance.cc b/eckit/tests/utils/hash-performance.cc
similarity index 100%
rename from eckit/src/tests/utils/hash-performance.cc
rename to eckit/tests/utils/hash-performance.cc
diff --git a/eckit/src/tests/utils/test_md4.cc b/eckit/tests/utils/test_md4.cc
similarity index 100%
rename from eckit/src/tests/utils/test_md4.cc
rename to eckit/tests/utils/test_md4.cc
diff --git a/eckit/src/tests/utils/test_md5.cc b/eckit/tests/utils/test_md5.cc
similarity index 100%
rename from eckit/src/tests/utils/test_md5.cc
rename to eckit/tests/utils/test_md5.cc
diff --git a/eckit/src/tests/utils/test_rendezvoushash.cc b/eckit/tests/utils/test_rendezvoushash.cc
similarity index 100%
rename from eckit/src/tests/utils/test_rendezvoushash.cc
rename to eckit/tests/utils/test_rendezvoushash.cc
diff --git a/eckit/src/tests/utils/test_sha1.cc b/eckit/tests/utils/test_sha1.cc
similarity index 100%
rename from eckit/src/tests/utils/test_sha1.cc
rename to eckit/tests/utils/test_sha1.cc
diff --git a/eckit/tests/utils/test_string_tools.cc b/eckit/tests/utils/test_string_tools.cc
new file mode 100644
index 0000000..7d21697
--- /dev/null
+++ b/eckit/tests/utils/test_string_tools.cc
@@ -0,0 +1,199 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "eckit/log/Log.h"
+#include "eckit/runtime/Tool.h"
+#include "eckit/parser/StringTools.h"
+#include "eckit/types/Types.h"
+
+using namespace std;
+using namespace eckit;
+
+
+namespace eckit_test {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class TestStringTools : public Tool {
+public:
+
+    TestStringTools(int argc,char **argv): Tool(argc,argv) {}
+
+    ~TestStringTools() {}
+
+    virtual void run();
+
+protected:
+    
+    void substitute();
+    void listVariables();
+    void startsWith();
+    void endsWith();
+    void trim();
+    void front_trim();
+    void back_trim();
+
+};
+
+
+            
+void TestStringTools::run()
+{
+    substitute();
+    listVariables();
+    startsWith();
+    trim();
+    front_trim();
+    back_trim();
+}
+
+void TestStringTools::substitute()
+{
+    StringDict m;
+
+    m["class"]  = "od";
+    m["stream"] = "oper";
+
+    string in ( "{class}:none:{stream}" );
+    
+    string out = StringTools::substitute(in,m);
+    
+    ASSERT( out == "od:none:oper" );    
+}
+
+void TestStringTools::listVariables()
+{
+    string in ( "{class}:none:{stream}" );
+
+    StringList out = StringTools::listVariables(in);
+    
+    ASSERT( out.size() == 2 );    
+    ASSERT( out[0] == "class" );    
+    ASSERT( out[1] == "stream" );    
+}
+
+void TestStringTools::startsWith()
+{
+    string in ( "_lolo_test" );
+    string s1 ( "_lolo" );
+    string s2 ( "lolo" );
+    string s3 ( "_lolo_test_bigger" );
+
+    ASSERT( !StringTools::startsWith(in,"") );
+    ASSERT(  StringTools::startsWith(in,in) );
+    ASSERT(  StringTools::startsWith(in,s1) );
+    ASSERT(  StringTools::startsWith(in,"_") );
+    ASSERT( !StringTools::startsWith(in,s2) );
+    ASSERT( !StringTools::startsWith(in,s3) );
+}
+
+void TestStringTools::endsWith()
+{
+    string in ( "_lolo_test" );
+    ASSERT(  StringTools::endsWith(in,"") );
+    ASSERT(  StringTools::endsWith(in,in) );
+    ASSERT(  StringTools::endsWith(in,"t") );
+
+    string s1 ( "_test" );
+    ASSERT(  StringTools::endsWith(in,s1) );
+
+    string s2 ( "lolo" );
+    ASSERT( !StringTools::endsWith(in,s2) );
+
+    string s3 ( "_lolo_test333" );
+    ASSERT( !StringTools::endsWith(in,s3) );
+}
+
+void TestStringTools::trim()
+{
+    string t1 ( "   lolo_test    " );
+    ASSERT(  StringTools::trim(t1) == string("lolo_test") );
+
+    string t2 ( "   lolo_test" );
+    ASSERT(  StringTools::trim(t2) == string("lolo_test") );
+
+    string t3 ( "lolo_test   " );
+    ASSERT(  StringTools::trim(t3) == string("lolo_test") );
+
+    string t4 ( "" );
+    ASSERT(  StringTools::trim(t4) == string("") );
+
+    string t5 ( "nothing_here" );
+    ASSERT(  StringTools::trim(t5) == string("nothing_here") );
+
+    string t6 ( "XXXXXXusefullXXXXX" );
+    ASSERT(  StringTools::trim(t6,"X") == string("usefull") );
+
+    string t7 ( "0000010" );
+    ASSERT(  StringTools::trim(t7,"0") == string("1") );
+}
+
+void TestStringTools::front_trim()
+{
+    string t1 ( "   lolo_test    " );
+    ASSERT(  StringTools::front_trim(t1) == string("lolo_test    ") );
+
+    string t2 ( "   lolo_test" );
+    ASSERT(  StringTools::front_trim(t2) == string("lolo_test") );
+
+    string t3 ( "lolo_test   " );
+    ASSERT(  StringTools::front_trim(t3) == string("lolo_test   ") );
+
+    string t4 ( "" );
+    ASSERT(  StringTools::front_trim(t4) == string("") );
+
+    string t5 ( "nothing_here" );
+    ASSERT(  StringTools::front_trim(t5) == string("nothing_here") );
+
+    string t6 ( "XXXXXXusefullXXXXX" );
+    ASSERT(  StringTools::front_trim(t6,"X") == string("usefullXXXXX") );
+
+    string t7 ( "0000010" );
+    ASSERT(  StringTools::front_trim(t7,"0") == string("10") );
+}
+
+void TestStringTools::back_trim()
+{
+    string t1 ( "   lolo_test    " );
+
+    Log::info() << StringTools::back_trim(t1) << std::endl;
+
+    ASSERT(  StringTools::back_trim(t1) == string("   lolo_test") );
+
+    string t2 ( "   lolo_test" );
+    ASSERT(  StringTools::back_trim(t2) == string("   lolo_test") );
+
+    string t3 ( "lolo_test   " );
+    ASSERT(  StringTools::back_trim(t3) == string("lolo_test") );
+
+    string t4 ( "" );
+    ASSERT(  StringTools::back_trim(t4) == string("") );
+
+    string t5 ( "nothing_here" );
+    ASSERT(  StringTools::back_trim(t5) == string("nothing_here") );
+
+    string t6 ( "XXXXXXusefullXXXXX" );
+    ASSERT(  StringTools::back_trim(t6,"X") == string("XXXXXXusefull") );
+
+    string t7 ( "0000010" );
+    ASSERT(  StringTools::back_trim(t7,"0") == string("000001") );
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit_test
+
+
+int main(int argc,char **argv)
+{
+    eckit_test::TestStringTools app(argc,argv);
+    return app.start();
+}
+
diff --git a/eckit/src/tests/utils/test_tokenizer.cc b/eckit/tests/utils/test_tokenizer.cc
similarity index 100%
rename from eckit/src/tests/utils/test_tokenizer.cc
rename to eckit/tests/utils/test_tokenizer.cc
diff --git a/eckit/src/tests/utils/test_translator.cc b/eckit/tests/utils/test_translator.cc
similarity index 100%
rename from eckit/src/tests/utils/test_translator.cc
rename to eckit/tests/utils/test_translator.cc
diff --git a/eckit/src/tests/utils/test_xxhash.cc b/eckit/tests/utils/test_xxhash.cc
similarity index 100%
rename from eckit/src/tests/utils/test_xxhash.cc
rename to eckit/tests/utils/test_xxhash.cc
diff --git a/eckit/src/tests/value/AnyKeyParams.cc b/eckit/tests/value/AnyKeyParams.cc
similarity index 100%
rename from eckit/src/tests/value/AnyKeyParams.cc
rename to eckit/tests/value/AnyKeyParams.cc
diff --git a/eckit/src/tests/value/AnyKeyParams.h b/eckit/tests/value/AnyKeyParams.h
similarity index 100%
rename from eckit/src/tests/value/AnyKeyParams.h
rename to eckit/tests/value/AnyKeyParams.h
diff --git a/eckit/src/tests/value/CMakeLists.txt b/eckit/tests/value/CMakeLists.txt
similarity index 100%
rename from eckit/src/tests/value/CMakeLists.txt
rename to eckit/tests/value/CMakeLists.txt
diff --git a/eckit/tests/value/test_value.cc b/eckit/tests/value/test_value.cc
new file mode 100644
index 0000000..a43a252
--- /dev/null
+++ b/eckit/tests/value/test_value.cc
@@ -0,0 +1,2624 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_value
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/value/Value.h"
+
+#include "eckit/testing/Setup.h"
+
+using namespace std;
+using namespace eckit;
+using namespace eckit::testing;
+
+namespace eckit {
+namespace test {
+
+BOOST_GLOBAL_FIXTURE(Setup);
+
+//----------------------------------------------------------------------------------------------------------------------
+
+// eckit::Value offloads its functionality onto various subclasses of eckit::Content, which are
+// internally allocated on the heap and managed by the Value objects. This allows the behaviour to
+// depend on the type of content stored, with a consistent exposed interface.
+//
+// As a result of this, eckit::Value has an extremely thick interface, with potentially NxN possibilities for each
+// action (N possible types of argument, N possible types of content) - e.g. ::as<double>() will happily return a
+// (casted) double if the content type is a long...
+//
+// --> it is not realistic to catch all of this behaviour in the tests.
+
+//----------------------------------------------------------------------------------------------------------------------
+
+namespace {
+
+    // Helper functions, so that we can put operator expressions inside callables that can be passed into
+    // BOOST_CHECK_THROW
+
+    Value ValueAdd(const Value& lhs, const Value& rhs) { return lhs + rhs; }
+    Value ValueSub(const Value& lhs, const Value& rhs) { return lhs - rhs; }
+    Value ValueMul(const Value& lhs, const Value& rhs) { return lhs * rhs; }
+    Value ValueDiv(const Value& lhs, const Value& rhs) { return lhs / rhs; }
+    Value ValueMod(const Value& lhs, const Value& rhs) { return lhs % rhs; }
+
+    Value ValueAddSelf(Value& lhs, const Value& rhs) { return lhs += rhs; }
+    Value ValueSubSelf(Value& lhs, const Value& rhs) { return lhs -= rhs; }
+    Value ValueMulSelf(Value& lhs, const Value& rhs) { return lhs *= rhs; }
+    Value ValueDivSelf(Value& lhs, const Value& rhs) { return lhs /= rhs; }
+    Value ValueModSelf(Value& lhs, const Value& rhs) { return lhs %= rhs; }
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+// TODO:
+// - Tests for Stream
+// - Test json, print, encode
+
+
+BOOST_AUTO_TEST_SUITE( test_eckit_value )
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of bools first
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_cast ) {
+    Value val_true(true);
+    Value val_false(false);
+
+    //
+    // Access and conversion of bools
+    //
+
+    BOOST_CHECK_EQUAL(bool(val_true), true);
+    BOOST_CHECK_EQUAL(bool(val_false), false);
+    BOOST_CHECK_EQUAL(val_true.as<bool>(), true);
+    BOOST_CHECK_EQUAL(val_false.as<bool>(), false);
+
+    // Integer type conversions
+    BOOST_CHECK_EQUAL(int(val_true), 1);
+    BOOST_CHECK_EQUAL(int(val_false), 0);
+    BOOST_CHECK_EQUAL(val_true.as<long long>(), 1);
+    BOOST_CHECK_EQUAL(val_false.as<long long>(), 0);
+
+    // For pretty printing
+
+    BOOST_CHECK_EQUAL(std::string(val_true), "true");
+    BOOST_CHECK_EQUAL(std::string(val_false), "false");
+    BOOST_CHECK_EQUAL(val_true.as<std::string>(), "true");
+    BOOST_CHECK_EQUAL(val_false.as<std::string>(), "false");
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl_true(val_true.as<ValueList>());
+    ValueList vl_false = val_false;
+    BOOST_CHECK_EQUAL(vl_true.size(), 1);
+    BOOST_CHECK_EQUAL(vl_false.size(), 1);
+    BOOST_CHECK_EQUAL(vl_true[0].as<bool>(), true);
+    BOOST_CHECK_EQUAL(vl_false[0].as<bool>(), false);
+
+    // And all the invalid conversions
+
+    /// For some reason, Value(bool) happily converts to double...
+    /// BOOST_CHECK_THROW(val_false.as<double>(), BadConversion);
+
+    /// Length/Offset are just integers, so bool-->Offset conversion works...!!!
+    /// BOOST_CHECK_THROW(Length(val_false), BadConversion);
+    /// BOOST_CHECK_THROW(Offset(val_false), BadConversion);
+
+    BOOST_CHECK_THROW(val_false.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val_false.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val_false.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val_false.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_type ) {
+    Value val_true(true);
+    Value val_false(false);
+
+    BOOST_CHECK(val_true.isBool());
+    BOOST_CHECK(val_false.isBool());
+
+    BOOST_CHECK(!val_true.isNil());
+    BOOST_CHECK(!val_true.isNumber());
+    BOOST_CHECK(!val_true.isDouble());
+    BOOST_CHECK(!val_true.isString());
+    BOOST_CHECK(!val_true.isList());
+    BOOST_CHECK(!val_true.isMap());
+    BOOST_CHECK(!val_true.isDate());
+    BOOST_CHECK(!val_true.isTime());
+    BOOST_CHECK(!val_true.isDateTime());
+
+    BOOST_CHECK(!val_false.isNil());
+    BOOST_CHECK(!val_false.isNumber());
+    BOOST_CHECK(!val_false.isDouble());
+    BOOST_CHECK(!val_false.isString());
+    BOOST_CHECK(!val_false.isList());
+    BOOST_CHECK(!val_false.isMap());
+    BOOST_CHECK(!val_false.isDate());
+    BOOST_CHECK(!val_false.isTime());
+    BOOST_CHECK(!val_false.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_comparisons ) {
+    Value val_true1(true);
+    Value val_true2(true);
+    Value val_false1(false);
+    Value val_false2(false);
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+
+    // ************************
+    // WARNING: This logic is inverted from all the other Value types. Should probably be checked.
+    // ************************
+
+    BOOST_CHECK(val_true1.compare(val_true1) == -1);
+    BOOST_CHECK(val_true1.compare(val_true2) == -1);
+    BOOST_CHECK(val_false1.compare(val_false1) == 1);
+    BOOST_CHECK(val_false1.compare(val_false2) == 1);
+
+    BOOST_CHECK(val_true1.compare(val_false1) == 0);
+    BOOST_CHECK(val_false2.compare(val_true2) == 0);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val_true1.compare(Value(1234)) > 0); // Only need 1 integral test, they are all the same.
+    BOOST_CHECK(val_true1.compare(Value(1234.5)) > 0);
+    BOOST_CHECK(val_true1.compare(Value("test str")) > 0);
+    BOOST_CHECK(val_true1.compare(Value(std::string("testing string"))) > 0);
+    BOOST_CHECK(val_true1.compare(Value(ValueMap())) > 0);
+    BOOST_CHECK(val_true1.compare(Value(Date(2016, 3, 30))) > 0);
+    BOOST_CHECK(val_true1.compare(ValueList()) > 0);
+
+    BOOST_CHECK(Value(1234).compare(val_false1) < 0); // Only need 1 integral test, they are all the same.
+    BOOST_CHECK(Value(1234.5).compare(val_false1) < 0);
+    BOOST_CHECK(Value("test str").compare(val_false1) < 0);
+    BOOST_CHECK(Value(std::string("testing string")).compare(val_false1) < 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val_false1) < 0);
+    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val_false1) < 0);
+    BOOST_CHECK(Value(ValueList()).compare(val_false1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_index_operator ) {
+    // No indexing operations should work on a bool...
+
+    Value val_true(true);
+    Value val_false(false);
+
+    BOOST_CHECK_THROW(val_true["idx"], BadOperator);
+    BOOST_CHECK_THROW(val_true[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val_true[123], BadOperator);
+    BOOST_CHECK_THROW(val_true[Value(123)], BadOperator);
+
+    BOOST_CHECK_THROW(val_false["idx"], BadOperator);
+    BOOST_CHECK_THROW(val_false[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val_false[123], BadOperator);
+    BOOST_CHECK_THROW(val_false[Value(123)], BadOperator);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK_THROW(val_true.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val_true.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val_true.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val_true.contains(Value(123)), BadOperator);
+
+    BOOST_CHECK_THROW(val_false.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val_false.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val_false.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val_false.contains(Value(123)), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_add_operator ) {
+    // There are no valid boolean addition operations.
+
+    Value val(true);
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_subtract_operator ) {
+    // There are no valid boolean subtraction operations.
+
+    Value val(true);
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_multiply_operator ) {
+    // There are no valid boolean multiplication operations.
+
+    Value val(true);
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_divide_operator ) {
+    // There are no valid boolean division operations.
+
+    Value val(true);
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_modulo_operator ) {
+    // There are no valid boolean modulo operations.
+
+    Value val(true);
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_bool_head_tail ) {
+    Value val(true);
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of integers next. Note that all integral types are treated identically.
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_cast ) {
+    // Note that _all_ the integer types are stored as a signed long long
+    // --> There are constraints on the size that can be stored
+    Value val_zero(0U);
+    Value val_int(12345);
+    Value val_long(-2147483647);
+
+    // Integer conversions
+
+    BOOST_CHECK_EQUAL(val_zero.as<long long>(), 0);
+    BOOST_CHECK_EQUAL(val_int.as<long long>(), 12345);
+    BOOST_CHECK_EQUAL(val_long.as<long long>(), -2147483647);
+
+    BOOST_CHECK_EQUAL(int(val_zero), 0);
+
+    BOOST_CHECK_EQUAL(int(val_int), 12345);
+    BOOST_CHECK_EQUAL((unsigned int)(val_int), 12345);
+    BOOST_CHECK_EQUAL(short(val_int), 12345);
+    BOOST_CHECK_EQUAL((unsigned short)(val_int), 12345);
+    BOOST_CHECK_EQUAL(long(val_int), 12345);
+    BOOST_CHECK_EQUAL((unsigned long)(val_int), 12345);
+    BOOST_CHECK_EQUAL((long long)(val_int), 12345);
+    BOOST_CHECK_EQUAL((unsigned long long)(val_int), 12345);
+
+    // NOTE that using an unsigned variable does NOT cause the check to fail, unless there is an overflow. The
+    // compiler will assume that everything is fine, and just do a bitwise check...
+    BOOST_CHECK_EQUAL(int(val_long), -2147483647);
+    BOOST_CHECK_EQUAL((unsigned int)(val_long), -2147483647);
+//    BOOST_CHECK(short(val_long) != -2147483647);             // a short ranges [−32767, +32767] so this is always true
+//    BOOST_CHECK((unsigned short)(val_long) != -2147483647);  // unsigned is always positive
+    BOOST_CHECK_EQUAL(long(val_long), -2147483647);
+    BOOST_CHECK_EQUAL((unsigned long)(val_long), -2147483647);
+    BOOST_CHECK_EQUAL((long long)(val_long), -2147483647);
+    BOOST_CHECK_EQUAL((unsigned long long)(val_long), -2147483647);
+
+    // Check boolean conversion
+
+    BOOST_CHECK(!val_zero);
+    BOOST_CHECK(val_int);
+    BOOST_CHECK(val_long);
+    BOOST_CHECK(!val_zero.as<bool>());
+    BOOST_CHECK(val_int.as<bool>());
+    BOOST_CHECK(val_long.as<bool>());
+
+    // Check double conversion
+
+    BOOST_CHECK_CLOSE(double(val_zero), 0.0, 1.0e-6);
+    BOOST_CHECK_CLOSE(double(val_int), 12345.0, 1.0e-6);
+    BOOST_CHECK_CLOSE(double(val_long), -2147483647.0, 1.0e-6);
+    BOOST_CHECK_CLOSE(val_zero.as<double>(), 0.0, 1.0e-6);
+    BOOST_CHECK_CLOSE(val_int.as<double>(), 12345.0, 1.0e-6);
+    BOOST_CHECK_CLOSE(val_long.as<double>(), -2147483647.0, 1.0e-6);
+
+    // Check pretty printing
+
+    BOOST_CHECK_EQUAL(std::string(val_zero), "0");
+    BOOST_CHECK_EQUAL(std::string(val_int), "12345");
+    BOOST_CHECK_EQUAL(std::string(val_long), "-2147483647");
+    BOOST_CHECK_EQUAL(val_zero.as<std::string>(), "0");
+    BOOST_CHECK_EQUAL(val_int.as<std::string>(), "12345");
+    BOOST_CHECK_EQUAL(val_long.as<std::string>(), "-2147483647");
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl(val_int.as<ValueList>());
+    BOOST_CHECK_EQUAL(vl.size(), 1);
+    BOOST_CHECK_EQUAL(vl[0].as<long long>(), 12345);
+
+    // And the conversions to Length/Offset, oooer.
+    // It would be nicer if these didn't work...
+
+    Length len = val_int; // Avoid ambiguities. Gah.
+    Offset off = val_int;
+    BOOST_CHECK_EQUAL(len, Length(12345));
+    BOOST_CHECK_EQUAL(off, Offset(12345));
+
+    // And the invalid conversions
+
+    BOOST_CHECK_THROW(val_int.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val_int.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val_int.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val_int.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_unsigned_overflow ) {
+    // Internally a Value(unsigned long long) is stored as a long long, as with all the other integer types. This should
+    // give very predictable overflow behaviour
+
+    Value val_max(9223372036854775807);
+    Value val_min(-9223372036854775807);
+    Value val_overflow(9223372036854775808U);
+
+    BOOST_CHECK_EQUAL((long long)val_max, 9223372036854775807);
+    BOOST_CHECK_EQUAL((long long)val_min, -9223372036854775807);
+    BOOST_CHECK((unsigned long long)(val_min) != 9223372036854775808U);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_type ) {
+    Value val_int(12345);
+    Value val_long(2147483647);
+    Value val_longlong(-9223372036854775807);
+
+    BOOST_CHECK(val_int.isNumber());
+    BOOST_CHECK(val_long.isNumber());
+    BOOST_CHECK(val_longlong.isNumber());
+
+    BOOST_CHECK(!val_int.isNil());
+    BOOST_CHECK(!val_int.isBool());
+    BOOST_CHECK(!val_int.isDouble());
+    BOOST_CHECK(!val_int.isString());
+    BOOST_CHECK(!val_int.isList());
+    BOOST_CHECK(!val_int.isMap());
+    BOOST_CHECK(!val_int.isDate());
+    BOOST_CHECK(!val_int.isTime());
+    BOOST_CHECK(!val_int.isDateTime());
+
+    BOOST_CHECK(!val_long.isNil());
+    BOOST_CHECK(!val_long.isBool());
+    BOOST_CHECK(!val_long.isDouble());
+    BOOST_CHECK(!val_long.isString());
+    BOOST_CHECK(!val_long.isList());
+    BOOST_CHECK(!val_long.isMap());
+    BOOST_CHECK(!val_long.isDate());
+    BOOST_CHECK(!val_long.isTime());
+    BOOST_CHECK(!val_long.isDateTime());
+
+    BOOST_CHECK(!val_longlong.isNil());
+    BOOST_CHECK(!val_longlong.isBool());
+    BOOST_CHECK(!val_longlong.isDouble());
+    BOOST_CHECK(!val_longlong.isString());
+    BOOST_CHECK(!val_longlong.isList());
+    BOOST_CHECK(!val_longlong.isMap());
+    BOOST_CHECK(!val_longlong.isDate());
+    BOOST_CHECK(!val_longlong.isTime());
+    BOOST_CHECK(!val_longlong.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_comparisons ) {
+    Value val1(1234);
+    Value val2(1234);
+    Value val3(4321);
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+
+    BOOST_CHECK(val1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val2) == 0);
+    BOOST_CHECK(val2.compare(val1) == 0);
+
+    BOOST_CHECK(val1.compare(val3) == -1);
+    BOOST_CHECK(val3.compare(val1) == 1);
+
+    // Check comparisons with floating point values ... these get checked by value
+    Value val_f1(1234.0);
+    Value val_f2(2222.0);
+
+    BOOST_CHECK(val_f1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val_f1) == 0);
+
+    BOOST_CHECK(val1.compare(val_f2) == -1);
+    BOOST_CHECK(val3.compare(val_f2) == 1);
+    BOOST_CHECK(val_f2.compare(val1) == 1);
+    BOOST_CHECK(val_f2.compare(val3) == -1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value("test str")) > 0);
+    BOOST_CHECK(val1.compare(Value(std::string("testing string"))) > 0);
+    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
+    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
+    BOOST_CHECK(val1.compare(ValueList()) > 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value("test str").compare(val1) < 0);
+    BOOST_CHECK(Value(std::string("testing string")).compare(val1) < 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
+    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
+    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_index_operator ) {
+    // No indexing operations should work on an integer...
+
+    Value val(1234);
+
+    BOOST_CHECK_THROW(val["idx"], BadOperator);
+    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val[123], BadOperator);
+    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_add_operator ) {
+    Value val(123);
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAdd(val, 1234).as<long long>(), 1357);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAdd(1234, val).as<long long>(), 1357);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAddSelf(val, 1234).as<long long>(), 1357);;
+    val = Value(123);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_subtract_operator ) {
+    Value val(123);
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueSub(val, 1234).as<long long>(), -1111);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_EQUAL(ValueSub(1234, val).as<long long>(), 1111);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueSubSelf(val, 1234).as<long long>(), -1111);
+    val = Value(123);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_multiply_operator ) {
+    Value val(123);
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueMul(val, 1234).as<long long>(), 151782);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_EQUAL(ValueMul(1234, val).as<long long>(), 151782);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueMulSelf(val, 1234).as<long long>(), 151782);
+    val = Value(123);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_divide_operator ) {
+    Value val(1476);
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueDiv(val, 12).as<long long>(), 123);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_EQUAL(ValueDiv(12, val).as<long long>(), 0);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_EQUAL(ValueDivSelf(val, 12).as<long long>(), 123);
+    val = Value(1476);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_modulo_operator ) {
+    Value val(123);
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_integer_head_tail ) {
+    Value val(12345);
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of doubles
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_cast ) {
+    Value val_zero(0.0);
+    Value val_double(99999999999999999999999999999.9);
+
+    // Double conversions
+
+    BOOST_CHECK_CLOSE(val_zero.as<double>(), 0.0, 1.0e-10);
+    BOOST_CHECK_CLOSE(val_double.as<double>(), 99999999999999999999999999999.9, 1.0e-10);
+
+    BOOST_CHECK_CLOSE(double(val_zero), 0.0, 1.0e-10);
+    BOOST_CHECK_CLOSE(double(val_double), 99999999999999999999999999999.9, 1.0e-10);
+
+    // Check pretty printing
+    /// @note rounding of values for pretty printing
+
+    BOOST_CHECK_EQUAL(std::string(val_zero), "0");
+    BOOST_CHECK_EQUAL(std::string(val_double), "1e+29");
+    BOOST_CHECK_EQUAL(val_zero.as<std::string>(), "0");
+    BOOST_CHECK_EQUAL(val_double.as<std::string>(), "1e+29");
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl(val_double.as<ValueList>());
+    BOOST_CHECK_EQUAL(vl.size(), 1);
+    BOOST_CHECK_CLOSE(vl[0].as<double>(), 99999999999999999999999999999.9, 1.0e-10);
+
+    BOOST_CHECK_THROW(val_double.as<bool>(), BadConversion);
+    BOOST_CHECK_THROW(val_double.as<long long>(), BadConversion);
+    BOOST_CHECK_THROW(val_double.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val_double.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val_double.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val_double.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_type ) {
+    Value val_double(-99999999999999999999999999999.9);
+
+    BOOST_CHECK(val_double.isDouble());
+
+    BOOST_CHECK(!val_double.isNil());
+    BOOST_CHECK(!val_double.isBool());
+    BOOST_CHECK(!val_double.isNumber());
+    BOOST_CHECK(!val_double.isString());
+    BOOST_CHECK(!val_double.isList());
+    BOOST_CHECK(!val_double.isMap());
+    BOOST_CHECK(!val_double.isDate());
+    BOOST_CHECK(!val_double.isTime());
+    BOOST_CHECK(!val_double.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_comparisons ) {
+    Value val1(1234.0);
+    Value val2(1234.0);
+    Value val3(4321.0);
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+
+    BOOST_CHECK(val1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val2) == 0);
+    BOOST_CHECK(val2.compare(val1) == 0);
+
+    BOOST_CHECK(val1.compare(val3) == -1);
+    BOOST_CHECK(val3.compare(val1) == 1);
+
+    // Check comparisons with integer values ... these get checked by value
+    Value val_i1(1234);
+    Value val_i2(2222);
+
+    BOOST_CHECK(val_i1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val_i1) == 0);
+
+    BOOST_CHECK(val1.compare(val_i2) == -1);
+    BOOST_CHECK(val3.compare(val_i2) == 1);
+    BOOST_CHECK(val_i2.compare(val1) == 1);
+    BOOST_CHECK(val_i2.compare(val3) == -1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value("test str")) > 0);
+    BOOST_CHECK(val1.compare(Value(std::string("testing string"))) > 0);
+    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
+    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
+    BOOST_CHECK(val1.compare(ValueList()) > 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value("test str").compare(val1) < 0);
+    BOOST_CHECK(Value(std::string("testing string")).compare(val1) < 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
+    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
+    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_index_operator ) {
+    // No indexing operations should work on a double...
+
+    Value val(1234.45);
+
+    BOOST_CHECK_THROW(val["idx"], BadOperator);
+    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val[123], BadOperator);
+    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_add_operator ) {
+    Value val(123.45);
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueAdd(val, 66.6).as<double>(), 190.05, 1.0e-10);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_CLOSE(ValueAdd(66.6, val).as<double>(), 190.05, 1.0e-10);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueAddSelf(val, 66.6).as<double>(), 190.05, 1.0e-10);
+    val = Value(123.45);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_subtract_operator ) {
+    Value val(123.45);
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueSub(val, 66.6).as<double>(), 56.85, 1.0e-10);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_CLOSE(ValueSub(66.6, val).as<double>(), -56.85, 1.0e-10);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueSubSelf(val, 66.6).as<double>(), 56.85, 1.0e-10);
+    val = Value(123.45);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_multiply_operator ) {
+    Value val(123.45);
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueMul(val, 66.6).as<double>(), 8221.77, 1.0e-10);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_CLOSE(ValueMul(66.6, val).as<double>(), 8221.77, 1.0e-10);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueMulSelf(val, 66.6).as<double>(), 8221.77, 1.0e-10);
+    val = Value(123.45);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_divide_operator ) {
+    Value val(123.45);
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueDiv(val, 66.6).as<double>(), 1.853603604, 1.0e-6);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_CLOSE(ValueDiv(66.6, val).as<double>(), 0.539489671, 1.0e-6);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_CLOSE(ValueDivSelf(val, 66.6).as<double>(), 1.853603604, 1.0e-6);
+    val = Value(123.45);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_modulo_operator ) {
+    Value val(123.45);
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_double_head_tail ) {
+    Value val(123.45);
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of strings
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_cast ) {
+    Value val_null("");
+    Value val_char("test string");
+    Value val_str(std::string("test string 2"));
+
+    // String conversion
+
+    BOOST_CHECK_EQUAL(std::string(val_null), "");
+    BOOST_CHECK_EQUAL(std::string(val_char), "test string");
+    BOOST_CHECK_EQUAL(std::string(val_str), "test string 2");
+
+    BOOST_CHECK_EQUAL(val_null.as<std::string>(), "");
+    BOOST_CHECK_EQUAL(val_char.as<std::string>(), "test string");
+    BOOST_CHECK_EQUAL(val_str.as<std::string>(), "test string 2");
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl(val_str.as<ValueList>());
+    BOOST_CHECK_EQUAL(vl.size(), 1);
+    BOOST_CHECK_EQUAL(vl[0].as<std::string>(), "test string 2");
+
+    // And the invalid conversions
+
+    BOOST_CHECK_THROW(val_str.as<bool>(), BadConversion);
+    /// BOOST_CHECK_THROW(val_str.as<long long>(), BadConversion); // This will return zero, not throw
+    BOOST_CHECK_THROW(val_str.as<double>(), BadParameter); // n.b. BadParameter, not BadConversion
+    BOOST_CHECK_THROW(val_str.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val_str.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val_str.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val_str.as<ValueMap>(), BadConversion);
+
+    BOOST_CHECK_THROW(val_null.as<bool>(), BadConversion);
+    /// BOOST_CHECK_THROW(val_null.as<long long>(), BadConversion); // This will return zero, not throw
+    BOOST_CHECK_THROW(val_null.as<double>(), BadParameter); // n.b. BadParameter, not BadConversion`
+    BOOST_CHECK_THROW(val_null.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val_null.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val_null.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val_null.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_cast_bool ) {
+    // Boolean casting for Value(StringContent) types is a bit complicated, as it allows strings to be used to
+    // represent truthy values, but nothing else
+
+    Value val_true1("true");
+    Value val_true2("on");
+    Value val_true3("yes");
+    Value val_true4("1");
+
+    BOOST_CHECK(bool(val_true1));
+    BOOST_CHECK(bool(val_true2));
+    BOOST_CHECK(bool(val_true3));
+    BOOST_CHECK(bool(val_true4));
+
+    BOOST_CHECK(val_true1.as<bool>());
+    BOOST_CHECK(val_true2.as<bool>());
+    BOOST_CHECK(val_true3.as<bool>());
+    BOOST_CHECK(val_true4.as<bool>());
+
+    Value val_false1("false");
+    Value val_false2("off");
+    Value val_false3("no");
+    Value val_false4("0");
+
+    BOOST_CHECK(!bool(val_false1));
+    BOOST_CHECK(!bool(val_false2));
+    BOOST_CHECK(!bool(val_false3));
+    BOOST_CHECK(!bool(val_false4));
+
+    BOOST_CHECK(!val_false1.as<bool>());
+    BOOST_CHECK(!val_false2.as<bool>());
+    BOOST_CHECK(!val_false3.as<bool>());
+    BOOST_CHECK(!val_false4.as<bool>());
+
+    Value val_other("other");
+
+    BOOST_CHECK_THROW(val_other.as<bool>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_vaule_string_cast_numbers ) {
+    Value val_double("123.45");
+    Value val_int("12345");
+    Value val_other("string");
+
+    // Test conversions to integers
+
+    BOOST_CHECK_EQUAL((int)(val_double), 123);
+    BOOST_CHECK_EQUAL((int)(val_int), 12345);
+
+    BOOST_CHECK_EQUAL(val_double.as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val_int.as<long long>(), 12345);
+
+    /// Integer conversion returns zero, rather than throwing, on no matching input
+    /// BOOST_CHECK_THROW(val_other.as<long long>(), std::exception);
+    BOOST_CHECK_EQUAL(val_other.as<long long>(), 0);
+
+    // Test conversions to doubles
+
+    BOOST_CHECK_CLOSE((double)(val_double), 123.45, 1.0e-10);
+    BOOST_CHECK_CLOSE((double)(val_int), 12345.0, 1.0e-10);
+
+    BOOST_CHECK_CLOSE(val_double.as<double>(), 123.45, 1.0e-10);
+    BOOST_CHECK_CLOSE(val_int.as<double>(), 12345.0, 1.0e-10);
+    BOOST_CHECK_THROW(val_other.as<double>(), BadParameter);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_type ) {
+    Value val_null("");
+    Value val_str("This is a test string");
+
+    BOOST_CHECK(val_null.isString());
+    BOOST_CHECK(val_str.isString());
+
+    BOOST_CHECK(!val_null.isNil());
+    BOOST_CHECK(!val_null.isBool());
+    BOOST_CHECK(!val_null.isNumber());
+    BOOST_CHECK(!val_null.isDouble());
+    BOOST_CHECK(!val_null.isList());
+    BOOST_CHECK(!val_null.isMap());
+    BOOST_CHECK(!val_null.isDate());
+    BOOST_CHECK(!val_null.isTime());
+    BOOST_CHECK(!val_null.isDateTime());
+
+    BOOST_CHECK(!val_str.isNil());
+    BOOST_CHECK(!val_str.isBool());
+    BOOST_CHECK(!val_str.isNumber());
+    BOOST_CHECK(!val_str.isDouble());
+    BOOST_CHECK(!val_str.isList());
+    BOOST_CHECK(!val_str.isMap());
+    BOOST_CHECK(!val_str.isDate());
+    BOOST_CHECK(!val_str.isTime());
+    BOOST_CHECK(!val_str.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_comparisons ) {
+    Value val1("a");
+    Value val2("a");
+    Value val3("b");
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+    // Comparison makes use of strcmp
+
+    BOOST_CHECK(val1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val2) == 0);
+    BOOST_CHECK(val2.compare(val1) == 0);
+
+    BOOST_CHECK(val1.compare(val3) == -1);
+    BOOST_CHECK(val3.compare(val1) == 1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value(123)) < 0);
+    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
+    BOOST_CHECK(val1.compare(Value(ValueMap())) > 0);
+    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
+    BOOST_CHECK(val1.compare(ValueList()) > 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value(123).compare(val1) > 0);
+    BOOST_CHECK(Value(123.45).compare(val1) > 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
+    BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
+    BOOST_CHECK(Value(ValueList()).compare(val1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_index_operator ) {
+    // No indexing operations should work on a string...
+
+    Value val_char("test string 1");
+    Value val_str(std::string("test string 2"));
+
+    BOOST_CHECK_THROW(val_char["idx"], BadOperator);
+    BOOST_CHECK_THROW(val_char[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val_char[123], BadOperator);
+    BOOST_CHECK_THROW(val_char[Value(123)], BadOperator);
+
+    BOOST_CHECK_THROW(val_str["idx"], BadOperator);
+    BOOST_CHECK_THROW(val_str[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val_str[123], BadOperator);
+    BOOST_CHECK_THROW(val_str[Value(123)], BadOperator);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK_THROW(val_char.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val_char.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val_char.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val_char.contains(Value(123)), BadOperator);
+
+    BOOST_CHECK_THROW(val_str.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val_str.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val_str.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val_str.contains(Value(123)), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_add_operator ) {
+    Value val("test string");
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAdd(val, "hi").as<std::string>(), "test stringhi");
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAdd("hi", val), "hitest string");
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_EQUAL(ValueAddSelf(val, "hi").as<std::string>(), "test stringhi");
+    val = Value("test string");
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_subtract_operator ) {
+    Value val("test string");
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_multiply_operator ) {
+    Value val("test string");
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_divide_operator ) {
+    Value val("test string");
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_modulo_operator ) {
+    Value val("test string");
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_string_head_tail ) {
+    Value val("this is a test string");
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of ValueMaps
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_cast ) {
+    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueMap vm;
+    vm[123] = 123;
+    vm["abc"] = "abc";
+    vm[Value(123.45)] = 123.45;
+    vm[Value(true)] = false;
+
+    Value val(vm);
+
+    // Extract the ValueMap
+    // n.b. We cannot compare eqality of ValueMaps, as the internal Values have been copied, and as a result the
+    //      operator== will return false, as it depends only on the memory address of the internal Content.
+
+    BOOST_CHECK_EQUAL(((ValueMap)val)[123].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val.as<ValueMap>()[123].as<long long>(), 123);
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl(val.as<ValueList>());
+    BOOST_CHECK_EQUAL(vl.size(), 1);
+    BOOST_CHECK_EQUAL(vl[0].as<ValueMap>()[123].as<long long>(), 123);
+
+    // And the invalid conversions
+
+    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_type ) {
+    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueMap vm;
+    vm[123] = 123;
+    vm["abc"] = "abc";
+    vm[Value(123.45)] = 123.45;
+    vm[Value(true)] = false;
+
+    Value val(vm);
+
+    BOOST_CHECK(val.isMap());
+
+    BOOST_CHECK(!val.isNil());
+    BOOST_CHECK(!val.isBool());
+    BOOST_CHECK(!val.isNumber());
+    BOOST_CHECK(!val.isDouble());
+    BOOST_CHECK(!val.isString());
+    BOOST_CHECK(!val.isList());
+    BOOST_CHECK(!val.isDate());
+    BOOST_CHECK(!val.isTime());
+    BOOST_CHECK(!val.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_comparisons ) {
+    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueMap vm;
+    vm[123] = 123;
+
+    ValueMap vm2;
+    vm2["abc"] = "abc";
+
+    Value val1(vm);
+    Value val2(vm);
+    Value val3(vm2);
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+    // Comparison makes use of strcmp
+
+    BOOST_CHECK(val1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val2) == 0);
+    BOOST_CHECK(val2.compare(val1) == 0);
+
+    BOOST_CHECK(val1.compare(val3) == 1);
+    BOOST_CHECK(val3.compare(val1) == -1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value(123)) < 0);
+    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
+    BOOST_CHECK(val1.compare(Value(std::string("test string"))) < 0);
+    BOOST_CHECK(val1.compare(ValueList()) < 0);
+    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value(123).compare(val1) > 0);
+    BOOST_CHECK(Value(123.45).compare(val1) > 0);
+    BOOST_CHECK(Value(std::string("test string")).compare(val1) > 0);
+    BOOST_CHECK(Value(ValueList()).compare(val1) > 0);
+
+    /// This is currently correct in MapContent.h
+    /// BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_index_operator ) {
+    // A ValueMap is just a std::map<Value, Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueMap vm;
+    vm[123] = 456;
+    vm["abc"] = "def";
+    vm[Value(123.45)] = 543.21;
+    vm[Value(true)] = false;
+
+    Value val(vm);
+
+    // Check with existent keys of the various types
+
+    BOOST_CHECK_EQUAL(val[123].as<long long>(), 456);
+    BOOST_CHECK_EQUAL(val["abc"].as<std::string>(), "def");
+    BOOST_CHECK_EQUAL(val[std::string("abc")].as<std::string>(), "def");
+
+    /// None of these seem to work with boolean indices
+    /// BOOST_CHECK_EQUAL(val[true].as<bool>(), false);
+
+    BOOST_CHECK_EQUAL(val[Value(123)].as<long long>(), 456);
+    BOOST_CHECK_EQUAL(val[Value("abc")].as<std::string>(), "def");
+    BOOST_CHECK_EQUAL(val[Value(std::string("abc"))].as<std::string>(), "def");
+    BOOST_CHECK_CLOSE(val[Value(123.45)].as<double>(), 543.21, 1.0e-10);
+
+    /// Indexing by Value(bool) doesn't seem to work
+    /// BOOST_CHECK_EQUAL(val[Value(true)].as<bool>(), false);
+
+    // And with values that don't exist
+
+    /// This code should not work!!! const has gone screwey
+    ValueMap vm2;
+    const Value cv(vm2);
+    cv[10];
+    Log::info() << cv << std::endl;
+
+    /// BOOST_CHECK(!cv.contains(10));
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK(val.contains(123));
+    BOOST_CHECK(val.contains("abc"));
+    BOOST_CHECK(val.contains(std::string("abc")));
+    BOOST_CHECK(val.contains(Value(123.45)));
+    /// BOOST_CHECK(val.contains(Value(true)));
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_add_operator ) {
+    // There are no valid ValueMap addition operations.
+
+    ValueMap vm;
+    Value val(vm);
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_subtract_operator ) {
+    // There are no valid ValueMap subtraction operations.
+
+    ValueMap vm;
+    Value val(vm);
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_multiply_operator ) {
+    // There are no valid ValueMap multiplication operations.
+
+    ValueMap vm;
+    Value val(vm);
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_divide_operator ) {
+    // There are no valid ValueMap division operations.
+
+    ValueMap vm;
+    Value val(vm);
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_modulo_operator ) {
+    // There are no valid ValueMap modulo operations.
+
+    ValueMap vm;
+    Value val(vm);
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_map_head_tail ) {
+    ValueMap vm;
+    vm[123] = 456;
+
+    Value val(vm);
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of ValueMaps
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_cast ) {
+    // A ValueMap is just a std::list<Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    vl.push_back(1234.56);
+    vl.push_back(false);
+
+    Value val(vl);
+
+    // Extract the ValueList
+    // n.b. We cannot compare eqality of ValueLists, as the internal Values have been copied, and as a result the
+    //      operator== will return false, as it depends only on the memory address of the internal Content.
+
+    ValueList casted_vl = val;
+    BOOST_CHECK_EQUAL(casted_vl[0].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val.as<ValueList>()[0].as<long long>(), 123);
+
+    // And the invalid conversions
+
+    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<Date>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_type ) {
+    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    vl.push_back(1234.56);
+    vl.push_back(false);
+
+    Value val(vl);
+
+    BOOST_CHECK(val.isList());
+
+    BOOST_CHECK(!val.isNil());
+    BOOST_CHECK(!val.isBool());
+    BOOST_CHECK(!val.isNumber());
+    BOOST_CHECK(!val.isDouble());
+    BOOST_CHECK(!val.isString());
+    BOOST_CHECK(!val.isMap());
+    BOOST_CHECK(!val.isDate());
+    BOOST_CHECK(!val.isTime());
+    BOOST_CHECK(!val.isDateTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_comparisons ) {
+    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueList vl;
+    vl.push_back(123);
+
+    ValueList vl2;
+    vl2.push_back(321);
+
+    Value val1(vl);
+    Value val2(vl);
+    Value val3(vl2);
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+    // Comparison makes use of strcmp
+
+    BOOST_CHECK(val1.compare(val1) == 0);
+    BOOST_CHECK(val1.compare(val2) == 0);
+    BOOST_CHECK(val2.compare(val1) == 0);
+
+    BOOST_CHECK(val1.compare(val3) == -1);
+    BOOST_CHECK(val3.compare(val1) == 1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value(123)) < 0);
+    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
+    BOOST_CHECK(val1.compare(Value(std::string("test string"))) < 0);
+    BOOST_CHECK(val1.compare(ValueMap()) > 0);
+    BOOST_CHECK(val1.compare(Value(Date(2016, 3, 30))) > 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value(123).compare(val1) > 0);
+    BOOST_CHECK(Value(123.45).compare(val1) > 0);
+    BOOST_CHECK(Value(std::string("test string")).compare(val1) > 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val1) < 0);
+
+    /// This is currently correct in MapContent.h
+    /// BOOST_CHECK(Value(Date(2016, 3, 30)).compare(val1) < 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_index_operator ) {
+    // A ValueList is just a std::list<Value>. No point in testing the functionality of stl. Just test what
+    // it does when wrapped.
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    vl.push_back(1234.56);
+    vl.push_back(false);
+
+    Value val(vl);
+
+    // Check with existent keys of the various types
+
+    BOOST_CHECK_EQUAL(val[0].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val[1].as<std::string>(), "abc");
+    BOOST_CHECK_CLOSE(val[2].as<double>(), 1234.56, 1.0e-10);
+    BOOST_CHECK_EQUAL(val[3].as<bool>(), false);
+
+    BOOST_CHECK_EQUAL(int(val[Value(0)]), 123);
+    BOOST_CHECK_EQUAL(std::string(val[Value(1)]), "abc");
+    BOOST_CHECK_CLOSE(double(val[Value(2)]), 1234.56, 1.0e-10);
+    BOOST_CHECK_EQUAL(bool(val[Value(3)]), false);
+
+    // And with values that don't exist
+
+    BOOST_CHECK_THROW(val[-1], AssertionFailed);
+    BOOST_CHECK_THROW(val[4], AssertionFailed);
+    BOOST_CHECK_THROW(val[Value(-1)], AssertionFailed);
+    BOOST_CHECK_THROW(val[Value(4)], AssertionFailed);
+
+    /// Value(std::string) silently casts to 0, which means this returns val[0] spuriously
+    /// BOOST_CHECK_THROW(val["hello"], AssertionFailed);
+    /// BOOST_CHECK_THROW(val[std::string("hello")], AssertionFailed);
+    /// BOOST_CHECK_THROW(val[Value("hello")], AssertionFailed);
+
+    // Value(bool) automagically converts to a long, so these return elements 1, 0 respectively...
+    // BOOST_CHECK_THROW(val[Value(true)], BadConversion);
+    // BOOST_CHECK_THROW(val[Value(false)], BadConversion);
+
+    BOOST_CHECK_THROW(val[Value(666.66)], BadConversion);
+    BOOST_CHECK_THROW(val[Value(ValueList())], BadConversion);
+    BOOST_CHECK_THROW(val[Value(ValueMap())], BadConversion);
+    BOOST_CHECK_THROW(val[Value(Date(2016, 3, 31))], BadConversion);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK(!val.contains(-1));
+    BOOST_CHECK(val.contains(0));
+    BOOST_CHECK(val.contains(1));
+    BOOST_CHECK(val.contains(2));
+    BOOST_CHECK(val.contains(3));
+    BOOST_CHECK(!val.contains(4));
+
+    BOOST_CHECK(!val.contains(Value(-1)));
+    BOOST_CHECK(val.contains(Value(0)));
+    BOOST_CHECK(val.contains(Value(1)));
+    BOOST_CHECK(val.contains(Value(2)));
+    BOOST_CHECK(val.contains(Value(3)));
+    BOOST_CHECK(!val.contains(Value(4)));
+
+    /// Same oddities as above...
+    /// BOOST_CHECK(!val.contains("hello"));
+    /// BOOST_CHECK(!val.contains(std::string("hello")));
+    /// BOOST_CHECK(!val.contains(Value("hello")));
+
+    BOOST_CHECK_THROW(val.contains(Value(666.66)), BadConversion);
+    BOOST_CHECK_THROW(val.contains(Value(ValueList())), BadConversion);
+    BOOST_CHECK_THROW(val.contains(Value(ValueMap())), BadConversion);
+    BOOST_CHECK_THROW(val.contains(Value(Date(2016, 3, 31))), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_add_operator ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    Value val(vl);
+
+    ValueList vl2;
+    vl2.push_back(true);
+    vl2.push_back(Date(2016, 3, 31));
+    Value val2(vl2);
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+
+    Value tmp1 = val + val2;
+    BOOST_CHECK_EQUAL(tmp1.as<ValueList>().size(), 4);
+    BOOST_CHECK_EQUAL(tmp1[0].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(tmp1[1].as<std::string>(), "abc");
+    BOOST_CHECK_EQUAL(tmp1[2].as<bool>(), true);
+    BOOST_CHECK_EQUAL(tmp1[3].as<Date>(), Date(2016, 3, 31));
+
+    Value tmp2 = val2 + val;
+    BOOST_CHECK_EQUAL(tmp2.as<ValueList>().size(), 4);
+    BOOST_CHECK_EQUAL(tmp2[0].as<bool>(), true);
+    BOOST_CHECK_EQUAL(tmp2[1].as<Date>(), Date(2016, 3, 31));
+    BOOST_CHECK_EQUAL(tmp2[2].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(tmp2[3].as<std::string>(), "abc");
+
+    val += val2;
+    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 4);
+    BOOST_CHECK_EQUAL(val[0].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val[1].as<std::string>(), "abc");
+    BOOST_CHECK_EQUAL(val[2].as<bool>(), true);
+    BOOST_CHECK_EQUAL(val[3].as<Date>(), Date(2016, 3, 31));
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_subtract_operator ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    Value val(vl);
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_multiply_operator ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    Value val(vl);
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_divide_operator ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    Value val(vl);
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_modulo_operator ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    Value val(vl);
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_list_head_tail ) {
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back(666.66);
+    vl.push_back(true);
+    vl.push_back("test str");
+
+    Value val(vl);
+
+    Log::info() << "H" << val << " - " << val.head() << std::endl;
+    BOOST_CHECK_EQUAL(val.head().as<long long>(), 123);
+    Log::info() << "T" << val << " - " << val.tail() << std::endl;
+    /// BOOST_CHECK_EQUAL(val.tail().as<std::string>(), "test str");
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test the behaviour of Dates
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_cast ) {
+    Value val(Date(2016, 3, 31));
+
+    //
+    // Access and conversion
+    //
+
+    Date tmp = val;
+    BOOST_CHECK_EQUAL(tmp, Date(2016, 3, 31));
+    BOOST_CHECK_EQUAL(val.as<Date>(), Date(2016, 3, 31));
+
+    // ValueList is a bit of an odd one --> it just puts the value in a list of one element...
+
+    ValueList vl = val;
+    BOOST_CHECK_EQUAL(vl.size(), 1);
+    BOOST_CHECK_EQUAL(vl[0].as<Date>(), Date(2016, 3, 31));
+
+    // And all the invalid conversions
+
+    BOOST_CHECK_THROW(val.as<bool>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<double>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<long long>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<std::string>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<Time>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<DateTime>(), BadConversion);
+    BOOST_CHECK_THROW(val.as<ValueMap>(), BadConversion);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_type ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK(val.isDate());
+
+    BOOST_CHECK(!val.isNil());
+    BOOST_CHECK(!val.isBool());
+    BOOST_CHECK(!val.isNumber());
+    BOOST_CHECK(!val.isDouble());
+    BOOST_CHECK(!val.isString());
+    BOOST_CHECK(!val.isList());
+    BOOST_CHECK(!val.isMap());
+    BOOST_CHECK(!val.isDateTime());
+    BOOST_CHECK(!val.isTime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_comparisons ) {
+    Value val1(Date(2016, 3, 31));
+    Value val2(Date(2016, 3, 31));
+    Value val3(Date(2016, 4, 30));
+
+    // n.b. These comparisons are designed to define a well defined order between different data types
+    // bool [false < true] > number > string > nil > list > map > Date > Time > DateTime
+
+    // Check comparisons with same type of data
+    // Comparison makes use of strcmp
+
+    /// Value(Date) compare function is rather broken...
+    /// BOOST_CHECK(val1.compare(val1) == 0);
+    /// BOOST_CHECK(val1.compare(val2) == 0);
+    /// BOOST_CHECK(val2.compare(val1) == 0);
+
+    /// BOOST_CHECK(val1.compare(val3) == -1);
+    BOOST_CHECK(val3.compare(val1) == 1);
+
+    // Check comparisons with other types of data.
+
+    BOOST_CHECK(val1.compare(Value(true)) < 0);
+    BOOST_CHECK(val1.compare(Value(123)) < 0);
+    BOOST_CHECK(val1.compare(Value(123.45)) < 0);
+    BOOST_CHECK(val1.compare(Value("testing")) < 0);
+    /// There is a bug in the ValueMap implementation, so this would fail
+    /// BOOST_CHECK(val1.compare(Value(ValueMap())) < 0);
+    BOOST_CHECK(val1.compare(ValueList()) < 0);
+
+    BOOST_CHECK(Value(true).compare(val1) > 0);
+    BOOST_CHECK(Value(123).compare(val1) > 0);
+    BOOST_CHECK(Value(123.45).compare(val1) > 0);
+    BOOST_CHECK(Value("testing").compare(val1) > 0);
+    BOOST_CHECK(Value(ValueMap()).compare(val1) > 0);
+    BOOST_CHECK(Value(ValueList()).compare(val1) > 0);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_index_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(val["idx"], BadOperator);
+    BOOST_CHECK_THROW(val[std::string("idx")], BadOperator);
+    BOOST_CHECK_THROW(val[123], BadOperator);
+    BOOST_CHECK_THROW(val[Value(123)], BadOperator);
+
+    // Test the matching contains() function too
+
+    BOOST_CHECK_THROW(val.contains("idx"), BadOperator);
+    BOOST_CHECK_THROW(val.contains(std::string("idx")), BadOperator);
+    BOOST_CHECK_THROW(val.contains(123), BadOperator);
+    BOOST_CHECK_THROW(val.contains(Value(123)), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_add_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(ValueAdd(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAdd(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueAdd(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueAddSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, Date(2016, 3, 31)), BadOperator);
+    val = Date(2016, 3, 31);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueAddSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_subtract_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(ValueSub(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, "hi"), BadOperator);
+    /// The sign of the following test is wrong. SHOULD be +2
+    BOOST_CHECK_EQUAL(ValueSub(val, Date(2016, 3, 29)).as<long long>(), -2);
+    BOOST_CHECK_THROW(ValueSub(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSub(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub("hi", val), BadOperator);
+    /// The sign of the following test is wrong. SHOULD be -2
+    BOOST_CHECK_EQUAL(ValueSub(Date(2016, 3, 29), val).as<long long>(), 2);
+    BOOST_CHECK_THROW(ValueSub(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueSub(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueSubSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, "hi"), BadOperator);
+    /// The sign of the following test is wrong. SHOULD be +2
+    BOOST_CHECK_EQUAL(ValueSubSelf(val, Date(2016, 3, 29)).as<long long>(), -2);
+    val = Date(2016, 3, 31);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueSubSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_multiply_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(ValueMul(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMul(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMul(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMulSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMulSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_divide_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(ValueDiv(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDiv(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueDiv(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueDivSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueDivSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_modulo_operator ) {
+    Value val(Date(2016, 3, 31));
+
+    BOOST_CHECK_THROW(ValueMod(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(val, ValueMap()), BadOperator);
+
+    BOOST_CHECK_THROW(ValueMod(true, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(1234, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(66.6, val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod("hi", val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(Date(2016, 3, 31), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueList(), val), BadOperator);
+    BOOST_CHECK_THROW(ValueMod(ValueMap(), val), BadOperator);
+
+    BOOST_CHECK_THROW(ValueModSelf(val, true), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 1234), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, 66.6), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, "hi"), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, Date(2016, 3, 31)), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueList()), BadOperator);
+    BOOST_CHECK_THROW(ValueModSelf(val, ValueMap()), BadOperator);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_date_head_tail ) {
+    Value val(Date(2016, 3, 31));
+
+    /// BOOST_CHECK_THROW(val.head(), AssertationError);
+    /// BOOST_CHECK_THROW(val.tail(), AssertationError);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//
+// Test list/map helper functions
+//
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_makelist ) {
+    // Test the trivial version
+
+    Value val1 = Value::makeList();
+
+    BOOST_CHECK(val1.isList());
+    BOOST_CHECK_EQUAL(val1.as<ValueList>().size(), 0);
+
+    // Can we wrap an arbitrary ValueList?
+
+    ValueList vl;
+    vl.push_back(123);
+    vl.push_back("abc");
+    vl.push_back(1234.56);
+    vl.push_back(false);
+
+    Value val2 = Value::makeList(vl);
+
+    BOOST_CHECK(val2.isList());
+
+    BOOST_CHECK_EQUAL(val2.as<ValueList>().size(), 4);
+    BOOST_CHECK_EQUAL(val2[0].as<long long>(), 123);
+    BOOST_CHECK_EQUAL(val2[1].as<std::string>(), "abc");
+    BOOST_CHECK_CLOSE(val2[2].as<double>(), 1234.56, 1.0e-10);
+    BOOST_CHECK_EQUAL(val2[3].as<bool>(), false);
+
+    // Applied to a value, it puts the element in first
+
+    Value val3 = Value::makeList(val2);
+
+    BOOST_CHECK(val3.isList());
+
+    BOOST_CHECK_EQUAL(val3.as<ValueList>().size(), 1);
+    BOOST_CHECK(val3[0].isList());
+    BOOST_CHECK_EQUAL(val3[0].as<ValueList>()[0].as<long long>(), 123);
+
+    // This should work with all the things that can cast into values
+
+    Value val4 = Value::makeList(1234);
+
+    BOOST_CHECK(val4.isList());
+    BOOST_CHECK_EQUAL(val4.as<ValueList>().size(), 1);
+    BOOST_CHECK_EQUAL(val4[0].as<long long>(), 1234);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_makemap ) {
+    // Test the trivial version
+
+    Value val1 = Value::makeMap();
+
+    BOOST_CHECK(val1.isMap());
+    BOOST_CHECK_EQUAL(val1.as<ValueMap>().size(), 0);
+
+    // Can we wrap an arbitrary ValueMap?
+
+    ValueMap vm;
+    vm[123] = 456;
+    vm["abc"] = "def";
+    vm[1234.56] = 666.66;
+    vm[true] = false;
+
+    Value val2 = Value::makeMap(vm);
+
+    BOOST_CHECK(val2.isMap());
+
+    BOOST_CHECK_EQUAL(val2.as<ValueMap>().size(), 4);
+    BOOST_CHECK_EQUAL(val2[123].as<long long>(), 456);
+    BOOST_CHECK_EQUAL(val2["abc"].as<std::string>(), "def");
+    BOOST_CHECK_CLOSE(val2[Value(1234.56)].as<double>(), 666.66, 1.0e-10);
+    /// Cannot index using bools
+    /// BOOST_CHECK_EQUAL(val2[3].as<bool>(), false);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_makelist_vector ) {
+    // n.b. This is templated, so will work for a std::vector<T> for any T for which a Value can be constructed.
+
+    std::vector<int> vint;
+    for (int i = 99; i > 0; i -= 11)
+        vint.push_back(i);
+
+    Value val = toValue(vint);
+
+    BOOST_CHECK(val.isList());
+    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 9);
+    BOOST_CHECK_EQUAL(val[4].as<long long>(), 55);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_makelist_list ) {
+    // n.b. This is templated, so will work for a std::list<T> for any T for which a Value can be constructed.
+
+    std::list<int> lint;
+    for (int i = 99; i > 0; i -= 11)
+        lint.push_back(i);
+
+    Value val = toValue(lint);
+
+    BOOST_CHECK(val.isList());
+    BOOST_CHECK_EQUAL(val.as<ValueList>().size(), 9);
+    BOOST_CHECK_EQUAL(val[4].as<long long>(), 55);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_CASE( test_eckit_value_wrapper_types ) {
+    // There are some constructors that have been added for easy conversion, that aren't actually part of the
+    // internal interface
+
+    // Length type
+
+    Value val_length(Length(12345));
+
+    BOOST_CHECK(val_length.isNumber());
+
+    BOOST_CHECK(!val_length.isNil());
+    BOOST_CHECK(!val_length.isBool());
+    BOOST_CHECK(!val_length.isDouble());
+    BOOST_CHECK(!val_length.isString());
+    BOOST_CHECK(!val_length.isList());
+    BOOST_CHECK(!val_length.isMap());
+    BOOST_CHECK(!val_length.isDate());
+    BOOST_CHECK(!val_length.isTime());
+    BOOST_CHECK(!val_length.isDateTime());
+
+    BOOST_CHECK_EQUAL(int(val_length), 12345);
+    BOOST_CHECK_EQUAL(val_length.as<long long>(), 12345);
+
+    // Offset type
+
+    Value val_offset(Offset(54321));
+
+    BOOST_CHECK(val_offset.isNumber());
+
+    BOOST_CHECK(!val_offset.isNil());
+    BOOST_CHECK(!val_offset.isBool());
+    BOOST_CHECK(!val_offset.isDouble());
+    BOOST_CHECK(!val_offset.isString());
+    BOOST_CHECK(!val_offset.isList());
+    BOOST_CHECK(!val_offset.isMap());
+    BOOST_CHECK(!val_offset.isDate());
+    BOOST_CHECK(!val_offset.isTime());
+    BOOST_CHECK(!val_offset.isDateTime());
+
+    BOOST_CHECK_EQUAL(int(val_offset), 54321);
+    BOOST_CHECK_EQUAL(val_offset.as<long long>(), 54321);
+
+    // PathName type
+
+    Value val_pathname(PathName("/usr/bin"));
+
+    BOOST_CHECK(val_pathname.isString());
+
+    BOOST_CHECK(!val_pathname.isNil());
+    BOOST_CHECK(!val_pathname.isBool());
+    BOOST_CHECK(!val_pathname.isDouble());
+    BOOST_CHECK(!val_pathname.isNumber());
+    BOOST_CHECK(!val_pathname.isList());
+    BOOST_CHECK(!val_pathname.isMap());
+    BOOST_CHECK(!val_pathname.isDate());
+    BOOST_CHECK(!val_pathname.isTime());
+    BOOST_CHECK(!val_pathname.isDateTime());
+
+    BOOST_CHECK_EQUAL(std::string(val_pathname), "/usr/bin");
+    BOOST_CHECK_EQUAL(val_pathname.as<std::string>(), "/usr/bin");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace test
+} // namespace eckit
diff --git a/eckit/src/tests/value/test_value_params.cc b/eckit/tests/value/test_value_params.cc
similarity index 100%
rename from eckit/src/tests/value/test_value_params.cc
rename to eckit/tests/value/test_value_params.cc
diff --git a/eckit/tests/value/test_value_properties.cc b/eckit/tests/value/test_value_properties.cc
new file mode 100644
index 0000000..8060ae5
--- /dev/null
+++ b/eckit/tests/value/test_value_properties.cc
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#define BOOST_TEST_MODULE test_eckit_value_properties
+
+#include <limits>
+
+#include "ecbuild/boost_test_framework.h"
+
+#include "eckit/filesystem/PathName.h"
+#include "eckit/io/Length.h"
+#include "eckit/serialisation/FileStream.h"
+#include "eckit/types/Date.h"
+#include "eckit/value/Properties.h"
+
+using namespace std;
+using namespace eckit;
+
+//-----------------------------------------------------------------------------
+
+namespace eckit_test {
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE( test_eckit_value_properties )
+
+BOOST_AUTO_TEST_CASE( test_serialize )
+{
+    BOOST_TEST_MESSAGE("(de)serialize Properties to/from file");
+    PathName filename = PathName::unique( "data" );
+    std::string filepath = filename.asString();
+    Properties p;
+    p.set("bool", true);
+    p.set("int", numeric_limits<int>::max());
+    p.set("unsigned int", numeric_limits<unsigned int>::max());
+    p.set("long long", numeric_limits<long long>::max());
+    p.set("unsigned long long", numeric_limits<unsigned long long>::max());
+    p.set("double", numeric_limits<double>::max());
+    p.set("string", "foo");
+    p.set("Length", Length(42));
+    p.set("Date", Date(2015, 2, 1));
+    // p.set("Time", Time(11, 59, 59));  <-- not implemented
+    // p.set("DateTime", DateTime(Date(1, 2, 2015), Time(11, 59, 59)));  <-- not implemented
+    p.set("PathName", PathName("/var/tmp"));
+    p.set("Vector", ValueList(5, "string"));
+    ValueMap m;
+    m.insert( std::make_pair("int", numeric_limits<int>::max()) );
+    m.insert( std::make_pair("unsigned int", numeric_limits<unsigned int>::max()) );
+    m.insert( std::make_pair("long long", numeric_limits<long long>::max()) );
+    m.insert( std::make_pair("unsigned long long", numeric_limits<unsigned long long>::max()) );
+    m.insert( std::make_pair("double", numeric_limits<double>::max()) );
+    m.insert( std::make_pair("string", "foo") );
+    m.insert( std::make_pair("Length", Length(42)) );
+    m.insert( std::make_pair("PathName", PathName("/var/tmp")) );
+    m.insert( std::make_pair("Vector", ValueList(5, "string")) );
+    p.set("Map", Value(m) );
+
+    Properties pm;
+    pm.set("int",numeric_limits<int>::max());
+    pm.set("unsigned int", numeric_limits<unsigned int>::max());
+    p.set("Nested", pm );
+
+    std::vector<Properties> property_list(2);
+    property_list[0].set("int",numeric_limits<int>::max());
+    property_list[1].set("string","foo");
+    p.set("list", toValue(property_list) );
+
+    BOOST_TEST_MESSAGE("encoded Properties: " << p);
+    {
+        FileStream sout( filepath.c_str(), "w" );
+        sout << p;
+    }
+    {
+        FileStream sin( filepath.c_str(), "r" );
+        Properties p2(sin);
+        BOOST_TEST_MESSAGE("decoded Properties: " << p2);
+        BOOST_CHECK_EQUAL((bool)p["bool"], (bool)p2["bool"]);
+        BOOST_CHECK_EQUAL(p["int"], p2["int"]);
+        BOOST_CHECK_EQUAL(p["unsigned int"], p2["unsigned int"]);
+        BOOST_CHECK_EQUAL(p["long long"], p2["long long"]);
+        BOOST_CHECK_EQUAL(p["unsigned long long"], p2["unsigned long long"]);
+        BOOST_CHECK_EQUAL(p["double"], p2["double"]);
+        BOOST_CHECK_EQUAL(p["string"], p2["string"]);
+        BOOST_CHECK_EQUAL(p["Length"], p2["Length"]);
+        BOOST_CHECK(p["Date"].compare(p2["Date"])); // FIXME: equality check fails
+        // BOOST_CHECK_EQUAL(p["Time"], p2["Time"]);  <-- not implemented
+        // BOOST_CHECK_EQUAL(p["DateTime"], p2["DateTime"]); <-- not implemented
+        BOOST_CHECK_EQUAL(p["PathName"], p2["PathName"]);
+        BOOST_CHECK_EQUAL(p["Vector"], p2["Vector"]);
+        BOOST_CHECK_EQUAL(p["Map"], p2["Map"]);
+    }
+    if (filename.exists()) filename.unlink();
+
+    Properties access_nested = p.get("Nested");
+
+    eckit::ValueList access_list = p.get("list");
+    BOOST_TEST_MESSAGE("encoded list: " <<  access_list );
+    std::vector<eckit::Properties> access_property_list(access_list.begin(),access_list.end());
+
+    BOOST_TEST_MESSAGE("encoded Nested: " << access_nested);
+    {
+        FileStream sout( filepath.c_str(), "w" );
+        sout << p;
+    }
+
+}
+
+//-----------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace eckit_test
diff --git a/metkit/CMakeLists.txt b/metkit/CMakeLists.txt
index 4761ee9..c3214b5 100644
--- a/metkit/CMakeLists.txt
+++ b/metkit/CMakeLists.txt
@@ -29,8 +29,10 @@ if( HAVE_GRIB )
     set( GRIB_API_LIBRARIES    ${ECCODES_LIBRARIES} )
     set( GRIB_API_DEFINITIONS  ${ECCODES_DEFINITIONS} )
     set( grib_api_BASE_DIR     ${eccodes_BASE_DIR} )
+    set( grib_handling_pkg     eccodes )
   else()
     ecbuild_use_package( PROJECT grib_api VERSION 1.14 )
+    set( grib_handling_pkg     grib_api )
     if(NOT GRIB_API_FOUND)
       set(HAVE_GRIB 0)
     endif()
@@ -40,7 +42,7 @@ endif()
 
 # eckit
 
-ecbuild_use_package( PROJECT eckit  VERSION  0.13 REQUIRED )
+ecbuild_use_package( PROJECT eckit  VERSION  0.16.5 REQUIRED )
 
 ### start project
 
diff --git a/metkit/VERSION.cmake b/metkit/VERSION.cmake
index a61bea4..b2b7052 100644
--- a/metkit/VERSION.cmake
+++ b/metkit/VERSION.cmake
@@ -1 +1 @@
-set( ${PROJECT_NAME}_VERSION_STR  "0.5.2")
+set( ${PROJECT_NAME}_VERSION_STR  "0.6.0" )
diff --git a/metkit/bamboo/INTEL-env.sh b/metkit/bamboo/INTEL-env.sh
index cbd28c0..441a81d 100644
--- a/metkit/bamboo/INTEL-env.sh
+++ b/metkit/bamboo/INTEL-env.sh
@@ -6,6 +6,7 @@ if [[ ! $(command -v module > /dev/null 2>&1) ]]; then
 fi
 # Unload modules not available for Intel
 module unload grib_api
+module unload eccodes
 module unload emos
 module unload fftw
 module unload libemos
diff --git a/metkit/etc/language.json b/metkit/etc/language.json
index 2bb9841..f809ad7 100644
--- a/metkit/etc/language.json
+++ b/metkit/etc/language.json
@@ -12,9 +12,6 @@
             "more": [{
                 "type": "float"
             }],
-            "never": [{
-                "repres": "sh"
-            }],
             "only": [{}]
         },
         "class": {
@@ -48,8 +45,14 @@
             "type": "integer",
             "flatten": false
         },
-         "hdate": {
-            "type": "integer"
+        "hdate": {
+            "type": "integer",
+            "only": [{
+                "stream": [
+                    "enfh",
+                    "enwh"
+                ]
+            }]
         },
         "format": {
             "type": "enum",
@@ -211,11 +214,16 @@
                 "type": [
                     "pf",
                     "cr",
-                    "cm"
+                    "cm",
+                    "fcmean",
+                    "fc",
+                    "fcmin",
+                    "fcmax",
+                    "fcstdev"
                 ]
             }]
         },
-          "ensemble": {
+        "ensemble": {
             "type": "to-by-list",
             "by": 1,
             "aliases": [
@@ -298,8 +306,8 @@
         "origin": {
             "type": "enum",
             "values": [
-                "ecmf",
-                "ecmwf"
+                ["ecmf",
+                "ecmwf"]
             ]
         },
         "system": {
@@ -444,8 +452,15 @@
             ]
         },
         "accuracy": {
-            "type": "any",
-            "flatten": false
+            "type": "enum-or-more",
+            "flatten": false,
+            "values": [
+                ["av"],
+                ["off", "normal", "auto"]
+            ],
+            "more": [{
+                "type": "integer"
+            }]
         },
         "interpolation": {
             "type": "enum",
@@ -472,7 +487,7 @@
             ]
         },
         "bitmap": {
-            "type": "any",
+        "type": "any",
             "flatten": false
         },
         "direction": {
@@ -480,7 +495,6 @@
             "by": 1,
             "only": [{
                 "param": [
-                    "251",
                     "140251"
                 ]
             }]
@@ -490,7 +504,6 @@
             "by": 1,
             "only": [{
                 "param": [
-                    "251",
                     "140251"
                 ]
             }]
@@ -527,7 +540,14 @@
             "multiple": true
         },
         "resol": {
-            "type": "any"
+            "type": "enum-or-more",
+            "flatten": false,
+            "values": [
+                ["off", "av", "reduced gaussian 160"]
+            ],
+            "more": [{
+                "type": "integer"
+            }]
         },
         "gaussian": {
             "type": "enum",
diff --git a/metkit/etc/param.json b/metkit/etc/param.json
index 43ecdad..05647e6 100644
--- a/metkit/etc/param.json
+++ b/metkit/etc/param.json
@@ -1,19553 +1,18277 @@
-[
-    [
-        "1",
-        "strf",
-        "stream function"
-    ],
-    [
-        "2",
-        "vp",
-        "velocity potential",
-        "vpot"
-    ],
-    [
-        "3",
-        "pt",
-        "potential temperature"
-    ],
-    [
-        "4",
-        "eqpt",
-        "equivalent potential temperature"
-    ],
-    [
-        "5",
-        "sept",
-        "saturated equivalent potential temperature"
-    ],
-    [
-        "6",
-        "ssfr",
-        "soil sand fraction"
-    ],
-    [
-        "7",
-        "scfr",
-        "soil clay fraction"
-    ],
-    [
-        "8",
-        "sro",
-        "surface runoff"
-    ],
-    [
-        "9",
-        "ssro",
-        "sub-surface runoff"
-    ],
-    [
-        "10",
-        "ws",
-        "wind speed"
-    ],
-    [
-        "11",
-        "udvw",
-        "u component of divergent wind"
-    ],
-    [
-        "12",
-        "vdvw",
-        "v component of divergent wind"
-    ],
-    [
-        "13",
-        "urtw",
-        "u component of rotational wind"
-    ],
-    [
-        "14",
-        "vrtw",
-        "v component of rotational wind"
-    ],
-    [
-        "15",
-        "aluvp",
-        "uv visible albedo for direct radiation"
-    ],
-    [
-        "16",
-        "aluvd",
-        "uv visible albedo for diffuse radiation"
-    ],
-    [
-        "17",
-        "alnip",
-        "near ir albedo for direct radiation"
-    ],
-    [
-        "18",
-        "alnid",
-        "near ir albedo for diffuse radiation"
-    ],
-    [
-        "19",
-        "uvcs",
-        "clear sky surface uv"
-    ],
-    [
-        "20",
-        "parcs",
-        "clear sky surface photosynthetically active radiation"
-    ],
-    [
-        "21",
-        "uctp",
-        "unbalanced component of temperature"
-    ],
-    [
-        "22",
-        "ucln",
-        "unbalanced component of logarithm of surface pressure"
-    ],
-    [
-        "23",
-        "ucdv",
-        "unbalanced component of divergence"
-    ],
-    [
-        "26",
-        "cl",
-        "lake cover"
-    ],
-    [
-        "27",
-        "cvl",
-        "low vegetation cover"
-    ],
-    [
-        "28",
-        "cvh",
-        "high vegetation cover"
-    ],
-    [
-        "29",
-        "tvl",
-        "type of low vegetation"
-    ],
-    [
-        "30",
-        "tvh",
-        "type of high vegetation"
-    ],
-    [
-        "31",
-        "ci",
-        "sea-ice cover"
-    ],
-    [
-        "32",
-        "asn",
-        "snow albedo"
-    ],
-    [
-        "33",
-        "rsn",
-        "snow density"
-    ],
-    [
-        "34",
-        "sst",
-        "sea surface temperature",
-        "sstk"
-    ],
-    [
-        "35",
-        "istl1",
-        "ice temperature layer 1"
-    ],
-    [
-        "36",
-        "istl2",
-        "ice temperature layer 2"
-    ],
-    [
-        "37",
-        "istl3",
-        "ice temperature layer 3"
-    ],
-    [
-        "38",
-        "istl4",
-        "ice temperature layer 4"
-    ],
-    [
-        "39",
-        "swvl1",
-        "volumetric soil water layer 1",
-        "swv1"
-    ],
-    [
-        "40",
-        "swvl2",
-        "volumetric soil water layer 2",
-        "swv2"
-    ],
-    [
-        "41",
-        "swvl3",
-        "volumetric soil water layer 3",
-        "swv3"
-    ],
-    [
-        "42",
-        "swvl4",
-        "volumetric soil water layer 4",
-        "swv4"
-    ],
-    [
-        "43",
-        "slt",
-        "soil type"
-    ],
-    [
-        "44",
-        "es",
-        "snow evaporation"
-    ],
-    [
-        "45",
-        "smlt",
-        "snowmelt"
-    ],
-    [
-        "46",
-        "sdur",
-        "solar duration"
-    ],
-    [
-        "47",
-        "dsrp",
-        "direct solar radiation"
-    ],
-    [
-        "48",
-        "magss",
-        "magnitude of turbulent surface stress"
-    ],
-    [
-        "49",
-        "10fg",
-        "10 metre wind gust since previous post-processing"
-    ],
-    [
-        "50",
-        "lspf",
-        "large-scale precipitation fraction"
-    ],
-    [
-        "51",
-        "mx2t24",
-        "maximum temperature at 2 metres in the last 24 hours"
-    ],
-    [
-        "52",
-        "mn2t24",
-        "minimum temperature at 2 metres in the last 24 hours"
-    ],
-    [
-        "53",
-        "mont",
-        "montgomery potential"
-    ],
-    [
-        "54",
-        "pres",
-        "pressure"
-    ],
-    [
-        "55",
-        "mean2t24",
-        "mean temperature at 2 metres in the last 24 hours"
-    ],
-    [
-        "56",
-        "mn2d24",
-        "mean 2 metre dewpoint temperature in the last 24 hours"
-    ],
-    [
-        "57",
-        "uvb",
-        "downward uv radiation at the surface"
-    ],
-    [
-        "58",
-        "par",
-        "photosynthetically active radiation at the surface"
-    ],
-    [
-        "59",
-        "cape",
-        "convective available potential energy"
-    ],
-    [
-        "60",
-        "pv",
-        "potential vorticity"
-    ],
-    [
-        "62",
-        "obct",
-        "observation count"
-    ],
-    [
-        "63",
-        "stsktd",
-        "start time for skin temperature difference"
-    ],
-    [
-        "64",
-        "ftsktd",
-        "finish time for skin temperature difference"
-    ],
-    [
-        "65",
-        "sktd",
-        "skin temperature difference"
-    ],
-    [
-        "66",
-        "lai_lv",
-        "leaf area index, low vegetation",
-        "lailv"
-    ],
-    [
-        "67",
-        "lai_hv",
-        "leaf area index, high vegetation",
-        "laihv"
-    ],
-    [
-        "68",
-        "msr_lv",
-        "minimum stomatal resistance, low vegetation"
-    ],
-    [
-        "69",
-        "msr_hv",
-        "minimum stomatal resistance, high vegetation"
-    ],
-    [
-        "70",
-        "bc_lv",
-        "biome cover, low vegetation"
-    ],
-    [
-        "71",
-        "bc_hv",
-        "biome cover, high vegetation"
-    ],
-    [
-        "72",
-        "issrd",
-        "instantaneous surface solar radiation downwards"
-    ],
-    [
-        "73",
-        "istrd",
-        "instantaneous surface thermal radiation downwards"
-    ],
-    [
-        "74",
-        "sdfor",
-        "standard deviation of filtered subgrid orography"
-    ],
-    [
-        "75",
-        "crwc",
-        "specific rain water content"
-    ],
-    [
-        "76",
-        "cswc",
-        "specific snow water content"
-    ],
-    [
-        "77",
-        "etadot",
-        "eta-coordinate vertical velocity",
-        "etad"
-    ],
-    [
-        "78",
-        "tclw",
-        "total column liquid water"
-    ],
-    [
-        "79",
-        "tciw",
-        "total column ice water"
-    ],
-    [
-        "121",
-        "mx2t6",
-        "maximum temperature at 2 metres in the last 6 hours"
-    ],
-    [
-        "122",
-        "mn2t6",
-        "minimum temperature at 2 metres in the last 6 hours"
-    ],
-    [
-        "123",
-        "10fg6",
-        "10 metre wind gust in the last 6 hours"
-    ],
-    [
-        "124",
-        "emis",
-        "surface emissivity"
-    ],
-    [
-        "125",
-        "vite",
-        "vertically integrated total energy"
-    ],
-    [
-        "126",
-        "generic parameter for sensitive area prediction"
-    ],
-    [
-        "127",
-        "at",
-        "atmospheric tide"
-    ],
-    [
-        "128",
-        "bv",
-        "budget values"
-    ],
-    [
-        "129",
-        "z",
-        "geopotential"
-    ],
-    [
-        "130",
-        "t",
-        "temperature"
-    ],
-    [
-        "131",
-        "u",
-        "u component of wind"
-    ],
-    [
-        "132",
-        "v",
-        "v component of wind"
-    ],
-    [
-        "133",
-        "q",
-        "specific humidity"
-    ],
-    [
-        "134",
-        "sp",
-        "surface pressure"
-    ],
-    [
-        "135",
-        "w",
-        "vertical velocity"
-    ],
-    [
-        "136",
-        "tcw",
-        "total column water"
-    ],
-    [
-        "137",
-        "tcwv",
-        "total column water vapour"
-    ],
-    [
-        "138",
-        "vo",
-        "vorticity (relative)"
-    ],
-    [
-        "139",
-        "stl1",
-        "soil temperature level 1"
-    ],
-    [
-        "140",
-        "swl1",
-        "soil wetness level 1"
-    ],
-    [
-        "141",
-        "sd",
-        "snow depth"
-    ],
-    [
-        "142",
-        "lsp",
-        "large-scale precipitation"
-    ],
-    [
-        "143",
-        "cp",
-        "convective precipitation"
-    ],
-    [
-        "144",
-        "sf",
-        "snowfall"
-    ],
-    [
-        "145",
-        "bld",
-        "boundary layer dissipation"
-    ],
-    [
-        "146",
-        "sshf",
-        "surface sensible heat flux"
-    ],
-    [
-        "147",
-        "slhf",
-        "surface latent heat flux"
-    ],
-    [
-        "148",
-        "chnk",
-        "charnock",
-		"ss"
-    ],
-    [
-        "149",
-        "snr",
-        "surface net radiation"
-    ],
-    [
-        "150",
-        "tnr",
-        "top net radiation"
-    ],
-    [
-        "151",
-        "msl",
-        "mean sea level pressure"
-    ],
-    [
-        "152",
-        "lnsp",
-        "logarithm of surface pressure"
-    ],
-    [
-        "153",
-        "swhr",
-        "short-wave heating rate"
-    ],
-    [
-        "154",
-        "lwhr",
-        "long-wave heating rate"
-    ],
-    [
-        "155",
-        "d",
-        "divergence"
-    ],
-    [
-        "156",
-        "gh",
-        "geopotential height"
-    ],
-    [
-        "157",
-        "r",
-        "relative humidity"
-    ],
-    [
-        "158",
-        "tsp",
-        "tendency of surface pressure"
-    ],
-    [
-        "159",
-        "blh",
-        "boundary layer height"
-    ],
-    [
-        "160",
-        "sdor",
-        "standard deviation of orography"
-    ],
-    [
-        "161",
-        "isor",
-        "anisotropy of sub-gridscale orography"
-    ],
-    [
-        "162",
-        "anor",
-        "angle of sub-gridscale orography"
-    ],
-    [
-        "163",
-        "slor",
-        "slope of sub-gridscale orography"
-    ],
-    [
-        "164",
-        "tcc",
-        "total cloud cover"
-    ],
-    [
-        "165",
-        "10u",
-        "10 metre u wind component"
-    ],
-    [
-        "166",
-        "10v",
-        "10 metre v wind component"
-    ],
-    [
-        "167",
-        "2t",
-        "2 metre temperature"
-    ],
-    [
-        "168",
-        "2d",
-        "2 metre dewpoint temperature"
-    ],
-    [
-        "169",
-        "ssrd",
-        "surface solar radiation downwards"
-    ],
-    [
-        "170",
-        "stl2",
-        "soil temperature level 2"
-    ],
-    [
-        "171",
-        "swl2",
-        "soil wetness level 2"
-    ],
-    [
-        "172",
-        "lsm",
-        "land-sea mask"
-    ],
-    [
-        "173",
-        "sr",
-        "surface roughness"
-    ],
-    [
-        "174",
-        "al",
-        "albedo",
-        "174.128"
-    ],
-    [
-        "175",
-        "strd",
-        "surface thermal radiation downwards"
-    ],
-    [
-        "176",
-        "ssr",
-        "surface net solar radiation"
-    ],
-    [
-        "177",
-        "str",
-        "surface net thermal radiation"
-    ],
-    [
-        "178",
-        "tsr",
-        "top net solar radiation"
-    ],
-    [
-        "179",
-        "ttr",
-        "top net thermal radiation"
-    ],
-    [
-        "180",
-        "ewss",
-        "eastward turbulent surface stress"
-    ],
-    [
-        "181",
-        "nsss",
-        "northward turbulent surface stress"
-    ],
-    [
-        "182",
-        "e",
-        "evaporation"
-    ],
-    [
-        "183",
-        "stl3",
-        "soil temperature level 3"
-    ],
-    [
-        "184",
-        "swl3",
-        "soil wetness level 3"
-    ],
-    [
-        "185",
-        "ccc",
-        "convective cloud cover"
-    ],
-    [
-        "186",
-        "lcc",
-        "low cloud cover"
-    ],
-    [
-        "187",
-        "mcc",
-        "medium cloud cover"
-    ],
-    [
-        "188",
-        "hcc",
-        "high cloud cover"
-    ],
-    [
-        "189",
-        "sund",
-        "sunshine duration"
-    ],
-    [
-        "190",
-        "ewov",
-        "east-west component of sub-gridscale orographic variance"
-    ],
-    [
-        "191",
-        "nsov",
-        "north-south component of sub-gridscale orographic variance"
-    ],
-    [
-        "192",
-        "nwov",
-        "north-west/south-east component of sub-gridscale orographic variance"
-    ],
-    [
-        "193",
-        "neov",
-        "north-east/south-west component of sub-gridscale orographic variance"
-    ],
-    [
-        "194",
-        "btmp",
-        "brightness temperature"
-    ],
-    [
-        "195",
-        "lgws",
-        "eastward gravity wave surface stress"
-    ],
-    [
-        "196",
-        "mgws",
-        "northward gravity wave surface stress"
-    ],
-    [
-        "197",
-        "gwd",
-        "gravity wave dissipation"
-    ],
-    [
-        "198",
-        "src",
-        "skin reservoir content"
-    ],
-    [
-        "199",
-        "veg",
-        "vegetation fraction"
-    ],
-    [
-        "200",
-        "vso",
-        "variance of sub-gridscale orography"
-    ],
-    [
-        "201",
-        "mx2t",
-        "maximum temperature at 2 metres since previous post-processing"
-    ],
-    [
-        "202",
-        "mn2t",
-        "minimum temperature at 2 metres since previous post-processing"
-    ],
-    [
-        "203",
-        "o3",
-        "ozone mass mixing ratio"
-    ],
-    [
-        "204",
-        "paw",
-        "precipitation analysis weights"
-    ],
-    [
-        "205",
-        "ro",
-        "runoff"
-    ],
-    [
-        "206",
-        "tco3",
-        "total column ozone"
-    ],
-    [
-        "207",
-        "10si",
-        "10 metre wind speed"
-    ],
-    [
-        "208",
-        "tsrc",
-        "top net solar radiation, clear sky"
-    ],
-    [
-        "209",
-        "ttrc",
-        "top net thermal radiation, clear sky"
-    ],
-    [
-        "210",
-        "ssrc",
-        "surface net solar radiation, clear sky"
-    ],
-    [
-        "211",
-        "strc",
-        "surface net thermal radiation, clear sky"
-    ],
-    [
-        "212",
-        "tisr",
-        "toa incident solar radiation"
-    ],
-    [
-        "213",
-        "vimd",
-        "vertically integrated moisture divergence"
-    ],
-    [
-        "214",
-        "dhr",
-        "diabatic heating by radiation"
-    ],
-    [
-        "215",
-        "dhvd",
-        "diabatic heating by vertical diffusion"
-    ],
-    [
-        "216",
-        "dhcc",
-        "diabatic heating by cumulus convection"
-    ],
-    [
-        "217",
-        "dhlc",
-        "diabatic heating large-scale condensation"
-    ],
-    [
-        "218",
-        "vdzw",
-        "vertical diffusion of zonal wind"
-    ],
-    [
-        "219",
-        "vdmw",
-        "vertical diffusion of meridional wind"
-    ],
-    [
-        "220",
-        "ewgd",
-        "east-west gravity wave drag tendency"
-    ],
-    [
-        "221",
-        "nsgd",
-        "north-south gravity wave drag tendency"
-    ],
-    [
-        "222",
-        "ctzw",
-        "convective tendency of zonal wind"
-    ],
-    [
-        "223",
-        "ctmw",
-        "convective tendency of meridional wind"
-    ],
-    [
-        "224",
-        "vdh",
-        "vertical diffusion of humidity"
-    ],
-    [
-        "225",
-        "htcc",
-        "humidity tendency by cumulus convection"
-    ],
-    [
-        "226",
-        "htlc",
-        "humidity tendency by large-scale condensation"
-    ],
-    [
-        "227",
-        "crnh",
-        "tendency due to removal of negative humidity"
-    ],
-    [
-        "228",
-        "tp",
-        "total precipitation"
-    ],
-    [
-        "229",
-        "iews",
-        "instantaneous eastward turbulent surface stress"
-    ],
-    [
-        "230",
-        "inss",
-        "instantaneous northward turbulent surface stress"
-    ],
-    [
-        "231",
-        "ishf",
-        "instantaneous surface sensible heat flux"
-    ],
-    [
-        "232",
-        "ie",
-        "instantaneous moisture flux"
-    ],
-    [
-        "233",
-        "asq",
-        "apparent surface humidity"
-    ],
-    [
-        "234",
-        "lsrh",
-        "logarithm of surface roughness length for heat"
-    ],
-    [
-        "235",
-        "skt",
-        "skin temperature"
-    ],
-    [
-        "236",
-        "stl4",
-        "soil temperature level 4"
-    ],
-    [
-        "237",
-        "swl4",
-        "soil wetness level 4"
-    ],
-    [
-        "238",
-        "tsn",
-        "temperature of snow layer"
-    ],
-    [
-        "239",
-        "csf",
-        "convective snowfall"
-    ],
-    [
-        "240",
-        "lsf",
-        "large-scale snowfall"
-    ],
-    [
-        "241",
-        "acf",
-        "accumulated cloud fraction tendency"
-    ],
-    [
-        "242",
-        "alw",
-        "accumulated liquid water tendency"
-    ],
-    [
-        "243",
-        "fal",
-        "forecast albedo"
-    ],
-    [
-        "244",
-        "fsr",
-        "forecast surface roughness"
-    ],
-    [
-        "245",
-        "flsr",
-        "forecast logarithm of surface roughness for heat"
-    ],
-    [
-        "246",
-        "clwc",
-        "specific cloud liquid water content"
-    ],
-    [
-        "247",
-        "ciwc",
-        "specific cloud ice water content"
-    ],
-    [
-        "248",
-        "cc",
-        "fraction of cloud cover"
-    ],
-    [
-        "249",
-        "aiw",
-        "accumulated ice water tendency"
-    ],
-    [
-        "250",
-        "ice",
-        "ice age"
-    ],
-    [
-        "251",
-        "atte",
-        "adiabatic tendency of temperature"
-    ],
-    [
-        "252",
-        "athe",
-        "adiabatic tendency of humidity"
-    ],
-    [
-        "253",
-        "atze",
-        "adiabatic tendency of zonal wind"
-    ],
-    [
-        "254",
-        "atmw",
-        "adiabatic tendency of meridional wind"
-    ],
-    [
-        "129001",
-        "strfgrd",
-        "stream function gradient"
-    ],
-    [
-        "129002",
-        "vpotgrd",
-        "velocity potential gradient"
-    ],
-    [
-        "129003",
-        "ptgrd",
-        "potential temperature gradient"
-    ],
-    [
-        "129004",
-        "eqptgrd",
-        "equivalent potential temperature gradient"
-    ],
-    [
-        "129005",
-        "septgrd",
-        "saturated equivalent potential temperature gradient"
-    ],
-    [
-        "129011",
-        "udvwgrd",
-        "u component of divergent wind gradient"
-    ],
-    [
-        "129012",
-        "vdvwgrd",
-        "v component of divergent wind gradient"
-    ],
-    [
-        "129013",
-        "urtwgrd",
-        "u component of rotational wind gradient"
-    ],
-    [
-        "129014",
-        "vrtwgrd",
-        "v component of rotational wind gradient"
-    ],
-    [
-        "129021",
-        "uctpgrd",
-        "unbalanced component of temperature gradient"
-    ],
-    [
-        "129022",
-        "uclngrd",
-        "unbalanced component of logarithm of surface pressure gradient"
-    ],
-    [
-        "129023",
-        "ucdvgrd",
-        "unbalanced component of divergence gradient"
-    ],
-    [
-        "129026",
-        "clgrd",
-        "lake cover gradient"
-    ],
-    [
-        "129027",
-        "cvlgrd",
-        "low vegetation cover gradient"
-    ],
-    [
-        "129028",
-        "cvhgrd",
-        "high vegetation cover gradient"
-    ],
-    [
-        "129029",
-        "tvlgrd",
-        "type of low vegetation gradient"
-    ],
-    [
-        "129030",
-        "tvhgrd",
-        "type of high vegetation gradient"
-    ],
-    [
-        "129031",
-        "sicgrd",
-        "sea-ice cover gradient"
-    ],
-    [
-        "129032",
-        "asngrd",
-        "snow albedo gradient"
-    ],
-    [
-        "129033",
-        "rsngrd",
-        "snow density gradient"
-    ],
-    [
-        "129034",
-        "sstkgrd",
-        "sea surface temperature gradient"
-    ],
-    [
-        "129035",
-        "istl1grd",
-        "ice surface temperature layer 1 gradient"
-    ],
-    [
-        "129036",
-        "istl2grd",
-        "ice surface temperature layer 2 gradient"
-    ],
-    [
-        "129037",
-        "istl3grd",
-        "ice surface temperature layer 3 gradient"
-    ],
-    [
-        "129038",
-        "istl4grd",
-        "ice surface temperature layer 4 gradient"
-    ],
-    [
-        "129039",
-        "swvl1grd",
-        "volumetric soil water layer 1 gradient"
-    ],
-    [
-        "129040",
-        "swvl2grd",
-        "volumetric soil water layer 2 gradient"
-    ],
-    [
-        "129041",
-        "swvl3grd",
-        "volumetric soil water layer 3 gradient"
-    ],
-    [
-        "129042",
-        "swvl4grd",
-        "volumetric soil water layer 4 gradient"
-    ],
-    [
-        "129043",
-        "sltgrd",
-        "soil type gradient"
-    ],
-    [
-        "129044",
-        "esgrd",
-        "snow evaporation gradient"
-    ],
-    [
-        "129045",
-        "smltgrd",
-        "snowmelt gradient"
-    ],
-    [
-        "129046",
-        "sdurgrd",
-        "solar duration gradient"
-    ],
-    [
-        "129047",
-        "dsrpgrd",
-        "direct solar radiation gradient"
-    ],
-    [
-        "129048",
-        "magssgrd",
-        "magnitude of turbulent surface stress gradient"
-    ],
-    [
-        "129049",
-        "10fggrd",
-        "10 metre wind gust gradient"
-    ],
-    [
-        "129050",
-        "lspfgrd",
-        "large-scale precipitation fraction gradient"
-    ],
-    [
-        "129051",
-        "mx2t24grd",
-        "maximum 2 metre temperature gradient"
-    ],
-    [
-        "129052",
-        "mn2t24grd",
-        "minimum 2 metre temperature gradient"
-    ],
-    [
-        "129053",
-        "montgrd",
-        "montgomery potential gradient"
-    ],
-    [
-        "129054",
-        "presgrd",
-        "pressure gradient"
-    ],
-    [
-        "129055",
-        "mean2t24grd",
-        "mean 2 metre temperature in the last 24 hours gradient"
-    ],
-    [
-        "129056",
-        "mn2d24grd",
-        "mean 2 metre dewpoint temperature in the last 24 hours gradient"
-    ],
-    [
-        "129057",
-        "uvbgrd",
-        "downward uv radiation at the surface gradient"
-    ],
-    [
-        "129058",
-        "pargrd",
-        "photosynthetically active radiation at the surface gradient"
-    ],
-    [
-        "129059",
-        "capegrd",
-        "convective available potential energy gradient"
-    ],
-    [
-        "129060",
-        "pvgrd",
-        "potential vorticity gradient"
-    ],
-    [
-        "129061",
-        "tpogrd",
-        "total precipitation from observations gradient"
-    ],
-    [
-        "129062",
-        "obctgrd",
-        "observation count gradient"
-    ],
-    [
-        "129063",
-        "start time for skin temperature difference"
-    ],
-    [
-        "129064",
-        "finish time for skin temperature difference"
-    ],
-    [
-        "129065",
-        "skin temperature difference"
-    ],
-    [
-        "129066",
-        "leaf area index, low vegetation"
-    ],
-    [
-        "129067",
-        "leaf area index, high vegetation"
-    ],
-    [
-        "129068",
-        "minimum stomatal resistance, low vegetation"
-    ],
-    [
-        "129069",
-        "minimum stomatal resistance, high vegetation"
-    ],
-    [
-        "129070",
-        "biome cover, low vegetation"
-    ],
-    [
-        "129071",
-        "biome cover, high vegetation"
-    ],
-    [
-        "129078",
-        "total column liquid water"
-    ],
-    [
-        "129079",
-        "total column ice water"
-    ],
-    [
-        "129121",
-        "mx2t6grd",
-        "maximum temperature at 2 metres gradient"
-    ],
-    [
-        "129122",
-        "mn2t6grd",
-        "minimum temperature at 2 metres gradient"
-    ],
-    [
-        "129123",
-        "10fg6grd",
-        "10 metre wind gust in the last 6 hours gradient"
-    ],
-    [
-        "129125",
-        "vertically integrated total energy"
-    ],
-    [
-        "129126",
-        "generic parameter for sensitive area prediction"
-    ],
-    [
-        "129127",
-        "atgrd",
-        "atmospheric tide gradient"
-    ],
-    [
-        "129128",
-        "bvgrd",
-        "budget values gradient"
-    ],
-    [
-        "129129",
-        "zgrd",
-        "geopotential gradient"
-    ],
-    [
-        "129130",
-        "tgrd",
-        "temperature gradient"
-    ],
-    [
-        "129131",
-        "ugrd",
-        "u component of wind gradient"
-    ],
-    [
-        "129132",
-        "vgrd",
-        "v component of wind gradient"
-    ],
-    [
-        "129133",
-        "qgrd",
-        "specific humidity gradient"
-    ],
-    [
-        "129134",
-        "spgrd",
-        "surface pressure gradient"
-    ],
-    [
-        "129135",
-        "wgrd",
-        "vertical velocity (pressure) gradient"
-    ],
-    [
-        "129136",
-        "tcwgrd",
-        "total column water gradient"
-    ],
-    [
-        "129137",
-        "tcwvgrd",
-        "total column water vapour gradient"
-    ],
-    [
-        "129138",
-        "vogrd",
-        "vorticity (relative) gradient"
-    ],
-    [
-        "129139",
-        "stl1grd",
-        "soil temperature level 1 gradient"
-    ],
-    [
-        "129140",
-        "swl1grd",
-        "soil wetness level 1 gradient"
-    ],
-    [
-        "129141",
-        "sdgrd",
-        "snow depth gradient"
-    ],
-    [
-        "129142",
-        "lspgrd",
-        "stratiform precipitation (large-scale precipitation) gradient"
-    ],
-    [
-        "129143",
-        "cpgrd",
-        "convective precipitation gradient"
-    ],
-    [
-        "129144",
-        "sfgrd",
-        "snowfall (convective + stratiform) gradient"
-    ],
-    [
-        "129145",
-        "bldgrd",
-        "boundary layer dissipation gradient"
-    ],
-    [
-        "129146",
-        "sshfgrd",
-        "surface sensible heat flux gradient"
-    ],
-    [
-        "129147",
-        "slhfgrd",
-        "surface latent heat flux gradient"
-    ],
-    [
-        "129148",
-        "chnkgrd",
-        "charnock gradient"
-    ],
-    [
-        "129149",
-        "snrgrd",
-        "surface net radiation gradient"
-    ],
-    [
-        "129150",
-        "tnrgrd",
-        "top net radiation gradient"
-    ],
-    [
-        "129151",
-        "mslgrd",
-        "mean sea level pressure gradient"
-    ],
-    [
-        "129152",
-        "lnspgrd",
-        "logarithm of surface pressure gradient"
-    ],
-    [
-        "129153",
-        "swhrgrd",
-        "short-wave heating rate gradient"
-    ],
-    [
-        "129154",
-        "lwhrgrd",
-        "long-wave heating rate gradient"
-    ],
-    [
-        "129155",
-        "dgrd",
-        "divergence gradient"
-    ],
-    [
-        "129156",
-        "ghgrd",
-        "height gradient"
-    ],
-    [
-        "129157",
-        "rgrd",
-        "relative humidity gradient"
-    ],
-    [
-        "129158",
-        "tspgrd",
-        "tendency of surface pressure gradient"
-    ],
-    [
-        "129159",
-        "blhgrd",
-        "boundary layer height gradient"
-    ],
-    [
-        "129160",
-        "sdorgrd",
-        "standard deviation of orography gradient"
-    ],
-    [
-        "129161",
-        "isorgrd",
-        "anisotropy of sub-gridscale orography gradient"
-    ],
-    [
-        "129162",
-        "anorgrd",
-        "angle of sub-gridscale orography gradient"
-    ],
-    [
-        "129163",
-        "slorgrd",
-        "slope of sub-gridscale orography gradient"
-    ],
-    [
-        "129164",
-        "tccgrd",
-        "total cloud cover gradient"
-    ],
-    [
-        "129165",
-        "10ugrd",
-        "10 metre u wind component gradient"
-    ],
-    [
-        "129166",
-        "10vgrd",
-        "10 metre v wind component gradient"
-    ],
-    [
-        "129167",
-        "2tgrd",
-        "2 metre temperature gradient"
-    ],
-    [
-        "129168",
-        "2dgrd",
-        "2 metre dewpoint temperature gradient"
-    ],
-    [
-        "129169",
-        "ssrdgrd",
-        "surface solar radiation downwards gradient"
-    ],
-    [
-        "129170",
-        "stl2grd",
-        "soil temperature level 2 gradient"
-    ],
-    [
-        "129171",
-        "swl2grd",
-        "soil wetness level 2 gradient"
-    ],
-    [
-        "129172",
-        "lsmgrd",
-        "land-sea mask gradient"
-    ],
-    [
-        "129173",
-        "srgrd",
-        "surface roughness gradient"
-    ],
-    [
-        "129174",
-        "algrd",
-        "albedo gradient"
-    ],
-    [
-        "129175",
-        "strdgrd",
-        "surface thermal radiation downwards gradient"
-    ],
-    [
-        "129176",
-        "ssrgrd",
-        "surface net solar radiation gradient"
-    ],
-    [
-        "129177",
-        "strgrd",
-        "surface net thermal radiation gradient"
-    ],
-    [
-        "129178",
-        "tsrgrd",
-        "top net solar radiation gradient"
-    ],
-    [
-        "129179",
-        "ttrgrd",
-        "top net thermal radiation gradient"
-    ],
-    [
-        "129180",
-        "ewssgrd",
-        "east-west surface stress gradient"
-    ],
-    [
-        "129181",
-        "nsssgrd",
-        "north-south surface stress gradient"
-    ],
-    [
-        "129182",
-        "egrd",
-        "evaporation gradient"
-    ],
-    [
-        "129183",
-        "stl3grd",
-        "soil temperature level 3 gradient"
-    ],
-    [
-        "129184",
-        "swl3grd",
-        "soil wetness level 3 gradient"
-    ],
-    [
-        "129185",
-        "cccgrd",
-        "convective cloud cover gradient"
-    ],
-    [
-        "129186",
-        "lccgrd",
-        "low cloud cover gradient"
-    ],
-    [
-        "129187",
-        "mccgrd",
-        "medium cloud cover gradient"
-    ],
-    [
-        "129188",
-        "hccgrd",
-        "high cloud cover gradient"
-    ],
-    [
-        "129189",
-        "sundgrd",
-        "sunshine duration gradient"
-    ],
-    [
-        "129190",
-        "ewovgrd",
-        "east-west component of sub-gridscale orographic variance gradient"
-    ],
-    [
-        "129191",
-        "nsovgrd",
-        "north-south component of sub-gridscale orographic variance gradient"
-    ],
-    [
-        "129192",
-        "nwovgrd",
-        "north-west/south-east component of sub-gridscale orographic variance gradient"
-    ],
-    [
-        "129193",
-        "neovgrd",
-        "north-east/south-west component of sub-gridscale orographic variance gradient"
-    ],
-    [
-        "129194",
-        "btmpgrd",
-        "brightness temperature gradient"
-    ],
-    [
-        "129195",
-        "lgwsgrd",
-        "longitudinal component of gravity wave stress gradient"
-    ],
-    [
-        "129196",
-        "mgwsgrd",
-        "meridional component of gravity wave stress gradient"
-    ],
-    [
-        "129197",
-        "gwdgrd",
-        "gravity wave dissipation gradient"
-    ],
-    [
-        "129198",
-        "srcgrd",
-        "skin reservoir content gradient"
-    ],
-    [
-        "129199",
-        "veggrd",
-        "vegetation fraction gradient"
-    ],
-    [
-        "129200",
-        "vsogrd",
-        "variance of sub-gridscale orography gradient"
-    ],
-    [
-        "129201",
-        "mx2tgrd",
-        "maximum temperature at 2 metres since previous post-processing gradient"
-    ],
-    [
-        "129202",
-        "mn2tgrd",
-        "minimum temperature at 2 metres since previous post-processing gradient"
-    ],
-    [
-        "129203",
-        "o3grd",
-        "ozone mass mixing ratio gradient"
-    ],
-    [
-        "129204",
-        "pawgrd",
-        "precipitation analysis weights gradient"
-    ],
-    [
-        "129205",
-        "rogrd",
-        "runoff gradient"
-    ],
-    [
-        "129206",
-        "tco3grd",
-        "total column ozone gradient"
-    ],
-    [
-        "129207",
-        "10sigrd",
-        "10 metre wind speed gradient"
-    ],
-    [
-        "129208",
-        "tsrcgrd",
-        "top net solar radiation, clear sky gradient"
-    ],
-    [
-        "129209",
-        "ttrcgrd",
-        "top net thermal radiation, clear sky gradient"
-    ],
-    [
-        "129210",
-        "ssrcgrd",
-        "surface net solar radiation, clear sky gradient"
-    ],
-    [
-        "129211",
-        "strcgrd",
-        "surface net thermal radiation, clear sky gradient"
-    ],
-    [
-        "129212",
-        "tisrgrd",
-        "toa incident solar radiation gradient"
-    ],
-    [
-        "129214",
-        "dhrgrd",
-        "diabatic heating by radiation gradient"
-    ],
-    [
-        "129215",
-        "dhvdgrd",
-        "diabatic heating by vertical diffusion gradient"
-    ],
-    [
-        "129216",
-        "dhccgrd",
-        "diabatic heating by cumulus convection gradient"
-    ],
-    [
-        "129217",
-        "dhlcgrd",
-        "diabatic heating large-scale condensation gradient"
-    ],
-    [
-        "129218",
-        "vdzwgrd",
-        "vertical diffusion of zonal wind gradient"
-    ],
-    [
-        "129219",
-        "vdmwgrd",
-        "vertical diffusion of meridional wind gradient"
-    ],
-    [
-        "129220",
-        "ewgdgrd",
-        "east-west gravity wave drag tendency gradient"
-    ],
-    [
-        "129221",
-        "nsgdgrd",
-        "north-south gravity wave drag tendency gradient"
-    ],
-    [
-        "129222",
-        "ctzwgrd",
-        "convective tendency of zonal wind gradient"
-    ],
-    [
-        "129223",
-        "ctmwgrd",
-        "convective tendency of meridional wind gradient"
-    ],
-    [
-        "129224",
-        "vdhgrd",
-        "vertical diffusion of humidity gradient"
-    ],
-    [
-        "129225",
-        "htccgrd",
-        "humidity tendency by cumulus convection gradient"
-    ],
-    [
-        "129226",
-        "htlcgrd",
-        "humidity tendency by large-scale condensation gradient"
-    ],
-    [
-        "129227",
-        "crnhgrd",
-        "change from removal of negative humidity gradient"
-    ],
-    [
-        "129228",
-        "tpgrd",
-        "total precipitation gradient"
-    ],
-    [
-        "129229",
-        "iewsgrd",
-        "instantaneous x surface stress gradient"
-    ],
-    [
-        "129230",
-        "inssgrd",
-        "instantaneous y surface stress gradient"
-    ],
-    [
-        "129231",
-        "ishfgrd",
-        "instantaneous surface heat flux gradient"
-    ],
-    [
-        "129232",
-        "iegrd",
-        "instantaneous moisture flux gradient"
-    ],
-    [
-        "129233",
-        "asqgrd",
-        "apparent surface humidity gradient"
-    ],
-    [
-        "129234",
-        "lsrhgrd",
-        "logarithm of surface roughness length for heat gradient"
-    ],
-    [
-        "129235",
-        "sktgrd",
-        "skin temperature gradient"
-    ],
-    [
-        "129236",
-        "stl4grd",
-        "soil temperature level 4 gradient"
-    ],
-    [
-        "129237",
-        "swl4grd",
-        "soil wetness level 4 gradient"
-    ],
-    [
-        "129238",
-        "tsngrd",
-        "temperature of snow layer gradient"
-    ],
-    [
-        "129239",
-        "csfgrd",
-        "convective snowfall gradient"
-    ],
-    [
-        "129240",
-        "lsfgrd",
-        "large scale snowfall gradient"
-    ],
-    [
-        "129241",
-        "acfgrd",
-        "accumulated cloud fraction tendency gradient"
-    ],
-    [
-        "129242",
-        "alwgrd",
-        "accumulated liquid water tendency gradient"
-    ],
-    [
-        "129243",
-        "falgrd",
-        "forecast albedo gradient"
-    ],
-    [
-        "129244",
-        "fsrgrd",
-        "forecast surface roughness gradient"
-    ],
-    [
-        "129245",
-        "flsrgrd",
-        "forecast logarithm of surface roughness for heat gradient"
-    ],
-    [
-        "129246",
-        "clwcgrd",
-        "specific cloud liquid water content gradient"
-    ],
-    [
-        "129247",
-        "ciwcgrd",
-        "specific cloud ice water content gradient"
-    ],
-    [
-        "129248",
-        "ccgrd",
-        "cloud cover gradient"
-    ],
-    [
-        "129249",
-        "aiwgrd",
-        "accumulated ice water tendency gradient"
-    ],
-    [
-        "129250",
-        "icegrd",
-        "ice age gradient"
-    ],
-    [
-        "129251",
-        "attegrd",
-        "adiabatic tendency of temperature gradient"
-    ],
-    [
-        "129252",
-        "athegrd",
-        "adiabatic tendency of humidity gradient"
-    ],
-    [
-        "129253",
-        "atzegrd",
-        "adiabatic tendency of zonal wind gradient"
-    ],
-    [
-        "129254",
-        "atmwgrd",
-        "adiabatic tendency of meridional wind gradient"
-    ],
-    [
-        "130208",
-        "tsru",
-        "top solar radiation upward"
-    ],
-    [
-        "130209",
-        "ttru",
-        "top thermal radiation upward"
-    ],
-    [
-        "130210",
-        "tsuc",
-        "top solar radiation upward, clear sky"
-    ],
-    [
-        "130211",
-        "ttuc",
-        "top thermal radiation upward, clear sky"
-    ],
-    [
-        "130212",
-        "clw",
-        "cloud liquid water"
-    ],
-    [
-        "130213",
-        "cf",
-        "cloud fraction"
-    ],
-    [
-        "130214",
-        "dhr",
-        "diabatic heating by radiation"
-    ],
-    [
-        "130215",
-        "dhvd",
-        "diabatic heating by vertical diffusion"
-    ],
-    [
-        "130216",
-        "dhcc",
-        "diabatic heating by cumulus convection"
-    ],
-    [
-        "130217",
-        "dhlc",
-        "diabatic heating by large-scale condensation"
-    ],
-    [
-        "130218",
-        "vdzw",
-        "vertical diffusion of zonal wind"
-    ],
-    [
-        "130219",
-        "vdmw",
-        "vertical diffusion of meridional wind"
-    ],
-    [
-        "130220",
-        "ewgd",
-        "east-west gravity wave drag"
-    ],
-    [
-        "130221",
-        "nsgd",
-        "north-south gravity wave drag"
-    ],
-    [
-        "130224",
-        "vdh",
-        "vertical diffusion of humidity"
-    ],
-    [
-        "130225",
-        "htcc",
-        "humidity tendency by cumulus convection"
-    ],
-    [
-        "130226",
-        "htlc",
-        "humidity tendency by large-scale condensation"
-    ],
-    [
-        "130228",
-        "att",
-        "adiabatic tendency of temperature"
-    ],
-    [
-        "130229",
-        "ath",
-        "adiabatic tendency of humidity"
-    ],
-    [
-        "130230",
-        "atzw",
-        "adiabatic tendency of zonal wind"
-    ],
-    [
-        "130231",
-        "atmwax",
-        "adiabatic tendency of meridional wind"
-    ],
-    [
-        "130232",
-        "mvv",
-        "mean vertical velocity"
-    ],
-    [
-        "131001",
-        "2tag2",
-        "2m temperature anomaly of at least +2k"
-    ],
-    [
-        "131002",
-        "2tag1",
-        "2m temperature anomaly of at least +1k"
-    ],
-    [
-        "131003",
-        "2tag0",
-        "2m temperature anomaly of at least 0k"
-    ],
-    [
-        "131004",
-        "2talm1",
-        "2m temperature anomaly of at most -1k"
-    ],
-    [
-        "131005",
-        "2talm2",
-        "2m temperature anomaly of at most -2k"
-    ],
-    [
-        "131006",
-        "tpag20",
-        "total precipitation anomaly of at least 20 mm"
-    ],
-    [
-        "131007",
-        "tpag10",
-        "total precipitation anomaly of at least 10 mm"
-    ],
-    [
-        "131008",
-        "tpag0",
-        "total precipitation anomaly of at least 0 mm"
-    ],
-    [
-        "131009",
-        "stag0",
-        "surface temperature anomaly of at least 0k"
-    ],
-    [
-        "131010",
-        "mslag0",
-        "mean sea level pressure anomaly of at least 0 pa"
-    ],
-    [
-        "131015",
-        "h0dip",
-        "height of 0 degree isotherm probability"
-    ],
-    [
-        "131016",
-        "hslp",
-        "height of snowfall limit probability"
-    ],
-    [
-        "131017",
-        "saip",
-        "showalter index probability"
-    ],
-    [
-        "131018",
-        "whip",
-        "whiting index probability"
-    ],
-    [
-        "131020",
-        "talm2",
-        "temperature anomaly less than -2 k",
-        "temperature anomaly of at most -2 k",
-        "talm2k"
-    ],
-    [
-        "131021",
-        "tag2",
-        "temperature anomaly of at least +2 k",
-        "temperature anomaly of at least 2 k",
-        "tag2k"
-    ],
-    [
-        "131022",
-        "talm8",
-        "temperature anomaly less than -8 k",
-        "temperature anomaly of at most -8 k",
-        "talm8k"
-    ],
-    [
-        "131023",
-        "talm4",
-        "temperature anomaly less than -4 k",
-        "temperature anomaly of at most -4 k",
-        "talm4k"
-    ],
-    [
-        "131024",
-        "tag4",
-        "temperature anomaly greater than +4 k",
-        "temperature anomaly of at least 4 k",
-        "tag4k"
-    ],
-    [
-        "131025",
-        "tag8",
-        "temperature anomaly greater than +8 k",
-        "temperature anomaly of at least 8 k",
-        "tag8k"
-    ],
-    [
-        "131049",
-        "10gp",
-        "10 metre wind gust probability"
-    ],
-    [
-        "131059",
-        "capep",
-        "convective available potential energy probability"
-    ],
-    [
-        "131060",
-        "tpg1",
-        "total precipitation of at least 1 mm"
-    ],
-    [
-        "131061",
-        "tpg5",
-        "total precipitation of at least 5 mm"
-    ],
-    [
-        "131062",
-        "tpg10",
-        "total precipitation of at least 10 mm"
-    ],
-    [
-        "131063",
-        "tpg20",
-        "total precipitation of at least 20 mm"
-    ],
-    [
-        "131064",
-        "tpl01",
-        "total precipitation less than 0.1 mm",
-        "tplo1"
-    ],
-    [
-        "131065",
-        "tprl1",
-        "total precipitation rate less than 1 mm/day"
-    ],
-    [
-        "131066",
-        "tprg3",
-        "total precipitation rate of at least 3 mm/day"
-    ],
-    [
-        "131067",
-        "tprg5",
-        "total precipitation rate of at least 5 mm/day"
-    ],
-    [
-        "131068",
-        "10spg10",
-        "10 metre wind speed of at least 10 m/s"
-    ],
-    [
-        "131069",
-        "10spg15",
-        "10 metre wind speed of at least 15 m/s"
-    ],
-    [
-        "131070",
-        "10fgg15",
-        "10 metre wind gust of at least 15 m/s"
-    ],
-    [
-        "131071",
-        "10fgg20",
-        "10 metre wind gust of at least 20 m/s"
-    ],
-    [
-        "131072",
-        "10fgg25",
-        "10 metre wind gust of at least 25 m/s"
-    ],
-    [
-        "131073",
-        "2tl273",
-        "2 metre temperature less than 273.15 k"
-    ],
-    [
-        "131074",
-        "swhg2",
-        "significant wave height of at least 2 m"
-    ],
-    [
-        "131075",
-        "swhg4",
-        "significant wave height of at least 4 m"
-    ],
-    [
-        "131076",
-        "swhg6",
-        "significant wave height of at least 6 m"
-    ],
-    [
-        "131077",
-        "swhg8",
-        "significant wave height of at least 8 m"
-    ],
-    [
-        "131078",
-        "mwpg8",
-        "mean wave period of at least 8 s"
-    ],
-    [
-        "131079",
-        "mwpg10",
-        "mean wave period of at least 10 s"
-    ],
-    [
-        "131080",
-        "mwpg12",
-        "mean wave period of at least 12 s"
-    ],
-    [
-        "131081",
-        "mwpg15",
-        "mean wave period of at least 15 s"
-    ],
-    [
-        "131082",
-        "tpg40",
-        "total precipitation of at least 40 mm"
-    ],
-    [
-        "131083",
-        "tpg60",
-        "total precipitation of at least 60 mm"
-    ],
-    [
-        "131084",
-        "tpg80",
-        "total precipitation of at least 80 mm"
-    ],
-    [
-        "131085",
-        "tpg100",
-        "total precipitation of at least 100 mm"
-    ],
-    [
-        "131086",
-        "tpg150",
-        "total precipitation of at least 150 mm"
-    ],
-    [
-        "131087",
-        "tpg200",
-        "total precipitation of at least 200 mm"
-    ],
-    [
-        "131088",
-        "tpg300",
-        "total precipitation of at least 300 mm"
-    ],
-    [
-        "131129",
-        "zp",
-        "geopotential probability"
-    ],
-    [
-        "131130",
-        "tap",
-        "temperature anomaly probability"
-    ],
-    [
-        "131139",
-        "stl1p",
-        "soil temperature level 1 probability"
-    ],
-    [
-        "131144",
-        "sfp",
-        "snowfall (convective + stratiform) probability"
-    ],
-    [
-        "131151",
-        "mslpp",
-        "mean sea level pressure probability"
-    ],
-    [
-        "131164",
-        "tccp",
-        "total cloud cover probability"
-    ],
-    [
-        "131165",
-        "10sp",
-        "10 metre speed probability"
-    ],
-    [
-        "131167",
-        "2tp",
-        "2 metre temperature probability"
-    ],
-    [
-        "131201",
-        "mx2tp",
-        "maximum 2 metre temperature probability"
-    ],
-    [
-        "131202",
-        "mn2tp",
-        "minimum 2 metre temperature probability"
-    ],
-    [
-        "131228",
-        "tpp",
-        "total precipitation probability"
-    ],
-    [
-        "131229",
-        "swhp",
-        "significant wave height probability"
-    ],
-    [
-        "131232",
-        "mwpp",
-        "mean wave period probability"
-    ],
-    [
-        "132049",
-        "10fgi",
-        "10 metre wind gust index",
-        "49.132",
-        "10gi"
-    ],
-    [
-        "132144",
-        "sfi",
-        "snowfall index",
-        "144.132"
-    ],
-    [
-        "132165",
-        "10wsi",
-        "10 metre speed index",
-        "165.132"
-    ],
-    [
-        "132167",
-        "2ti",
-        "2 metre temperature index",
-        "167.132"
-    ],
-    [
-        "214001",
-        "uvcossza",
-        " cosine of solar zenith angle"
-    ],
-    [
-        "132201",
-        "mx2ti",
-        "maximum temperature at 2 metres index",
-        "201.132"
-    ],
-    [
-        "132202",
-        "mn2ti",
-        "minimum temperature at 2 metres index",
-        "202.132"
-    ],
-    [
-        "132228",
-        "tpi",
-        "total precipitation index"
-    ],
-    [
-        "133001",
-        "2tplm10",
-        "2m temperature probability less than -10 c"
-    ],
-    [
-        "133002",
-        "2tplm5",
-        "2m temperature probability less than -5 c"
-    ],
-    [
-        "133003",
-        "2tpl0",
-        "2m temperature probability less than 0 c"
-    ],
-    [
-        "133004",
-        "2tpl5",
-        "2m temperature probability less than 5 c"
-    ],
-    [
-        "133005",
-        "2tpl10",
-        "2m temperature probability less than 10 c"
-    ],
-    [
-        "133006",
-        "2tpg25",
-        "2m temperature probability greater than 25 c"
-    ],
-    [
-        "133007",
-        "2tpg30",
-        "2m temperature probability greater than 30 c"
-    ],
-    [
-        "133008",
-        "2tpg35",
-        "2m temperature probability greater than 35 c"
-    ],
-    [
-        "133009",
-        "2tpg40",
-        "2m temperature probability greater than 40 c"
-    ],
-    [
-        "133010",
-        "2tpg45",
-        "2m temperature probability greater than 45 c"
-    ],
-    [
-        "133011",
-        "mn2tplm10",
-        "minimum 2 metre temperature probability less than -10 c"
-    ],
-    [
-        "133012",
-        "mn2tplm5",
-        "minimum 2 metre temperature probability less than -5 c"
-    ],
-    [
-        "133013",
-        "mn2tpl0",
-        "minimum 2 metre temperature probability less than 0 c"
-    ],
-    [
-        "133014",
-        "mn2tpl5",
-        "minimum 2 metre temperature probability less than 5 c"
-    ],
-    [
-        "133015",
-        "mn2tpl10",
-        "minimum 2 metre temperature probability less than 10 c"
-    ],
-    [
-        "133016",
-        "mx2tpg25",
-        "maximum 2 metre temperature probability greater than 25 c"
-    ],
-    [
-        "133017",
-        "mx2tpg30",
-        "maximum 2 metre temperature probability greater than 30 c"
-    ],
-    [
-        "133018",
-        "mx2tpg35",
-        "maximum 2 metre temperature probability greater than 35 c"
-    ],
-    [
-        "133019",
-        "mx2tpg40",
-        "maximum 2 metre temperature probability greater than 40 c"
-    ],
-    [
-        "133020",
-        "mx2tpg45",
-        "maximum 2 metre temperature probability greater than 45 c"
-    ],
-    [
-        "133021",
-        "10spg10",
-        "10 metre wind speed probability of at least 10 m/s"
-    ],
-    [
-        "133022",
-        "10spg15",
-        "10 metre wind speed probability of at least 15 m/s"
-    ],
-    [
-        "133023",
-        "10spg20",
-        "10 metre wind speed probability of at least 20 m/s"
-    ],
-    [
-        "133024",
-        "10spg35",
-        "10 metre wind speed probability of at least 35 m/s"
-    ],
-    [
-        "133025",
-        "10spg50",
-        "10 metre wind speed probability of at least 50 m/s"
-    ],
-    [
-        "133026",
-        "10gpg20",
-        "10 metre wind gust probability of at least 20 m/s"
-    ],
-    [
-        "133027",
-        "10gpg35",
-        "10 metre wind gust probability of at least 35 m/s"
-    ],
-    [
-        "133028",
-        "10gpg50",
-        "10 metre wind gust probability of at least 50 m/s"
-    ],
-    [
-        "133029",
-        "10gpg75",
-        "10 metre wind gust probability of at least 75 m/s"
-    ],
-    [
-        "133030",
-        "10gpg100",
-        "10 metre wind gust probability of at least 100 m/s"
-    ],
-    [
-        "133031",
-        "tppg1",
-        "total precipitation probability of at least 1 mm"
-    ],
-    [
-        "133032",
-        "tppg5",
-        "total precipitation probability of at least 5 mm"
-    ],
-    [
-        "133033",
-        "tppg10",
-        "total precipitation probability of at least 10 mm"
-    ],
-    [
-        "133034",
-        "tppg20",
-        "total precipitation probability of at least 20 mm"
-    ],
-    [
-        "133035",
-        "tppg40",
-        "total precipitation probability of at least 40 mm"
-    ],
-    [
-        "133036",
-        "tppg60",
-        "total precipitation probability of at least 60 mm"
-    ],
-    [
-        "133037",
-        "tppg80",
-        "total precipitation probability of at least 80 mm"
-    ],
-    [
-        "133038",
-        "tppg100",
-        "total precipitation probability of at least 100 mm"
-    ],
-    [
-        "133039",
-        "tppg150",
-        "total precipitation probability of at least 150 mm"
-    ],
-    [
-        "133040",
-        "tppg200",
-        "total precipitation probability of at least 200 mm"
-    ],
-    [
-        "133041",
-        "tppg300",
-        "total precipitation probability of at least 300 mm"
-    ],
-    [
-        "133042",
-        "sfpg1",
-        "snowfall probability of at least 1 mm"
-    ],
-    [
-        "133043",
-        "sfpg5",
-        "snowfall probability of at least 5 mm"
-    ],
-    [
-        "133044",
-        "sfpg10",
-        "snowfall probability of at least 10 mm"
-    ],
-    [
-        "133045",
-        "sfpg20",
-        "snowfall probability of at least 20 mm"
-    ],
-    [
-        "133046",
-        "sfpg40",
-        "snowfall probability of at least 40 mm"
-    ],
-    [
-        "133047",
-        "sfpg60",
-        "snowfall probability of at least 60 mm"
-    ],
-    [
-        "133048",
-        "sfpg80",
-        "snowfall probability of at least 80 mm"
-    ],
-    [
-        "133049",
-        "sfpg100",
-        "snowfall probability of at least 100 mm"
-    ],
-    [
-        "133050",
-        "sfpg150",
-        "snowfall probability of at least 150 mm"
-    ],
-    [
-        "133051",
-        "sfpg200",
-        "snowfall probability of at least 200 mm"
-    ],
-    [
-        "133052",
-        "sfpg300",
-        "snowfall probability of at least 300 mm"
-    ],
-    [
-        "133053",
-        "tccpg10",
-        "total cloud cover probability greater than 10%"
-    ],
-    [
-        "133054",
-        "tccpg20",
-        "total cloud cover probability greater than 20%"
-    ],
-    [
-        "133055",
-        "tccpg30",
-        "total cloud cover probability greater than 30%"
-    ],
-    [
-        "133056",
-        "tccpg40",
-        "total cloud cover probability greater than 40%"
-    ],
-    [
-        "133057",
-        "tccpg50",
-        "total cloud cover probability greater than 50%"
-    ],
-    [
-        "133058",
-        "tccpg60",
-        "total cloud cover probability greater than 60%"
-    ],
-    [
-        "133059",
-        "tccpg70",
-        "total cloud cover probability greater than 70%"
-    ],
-    [
-        "133060",
-        "tccpg80",
-        "total cloud cover probability greater than 80%"
-    ],
-    [
-        "133061",
-        "tccpg90",
-        "total cloud cover probability greater than 90%"
-    ],
-    [
-        "133062",
-        "tccpg99",
-        "total cloud cover probability greater than 99%"
-    ],
-    [
-        "133063",
-        "hccpg10",
-        "high cloud cover probability greater than 10%"
-    ],
-    [
-        "133064",
-        "hccpg20",
-        "high cloud cover probability greater than 20%"
-    ],
-    [
-        "133065",
-        "hccpg30",
-        "high cloud cover probability greater than 30%"
-    ],
-    [
-        "133066",
-        "hccpg40",
-        "high cloud cover probability greater than 40%"
-    ],
-    [
-        "133067",
-        "hccpg50",
-        "high cloud cover probability greater than 50%"
-    ],
-    [
-        "133068",
-        "hccpg60",
-        "high cloud cover probability greater than 60%"
-    ],
-    [
-        "133069",
-        "hccpg70",
-        "high cloud cover probability greater than 70%"
-    ],
-    [
-        "133070",
-        "hccpg80",
-        "high cloud cover probability greater than 80%"
-    ],
-    [
-        "133071",
-        "hccpg90",
-        "high cloud cover probability greater than 90%"
-    ],
-    [
-        "133072",
-        "hccpg99",
-        "high cloud cover probability greater than 99%"
-    ],
-    [
-        "133073",
-        "mccpg10",
-        "medium cloud cover probability greater than 10%"
-    ],
-    [
-        "133074",
-        "mccpg20",
-        "medium cloud cover probability greater than 20%"
-    ],
-    [
-        "133075",
-        "mccpg30",
-        "medium cloud cover probability greater than 30%"
-    ],
-    [
-        "133076",
-        "mccpg40",
-        "medium cloud cover probability greater than 40%"
-    ],
-    [
-        "133077",
-        "mccpg50",
-        "medium cloud cover probability greater than 50%"
-    ],
-    [
-        "133078",
-        "mccpg60",
-        "medium cloud cover probability greater than 60%"
-    ],
-    [
-        "133079",
-        "mccpg70",
-        "medium cloud cover probability greater than 70%"
-    ],
-    [
-        "133080",
-        "mccpg80",
-        "medium cloud cover probability greater than 80%"
-    ],
-    [
-        "133081",
-        "mccpg90",
-        "medium cloud cover probability greater than 90%"
-    ],
-    [
-        "133082",
-        "mccpg99",
-        "medium cloud cover probability greater than 99%"
-    ],
-    [
-        "133083",
-        "lccpg10",
-        "low cloud cover probability greater than 10%"
-    ],
-    [
-        "133084",
-        "lccpg20",
-        "low cloud cover probability greater than 20%"
-    ],
-    [
-        "133085",
-        "lccpg30",
-        "low cloud cover probability greater than 30%"
-    ],
-    [
-        "133086",
-        "lccpg40",
-        "low cloud cover probability greater than 40%"
-    ],
-    [
-        "133087",
-        "lccpg50",
-        "low cloud cover probability greater than 50%"
-    ],
-    [
-        "133088",
-        "lccpg60",
-        "low cloud cover probability greater than 60%"
-    ],
-    [
-        "133089",
-        "lccpg70",
-        "low cloud cover probability greater than 70%"
-    ],
-    [
-        "133090",
-        "lccpg80",
-        "low cloud cover probability greater than 80%"
-    ],
-    [
-        "133091",
-        "lccpg90",
-        "low cloud cover probability greater than 90%"
-    ],
-    [
-        "133092",
-        "lccpg99",
-        "low cloud cover probability greater than 99%"
-    ],
-    [
-        "140200",
-        "maxswh",
-        "maximum of significant wave height"
-    ],
-    [
-        "140217",
-        "tmax",
-        "period corresponding to maximum individual wave height"
-    ],
-    [
-        "140218",
-        "hmax",
-        "maximum individual wave height"
-    ],
-    [
-        "140219",
-        "wmb",
-        "model bathymetry"
-    ],
-    [
-        "140220",
-        "mp1",
-        "mean wave period based on first moment"
-    ],
-    [
-        "140221",
-        "mp2",
-        "mean wave period based on second moment"
-    ],
-    [
-        "140222",
-        "wdw",
-        "wave spectral directional width"
-    ],
-    [
-        "140223",
-        "p1ww",
-        "mean wave period based on first moment for wind waves"
-    ],
-    [
-        "140224",
-        "p2ww",
-        "mean wave period based on second moment for wind waves"
-    ],
-    [
-        "140225",
-        "dwww",
-        "wave spectral directional width for wind waves"
-    ],
-    [
-        "140226",
-        "p1ps",
-        "mean wave period based on first moment for swell"
-    ],
-    [
-        "140227",
-        "p2ps",
-        "mean wave period based on second moment for swell"
-    ],
-    [
-        "140228",
-        "dwps",
-        "wave spectral directional width for swell"
-    ],
-    [
-        "140229",
-        "swh",
-        "significant height of combined wind waves and swell"
-    ],
-    [
-        "140230",
-        "mwd",
-        "mean wave direction"
-    ],
-    [
-        "140231",
-        "pp1d",
-        "peak period of 1d spectra"
-    ],
-    [
-        "140232",
-        "mwp",
-        "mean wave period"
-    ],
-    [
-        "140233",
-        "cdww",
-        "coefficient of drag with waves"
-    ],
-    [
-        "140234",
-        "shww",
-        "significant height of wind waves"
-    ],
-    [
-        "140235",
-        "mdww",
-        "mean direction of wind waves"
-    ],
-    [
-        "140236",
-        "mpww",
-        "mean period of wind waves"
-    ],
-    [
-        "140237",
-        "shts",
-        "significant height of total swell"
-    ],
-    [
-        "140238",
-        "mdts",
-        "mean direction of total swell"
-    ],
-    [
-        "140239",
-        "mpts",
-        "mean period of total swell"
-    ],
-    [
-        "140240",
-        "sdhs",
-        "standard deviation wave height"
-    ],
-    [
-        "140241",
-        "mu10",
-        "mean of 10 metre wind speed"
-    ],
-    [
-        "140242",
-        "mdwi",
-        "mean wind direction"
-    ],
-    [
-        "140243",
-        "sdu",
-        "standard deviation of 10 metre wind speed"
-    ],
-    [
-        "140244",
-        "msqs",
-        "mean square slope of waves"
-    ],
-    [
-        "140245",
-        "wind",
-        "10 metre wind speed"
-    ],
-    [
-        "140246",
-        "awh",
-        "altimeter wave height"
-    ],
-    [
-        "140247",
-        "acwh",
-        "altimeter corrected wave height"
-    ],
-    [
-        "140248",
-        "arrc",
-        "altimeter range relative correction"
-    ],
-    [
-        "140249",
-        "dwi",
-        "10 metre wind direction"
-    ],
-    [
-        "140250",
-        "2dsp",
-        "2d wave spectra (multiple)"
-    ],
-    [
-        "140251",
-        "2dfd",
-        "2d wave spectra (single)"
-    ],
-    [
-        "140252",
-        "wsk",
-        "wave spectral kurtosis"
-    ],
-    [
-        "140253",
-        "bfi",
-        "benjamin-feir index"
-    ],
-    [
-        "140254",
-        "wsp",
-        "wave spectral peakedness"
-    ],
-    [
-        "150129",
-        "ocpt",
-        "ocean potential temperature"
-    ],
-    [
-        "150130",
-        "ocs",
-        "ocean salinity"
-    ],
-    [
-        "150131",
-        "ocpd",
-        "ocean potential density"
-    ],
-    [
-        "150133",
-        "ocu",
-        "ocean u wind component"
-    ],
-    [
-        "150134",
-        "ocv",
-        "ocean v wind component"
-    ],
-    [
-        "150135",
-        "ocw",
-        "ocean w wind component"
-    ],
-    [
-        "150137",
-        "rn",
-        "richardson number"
-    ],
-    [
-        "150139",
-        "uv",
-        "u*v product"
-    ],
-    [
-        "150140",
-        "ut",
-        "u*t product"
-    ],
-    [
-        "150141",
-        "vt",
-        "v*t product"
-    ],
-    [
-        "150142",
-        "uu",
-        "u*u product"
-    ],
-    [
-        "150143",
-        "vv",
-        "v*v product"
-    ],
-    [
-        "150144",
-        "uv - u~v~"
-    ],
-    [
-        "150145",
-        "ut - u~t~"
-    ],
-    [
-        "150146",
-        "vt - v~t~"
-    ],
-    [
-        "150147",
-        "uu - u~u~"
-    ],
-    [
-        "150148",
-        "vv - v~v~"
-    ],
-    [
-        "150152",
-        "sl",
-        "sea level"
-    ],
-    [
-        "150153",
-        "barotropic stream function"
-    ],
-    [
-        "150154",
-        "mld",
-        "mixed layer depth"
-    ],
-    [
-        "150155",
-        "depth"
-    ],
-    [
-        "150168",
-        "u stress"
-    ],
-    [
-        "150169",
-        "v stress"
-    ],
-    [
-        "150170",
-        "turbulent kinetic energy input"
-    ],
-    [
-        "150171",
-        "nsf",
-        "net surface heat flux"
-    ],
-    [
-        "150172",
-        "surface solar radiation"
-    ],
-    [
-        "150173",
-        "p-e"
-    ],
-    [
-        "150180",
-        "diagnosed sea surface temperature error"
-    ],
-    [
-        "150181",
-        "heat flux correction"
-    ],
-    [
-        "150182",
-        "observed sea surface temperature"
-    ],
-    [
-        "150183",
-        "observed heat flux"
-    ],
-    [
-        "151128",
-        "in situ temperature"
-    ],
-    [
-        "151129",
-        "ocpt",
-        "ocean potential temperature"
-    ],
-    [
-        "151130",
-        "s",
-        "salinity"
-    ],
-    [
-        "151131",
-        "ocu",
-        "ocean current zonal component"
-    ],
-    [
-        "151132",
-        "ocv",
-        "ocean current meridional component"
-    ],
-    [
-        "151133",
-        "ocw",
-        "ocean current vertical component"
-    ],
-    [
-        "151134",
-        "mst",
-        "modulus of strain rate tensor"
-    ],
-    [
-        "151135",
-        "vvs",
-        "vertical viscosity"
-    ],
-    [
-        "151136",
-        "vdf",
-        "vertical diffusivity"
-    ],
-    [
-        "151137",
-        "dep",
-        "bottom level depth"
-    ],
-    [
-        "151138",
-        "sth",
-        "sigma-theta"
-    ],
-    [
-        "151139",
-        "rn",
-        "richardson number"
-    ],
-    [
-        "151140",
-        "uv",
-        "uv product"
-    ],
-    [
-        "151141",
-        "ut",
-        "ut product"
-    ],
-    [
-        "151142",
-        "vt",
-        "vt product"
-    ],
-    [
-        "151143",
-        "uu",
-        "uu product"
-    ],
-    [
-        "151144",
-        "vv",
-        "vv product"
-    ],
-    [
-        "151145",
-        "sl",
-        "sea level"
-    ],
-    [
-        "151146",
-        "sl_1",
-        "sea level previous timestep"
-    ],
-    [
-        "151147",
-        "bsf",
-        "barotropic stream function"
-    ],
-    [
-        "151148",
-        "mld",
-        "mixed layer depth"
-    ],
-    [
-        "151149",
-        "btp",
-        "bottom pressure (equivalent height)"
-    ],
-    [
-        "151150",
-        "sh",
-        "steric height"
-    ],
-    [
-        "151151",
-        "crl",
-        "curl of wind stress"
-    ],
-    [
-        "151152",
-        "divergence of wind stress"
-    ],
-    [
-        "151153",
-        "tax",
-        "u stress"
-    ],
-    [
-        "151154",
-        "tay",
-        "v stress"
-    ],
-    [
-        "151155",
-        "tki",
-        "turbulent kinetic energy input"
-    ],
-    [
-        "151156",
-        "nsf",
-        "net surface heat flux"
-    ],
-    [
-        "151157",
-        "asr",
-        "absorbed solar radiation"
-    ],
-    [
-        "151158",
-        "pme",
-        "precipitation - evaporation"
-    ],
-    [
-        "151159",
-        "sst",
-        "specified sea surface temperature"
-    ],
-    [
-        "151160",
-        "shf",
-        "specified surface heat flux"
-    ],
-    [
-        "151161",
-        "dte",
-        "diagnosed sea surface temperature error"
-    ],
-    [
-        "151162",
-        "hfc",
-        "heat flux correction"
-    ],
-    [
-        "151163",
-        "20d",
-        "20 degrees isotherm depth"
-    ],
-    [
-        "151164",
-        "tav300",
-        "average potential temperature in the upper 300m"
-    ],
-    [
-        "151165",
-        "uba1",
-        "vertically integrated zonal velocity (previous time step)"
-    ],
-    [
-        "151166",
-        "vba1",
-        "vertically integrated meridional velocity (previous time step)"
-    ],
-    [
-        "151167",
-        "ztr",
-        "vertically integrated zonal volume transport"
-    ],
-    [
-        "151168",
-        "mtr",
-        "vertically integrated meridional volume transport"
-    ],
-    [
-        "151169",
-        "zht",
-        "vertically integrated zonal heat transport"
-    ],
-    [
-        "151170",
-        "mht",
-        "vertically integrated meridional heat transport"
-    ],
-    [
-        "151171",
-        "umax",
-        "u velocity maximum"
-    ],
-    [
-        "151172",
-        "dumax",
-        "depth of the velocity maximum"
-    ],
-    [
-        "151173",
-        "smax",
-        "salinity maximum"
-    ],
-    [
-        "151174",
-        "dsmax",
-        "depth of salinity maximum"
-    ],
-    [
-        "151175",
-        "sav300",
-        "average salinity in the upper 300m"
-    ],
-    [
-        "151176",
-        "ldp",
-        "layer thickness at scalar points"
-    ],
-    [
-        "151177",
-        "ldu",
-        "layer thickness at vector points"
-    ],
-    [
-        "151178",
-        "pti",
-        "potential temperature increment"
-    ],
-    [
-        "151179",
-        "ptae",
-        "potential temperature analysis error"
-    ],
-    [
-        "151180",
-        "bpt",
-        "background potential temperature"
-    ],
-    [
-        "151181",
-        "apt",
-        "analysed potential temperature"
-    ],
-    [
-        "151182",
-        "ptbe",
-        "potential temperature background error"
-    ],
-    [
-        "151183",
-        "as",
-        "analysed salinity"
-    ],
-    [
-        "151184",
-        "sali",
-        "salinity increment"
-    ],
-    [
-        "151185",
-        "ebt",
-        "estimated bias in temperature"
-    ],
-    [
-        "151186",
-        "ebs",
-        "estimated bias in salinity"
-    ],
-    [
-        "151187",
-        "uvi",
-        "zonal velocity increment (from balance operator)"
-    ],
-    [
-        "151188",
-        "vvi",
-        "meridional velocity increment (from balance operator)"
-    ],
-    [
-        "151190",
-        "subi",
-        "salinity increment (from salinity data)"
-    ],
-    [
-        "151191",
-        "sale",
-        "salinity analysis error"
-    ],
-    [
-        "151192",
-        "bsal",
-        "background salinity"
-    ],
-    [
-        "151194",
-        "salbe",
-        "salinity background error"
-    ],
-    [
-        "151199",
-        "ebta",
-        "estimated temperature bias from assimilation"
-    ],
-    [
-        "151200",
-        "ebsa",
-        "estimated salinity bias from assimilation"
-    ],
-    [
-        "151201",
-        "lti",
-        "temperature increment from relaxation term"
-    ],
-    [
-        "151202",
-        "lsi",
-        "salinity increment from relaxation term"
-    ],
-    [
-        "151203",
-        "bzpga",
-        "bias in the zonal pressure gradient (applied)"
-    ],
-    [
-        "151204",
-        "bmpga",
-        "bias in the meridional pressure gradient (applied)"
-    ],
-    [
-        "151205",
-        "ebtl",
-        "estimated temperature bias from relaxation"
-    ],
-    [
-        "151206",
-        "ebsl",
-        "estimated salinity bias from relaxation"
-    ],
-    [
-        "151207",
-        "fgbt",
-        "first guess bias in temperature"
-    ],
-    [
-        "151208",
-        "fgbs",
-        "first guess bias in salinity"
-    ],
-    [
-        "151209",
-        "bpa",
-        "applied bias in pressure"
-    ],
-    [
-        "151210",
-        "fgbp",
-        "fg bias in pressure"
-    ],
-    [
-        "151211",
-        "pta",
-        "bias in temperature(applied)"
-    ],
-    [
-        "151212",
-        "psa",
-        "bias in salinity (applied)"
-    ],
-    [
-        "160049",
-        "10fgrea",
-        "10 metre wind gust during averaging time"
-    ],
-    [
-        "160135",
-        "wrea",
-        "vertical velocity (pressure)"
-    ],
-    [
-        "160137",
-        "pwcrea",
-        "precipitable water content"
-    ],
-    [
-        "160140",
-        "swl1rea",
-        "soil wetness level 1"
-    ],
-    [
-        "160141",
-        "sdrea",
-        "snow depth"
-    ],
-    [
-        "160142",
-        "lsprea",
-        "large-scale precipitation"
-    ],
-    [
-        "160143",
-        "cprea",
-        "convective precipitation"
-    ],
-    [
-        "160144",
-        "sfrea",
-        "snowfall"
-    ],
-    [
-        "160156",
-        "ghrea",
-        "height"
-    ],
-    [
-        "160157",
-        "rrea",
-        "relative humidity"
-    ],
-    [
-        "160171",
-        "swl2rea",
-        "soil wetness level 2"
-    ],
-    [
-        "160180",
-        "ewssrea",
-        "east-west surface stress"
-    ],
-    [
-        "160181",
-        "nsssrea",
-        "north-south surface stress"
-    ],
-    [
-        "160182",
-        "erea",
-        "evaporation"
-    ],
-    [
-        "160184",
-        "swl3rea",
-        "soil wetness level 3"
-    ],
-    [
-        "160198",
-        "srcrea",
-        "skin reservoir content"
-    ],
-    [
-        "160199",
-        "vegrea",
-        "percentage of vegetation"
-    ],
-    [
-        "160201",
-        "mx2trea",
-        "maximum temperature at 2 metres during averaging time"
-    ],
-    [
-        "160202",
-        "mn2trea",
-        "minimum temperature at 2 metres during averaging time"
-    ],
-    [
-        "160205",
-        "rorea",
-        "runoff"
-    ],
-    [
-        "160206",
-        "zzrea",
-        "standard deviation of geopotential"
-    ],
-    [
-        "160207",
-        "tzrea",
-        "covariance of temperature and geopotential"
-    ],
-    [
-        "160208",
-        "ttrea",
-        "standard deviation of temperature"
-    ],
-    [
-        "160209",
-        "qzrea",
-        "covariance of specific humidity and geopotential"
-    ],
-    [
-        "160210",
-        "qtrea",
-        "covariance of specific humidity and temperature"
-    ],
-    [
-        "160211",
-        "qqrea",
-        "standard deviation of specific humidity"
-    ],
-    [
-        "160212",
-        "uzrea",
-        "covariance of u component and geopotential"
-    ],
-    [
-        "160213",
-        "utrea",
-        "covariance of u component and temperature"
-    ],
-    [
-        "160214",
-        "uqrea",
-        "covariance of u component and specific humidity"
-    ],
-    [
-        "160215",
-        "uurea",
-        "standard deviation of u velocity"
-    ],
-    [
-        "160216",
-        "vzrea",
-        "covariance of v component and geopotential"
-    ],
-    [
-        "160217",
-        "vtrea",
-        "covariance of v component and temperature"
-    ],
-    [
-        "160218",
-        "vqrea",
-        "covariance of v component and specific humidity"
-    ],
-    [
-        "160219",
-        "vurea",
-        "covariance of v component and u component"
-    ],
-    [
-        "160220",
-        "vvrea",
-        "standard deviation of v component"
-    ],
-    [
-        "160221",
-        "wzrea",
-        "covariance of w component and geopotential"
-    ],
-    [
-        "160222",
-        "wtrea",
-        "covariance of w component and temperature"
-    ],
-    [
-        "160223",
-        "wqrea",
-        "covariance of w component and specific humidity"
-    ],
-    [
-        "160224",
-        "wurea",
-        "covariance of w component and u component"
-    ],
-    [
-        "160225",
-        "wvrea",
-        "covariance of w component and v component"
-    ],
-    [
-        "160226",
-        "wwrea",
-        "standard deviation of vertical velocity"
-    ],
-    [
-        "160231",
-        "ishfrea",
-        "instantaneous surface heat flux"
-    ],
-    [
-        "160239",
-        "csfrea",
-        "convective snowfall"
-    ],
-    [
-        "160240",
-        "lsfrea",
-        "large scale snowfall"
-    ],
-    [
-        "160241",
-        "clwcerrea",
-        "cloud liquid water content"
-    ],
-    [
-        "160242",
-        "ccrea",
-        "cloud cover"
-    ],
-    [
-        "160243",
-        "falrea",
-        "forecast albedo"
-    ],
-    [
-        "160246",
-        "10wsrea",
-        "10 metre wind speed"
-    ],
-    [
-        "160247",
-        "moflrea",
-        "momentum flux"
-    ],
-    [
-        "160249",
-        "gravity wave dissipation flux"
-    ],
-    [
-        "160254",
-        "hsdrea",
-        "heaviside beta function"
-    ],
-    [
-        "162051",
-        "surface geopotential"
-    ],
-    [
-        "162053",
-        "vima",
-        "vertical integral of mass of atmosphere"
-    ],
-    [
-        "162054",
-        "vit",
-        "vertical integral of temperature"
-    ],
-    [
-        "162055",
-        "viwv",
-        "vertical integral of water vapour"
-    ],
-    [
-        "162056",
-        "vilw",
-        "vertical integral of cloud liquid water"
-    ],
-    [
-        "162057",
-        "viiw",
-        "vertical integral of cloud frozen water"
-    ],
-    [
-        "162058",
-        "vioz",
-        "vertical integral of ozone"
-    ],
-    [
-        "162059",
-        "vike",
-        "vertical integral of kinetic energy"
-    ],
-    [
-        "162060",
-        "vithe",
-        "vertical integral of thermal energy"
-    ],
-    [
-        "162061",
-        "vipie",
-        "vertical integral of potential+internal energy"
-    ],
-    [
-        "162062",
-        "vipile",
-        "vertical integral of potential+internal+latent energy"
-    ],
-    [
-        "162063",
-        "vitoe",
-        "vertical integral of total energy"
-    ],
-    [
-        "162064",
-        "viec",
-        "vertical integral of energy conversion"
-    ],
-    [
-        "162065",
-        "vimae",
-        "vertical integral of eastward mass flux"
-    ],
-    [
-        "162066",
-        "viman",
-        "vertical integral of northward mass flux"
-    ],
-    [
-        "162067",
-        "vikee",
-        "vertical integral of eastward kinetic energy flux"
-    ],
-    [
-        "162068",
-        "viken",
-        "vertical integral of northward kinetic energy flux"
-    ],
-    [
-        "162069",
-        "vithee",
-        "vertical integral of eastward heat flux"
-    ],
-    [
-        "162070",
-        "vithen",
-        "vertical integral of northward heat flux"
-    ],
-    [
-        "162071",
-        "viwve",
-        "vertical integral of eastward water vapour flux"
-    ],
-    [
-        "162072",
-        "viwvn",
-        "vertical integral of northward water vapour flux"
-    ],
-    [
-        "162073",
-        "vige",
-        "vertical integral of eastward geopotential flux"
-    ],
-    [
-        "162074",
-        "vign",
-        "vertical integral of northward geopotential flux"
-    ],
-    [
-        "162075",
-        "vitoee",
-        "vertical integral of eastward total energy flux"
-    ],
-    [
-        "162076",
-        "vitoen",
-        "vertical integral of northward total energy flux"
-    ],
-    [
-        "162077",
-        "vioze",
-        "vertical integral of eastward ozone flux"
-    ],
-    [
-        "162078",
-        "viozn",
-        "vertical integral of northward ozone flux"
-    ],
-    [
-        "162081",
-        "vimad",
-        "vertical integral of divergence of mass flux"
-    ],
-    [
-        "162082",
-        "viked",
-        "vertical integral of divergence of kinetic energy flux"
-    ],
-    [
-        "162083",
-        "vithed",
-        "vertical integral of divergence of thermal energy flux"
-    ],
-    [
-        "162084",
-        "viwvd",
-        "vertical integral of divergence of moisture flux"
-    ],
-    [
-        "162085",
-        "vigd",
-        "vertical integral of divergence of geopotential flux"
-    ],
-    [
-        "162086",
-        "vitoed",
-        "vertical integral of divergence of total energy flux"
-    ],
-    [
-        "162087",
-        "viozd",
-        "vertical integral of divergence of ozone flux"
-    ],
-    [
-        "162100",
-        "srta",
-        "tendency of short wave radiation"
-    ],
-    [
-        "162101",
-        "trta",
-        "tendency of long wave radiation"
-    ],
-    [
-        "162102",
-        "srtca",
-        "tendency of clear sky short wave radiation"
-    ],
-    [
-        "162103",
-        "trtca",
-        "tendency of clear sky long wave radiation"
-    ],
-    [
-        "162104",
-        "umfa",
-        "updraught mass flux"
-    ],
-    [
-        "162105",
-        "dmfa",
-        "downdraught mass flux"
-    ],
-    [
-        "162106",
-        "udra",
-        "updraught detrainment rate"
-    ],
-    [
-        "162107",
-        "ddra",
-        "downdraught detrainment rate"
-    ],
-    [
-        "162108",
-        "tpfa",
-        "total precipitation flux"
-    ],
-    [
-        "162109",
-        "tdcha",
-        "turbulent diffusion coefficient for heat"
-    ],
-    [
-        "162110",
-        "ttpha",
-        "tendency of temperature due to physics"
-    ],
-    [
-        "162111",
-        "qtpha",
-        "tendency of specific humidity due to physics"
-    ],
-    [
-        "162112",
-        "utpha",
-        "tendency of u component due to physics"
-    ],
-    [
-        "162113",
-        "vtpha",
-        "tendency of v component due to physics"
-    ],
-    [
-        "162206",
-        "variance of geopotential"
-    ],
-    [
-        "162207",
-        "covariance of geopotential/temperature"
-    ],
-    [
-        "162208",
-        "variance of temperature"
-    ],
-    [
-        "162209",
-        "covariance of geopotential/specific humidity"
-    ],
-    [
-        "162210",
-        "covariance of temperature/specific humidity"
-    ],
-    [
-        "162211",
-        "variance of specific humidity"
-    ],
-    [
-        "162212",
-        "covariance of u component/geopotential"
-    ],
-    [
-        "162213",
-        "covariance of u component/temperature"
-    ],
-    [
-        "162214",
-        "covariance of u component/specific humidity"
-    ],
-    [
-        "162215",
-        "variance of u component"
-    ],
-    [
-        "162216",
-        "covariance of v component/geopotential"
-    ],
-    [
-        "162217",
-        "covariance of v component/temperature"
-    ],
-    [
-        "162218",
-        "covariance of v component/specific humidity"
-    ],
-    [
-        "162219",
-        "covariance of v component/u component"
-    ],
-    [
-        "162220",
-        "variance of v component"
-    ],
-    [
-        "162221",
-        "covariance of omega/geopotential"
-    ],
-    [
-        "162222",
-        "covariance of omega/temperature"
-    ],
-    [
-        "162223",
-        "covariance of omega/specific humidity"
-    ],
-    [
-        "162224",
-        "covariance of omega/u component"
-    ],
-    [
-        "162225",
-        "covariance of omega/v component"
-    ],
-    [
-        "162226",
-        "variance of omega"
-    ],
-    [
-        "162227",
-        "variance of surface pressure"
-    ],
-    [
-        "162229",
-        "variance of relative humidity"
-    ],
-    [
-        "162230",
-        "covariance of u component/ozone"
-    ],
-    [
-        "162231",
-        "covariance of v component/ozone"
-    ],
-    [
-        "162232",
-        "covariance of omega/ozone"
-    ],
-    [
-        "162233",
-        "variance of ozone"
-    ],
-    [
-        "170149",
-        "tsw",
-        "total soil moisture"
-    ],
-    [
-        "170171",
-        "swl2",
-        "soil wetness level 2"
-    ],
-    [
-        "170179",
-        "ttr",
-        "top net thermal radiation"
-    ],
-    [
-        "171001",
-        "strfa",
-        "stream function anomaly"
-    ],
-    [
-        "171002",
-        "vpota",
-        "velocity potential anomaly"
-    ],
-    [
-        "171003",
-        "pta",
-        "potential temperature anomaly"
-    ],
-    [
-        "171004",
-        "epta",
-        "equivalent potential temperature anomaly"
-    ],
-    [
-        "171005",
-        "septa",
-        "saturated equivalent potential temperature anomaly"
-    ],
-    [
-        "171011",
-        "udwa",
-        "u component of divergent wind anomaly"
-    ],
-    [
-        "171012",
-        "vdwa",
-        "v component of divergent wind anomaly"
-    ],
-    [
-        "171013",
-        "urwa",
-        "u component of rotational wind anomaly"
-    ],
-    [
-        "171014",
-        "vrwa",
-        "v component of rotational wind anomaly"
-    ],
-    [
-        "171021",
-        "uctpa",
-        "unbalanced component of temperature anomaly"
-    ],
-    [
-        "171022",
-        "uclna",
-        "unbalanced component of logarithm of surface pressure anomaly"
-    ],
-    [
-        "171023",
-        "ucdva",
-        "unbalanced component of divergence anomaly"
-    ],
-    [
-        "171026",
-        "cla",
-        "lake cover anomaly"
-    ],
-    [
-        "171027",
-        "cvla",
-        "low vegetation cover anomaly"
-    ],
-    [
-        "171028",
-        "cvha",
-        "high vegetation cover anomaly"
-    ],
-    [
-        "171029",
-        "tvla",
-        "type of low vegetation anomaly"
-    ],
-    [
-        "171030",
-        "tvha",
-        "type of high vegetation anomaly"
-    ],
-    [
-        "171031",
-        "sica",
-        "sea-ice cover anomaly"
-    ],
-    [
-        "171032",
-        "asna",
-        "snow albedo anomaly"
-    ],
-    [
-        "171033",
-        "rsna",
-        "snow density anomaly"
-    ],
-    [
-        "171034",
-        "ssta",
-        "sea surface temperature anomaly",
-        "sstak"
-    ],
-    [
-        "171035",
-        "istal1",
-        "ice surface temperature anomaly layer 1"
-    ],
-    [
-        "171036",
-        "istal2",
-        "ice surface temperature anomaly layer 2"
-    ],
-    [
-        "171037",
-        "istal3",
-        "ice surface temperature anomaly layer 3"
-    ],
-    [
-        "171038",
-        "istal4",
-        "ice surface temperature anomaly layer 4"
-    ],
-    [
-        "171039",
-        "swval1",
-        "volumetric soil water anomaly layer 1"
-    ],
-    [
-        "171040",
-        "swval2",
-        "volumetric soil water anomaly layer 2"
-    ],
-    [
-        "171041",
-        "swval3",
-        "volumetric soil water anomaly layer 3"
-    ],
-    [
-        "171042",
-        "swval4",
-        "volumetric soil water anomaly layer 4"
-    ],
-    [
-        "171043",
-        "slta",
-        "soil type anomaly"
-    ],
-    [
-        "171044",
-        "esa",
-        "snow evaporation anomaly"
-    ],
-    [
-        "171045",
-        "smlta",
-        "snowmelt anomaly"
-    ],
-    [
-        "171046",
-        "sdura",
-        "solar duration anomaly"
-    ],
-    [
-        "171047",
-        "dsrpa",
-        "direct solar radiation anomaly"
-    ],
-    [
-        "171048",
-        "magssa",
-        "magnitude of turbulent surface stress anomaly"
-    ],
-    [
-        "171049",
-        "10fga",
-        "10 metre wind gust anomaly"
-    ],
-    [
-        "171050",
-        "lspfa",
-        "large-scale precipitation fraction anomaly"
-    ],
-    [
-        "171051",
-        "mx2t24a",
-        "maximum 2 metre temperature in the last 24 hours anomaly"
-    ],
-    [
-        "171052",
-        "mn2t24a",
-        "minimum 2 metre temperature in the last 24 hours anomaly"
-    ],
-    [
-        "171053",
-        "monta",
-        "montgomery potential anomaly"
-    ],
-    [
-        "171054",
-        "pa",
-        "pressure anomaly"
-    ],
-    [
-        "171055",
-        "mn2t24a",
-        "mean 2 metre temperature in the last 24 hours anomaly"
-    ],
-    [
-        "171056",
-        "mn2d24a",
-        "mean 2 metre dewpoint temperature in the last 24 hours anomaly"
-    ],
-    [
-        "171057",
-        "uvba",
-        "downward uv radiation at the surface anomaly"
-    ],
-    [
-        "171058",
-        "para",
-        "photosynthetically active radiation at the surface anomaly"
-    ],
-    [
-        "171059",
-        "capea",
-        "convective available potential energy anomaly"
-    ],
-    [
-        "171060",
-        "pva",
-        "potential vorticity anomaly"
-    ],
-    [
-        "171061",
-        "tpoa",
-        "total precipitation from observations anomaly"
-    ],
-    [
-        "171062",
-        "obcta",
-        "observation count anomaly"
-    ],
-    [
-        "171063",
-        "stsktda",
-        "start time for skin temperature difference anomaly"
-    ],
-    [
-        "171064",
-        "ftsktda",
-        "finish time for skin temperature difference anomaly"
-    ],
-    [
-        "171065",
-        "sktda",
-        "skin temperature difference anomaly"
-    ],
-    [
-        "171078",
-        "tclwa",
-        "total column liquid water anomaly"
-    ],
-    [
-        "171079",
-        "tciwa",
-        "total column ice water anomaly"
-    ],
-    [
-        "171125",
-        "vitea",
-        "vertically integrated total energy anomaly"
-    ],
-    [
-        "171126",
-        "generic parameter for sensitive area prediction"
-    ],
-    [
-        "171127",
-        "ata",
-        "atmospheric tide anomaly"
-    ],
-    [
-        "171128",
-        "bva",
-        "budget values anomaly"
-    ],
-    [
-        "171129",
-        "za",
-        "geopotential anomaly"
-    ],
-    [
-        "171130",
-        "ta",
-        "temperature anomaly"
-    ],
-    [
-        "171131",
-        "ua",
-        "u component of wind anomaly"
-    ],
-    [
-        "171132",
-        "va",
-        "v component of wind anomaly"
-    ],
-    [
-        "171133",
-        "qa",
-        "specific humidity anomaly"
-    ],
-    [
-        "171134",
-        "spa",
-        "surface pressure anomaly"
-    ],
-    [
-        "171135",
-        "wa",
-        "vertical velocity (pressure) anomaly"
-    ],
-    [
-        "171136",
-        "tcwa",
-        "total column water anomaly"
-    ],
-    [
-        "171137",
-        "tcwva",
-        "total column water vapour anomaly"
-    ],
-    [
-        "171138",
-        "voa",
-        "relative vorticity anomaly"
-    ],
-    [
-        "171139",
-        "stal1",
-        "soil temperature anomaly level 1"
-    ],
-    [
-        "171140",
-        "swal1",
-        "soil wetness anomaly level 1"
-    ],
-    [
-        "171141",
-        "sda",
-        "snow depth anomaly"
-    ],
-    [
-        "171142",
-        "lspa",
-        "stratiform precipitation (large-scale precipitation) anomaly"
-    ],
-    [
-        "171143",
-        "cpa",
-        "convective precipitation anomaly"
-    ],
-    [
-        "171144",
-        "sfa",
-        "snowfall (convective + stratiform) anomaly"
-    ],
-    [
-        "171145",
-        "blda",
-        "boundary layer dissipation anomaly"
-    ],
-    [
-        "171146",
-        "sshfa",
-        "surface sensible heat flux anomaly"
-    ],
-    [
-        "171147",
-        "slhfa",
-        "surface latent heat flux anomaly"
-    ],
-    [
-        "171148",
-        "chnka",
-        "charnock anomaly"
-    ],
-    [
-        "171149",
-        "snra",
-        "surface net radiation anomaly"
-    ],
-    [
-        "171150",
-        "tnra",
-        "top net radiation anomaly"
-    ],
-    [
-        "171151",
-        "msla",
-        "mean sea level pressure anomaly",
-        "151.171"
-    ],
-    [
-        "171152",
-        "lspa",
-        "logarithm of surface pressure anomaly"
-    ],
-    [
-        "171153",
-        "swhra",
-        "short-wave heating rate anomaly"
-    ],
-    [
-        "171154",
-        "lwhra",
-        "long-wave heating rate anomaly"
-    ],
-    [
-        "171155",
-        "da",
-        "relative divergence anomaly"
-    ],
-    [
-        "171156",
-        "gha",
-        "height anomaly"
-    ],
-    [
-        "171157",
-        "ra",
-        "relative humidity anomaly"
-    ],
-    [
-        "171158",
-        "tspa",
-        "tendency of surface pressure anomaly"
-    ],
-    [
-        "171159",
-        "blha",
-        "boundary layer height anomaly"
-    ],
-    [
-        "171160",
-        "sdora",
-        "standard deviation of orography anomaly"
-    ],
-    [
-        "171161",
-        "isora",
-        "anisotropy of sub-gridscale orography anomaly"
-    ],
-    [
-        "171162",
-        "anora",
-        "angle of sub-gridscale orography anomaly"
-    ],
-    [
-        "171163",
-        "slora",
-        "slope of sub-gridscale orography anomaly"
-    ],
-    [
-        "171164",
-        "tcca",
-        "total cloud cover anomaly"
-    ],
-    [
-        "171165",
-        "10ua",
-        "10 metre u wind component anomaly"
-    ],
-    [
-        "171166",
-        "10va",
-        "10 metre v wind component anomaly"
-    ],
-    [
-        "171167",
-        "2ta",
-        "2 metre temperature anomaly"
-    ],
-    [
-        "171168",
-        "2da",
-        "2 metre dewpoint temperature anomaly"
-    ],
-    [
-        "171169",
-        "ssrda",
-        "surface solar radiation downwards anomaly"
-    ],
-    [
-        "171170",
-        "slal2",
-        "soil temperature anomaly level 2"
-    ],
-    [
-        "171171",
-        "swal2",
-        "soil wetness anomaly level 2"
-    ],
-    [
-        "171173",
-        "sra",
-        "surface roughness anomaly"
-    ],
-    [
-        "171174",
-        "ala",
-        "albedo anomaly"
-    ],
-    [
-        "171175",
-        "strda",
-        "surface thermal radiation downwards anomaly"
-    ],
-    [
-        "171176",
-        "ssra",
-        "surface net solar radiation anomaly"
-    ],
-    [
-        "171177",
-        "stra",
-        "surface net thermal radiation anomaly"
-    ],
-    [
-        "171178",
-        "tsra",
-        "top net solar radiation anomaly"
-    ],
-    [
-        "171179",
-        "ttra",
-        "top net thermal radiation anomaly"
-    ],
-    [
-        "171180",
-        "eqssa",
-        "east-west surface stress anomaly"
-    ],
-    [
-        "171181",
-        "nsssa",
-        "north-south surface stress anomaly"
-    ],
-    [
-        "171182",
-        "ea",
-        "evaporation anomaly"
-    ],
-    [
-        "171183",
-        "stal3",
-        "soil temperature anomaly level 3"
-    ],
-    [
-        "171184",
-        "swal3",
-        "soil wetness anomaly level 3"
-    ],
-    [
-        "171185",
-        "ccca",
-        "convective cloud cover anomaly"
-    ],
-    [
-        "171186",
-        "lcca",
-        "low cloud cover anomaly"
-    ],
-    [
-        "171187",
-        "mcca",
-        "medium cloud cover anomaly"
-    ],
-    [
-        "171188",
-        "hcca",
-        "high cloud cover anomaly"
-    ],
-    [
-        "171189",
-        "sunda",
-        "sunshine duration anomaly"
-    ],
-    [
-        "171190",
-        "ewova",
-        "east-west component of sub-gridscale orographic variance anomaly"
-    ],
-    [
-        "171191",
-        "nsova",
-        "north-south component of sub-gridscale orographic variance anomaly"
-    ],
-    [
-        "171192",
-        "nwova",
-        "north-west/south-east component of sub-gridscale orographic variance anomaly"
-    ],
-    [
-        "171193",
-        "neova",
-        "north-east/south-west component of sub-gridscale orographic variance anomaly"
-    ],
-    [
-        "171194",
-        "btmpa",
-        "brightness temperature anomaly"
-    ],
-    [
-        "171195",
-        "lgwsa",
-        "longitudinal component of gravity wave stress anomaly"
-    ],
-    [
-        "171196",
-        "mgwsa",
-        "meridional component of gravity wave stress anomaly"
-    ],
-    [
-        "171197",
-        "gwda",
-        "gravity wave dissipation anomaly"
-    ],
-    [
-        "171198",
-        "srca",
-        "skin reservoir content anomaly"
-    ],
-    [
-        "171199",
-        "vfa",
-        "vegetation fraction anomaly"
-    ],
-    [
-        "171200",
-        "vsoa",
-        "variance of sub-gridscale orography anomaly"
-    ],
-    [
-        "171201",
-        "mx2ta",
-        "maximum temperature at 2 metres anomaly"
-    ],
-    [
-        "171202",
-        "mn2ta",
-        "minimum temperature at 2 metres anomaly"
-    ],
-    [
-        "171203",
-        "o3a",
-        "ozone mass mixing ratio anomaly"
-    ],
-    [
-        "171204",
-        "pawa",
-        "precipitation analysis weights anomaly"
-    ],
-    [
-        "171205",
-        "roa",
-        "runoff anomaly"
-    ],
-    [
-        "171206",
-        "tco3a",
-        "total column ozone anomaly"
-    ],
-    [
-        "171207",
-        "10ua",
-        "10 metre wind speed anomaly"
-    ],
-    [
-        "171208",
-        "tsrca",
-        "top net solar radiation clear sky anomaly"
-    ],
-    [
-        "171209",
-        "ttrca",
-        "top net thermal radiation clear sky anomaly"
-    ],
-    [
-        "171210",
-        "ssrca",
-        "surface net solar radiation clear sky anomaly"
-    ],
-    [
-        "171211",
-        "strca",
-        "surface net thermal radiation, clear sky anomaly"
-    ],
-    [
-        "171212",
-        "sia",
-        "solar insolation anomaly"
-    ],
-    [
-        "171214",
-        "dhra",
-        "diabatic heating by radiation anomaly"
-    ],
-    [
-        "171215",
-        "dhvda",
-        "diabatic heating by vertical diffusion anomaly"
-    ],
-    [
-        "171216",
-        "dhcca",
-        "diabatic heating by cumulus convection anomaly"
-    ],
-    [
-        "171217",
-        "dhlca",
-        "diabatic heating by large-scale condensation anomaly"
-    ],
-    [
-        "171218",
-        "vdzwa",
-        "vertical diffusion of zonal wind anomaly"
-    ],
-    [
-        "171219",
-        "vdmwa",
-        "vertical diffusion of meridional wind anomaly"
-    ],
-    [
-        "171220",
-        "ewgda",
-        "east-west gravity wave drag tendency anomaly"
-    ],
-    [
-        "171221",
-        "nsgda",
-        "north-south gravity wave drag tendency anomaly"
-    ],
-    [
-        "171222",
-        "ctzwa",
-        "convective tendency of zonal wind anomaly"
-    ],
-    [
-        "171223",
-        "ctmwa",
-        "convective tendency of meridional wind anomaly"
-    ],
-    [
-        "171224",
-        "vdha",
-        "vertical diffusion of humidity anomaly"
-    ],
-    [
-        "171225",
-        "htcca",
-        "humidity tendency by cumulus convection anomaly"
-    ],
-    [
-        "171226",
-        "htlca",
-        "humidity tendency by large-scale condensation anomaly"
-    ],
-    [
-        "171227",
-        "crnha",
-        "change from removal of negative humidity anomaly"
-    ],
-    [
-        "171228",
-        "tpa",
-        "total precipitation anomaly"
-    ],
-    [
-        "171229",
-        "iewsa",
-        "instantaneous x surface stress anomaly"
-    ],
-    [
-        "171230",
-        "inssa",
-        "instantaneous y surface stress anomaly"
-    ],
-    [
-        "171231",
-        "ishfa",
-        "instantaneous surface heat flux anomaly"
-    ],
-    [
-        "171232",
-        "iea",
-        "instantaneous moisture flux anomaly"
-    ],
-    [
-        "171233",
-        "asqa",
-        "apparent surface humidity anomaly"
-    ],
-    [
-        "171234",
-        "lsrha",
-        "logarithm of surface roughness length for heat anomaly"
-    ],
-    [
-        "171235",
-        "skta",
-        "skin temperature anomaly"
-    ],
-    [
-        "171236",
-        "stal4",
-        "soil temperature level 4 anomaly"
-    ],
-    [
-        "171237",
-        "swal4",
-        "soil wetness level 4 anomaly"
-    ],
-    [
-        "171238",
-        "tsna",
-        "temperature of snow layer anomaly"
-    ],
-    [
-        "171239",
-        "csfa",
-        "convective snowfall anomaly"
-    ],
-    [
-        "171240",
-        "lsfa",
-        "large scale snowfall anomaly"
-    ],
-    [
-        "171241",
-        "acfa",
-        "accumulated cloud fraction tendency anomaly"
-    ],
-    [
-        "171242",
-        "alwa",
-        "accumulated liquid water tendency anomaly"
-    ],
-    [
-        "171243",
-        "fala",
-        "forecast albedo anomaly"
-    ],
-    [
-        "171244",
-        "fsra",
-        "forecast surface roughness anomaly"
-    ],
-    [
-        "171245",
-        "flsra",
-        "forecast logarithm of surface roughness for heat anomaly"
-    ],
-    [
-        "171246",
-        "clwca",
-        "cloud liquid water content anomaly"
-    ],
-    [
-        "171247",
-        "ciwca",
-        "cloud ice water content anomaly"
-    ],
-    [
-        "171248",
-        "cca",
-        "cloud cover anomaly"
-    ],
-    [
-        "171249",
-        "aiwa",
-        "accumulated ice water tendency anomaly"
-    ],
-    [
-        "171250",
-        "iaa",
-        "ice age anomaly"
-    ],
-    [
-        "171251",
-        "attea",
-        "adiabatic tendency of temperature anomaly"
-    ],
-    [
-        "171252",
-        "athea",
-        "adiabatic tendency of humidity anomaly"
-    ],
-    [
-        "171253",
-        "atzea",
-        "adiabatic tendency of zonal wind anomaly"
-    ],
-    [
-        "171254",
-        "atmwa",
-        "adiabatic tendency of meridional wind anomaly"
-    ],
-    [
-        "172044",
-        "esrate",
-        "snow evaporation"
-    ],
-    [
-        "172045",
-        "snowmelt"
-    ],
-    [
-        "172048",
-        "magnitude of turbulent surface stress"
-    ],
-    [
-        "172050",
-        "large-scale precipitation fraction"
-    ],
-    [
-        "172142",
-        "stratiform precipitation (large-scale precipitation)"
-    ],
-    [
-        "172143",
-        "cprate",
-        "convective precipitation"
-    ],
-    [
-        "172144",
-        "snowfall (convective + stratiform)"
-    ],
-    [
-        "172145",
-        "bldrate",
-        "boundary layer dissipation"
-    ],
-    [
-        "172146",
-        "surface sensible heat flux"
-    ],
-    [
-        "172147",
-        "surface latent heat flux"
-    ],
-    [
-        "172149",
-        "surface net radiation"
-    ],
-    [
-        "172153",
-        "short-wave heating rate"
-    ],
-    [
-        "172154",
-        "long-wave heating rate"
-    ],
-    [
-        "172169",
-        "surface solar radiation downwards"
-    ],
-    [
-        "172175",
-        "surface thermal radiation downwards"
-    ],
-    [
-        "172176",
-        "surface solar radiation"
-    ],
-    [
-        "172177",
-        "surface thermal radiation"
-    ],
-    [
-        "172178",
-        "top solar radiation"
-    ],
-    [
-        "172179",
-        "top thermal radiation"
-    ],
-    [
-        "172180",
-        "east-west surface stress"
-    ],
-    [
-        "172181",
-        "north-south surface stress"
-    ],
-    [
-        "172182",
-        "erate",
-        "evaporation"
-    ],
-    [
-        "172189",
-        "sunshine duration"
-    ],
-    [
-        "172195",
-        "longitudinal component of gravity wave stress"
-    ],
-    [
-        "172196",
-        "meridional component of gravity wave stress"
-    ],
-    [
-        "172197",
-        "gwdrate",
-        "gravity wave dissipation"
-    ],
-    [
-        "172205",
-        "runoff"
-    ],
-    [
-        "172208",
-        "top net solar radiation, clear sky"
-    ],
-    [
-        "172209",
-        "top net thermal radiation, clear sky"
-    ],
-    [
-        "172210",
-        "surface net solar radiation, clear sky"
-    ],
-    [
-        "172211",
-        "surface net thermal radiation, clear sky"
-    ],
-    [
-        "172212",
-        "solar insolation"
-    ],
-    [
-        "172228",
-        "tprate",
-        "total precipitation"
-    ],
-    [
-        "172239",
-        "convective snowfall"
-    ],
-    [
-        "172240",
-        "large scale snowfall"
-    ],
-    [
-        "173044",
-        "snow evaporation anomaly"
-    ],
-    [
-        "173045",
-        "snowmelt anomaly"
-    ],
-    [
-        "173048",
-        "magnitude of turbulent surface stress anomaly"
-    ],
-    [
-        "173050",
-        "large-scale precipitation fraction anomaly"
-    ],
-    [
-        "173142",
-        "stratiform precipitation (large-scale precipitation) anomaly"
-    ],
-    [
-        "173143",
-        "convective precipitation anomaly"
-    ],
-    [
-        "173144",
-        "sfara",
-        "snowfall (convective + stratiform) anomalous rate of accumulation"
-    ],
-    [
-        "173145",
-        "boundary layer dissipation anomaly"
-    ],
-    [
-        "173146",
-        "surface sensible heat flux anomaly"
-    ],
-    [
-        "173147",
-        "surface latent heat flux anomaly"
-    ],
-    [
-        "173149",
-        "surface net radiation anomaly"
-    ],
-    [
-        "173153",
-        "short-wave heating rate anomaly"
-    ],
-    [
-        "173154",
-        "long-wave heating rate anomaly"
-    ],
-    [
-        "173169",
-        "surface solar radiation downwards anomaly"
-    ],
-    [
-        "173175",
-        "surface thermal radiation downwards anomaly"
-    ],
-    [
-        "173176",
-        "surface solar radiation anomaly"
-    ],
-    [
-        "173177",
-        "surface thermal radiation anomaly"
-    ],
-    [
-        "173178",
-        "top solar radiation anomaly"
-    ],
-    [
-        "173179",
-        "top thermal radiation anomaly"
-    ],
-    [
-        "173180",
-        "east-west surface stress anomaly"
-    ],
-    [
-        "173181",
-        "north-south surface stress anomaly"
-    ],
-    [
-        "173182",
-        "evaporation anomaly"
-    ],
-    [
-        "173189",
-        "sundara",
-        "sunshine duration anomalous rate of accumulation"
-    ],
-    [
-        "173195",
-        "longitudinal component of gravity wave stress anomaly"
-    ],
-    [
-        "173196",
-        "meridional component of gravity wave stress anomaly"
-    ],
-    [
-        "173197",
-        "gravity wave dissipation anomaly"
-    ],
-    [
-        "173205",
-        "runoff anomaly"
-    ],
-    [
-        "173208",
-        "top net solar radiation, clear sky anomaly"
-    ],
-    [
-        "173209",
-        "top net thermal radiation, clear sky anomaly"
-    ],
-    [
-        "173210",
-        "surface net solar radiation, clear sky anomaly"
-    ],
-    [
-        "173211",
-        "surface net thermal radiation, clear sky anomaly"
-    ],
-    [
-        "173212",
-        "solar insolation anomaly"
-    ],
-    [
-        "173228",
-        "tpara",
-        "total precipitation anomalous rate of accumulation",
-        "228.173"
-    ],
-    [
-        "173239",
-        "convective snowfall anomaly"
-    ],
-    [
-        "173240",
-        "large scale snowfall anomaly"
-    ],
-    [
-        "174006",
-        "total soil moisture"
-    ],
-    [
-        "174008",
-        "sro",
-        "surface runoff"
-    ],
-    [
-        "174009",
-        "ssro",
-        "sub-surface runoff"
-    ],
-    [
-        "174031",
-        "fraction of sea-ice in sea"
-    ],
-    [
-        "174034",
-        "open-sea surface temperature"
-    ],
-    [
-        "174039",
-        "volumetric soil water layer 1"
-    ],
-    [
-        "174040",
-        "volumetric soil water layer 2"
-    ],
-    [
-        "174041",
-        "volumetric soil water layer 3"
-    ],
-    [
-        "174042",
-        "volumetric soil water layer 4"
-    ],
-    [
-        "174049",
-        "10 metre wind gust in the last 24 hours"
-    ],
-    [
-        "174055",
-        "1.5m temperature - mean in the last 24 hours"
-    ],
-    [
-        "174083",
-        "net primary productivity"
-    ],
-    [
-        "174085",
-        "10m u wind over land"
-    ],
-    [
-        "174086",
-        "10m v wind over land"
-    ],
-    [
-        "174087",
-        "1.5m temperature over land"
-    ],
-    [
-        "174088",
-        "1.5m dewpoint temperature over land"
-    ],
-    [
-        "174089",
-        "top incoming solar radiation"
-    ],
-    [
-        "174090",
-        "top outgoing solar radiation"
-    ],
-    [
-        "174094",
-        "mean sea surface temperature"
-    ],
-    [
-        "174095",
-        "1.5m specific humidity"
-    ],
-    [
-        "174098",
-        "sit",
-        "sea-ice thickness"
-    ],
-    [
-        "174099",
-        "liquid water potential temperature"
-    ],
-    [
-        "174110",
-        "ocean ice concentration"
-    ],
-    [
-        "174111",
-        "ocean mean ice depth"
-    ],
-    [
-        "174139",
-        "soil temperature layer 1"
-    ],
-    [
-        "174164",
-        "average potential temperature in upper 293.4m"
-    ],
-    [
-        "174167",
-        "1.5m temperature"
-    ],
-    [
-        "174168",
-        "1.5m dewpoint temperature"
-    ],
-    [
-        "174170",
-        "soil temperature layer 2"
-    ],
-    [
-        "174175",
-        "average salinity in upper 293.4m"
-    ],
-    [
-        "174183",
-        "soil temperature layer 3"
-    ],
-    [
-        "174201",
-        "1.5m temperature - maximum in the last 24 hours"
-    ],
-    [
-        "174202",
-        "1.5m temperature - minimum in the last 24 hours"
-    ],
-    [
-        "174236",
-        "soil temperature layer 4"
-    ],
-    [
-        "175006",
-        "total soil moisture"
-    ],
-    [
-        "175031",
-        "fraction of sea-ice in sea"
-    ],
-    [
-        "175034",
-        "open-sea surface temperature"
-    ],
-    [
-        "175039",
-        "volumetric soil water layer 1"
-    ],
-    [
-        "175040",
-        "volumetric soil water layer 2"
-    ],
-    [
-        "175041",
-        "volumetric soil water layer 3"
-    ],
-    [
-        "175042",
-        "volumetric soil water layer 4"
-    ],
-    [
-        "175049",
-        "10m wind gust in the last 24 hours"
-    ],
-    [
-        "175055",
-        "1.5m temperature - mean in the last 24 hours"
-    ],
-    [
-        "175083",
-        "net primary productivity"
-    ],
-    [
-        "175085",
-        "10m u wind over land"
-    ],
-    [
-        "175086",
-        "10m v wind over land"
-    ],
-    [
-        "175087",
-        "1.5m temperature over land"
-    ],
-    [
-        "175088",
-        "1.5m dewpoint temperature over land"
-    ],
-    [
-        "175089",
-        "top incoming solar radiation"
-    ],
-    [
-        "175090",
-        "top outgoing solar radiation"
-    ],
-    [
-        "175110",
-        "ocean ice concentration"
-    ],
-    [
-        "175111",
-        "ocean mean ice depth"
-    ],
-    [
-        "175139",
-        "soil temperature layer 1"
-    ],
-    [
-        "175164",
-        "average potential temperature in upper 293.4m"
-    ],
-    [
-        "175167",
-        "1.5m temperature"
-    ],
-    [
-        "175168",
-        "1.5m dewpoint temperature"
-    ],
-    [
-        "175170",
-        "soil temperature layer 2"
-    ],
-    [
-        "175175",
-        "average salinity in upper 293.4m"
-    ],
-    [
-        "175183",
-        "soil temperature layer 3"
-    ],
-    [
-        "175201",
-        "1.5m temperature - maximum in the last 24 hours"
-    ],
-    [
-        "175202",
-        "1.5m temperature - minimum in the last 24 hours"
-    ],
-    [
-        "175236",
-        "soil temperature layer 4"
-    ],
-    [
-        "180149",
-        "tsw",
-        "total soil wetness"
-    ],
-    [
-        "180176",
-        "ssr",
-        "surface net solar radiation"
-    ],
-    [
-        "180177",
-        "str",
-        "surface net thermal radiation"
-    ],
-    [
-        "180178",
-        "tsr",
-        "top net solar radiation"
-    ],
-    [
-        "180179",
-        "ttr",
-        "top net thermal radiation"
-    ],
-    [
-        "190141",
-        "sdsien",
-        "snow depth"
-    ],
-    [
-        "190170",
-        "cap",
-        "field capacity"
-    ],
-    [
-        "190171",
-        "wiltsien",
-        "wilting point"
-    ],
-    [
-        "190173",
-        "sr",
-        "roughness length"
-    ],
-    [
-        "190229",
-        "tsm",
-        "total soil moisture"
-    ],
-    [
-        "200001",
-        "strfdiff",
-        "stream function difference"
-    ],
-    [
-        "200002",
-        "vpotdiff",
-        "velocity potential difference"
-    ],
-    [
-        "200003",
-        "ptdiff",
-        "potential temperature difference"
-    ],
-    [
-        "200004",
-        "eqptdiff",
-        "equivalent potential temperature difference"
-    ],
-    [
-        "200005",
-        "septdiff",
-        "saturated equivalent potential temperature difference"
-    ],
-    [
-        "200011",
-        "udvwdiff",
-        "u component of divergent wind difference"
-    ],
-    [
-        "200012",
-        "vdvwdiff",
-        "v component of divergent wind difference"
-    ],
-    [
-        "200013",
-        "urtwdiff",
-        "u component of rotational wind difference"
-    ],
-    [
-        "200014",
-        "vrtwdiff",
-        "v component of rotational wind difference"
-    ],
-    [
-        "200021",
-        "uctpdiff",
-        "unbalanced component of temperature difference"
-    ],
-    [
-        "200022",
-        "uclndiff",
-        "unbalanced component of logarithm of surface pressure difference"
-    ],
-    [
-        "200023",
-        "ucdvdiff",
-        "unbalanced component of divergence difference"
-    ],
-    [
-        "200026",
-        "cldiff",
-        "lake cover difference"
-    ],
-    [
-        "200027",
-        "cvldiff",
-        "low vegetation cover difference"
-    ],
-    [
-        "200028",
-        "cvhdiff",
-        "high vegetation cover difference"
-    ],
-    [
-        "200029",
-        "tvldiff",
-        "type of low vegetation difference"
-    ],
-    [
-        "200030",
-        "tvhdiff",
-        "type of high vegetation difference"
-    ],
-    [
-        "200031",
-        "sicdiff",
-        "sea-ice cover difference"
-    ],
-    [
-        "200032",
-        "asndiff",
-        "snow albedo difference"
-    ],
-    [
-        "200033",
-        "rsndiff",
-        "snow density difference"
-    ],
-    [
-        "200034",
-        "sstdiff",
-        "sea surface temperature difference"
-    ],
-    [
-        "200035",
-        "istl1diff",
-        "ice surface temperature layer 1 difference"
-    ],
-    [
-        "200036",
-        "istl2diff",
-        "ice surface temperature layer 2 difference"
-    ],
-    [
-        "200037",
-        "istl3diff",
-        "ice surface temperature layer 3 difference"
-    ],
-    [
-        "200038",
-        "istl4diff",
-        "ice surface temperature layer 4 difference"
-    ],
-    [
-        "200039",
-        "swvl1diff",
-        "volumetric soil water layer 1 difference"
-    ],
-    [
-        "200040",
-        "swvl2diff",
-        "volumetric soil water layer 2 difference"
-    ],
-    [
-        "200041",
-        "swvl3diff",
-        "volumetric soil water layer 3 difference"
-    ],
-    [
-        "200042",
-        "swvl4diff",
-        "volumetric soil water layer 4 difference"
-    ],
-    [
-        "200043",
-        "sltdiff",
-        "soil type difference"
-    ],
-    [
-        "200044",
-        "esdiff",
-        "snow evaporation difference"
-    ],
-    [
-        "200045",
-        "smltdiff",
-        "snowmelt difference"
-    ],
-    [
-        "200046",
-        "sdurdiff",
-        "solar duration difference"
-    ],
-    [
-        "200047",
-        "dsrpdiff",
-        "direct solar radiation difference"
-    ],
-    [
-        "200048",
-        "magssdiff",
-        "magnitude of turbulent surface stress difference"
-    ],
-    [
-        "200049",
-        "10fgdiff",
-        "10 metre wind gust difference"
-    ],
-    [
-        "200050",
-        "lspfdiff",
-        "large-scale precipitation fraction difference"
-    ],
-    [
-        "200051",
-        "mx2t24diff",
-        "maximum 2 metre temperature difference"
-    ],
-    [
-        "200052",
-        "mn2t24diff",
-        "minimum 2 metre temperature difference"
-    ],
-    [
-        "200053",
-        "montdiff",
-        "montgomery potential difference"
-    ],
-    [
-        "200054",
-        "presdiff",
-        "pressure difference"
-    ],
-    [
-        "200055",
-        "mean2t24diff",
-        "mean 2 metre temperature in the last 24 hours difference"
-    ],
-    [
-        "200056",
-        "mn2d24diff",
-        "mean 2 metre dewpoint temperature in the last 24 hours difference"
-    ],
-    [
-        "200057",
-        "uvbdiff",
-        "downward uv radiation at the surface difference"
-    ],
-    [
-        "200058",
-        "pardiff",
-        "photosynthetically active radiation at the surface difference"
-    ],
-    [
-        "200059",
-        "capediff",
-        "convective available potential energy difference"
-    ],
-    [
-        "200060",
-        "pvdiff",
-        "potential vorticity difference"
-    ],
-    [
-        "200061",
-        "tpodiff",
-        "total precipitation from observations difference"
-    ],
-    [
-        "200062",
-        "obctdiff",
-        "observation count difference"
-    ],
-    [
-        "200063",
-        "start time for skin temperature difference"
-    ],
-    [
-        "200064",
-        "finish time for skin temperature difference"
-    ],
-    [
-        "200065",
-        "skin temperature difference"
-    ],
-    [
-        "200066",
-        "leaf area index, low vegetation"
-    ],
-    [
-        "200067",
-        "leaf area index, high vegetation"
-    ],
-    [
-        "200068",
-        "minimum stomatal resistance, low vegetation"
-    ],
-    [
-        "200069",
-        "minimum stomatal resistance, high vegetation"
-    ],
-    [
-        "200070",
-        "biome cover, low vegetation"
-    ],
-    [
-        "200071",
-        "biome cover, high vegetation"
-    ],
-    [
-        "200078",
-        "total column liquid water"
-    ],
-    [
-        "200079",
-        "total column ice water"
-    ],
-    [
-        "200121",
-        "mx2t6diff",
-        "maximum temperature at 2 metres difference"
-    ],
-    [
-        "200122",
-        "mn2t6diff",
-        "minimum temperature at 2 metres difference"
-    ],
-    [
-        "200123",
-        "10fg6diff",
-        "10 metre wind gust in the last 6 hours difference"
-    ],
-    [
-        "200125",
-        "vertically integrated total energy"
-    ],
-    [
-        "200126",
-        "generic parameter for sensitive area prediction"
-    ],
-    [
-        "200127",
-        "atdiff",
-        "atmospheric tide difference"
-    ],
-    [
-        "200128",
-        "bvdiff",
-        "budget values difference"
-    ],
-    [
-        "200129",
-        "zdiff",
-        "geopotential difference"
-    ],
-    [
-        "200130",
-        "tdiff",
-        "temperature difference"
-    ],
-    [
-        "200131",
-        "udiff",
-        "u component of wind difference"
-    ],
-    [
-        "200132",
-        "vdiff",
-        "v component of wind difference"
-    ],
-    [
-        "200133",
-        "qdiff",
-        "specific humidity difference"
-    ],
-    [
-        "200134",
-        "spdiff",
-        "surface pressure difference"
-    ],
-    [
-        "200135",
-        "wdiff",
-        "vertical velocity (pressure) difference"
-    ],
-    [
-        "200136",
-        "tcwdiff",
-        "total column water difference"
-    ],
-    [
-        "200137",
-        "tcwvdiff",
-        "total column water vapour difference"
-    ],
-    [
-        "200138",
-        "vodiff",
-        "vorticity (relative) difference"
-    ],
-    [
-        "200139",
-        "stl1diff",
-        "soil temperature level 1 difference"
-    ],
-    [
-        "200140",
-        "swl1diff",
-        "soil wetness level 1 difference"
-    ],
-    [
-        "200141",
-        "sddiff",
-        "snow depth difference"
-    ],
-    [
-        "200142",
-        "lspdiff",
-        "stratiform precipitation (large-scale precipitation) difference"
-    ],
-    [
-        "200143",
-        "cpdiff",
-        "convective precipitation difference"
-    ],
-    [
-        "200144",
-        "sfdiff",
-        "snowfall (convective + stratiform) difference"
-    ],
-    [
-        "200145",
-        "blddiff",
-        "boundary layer dissipation difference"
-    ],
-    [
-        "200146",
-        "sshfdiff",
-        "surface sensible heat flux difference"
-    ],
-    [
-        "200147",
-        "slhfdiff",
-        "surface latent heat flux difference"
-    ],
-    [
-        "200148",
-        "chnkdiff",
-        "charnock difference"
-    ],
-    [
-        "200149",
-        "snrdiff",
-        "surface net radiation difference"
-    ],
-    [
-        "200150",
-        "tnrdiff",
-        "top net radiation difference"
-    ],
-    [
-        "200151",
-        "msldiff",
-        "mean sea level pressure difference"
-    ],
-    [
-        "200152",
-        "lnspdiff",
-        "logarithm of surface pressure difference"
-    ],
-    [
-        "200153",
-        "swhrdiff",
-        "short-wave heating rate difference"
-    ],
-    [
-        "200154",
-        "lwhrdiff",
-        "long-wave heating rate difference"
-    ],
-    [
-        "200155",
-        "ddiff",
-        "divergence difference"
-    ],
-    [
-        "200156",
-        "ghdiff",
-        "height difference"
-    ],
-    [
-        "200157",
-        "rdiff",
-        "relative humidity difference"
-    ],
-    [
-        "200158",
-        "tspdiff",
-        "tendency of surface pressure difference"
-    ],
-    [
-        "200159",
-        "blhdiff",
-        "boundary layer height difference"
-    ],
-    [
-        "200160",
-        "sdordiff",
-        "standard deviation of orography difference"
-    ],
-    [
-        "200161",
-        "isordiff",
-        "anisotropy of sub-gridscale orography difference"
-    ],
-    [
-        "200162",
-        "anordiff",
-        "angle of sub-gridscale orography difference"
-    ],
-    [
-        "200163",
-        "slordiff",
-        "slope of sub-gridscale orography difference"
-    ],
-    [
-        "200164",
-        "tccdiff",
-        "total cloud cover difference"
-    ],
-    [
-        "200165",
-        "10udiff",
-        "10 metre u wind component difference"
-    ],
-    [
-        "200166",
-        "10vdiff",
-        "10 metre v wind component difference"
-    ],
-    [
-        "200167",
-        "2tdiff",
-        "2 metre temperature difference"
-    ],
-    [
-        "200168",
-        "2ddiff",
-        "2 metre dewpoint temperature difference"
-    ],
-    [
-        "200169",
-        "ssrddiff",
-        "surface solar radiation downwards difference"
-    ],
-    [
-        "200170",
-        "stl2diff",
-        "soil temperature level 2 difference"
-    ],
-    [
-        "200171",
-        "swl2diff",
-        "soil wetness level 2 difference"
-    ],
-    [
-        "200172",
-        "lsmdiff",
-        "land-sea mask difference"
-    ],
-    [
-        "200173",
-        "srdiff",
-        "surface roughness difference"
-    ],
-    [
-        "200174",
-        "aldiff",
-        "albedo difference"
-    ],
-    [
-        "200175",
-        "strddiff",
-        "surface thermal radiation downwards difference"
-    ],
-    [
-        "200176",
-        "ssrdiff",
-        "surface net solar radiation difference"
-    ],
-    [
-        "200177",
-        "strdiff",
-        "surface net thermal radiation difference"
-    ],
-    [
-        "200178",
-        "tsrdiff",
-        "top net solar radiation difference"
-    ],
-    [
-        "200179",
-        "ttrdiff",
-        "top net thermal radiation difference"
-    ],
-    [
-        "200180",
-        "ewssdiff",
-        "east-west surface stress difference"
-    ],
-    [
-        "200181",
-        "nsssdiff",
-        "north-south surface stress difference"
-    ],
-    [
-        "200182",
-        "ediff",
-        "evaporation difference"
-    ],
-    [
-        "200183",
-        "stl3diff",
-        "soil temperature level 3 difference"
-    ],
-    [
-        "200184",
-        "swl3diff",
-        "soil wetness level 3 difference"
-    ],
-    [
-        "200185",
-        "cccdiff",
-        "convective cloud cover difference"
-    ],
-    [
-        "200186",
-        "lccdiff",
-        "low cloud cover difference"
-    ],
-    [
-        "200187",
-        "mccdiff",
-        "medium cloud cover difference"
-    ],
-    [
-        "200188",
-        "hccdiff",
-        "high cloud cover difference"
-    ],
-    [
-        "200189",
-        "sunddiff",
-        "sunshine duration difference"
-    ],
-    [
-        "200190",
-        "ewovdiff",
-        "east-west component of sub-gridscale orographic variance difference"
-    ],
-    [
-        "200191",
-        "nsovdiff",
-        "north-south component of sub-gridscale orographic variance difference"
-    ],
-    [
-        "200192",
-        "nwovdiff",
-        "north-west/south-east component of sub-gridscale orographic variance difference"
-    ],
-    [
-        "200193",
-        "neovdiff",
-        "north-east/south-west component of sub-gridscale orographic variance difference"
-    ],
-    [
-        "200194",
-        "btmpdiff",
-        "brightness temperature difference"
-    ],
-    [
-        "200195",
-        "lgwsdiff",
-        "longitudinal component of gravity wave stress difference"
-    ],
-    [
-        "200196",
-        "mgwsdiff",
-        "meridional component of gravity wave stress difference"
-    ],
-    [
-        "200197",
-        "gwddiff",
-        "gravity wave dissipation difference"
-    ],
-    [
-        "200198",
-        "srcdiff",
-        "skin reservoir content difference"
-    ],
-    [
-        "200199",
-        "vegdiff",
-        "vegetation fraction difference"
-    ],
-    [
-        "200200",
-        "vsodiff",
-        "variance of sub-gridscale orography difference"
-    ],
-    [
-        "200201",
-        "mx2tdiff",
-        "maximum temperature at 2 metres since previous post-processing difference"
-    ],
-    [
-        "200202",
-        "mn2tdiff",
-        "minimum temperature at 2 metres since previous post-processing difference"
-    ],
-    [
-        "200203",
-        "o3diff",
-        "ozone mass mixing ratio difference"
-    ],
-    [
-        "200204",
-        "pawdiff",
-        "precipitation analysis weights difference"
-    ],
-    [
-        "200205",
-        "rodiff",
-        "runoff difference"
-    ],
-    [
-        "200206",
-        "tco3diff",
-        "total column ozone difference"
-    ],
-    [
-        "200207",
-        "10sidiff",
-        "10 metre wind speed difference"
-    ],
-    [
-        "200208",
-        "tsrcdiff",
-        "top net solar radiation, clear sky difference"
-    ],
-    [
-        "200209",
-        "ttrcdiff",
-        "top net thermal radiation, clear sky difference"
-    ],
-    [
-        "200210",
-        "ssrcdiff",
-        "surface net solar radiation, clear sky difference"
-    ],
-    [
-        "200211",
-        "strcdiff",
-        "surface net thermal radiation, clear sky difference"
-    ],
-    [
-        "200212",
-        "tisrdiff",
-        "toa incident solar radiation difference"
-    ],
-    [
-        "200214",
-        "dhrdiff",
-        "diabatic heating by radiation difference"
-    ],
-    [
-        "200215",
-        "dhvddiff",
-        "diabatic heating by vertical diffusion difference"
-    ],
-    [
-        "200216",
-        "dhccdiff",
-        "diabatic heating by cumulus convection difference"
-    ],
-    [
-        "200217",
-        "dhlcdiff",
-        "diabatic heating large-scale condensation difference"
-    ],
-    [
-        "200218",
-        "vdzwdiff",
-        "vertical diffusion of zonal wind difference"
-    ],
-    [
-        "200219",
-        "vdmwdiff",
-        "vertical diffusion of meridional wind difference"
-    ],
-    [
-        "200220",
-        "ewgddiff",
-        "east-west gravity wave drag tendency difference"
-    ],
-    [
-        "200221",
-        "nsgddiff",
-        "north-south gravity wave drag tendency difference"
-    ],
-    [
-        "200222",
-        "ctzwdiff",
-        "convective tendency of zonal wind difference"
-    ],
-    [
-        "200223",
-        "ctmwdiff",
-        "convective tendency of meridional wind difference"
-    ],
-    [
-        "200224",
-        "vdhdiff",
-        "vertical diffusion of humidity difference"
-    ],
-    [
-        "200225",
-        "htccdiff",
-        "humidity tendency by cumulus convection difference"
-    ],
-    [
-        "200226",
-        "htlcdiff",
-        "humidity tendency by large-scale condensation difference"
-    ],
-    [
-        "200227",
-        "crnhdiff",
-        "change from removal of negative humidity difference"
-    ],
-    [
-        "200228",
-        "tpdiff",
-        "total precipitation difference"
-    ],
-    [
-        "200229",
-        "iewsdiff",
-        "instantaneous x surface stress difference"
-    ],
-    [
-        "200230",
-        "inssdiff",
-        "instantaneous y surface stress difference"
-    ],
-    [
-        "200231",
-        "ishfdiff",
-        "instantaneous surface heat flux difference"
-    ],
-    [
-        "200232",
-        "iediff",
-        "instantaneous moisture flux difference"
-    ],
-    [
-        "200233",
-        "asqdiff",
-        "apparent surface humidity difference"
-    ],
-    [
-        "200234",
-        "lsrhdiff",
-        "logarithm of surface roughness length for heat difference"
-    ],
-    [
-        "200235",
-        "sktdiff",
-        "skin temperature difference"
-    ],
-    [
-        "200236",
-        "stl4diff",
-        "soil temperature level 4 difference"
-    ],
-    [
-        "200237",
-        "swl4diff",
-        "soil wetness level 4 difference"
-    ],
-    [
-        "200238",
-        "tsndiff",
-        "temperature of snow layer difference"
-    ],
-    [
-        "200239",
-        "csfdiff",
-        "convective snowfall difference"
-    ],
-    [
-        "200240",
-        "lsfdiff",
-        "large scale snowfall difference"
-    ],
-    [
-        "200241",
-        "acfdiff",
-        "accumulated cloud fraction tendency difference"
-    ],
-    [
-        "200242",
-        "alwdiff",
-        "accumulated liquid water tendency difference"
-    ],
-    [
-        "200243",
-        "faldiff",
-        "forecast albedo difference"
-    ],
-    [
-        "200244",
-        "fsrdiff",
-        "forecast surface roughness difference"
-    ],
-    [
-        "200245",
-        "flsrdiff",
-        "forecast logarithm of surface roughness for heat difference"
-    ],
-    [
-        "200246",
-        "clwcdiff",
-        "specific cloud liquid water content difference"
-    ],
-    [
-        "200247",
-        "ciwcdiff",
-        "specific cloud ice water content difference"
-    ],
-    [
-        "200248",
-        "ccdiff",
-        "cloud cover difference"
-    ],
-    [
-        "200249",
-        "aiwdiff",
-        "accumulated ice water tendency difference"
-    ],
-    [
-        "200250",
-        "icediff",
-        "ice age difference"
-    ],
-    [
-        "200251",
-        "attediff",
-        "adiabatic tendency of temperature difference"
-    ],
-    [
-        "200252",
-        "athediff",
-        "adiabatic tendency of humidity difference"
-    ],
-    [
-        "200253",
-        "atzediff",
-        "adiabatic tendency of zonal wind difference"
-    ],
-    [
-        "200254",
-        "atmwdiff",
-        "adiabatic tendency of meridional wind difference"
-    ],
-    [
-        "201001",
-        "downward shortwave radiant flux density"
-    ],
-    [
-        "201002",
-        "upward shortwave radiant flux density"
-    ],
-    [
-        "201003",
-        "downward longwave radiant flux density"
-    ],
-    [
-        "201004",
-        "upward longwave radiant flux density"
-    ],
-    [
-        "201005",
-        "apab_s",
-        "downwd photosynthetic active radiant flux density"
-    ],
-    [
-        "201006",
-        "net shortwave flux"
-    ],
-    [
-        "201007",
-        "net longwave flux"
-    ],
-    [
-        "201008",
-        "total net radiative flux density"
-    ],
-    [
-        "201009",
-        "downw shortw radiant flux density, cloudfree part"
-    ],
-    [
-        "201010",
-        "upw shortw radiant flux density, cloudy part"
-    ],
-    [
-        "201011",
-        "downw longw radiant flux density, cloudfree part"
-    ],
-    [
-        "201012",
-        "upw longw radiant flux density, cloudy part"
-    ],
-    [
-        "201013",
-        "sohr_rad",
-        "shortwave radiative heating rate"
-    ],
-    [
-        "201014",
-        "thhr_rad",
-        "longwave radiative heating rate"
-    ],
-    [
-        "201015",
-        "total radiative heating rate"
-    ],
-    [
-        "201016",
-        "soil heat flux, surface"
-    ],
-    [
-        "201017",
-        "soil heat flux, bottom of layer"
-    ],
-    [
-        "201029",
-        "clc",
-        "fractional cloud cover"
-    ],
-    [
-        "201030",
-        "cloud cover, grid scale"
-    ],
-    [
-        "201031",
-        "qc",
-        "specific cloud water content"
-    ],
-    [
-        "201032",
-        "cloud water content, grid scale, vert integrated"
-    ],
-    [
-        "201033",
-        "qi",
-        "specific cloud ice content, grid scale"
-    ],
-    [
-        "201034",
-        "cloud ice content, grid scale, vert integrated"
-    ],
-    [
-        "201035",
-        "specific rainwater content, grid scale"
-    ],
-    [
-        "201036",
-        "specific snow content, grid scale"
-    ],
-    [
-        "201037",
-        "specific rainwater content, gs, vert. integrated"
-    ],
-    [
-        "201038",
-        "specific snow content, gs, vert. integrated"
-    ],
-    [
-        "201041",
-        "twater",
-        "total column water"
-    ],
-    [
-        "201042",
-        "vert. integral of divergence of tot. water content"
-    ],
-    [
-        "201050",
-        "ch_cm_cl",
-        "cloud covers ch_cm_cl (000...888)"
-    ],
-    [
-        "201051",
-        "cloud cover ch (0..8)"
-    ],
-    [
-        "201052",
-        "cloud cover cm (0..8)"
-    ],
-    [
-        "201053",
-        "cloud cover cl (0..8)"
-    ],
-    [
-        "201054",
-        "total cloud cover (0..8)"
-    ],
-    [
-        "201055",
-        "fog (0..8)"
-    ],
-    [
-        "201056",
-        "fog"
-    ],
-    [
-        "201060",
-        "cloud cover, convective cirrus"
-    ],
-    [
-        "201061",
-        "specific cloud water content, convective clouds"
-    ],
-    [
-        "201062",
-        "cloud water content, conv clouds, vert integrated"
-    ],
-    [
-        "201063",
-        "specific cloud ice content, convective clouds"
-    ],
-    [
-        "201064",
-        "cloud ice content, conv clouds, vert integrated"
-    ],
-    [
-        "201065",
-        "convective mass flux"
-    ],
-    [
-        "201066",
-        "updraft velocity, convection"
-    ],
-    [
-        "201067",
-        "entrainment parameter, convection"
-    ],
-    [
-        "201068",
-        "hbas_con",
-        "cloud base, convective clouds (above msl)"
-    ],
-    [
-        "201069",
-        "htop_con",
-        "cloud top, convective clouds (above msl)"
-    ],
-    [
-        "201070",
-        "convective layers (00...77)  (bke)"
-    ],
-    [
-        "201071",
-        "ko-index"
-    ],
-    [
-        "201072",
-        "bas_con",
-        "convection base index"
-    ],
-    [
-        "201073",
-        "top_con",
-        "convection top index"
-    ],
-    [
-        "201074",
-        "dt_con",
-        "convective temperature tendency"
-    ],
-    [
-        "201075",
-        "dqv_con",
-        "convective tendency of specific humidity"
-    ],
-    [
-        "201076",
-        "convective tendency of total heat"
-    ],
-    [
-        "201077",
-        "convective tendency of total water"
-    ],
-    [
-        "201078",
-        "du_con",
-        "convective momentum tendency (x-component)"
-    ],
-    [
-        "201079",
-        "dv_con",
-        "convective momentum tendency (y-component)"
-    ],
-    [
-        "201080",
-        "convective vorticity tendency"
-    ],
-    [
-        "201081",
-        "convective divergence tendency"
-    ],
-    [
-        "201082",
-        "htop_dc",
-        "top of dry convection (above msl)"
-    ],
-    [
-        "201083",
-        "dry convection top index"
-    ],
-    [
-        "201084",
-        "hzerocl",
-        "height of 0 degree celsius isotherm above msl"
-    ],
-    [
-        "201085",
-        "snowlmt",
-        "height of snow-fall limit"
-    ],
-    [
-        "201099",
-        "qrs_gsp",
-        "spec. content of precip. particles"
-    ],
-    [
-        "201100",
-        "prr_gsp",
-        "surface precipitation rate, rain, grid scale"
-    ],
-    [
-        "201101",
-        "prs_gsp",
-        "surface precipitation rate, snow, grid scale"
-    ],
-    [
-        "201102",
-        "rain_gsp",
-        "surface precipitation amount, rain, grid scale"
-    ],
-    [
-        "201111",
-        "prr_con",
-        "surface precipitation rate, rain, convective"
-    ],
-    [
-        "201112",
-        "prs_con",
-        "surface precipitation rate, snow, convective"
-    ],
-    [
-        "201113",
-        "rain_con",
-        "surface precipitation amount, rain, convective"
-    ],
-    [
-        "201139",
-        "pp",
-        "deviation of pressure from reference value"
-    ],
-    [
-        "201150",
-        "coefficient of horizontal diffusion"
-    ],
-    [
-        "201187",
-        "vmax_10m",
-        "maximum wind velocity"
-    ],
-    [
-        "201200",
-        "w_i",
-        "water content of interception store"
-    ],
-    [
-        "201203",
-        "t_snow",
-        "snow temperature"
-    ],
-    [
-        "201215",
-        "t_ice",
-        "ice surface temperature"
-    ],
-    [
-        "201241",
-        "cape_con",
-        "convective available potential energy"
-    ],
-    [
-        "210001",
-        "aermr01",
-        "sea salt aerosol (0.03 - 0.5 um) mixing ratio"
-    ],
-    [
-        "210002",
-        "aermr02",
-        "sea salt aerosol (0.5 - 5 um) mixing ratio"
-    ],
-    [
-        "210003",
-        "aermr03",
-        "sea salt aerosol (5 - 20 um) mixing ratio"
-    ],
-    [
-        "210004",
-        "aermr04",
-        "dust aerosol (0.03 - 0.55 um) mixing ratio"
-    ],
-    [
-        "210005",
-        "aermr05",
-        "dust aerosol (0.55 - 0.9 um) mixing ratio"
-    ],
-    [
-        "210006",
-        "aermr06",
-        "dust aerosol (0.9 - 20 um) mixing ratio"
-    ],
-    [
-        "210007",
-        "aermr07",
-        "hydrophobic organic matter aerosol mixing ratio"
-    ],
-    [
-        "210008",
-        "aermr08",
-        "hydrophilic organic matter aerosol mixing ratio"
-    ],
-    [
-        "210009",
-        "aermr09",
-        "hydrophobic black carbon aerosol mixing ratio"
-    ],
-    [
-        "210010",
-        "aermr10",
-        "hydrophilic black carbon aerosol mixing ratio"
-    ],
-    [
-        "210011",
-        "aermr11",
-        "sulphate aerosol mixing ratio"
-    ],
-    [
-        "210012",
-        "aermr12",
-        "so2 precursor mixing ratio"
-    ],
-    [
-        "210016",
-        "aergn01",
-        "aerosol type 1 source/gain accumulated"
-    ],
-    [
-        "210017",
-        "aergn02",
-        "aerosol type 2 source/gain accumulated"
-    ],
-    [
-        "210018",
-        "aergn03",
-        "aerosol type 3 source/gain accumulated"
-    ],
-    [
-        "210019",
-        "aergn04",
-        "aerosol type 4 source/gain accumulated"
-    ],
-    [
-        "210020",
-        "aergn05",
-        "aerosol type 5 source/gain accumulated"
-    ],
-    [
-        "210021",
-        "aergn06",
-        "aerosol type 6 source/gain accumulated"
-    ],
-    [
-        "210022",
-        "aergn07",
-        "aerosol type 7 source/gain accumulated"
-    ],
-    [
-        "210023",
-        "aergn08",
-        "aerosol type 8 source/gain accumulated"
-    ],
-    [
-        "210024",
-        "aergn09",
-        "aerosol type 9 source/gain accumulated"
-    ],
-    [
-        "210025",
-        "aergn10",
-        "aerosol type 10 source/gain accumulated"
-    ],
-    [
-        "210026",
-        "aergn11",
-        "aerosol type 11 source/gain accumulated"
-    ],
-    [
-        "210027",
-        "aergn12",
-        "aerosol type 12 source/gain accumulated"
-    ],
-    [
-        "210031",
-        "aerls01",
-        "aerosol type 1 sink/loss accumulated"
-    ],
-    [
-        "210032",
-        "aerls02",
-        "aerosol type 2 sink/loss accumulated"
-    ],
-    [
-        "210033",
-        "aerls03",
-        "aerosol type 3 sink/loss accumulated"
-    ],
-    [
-        "210034",
-        "aerls04",
-        "aerosol type 4 sink/loss accumulated"
-    ],
-    [
-        "210035",
-        "aerls05",
-        "aerosol type 5 sink/loss accumulated"
-    ],
-    [
-        "210036",
-        "aerls06",
-        "aerosol type 6 sink/loss accumulated"
-    ],
-    [
-        "210037",
-        "aerls07",
-        "aerosol type 7 sink/loss accumulated"
-    ],
-    [
-        "210038",
-        "aerls08",
-        "aerosol type 8 sink/loss accumulated"
-    ],
-    [
-        "210039",
-        "aerls09",
-        "aerosol type 9 sink/loss accumulated"
-    ],
-    [
-        "210040",
-        "aerls10",
-        "aerosol type 10 sink/loss accumulated"
-    ],
-    [
-        "210041",
-        "aerls11",
-        "aerosol type 11 sink/loss accumulated"
-    ],
-    [
-        "210042",
-        "aerls12",
-        "aerosol type 12 sink/loss accumulated"
-    ],
-    [
-        "210046",
-        "aerpr",
-        "aerosol precursor mixing ratio"
-    ],
-    [
-        "210047",
-        "aersm",
-        "aerosol small mode mixing ratio"
-    ],
-    [
-        "210048",
-        "aerlg",
-        "aerosol large mode mixing ratio"
-    ],
-    [
-        "210049",
-        "aodpr",
-        "aerosol precursor optical depth"
-    ],
-    [
-        "210050",
-        "aodsm",
-        "aerosol small mode optical depth"
-    ],
-    [
-        "210051",
-        "aodlg",
-        "aerosol large mode optical depth"
-    ],
-    [
-        "210052",
-        "aerdep",
-        "dust emission potential"
-    ],
-    [
-        "210053",
-        "aerlts",
-        "lifting threshold speed"
-    ],
-    [
-        "210054",
-        "aerscc",
-        "soil clay content"
-    ],
-    [
-        "210061",
-        "co2",
-        "carbon dioxide"
-    ],
-    [
-        "210062",
-        "ch4",
-        "methane"
-    ],
-    [
-        "210063",
-        "n2o",
-        "nitrous oxide"
-    ],
-    [
-        "210064",
-        "tcco2",
-        "total column carbon dioxide"
-    ],
-    [
-        "210065",
-        "tcch4",
-        "total column methane"
-    ],
-    [
-        "210066",
-        "tcn2o",
-        "total column nitrous oxide"
-    ],
-    [
-        "210067",
-        "co2of",
-        "ocean flux of carbon dioxide"
-    ],
-    [
-        "210068",
-        "co2nbf",
-        "natural biosphere flux of carbon dioxide"
-    ],
-    [
-        "210069",
-        "co2apf",
-        "anthropogenic emissions of carbon dioxide"
-    ],
-    [
-        "210070",
-        "ch4f",
-        "methane surface fluxes"
-    ],
-    [
-        "210071",
-        "kch4",
-        "methane loss rate due to radical hydroxyl (oh)"
-    ],
-    [
-        "210080",
-        "co2fire",
-        "wildfire flux of carbon dioxide"
-    ],
-    [
-        "210081",
-        "cofire",
-        "wildfire flux of carbon monoxide"
-    ],
-    [
-        "210082",
-        "ch4fire",
-        "wildfire flux of methane"
-    ],
-    [
-        "210083",
-        "nmhcfire",
-        "wildfire flux of non-methane hydro-carbons"
-    ],
-    [
-        "210084",
-        "h2fire",
-        "wildfire flux of hydrogen"
-    ],
-    [
-        "210085",
-        "noxfire",
-        "wildfire flux of nitrogen oxides nox"
-    ],
-    [
-        "210086",
-        "n2ofire",
-        "wildfire flux of nitrous oxide"
-    ],
-    [
-        "210087",
-        "pm2p5fire",
-        "wildfire flux of particulate matter pm2.5"
-    ],
-    [
-        "210088",
-        "tpmfire",
-        "wildfire flux of total particulate matter"
-    ],
-    [
-        "210089",
-        "tcfire",
-        "wildfire flux of total carbon in aerosols"
-    ],
-    [
-        "210090",
-        "ocfire",
-        "wildfire flux of organic carbon"
-    ],
-    [
-        "210091",
-        "bcfire",
-        "wildfire flux of black carbon"
-    ],
-    [
-        "210092",
-        "cfire",
-        "wildfire overall flux of burnt carbon"
-    ],
-    [
-        "210093",
-        "c4ffire",
-        "wildfire fraction of c4 plants"
-    ],
-    [
-        "210094",
-        "vegfire",
-        "wildfire vegetation map index"
-    ],
-    [
-        "210095",
-        "ccfire",
-        "wildfire combustion completeness"
-    ],
-    [
-        "210096",
-        "flfire",
-        "wildfire fuel load: carbon per unit area"
-    ],
-    [
-        "210097",
-        "offire",
-        "wildfire fraction of area observed"
-    ],
-    [
-        "210098",
-        "nofrp",
-        "number of positive frp pixels per grid cell"
-    ],
-    [
-        "210099",
-        "frpfire",
-        "wildfire radiative power"
-    ],
-    [
-        "210100",
-        "crfire",
-        "wildfire combustion rate"
-    ],
-    [
-        "210121",
-        "no2",
-        "nitrogen dioxide"
-    ],
-    [
-        "210122",
-        "so2",
-        "sulphur dioxide"
-    ],
-    [
-        "210123",
-        "co",
-        "carbon monoxide"
-    ],
-    [
-        "210124",
-        "hcho",
-        "formaldehyde"
-    ],
-    [
-        "210125",
-        "tcno2",
-        "total column nitrogen dioxide"
-    ],
-    [
-        "210126",
-        "tcso2",
-        "total column sulphur dioxide"
-    ],
-    [
-        "210127",
-        "tcco",
-        "total column carbon monoxide"
-    ],
-    [
-        "210128",
-        "tchcho",
-        "total column formaldehyde"
-    ],
-    [
-        "210129",
-        "nox",
-        "nitrogen oxides"
-    ],
-    [
-        "210130",
-        "tcnox",
-        "total column nitrogen oxides"
-    ],
-    [
-        "210131",
-        "grg1",
-        "reactive tracer 1 mass mixing ratio"
-    ],
-    [
-        "210132",
-        "tcgrg1",
-        "total column grg tracer 1"
-    ],
-    [
-        "210133",
-        "grg2",
-        "reactive tracer 2 mass mixing ratio"
-    ],
-    [
-        "210134",
-        "tcgrg2",
-        "total column grg tracer 2"
-    ],
-    [
-        "210135",
-        "grg3",
-        "reactive tracer 3 mass mixing ratio"
-    ],
-    [
-        "210136",
-        "tcgrg3",
-        "total column grg tracer 3"
-    ],
-    [
-        "210137",
-        "grg4",
-        "reactive tracer 4 mass mixing ratio"
-    ],
-    [
-        "210138",
-        "tcgrg4",
-        "total column grg tracer 4"
-    ],
-    [
-        "210139",
-        "grg5",
-        "reactive tracer 5 mass mixing ratio"
-    ],
-    [
-        "210140",
-        "tcgrg5",
-        "total column grg tracer 5"
-    ],
-    [
-        "210141",
-        "grg6",
-        "reactive tracer 6 mass mixing ratio"
-    ],
-    [
-        "210142",
-        "tcgrg6",
-        "total column grg tracer 6"
-    ],
-    [
-        "210143",
-        "grg7",
-        "reactive tracer 7 mass mixing ratio"
-    ],
-    [
-        "210144",
-        "tcgrg7",
-        "total column grg tracer 7"
-    ],
-    [
-        "210145",
-        "grg8",
-        "reactive tracer 8 mass mixing ratio"
-    ],
-    [
-        "210146",
-        "tcgrg8",
-        "total column grg tracer 8"
-    ],
-    [
-        "210147",
-        "grg9",
-        "reactive tracer 9 mass mixing ratio"
-    ],
-    [
-        "210148",
-        "tcgrg9",
-        "total column grg tracer 9"
-    ],
-    [
-        "210149",
-        "grg10",
-        "reactive tracer 10 mass mixing ratio"
-    ],
-    [
-        "210150",
-        "tcgrg10",
-        "total column grg tracer 10"
-    ],
-    [
-        "210151",
-        "sfnox",
-        "surface flux nitrogen oxides"
-    ],
-    [
-        "210152",
-        "sfno2",
-        "surface flux nitrogen dioxide"
-    ],
-    [
-        "210153",
-        "sfso2",
-        "surface flux sulphur dioxide"
-    ],
-    [
-        "210154",
-        "sfco2",
-        "surface flux carbon monoxide"
-    ],
-    [
-        "210155",
-        "sfhcho",
-        "surface flux formaldehyde"
-    ],
-    [
-        "210156",
-        "sfgo3",
-        "surface flux gems ozone"
-    ],
-    [
-        "210157",
-        "sfgr1",
-        "surface flux reactive tracer 1"
-    ],
-    [
-        "210158",
-        "sfgr2",
-        "surface flux reactive tracer 2"
-    ],
-    [
-        "210159",
-        "sfgr3",
-        "surface flux reactive tracer 3"
-    ],
-    [
-        "210160",
-        "sfgr4",
-        "surface flux reactive tracer 4"
-    ],
-    [
-        "210161",
-        "sfgr5",
-        "surface flux reactive tracer 5"
-    ],
-    [
-        "210162",
-        "sfgr6",
-        "surface flux reactive tracer 6"
-    ],
-    [
-        "210163",
-        "sfgr7",
-        "surface flux reactive tracer 7"
-    ],
-    [
-        "210164",
-        "sfgr8",
-        "surface flux reactive tracer 8"
-    ],
-    [
-        "210165",
-        "sfgr9",
-        "surface flux reactive tracer 9"
-    ],
-    [
-        "210166",
-        "sfgr10",
-        "surface flux reactive tracer 10"
-    ],
-    [
-        "210181",
-        "ra",
-        "radon"
-    ],
-    [
-        "210182",
-        "sf6",
-        "sulphur hexafluoride"
-    ],
-    [
-        "210183",
-        "tcra",
-        "total column radon"
-    ],
-    [
-        "210184",
-        "tcsf6",
-        "total column sulphur hexafluoride"
-    ],
-    [
-        "210185",
-        "sf6apf",
-        "anthropogenic emissions of sulphur hexafluoride"
-    ],
-    [
-        "210203",
-        "go3",
-        "gems ozone"
-    ],
-    [
-        "210206",
-        "gtco3",
-        "gems total column ozone"
-    ],
-    [
-        "210207",
-        "aod550",
-        "total aerosol optical depth at 550nm"
-    ],
-    [
-        "210208",
-        "ssaod550",
-        "sea salt aerosol optical depth at 550nm"
-    ],
-    [
-        "210209",
-        "duaod550",
-        "dust aerosol optical depth at 550nm"
-    ],
-    [
-        "210210",
-        "omaod550",
-        "organic matter aerosol optical depth at 550nm"
-    ],
-    [
-        "210211",
-        "bcaod550",
-        "black carbon aerosol optical depth at 550nm"
-    ],
-    [
-        "210212",
-        "suaod550",
-        "sulphate aerosol optical depth at 550nm"
-    ],
-    [
-        "210213",
-        "aod469",
-        "total aerosol optical depth at 469nm"
-    ],
-    [
-        "210214",
-        "aod670",
-        "total aerosol optical depth at 670nm"
-    ],
-    [
-        "210215",
-        "aod865",
-        "total aerosol optical depth at 865nm"
-    ],
-    [
-        "210216",
-        "aod1240",
-        "total aerosol optical depth at 1240nm"
-    ],
-    [
-        "211046",
-        "aerprdiff",
-        "aerosol precursor mixing ratio"
-    ],
-    [
-        "211047",
-        "aersmdiff",
-        "aerosol small mode mixing ratio"
-    ],
-    [
-        "211048",
-        "aerlgdiff",
-        "aerosol large mode mixing ratio"
-    ],
-    [
-        "211049",
-        "aodprdiff",
-        "aerosol precursor optical depth"
-    ],
-    [
-        "211050",
-        "aodsmdiff",
-        "aerosol small mode optical depth"
-    ],
-    [
-        "211051",
-        "aodlgdiff",
-        "aerosol large mode optical depth"
-    ],
-    [
-        "211061",
-        "co2diff",
-        "carbon dioxide"
-    ],
-    [
-        "211062",
-        "ch4diff",
-        "methane"
-    ],
-    [
-        "211063",
-        "n2odiff",
-        "nitrous oxide"
-    ],
-    [
-        "211121",
-        "no2diff",
-        "nitrogen dioxide"
-    ],
-    [
-        "211122",
-        "so2diff",
-        "sulphur dioxide"
-    ],
-    [
-        "211123",
-        "codiff",
-        "carbon monoxide"
-    ],
-    [
-        "211124",
-        "hchodiff",
-        "formaldehyde"
-    ],
-    [
-        "211203",
-        "go3diff",
-        "gems ozone"
-    ],
-    [
-        "220228",
-        "tpoc",
-        "total precipitation observation count"
-    ],
-    [
-        "228001",
-        "cin",
-        "convective inhibition"
-    ],
-    [
-        "228002",
-        "orog",
-        "orography"
-    ],
-    [
-        "228003",
-        "zust",
-        "friction velocity"
-    ],
-    [
-        "228004",
-        "mean2t",
-        "mean temperature at 2 metres"
-    ],
-    [
-        "228005",
-        "mean10ws",
-        "mean of 10 metre wind speed"
-    ],
-    [
-        "228006",
-        "meantcc",
-        "mean total cloud cover"
-    ],
-    [
-        "228007",
-        "dl",
-        "lake depth"
-    ],
-    [
-        "228008",
-        "lmlt",
-        "lake mix-layer temperature"
-    ],
-    [
-        "228009",
-        "lmld",
-        "lake mix-layer depth"
-    ],
-    [
-        "228010",
-        "lblt",
-        "lake bottom temperature"
-    ],
-    [
-        "228011",
-        "ltlt",
-        "lake total layer temperature"
-    ],
-    [
-        "228012",
-        "lshf",
-        "lake shape factor"
-    ],
-    [
-        "228013",
-        "lict",
-        "lake ice temperature"
-    ],
-    [
-        "228014",
-        "licd",
-        "lake ice depth"
-    ],
-    [
-        "228015",
-        "dndzn",
-        "minimum vertical gradient of refractivity inside trapping layer"
-    ],
-    [
-        "228016",
-        "dndza",
-        "mean vertical gradient of refractivity inside trapping layer"
-    ],
-    [
-        "228017",
-        "dctb",
-        "duct base height"
-    ],
-    [
-        "228018",
-        "tplb",
-        "trapping layer base height"
-    ],
-    [
-        "228019",
-        "tplt",
-        "trapping layer top height"
-    ],
-    [
-        "228039",
-        "sm",
-        "soil moisture"
-    ],
-    [
-        "228131",
-        "u10n",
-        "neutral wind at 10 m u-component"
-    ],
-    [
-        "228132",
-        "v10n",
-        "neutral wind at 10 m v-component"
-    ],
-    [
-        "228139",
-        "st",
-        "soil temperature"
-    ],
-    [
-        "228141",
-        "sd",
-        "snow depth water equivalent"
-    ],
-    [
-        "228144",
-        "sf",
-        "snow fall water equivalent"
-    ],
-    [
-        "228164",
-        "tcc",
-        "total cloud cover"
-    ],
-    [
-        "228170",
-        "cap",
-        "field capacity"
-    ],
-    [
-        "228171",
-        "wilt",
-        "wilting point"
-    ],
-    [
-        "228228",
-        "tp",
-        "total precipitation"
-    ],
-    [
-        "230044",
-        "esvar",
-        "snow evaporation (variable resolution)"
-    ],
-    [
-        "230045",
-        "smltvar",
-        "snowmelt (variable resolution)"
-    ],
-    [
-        "230046",
-        "sdurvar",
-        "solar duration (variable resolution)"
-    ],
-    [
-        "230057",
-        "uvbvar",
-        "downward uv radiation at the surface (variable resolution)"
-    ],
-    [
-        "230058",
-        "parvar",
-        "photosynthetically active radiation at the surface (variable resolution)"
-    ],
-    [
-        "230142",
-        "lspvar",
-        "stratiform precipitation (large-scale precipitation) (variable resolution)"
-    ],
-    [
-        "230143",
-        "cpvar",
-        "convective precipitation (variable resolution)"
-    ],
-    [
-        "230144",
-        "sfvar",
-        "snowfall (convective + stratiform) (variable resolution)"
-    ],
-    [
-        "230145",
-        "bldvar",
-        "boundary layer dissipation (variable resolution)"
-    ],
-    [
-        "230146",
-        "sshfvar",
-        "surface sensible heat flux (variable resolution)"
-    ],
-    [
-        "230147",
-        "slhfvar",
-        "surface latent heat flux (variable resolution)"
-    ],
-    [
-        "230169",
-        "ssrdvar",
-        "surface solar radiation downwards (variable resolution)"
-    ],
-    [
-        "230175",
-        "strdvar",
-        "surface thermal radiation downwards (variable resolution)"
-    ],
-    [
-        "230176",
-        "ssrvar",
-        "surface net solar radiation (variable resolution)"
-    ],
-    [
-        "230177",
-        "strvar",
-        "surface net thermal radiation (variable resolution)"
-    ],
-    [
-        "230178",
-        "tsrvar",
-        "top net solar radiation (variable resolution)"
-    ],
-    [
-        "230179",
-        "ttrvar",
-        "top net thermal radiation (variable resolution)"
-    ],
-    [
-        "230180",
-        "ewssvar",
-        "east-west surface stress (variable resolution)"
-    ],
-    [
-        "230181",
-        "nsssvar",
-        "north-south surface stress (variable resolution)"
-    ],
-    [
-        "230182",
-        "evar",
-        "evaporation (variable resolution)"
-    ],
-    [
-        "230189",
-        "sundvar",
-        "sunshine duration (variable resolution)"
-    ],
-    [
-        "230195",
-        "lgwsvar",
-        "longitudinal component of gravity wave stress (variable resolution)"
-    ],
-    [
-        "230196",
-        "mgwsvar",
-        "meridional component of gravity wave stress (variable resolution)"
-    ],
-    [
-        "230197",
-        "gwdvar",
-        "gravity wave dissipation (variable resolution)"
-    ],
-    [
-        "230198",
-        "srcvar",
-        "skin reservoir content (variable resolution)"
-    ],
-    [
-        "230205",
-        "rovar",
-        "runoff (variable resolution)"
-    ],
-    [
-        "230208",
-        "tsrcvar",
-        "top net solar radiation, clear sky (variable resolution)"
-    ],
-    [
-        "230209",
-        "ttrcvar",
-        "top net thermal radiation, clear sky (variable resolution)"
-    ],
-    [
-        "230210",
-        "ssrcvar",
-        "surface net solar radiation, clear sky (variable resolution)"
-    ],
-    [
-        "230211",
-        "strcvar",
-        "surface net thermal radiation, clear sky (variable resolution)"
-    ],
-    [
-        "230212",
-        "tisrvar",
-        "toa incident solar radiation (variable resolution)"
-    ],
-    [
-        "234139",
-        "sts",
-        "surface temperature significance"
-    ],
-    [
-        "234151",
-        "msls",
-        "mean sea level pressure significance"
-    ],
-    [
-        "234167",
-        "2ts",
-        "2 metre temperature significance"
-    ],
-    [
-        "234228",
-        "tps",
-        "total precipitation significance"
-    ],
-    [
-        "3042",
-        "absd",
-        "absolute divergence"
-    ],
-    [
-        "3064",
-        "srweq",
-        "snow fall rate water equivalent"
-    ],
-    [
-        "3105",
-        "swell",
-        "significant height of swell waves"
-    ],
-    [
-        "3027",
-        "gpa",
-        "geopotential height anomaly"
-    ],
-    [
-        "3062",
-        "lsp",
-        "large scale precipitation"
-    ],
-    [
-        "3025",
-        "ta",
-        "temperature anomaly"
-    ],
-    [
-        "3055",
-        "vp",
-        "vapour pressure"
-    ],
-    [
-        "3047",
-        "dirc",
-        "direction of current"
-    ],
-    [
-        "3049",
-        "ucurr",
-        "u-component of current "
-    ],
-    [
-        "3119",
-        "lwrad",
-        "radiance (with respect to wave number)"
-    ],
-    [
-        "3028",
-        "wvsp1",
-        "wave spectra (1)"
-    ],
-    [
-        "3104",
-        "swdir",
-        "direction of swell waves"
-    ],
-    [
-        "3093",
-        "diced",
-        "direction of ice drift"
-    ],
-    [
-        "3056",
-        "satd",
-        "saturation deficit"
-    ],
-    [
-        "3114",
-        "nlwrt",
-        "net long-wave radiation flux(atmosph.top)"
-    ],
-    [
-        "3103",
-        "mpww",
-        "mean period of wind waves"
-    ],
-    [
-        "3108",
-        "mpps",
-        "primary wave mean period"
-    ],
-    [
-        "3088",
-        "s",
-        "salinity"
-    ],
-    [
-        "3024",
-        "pli",
-        "parcel lifted index (to 500 hpa)"
-    ],
-    [
-        "3069",
-        "mthd",
-        "main thermocline depth"
-    ],
-    [
-        "3125",
-        "vflx",
-        "momentum flux, v-component"
-    ],
-    [
-        "3095",
-        "uice",
-        "u-component of ice drift"
-    ],
-    [
-        "3018",
-        "depr",
-        "dew point depression (or deficit)"
-    ],
-    [
-        "3082",
-        "dslm",
-        "deviation of sea-level from mean"
-    ],
-    [
-        "3008",
-        "h",
-        "geometrical height"
-    ],
-    [
-        "3046",
-        "vvcsh",
-        "vertical v-component shear"
-    ],
-    [
-        "3048",
-        "spc",
-        "speed of current"
-    ],
-    [
-        "3097",
-        "iceg",
-        "ice growth rate"
-    ],
-    [
-        "3016",
-        "tmin",
-        "minimum temperature"
-    ],
-    [
-        "3029",
-        "wvsp2",
-        "wave spectra (2)"
-    ],
-    [
-        "3017",
-        "dpt",
-        "dew point temperature"
-    ],
-    [
-        "3115",
-        "lwavr",
-        "long wave radiation flux"
-    ],
-    [
-        "3031",
-        "wdir",
-        "wind direction"
-    ],
-    [
-        "3021",
-        "rdsp1",
-        "radar spectra (1)"
-    ],
-    [
-        "3080",
-        "wtmp",
-        "water temperature"
-    ],
-    [
-        "3112",
-        "nlwrs",
-        "net long-wave radiation flux (surface)"
-    ],
-    [
-        "3124",
-        "uflx",
-        "momentum flux, u-component"
-    ],
-    [
-        "3101",
-        "mdww",
-        "mean direction of wind waves"
-    ],
-    [
-        "3127",
-        "imgd",
-        "image data"
-    ],
-    [
-        "3116",
-        "swavr",
-        "short wave radiation flux"
-    ],
-    [
-        "3096",
-        "vice",
-        "v-component of ice drift"
-    ],
-    [
-        "3086",
-        "ssw",
-        "soil moisture content"
-    ],
-    [
-        "3037",
-        "mntsf",
-        "montgomery stream function"
-    ],
-    [
-        "3094",
-        "siced",
-        "speed of ice drift"
-    ],
-    [
-        "3012",
-        "vptmp",
-        "virtual potential temperature"
-    ],
-    [
-        "3009",
-        "hstdv",
-        "standard deviation of height"
-    ],
-    [
-        "3050",
-        "vcurr",
-        "v-component of current "
-    ],
-    [
-        "3067",
-        "mld",
-        "mixed layer depth"
-    ],
-    [
-        "3111",
-        "nswrs",
-        "net short-wave radiation flux (surface)"
-    ],
-    [
-        "3068",
-        "tthdp",
-        "transient thermocline depth"
-    ],
-    [
-        "3110",
-        "swp",
-        "secondary wave mean period"
-    ],
-    [
-        "3102",
-        "shww",
-        "significant height of wind waves"
-    ],
-    [
-        "3126",
-        "wmixe",
-        "wind mixing energy"
-    ],
-    [
-        "3070",
-        "mtha",
-        "main thermocline anomaly"
-    ],
-    [
-        "3060",
-        "tstm",
-        "thunderstorm probability"
-    ],
-    [
-        "3003",
-        "ptend",
-        "pressure tendency"
-    ],
-    [
-        "3015",
-        "tmax",
-        "maximum temperature"
-    ],
-    [
-        "3098",
-        "iced",
-        "ice divergence"
-    ],
-    [
-        "3100",
-        "swh",
-        "signific.height,combined wind waves+swell"
-    ],
-    [
-        "3117",
-        "grad",
-        "global radiation flux"
-    ],
-    [
-        "3092",
-        "icetk",
-        "ice thickness"
-    ],
-    [
-        "3091",
-        "icec",
-        "ice cover (1=ice, 0=no ice)"
-    ],
-    [
-        "3109",
-        "dirsw",
-        "secondary wave direction"
-    ],
-    [
-        "3030",
-        "wvsp3",
-        "wave spectra (3)"
-    ],
-    [
-        "3026",
-        "presa",
-        "pressure anomaly"
-    ],
-    [
-        "3107",
-        "mdps",
-        "primary wave direction"
-    ],
-    [
-        "3014",
-        "papt",
-        "pseudo-adiabatic potential temperature"
-    ],
-    [
-        "3022",
-        "rdsp2",
-        "radar spectra (2)"
-    ],
-    [
-        "3019",
-        "lapr",
-        "lapse rate"
-    ],
-    [
-        "3077",
-        "bli",
-        "best lifted index (to 500 hpa)"
-    ],
-    [
-        "3038",
-        "sgcvv",
-        "sigma coordinate vertical velocity"
-    ],
-    [
-        "3089",
-        "den",
-        "density"
-    ],
-    [
-        "3059",
-        "prate",
-        "precipitation rate"
-    ],
-    [
-        "3054",
-        "pwat",
-        "precipitable water"
-    ],
-    [
-        "3020",
-        "vis",
-        "visibility"
-    ],
-    [
-        "3005",
-        "icaht",
-        "icao standard atmosphere reference height"
-    ],
-    [
-        "3106",
-        "swper",
-        "mean period of swell waves"
-    ],
-    [
-        "3063",
-        "acpcp",
-        "convective precipitation (water)"
-    ],
-    [
-        "3041",
-        "absv",
-        "absolute vorticity"
-    ],
-    [
-        "3113",
-        "nswrt",
-        "net short-wave radiation flux(atmosph.top)"
-    ],
-    [
-        "3120",
-        "swrad",
-        "radiance (with respect to wave length)"
-    ],
-    [
-        "3099",
-        "snom",
-        "snow melt"
-    ],
-    [
-        "3053",
-        "mixr",
-        "humidity mixing ratio"
-    ],
-    [
-        "3023",
-        "rdsp3",
-        "radar spectra (3)"
-    ],
-    [
-        "3045",
-        "vucsh",
-        "vertical u-component shear"
-    ],
-    [
-        "228080",
-        "aco2nee",
-        "accumulated carbon dioxide net ecosystem exchange"
-    ],
-    [
-        "260002",
-        "lhtfl",
-        "latent heat net flux"
-    ],
-    [
-        "260003",
-        "shtfl",
-        "sensible heat net flux"
-    ],
-    [
-        "260004",
-        "heatx",
-        "heat index"
-    ],
-    [
-        "260005",
-        "wcf",
-        "wind chill factor"
-    ],
-    [
-        "260006",
-        "mindpd",
-        "minimum dew point depression"
-    ],
-    [
-        "260007",
-        "snohf",
-        "snow phase change heat flux"
-    ],
-    [
-        "260008",
-        "vapp",
-        "vapor pressure"
-    ],
-    [
-        "260009",
-        "ncpcp",
-        "large scale precipitation (non-convective)"
-    ],
-    [
-        "260010",
-        "srweq",
-        "snowfall rate water equivalent"
-    ],
-    [
-        "260011",
-        "snoc",
-        "convective snow"
-    ],
-    [
-        "260012",
-        "snol",
-        "large scale snow"
-    ],
-    [
-        "260013",
-        "snoag",
-        "snow age"
-    ],
-    [
-        "260014",
-        "absh",
-        "absolute humidity"
-    ],
-    [
-        "260015",
-        "ptype",
-        "precipitation type"
-    ],
-    [
-        "260016",
-        "iliqw",
-        "integrated liquid water"
-    ],
-    [
-        "260017",
-        "tcond",
-        "condensate"
-    ],
-    [
-        "260018",
-        "clwmr",
-        "cloud mixing ratio"
-    ],
-    [
-        "260019",
-        "icmr",
-        "ice water mixing ratio"
-    ],
-    [
-        "260020",
-        "rwmr",
-        "rain mixing ratio"
-    ],
-    [
-        "260021",
-        "snmr",
-        "snow mixing ratio"
-    ],
-    [
-        "260022",
-        "mconv",
-        "horizontal moisture convergence"
-    ],
-    [
-        "260023",
-        "maxrh",
-        "maximum relative humidity"
-    ],
-    [
-        "260024",
-        "maxah",
-        "maximum absolute humidity"
-    ],
-    [
-        "260025",
-        "asnow",
-        "total snowfall"
-    ],
-    [
-        "260026",
-        "pwcat",
-        "precipitable water category"
-    ],
-    [
-        "260027",
-        "hail",
-        "hail"
-    ],
-    [
-        "260028",
-        "grle",
-        "graupel (snow pellets)"
-    ],
-    [
-        "260029",
-        "crain",
-        "categorical rain"
-    ],
-    [
-        "260030",
-        "cfrzr",
-        "categorical freezing rain"
-    ],
-    [
-        "260031",
-        "cicep",
-        "categorical ice pellets"
-    ],
-    [
-        "260032",
-        "csnow",
-        "categorical snow"
-    ],
-    [
-        "260033",
-        "cprat",
-        "convective precipitation rate"
-    ],
-    [
-        "260034",
-        "mdiv",
-        "horizontal moisture divergence"
-    ],
-    [
-        "260035",
-        "cpofp",
-        "percent frozen precipitation"
-    ],
-    [
-        "260036",
-        "pevap",
-        "potential evaporation"
-    ],
-    [
-        "260037",
-        "pevpr",
-        "potential evaporation rate"
-    ],
-    [
-        "260038",
-        "snowc",
-        "snow cover"
-    ],
-    [
-        "260039",
-        "frain",
-        "rain fraction of total cloud water"
-    ],
-    [
-        "260040",
-        "rime",
-        "rime factor"
-    ],
-    [
-        "260041",
-        "tcolr",
-        "total column integrated rain"
-    ],
-    [
-        "260042",
-        "tcols",
-        "total column integrated snow"
-    ],
-    [
-        "260043",
-        "lswp",
-        "large scale water precipitation (non-convective)"
-    ],
-    [
-        "260044",
-        "cwp",
-        "convective water precipitation"
-    ],
-    [
-        "260045",
-        "twatp",
-        "total water precipitation"
-    ],
-    [
-        "260046",
-        "tsnowp",
-        "total snow precipitation"
-    ],
-    [
-        "260047",
-        "tcwat",
-        "total column water (vertically integrated total water (vapour + cloud water/ice))"
-    ],
-    [
-        "260048",
-        "tprate",
-        "total precipitation rate"
-    ],
-    [
-        "260049",
-        "tsrwe",
-        "total snowfall rate water equivalent"
-    ],
-    [
-        "260050",
-        "lsprate",
-        "large scale precipitation rate"
-    ],
-    [
-        "260051",
-        "csrwe",
-        "convective snowfall rate water equivalent"
-    ],
-    [
-        "260052",
-        "lssrwe",
-        "large scale snowfall rate water equivalent"
-    ],
-    [
-        "260053",
-        "tsrate",
-        "total snowfall rate"
-    ],
-    [
-        "260054",
-        "csrate",
-        "convective snowfall rate"
-    ],
-    [
-        "260055",
-        "lssrate",
-        "large scale snowfall rate"
-    ],
-    [
-        "260056",
-        "sdwe",
-        "water equivalent of accumulated snow depth"
-    ],
-    [
-        "260057",
-        "tciwv",
-        "total column integrated water vapour"
-    ],
-    [
-        "260058",
-        "rprate",
-        "rain precipitation rate"
-    ],
-    [
-        "260059",
-        "sprate",
-        "snow precipitation rate"
-    ],
-    [
-        "260060",
-        "fprate",
-        "freezing rain precipitation rate"
-    ],
-    [
-        "260061",
-        "iprate",
-        "ice pellets precipitation rate"
-    ],
-    [
-        "260062",
-        "uflx",
-        "momentum flux, u component"
-    ],
-    [
-        "260063",
-        "vflx",
-        "momentum flux, v component"
-    ],
-    [
-        "260064",
-        "maxgust",
-        "maximum wind speed"
-    ],
-    [
-        "260065",
-        "gust",
-        "wind speed (gust)"
-    ],
-    [
-        "260066",
-        "ugust",
-        "u-component of wind (gust)"
-    ],
-    [
-        "260067",
-        "vgust",
-        "v-component of wind (gust)"
-    ],
-    [
-        "260068",
-        "vwsh",
-        "vertical speed shear"
-    ],
-    [
-        "260069",
-        "mflx",
-        "horizontal momentum flux"
-    ],
-    [
-        "260070",
-        "ustm",
-        "u-component storm motion"
-    ],
-    [
-        "260071",
-        "vstm",
-        "v-component storm motion"
-    ],
-    [
-        "260072",
-        "cd",
-        "drag coefficient"
-    ],
-    [
-        "260073",
-        "fricv",
-        "frictional velocity"
-    ],
-    [
-        "260074",
-        "prmsl",
-        "pressure reduced to msl"
-    ],
-    [
-        "260075",
-        "dist",
-        "geometric height"
-    ],
-    [
-        "260076",
-        "alts",
-        "altimeter setting"
-    ],
-    [
-        "260077",
-        "thick",
-        "thickness"
-    ],
-    [
-        "260078",
-        "presalt",
-        "pressure altitude"
-    ],
-    [
-        "260079",
-        "denalt",
-        "density altitude"
-    ],
-    [
-        "260080",
-        "5wavh",
-        "5-wave geopotential height"
-    ],
-    [
-        "260081",
-        "u-gwd",
-        "zonal flux of gravity wave stress"
-    ],
-    [
-        "260082",
-        "v-gwd",
-        "meridional flux of gravity wave stress"
-    ],
-    [
-        "260083",
-        "hpbl",
-        "planetary boundary layer height"
-    ],
-    [
-        "260084",
-        "5wava",
-        "5-wave geopotential height anomaly"
-    ],
-    [
-        "260085",
-        "sdsgso",
-        "standard deviation of sub-grid scale orography"
-    ],
-    [
-        "260086",
-        "nswrt",
-        "net short-wave radiation flux (top of atmosphere)"
-    ],
-    [
-        "260087",
-        "dswrf",
-        "downward short-wave radiation flux"
-    ],
-    [
-        "260088",
-        "uswrf",
-        "upward short-wave radiation flux"
-    ],
-    [
-        "260089",
-        "nswrf",
-        "net short wave radiation flux"
-    ],
-    [
-        "260090",
-        "photar",
-        "photosynthetically active radiation"
-    ],
-    [
-        "260091",
-        "nswrfcs",
-        "net short-wave radiation flux, clear sky"
-    ],
-    [
-        "260092",
-        "dwuvr",
-        "downward uv radiation"
-    ],
-    [
-        "260093",
-        "uviucs",
-        "uv index (under clear sky)"
-    ],
-    [
-        "260094",
-        "uvi",
-        "uv index "
-    ],
-    [
-        "260095",
-        "nlwrs",
-        "net long wave radiation flux (surface)"
-    ],
-    [
-        "260096",
-        "nlwrt",
-        "net long wave radiation flux (top of atmosphere)"
-    ],
-    [
-        "260097",
-        "dlwrf",
-        "downward long-wave radiation flux"
-    ],
-    [
-        "260098",
-        "ulwrf",
-        "upward long-wave radiation flux"
-    ],
-    [
-        "260099",
-        "nlwrf",
-        "net long wave radiation flux"
-    ],
-    [
-        "260100",
-        "nlwrcs",
-        "net long-wave radiation flux, clear sky"
-    ],
-    [
-        "260101",
-        "cice",
-        "cloud ice"
-    ],
-    [
-        "260102",
-        "cwat",
-        "cloud water"
-    ],
-    [
-        "260103",
-        "cdca",
-        "cloud amount"
-    ],
-    [
-        "260104",
-        "cdct",
-        "cloud type"
-    ],
-    [
-        "260105",
-        "tmaxt",
-        "thunderstorm maximum tops"
-    ],
-    [
-        "260106",
-        "thunc",
-        "thunderstorm coverage"
-    ],
-    [
-        "260107",
-        "cdcb",
-        "cloud base"
-    ],
-    [
-        "260108",
-        "cdct",
-        "cloud top"
-    ],
-    [
-        "260109",
-        "ceil",
-        "ceiling"
-    ],
-    [
-        "260110",
-        "cdlyr",
-        "non-convective cloud cover"
-    ],
-    [
-        "260111",
-        "cwork",
-        "cloud work function"
-    ],
-    [
-        "260112",
-        "cuefi",
-        "convective cloud efficiency"
-    ],
-    [
-        "260113",
-        "tcond",
-        "total condensate"
-    ],
-    [
-        "260114",
-        "tcolw",
-        "total column-integrated cloud water"
-    ],
-    [
-        "260115",
-        "tcoli",
-        "total column-integrated cloud ice"
-    ],
-    [
-        "260116",
-        "tcolc",
-        "total column-integrated condensate"
-    ],
-    [
-        "260117",
-        "fice",
-        "ice fraction of total condensate"
-    ],
-    [
-        "260118",
-        "cdcimr",
-        "cloud ice mixing ratio"
-    ],
-    [
-        "260119",
-        "suns",
-        "sunshine"
-    ],
-    [
-        "260120",
-        "horizontal extent of cumulonimbus (cb)"
-    ],
-    [
-        "260121",
-        "kx",
-        "k index"
-    ],
-    [
-        "260122",
-        "kox",
-        "ko index"
-    ],
-    [
-        "260123",
-        "totalx",
-        "total totals index"
-    ],
-    [
-        "260124",
-        "sx",
-        "sweat index"
-    ],
-    [
-        "260125",
-        "hlcy",
-        "storm relative helicity"
-    ],
-    [
-        "260126",
-        "ehlx",
-        "energy helicity index"
-    ],
-    [
-        "260127",
-        "lftx",
-        "surface lifted index"
-    ],
-    [
-        "260128",
-        "4lftx",
-        "best (4-layer) lifted index"
-    ],
-    [
-        "260129",
-        "aerot",
-        "aerosol type"
-    ],
-    [
-        "260130",
-        "tozne",
-        "total ozone"
-    ],
-    [
-        "260131",
-        "o3mr",
-        "ozone mixing ratio"
-    ],
-    [
-        "260132",
-        "tcioz",
-        "total column integrated ozone"
-    ],
-    [
-        "260133",
-        "bswid",
-        "base spectrum width"
-    ],
-    [
-        "260134",
-        "bref",
-        "base reflectivity"
-    ],
-    [
-        "260135",
-        "brvel",
-        "base radial velocity"
-    ],
-    [
-        "260136",
-        "veril",
-        "vertically-integrated liquid"
-    ],
-    [
-        "260137",
-        "lmaxbr",
-        "layer-maximum base reflectivity"
-    ],
-    [
-        "260138",
-        "prec",
-        "precipitation"
-    ],
-    [
-        "260139",
-        "acces",
-        "air concentration of caesium 137"
-    ],
-    [
-        "260140",
-        "aciod",
-        "air concentration of iodine 131"
-    ],
-    [
-        "260141",
-        "acradp",
-        "air concentration of radioactive pollutant"
-    ],
-    [
-        "260142",
-        "gdces",
-        "ground deposition of caesium 137"
-    ],
-    [
-        "260143",
-        "gdiod",
-        "ground deposition of iodine 131"
-    ],
-    [
-        "260144",
-        "gdradp",
-        "ground deposition of radioactive pollutant"
-    ],
-    [
-        "260145",
-        "tiaccp",
-        "time-integrated air concentration of caesium pollutant"
-    ],
-    [
-        "260146",
-        "tiacip",
-        "time-integrated air concentration of iodine pollutant"
-    ],
-    [
-        "260147",
-        "tiacrp",
-        "time-integrated air concentration of radioactive pollutant"
-    ],
-    [
-        "260148",
-        "volash",
-        "volcanic ash"
-    ],
-    [
-        "260149",
-        "icit",
-        "icing top"
-    ],
-    [
-        "260150",
-        "icib",
-        "icing base"
-    ],
-    [
-        "260151",
-        "ici",
-        "icing"
-    ],
-    [
-        "260152",
-        "turbt",
-        "turbulence top"
-    ],
-    [
-        "260153",
-        "turbb",
-        "turbulence base"
-    ],
-    [
-        "260154",
-        "turb",
-        "turbulence"
-    ],
-    [
-        "260155",
-        "tke",
-        "turbulent kinetic energy"
-    ],
-    [
-        "260156",
-        "pblreg",
-        "planetary boundary layer regime"
-    ],
-    [
-        "260157",
-        "conti",
-        "contrail intensity"
-    ],
-    [
-        "260158",
-        "contet",
-        "contrail engine type"
-    ],
-    [
-        "260159",
-        "contt",
-        "contrail top"
-    ],
-    [
-        "260160",
-        "contb",
-        "contrail base"
-    ],
-    [
-        "260161",
-        "mxsalb",
-        "maximum snow albedo"
-    ],
-    [
-        "260162",
-        "snfalb",
-        "snow free albedo"
-    ],
-    [
-        "260163",
-        "icing"
-    ],
-    [
-        "260164",
-        "in-cloud turbulence"
-    ],
-    [
-        "260165",
-        "cat",
-        "clear air turbulence (cat)"
-    ],
-    [
-        "260166",
-        "supercooled large droplet probability (see note 4)"
-    ],
-    [
-        "260167",
-        "var190m0",
-        "arbitrary text string"
-    ],
-    [
-        "260168",
-        "tsec",
-        "seconds prior to initial reference time (defined in section 1)"
-    ],
-    [
-        "260169",
-        "ffldg",
-        "flash flood guidance (encoded as an accumulation over a floating subinterval of time between the ref"
-    ],
-    [
-        "260170",
-        "ffldro",
-        "flash flood runoff (encoded as an accumulation over a floating subinterval of time)"
-    ],
-    [
-        "260171",
-        "rssc",
-        "remotely sensed snow cover"
-    ],
-    [
-        "260172",
-        "esct",
-        "elevation of snow covered terrain"
-    ],
-    [
-        "260173",
-        "swepon",
-        "snow water equivalent percent of normal"
-    ],
-    [
-        "260174",
-        "bgrun",
-        "baseflow-groundwater runoff"
-    ],
-    [
-        "260175",
-        "ssrun",
-        "storm surface runoff"
-    ],
-    [
-        "260176",
-        "cppop",
-        "conditional percent precipitation amount fractile for an overall period (encoded as an accumulation)"
-    ],
-    [
-        "260177",
-        "pposp",
-        "percent precipitation in a sub-period of an overall period (encoded as per cent accumulation over th"
-    ],
-    [
-        "260178",
-        "pop",
-        "probability of 0.01 inch of precipitation (pop)"
-    ],
-    [
-        "260179",
-        "land",
-        "land cover (1=land, 0=sea)"
-    ],
-    [
-        "260180",
-        "veg",
-        "vegetation"
-    ],
-    [
-        "260181",
-        "watr",
-        "water runoff"
-    ],
-    [
-        "260182",
-        "evapt",
-        "evapotranspiration"
-    ],
-    [
-        "260183",
-        "mterh",
-        "model terrain height"
-    ],
-    [
-        "260184",
-        "landu",
-        "land use"
-    ],
-    [
-        "260185",
-        "soilw",
-        "volumetric soil moisture content"
-    ],
-    [
-        "260186",
-        "gflux",
-        "ground heat flux"
-    ],
-    [
-        "260187",
-        "mstav",
-        "moisture availability"
-    ],
-    [
-        "260188",
-        "sfexc",
-        "exchange coefficient"
-    ],
-    [
-        "260189",
-        "cnwat",
-        "plant canopy surface water"
-    ],
-    [
-        "260190",
-        "bmixl",
-        "blackadar mixing length scale"
-    ],
-    [
-        "260191",
-        "ccond",
-        "canopy conductance"
-    ],
-    [
-        "260192",
-        "rsmin",
-        "minimal stomatal resistance"
-    ],
-    [
-        "260193",
-        "rcs",
-        "solar parameter in canopy conductance"
-    ],
-    [
-        "260194",
-        "rct",
-        "temperature parameter in canopy conductance"
-    ],
-    [
-        "260195",
-        "rcsol",
-        "soil moisture parameter in canopy conductance"
-    ],
-    [
-        "260196",
-        "rcq",
-        "humidity parameter in canopy conductance"
-    ],
-    [
-        "260197",
-        "cisoilw",
-        "column-integrated soil water"
-    ],
-    [
-        "260198",
-        "hflux",
-        "heat flux"
-    ],
-    [
-        "260199",
-        "vsw",
-        "volumetric soil moisture"
-    ],
-    [
-        "260200",
-        "vwiltm",
-        "volumetric wilting point"
-    ],
-    [
-        "260201",
-        "uplst",
-        "upper layer soil temperature"
-    ],
-    [
-        "260202",
-        "uplsm",
-        "upper layer soil moisture"
-    ],
-    [
-        "260203",
-        "lowlsm",
-        "lower layer soil moisture"
-    ],
-    [
-        "260204",
-        "botlst",
-        "bottom layer soil temperature"
-    ],
-    [
-        "260205",
-        "soill",
-        "liquid volumetric soil moisture (non-frozen)"
-    ],
-    [
-        "260206",
-        "rlyrs",
-        "number of soil layers in root zone"
-    ],
-    [
-        "260207",
-        "smref",
-        "transpiration stress-onset (soil moisture)"
-    ],
-    [
-        "260208",
-        "smdry",
-        "direct evaporation cease (soil moisture)"
-    ],
-    [
-        "260209",
-        "poros",
-        "soil porosity"
-    ],
-    [
-        "260210",
-        "liqvsm",
-        "liquid volumetric soil moisture (non-frozen)"
-    ],
-    [
-        "260211",
-        "voltso",
-        "volumetric transpiration stress-onset (soil moisture)"
-    ],
-    [
-        "260212",
-        "transo",
-        "transpiration stress-onset (soil moisture)"
-    ],
-    [
-        "260213",
-        "voldec",
-        "volumetric direct evaporation cease (soil moisture)"
-    ],
-    [
-        "260214",
-        "direc",
-        "direct evaporation cease (soil moisture)"
-    ],
-    [
-        "260215",
-        "soilp",
-        "soil porosity"
-    ],
-    [
-        "260216",
-        "vsosm",
-        "volumetric saturation of soil moisture"
-    ],
-    [
-        "260217",
-        "satosm",
-        "saturation of soil moisture"
-    ],
-    [
-        "260218",
-        "estp",
-        "estimated precipitation"
-    ],
-    [
-        "260219",
-        "irrate",
-        "instantaneous rain rate"
-    ],
-    [
-        "260220",
-        "ctoph",
-        "cloud top height"
-    ],
-    [
-        "260221",
-        "ctophqi",
-        "cloud top height quality indicator"
-    ],
-    [
-        "260222",
-        "estu",
-        "estimated u component of wind "
-    ],
-    [
-        "260223",
-        "estv",
-        "estimated v component of wind"
-    ],
-    [
-        "260224",
-        "npixu",
-        "number of pixels used"
-    ],
-    [
-        "260225",
-        "solza",
-        "solar zenith angle"
-    ],
-    [
-        "260226",
-        "raza",
-        "relative azimuth angle"
-    ],
-    [
-        "260227",
-        "rfl06",
-        "reflectance in 0.6 micron channel"
-    ],
-    [
-        "260228",
-        "rfl08",
-        "reflectance in 0.8 micron channel"
-    ],
-    [
-        "260229",
-        "rfl16",
-        "reflectance in 1.6 micron channel"
-    ],
-    [
-        "260230",
-        "rfl39",
-        "reflectance in 3.9 micron channel"
-    ],
-    [
-        "260231",
-        "atmdiv",
-        "atmospheric divergence"
-    ],
-    [
-        "260232",
-        "wvdir",
-        "direction of wind waves"
-    ],
-    [
-        "260233",
-        "dirpw",
-        "primary wave direction"
-    ],
-    [
-        "260234",
-        "perpw",
-        "primary wave mean period"
-    ],
-    [
-        "260235",
-        "persw",
-        "secondary wave mean period"
-    ],
-    [
-        "260236",
-        "dirc",
-        "current direction"
-    ],
-    [
-        "260237",
-        "spc",
-        "current speed"
-    ],
-    [
-        "260239",
-        "ist",
-        "ice temperature"
-    ],
-    [
-        "260240",
-        "dslm",
-        "deviation of sea level from mean"
-    ],
-    [
-        "260241",
-        "tsec",
-        "seconds prior to initial reference time (defined in section 1)"
-    ],
-    [
-        "260243",
-        "ttrad",
-        "temperature tendency by all radiation"
-    ],
-    [
-        "260244",
-        "rev",
-        "relative error variance"
-    ],
-    [
-        "260245",
-        "lrghr",
-        "large scale condensate heating rate"
-    ],
-    [
-        "260246",
-        "cnvhr",
-        "deep convective heating rate"
-    ],
-    [
-        "260247",
-        "thflx",
-        "total downward heat flux at surface"
-    ],
-    [
-        "260248",
-        "ttdia",
-        "temperature tendency by all physics"
-    ],
-    [
-        "260249",
-        "ttphy",
-        "temperature tendency by non-radiation physics"
-    ],
-    [
-        "260250",
-        "tsd1d",
-        "standard dev. of ir temp. over 1x1 deg. area"
-    ],
-    [
-        "260251",
-        "shahr",
-        "shallow convective heating rate"
-    ],
-    [
-        "260252",
-        "vdfhr",
-        "vertical diffusion heating rate"
-    ],
-    [
-        "260253",
-        "thz0",
-        "potential temperature at top of viscous sublayer"
-    ],
-    [
-        "260254",
-        "tchp",
-        "tropical cyclone heat potential"
-    ],
-    [
-        "260261",
-        "minrh",
-        "minimum relative humidity"
-    ],
-    [
-        "260269",
-        "tipd",
-        "total icing potential diagnostic"
-    ],
-    [
-        "260270",
-        "ncip",
-        "number concentration for ice particles"
-    ],
-    [
-        "260271",
-        "snot",
-        "snow temperature"
-    ],
-    [
-        "260272",
-        "tclsw",
-        "total column-integrated supercooled liquid water"
-    ],
-    [
-        "260273",
-        "tcolm",
-        "total column-integrated melting ice"
-    ],
-    [
-        "260274",
-        "emnp",
-        "evaporation - precipitation"
-    ],
-    [
-        "260275",
-        "sbsno",
-        "sublimation (evaporation from snow)"
-    ],
-    [
-        "260276",
-        "cnvmr",
-        "deep convective moistening rate"
-    ],
-    [
-        "260277",
-        "shamr",
-        "shallow convective moistening rate"
-    ],
-    [
-        "260278",
-        "vdfmr",
-        "vertical diffusion moistening rate"
-    ],
-    [
-        "260279",
-        "condp",
-        "condensation pressure of parcali lifted from indicate surface"
-    ],
-    [
-        "260280",
-        "lrgmr",
-        "large scale moistening rate"
-    ],
-    [
-        "260281",
-        "qz0",
-        "specific humidity at top of viscous sublayer"
-    ],
-    [
-        "260282",
-        "qmax",
-        "maximum specific humidity at 2m"
-    ],
-    [
-        "260283",
-        "qmin",
-        "minimum specific humidity at 2m"
-    ],
-    [
-        "260284",
-        "arain",
-        "liquid precipitation (rainfall)"
-    ],
-    [
-        "260285",
-        "snowt",
-        "snow temperature, depth-avg"
-    ],
-    [
-        "260286",
-        "apcpn",
-        "total precipitation (nearest grid point)"
-    ],
-    [
-        "260287",
-        "acpcpn",
-        "convective precipitation (nearest grid point)"
-    ],
-    [
-        "260288",
-        "frzr",
-        "freezing rain"
-    ],
-    [
-        "260295",
-        "lauv",
-        "latitude of u wind component of velocity"
-    ],
-    [
-        "260296",
-        "louv",
-        "longitude of u wind component of velocity"
-    ],
-    [
-        "260297",
-        "lavv",
-        "latitude of v wind component of velocity"
-    ],
-    [
-        "260298",
-        "lovv",
-        "longitude of v wind component of velocity"
-    ],
-    [
-        "260299",
-        "lapp",
-        "latitude of presure point"
-    ],
-    [
-        "260300",
-        "lopp",
-        "longitude of presure point"
-    ],
-    [
-        "260301",
-        "vedh",
-        "vertical eddy diffusivity heat exchange"
-    ],
-    [
-        "260302",
-        "covmz",
-        "covariance between meridional and zonal components of the wind."
-    ],
-    [
-        "260303",
-        "covtz",
-        "covariance between temperature and zonal components of the wind."
-    ],
-    [
-        "260304",
-        "covtm",
-        "covariance between temperature and meridional components of the wind."
-    ],
-    [
-        "260305",
-        "vdfua",
-        "vertical diffusion zonal acceleration"
-    ],
-    [
-        "260306",
-        "vdfva",
-        "vertical diffusion meridional acceleration"
-    ],
-    [
-        "260307",
-        "gwdu",
-        "gravity wave drag zonal acceleration"
-    ],
-    [
-        "260308",
-        "gwdv",
-        "gravity wave drag meridional acceleration"
-    ],
-    [
-        "260309",
-        "cnvu",
-        "convective zonal momentum mixing acceleration"
-    ],
-    [
-        "260310",
-        "cnvv",
-        "convective meridional momentum mixing acceleration"
-    ],
-    [
-        "260311",
-        "wtend",
-        "tendency of vertical velocity"
-    ],
-    [
-        "260312",
-        "omgalf",
-        "omega (dp/dt) divide by density"
-    ],
-    [
-        "260313",
-        "cngwdu",
-        "convective gravity wave drag zonal acceleration"
-    ],
-    [
-        "260314",
-        "cngwdv",
-        "convective gravity wave drag meridional acceleration"
-    ],
-    [
-        "260315",
-        "lmv",
-        "velocity point model surface"
-    ],
-    [
-        "260316",
-        "pvmww",
-        "potential vorticity (mass-weighted)"
-    ],
-    [
-        "260317",
-        "mslet",
-        "mslp (eta model reduction)"
-    ],
-    [
-        "260323",
-        "mslma",
-        "mslp (maps system reduction)"
-    ],
-    [
-        "260324",
-        "tslsa",
-        "3-hr pressure tendency (std. atmos. reduction)"
-    ],
-    [
-        "260325",
-        "plpl",
-        "pressure of level from which parcel was lifted"
-    ],
-    [
-        "260326",
-        "lpsx",
-        "x-gradient of log pressure"
-    ],
-    [
-        "260327",
-        "lpsy",
-        "y-gradient of log pressure"
-    ],
-    [
-        "260328",
-        "hgtx",
-        "x-gradient of height"
-    ],
-    [
-        "260329",
-        "hgty",
-        "y-gradient of height"
-    ],
-    [
-        "260330",
-        "layth",
-        "layer thickness"
-    ],
-    [
-        "260331",
-        "nlgsp",
-        "natural log of surface pressure"
-    ],
-    [
-        "260332",
-        "cnvumf",
-        "convective updraft mass flux"
-    ],
-    [
-        "260333",
-        "cnvdmf",
-        "convective downdraft mass flux"
-    ],
-    [
-        "260334",
-        "cnvdemf",
-        "convective detrainment mass flux"
-    ],
-    [
-        "260335",
-        "lmh",
-        "mass point model surface"
-    ],
-    [
-        "260336",
-        "hgtn",
-        "geopotential height (nearest grid point)"
-    ],
-    [
-        "260337",
-        "presn",
-        "pressure (nearest grid point)"
-    ],
-    [
-        "260340",
-        "duvb",
-        "uv-b downward solar flux"
-    ],
-    [
-        "260341",
-        "cduvb",
-        "clear sky uv-b downward solar flux"
-    ],
-    [
-        "260342",
-        "csdsf",
-        "clear sky downward solar flux"
-    ],
-    [
-        "260343",
-        "swhr",
-        "solar radiative heating rate"
-    ],
-    [
-        "260344",
-        "csusf",
-        "clear sky upward solar flux"
-    ],
-    [
-        "260345",
-        "cfnsf",
-        "cloud forcing net solar flux"
-    ],
-    [
-        "260346",
-        "vbdsf",
-        "visible beam downward solar flux"
-    ],
-    [
-        "260347",
-        "vddsf",
-        "visible diffuse downward solar flux"
-    ],
-    [
-        "260348",
-        "nbdsf",
-        "near ir beam downward solar flux"
-    ],
-    [
-        "260349",
-        "nddsf",
-        "near ir diffuse downward solar flux"
-    ],
-    [
-        "260350",
-        "dtrf",
-        "downward total radiation flux"
-    ],
-    [
-        "260351",
-        "utrf",
-        "upward total radiation flux"
-    ],
-    [
-        "260354",
-        "lwhr",
-        "long-wave radiative heating rate"
-    ],
-    [
-        "260355",
-        "csulf",
-        "clear sky upward long wave flux"
-    ],
-    [
-        "260356",
-        "csdlf",
-        "clear sky downward long wave flux"
-    ],
-    [
-        "260357",
-        "cfnlf",
-        "cloud forcing net long wave flux"
-    ],
-    [
-        "260366",
-        "mflux",
-        "convective cloud mass flux"
-    ],
-    [
-        "260369",
-        "ri",
-        "richardson number"
-    ],
-    [
-        "260370",
-        "cwdi",
-        "convective weather detection index"
-    ],
-    [
-        "260372",
-        "uphl",
-        "updraft helicity"
-    ],
-    [
-        "260373",
-        "lai",
-        "leaf area index"
-    ],
-    [
-        "260374",
-        "pmtc",
-        "particulate matter (coarse)"
-    ],
-    [
-        "260375",
-        "pmtf",
-        "particulate matter (fine)"
-    ],
-    [
-        "260376",
-        "lpmtf",
-        "particulate matter (fine)"
-    ],
-    [
-        "260377",
-        "lipmf",
-        "integrated column particulate matter (fine)"
-    ],
-    [
-        "260379",
-        "ozcon",
-        "ozone concentration (ppb)"
-    ],
-    [
-        "260380",
-        "ozcat",
-        "categorical ozone concentration"
-    ],
-    [
-        "260381",
-        "vdfoz",
-        "ozone vertical diffusion"
-    ],
-    [
-        "260382",
-        "poz",
-        "ozone production"
-    ],
-    [
-        "260383",
-        "toz",
-        "ozone tendency"
-    ],
-    [
-        "260384",
-        "pozt",
-        "ozone production from temperature term"
-    ],
-    [
-        "260385",
-        "pozo",
-        "ozone production from col ozone term"
-    ],
-    [
-        "260386",
-        "refzr",
-        "derived radar reflectivity backscatter from rain"
-    ],
-    [
-        "260387",
-        "refzi",
-        "derived radar reflectivity backscatter from ice"
-    ],
-    [
-        "260388",
-        "refzc",
-        "derived radar reflectivity backscatter from parameterized convection"
-    ],
-    [
-        "260389",
-        "refd",
-        "derived radar reflectivity"
-    ],
-    [
-        "260390",
-        "refc",
-        "maximum/composite radar reflectivity"
-    ],
-    [
-        "260391",
-        "ltng",
-        "lightning"
-    ],
-    [
-        "260394",
-        "srcono",
-        "slight risk convective outlook"
-    ],
-    [
-        "260395",
-        "mrcono",
-        "moderate risk convective outlook"
-    ],
-    [
-        "260396",
-        "hrcono",
-        "high risk convective outlook"
-    ],
-    [
-        "260397",
-        "torprob",
-        "tornado probability"
-    ],
-    [
-        "260398",
-        "hailprob",
-        "hail probability"
-    ],
-    [
-        "260399",
-        "windprob",
-        "wind probability"
-    ],
-    [
-        "260400",
-        "storprob",
-        "significant tornado probability"
-    ],
-    [
-        "260401",
-        "shailpro",
-        "significant hail probability"
-    ],
-    [
-        "260402",
-        "swindpro",
-        "significant wind probability"
-    ],
-    [
-        "260403",
-        "tstmc",
-        "categorical thunderstorm (1-yes, 0-no)"
-    ],
-    [
-        "260404",
-        "mixly",
-        "number of mixed layers next to surface"
-    ],
-    [
-        "260405",
-        "flght",
-        "flight category"
-    ],
-    [
-        "260406",
-        "cicel",
-        "confidence - ceiling"
-    ],
-    [
-        "260407",
-        "civis",
-        "confidence - visibility"
-    ],
-    [
-        "260408",
-        "ciflt",
-        "confidence - flight category"
-    ],
-    [
-        "260409",
-        "lavni",
-        "low-level aviation interest"
-    ],
-    [
-        "260410",
-        "havni",
-        "high-level aviation interest"
-    ],
-    [
-        "260411",
-        "sbsalb",
-        "visible, black sky albedo"
-    ],
-    [
-        "260412",
-        "swsalb",
-        "visible, white sky albedo"
-    ],
-    [
-        "260413",
-        "nbsalb",
-        "near ir, black sky albedo"
-    ],
-    [
-        "260414",
-        "nwsalb",
-        "near ir, white sky albedo"
-    ],
-    [
-        "260415",
-        "prsvr",
-        "total probability of severe thunderstorms (days 2,3)"
-    ],
-    [
-        "260416",
-        "prsigsvr",
-        "total probability of extreme severe thunderstorms (days 2,3)"
-    ],
-    [
-        "260417",
-        "sipd",
-        "supercooled large droplet (sld) potential"
-    ],
-    [
-        "260418",
-        "epsr",
-        "radiative emissivity"
-    ],
-    [
-        "260419",
-        "tpfi",
-        "turbulence potential forecast index"
-    ],
-    [
-        "260420",
-        "vaftd",
-        "volcanic ash forecast transport and dispersion"
-    ],
-    [
-        "260421",
-        "nlat",
-        "latitude (-90 to +90)"
-    ],
-    [
-        "260422",
-        "elon",
-        "east longitude (0 - 360)"
-    ],
-    [
-        "260424",
-        "mlyno",
-        "model layer number (from bottom up)"
-    ],
-    [
-        "260425",
-        "nlatn",
-        "latitude (nearest neighbor) (-90 to +90)"
-    ],
-    [
-        "260426",
-        "elonn",
-        "east longitude (nearest neighbor) (0 - 360)"
-    ],
-    [
-        "260429",
-        "cpozp",
-        "probability of freezing precipitation"
-    ],
-    [
-        "260431",
-        "ppffg",
-        "probability of precipitation exceeding flash flood guidance values"
-    ],
-    [
-        "260432",
-        "cwr",
-        "probability of wetting rain, exceeding in 0.10 in a given time period"
-    ],
-    [
-        "260439",
-        "vgtyp",
-        "vegetation type"
-    ],
-    [
-        "260442",
-        "wilt",
-        "wilting point"
-    ],
-    [
-        "260447",
-        "rdrip",
-        "rate of water dropping from canopy to ground"
-    ],
-    [
-        "260448",
-        "icwat",
-        "ice-free water surface"
-    ],
-    [
-        "260449",
-        "akhs",
-        "surface exchange coefficients for t and q divided by delta z"
-    ],
-    [
-        "260450",
-        "akms",
-        "surface exchange coefficients for u and v divided by delta z"
-    ],
-    [
-        "260451",
-        "vegt",
-        "vegetation canopy temperature"
-    ],
-    [
-        "260452",
-        "sstor",
-        "surface water storage"
-    ],
-    [
-        "260453",
-        "lsoil",
-        "liquid soil moisture content (non-frozen)"
-    ],
-    [
-        "260454",
-        "ewatr",
-        "open water evaporation (standing water)"
-    ],
-    [
-        "260455",
-        "gwrec",
-        "groundwater recharge"
-    ],
-    [
-        "260456",
-        "qrec",
-        "flood plain recharge"
-    ],
-    [
-        "260457",
-        "sfcrh",
-        "roughness length for heat"
-    ],
-    [
-        "260458",
-        "ndvi",
-        "normalized difference vegetation index"
-    ],
-    [
-        "260459",
-        "landn",
-        "land-sea coverage (nearest neighbor) [land=1,sea=0]"
-    ],
-    [
-        "260460",
-        "amixl",
-        "asymptotic mixing length scale"
-    ],
-    [
-        "260461",
-        "wvinc",
-        "water vapor added by precip assimilation"
-    ],
-    [
-        "260462",
-        "wcinc",
-        "water condensate added by precip assimilation"
-    ],
-    [
-        "260463",
-        "wvconv",
-        "water vapor flux convergance (vertical int)"
-    ],
-    [
-        "260464",
-        "wcconv",
-        "water condensate flux convergance (vertical int)"
-    ],
-    [
-        "260465",
-        "wvuflx",
-        "water vapor zonal flux (vertical int)"
-    ],
-    [
-        "260466",
-        "wvvflx",
-        "water vapor meridional flux (vertical int)"
-    ],
-    [
-        "260467",
-        "wcuflx",
-        "water condensate zonal flux (vertical int)"
-    ],
-    [
-        "260468",
-        "wcvflx",
-        "water condensate meridional flux (vertical int)"
-    ],
-    [
-        "260469",
-        "acond",
-        "aerodynamic conductance"
-    ],
-    [
-        "260470",
-        "evcw",
-        "canopy water evaporation"
-    ],
-    [
-        "260471",
-        "trans",
-        "transpiration"
-    ],
-    [
-        "260474",
-        "sltyp",
-        "surface slope type"
-    ],
-    [
-        "260478",
-        "evbs",
-        "direct evaporation from bare soil"
-    ],
-    [
-        "260479",
-        "lspa",
-        "land surface precipitation accumulation"
-    ],
-    [
-        "260480",
-        "baret",
-        "bare soil surface skin temperature"
-    ],
-    [
-        "260481",
-        "avsft",
-        "average surface skin temperature"
-    ],
-    [
-        "260482",
-        "radt",
-        "effective radiative skin temperature"
-    ],
-    [
-        "260483",
-        "fldcp",
-        "field capacity"
-    ],
-    [
-        "260484",
-        "usct",
-        "scatterometer estimated u wind component"
-    ],
-    [
-        "260485",
-        "vsct",
-        "scatterometer estimated v wind component"
-    ],
-    [
-        "260486",
-        "wstp",
-        "wave steepness"
-    ],
-    [
-        "260487",
-        "omlu",
-        "ocean mixed layer u velocity"
-    ],
-    [
-        "260488",
-        "omlv",
-        "ocean mixed layer v velocity"
-    ],
-    [
-        "260489",
-        "ubaro",
-        "barotropic u velocity"
-    ],
-    [
-        "260490",
-        "vbaro",
-        "barotropic v velocity"
-    ],
-    [
-        "260491",
-        "surge",
-        "storm surge"
-    ],
-    [
-        "260492",
-        "etsrg",
-        "extra tropical storm surge"
-    ],
-    [
-        "260493",
-        "elevhtml",
-        "ocean surface elevation relative to geoid"
-    ],
-    [
-        "260494",
-        "sshg",
-        "sea surface height relative to geoid"
-    ],
-    [
-        "260495",
-        "p2omlt",
-        "ocean mixed layer potential density (reference 2000m)<br"
-    ],
-    [
-        "260496",
-        "aohflx",
-        "net air-ocean heat flux"
-    ],
-    [
-        "260497",
-        "ashfl",
-        "assimilative heat flux"
-    ],
-    [
-        "260498",
-        "sstt",
-        "surface temperature trend"
-    ],
-    [
-        "260499",
-        "ssst",
-        "surface salinity trend"
-    ],
-    [
-        "260500",
-        "keng",
-        "kinetic energy"
-    ],
-    [
-        "260501",
-        "sltfl",
-        "salt flux"
-    ],
-    [
-        "260502",
-        "wtmpc",
-        "3-d temperature"
-    ],
-    [
-        "260503",
-        "salin",
-        "3-d salinity"
-    ],
-    [
-        "260504",
-        "bkeng",
-        "barotropic kinectic energy"
-    ],
-    [
-        "260505",
-        "dbss",
-        "geometric depth below sea surface"
-    ],
-    [
-        "260506",
-        "intfd",
-        "interface depths"
-    ],
-    [
-        "260507",
-        "ohc",
-        "ocean heat content"
-    ],
-    [
-        "260508",
-        "imgd",
-        "image data"
-    ],
-    [
-        "260509",
-        "al",
-        "albedo"
-    ],
-    [
-        "132216",
-        "maxswhi",
-        "maximum of significant wave height index",
-        "216.132"
-    ],
-    [
-        "500008",
-        "hhl",
-        "geometric height of the layer limits above sea level(nn)"
-    ],
-    [
-        "140216",
-        "vst",
-        "v-component stokes drift"
-    ],
-    [
-        "210101",
-        "maxfrpfire",
-        "wildfire radiative power maximum"
-    ],
-    [
-        "210102",
-        "so2fire",
-        "wildfire flux of sulfur dioxide"
-    ],
-    [
-        "228134",
-        "vtnowd",
-        "v-tendency from non-orographic wave drag"
-    ],
-    [
-        "228136",
-        "utnowd",
-        "u-tendency from non-orographic wave drag"
-    ],
-    [
-        "228246",
-        "100u",
-        "100 metre u wind component"
-    ],
-    [
-        "228247",
-        "100v",
-        "100 metre v wind component"
-    ],
-    [
-        "228253",
-        "ascat_sm_cdfa",
-        "ascat first soil moisture cdf matching parameter"
-    ],
-    [
-        "228254",
-        "ascat_sm_cdfb",
-        "ascat second soil moisture cdf matching parameter"
-    ],
-    [
-        "140215",
-        "ust",
-        "u-component stokes drift"
-    ],
-    [
-        "500050",
-        "clch",
-        "cloud cover (0 - 400 hpa)"
-    ],
-    [
-        "500049",
-        "clcm",
-        "cloud cover (400 - 800 hpa)"
-    ],
-    [
-        "500048",
-        "clcl",
-        "cloud cover (800 hpa - soil)"
-    ],
-    [
-        "500047",
-        "clc_con",
-        "convective cloud cover"
-    ],
-    [
-        "500046",
-        "clct",
-        "total cloud cover"
-    ],
-    [
-        "500045",
-        "h_snow",
-        "snow depth"
-    ],
-    [
-        "500044",
-        "w_snow",
-        "snow depth water equivalent"
-    ],
-    [
-        "500043",
-        "prec_con",
-        "convective precipitation rate"
-    ],
-    [
-        "500042",
-        "prec_gsp",
-        "large-scale precipitation rate"
-    ],
-    [
-        "500041",
-        "tot_prec",
-        "total precipitation rate (s)"
-    ],
-    [
-        "500040",
-        "tqi",
-        "total column-integrated cloud ice"
-    ],
-    [
-        "500039",
-        "aevap_s",
-        "evaporation (s)"
-    ],
-    [
-        "500038",
-        "tqv",
-        "total column integrated water vapour"
-    ],
-    [
-        "500037",
-        "relhum",
-        "relative humidity"
-    ],
-    [
-        "500036",
-        "relhum_2m",
-        "2m relative humidity"
-    ],
-    [
-        "500035",
-        "qv",
-        "specific humidity"
-    ],
-    [
-        "500034",
-        "qv_2m",
-        "specific humidity (2m)"
-    ],
-    [
-        "500033",
-        "qv_s",
-        "specific humidity (s)"
-    ],
-    [
-        "500032",
-        "w",
-        "vertical velocity (geometric) (w)"
-    ],
-    [
-        "500031",
-        "omega",
-        "vertical velocity (pressure) ( omega=dp/dt )"
-    ],
-    [
-        "500030",
-        "v",
-        "v component of wind"
-    ],
-    [
-        "500029",
-        "v_10m",
-        "v component of wind"
-    ],
-    [
-        "500028",
-        "u",
-        "u component of wind"
-    ],
-    [
-        "500027",
-        "u_10m",
-        "u component of wind"
-    ],
-    [
-        "500026",
-        "sp",
-        "wind speed (sp)"
-    ],
-    [
-        "500025",
-        "sp_10m",
-        "wind speed (sp_10m)"
-    ],
-    [
-        "500024",
-        "dd",
-        "wind direction (dd)"
-    ],
-    [
-        "500023",
-        "dd_10m",
-        "wind direction (dd_10m)"
-    ],
-    [
-        "500022",
-        "wvsp3",
-        "wave spectra (3)"
-    ],
-    [
-        "500021",
-        "wvsp2",
-        "wave spectra (2)"
-    ],
-    [
-        "500020",
-        "wvsp1",
-        "wave spectra (1)"
-    ],
-    [
-        "500019",
-        "dbz_max",
-        "radar spectra (1)"
-    ],
-    [
-        "500018",
-        "td_2m_av",
-        "2m dew point temperature (av)"
-    ],
-    [
-        "500017",
-        "td_2m",
-        "2m dew point temperature"
-    ],
-    [
-        "500016",
-        "tmin_2m",
-        "min 2m temperature (i)"
-    ],
-    [
-        "500015",
-        "tmax_2m",
-        "max 2m temperature (i)"
-    ],
-    [
-        "500013",
-        "t_2m_cl",
-        "climat. temperature, 2m temperature"
-    ],
-    [
-        "500012",
-        "t_2m_av",
-        "2m temperature (av)"
-    ],
-    [
-        "500011",
-        "t_2m",
-        "2m temperature"
-    ],
-    [
-        "500010",
-        "t_g",
-        "temperature (g)"
-    ],
-    [
-        "500009",
-        "to3",
-        "total column integrated ozone"
-    ],
-    [
-        "500000",
-        "ps",
-        "pressure (s) (not reduced)"
-    ],
-    [
-        "500001",
-        "p",
-        "pressure"
-    ],
-    [
-        "500002",
-        "pmsl",
-        "pressure reduced to msl"
-    ],
-    [
-        "500003",
-        "dpsdt",
-        "pressure tendency (s)"
-    ],
-    [
-        "500004",
-        "fis",
-        "geopotential (s)"
-    ],
-    [
-        "500005",
-        "fif",
-        "geopotential (full lev)"
-    ],
-    [
-        "500006",
-        "fi",
-        "geopotential"
-    ],
-    [
-        "500007",
-        "hsurf",
-        "geometric height of the earths surface above sea level"
-    ],
-    [
-        "500051",
-        "tqc",
-        "total column-integrated cloud water"
-    ],
-    [
-        "500052",
-        "snow_con",
-        "convective snowfall rate water equivalent (s)"
-    ],
-    [
-        "500053",
-        "snow_gsp",
-        "large-scale snowfall rate water equivalent (s)"
-    ],
-    [
-        "500054",
-        "fr_land",
-        "land cover (1=land, 0=sea)"
-    ],
-    [
-        "500055",
-        "z0",
-        "surface roughness length surface roughness"
-    ],
-    [
-        "500057",
-        "albedo_b",
-        "albedo (in short-wave)"
-    ],
-    [
-        "500056",
-        "alb_rad",
-        "albedo (in short-wave)"
-    ],
-    [
-        "500058",
-        "t_cl",
-        "soil temperature  ( 36 cm depth, vv=0h)"
-    ],
-    [
-        "500060",
-        "t_m",
-        "soil temperature"
-    ],
-    [
-        "500061",
-        "t_s",
-        "soil temperature"
-    ],
-    [
-        "500059",
-        "t_cl_lm",
-        "soil temperature (41 cm depth)"
-    ],
-    [
-        "500062",
-        "w_cl",
-        "column-integrated soil moisture"
-    ],
-    [
-        "500063",
-        "w_g1",
-        "column-integrated soil moisture (1) 0 -10 cm"
-    ],
-    [
-        "500064",
-        "w_g2",
-        "column-integrated soil moisture (2) 10-100cm"
-    ],
-    [
-        "500065",
-        "plcov",
-        "plant cover"
-    ],
-    [
-        "500066",
-        "runoff_g",
-        "water runoff (10-100)"
-    ],
-    [
-        "500068",
-        "runoff_s",
-        "water runoff (s)"
-    ],
-    [
-        "500067",
-        "runoff_g_lm",
-        "water runoff (10-190)"
-    ],
-    [
-        "500069",
-        "fr_ice",
-        "sea ice cover ( 0= free, 1=cover)"
-    ],
-    [
-        "500070",
-        "h_ice",
-        "sea ice thickness"
-    ],
-    [
-        "500071",
-        "swh",
-        "significant height of combined wind waves and swell"
-    ],
-    [
-        "500072",
-        "mdww",
-        "direction of wind waves"
-    ],
-    [
-        "500073",
-        "shww",
-        "significant height of wind waves"
-    ],
-    [
-        "500074",
-        "mpww",
-        "mean period of wind waves"
-    ],
-    [
-        "500075",
-        "mdps",
-        "direction of swell waves"
-    ],
-    [
-        "500076",
-        "shps",
-        "significant height of swell waves"
-    ],
-    [
-        "500077",
-        "mpps",
-        "mean period of swell waves"
-    ],
-    [
-        "500078",
-        "asob_s",
-        "net short wave radiation flux (m) (at the surface)"
-    ],
-    [
-        "500079",
-        "sobs_rad",
-        "net short wave radiation flux"
-    ],
-    [
-        "500080",
-        "athb_s",
-        "net long wave radiation flux (m) (at the surface)"
-    ],
-    [
-        "500081",
-        "thbs_rad",
-        "net long wave radiation flux"
-    ],
-    [
-        "500082",
-        "asob_t",
-        "net short wave radiation flux (m) (on the model top)"
-    ],
-    [
-        "500083",
-        "sobt_rad",
-        "net short wave radiation flux"
-    ],
-    [
-        "500084",
-        "athb_t",
-        "net long wave radiation flux (m) (on the model top)"
-    ],
-    [
-        "500085",
-        "thbt_rad",
-        "net long wave radiation flux"
-    ],
-    [
-        "500086",
-        "alhfl_s",
-        "latent heat net flux (m)"
-    ],
-    [
-        "500087",
-        "ashfl_s",
-        "sensible heat net flux (m)"
-    ],
-    [
-        "500088",
-        "aumfl_s",
-        "momentum flux, u-component (m)"
-    ],
-    [
-        "500089",
-        "avmfl_s",
-        "momentum flux, v-component (m)"
-    ],
-    [
-        "500090",
-        "apab_s",
-        "photosynthetically active radiation (m) (at the surface)"
-    ],
-    [
-        "500091",
-        "pabs_rad",
-        "photosynthetically active radiation"
-    ],
-    [
-        "500092",
-        "sohr_rad",
-        "solar radiation heating rate"
-    ],
-    [
-        "500093",
-        "thhr_rad",
-        "thermal radiation heating rate"
-    ],
-    [
-        "500094",
-        "alhfl_bs",
-        "latent heat flux from bare soil"
-    ],
-    [
-        "500095",
-        "alhfl_pl",
-        "latent heat flux from plants"
-    ],
-    [
-        "500096",
-        "dursun",
-        "sunshine"
-    ],
-    [
-        "500097",
-        "rstom",
-        "stomatal resistance"
-    ],
-    [
-        "500098",
-        "clc",
-        "cloud cover"
-    ],
-    [
-        "500099",
-        "clc_sgs",
-        "non-convective cloud cover, grid scale"
-    ],
-    [
-        "500100",
-        "qc",
-        "cloud mixing ratio"
-    ],
-    [
-        "500101",
-        "qi",
-        "cloud ice mixing ratio"
-    ],
-    [
-        "500102",
-        "qr",
-        "rain mixing ratio"
-    ],
-    [
-        "500103",
-        "qs",
-        "snow mixing ratio"
-    ],
-    [
-        "500104",
-        "tqr",
-        "total column integrated rain"
-    ],
-    [
-        "500105",
-        "tqs",
-        "total column integrated snow"
-    ],
-    [
-        "500106",
-        "qg",
-        "grauple"
-    ],
-    [
-        "500107",
-        "tqg",
-        "total column integrated grauple"
-    ],
-    [
-        "500108",
-        "twater",
-        "total column integrated water (all components incl. precipitation)"
-    ],
-    [
-        "500109",
-        "tdiv_hum",
-        "vertical integral of divergence of total water content (s)"
-    ],
-    [
-        "500110",
-        "qc_rad",
-        "subgrid scale cloud water"
-    ],
-    [
-        "500111",
-        "qi_rad",
-        "subgridscale cloud ice"
-    ],
-    [
-        "500112",
-        "clch_8",
-        "cloud cover ch (0..8)"
-    ],
-    [
-        "500113",
-        "clcm_8",
-        "cloud cover cm (0..8)"
-    ],
-    [
-        "500114",
-        "clcl_8",
-        "cloud cover cl (0..8)"
-    ],
-    [
-        "500115",
-        "hbas_sc",
-        "cloud base above msl, shallow convection"
-    ],
-    [
-        "500116",
-        "htop_sc",
-        "cloud top above msl, shallow convection"
-    ],
-    [
-        "500117",
-        "clw_con",
-        "specific cloud water content, convective cloud"
-    ],
-    [
-        "500118",
-        "hbas_con",
-        "height of convective cloud base (i)"
-    ],
-    [
-        "500119",
-        "htop_con",
-        "height of convective cloud top (i)"
-    ],
-    [
-        "500120",
-        "bas_con",
-        "base index (vertical level) of main convective cloud (i)"
-    ],
-    [
-        "500121",
-        "top_con",
-        "top index (vertical level) of main convective cloud (i)"
-    ],
-    [
-        "500122",
-        "dt_con",
-        "temperature tendency due to convection"
-    ],
-    [
-        "500123",
-        "dqv_con",
-        "specific humitiy tendency due to convection"
-    ],
-    [
-        "500124",
-        "du_con",
-        "zonal wind tendency due to convection"
-    ],
-    [
-        "500125",
-        "dv_con",
-        "meridional wind tendency due to convection"
-    ],
-    [
-        "500126",
-        "htop_dc",
-        "height of top of dry convection"
-    ],
-    [
-        "500127",
-        "hzerocl",
-        "height of 0 degree celsius level code 0,3,6 ?"
-    ],
-    [
-        "500128",
-        "snowlmt",
-        "height of snow fall limit"
-    ],
-    [
-        "500129",
-        "dqc_con",
-        "tendency of specific cloud liquid water content due to conversion"
-    ],
-    [
-        "500130",
-        "dqi_con",
-        "tendency of  specific cloud ice content due to convection"
-    ],
-    [
-        "500131",
-        "q_sedim",
-        "specific content of precipitation particles (needed for water loadin)g"
-    ],
-    [
-        "500132",
-        "prr_gsp",
-        "large scale rain rate"
-    ],
-    [
-        "500133",
-        "prs_gsp",
-        "large scale snowfall rate water equivalent"
-    ],
-    [
-        "500134",
-        "rain_gsp",
-        "large scale rain rate (s)"
-    ],
-    [
-        "500135",
-        "prr_con",
-        "convective rain rate"
-    ],
-    [
-        "500136",
-        "prs_con",
-        "convective snowfall rate water equivalent"
-    ],
-    [
-        "500137",
-        "rain_con",
-        "convective rain rate (s)"
-    ],
-    [
-        "500138",
-        "rr_f",
-        "rain amount, grid-scale plus convective"
-    ],
-    [
-        "500139",
-        "rr_c",
-        "snow amount, grid-scale plus convective"
-    ],
-    [
-        "500140",
-        "dt_gsp",
-        "temperature tendency due to grid scale precipation"
-    ],
-    [
-        "500141",
-        "dqv_gsp",
-        "specific humitiy tendency due to grid scale precipitation"
-    ],
-    [
-        "500142",
-        "dqc_gsp",
-        "tendency of specific cloud liquid water content due to grid scale precipitation"
-    ],
-    [
-        "500143",
-        "freshsnw",
-        "fresh snow factor (weighting function for albedo indicating freshness of snow)"
-    ],
-    [
-        "500144",
-        "dqi_gsp",
-        "tendency of specific cloud ice content due to grid scale precipitation"
-    ],
-    [
-        "500145",
-        "prg_gsp",
-        "graupel (snow pellets) precipitation rate"
-    ],
-    [
-        "500146",
-        "grau_gsp",
-        "graupel (snow pellets) precipitation rate"
-    ],
-    [
-        "500147",
-        "rho_snow",
-        "snow density"
-    ],
-    [
-        "500148",
-        "pp",
-        "pressure perturbation"
-    ],
-    [
-        "500149",
-        "sdi_1",
-        "supercell detection index 1 (rot. up+down drafts)"
-    ],
-    [
-        "500150",
-        "sdi_2",
-        "supercell detection index 2 (only rot. up drafts)"
-    ],
-    [
-        "500151",
-        "cape_mu",
-        "convective available potential energy, most unstable"
-    ],
-    [
-        "500152",
-        "cin_mu",
-        "convective inhibition, most unstable"
-    ],
-    [
-        "500153",
-        "cape_ml",
-        "convective available potential energy, mean layer"
-    ],
-    [
-        "500154",
-        "cin_ml",
-        "convective inhibition, mean layer"
-    ],
-    [
-        "500155",
-        "tke_con",
-        "convective turbulent kinetic enery"
-    ],
-    [
-        "500156",
-        "tketens",
-        "tendency of turbulent kinetic energy"
-    ],
-    [
-        "500157",
-        "ke",
-        "kinetic energy"
-    ],
-    [
-        "500158",
-        "tke",
-        "turbulent kinetic energy"
-    ],
-    [
-        "500159",
-        "tkvm",
-        "turbulent diffusioncoefficient for momentum"
-    ],
-    [
-        "500160",
-        "tkvh",
-        "turbulent diffusion coefficient for heat (and moisture)"
-    ],
-    [
-        "500161",
-        "tcm",
-        "turbulent transfer coefficient for impulse"
-    ],
-    [
-        "500162",
-        "tch",
-        "turbulent transfer coefficient for heat (and moisture)"
-    ],
-    [
-        "500163",
-        "mh",
-        "mixed layer depth"
-    ],
-    [
-        "500164",
-        "vmax_10m",
-        "maximum wind 10m"
-    ],
-    [
-        "500165",
-        "ru-103",
-        "air concentration of ruthenium 103"
-    ],
-    [
-        "500166",
-        "t_so",
-        "soil temperature (multilayers)"
-    ],
-    [
-        "500167",
-        "w_so",
-        "column-integrated soil moisture (multilayers)"
-    ],
-    [
-        "500168",
-        "w_so_ice",
-        "soil ice content (multilayers)"
-    ],
-    [
-        "500169",
-        "w_i",
-        "plant canopy surface water"
-    ],
-    [
-        "500170",
-        "t_snow",
-        "snow temperature (top of snow)"
-    ],
-    [
-        "500171",
-        "prs_min",
-        "minimal stomatal resistance"
-    ],
-    [
-        "500172",
-        "t_ice",
-        "sea ice temperature"
-    ],
-    [
-        "500173",
-        "dbz_850",
-        "base reflectivity"
-    ],
-    [
-        "500174",
-        "dbz",
-        "base reflectivity"
-    ],
-    [
-        "500175",
-        "dbz_cmax",
-        "base reflectivity (cmax)"
-    ],
-    [
-        "500176",
-        "dttdiv",
-        "unknown"
-    ],
-    [
-        "500177",
-        "sotr_rad",
-        "effective transmissivity of solar radiation"
-    ],
-    [
-        "500178",
-        "evatra_sum",
-        "sum of contributions to evaporation"
-    ],
-    [
-        "500179",
-        "tra_sum",
-        "total transpiration from all soil layers"
-    ],
-    [
-        "500180",
-        "totforce_s",
-        "total forcing at soil surface"
-    ],
-    [
-        "500181",
-        "resid_wso",
-        "residuum of soil moisture"
-    ],
-    [
-        "500182",
-        "mflx_con",
-        "massflux at convective cloud base"
-    ],
-    [
-        "500183",
-        "cape_con",
-        "convective available potential energy"
-    ],
-    [
-        "500184",
-        "qcvg_con",
-        "moisture convergence for kuo-type closure"
-    ],
-    [
-        "500185",
-        "mwd",
-        "total wave direction"
-    ],
-    [
-        "500186",
-        "mwp_x",
-        "wind sea mean period"
-    ],
-    [
-        "500187",
-        "ppww",
-        "wind sea peak period"
-    ],
-    [
-        "500188",
-        "mpp_s",
-        "swell mean period"
-    ],
-    [
-        "500189",
-        "ppps",
-        "swell peak period"
-    ],
-    [
-        "500190",
-        "pp1d",
-        "total wave peak period"
-    ],
-    [
-        "500191",
-        "tm10",
-        "total wave mean period"
-    ],
-    [
-        "500192",
-        "tm01",
-        "total tm1 period"
-    ],
-    [
-        "500193",
-        "tm02",
-        "total tm2 period"
-    ],
-    [
-        "500194",
-        "sprd",
-        "total directional spread"
-    ],
-    [
-        "500195",
-        "ana_err_fi",
-        "analysis error(standard deviation), geopotential(gpm)"
-    ],
-    [
-        "500196",
-        "ana_err_u",
-        "analysis error(standard deviation), u-comp. of wind"
-    ],
-    [
-        "500197",
-        "ana_err_v",
-        "analysis error(standard deviation), v-comp. of wind"
-    ],
-    [
-        "500198",
-        "du_sso",
-        "zonal wind tendency due to subgrid scale oro."
-    ],
-    [
-        "500199",
-        "dv_sso",
-        "meridional wind tendency due to subgrid scale oro."
-    ],
-    [
-        "500200",
-        "sso_stdh",
-        "standard deviation of sub-grid scale orography"
-    ],
-    [
-        "500201",
-        "sso_gamma",
-        "anisotropy of sub-gridscale orography"
-    ],
-    [
-        "500202",
-        "sso_theta",
-        "angle of sub-gridscale orography"
-    ],
-    [
-        "500203",
-        "sso_sigma",
-        "slope of sub-gridscale orography"
-    ],
-    [
-        "500204",
-        "emis_rad",
-        "surface emissivity"
-    ],
-    [
-        "500205",
-        "soiltyp",
-        "soil type"
-    ],
-    [
-        "500206",
-        "lai",
-        "leaf area index"
-    ],
-    [
-        "500207",
-        "rootdp",
-        "root depth of vegetation"
-    ],
-    [
-        "500208",
-        "hmo3",
-        "height of ozone maximum (climatological)"
-    ],
-    [
-        "500209",
-        "vio3",
-        "vertically integrated ozone content (climatological)"
-    ],
-    [
-        "500210",
-        "plcov_mx",
-        "plant covering degree in the vegetation phase"
-    ],
-    [
-        "500211",
-        "plcov_mn",
-        "plant covering degree in the quiescent phas"
-    ],
-    [
-        "500212",
-        "lai_mx",
-        "max leaf area index"
-    ],
-    [
-        "500213",
-        "lai_mn",
-        "min leaf area index"
-    ],
-    [
-        "500214",
-        "oro_mod",
-        "orographie + land-meer-verteilung"
-    ],
-    [
-        "500215",
-        "wvar1",
-        "variance of soil moisture content (0-10)"
-    ],
-    [
-        "500216",
-        "wvar2",
-        "variance of soil moisture content (10-100)"
-    ],
-    [
-        "500217",
-        "for_e",
-        "evergreen forest"
-    ],
-    [
-        "500218",
-        "for_d",
-        "deciduous forest"
-    ],
-    [
-        "500219",
-        "ndvi",
-        "normalized differential vegetation index"
-    ],
-    [
-        "500220",
-        "ndvi_max",
-        "normalized differential vegetation index (ndvi)"
-    ],
-    [
-        "500221",
-        "ndvi_mrat",
-        "ratio of monthly mean ndvi (normalized differential vegetation index) to annual maximum"
-    ],
-    [
-        "500222",
-        "ndviratio",
-        "ratio of monthly mean ndvi (normalized differential vegetation index) to annual maximum"
-    ],
-    [
-        "500223",
-        "aer_so4",
-        "total sulfate aerosol"
-    ],
-    [
-        "500224",
-        "aer_so412",
-        "total sulfate aerosol (12m)"
-    ],
-    [
-        "500225",
-        "aer_dust",
-        "total soil dust aerosol"
-    ],
-    [
-        "500226",
-        "aer_dust12",
-        "total soil dust aerosol (12m)"
-    ],
-    [
-        "500228",
-        "aer_org12",
-        "organic aerosol (12m)"
-    ],
-    [
-        "500227",
-        "aer_org",
-        "organic aerosol"
-    ],
-    [
-        "500230",
-        "aer_bc12",
-        "black carbon aerosol (12m)"
-    ],
-    [
-        "500229",
-        "aer_bc",
-        "black carbon aerosol"
-    ],
-    [
-        "500232",
-        "aer_ss12",
-        "sea salt aerosol (12m)"
-    ],
-    [
-        "500231",
-        "aer_ss",
-        "sea salt aerosol"
-    ],
-    [
-        "500233",
-        "dqvdt",
-        "tendency of specific humidity"
-    ],
-    [
-        "500234",
-        "qvsflx",
-        "water vapor flux"
-    ],
-    [
-        "500235",
-        "fc",
-        "coriolis parameter"
-    ],
-    [
-        "500236",
-        "rlat",
-        "geographical latitude"
-    ],
-    [
-        "500237",
-        "rlon",
-        "geographical longitude"
-    ],
-    [
-        "500238",
-        "ustr",
-        "friction velocity"
-    ],
-    [
-        "500239",
-        "ztd",
-        "delay of the gps signal trough the (total) atm."
-    ],
-    [
-        "500240",
-        "zwd",
-        "delay of the gps signal trough wet atmos."
-    ],
-    [
-        "500241",
-        "zhd",
-        "delay of the gps signal trough dry atmos."
-    ],
-    [
-        "500242",
-        "o3",
-        "ozone mixing ratio"
-    ],
-    [
-        "500243",
-        "ru-103",
-        "air concentration of ruthenium 103 (ru103- concentration)"
-    ],
-    [
-        "500244",
-        "ru-103d",
-        "ru103-dry deposition"
-    ],
-    [
-        "500245",
-        "ru-103w",
-        "ru103-wet deposition"
-    ],
-    [
-        "500246",
-        "sr-90",
-        "air concentration of strontium 90"
-    ],
-    [
-        "500247",
-        "sr-90d",
-        "sr90-dry deposition"
-    ],
-    [
-        "500248",
-        "sr-90w",
-        "sr90-wet deposition"
-    ],
-    [
-        "500249",
-        "i-131a",
-        "i131-concentration"
-    ],
-    [
-        "500250",
-        "i-131ad",
-        "i131-dry deposition"
-    ],
-    [
-        "500251",
-        "i-131aw",
-        "i131-wet deposition"
-    ],
-    [
-        "500252",
-        "cs-137",
-        "cs137-concentration"
-    ],
-    [
-        "500253",
-        "cs-137d",
-        "cs137-dry deposition"
-    ],
-    [
-        "500254",
-        "cs-137w",
-        "cs137-wet deposition"
-    ],
-    [
-        "500255",
-        "te-132",
-        "air concentration of tellurium 132 (te132-concentration)"
-    ],
-    [
-        "500256",
-        "te-132d",
-        "te132-dry deposition"
-    ],
-    [
-        "500257",
-        "te-132w",
-        "te132-wet deposition"
-    ],
-    [
-        "500258",
-        "zr-95",
-        "air concentration of zirconium 95 (zr95-concentration)"
-    ],
-    [
-        "500259",
-        "zr-95d",
-        "zr95-dry deposition"
-    ],
-    [
-        "500260",
-        "zr-95w",
-        "zr95-wet deposition"
-    ],
-    [
-        "500261",
-        "kr-85",
-        "air concentration of krypton 85  (kr85-concentration)"
-    ],
-    [
-        "500262",
-        "kr-85d",
-        "kr85-dry deposition"
-    ],
-    [
-        "500263",
-        "kr-85w",
-        "kr85-wet deposition"
-    ],
-    [
-        "500264",
-        "tr-2",
-        "tracer - concentration"
-    ],
-    [
-        "500265",
-        "tr-2d",
-        "tracer - dry deposition"
-    ],
-    [
-        "500266",
-        "tr-2w",
-        "tracer - wet deposition"
-    ],
-    [
-        "500267",
-        "xe-133",
-        "air concentration of xenon 133 (xe133  - concentration)"
-    ],
-    [
-        "500268",
-        "xe-133d",
-        "xe133  - dry deposition"
-    ],
-    [
-        "500269",
-        "xe-133w",
-        "xe133  - wet deposition"
-    ],
-    [
-        "500270",
-        "i-131g",
-        "i131g - concentration"
-    ],
-    [
-        "500271",
-        "i-131gd",
-        "xe133  - wet deposition"
-    ],
-    [
-        "500272",
-        "i-131gw",
-        "i131g  - wet deposition"
-    ],
-    [
-        "500273",
-        "i-131o",
-        "i131o  - concentration"
-    ],
-    [
-        "500274",
-        "i-131od",
-        "i131o  - dry deposition"
-    ],
-    [
-        "500275",
-        "i-131ow",
-        "i131o  - wet deposition"
-    ],
-    [
-        "500276",
-        "ba-140",
-        "air concentration of barium 40"
-    ],
-    [
-        "500277",
-        "ba-140d",
-        "ba140 - dry deposition"
-    ],
-    [
-        "500278",
-        "ba-140w",
-        "ba140  - wet deposition"
-    ],
-    [
-        "500279",
-        "austr_sso",
-        "u-momentum flux due to sso-effects"
-    ],
-    [
-        "500280",
-        "ustr_sso",
-        "u-momentum flux due to sso-effects"
-    ],
-    [
-        "500282",
-        "vstr_sso",
-        "v-momentum flux due to sso-effects"
-    ],
-    [
-        "500281",
-        "avstr_sso",
-        "v-momentum flux due to sso-effects"
-    ],
-    [
-        "500283",
-        "avdis_sso",
-        "gravity wave dissipation (vertical integral)"
-    ],
-    [
-        "500284",
-        "vdis_sso",
-        "gravity wave dissipation (vertical integral)"
-    ],
-    [
-        "500285",
-        "uv_max",
-        "uv_index_maximum_w  uv_index clouded (w), daily maximum"
-    ],
-    [
-        "500286",
-        "w_shaer",
-        "wind shear"
-    ],
-    [
-        "500287",
-        "srh",
-        "storm relative helicity"
-    ],
-    [
-        "500288",
-        "vabs",
-        "absolute vorticity advection"
-    ],
-    [
-        "500289",
-        "cl_typ",
-        "niederschlagbew.-artkombination niederschl.-bew.-blautherm. (283..407)"
-    ],
-    [
-        "500290",
-        "ccl_gnd",
-        "konvektions-u-grenzehoehe der konvektionsuntergrenze ueber grund"
-    ],
-    [
-        "500291",
-        "ccl_nn",
-        "konv.-u-grenze-nn   hoehe der konvektionsuntergrenze ueber nn"
-    ],
-    [
-        "500292",
-        "ww",
-        "weather interpretation (wmo)"
-    ],
-    [
-        "500293",
-        "advorg",
-        "geostrophische  vorticityadvektion"
-    ],
-    [
-        "500294",
-        "advor",
-        "geo temperatur adv  geostrophische schichtdickenadvektion"
-    ],
-    [
-        "500295",
-        "adrtg",
-        "schichtdicken-advektion"
-    ],
-    [
-        "500296",
-        "wdiv",
-        "winddivergenz"
-    ],
-    [
-        "500297",
-        "fqn",
-        "qn-vektor q isother-senkr-kompqn ,komp. q-vektor senkrecht zu den isothermen"
-    ],
-    [
-        "500298",
-        "ipv",
-        "isentrope potentielle vorticity"
-    ],
-    [
-        "500299",
-        "up",
-        "xipv wind x-komp     wind x-komponente auf isentropen flaechen"
-    ],
-    [
-        "500300",
-        "vp",
-        "yipv wind y-komp     wind y-komponente auf isentropen flaechen"
-    ],
-    [
-        "500301",
-        "ptheta",
-        "druck einer isentropen flaeche"
-    ],
-    [
-        "500302",
-        "ko",
-        "ko index"
-    ],
-    [
-        "500303",
-        "thetae",
-        "aequivalentpotentielle temperatur"
-    ],
-    [
-        "500304",
-        "ceiling",
-        "ceiling"
-    ],
-    [
-        "500305",
-        "ice_grd",
-        "icing grade (1=lgt,2=mod,3=sev)"
-    ],
-    [
-        "500306",
-        "cldepth",
-        "modified cloud depth for media"
-    ],
-    [
-        "500307",
-        "clct_mod",
-        "modified cloud cover for media"
-    ],
-    [
-        "500308",
-        "efa-ps",
-        "monthly mean of rms of difference fg-an of pressure reduced to msl"
-    ],
-    [
-        "500309",
-        "eia-ps",
-        "monthly mean of rms of difference ia-an of pressure reduced to msl"
-    ],
-    [
-        "500310",
-        "efa-u",
-        "monthly mean of rms of difference fg-an of u-component of wind"
-    ],
-    [
-        "500311",
-        "eia-u",
-        "monthly mean of rms of difference ia-an of u-component of wind"
-    ],
-    [
-        "500312",
-        "efa-v",
-        "monthly mean of rms of difference fg-an of v-component of wind"
-    ],
-    [
-        "500313",
-        "eia-v",
-        "monthly mean of rms of difference ia-an of v-component of wind"
-    ],
-    [
-        "500314",
-        "efa-fi",
-        "monthly mean of rms of difference fg-an of geopotential"
-    ],
-    [
-        "500315",
-        "eia-fi",
-        "monthly mean of rms of difference ia-an of geopotential"
-    ],
-    [
-        "500316",
-        "efa-rh",
-        "monthly mean of rms of difference fg-an of relative humidity"
-    ],
-    [
-        "500317",
-        "eia-rh",
-        "monthly mean of rms of difference ia-an of relative humidity"
-    ],
-    [
-        "500318",
-        "efa-t",
-        "monthly mean of rms of difference fg-an of temperature"
-    ],
-    [
-        "500319",
-        "eia-t",
-        "monthly mean of rms of difference ia-an of temperature"
-    ],
-    [
-        "500320",
-        "efa-om",
-        "monthly mean of rms of difference fg-an of vert.velocity (pressure)"
-    ],
-    [
-        "500321",
-        "eia-om",
-        "monthly mean of rms of difference ia-an of vert.velocity (pressure)"
-    ],
-    [
-        "500322",
-        "efa-ke",
-        "monthly mean of rms of difference fg-an of kinetic energy"
-    ],
-    [
-        "500323",
-        "eia-ke",
-        "monthly mean of rms of difference ia-an of kinetic energy"
-    ],
-    [
-        "500324",
-        "synme5_bt_cl",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500325",
-        "synme5_bt_cs",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500327",
-        "synme5_rad_cs",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500326",
-        "synme5_rad_cl",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500328",
-        "synme6_bt_cl",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500330",
-        "synme6_rad_cl",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500331",
-        "synme6_rad_cs",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500329",
-        "synme6_bt_cs",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500332",
-        "synme7_bt_cl_ir11.5",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500334",
-        "synme7_bt_cs_ir11.5",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500335",
-        "synme7_bt_cs_wv6.4",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500336",
-        "synme7_rad_cl_ir11.5",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500338",
-        "synme7_rad_cs_ir11.5",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500339",
-        "synme7_rad_cs_wv6.4",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500333",
-        "synme7_bt_cl_wv6.4",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500337",
-        "synme7_rad_cl_wv6.4",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500366",
-        "synmsg_rad_cs_ir13.4",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500367",
-        "synmsg_rad_cs_ir3.9",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500368",
-        "synmsg_rad_cs_ir8.7",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500369",
-        "synmsg_rad_cs_ir9.7",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500370",
-        "synmsg_rad_cs_wv6.2",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500371",
-        "synmsg_rad_cs_wv7.3",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500340",
-        "synmsg_bt_cl_ir10.8",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500342",
-        "synmsg_bt_cl_ir13.4",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500343",
-        "synmsg_bt_cl_ir3.9",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500344",
-        "synmsg_bt_cl_ir8.7",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500345",
-        "synmsg_bt_cl_ir9.7",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500347",
-        "synmsg_bt_cl_wv7.3",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500348",
-        "synmsg_bt_cs_ir8.7",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500349",
-        "synmsg_bt_cs_ir10.8",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500350",
-        "synmsg_bt_cs_ir12.1",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500352",
-        "synmsg_bt_cs_ir3.9",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500353",
-        "synmsg_bt_cs_ir9.7",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500355",
-        "synmsg_bt_cs_wv7.3",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500356",
-        "synmsg_rad_cl_ir10.8",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500357",
-        "synmsg_rad_cl_ir12.1",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500359",
-        "synmsg_rad_cl_ir3.9",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500360",
-        "synmsg_rad_cl_ir8.7",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500361",
-        "synmsg_rad_cl_ir9.7",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500363",
-        "synmsg_rad_cl_wv7.3",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500364",
-        "synmsg_rad_cs_ir10.8",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500365",
-        "synmsg_rad_cs_ir12.1",
-        "synth. sat. radiance clear sky"
-    ],
-    [
-        "500341",
-        "synmsg_bt_cl_ir12.1",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500346",
-        "synmsg_bt_cl_wv6.2",
-        "synth. sat. brightness temperature cloudy"
-    ],
-    [
-        "500351",
-        "synmsg_bt_cs_ir13.4",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500354",
-        "synmsg_bt_cs_wv6.2",
-        "synth. sat. brightness temperature clear sky"
-    ],
-    [
-        "500358",
-        "synmsg_rad_cl_ir13.4",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500362",
-        "synmsg_rad_cl_wv6.2",
-        "synth. sat. radiance cloudy"
-    ],
-    [
-        "500372",
-        "t_2m_s",
-        "smoothed forecast, temperature"
-    ],
-    [
-        "500373",
-        "tmax_2m_s",
-        "smoothed forecast, maximum temp."
-    ],
-    [
-        "500374",
-        "tmin_2m_s",
-        "smoothed forecast, minimum temp."
-    ],
-    [
-        "500375",
-        "td_2m_s",
-        "smoothed forecast, dew point temp."
-    ],
-    [
-        "500376",
-        "u_10m_s",
-        "smoothed forecast, u comp. of wind"
-    ],
-    [
-        "500377",
-        "v_10m_s",
-        "smoothed forecast, v comp. of wind"
-    ],
-    [
-        "500378",
-        "tot_prec_s",
-        "smoothed forecast, total precipitation rate"
-    ],
-    [
-        "500379",
-        "clct_s",
-        "smoothed forecast, total cloud cover"
-    ],
-    [
-        "500380",
-        "clcl_s",
-        "smoothed forecast, cloud cover low"
-    ],
-    [
-        "500381",
-        "clcm_s",
-        "smoothed forecast, cloud cover medium"
-    ],
-    [
-        "500382",
-        "clch_s",
-        "smoothed forecast, cloud cover high"
-    ],
-    [
-        "500383",
-        "snow_gsp_s",
-        "smoothed forecast, large-scale snowfall rate w.e."
-    ],
-    [
-        "500384",
-        "t_s_s",
-        "smoothed forecast, soil temperature"
-    ],
-    [
-        "500385",
-        "vmax_10m_s",
-        "smoothed forecast, wind speed (gust)"
-    ],
-    [
-        "500386",
-        "tot_prec_c",
-        "calibrated forecast, total precipitation rate"
-    ],
-    [
-        "500387",
-        "snow_gsp_c",
-        "calibrated forecast, large-scale snowfall rate w.e."
-    ],
-    [
-        "500388",
-        "vmax_10m_c",
-        "calibrated forecast, wind speed (gust)"
-    ],
-    [
-        "500389",
-        "obsmsg_alb_hrv",
-        "obser. sat. meteosat sec. generation albedo (scaled)"
-    ],
-    [
-        "500390",
-        "obsmsg_alb_nir1.6",
-        "obser. sat. meteosat sec. generation albedo (scaled)"
-    ],
-    [
-        "500391",
-        "obsmsg_alb_vis0.6",
-        "obser. sat. meteosat sec. generation albedo (scaled)"
-    ],
-    [
-        "500392",
-        "obsmsg_alb_vis0.8",
-        "obser. sat. meteosat sec. generation albedo (scaled)"
-    ],
-    [
-        "500393",
-        "obsmsg_bt_ir10.8",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500394",
-        "obsmsg_bt_ir12.0",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500395",
-        "obsmsg_bt_ir13.4",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500396",
-        "obsmsg_bt_ir3.9",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500397",
-        "obsmsg_bt_ir8.7",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500398",
-        "obsmsg_bt_ir9.7",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500399",
-        "obsmsg_bt_wv6.2",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "500400",
-        "obsmsg_bt_wv7.3",
-        "obser. sat. meteosat sec. generation brightness temperature"
-    ],
-    [
-        "228022",
-        "cdir",
-        "clear-sky direct solar radiation at surface"
-    ],
-    [
-        "228021",
-        "fdir",
-        "total sky direct solar radiation at surface"
-    ],
-    [
-        "210112",
-        "hialkanesfire",
-        "wildfire flux of higher alkanes (cnh2n+2, c>=4)"
-    ],
-    [
-        "210111",
-        "hialkenesfire",
-        "wildfire flux of higher alkenes (cnh2n, c>=4)"
-    ],
-    [
-        "210110",
-        "toluenefire",
-        "wildfire flux of toluene_lump (c7h8+ c6h6 + c8h10)"
-    ],
-    [
-        "210117",
-        "c2h6sfire",
-        "wildfire flux of dimethyl sulfide (dms) (c2h6s)"
-    ],
-    [
-        "210116",
-        "nh3fire",
-        "wildfire flux of ammonia (nh3)"
-    ],
-    [
-        "210115",
-        "c3h6ofire",
-        "wildfire flux of acetone (c3h6o)"
-    ],
-    [
-        "210114",
-        "c2h4ofire",
-        "wildfire flux of acetaldehyde (c2h4o)"
-    ],
-    [
-        "210113",
-        "ch2ofire",
-        "wildfire flux of formaldehyde (ch2o)"
-    ],
-    [
-        "210109",
-        "terpenesfire",
-        "wildfire flux of terpenes (c5h8)n"
-    ],
-    [
-        "210108",
-        "c5h8fire",
-        "wildfire flux of isoprene (c5h8)"
-    ],
-    [
-        "210107",
-        "c3h6fire",
-        "wildfire flux of propene (c3h6)"
-    ],
-    [
-        "210106",
-        "c2h4fire",
-        "wildfire flux of ethene (c2h4)"
-    ],
-    [
-        "210105",
-        "c3h8fire",
-        "wildfire flux of propane (c3h8)"
-    ],
-    [
-        "210104",
-        "c2h5ohfire",
-        "wildfire flux of ethanol (c2h5oh)"
-    ],
-    [
-        "210103",
-        "ch3ohfire",
-        "wildfire flux of methanol (ch3oh)"
-    ],
-    [
-        "210013",
-        "aermr13",
-        "volcanic ash aerosol mixing ratio"
-    ],
-    [
-        "210118",
-        "c2h6fire",
-        "wildfire flux of ethane (c2h6)"
-    ],
-    [
-        "210119",
-        "mami",
-        "mean altitude of maximum injection"
-    ],
-    [
-        "210120",
-        "apt",
-        "altitude of plume top"
-    ],
-    [
-        "171121",
-        "mx2t6a",
-        "maximum temperature at 2 metres in the last 6 hours anomaly"
-    ],
-    [
-        "171122",
-        "mn2t6a",
-        "minimum temperature at 2 metres in the last 6 hours anomaly"
-    ],
-    [
-        "131089",
-        "pts",
-        "probability of a tropical storm",
-        "89.131"
-    ],
-    [
-        "131090",
-        "ph",
-        "probability of a hurricane",
-        "90.131"
-    ],
-    [
-        "131091",
-        "ptd",
-        "probability of a tropical depression",
-        "91.131"
-    ],
-    [
-        "131092",
-        "cpts",
-        "climatological probability of a tropical storm"
-    ],
-    [
-        "131093",
-        "cph",
-        "climatological probability of a hurricane"
-    ],
-    [
-        "131094",
-        "cptd",
-        "climatological probability of a tropical depression"
-    ],
-    [
-        "131095",
-        "pats",
-        "probability anomaly of a tropical storm"
-    ],
-    [
-        "131096",
-        "pah",
-        "probability anomaly of a hurricane"
-    ],
-    [
-        "131097",
-        "patd",
-        "probability anomaly of a tropical depression"
-    ],
-    [
-        "210014",
-        "aermr14",
-        "volcanic sulphate aerosol mixing ratio"
-    ],
-    [
-        "210015",
-        "aermr15",
-        "volcanic so2 precursor mixing ratio"
-    ],
-    [
-        "210028",
-        "aerpr03",
-        "so4 aerosol precursor mass mixing ratio"
-    ],
-    [
-        "210029",
-        "aerwv01",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 1"
-    ],
-    [
-        "210030",
-        "aerwv02",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 2"
-    ],
-    [
-        "210043",
-        "emdms",
-        "dms surface emission"
-    ],
-    [
-        "210044",
-        "aerwv03",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 3"
-    ],
-    [
-        "210045",
-        "aerwv04",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 4"
-    ],
-    [
-        "228023",
-        "cbh",
-        "cloud base height"
-    ],
-    [
-        "228024",
-        "deg0l",
-        "zero degree level",
-        "24.228",
-        "degol",
-        "deg0"
-    ],
-    [
-        "228025",
-        "hvis",
-        "horizontal visibility"
-    ],
-    [
-        "228089",
-        "tcrw",
-        "total column rain water"
-    ],
-    [
-        "228090",
-        "tcsw",
-        "total column snow water"
-    ],
-    [
-        "162114",
-        "utendd",
-        "u-tendency from dynamics"
-    ],
-    [
-        "162115",
-        "vtendd",
-        "v-tendency from dynamics"
-    ],
-    [
-        "162116",
-        "ttendd",
-        "t-tendency from dynamics"
-    ],
-    [
-        "162117",
-        "qtendd",
-        "q-tendency from dynamics"
-    ],
-    [
-        "162118",
-        "ttendr",
-        "t-tendency from radiation"
-    ],
-    [
-        "162119",
-        "utendts",
-        "u-tendency from turbulent diffusion + subgrid orography"
-    ],
-    [
-        "162120",
-        "vtendts",
-        "v-tendency from turbulent diffusion + subgrid orography"
-    ],
-    [
-        "162121",
-        "ttendts",
-        "t-tendency from turbulent diffusion + subgrid orography"
-    ],
-    [
-        "162122",
-        "qtendt",
-        "q-tendency from turbulent diffusion"
-    ],
-    [
-        "162123",
-        "utends",
-        "u-tendency from subgrid orography"
-    ],
-    [
-        "162124",
-        "vtends",
-        "v-tendency from subgrid orography"
-    ],
-    [
-        "162125",
-        "ttends",
-        "t-tendency from subgrid orography"
-    ],
-    [
-        "162126",
-        "utendcds",
-        "u-tendency from convection (deep+shallow)"
-    ],
-    [
-        "162127",
-        "vtendcds",
-        "v-tendency from convection (deep+shallow)"
-    ],
-    [
-        "162128",
-        "ttendcds",
-        "t-tendency from convection (deep+shallow)"
-    ],
-    [
-        "162129",
-        "qtendcds",
-        "q-tendency from convection (deep+shallow)"
-    ],
-    [
-        "162130",
-        "lpc",
-        "liquid precipitation flux from convection"
-    ],
-    [
-        "162131",
-        "ipc",
-        "ice precipitation flux from convection"
-    ],
-    [
-        "162132",
-        "ttendcs",
-        "t-tendency from cloud scheme"
-    ],
-    [
-        "162133",
-        "qtendcs",
-        "q-tendency from cloud scheme"
-    ],
-    [
-        "162134",
-        "qltendcs",
-        "ql-tendency from cloud scheme"
-    ],
-    [
-        "162135",
-        "qitendcs",
-        "qi-tendency from cloud scheme"
-    ],
-    [
-        "162136",
-        "lpcs",
-        "liquid precip flux from cloud scheme (stratiform)"
-    ],
-    [
-        "162137",
-        "ipcs",
-        "ice precip flux from cloud scheme (stratiform)"
-    ],
-    [
-        "162138",
-        "utendcs",
-        "u-tendency from shallow convection"
-    ],
-    [
-        "162139",
-        "vtendcs",
-        "v-tendency from shallow convection"
-    ],
-    [
-        "162140",
-        "ttendsc",
-        "t-tendency from shallow convection"
-    ],
-    [
-        "162141",
-        "qtendsc",
-        "q-tendency from shallow convection"
-    ],
-    [
-        "213001",
-        "sppt1",
-        "random pattern 1 for sppt"
-    ],
-    [
-        "213002",
-        "sppt2",
-        "random pattern 2 for sppt"
-    ],
-    [
-        "213003",
-        "sppt3",
-        "random pattern 3 for sppt"
-    ],
-    [
-        "213004",
-        "sppt4",
-        "random pattern 4 for sppt"
-    ],
-    [
-        "213005",
-        "sppt5",
-        "random pattern 5 for sppt"
-    ],
-    [
-        "228249",
-        "100si",
-        "100 metre wind speed"
-    ],
-    [
-        "228250",
-        "irrfr",
-        "irrigation fraction"
-    ],
-    [
-        "228251",
-        "pev",
-        "potential evaporation"
-    ],
-    [
-        "228252",
-        "irr",
-        "irrigation"
-    ],
-    [
-        "162079",
-        "vilwd",
-        "vertical integral of divergence of cloud liquid water flux"
-    ],
-    [
-        "162080",
-        "viiwd",
-        "vertical integral of divergence of cloud frozen water flux"
-    ],
-    [
-        "162088",
-        "vilwe",
-        "vertical integral of eastward cloud liquid water flux"
-    ],
-    [
-        "162089",
-        "vilwn",
-        "vertical integral of northward cloud liquid water flux"
-    ],
-    [
-        "162090",
-        "viiwe",
-        "vertical integral of eastward cloud frozen water flux"
-    ],
-    [
-        "162091",
-        "viiwn",
-        "vertical integral of northward cloud frozen water flux "
-    ],
-    [
-        "162092",
-        "vimat",
-        "vertical integral of mass tendency"
-    ],
-    [
-        "171006",
-        "100ua",
-        "100 metre u wind component anomaly"
-    ],
-    [
-        "171007",
-        "100va",
-        "100 metre v wind component anomaly"
-    ],
-    [
-        "228091",
-        "ccf",
-        "canopy cover fraction"
-    ],
-    [
-        "228092",
-        "stf",
-        "soil texture fraction"
-    ],
-    [
-        "228093",
-        "swv",
-        "volumetric soil moisture"
-    ],
-    [
-        "228094",
-        "ist",
-        "ice temperature"
-    ],
-    [
-        "214002",
-        "uvbed",
-        " uv biologically effective dose"
-    ],
-    [
-        "214003",
-        "uvbedcs",
-        " uv biologically effective dose clear-sky"
-    ],
-    [
-        "214004",
-        "uvsflxt280285",
-        " total surface uv spectral flux (280-285 nm)"
-    ],
-    [
-        "214005",
-        "uvsflxt285290",
-        " total surface uv spectral flux (285-290 nm)"
-    ],
-    [
-        "214006",
-        "uvsflxt290295",
-        " total surface uv spectral flux (290-295 nm)"
-    ],
-    [
-        "214007",
-        "uvsflxt295300",
-        " total surface uv spectral flux (295-300 nm)"
-    ],
-    [
-        "214008",
-        "uvsflxt300305",
-        " total surface uv spectral flux (300-305 nm)"
-    ],
-    [
-        "214009",
-        "uvsflxt305310",
-        " total surface uv spectral flux (305-310 nm)"
-    ],
-    [
-        "214010",
-        "uvsflxt310315",
-        " total surface uv spectral flux (310-315 nm)"
-    ],
-    [
-        "214011",
-        "uvsflxt315320",
-        " total surface uv spectral flux (315-320 nm)"
-    ],
-    [
-        "214012",
-        "uvsflxt320325",
-        " total surface uv spectral flux (320-325 nm)"
-    ],
-    [
-        "214013",
-        "uvsflxt325330",
-        " total surface uv spectral flux (325-330 nm)"
-    ],
-    [
-        "214014",
-        "uvsflxt330335",
-        " total surface uv spectral flux (330-335 nm)"
-    ],
-    [
-        "214015",
-        "uvsflxt335340",
-        " total surface uv spectral flux (335-340 nm)"
-    ],
-    [
-        "214016",
-        "uvsflxt340345",
-        " total surface uv spectral flux (340-345 nm)"
-    ],
-    [
-        "214017",
-        "uvsflxt345350",
-        " total surface uv spectral flux (345-350 nm)"
-    ],
-    [
-        "214018",
-        "uvsflxt350355",
-        " total surface uv spectral flux (350-355 nm)"
-    ],
-    [
-        "214019",
-        "uvsflxt355360",
-        " total surface uv spectral flux (355-360 nm)"
-    ],
-    [
-        "214020",
-        "uvsflxt360365",
-        " total surface uv spectral flux (360-365 nm)"
-    ],
-    [
-        "214021",
-        "uvsflxt365370",
-        " total surface uv spectral flux (365-370 nm)"
-    ],
-    [
-        "214022",
-        "uvsflxt370375",
-        " total surface uv spectral flux (370-375 nm)"
-    ],
-    [
-        "214023",
-        "uvsflxt375380",
-        " total surface uv spectral flux (375-380 nm)"
-    ],
-    [
-        "214024",
-        "uvsflxt380385",
-        " total surface uv spectral flux (380-385 nm)"
-    ],
-    [
-        "214025",
-        "uvsflxt385390",
-        " total surface uv spectral flux (385-390 nm)"
-    ],
-    [
-        "214026",
-        "uvsflxt390395",
-        " total surface uv spectral flux (390-395 nm)"
-    ],
-    [
-        "214027",
-        "uvsflxt395400",
-        " total surface uv spectral flux (395-400 nm)"
-    ],
-    [
-        "214028",
-        "uvsflxcs280285",
-        " clear-sky surface uv spectral flux (280-285 nm)"
-    ],
-    [
-        "214029",
-        "uvsflxcs285290",
-        " clear-sky surface uv spectral flux (285-290 nm)"
-    ],
-    [
-        "214030",
-        "uvsflxcs290295",
-        " clear-sky surface uv spectral flux (290-295 nm)"
-    ],
-    [
-        "214031",
-        "uvsflxcs295300",
-        " clear-sky surface uv spectral flux (295-300 nm)"
-    ],
-    [
-        "214032",
-        "uvsflxcs300305",
-        " clear-sky surface uv spectral flux (300-305 nm)"
-    ],
-    [
-        "214033",
-        "uvsflxcs305310",
-        " clear-sky surface uv spectral flux (305-310 nm)"
-    ],
-    [
-        "214034",
-        "uvsflxcs310315",
-        " clear-sky surface uv spectral flux (310-315 nm)"
-    ],
-    [
-        "214035",
-        "uvsflxcs315320",
-        " clear-sky surface uv spectral flux (315-320 nm)"
-    ],
-    [
-        "214036",
-        "uvsflxcs320325",
-        " clear-sky surface uv spectral flux (320-325 nm)"
-    ],
-    [
-        "214037",
-        "uvsflxcs325330",
-        " clear-sky surface uv spectral flux (325-330 nm)"
-    ],
-    [
-        "214038",
-        "uvsflxcs330335",
-        " clear-sky surface uv spectral flux (330-335 nm)"
-    ],
-    [
-        "214039",
-        "uvsflxcs335340",
-        " clear-sky surface uv spectral flux (335-340 nm)"
-    ],
-    [
-        "214040",
-        "uvsflxcs340345",
-        " clear-sky surface uv spectral flux (340-345 nm)"
-    ],
-    [
-        "214041",
-        "uvsflxcs345350",
-        " clear-sky surface uv spectral flux (345-350 nm)"
-    ],
-    [
-        "214042",
-        "uvsflxcs350355",
-        " clear-sky surface uv spectral flux (350-355 nm)"
-    ],
-    [
-        "214043",
-        "uvsflxcs355360",
-        " clear-sky surface uv spectral flux (355-360 nm)"
-    ],
-    [
-        "214044",
-        "uvsflxcs360365",
-        " clear-sky surface uv spectral flux (360-365 nm)"
-    ],
-    [
-        "214045",
-        "uvsflxcs365370",
-        " clear-sky surface uv spectral flux (365-370 nm)"
-    ],
-    [
-        "214046",
-        "uvsflxcs370375",
-        " clear-sky surface uv spectral flux (370-375 nm)"
-    ],
-    [
-        "214047",
-        "uvsflxcs375380",
-        " clear-sky surface uv spectral flux (375-380 nm)"
-    ],
-    [
-        "214048",
-        "uvsflxcs380385",
-        " clear-sky surface uv spectral flux (380-385 nm)"
-    ],
-    [
-        "214049",
-        "uvsflxcs385390",
-        " clear-sky surface uv spectral flux (385-390 nm)"
-    ],
-    [
-        "214050",
-        "uvsflxcs390395",
-        " clear-sky surface uv spectral flux (390-395 nm)"
-    ],
-    [
-        "214051",
-        "uvsflxcs395400",
-        " clear-sky surface uv spectral flux (395-400 nm)"
-    ],
-    [
-        "214052",
-        "aot340",
-        " profile of optical thickness at 340 nm"
-    ],
-    [
-        "215001",
-        "aersrcsss",
-        " source/gain of sea salt aerosol (0.03 - 0.5 um)"
-    ],
-    [
-        "215002",
-        "aersrcssm",
-        " source/gain of sea salt aerosol (0.5 - 5 um)"
-    ],
-    [
-        "215003",
-        "aersrcssl",
-        " source/gain of sea salt aerosol (5 - 20 um)"
-    ],
-    [
-        "215004",
-        "aerddpsss",
-        " dry deposition of sea salt aerosol (0.03 - 0.5 um)"
-    ],
-    [
-        "215005",
-        "aerddpssm",
-        " dry deposition of sea salt aerosol (0.5 - 5 um)"
-    ],
-    [
-        "215006",
-        "aerddpssl",
-        " dry deposition of sea salt aerosol (5 - 20 um)"
-    ],
-    [
-        "215007",
-        "aersdmsss",
-        " sedimentation of sea salt aerosol (0.03 - 0.5 um)"
-    ],
-    [
-        "215008",
-        "aersdmssm",
-        " sedimentation of sea salt aerosol (0.5 - 5 um)"
-    ],
-    [
-        "215009",
-        "aersdmssl",
-        " sedimentation of sea salt aerosol (5 - 20 um)"
-    ],
-    [
-        "215010",
-        "aerwdlssss",
-        " wet deposition of sea salt aerosol (0.03 - 0.5 um) by large-scale precipitation"
-    ],
-    [
-        "215011",
-        "aerwdlsssm",
-        " wet deposition of sea salt aerosol (0.5 - 5 um) by large-scale precipitation"
-    ],
-    [
-        "215012",
-        "aerwdlsssl",
-        " wet deposition of sea salt aerosol (5 - 20 um) by large-scale precipitation"
-    ],
-    [
-        "215013",
-        "aerwdccsss",
-        " wet deposition of sea salt aerosol (0.03 - 0.5 um) by convective precipitation"
-    ],
-    [
-        "215014",
-        "aerwdccssm",
-        " wet deposition of sea salt aerosol (0.5 - 5 um) by convective precipitation"
-    ],
-    [
-        "215015",
-        "aerwdccssl",
-        " wet deposition of sea salt aerosol (5 - 20 um) by convective precipitation"
-    ],
-    [
-        "215016",
-        "aerngtsss",
-        " negative fixer of sea salt aerosol (0.03 - 0.5 um)"
-    ],
-    [
-        "215017",
-        "aerngtssm",
-        " negative fixer of sea salt aerosol (0.5 - 5 um)"
-    ],
-    [
-        "215018",
-        "aerngtssl",
-        " negative fixer of sea salt aerosol (5 - 20 um)"
-    ],
-    [
-        "215019",
-        "aermsssss",
-        " vertically integrated mass of sea salt aerosol (0.03 - 0.5 um)"
-    ],
-    [
-        "215020",
-        "aermssssm",
-        " vertically integrated mass of sea salt aerosol (0.5 - 5 um)"
-    ],
-    [
-        "215021",
-        "aermssssl",
-        " vertically integrated mass of sea salt aerosol (5 - 20 um)"
-    ],
-    [
-        "215022",
-        "aerodsss",
-        " sea salt aerosol (0.03 - 0.5 um) optical depth"
-    ],
-    [
-        "215023",
-        "aerodssm",
-        " sea salt aerosol (0.5 - 5 um) optical depth"
-    ],
-    [
-        "215024",
-        "aerodssl",
-        " sea salt aerosol (5 - 20 um) optical depth"
-    ],
-    [
-        "215025",
-        "aersrcdus",
-        " source/gain of dust aerosol (0.03 - 0.55 um)"
-    ],
-    [
-        "215026",
-        "aersrcdum",
-        " source/gain of dust aerosol (0.55 - 9 um)"
-    ],
-    [
-        "215027",
-        "aersrcdul",
-        " source/gain of dust aerosol (9 - 20 um)"
-    ],
-    [
-        "215028",
-        "aerddpdus",
-        " dry deposition of dust aerosol (0.03 - 0.55 um)"
-    ],
-    [
-        "215029",
-        "aerddpdum",
-        " dry deposition of dust aerosol (0.55 - 9 um)"
-    ],
-    [
-        "215030",
-        "aerddpdul",
-        " dry deposition of dust aerosol (9 - 20 um)"
-    ],
-    [
-        "215031",
-        "aersdmdus",
-        " sedimentation of dust aerosol (0.03 - 0.55 um)"
-    ],
-    [
-        "215032",
-        "aersdmdum",
-        " sedimentation of dust aerosol (0.55 - 9 um)"
-    ],
-    [
-        "215033",
-        "aersdmdul",
-        " sedimentation of dust aerosol (9 - 20 um)"
-    ],
-    [
-        "215034",
-        "aerwdlsdus",
-        " wet deposition of dust aerosol (0.03 - 0.55 um) by large-scale precipitation"
-    ],
-    [
-        "215035",
-        "aerwdlsdum",
-        " wet deposition of dust aerosol (0.55 - 9 um) by large-scale precipitation"
-    ],
-    [
-        "215036",
-        "aerwdlsdul",
-        " wet deposition of dust aerosol (9 - 20 um) by large-scale precipitation"
-    ],
-    [
-        "215037",
-        "aerwdccdus",
-        " wet deposition of dust aerosol (0.03 - 0.55 um) by convective precipitation"
-    ],
-    [
-        "215038",
-        "aerwdccdum",
-        " wet deposition of dust aerosol (0.55 - 9 um) by convective precipitation"
-    ],
-    [
-        "215039",
-        "aerwdccdul",
-        " wet deposition of dust aerosol (9 - 20 um) by convective precipitation"
-    ],
-    [
-        "215040",
-        "aerngtdus",
-        " negative fixer of dust aerosol (0.03 - 0.55 um)"
-    ],
-    [
-        "215041",
-        "aerngtdum",
-        " negative fixer of dust aerosol (0.55 - 9 um)"
-    ],
-    [
-        "215042",
-        "aerngtdul",
-        " negative fixer of dust aerosol (9 - 20 um)"
-    ],
-    [
-        "215043",
-        "aermssdus",
-        " vertically integrated mass of dust aerosol (0.03 - 0.55 um)"
-    ],
-    [
-        "215044",
-        "aermssdum",
-        " vertically integrated mass of dust aerosol (0.55 - 9 um)"
-    ],
-    [
-        "215045",
-        "aermssdul",
-        " vertically integrated mass of dust aerosol (9 - 20 um)"
-    ],
-    [
-        "215046",
-        "aeroddus",
-        " dust aerosol (0.03 - 0.55 um) optical depth"
-    ],
-    [
-        "215047",
-        "aeroddum",
-        " dust aerosol (0.55 - 9 um) optical depth"
-    ],
-    [
-        "215048",
-        "aeroddul",
-        " dust aerosol (9 - 20 um) optical depth"
-    ],
-    [
-        "215049",
-        "aersrcomhphob",
-        " source/gain of hydrophobic organic matter aerosol"
-    ],
-    [
-        "215050",
-        "aersrcomhphil",
-        " source/gain of hydrophilic organic matter aerosol"
-    ],
-    [
-        "215051",
-        "aerddpomhphob",
-        " dry deposition of hydrophobic organic matter aerosol"
-    ],
-    [
-        "215052",
-        "aerddpomhphil",
-        " dry deposition of hydrophilic organic matter aerosol"
-    ],
-    [
-        "215053",
-        "aersdmomhphob",
-        " sedimentation of hydrophobic organic matter aerosol"
-    ],
-    [
-        "215054",
-        "aersdmomhphil",
-        " sedimentation of hydrophilic organic matter aerosol"
-    ],
-    [
-        "215055",
-        "aerwdlsomhphob",
-        " wet deposition of hydrophobic organic matter aerosol by large-scale precipitation"
-    ],
-    [
-        "215056",
-        "aerwdlsomhphil",
-        " wet deposition of hydrophilic organic matter aerosol by large-scale precipitation"
-    ],
-    [
-        "215057",
-        "aerwdccomhphob",
-        " wet deposition of hydrophobic organic matter aerosol by convective precipitation"
-    ],
-    [
-        "215058",
-        "aerwdccomhphil",
-        " wet deposition of hydrophilic organic matter aerosol by convective precipitation"
-    ],
-    [
-        "215059",
-        "aerngtomhphob",
-        " negative fixer of hydrophobic organic matter aerosol"
-    ],
-    [
-        "215060",
-        "aerngtomhphil",
-        " negative fixer of hydrophilic organic matter aerosol"
-    ],
-    [
-        "215061",
-        "aermssomhphob",
-        " vertically integrated mass of hydrophobic organic matter aerosol"
-    ],
-    [
-        "215062",
-        "aermssomhphil",
-        " vertically integrated mass of hydrophilic organic matter aerosol"
-    ],
-    [
-        "215063",
-        "aerodomhphob",
-        " hydrophobic organic matter aerosol optical depth"
-    ],
-    [
-        "215064",
-        "aerodomhphil",
-        " hydrophilic organic matter aerosol optical depth"
-    ],
-    [
-        "215065",
-        "aersrcbchphob",
-        " source/gain of hydrophobic black carbon aerosol"
-    ],
-    [
-        "215066",
-        "aersrcbchphil",
-        " source/gain of hydrophilic black carbon aerosol"
-    ],
-    [
-        "215067",
-        "aerddpbchphob",
-        " dry deposition of hydrophobic black carbon aerosol"
-    ],
-    [
-        "215068",
-        "aerddpbchphil",
-        " dry deposition of hydrophilic black carbon aerosol"
-    ],
-    [
-        "215069",
-        "aersdmbchphob",
-        " sedimentation of hydrophobic black carbon aerosol"
-    ],
-    [
-        "215070",
-        "aersdmbchphil",
-        " sedimentation of hydrophilic black carbon aerosol"
-    ],
-    [
-        "215071",
-        "aerwdlsbchphob",
-        " wet deposition of hydrophobic black carbon aerosol by large-scale precipitation"
-    ],
-    [
-        "215072",
-        "aerwdlsbchphil",
-        " wet deposition of hydrophilic black carbon aerosol by large-scale precipitation"
-    ],
-    [
-        "215073",
-        "aerwdccbchphob",
-        " wet deposition of hydrophobic black carbon aerosol by convective precipitation"
-    ],
-    [
-        "215074",
-        "aerwdccbchphil",
-        " wet deposition of hydrophilic black carbon aerosol by convective precipitation"
-    ],
-    [
-        "215075",
-        "aerngtbchphob",
-        " negative fixer of hydrophobic black carbon aerosol"
-    ],
-    [
-        "215076",
-        "aerngtbchphil",
-        " negative fixer of hydrophilic black carbon aerosol"
-    ],
-    [
-        "215077",
-        "aermssbchphob",
-        " vertically integrated mass of hydrophobic black carbon aerosol"
-    ],
-    [
-        "215078",
-        "aermssbchphil",
-        " vertically integrated mass of hydrophilic black carbon aerosol"
-    ],
-    [
-        "215079",
-        "aerodbchphob",
-        " hydrophobic black carbon aerosol optical depth"
-    ],
-    [
-        "215080",
-        "aerodbchphil",
-        " hydrophilic black carbon aerosol optical depth"
-    ],
-    [
-        "215081",
-        "aersrcsu",
-        " source/gain of sulphate aerosol"
-    ],
-    [
-        "215082",
-        "aerddpsu",
-        " dry deposition of sulphate aerosol"
-    ],
-    [
-        "215083",
-        "aersdmsu",
-        " sedimentation of sulphate aerosol"
-    ],
-    [
-        "215084",
-        "aerwdlssu",
-        " wet deposition of sulphate aerosol by large-scale precipitation"
-    ],
-    [
-        "215085",
-        "aerwdccsu",
-        " wet deposition of sulphate aerosol by convective precipitation"
-    ],
-    [
-        "215086",
-        "aerngtsu",
-        " negative fixer of sulphate aerosol"
-    ],
-    [
-        "215087",
-        "aermsssu",
-        " vertically integrated mass of sulphate aerosol"
-    ],
-    [
-        "215088",
-        "aerodsu",
-        " sulphate aerosol optical depth"
-    ],
-    [
-        "211001",
-        "aermr01diff",
-        "sea salt aerosol (0.03 - 0.5 um) mixing ratio"
-    ],
-    [
-        "211002",
-        "aermr02diff",
-        "sea salt aerosol (0.5 - 5 um) mixing ratio"
-    ],
-    [
-        "211003",
-        "aermr03diff",
-        "sea salt aerosol (5 - 20 um) mixing ratio"
-    ],
-    [
-        "211004",
-        "aermr04diff",
-        "dust aerosol (0.03 - 0.55 um) mixing ratio"
-    ],
-    [
-        "211005",
-        "aermr05diff",
-        "dust aerosol (0.55 - 0.9 um) mixing ratio"
-    ],
-    [
-        "211006",
-        "aermr06diff",
-        "dust aerosol (0.9 - 20 um) mixing ratio"
-    ],
-    [
-        "211007",
-        "aermr07diff",
-        "hydrophobic organic matter aerosol mixing ratio"
-    ],
-    [
-        "211008",
-        "aermr08diff",
-        "hydrophilic organic matter aerosol mixing ratio"
-    ],
-    [
-        "211009",
-        "aermr09diff",
-        "hydrophobic black carbon aerosol mixing ratio"
-    ],
-    [
-        "211010",
-        "aermr10diff",
-        "hydrophilic black carbon aerosol mixing ratio"
-    ],
-    [
-        "211011",
-        "aermr11diff",
-        "sulphate aerosol mixing ratio"
-    ],
-    [
-        "211012",
-        "aermr12diff",
-        "aerosol type 12 mixing ratio"
-    ],
-    [
-        "211016",
-        "aergn01diff",
-        "aerosol type 1 source/gain accumulated"
-    ],
-    [
-        "211017",
-        "aergn02diff",
-        "aerosol type 2 source/gain accumulated"
-    ],
-    [
-        "211018",
-        "aergn03diff",
-        "aerosol type 3 source/gain accumulated"
-    ],
-    [
-        "211019",
-        "aergn04diff",
-        "aerosol type 4 source/gain accumulated"
-    ],
-    [
-        "211020",
-        "aergn05diff",
-        "aerosol type 5 source/gain accumulated"
-    ],
-    [
-        "211021",
-        "aergn06diff",
-        "aerosol type 6 source/gain accumulated"
-    ],
-    [
-        "211022",
-        "aergn07diff",
-        "aerosol type 7 source/gain accumulated"
-    ],
-    [
-        "211023",
-        "aergn08diff",
-        "aerosol type 8 source/gain accumulated"
-    ],
-    [
-        "211024",
-        "aergn09diff",
-        "aerosol type 9 source/gain accumulated"
-    ],
-    [
-        "211025",
-        "aergn10diff",
-        "aerosol type 10 source/gain accumulated"
-    ],
-    [
-        "211026",
-        "aergn11diff",
-        "aerosol type 11 source/gain accumulated"
-    ],
-    [
-        "211027",
-        "aergn12diff",
-        "aerosol type 12 source/gain accumulated"
-    ],
-    [
-        "211031",
-        "aerls01diff",
-        "aerosol type 1 sink/loss accumulated"
-    ],
-    [
-        "211032",
-        "aerls02diff",
-        "aerosol type 2 sink/loss accumulated"
-    ],
-    [
-        "211033",
-        "aerls03diff",
-        "aerosol type 3 sink/loss accumulated"
-    ],
-    [
-        "211034",
-        "aerls04diff",
-        "aerosol type 4 sink/loss accumulated"
-    ],
-    [
-        "211035",
-        "aerls05diff",
-        "aerosol type 5 sink/loss accumulated"
-    ],
-    [
-        "211036",
-        "aerls06diff",
-        "aerosol type 6 sink/loss accumulated"
-    ],
-    [
-        "211037",
-        "aerls07diff",
-        "aerosol type 7 sink/loss accumulated"
-    ],
-    [
-        "211038",
-        "aerls08diff",
-        "aerosol type 8 sink/loss accumulated"
-    ],
-    [
-        "211039",
-        "aerls09diff",
-        "aerosol type 9 sink/loss accumulated"
-    ],
-    [
-        "211040",
-        "aerls10diff",
-        "aerosol type 10 sink/loss accumulated"
-    ],
-    [
-        "211041",
-        "aerls11diff",
-        "aerosol type 11 sink/loss accumulated"
-    ],
-    [
-        "211042",
-        "aerls12diff",
-        "aerosol type 12 sink/loss accumulated"
-    ],
-    [
-        "211052",
-        "aerdepdiff",
-        "dust emission potential"
-    ],
-    [
-        "211053",
-        "aerltsdiff",
-        "lifting threshold speed"
-    ],
-    [
-        "211054",
-        "aersccdiff",
-        "soil clay content"
-    ],
-    [
-        "211064",
-        "tcco2diff",
-        "total column carbon dioxide"
-    ],
-    [
-        "211065",
-        "tcch4diff",
-        "total column methane"
-    ],
-    [
-        "211066",
-        "tcn2odiff",
-        "total column nitrous oxide"
-    ],
-    [
-        "211067",
-        "co2ofdiff",
-        "ocean flux of carbon dioxide"
-    ],
-    [
-        "211068",
-        "co2nbfdiff",
-        "natural biosphere flux of carbon dioxide"
-    ],
-    [
-        "211069",
-        "co2apfdiff",
-        "anthropogenic emissions of carbon dioxide"
-    ],
-    [
-        "211070",
-        "ch4fdiff",
-        "methane surface fluxes"
-    ],
-    [
-        "211071",
-        "kch4diff",
-        "methane loss rate due to radical hydroxyl (oh)"
-    ],
-    [
-        "211080",
-        "co2firediff",
-        "wildfire flux of carbon dioxide"
-    ],
-    [
-        "211081",
-        "cofirediff",
-        "wildfire flux of carbon monoxide"
-    ],
-    [
-        "211082",
-        "ch4firediff",
-        "wildfire flux of methane"
-    ],
-    [
-        "211083",
-        "nmhcfirediff",
-        "wildfire flux of non-methane hydro-carbons"
-    ],
-    [
-        "211084",
-        "h2firediff",
-        "wildfire flux of hydrogen"
-    ],
-    [
-        "211085",
-        "noxfirediff",
-        "wildfire flux of nitrogen oxides nox"
-    ],
-    [
-        "211086",
-        "n2ofirediff",
-        "wildfire flux of nitrous oxide"
-    ],
-    [
-        "211087",
-        "pm2p5firediff",
-        "wildfire flux of particulate matter pm2.5"
-    ],
-    [
-        "211088",
-        "tpmfirediff",
-        "wildfire flux of total particulate matter"
-    ],
-    [
-        "211089",
-        "tcfirediff",
-        "wildfire flux of total carbon in aerosols"
-    ],
-    [
-        "211090",
-        "ocfirediff",
-        "wildfire flux of organic carbon"
-    ],
-    [
-        "211091",
-        "bcfirediff",
-        "wildfire flux of black carbon"
-    ],
-    [
-        "211092",
-        "cfirediff",
-        "wildfire overall flux of burnt carbon"
-    ],
-    [
-        "211093",
-        "c4ffirediff",
-        "wildfire fraction of c4 plants"
-    ],
-    [
-        "211094",
-        "vegfirediff",
-        "wildfire vegetation map index"
-    ],
-    [
-        "211095",
-        "ccfirediff",
-        "wildfire combustion completeness"
-    ],
-    [
-        "211096",
-        "flfirediff",
-        "wildfire fuel load: carbon per unit area"
-    ],
-    [
-        "211097",
-        "offirediff",
-        "wildfire fraction of area observed"
-    ],
-    [
-        "211098",
-        "oafirediff",
-        "wildfire observed area"
-    ],
-    [
-        "211099",
-        "frpfirediff",
-        "wildfire radiative power"
-    ],
-    [
-        "211100",
-        "crfirediff",
-        "wildfire combustion rate"
-    ],
-    [
-        "211125",
-        "tcno2diff",
-        "total column nitrogen dioxide"
-    ],
-    [
-        "211126",
-        "tcso2diff",
-        "total column sulphur dioxide"
-    ],
-    [
-        "211127",
-        "tccodiff",
-        "total column carbon monoxide"
-    ],
-    [
-        "211128",
-        "tchchodiff",
-        "total column formaldehyde"
-    ],
-    [
-        "211129",
-        "noxdiff",
-        "nitrogen oxides"
-    ],
-    [
-        "211130",
-        "tcnoxdiff",
-        "total column nitrogen oxides"
-    ],
-    [
-        "211131",
-        "grg1diff",
-        "reactive tracer 1 mass mixing ratio"
-    ],
-    [
-        "211132",
-        "tcgrg1diff",
-        "total column grg tracer 1"
-    ],
-    [
-        "211133",
-        "grg2diff",
-        "reactive tracer 2 mass mixing ratio"
-    ],
-    [
-        "211134",
-        "tcgrg2diff",
-        "total column grg tracer 2"
-    ],
-    [
-        "211135",
-        "grg3diff",
-        "reactive tracer 3 mass mixing ratio"
-    ],
-    [
-        "211136",
-        "tcgrg3diff",
-        "total column grg tracer 3"
-    ],
-    [
-        "211137",
-        "grg4diff",
-        "reactive tracer 4 mass mixing ratio"
-    ],
-    [
-        "211138",
-        "tcgrg4diff",
-        "total column grg tracer 4"
-    ],
-    [
-        "211139",
-        "grg5diff",
-        "reactive tracer 5 mass mixing ratio"
-    ],
-    [
-        "211140",
-        "tcgrg5diff",
-        "total column grg tracer 5"
-    ],
-    [
-        "211141",
-        "grg6diff",
-        "reactive tracer 6 mass mixing ratio"
-    ],
-    [
-        "211142",
-        "tcgrg6diff",
-        "total column grg tracer 6"
-    ],
-    [
-        "211143",
-        "grg7diff",
-        "reactive tracer 7 mass mixing ratio"
-    ],
-    [
-        "211144",
-        "tcgrg7diff",
-        "total column grg tracer 7"
-    ],
-    [
-        "211145",
-        "grg8diff",
-        "reactive tracer 8 mass mixing ratio"
-    ],
-    [
-        "211146",
-        "tcgrg8diff",
-        "total column grg tracer 8"
-    ],
-    [
-        "211147",
-        "grg9diff",
-        "reactive tracer 9 mass mixing ratio"
-    ],
-    [
-        "211148",
-        "tcgrg9diff",
-        "total column grg tracer 9"
-    ],
-    [
-        "211149",
-        "grg10diff",
-        "reactive tracer 10 mass mixing ratio"
-    ],
-    [
-        "211150",
-        "tcgrg10diff",
-        "total column grg tracer 10"
-    ],
-    [
-        "211151",
-        "sfnoxdiff",
-        "surface flux nitrogen oxides"
-    ],
-    [
-        "211152",
-        "sfno2diff",
-        "surface flux nitrogen dioxide"
-    ],
-    [
-        "211153",
-        "sfso2diff",
-        "surface flux sulphur dioxide"
-    ],
-    [
-        "211154",
-        "sfco2diff",
-        "surface flux carbon monoxide"
-    ],
-    [
-        "211155",
-        "sfhchodiff",
-        "surface flux formaldehyde"
-    ],
-    [
-        "211156",
-        "sfgo3diff",
-        "surface flux gems ozone"
-    ],
-    [
-        "211157",
-        "sfgr1diff",
-        "surface flux reactive tracer 1"
-    ],
-    [
-        "211158",
-        "sfgr2diff",
-        "surface flux reactive tracer 2"
-    ],
-    [
-        "211159",
-        "sfgr3diff",
-        "surface flux reactive tracer 3"
-    ],
-    [
-        "211160",
-        "sfgr4diff",
-        "surface flux reactive tracer 4"
-    ],
-    [
-        "211161",
-        "sfgr5diff",
-        "surface flux reactive tracer 5"
-    ],
-    [
-        "211162",
-        "sfgr6diff",
-        "surface flux reactive tracer 6"
-    ],
-    [
-        "211163",
-        "sfgr7diff",
-        "surface flux reactive tracer 7"
-    ],
-    [
-        "211164",
-        "sfgr8diff",
-        "surface flux reactive tracer 8"
-    ],
-    [
-        "211165",
-        "sfgr9diff",
-        "surface flux reactive tracer 9"
-    ],
-    [
-        "211166",
-        "sfgr10diff",
-        "surface flux reactive tracer 10"
-    ],
-    [
-        "211181",
-        "radiff",
-        "radon"
-    ],
-    [
-        "211182",
-        "sf6diff",
-        "sulphur hexafluoride"
-    ],
-    [
-        "211183",
-        "tcradiff",
-        "total column radon"
-    ],
-    [
-        "211184",
-        "tcsf6diff",
-        "total column sulphur hexafluoride"
-    ],
-    [
-        "211185",
-        "sf6apfdiff",
-        "anthropogenic emissions of sulphur hexafluoride"
-    ],
-    [
-        "211206",
-        "gtco3diff",
-        "gems total column ozone"
-    ],
-    [
-        "211207",
-        "aod550diff",
-        "total aerosol optical depth at 550nm"
-    ],
-    [
-        "211208",
-        "ssaod550diff",
-        "sea salt aerosol optical depth at 550nm"
-    ],
-    [
-        "211209",
-        "duaod550diff",
-        "dust aerosol optical depth at 550nm"
-    ],
-    [
-        "211210",
-        "omaod550diff",
-        "organic matter aerosol optical depth at 550nm"
-    ],
-    [
-        "211211",
-        "bcaod550diff",
-        "black carbon aerosol optical depth at 550nm"
-    ],
-    [
-        "211212",
-        "suaod550diff",
-        "sulphate aerosol optical depth at 550nm"
-    ],
-    [
-        "211213",
-        "aod469diff",
-        "total aerosol optical depth at 469nm"
-    ],
-    [
-        "211214",
-        "aod670diff",
-        "total aerosol optical depth at 670nm"
-    ],
-    [
-        "211215",
-        "aod865diff",
-        "total aerosol optical depth at 865nm"
-    ],
-    [
-        "211216",
-        "aod1240diff",
-        "total aerosol optical depth at 1240nm"
-    ],
-    [
-        "211101",
-        "maxfrpfirediff",
-        "wildfire radiative power maximum"
-    ],
-    [
-        "211102",
-        "so2firediff",
-        "wildfire flux of sulfur dioxide"
-    ],
-    [
-        "211112",
-        "hialkanesfirediff",
-        "wildfire flux of higher alkanes (cnh2n+2, c>=4)"
-    ],
-    [
-        "211111",
-        "hialkenesfirediff",
-        "wildfire flux of higher alkenes (cnh2n, c>=4)"
-    ],
-    [
-        "211110",
-        "toluenefirediff",
-        "wildfire flux of toluene_lump (c7h8+ c6h6 + c8h10)"
-    ],
-    [
-        "211117",
-        "c2h6sfirediff",
-        "wildfire flux of dimethyl sulfide (dms) (c2h6s)"
-    ],
-    [
-        "211116",
-        "nh3firediff",
-        "wildfire flux of ammonia (nh3)"
-    ],
-    [
-        "211115",
-        "c3h6ofirediff",
-        "wildfire flux of acetone (c3h6o)"
-    ],
-    [
-        "211114",
-        "c2h4ofirediff",
-        "wildfire flux of acetaldehyde (c2h4o)"
-    ],
-    [
-        "211113",
-        "ch2ofirediff",
-        "wildfire flux of formaldehyde (ch2o)"
-    ],
-    [
-        "211109",
-        "terpenesfirediff",
-        "wildfire flux of terpenes (c5h8)n"
-    ],
-    [
-        "211108",
-        "c5h8firediff",
-        "wildfire flux of isoprene (c5h8)"
-    ],
-    [
-        "211107",
-        "c3h6firediff",
-        "wildfire flux of propene (c3h6)"
-    ],
-    [
-        "211106",
-        "c2h4firediff",
-        "wildfire flux of ethene (c2h4)"
-    ],
-    [
-        "211105",
-        "c3h8firediff",
-        "wildfire flux of propane (c3h8)"
-    ],
-    [
-        "211104",
-        "c2h5ohfirediff",
-        "wildfire flux of ethanol (c2h5oh)"
-    ],
-    [
-        "211103",
-        "ch3ohfirediff",
-        "wildfire flux of methanol (ch3oh)"
-    ],
-    [
-        "211013",
-        "aermr13diff",
-        "aerosol type 13 mass mixing ratio"
-    ],
-    [
-        "211118",
-        "c2h6firediff",
-        "wildfire flux of ethane (c2h6)"
-    ],
-    [
-        "211119",
-        "alediff",
-        "altitude of emitter"
-    ],
-    [
-        "211120",
-        "aptdiff",
-        "altitude of plume top"
-    ],
-    [
-        "211014",
-        "aermr14diff",
-        "aerosol type 14 mass mixing ratio"
-    ],
-    [
-        "211015",
-        "aermr15diff",
-        "aerosol type 15 mass mixing ratio"
-    ],
-    [
-        "211028",
-        "aerpr03diff",
-        "so4 aerosol precursor mass mixing ratio"
-    ],
-    [
-        "211029",
-        "aerwv01diff",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 1"
-    ],
-    [
-        "211030",
-        "aerwv02diff",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 2"
-    ],
-    [
-        "211043",
-        "emdmsdiff",
-        "dms surface emission"
-    ],
-    [
-        "211044",
-        "aerwv03diff",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 3"
-    ],
-    [
-        "211045",
-        "aerwv04diff",
-        "water vapour mixing ratio for hydrophilic aerosols in mode 4"
-    ],
-    [
-        "210217",
-        "aod340",
-        "total aerosol optical depth at 340 nm"
-    ],
-    [
-        "210218",
-        "aod355",
-        "total aerosol optical depth at 355 nm"
-    ],
-    [
-        "210219",
-        "aod380",
-        "total aerosol optical depth at 380 nm"
-    ],
-    [
-        "210220",
-        "aod400",
-        "total aerosol optical depth at 400 nm"
-    ],
-    [
-        "210221",
-        "aod440",
-        "total aerosol optical depth at 440 nm"
-    ],
-    [
-        "210222",
-        "aod500",
-        "total aerosol optical depth at 500 nm"
-    ],
-    [
-        "210223",
-        "aod532",
-        "total aerosol optical depth at 532 nm"
-    ],
-    [
-        "210224",
-        "aod645",
-        "total aerosol optical depth at 645 nm"
-    ],
-    [
-        "210225",
-        "aod800",
-        "total aerosol optical depth at 800 nm"
-    ],
-    [
-        "210226",
-        "aod858",
-        "total aerosol optical depth at 858 nm"
-    ],
-    [
-        "210227",
-        "aod1020",
-        "total aerosol optical depth at 1020 nm"
-    ],
-    [
-        "210228",
-        "aod1064",
-        "total aerosol optical depth at 1064 nm"
-    ],
-    [
-        "210229",
-        "aod1640",
-        "total aerosol optical depth at 1640 nm"
-    ],
-    [
-        "215089",
-        "accaod550",
-        "accumulated total aerosol optical depth at 550 nm"
-    ],
-    [
-        "215090",
-        "aluvpsn",
-        "effective (snow effect included) uv visible albedo for direct radiation"
-    ],
-    [
-        "215091",
-        "aerdep10si",
-        "10 metre wind speed dust emission potential"
-    ],
-    [
-        "215092",
-        "aerdep10fg",
-        "10 metre wind gustiness dust emission potential"
-    ],
-    [
-        "215093",
-        "aot532",
-        "total aerosol optical thickness at 532 nm"
-    ],
-    [
-        "215094",
-        "naot532",
-        "natural (sea-salt and dust) aerosol optical thickness at 532 nm"
-    ],
-    [
-        "215095",
-        "aaot532",
-        "antropogenic (black carbon, organic matter, sulphate) aerosol optical thickness at 532 nm"
-    ],
-    [
-        "215096",
-        "aodabs340",
-        "total absorption aerosol optical depth at 340 nm"
-    ],
-    [
-        "215097",
-        "aodabs355",
-        "total absorption aerosol optical depth at 355 nm"
-    ],
-    [
-        "215098",
-        "aodabs380",
-        "total absorption aerosol optical depth at 380 nm"
-    ],
-    [
-        "215099",
-        "aodabs400",
-        "total absorption aerosol optical depth at 400 nm"
-    ],
-    [
-        "215100",
-        "aodabs440",
-        "total absorption aerosol optical depth at 440 nm"
-    ],
-    [
-        "215101",
-        "aodabs469",
-        "total absorption aerosol optical depth at 469 nm"
-    ],
-    [
-        "215102",
-        "aodabs500",
-        "total absorption aerosol optical depth at 500 nm"
-    ],
-    [
-        "215103",
-        "aodabs532",
-        "total absorption aerosol optical depth at 532 nm"
-    ],
-    [
-        "215104",
-        "aodabs550",
-        "total absorption aerosol optical depth at 550 nm"
-    ],
-    [
-        "215105",
-        "aodabs645",
-        "total absorption aerosol optical depth at 645 nm"
-    ],
-    [
-        "215106",
-        "aodabs670",
-        "total absorption aerosol optical depth at 670 nm"
-    ],
-    [
-        "215107",
-        "aodabs800",
-        "total absorption aerosol optical depth at 800 nm"
-    ],
-    [
-        "215108",
-        "aodabs858",
-        "total absorption aerosol optical depth at 858 nm"
-    ],
-    [
-        "215109",
-        "aodabs865",
-        "total absorption aerosol optical depth at 865 nm"
-    ],
-    [
-        "215110",
-        "aodabs1020",
-        "total absorption aerosol optical depth at 1020 nm"
-    ],
-    [
-        "215111",
-        "aodabs1064",
-        "total absorption aerosol optical depth at 1064 nm"
-    ],
-    [
-        "215112",
-        "aodabs1240",
-        "total absorption aerosol optical depth at 1240 nm"
-    ],
-    [
-        "215113",
-        "aodabs1640",
-        "total absorption aerosol optical depth at 1640 nm"
-    ],
-    [
-        "215114",
-        "aodfm340",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 340 nm"
-    ],
-    [
-        "215115",
-        "aodfm355",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 355 nm"
-    ],
-    [
-        "215116",
-        "aodfm380",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 380 nm"
-    ],
-    [
-        "215117",
-        "aodfm400",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 400 nm"
-    ],
-    [
-        "215118",
-        "aodfm440",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 440 nm"
-    ],
-    [
-        "215119",
-        "aodfm469",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 469 nm"
-    ],
-    [
-        "215120",
-        "aodfm500",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 500 nm"
-    ],
-    [
-        "215121",
-        "aodfm532",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 532 nm"
-    ],
-    [
-        "215122",
-        "aodfm550",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 550 nm"
-    ],
-    [
-        "215123",
-        "aodfm645",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 645 nm"
-    ],
-    [
-        "215124",
-        "aodfm670",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 670 nm"
-    ],
-    [
-        "215125",
-        "aodfm800",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 800 nm"
-    ],
-    [
-        "215126",
-        "aodfm858",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 858 nm"
-    ],
-    [
-        "215127",
-        "aodfm865",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 865 nm"
-    ],
-    [
-        "215128",
-        "aodfm1020",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 1020 nm"
-    ],
-    [
-        "215129",
-        "aodfm1064",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 1064 nm"
-    ],
-    [
-        "215130",
-        "aodfm1240",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 1240 nm"
-    ],
-    [
-        "215131",
-        "aodfm1640",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 1640 nm"
-    ],
-    [
-        "215132",
-        "ssa340",
-        "single scattering albedo at 340 nm"
-    ],
-    [
-        "215133",
-        "ssa355",
-        "single scattering albedo at 355 nm"
-    ],
-    [
-        "215134",
-        "ssa380",
-        "single scattering albedo at 380 nm"
-    ],
-    [
-        "215135",
-        "ssa400",
-        "single scattering albedo at 400 nm"
-    ],
-    [
-        "215136",
-        "ssa440",
-        "single scattering albedo at 440 nm"
-    ],
-    [
-        "215137",
-        "ssa469",
-        "single scattering albedo at 469 nm"
-    ],
-    [
-        "215138",
-        "ssa500",
-        "single scattering albedo at 500 nm"
-    ],
-    [
-        "215139",
-        "ssa532",
-        "single scattering albedo at 532 nm"
-    ],
-    [
-        "215140",
-        "ssa550",
-        "single scattering albedo at 550 nm"
-    ],
-    [
-        "215141",
-        "ssa645",
-        "single scattering albedo at 645 nm"
-    ],
-    [
-        "215142",
-        "ssa670",
-        "single scattering albedo at 670 nm"
-    ],
-    [
-        "215143",
-        "ssa800",
-        "single scattering albedo at 800 nm"
-    ],
-    [
-        "215144",
-        "ssa858",
-        "single scattering albedo at 858 nm"
-    ],
-    [
-        "215145",
-        "ssa865",
-        "single scattering albedo at 865 nm"
-    ],
-    [
-        "215146",
-        "ssa1020",
-        "single scattering albedo at 1020 nm"
-    ],
-    [
-        "215147",
-        "ssa1064",
-        "single scattering albedo at 1064 nm"
-    ],
-    [
-        "215148",
-        "ssa1240",
-        "single scattering albedo at 1240 nm"
-    ],
-    [
-        "215149",
-        "ssa1640",
-        "single scattering albedo at 1640 nm"
-    ],
-    [
-        "215150",
-        "assimetry340",
-        "assimetry factor at 340 nm"
-    ],
-    [
-        "215151",
-        "assimetry355",
-        "assimetry factor at 355 nm"
-    ],
-    [
-        "215152",
-        "assimetry380",
-        "assimetry factor at 380 nm"
-    ],
-    [
-        "215153",
-        "assimetry400",
-        "assimetry factor at 400 nm"
-    ],
-    [
-        "215154",
-        "assimetry440",
-        "assimetry factor at 440 nm"
-    ],
-    [
-        "215155",
-        "assimetry469",
-        "assimetry factor at 469 nm"
-    ],
-    [
-        "215156",
-        "assimetry500",
-        "assimetry factor at 500 nm"
-    ],
-    [
-        "215157",
-        "assimetry532",
-        "assimetry factor at 532 nm"
-    ],
-    [
-        "215158",
-        "assimetry550",
-        "assimetry factor at 550 nm"
-    ],
-    [
-        "215159",
-        "assimetry645",
-        "assimetry factor at 645 nm"
-    ],
-    [
-        "215160",
-        "assimetry670",
-        "assimetry factor at 670 nm"
-    ],
-    [
-        "215161",
-        "assimetry800",
-        "assimetry factor at 800 nm"
-    ],
-    [
-        "215162",
-        "assimetry858",
-        "assimetry factor at 858 nm"
-    ],
-    [
-        "215163",
-        "assimetry865",
-        "assimetry factor at 865 nm"
-    ],
-    [
-        "215164",
-        "assimetry1020",
-        "assimetry factor at 1020 nm"
-    ],
-    [
-        "215165",
-        "assimetry1064",
-        "assimetry factor at 1064 nm"
-    ],
-    [
-        "215166",
-        "assimetry1240",
-        "assimetry factor at 1240 nm"
-    ],
-    [
-        "215167",
-        "assimetry1640",
-        "assimetry factor at 1640 nm"
-    ],
-    [
-        "215168",
-        "aersrcso2",
-        "source/gain of sulphur dioxide"
-    ],
-    [
-        "215169",
-        "aerddpso2",
-        "dry deposition of sulphur dioxide"
-    ],
-    [
-        "215170",
-        "aersdmso2",
-        "sedimentation of sulphur dioxide"
-    ],
-    [
-        "215171",
-        "aerwdlsso2",
-        "wet deposition of sulphur dioxide by large-scale precipitation"
-    ],
-    [
-        "215172",
-        "aerwdccso2",
-        "wet deposition of sulphur dioxide by convective precipitation"
-    ],
-    [
-        "215173",
-        "aerngtso2",
-        "negative fixer of sulphur dioxide"
-    ],
-    [
-        "215174",
-        "aermssso2",
-        "vertically integrated mass of sulphur dioxide"
-    ],
-    [
-        "215175",
-        "aerodso2",
-        "sulphur dioxide optical depth"
-    ],
-    [
-        "215176",
-        "aodabs2130",
-        "total absorption aerosol optical depth at 2130 nm"
-    ],
-    [
-        "215177",
-        "aodfm2130",
-        "total fine mode (r < 0.5 um) aerosol optical depth at 2130 nm"
-    ],
-    [
-        "215178",
-        "ssa2130",
-        "single scattering albedo at 2130 nm"
-    ],
-    [
-        "215179",
-        "assimetry2130",
-        "assimetry factor at 2130 nm"
-    ],
-    [
-        "210230",
-        "aod2130",
-        "total aerosol optical depth at 2130 nm"
-    ],
-    [
-        "210057",
-        "ocnuc",
-        "mixing ration of organic carbon aerosol, nucleation mode"
-    ],
-    [
-        "210058",
-        "monot",
-        "monoterpene precursor mixing ratio"
-    ],
-    [
-        "210059",
-        "soapr",
-        "secondary organic precursor mixing ratio"
-    ],
-    [
-        "228129",
-        "ssrdc",
-        "surface solar radiation downward clear-sky"
-    ],
-    [
-        "228130",
-        "strdc",
-        "surface thermal radiation downward clear-sky"
-    ],
-    [
-        "228026",
-        "mx2t3",
-        "maximum temperature at 2 metres in the last 3 hours"
-    ],
-    [
-        "228027",
-        "mn2t3",
-        "minimum temperature at 2 metres in the last 3 hours"
-    ],
-    [
-        "228028",
-        "10fg3",
-        "10 metre wind gust in the last 3 hours",
-        "I10FG3"
-    ],
-    [
-        "300001",
-        "pres",
-        "pressure"
-    ],
-    [
-        "300002",
-        "psnm",
-        "pressure reduced to msl"
-    ],
-    [
-        "300003",
-        "tsps",
-        "pressure tendency"
-    ],
-    [
-        "300006",
-        "geop",
-        "geopotential"
-    ],
-    [
-        "300007",
-        "zgeo",
-        "geopotential height"
-    ],
-    [
-        "300008",
-        "gzge",
-        "geometric height"
-    ],
-    [
-        "300011",
-        "temp",
-        "absolute temperature"
-    ],
-    [
-        "300012",
-        "vtmp",
-        "virtual temperature"
-    ],
-    [
-        "300013",
-        "ptmp",
-        "potential temperature"
-    ],
-    [
-        "300014",
-        "psat",
-        "pseudo-adiabatic potential temperature"
-    ],
-    [
-        "300015",
-        "mxtp",
-        "maximum temperature"
-    ],
-    [
-        "300016",
-        "mntp",
-        "minimum temperature"
-    ],
-    [
-        "300017",
-        "tpor",
-        "dew point temperature"
-    ],
-    [
-        "300018",
-        "dptd",
-        "dew point depression"
-    ],
-    [
-        "300019",
-        "lpsr",
-        "lapse rate"
-    ],
-    [
-        "300021",
-        "rds1",
-        "radar spectra(1)"
-    ],
-    [
-        "300022",
-        "rds2",
-        "radar spectra(2)"
-    ],
-    [
-        "300023",
-        "rds3",
-        "radar spectra(3)"
-    ],
-    [
-        "300025",
-        "tpan",
-        "temperature anomaly"
-    ],
-    [
-        "300026",
-        "psan",
-        "pressure anomaly"
-    ],
-    [
-        "300027",
-        "zgan",
-        "geopot height anomaly"
-    ],
-    [
-        "300028",
-        "wvs1",
-        "wave spectra(1)"
-    ],
-    [
-        "300029",
-        "wvs2",
-        "wave spectra(2)"
-    ],
-    [
-        "300030",
-        "wvs3",
-        "wave spectra(3)"
-    ],
-    [
-        "300031",
-        "wind",
-        "wind direction"
-    ],
-    [
-        "300032",
-        "wins",
-        "wind speed"
-    ],
-    [
-        "300033",
-        "uvel",
-        "zonal wind (u)"
-    ],
-    [
-        "300034",
-        "vvel",
-        "meridional wind (v)"
-    ],
-    [
-        "300035",
-        "fcor",
-        "stream function"
-    ],
-    [
-        "300036",
-        "potv",
-        "velocity potential"
-    ],
-    [
-        "300038",
-        "sgvv",
-        "sigma coord vert vel"
-    ],
-    [
-        "300039",
-        "omeg",
-        "omega"
-    ],
-    [
-        "300040",
-        "omg2",
-        "vertical velocity"
-    ],
-    [
-        "300041",
-        "abvo",
-        "absolute vorticity"
-    ],
-    [
-        "300042",
-        "abdv",
-        "absolute divergence"
-    ],
-    [
-        "300043",
-        "vort",
-        "vorticity"
-    ],
-    [
-        "300044",
-        "divg",
-        "divergence"
-    ],
-    [
-        "300045",
-        "vucs",
-        "vertical u-comp shear"
-    ],
-    [
-        "300046",
-        "vvcs",
-        "vert v-comp shear"
-    ],
-    [
-        "300047",
-        "dirc",
-        "direction of current"
-    ],
-    [
-        "300048",
-        "spdc",
-        "speed of current"
-    ],
-    [
-        "300049",
-        "ucpc",
-        "u-component of current"
-    ],
-    [
-        "300050",
-        "vcpc",
-        "v-component of current"
-    ],
-    [
-        "300051",
-        "umes",
-        "specific humidity"
-    ],
-    [
-        "300052",
-        "umrl",
-        "relative humidity"
-    ],
-    [
-        "300053",
-        "hmxr",
-        "humidity mixing ratio"
-    ],
-    [
-        "300054",
-        "agpl",
-        "inst. precipitable water"
-    ],
-    [
-        "300055",
-        "vapp",
-        "vapour pressure"
-    ],
-    [
-        "300056",
-        "sadf",
-        "saturation deficit"
-    ],
-    [
-        "300057",
-        "evap",
-        "evaporation"
-    ],
-    [
-        "300059",
-        "prcr",
-        "precipitation rate"
-    ],
-    [
-        "300060",
-        "thpb",
-        "thunder probability"
-    ],
-    [
-        "300061",
-        "prec",
-        "total precipitation"
-    ],
-    [
-        "300062",
-        "prge",
-        "large scale precipitation"
-    ],
-    [
-        "300063",
-        "prcv",
-        "convective precipitation"
-    ],
-    [
-        "300064",
-        "neve",
-        "snowfall"
-    ],
-    [
-        "300065",
-        "wenv",
-        "wat equiv acc snow depth"
-    ],
-    [
-        "300066",
-        "nvde",
-        "snow depth"
-    ],
-    [
-        "300067",
-        "mxld",
-        "mixed layer depth"
-    ],
-    [
-        "300068",
-        "tthd",
-        "trans thermocline depth"
-    ],
-    [
-        "300069",
-        "mthd",
-        "main thermocline depth"
-    ],
-    [
-        "300070",
-        "mtha",
-        "main thermocline anom"
-    ],
-    [
-        "300071",
-        "cbnv",
-        "cloud cover"
-    ],
-    [
-        "300072",
-        "cvnv",
-        "convective cloud cover"
-    ],
-    [
-        "300073",
-        "lwnv",
-        "low cloud cover"
-    ],
-    [
-        "300074",
-        "mdnv",
-        "medium cloud cover"
-    ],
-    [
-        "300075",
-        "hinv",
-        "high cloud cover"
-    ],
-    [
-        "300076",
-        "wtnv",
-        "cloud water"
-    ],
-    [
-        "300077",
-        "bli",
-        "best lifted index (to 500 hpa)"
-    ],
-    [
-        "300081",
-        "lsmk",
-        "land sea mask"
-    ],
-    [
-        "300082",
-        "dslm",
-        "dev sea_lev from mean"
-    ],
-    [
-        "300083",
-        "zorl",
-        "roughness length"
-    ],
-    [
-        "300084",
-        "albe",
-        "albedo"
-    ],
-    [
-        "300085",
-        "dstp",
-        "deep soil temperature"
-    ],
-    [
-        "300086",
-        "soic",
-        "soil moisture content"
-    ],
-    [
-        "300087",
-        "vege",
-        "vegetation"
-    ],
-    [
-        "300089",
-        "dens",
-        "density"
-    ],
-    [
-        "300091",
-        "icec",
-        "ice concentration"
-    ],
-    [
-        "300092",
-        "icet",
-        "ice thickness"
-    ],
-    [
-        "300093",
-        "iced",
-        "direction of ice drift"
-    ],
-    [
-        "300094",
-        "ices",
-        "speed of ice drift"
-    ],
-    [
-        "300095",
-        "iceu",
-        "u-comp of ice drift"
-    ],
-    [
-        "300096",
-        "icev",
-        "v-comp of ice drift"
-    ],
-    [
-        "300097",
-        "iceg",
-        "ice growth"
-    ],
-    [
-        "300098",
-        "icdv",
-        "ice divergence"
-    ],
-    [
-        "300100",
-        "shcw",
-        "sig hgt com wave/swell"
-    ],
-    [
-        "300101",
-        "wwdi",
-        "direction of wind wave"
-    ],
-    [
-        "300102",
-        "wwsh",
-        "sig hght of wind waves"
-    ],
-    [
-        "300103",
-        "wwmp",
-        "mean period wind waves"
-    ],
-    [
-        "300104",
-        "swdi",
-        "direction of swell wave"
-    ],
-    [
-        "300105",
-        "swsh",
-        "sig height swell waves"
-    ],
-    [
-        "300106",
-        "swmp",
-        "mean period swell waves"
-    ],
-    [
-        "300107",
-        "prwd",
-        "primary wave direction"
-    ],
-    [
-        "300108",
-        "prmp",
-        "prim wave mean period"
-    ],
-    [
-        "300109",
-        "swdi",
-        "second wave direction"
-    ],
-    [
-        "300110",
-        "swmp",
-        "second wave mean period"
-    ],
-    [
-        "300111",
-        "ocas",
-        "short wave absorbed at ground"
-    ],
-    [
-        "300112",
-        "slds",
-        "net long wave at bottom"
-    ],
-    [
-        "300113",
-        "nswr",
-        "net short-wav rad(top)"
-    ],
-    [
-        "300114",
-        "role",
-        "outgoing long wave at top"
-    ],
-    [
-        "300115",
-        "lwrd",
-        "long-wav rad"
-    ],
-    [
-        "300116",
-        "swea",
-        "short wave absorbed by earth/atmosphere"
-    ],
-    [
-        "300117",
-        "glbr",
-        "global radiation"
-    ],
-    [
-        "300121",
-        "clsf",
-        "latent heat flux from surface"
-    ],
-    [
-        "300122",
-        "cssf",
-        "sensible heat flux from surface"
-    ],
-    [
-        "300123",
-        "blds",
-        "bound layer dissipation"
-    ],
-    [
-        "300127",
-        "imag",
-        "image"
-    ],
-    [
-        "300128",
-        "tp2m",
-        "2 metre temperature"
-    ],
-    [
-        "300129",
-        "dp2m",
-        "2 metre dewpoint temperature"
-    ],
-    [
-        "300130",
-        "u10m",
-        "10 metre u-wind component"
-    ],
-    [
-        "300131",
-        "v10m",
-        "10 metre v-wind component"
-    ],
-    [
-        "300132",
-        "topo",
-        "topography"
-    ],
-    [
-        "300133",
-        "gsfp",
-        "geometric mean surface pressure"
-    ],
-    [
-        "300134",
-        "lnsp",
-        "ln surface pressure"
-    ],
-    [
-        "300135",
-        "pslc",
-        "surface pressure"
-    ],
-    [
-        "300136",
-        "pslm",
-        "m s l pressure (mesinger method)"
-    ],
-    [
-        "300137",
-        "mask",
-        "mask"
-    ],
-    [
-        "300138",
-        "mxwu",
-        "maximum u-wind"
-    ],
-    [
-        "300139",
-        "mxwv",
-        "maximum v-wind"
-    ],
-    [
-        "300140",
-        "cape",
-        "convective avail. pot.energy"
-    ],
-    [
-        "300141",
-        "cine",
-        "convective inhib. energy"
-    ],
-    [
-        "300142",
-        "lhcv",
-        "convective latent heating"
-    ],
-    [
-        "300143",
-        "mscv",
-        "convective moisture source"
-    ],
-    [
-        "300144",
-        "scvm",
-        "shallow conv. moisture source"
-    ],
-    [
-        "300145",
-        "scvh",
-        "shallow convective heating"
-    ],
-    [
-        "300146",
-        "mxwp",
-        "maximum wind press. lvl"
-    ],
-    [
-        "300147",
-        "ustr",
-        "storm motion u-component"
-    ],
-    [
-        "300148",
-        "vstr",
-        "storm motion v-component"
-    ],
-    [
-        "300149",
-        "cbnt",
-        "mean cloud cover"
-    ],
-    [
-        "300150",
-        "pcbs",
-        "pressure at cloud base"
-    ],
-    [
-        "300151",
-        "pctp",
-        "pressure at cloud top"
-    ],
-    [
-        "300152",
-        "fzht",
-        "freezing level height"
-    ],
-    [
-        "300153",
-        "fzrh",
-        "freezing level relative humidity"
-    ],
-    [
-        "300154",
-        "fdlt",
-        "flight levels temperature"
-    ],
-    [
-        "300155",
-        "fdlu",
-        "flight levels u-wind"
-    ],
-    [
-        "300156",
-        "fdlv",
-        "flight levels v-wind"
-    ],
-    [
-        "300157",
-        "tppp",
-        "tropopause pressure"
-    ],
-    [
-        "300158",
-        "tppt",
-        "tropopause temperature"
-    ],
-    [
-        "300159",
-        "tppu",
-        "tropopause u-wind component"
-    ],
-    [
-        "300160",
-        "tppv",
-        "tropopause v-wind component"
-    ],
-    [
-        "300162",
-        "gvdu",
-        "gravity wave drag du/dt"
-    ],
-    [
-        "300163",
-        "gvdv",
-        "gravity wave drag dv/dt"
-    ],
-    [
-        "300164",
-        "gvus",
-        "gravity wave drag sfc zonal stress"
-    ],
-    [
-        "300165",
-        "gvvs",
-        "gravity wave drag sfc meridional stress"
-    ],
-    [
-        "300167",
-        "dvsh",
-        "divergence of specific humidity"
-    ],
-    [
-        "300168",
-        "hmfc",
-        "horiz. moisture flux conv."
-    ],
-    [
-        "300169",
-        "vmfl",
-        "vert. integrated moisture flux conv."
-    ],
-    [
-        "300170",
-        "vadv",
-        "vertical moisture advection"
-    ],
-    [
-        "300171",
-        "nhcm",
-        "neg. hum. corr. moisture source"
-    ],
-    [
-        "300172",
-        "lglh",
-        "large scale latent heating"
-    ],
-    [
-        "300173",
-        "lgms",
-        "large scale moisture source"
-    ],
-    [
-        "300174",
-        "smav",
-        "soil moisture availability"
-    ],
-    [
-        "300175",
-        "tgrz",
-        "soil temperature of root zone"
-    ],
-    [
-        "300176",
-        "bslh",
-        "bare soil latent heat"
-    ],
-    [
-        "300177",
-        "evpp",
-        "potential sfc evaporation"
-    ],
-    [
-        "300178",
-        "rnof",
-        "runoff"
-    ],
-    [
-        "300179",
-        "pitp",
-        "interception loss"
-    ],
-    [
-        "300180",
-        "vpca",
-        "vapor pressure of canopy air space"
-    ],
-    [
-        "300181",
-        "qsfc",
-        "surface spec humidity"
-    ],
-    [
-        "300182",
-        "ussl",
-        "soil wetness of surface"
-    ],
-    [
-        "300183",
-        "uzrs",
-        "soil wetness of root zone"
-    ],
-    [
-        "300184",
-        "uzds",
-        "soil wetness of drainage zone"
-    ],
-    [
-        "300185",
-        "amdl",
-        "storage on canopy"
-    ],
-    [
-        "300186",
-        "amsl",
-        "storage on ground"
-    ],
-    [
-        "300187",
-        "tsfc",
-        "surface temperature"
-    ],
-    [
-        "300188",
-        "tems",
-        "surface absolute temperature"
-    ],
-    [
-        "300189",
-        "tcas",
-        "temperature of canopy air space"
-    ],
-    [
-        "300190",
-        "ctmp",
-        "temperature at canopy"
-    ],
-    [
-        "300191",
-        "tgsc",
-        "ground/surface cover temperature"
-    ],
-    [
-        "300192",
-        "uves",
-        "surface zonal wind (u)"
-    ],
-    [
-        "300193",
-        "usst",
-        "surface zonal wind stress"
-    ],
-    [
-        "300194",
-        "vves",
-        "surface meridional wind (v)"
-    ],
-    [
-        "300195",
-        "vsst",
-        "surface meridional wind stress"
-    ],
-    [
-        "300196",
-        "suvf",
-        "surface momentum flux"
-    ],
-    [
-        "300197",
-        "iswf",
-        "incident short wave flux"
-    ],
-    [
-        "300198",
-        "ghfl",
-        "time ave ground ht flx"
-    ],
-    [
-        "300200",
-        "lwbc",
-        "net long wave at bottom (clear)"
-    ],
-    [
-        "300201",
-        "lwtc",
-        "outgoing long wave at top (clear)"
-    ],
-    [
-        "300202",
-        "swec",
-        "short wv absrbd by earth/atmos (clear)"
-    ],
-    [
-        "300203",
-        "ocac",
-        "short wave absorbed at ground (clear)"
-    ],
-    [
-        "300205",
-        "lwrh",
-        "long wave radiative heating"
-    ],
-    [
-        "300206",
-        "swrh",
-        "short wave radiative heating"
-    ],
-    [
-        "300207",
-        "olis",
-        "downward long wave at bottom"
-    ],
-    [
-        "300208",
-        "olic",
-        "downward long wave at bottom (clear)"
-    ],
-    [
-        "300209",
-        "ocis",
-        "downward short wave at ground"
-    ],
-    [
-        "300210",
-        "ocic",
-        "downward short wave at ground (clear)"
-    ],
-    [
-        "300211",
-        "oles",
-        "upward long wave at bottom"
-    ],
-    [
-        "300212",
-        "oces",
-        "upward short wave at ground"
-    ],
-    [
-        "300213",
-        "swgc",
-        "upward short wave at ground (clear)"
-    ],
-    [
-        "300214",
-        "roce",
-        "upward short wave at top"
-    ],
-    [
-        "300215",
-        "swtc",
-        "upward short wave at top (clear)"
-    ],
-    [
-        "300218",
-        "hhdf",
-        "horizontal heating diffusion"
-    ],
-    [
-        "300219",
-        "hmdf",
-        "horizontal moisture diffusion"
-    ],
-    [
-        "300220",
-        "hddf",
-        "horizontal divergence diffusion"
-    ],
-    [
-        "300221",
-        "hvdf",
-        "horizontal vorticity diffusion"
-    ],
-    [
-        "300222",
-        "vdms",
-        "vertical diff. moisture source"
-    ],
-    [
-        "300223",
-        "vdfu",
-        "vertical diffusion du/dt"
-    ],
-    [
-        "300224",
-        "vdfv",
-        "vertical diffusion dv/dt"
-    ],
-    [
-        "300225",
-        "vdfh",
-        "vertical diffusion heating"
-    ],
-    [
-        "300226",
-        "umrs",
-        "surface relative humidity"
-    ],
-    [
-        "300227",
-        "vdcc",
-        "vertical dist total cloud cover"
-    ],
-    [
-        "300230",
-        "usmt",
-        "time mean surface zonal wind (u)"
-    ],
-    [
-        "300231",
-        "vsmt",
-        "time mean surface meridional wind (v)"
-    ],
-    [
-        "300232",
-        "tsmt",
-        "time mean surface absolute temperature"
-    ],
-    [
-        "300233",
-        "rsmt",
-        "time mean surface relative humidity"
-    ],
-    [
-        "300234",
-        "atmt",
-        "time mean absolute temperature"
-    ],
-    [
-        "300235",
-        "stmt",
-        "time mean deep soil temperature"
-    ],
-    [
-        "300236",
-        "ommt",
-        "time mean derived omega"
-    ],
-    [
-        "300237",
-        "dvmt",
-        "time mean divergence"
-    ],
-    [
-        "300238",
-        "zhmt",
-        "time mean geopotential height"
-    ],
-    [
-        "300239",
-        "lnmt",
-        "time mean log surface pressure"
-    ],
-    [
-        "300240",
-        "mkmt",
-        "time mean mask"
-    ],
-    [
-        "300241",
-        "vvmt",
-        "time mean meridional wind (v)"
-    ],
-    [
-        "300242",
-        "omtm",
-        "time mean omega"
-    ],
-    [
-        "300243",
-        "ptmt",
-        "time mean potential temperature"
-    ],
-    [
-        "300244",
-        "pcmt",
-        "time mean precip. water"
-    ],
-    [
-        "300245",
-        "rhmt",
-        "time mean relative humidity"
-    ],
-    [
-        "300246",
-        "mpmt",
-        "time mean sea level pressure"
-    ],
-    [
-        "300247",
-        "simt",
-        "time mean sigmadot"
-    ],
-    [
-        "300248",
-        "uemt",
-        "time mean specific humidity"
-    ],
-    [
-        "300249",
-        "fcmt",
-        "time mean stream function"
-    ],
-    [
-        "300250",
-        "psmt",
-        "time mean surface pressure"
-    ],
-    [
-        "300251",
-        "tmmt",
-        "time mean surface temperature"
-    ],
-    [
-        "300252",
-        "pvmt",
-        "time mean velocity potential"
-    ],
-    [
-        "300253",
-        "tvmt",
-        "time mean virtual temperature"
-    ],
-    [
-        "300254",
-        "vtmt",
-        "time mean vorticity"
-    ],
-    [
-        "300255",
-        "uvmt",
-        "time mean zonal wind (u)"
-    ],
-    [
-        "85001156",
-        "prec_convec",
-        "total convective precipitation"
-    ],
-    [
-        "85001157",
-        "prec_gde_ech",
-        "total large scale precipitation"
-    ],
-    [
-        "85001160",
-        "cape_ins",
-        "convective available potential energy instantaneous"
-    ],
-    [
-        "140211",
-        "phiaw",
-        "normalized energy flux into waves"
-    ],
-    [
-        "140212",
-        "phioc",
-        "normalized energy flux into ocean"
-    ],
-    [
-        "140213",
-        "tla",
-        "turbulent langmuir number"
-    ],
-    [
-        "140214",
-        "tauoc",
-        "normalized stress into ocean"
-    ],
-    [
-        "228081",
-        "aco2gpp",
-        "accumulated carbon dioxide gross primary production"
-    ],
-    [
-        "228082",
-        "aco2rec",
-        "accumulated carbon dioxide ecosystem respiration"
-    ],
-    [
-        "228083",
-        "fco2nee",
-        "flux of carbon dioxide net ecosystem exchange"
-    ],
-    [
-        "228084",
-        "fco2gpp",
-        "flux of carbon dioxide gross primary production"
-    ],
-    [
-        "228085",
-        "fco2rec",
-        "flux of carbon dioxide ecosystem respiration"
-    ],
-    [
-        "210231",
-        "c7h8fire",
-        "wildfire flux of toluene (c7h8)"
-    ],
-    [
-        "210232",
-        "c6h6fire",
-        "wildfire flux of benzene (c6h6)"
-    ],
-    [
-        "210233",
-        "c8h10fire",
-        "wildfire flux of xylene (c8h10)"
-    ],
-    [
-        "210234",
-        "c4h8fire",
-        "wildfire flux of butenes (c4h8)"
-    ],
-    [
-        "210235",
-        "c5h10fire",
-        "wildfire flux of pentenes (c5h10)"
-    ],
-    [
-        "210236",
-        "c6h12fire",
-        "wildfire flux of hexene (c6h12)"
-    ],
-    [
-        "210237",
-        "c8h16fire",
-        "wildfire flux of octene (c8h16)"
-    ],
-    [
-        "210238",
-        "c4h10fire",
-        "wildfire flux of butanes (c4h10)"
-    ],
-    [
-        "210239",
-        "c5h12fire",
-        "wildfire flux of pentanes (c5h12)"
-    ],
-    [
-        "210240",
-        "c6h14fire",
-        "wildfire flux of hexanes (c6h14)"
-    ],
-    [
-        "210241",
-        "c7h16fire",
-        "wildfire flux of heptane (c7h16)"
-    ],
-    [
-        "228242",
-        "fdif",
-        "surface solar radiation diffuse total sky"
-    ],
-    [
-        "228243",
-        "cdif",
-        "surface solar radiation diffuse clear-sky"
-    ],
-    [
-        "228244",
-        "aldr",
-        "surface albedo of direct radiation"
-    ],
-    [
-        "228245",
-        "aldf",
-        "surface albedo of diffuse radiation"
-    ],
-    [
-        "230008",
-        "srovar",
-        "surface runoff (variable resolution)"
-    ],
-    [
-        "230009",
-        "ssrovar",
-        "sub-surface runoff (variable resolution)"
-    ],
-    [
-        "230174",
-        "alvar",
-        "albedo (variable resolution)"
-    ],
-    [
-        "230228",
-        "tpvar",
-        "total precipitation (variable resolution)"
-    ],
-    [
-        "210072",
-        "pm1",
-        "particulate matter d < 1 um"
-    ],
-    [
-        "210073",
-        "pm2p5",
-        "particulate matter d < 2.5 um"
-    ],
-    [
-        "210074",
-        "pm10",
-        "particulate matter d < 10 um"
-    ],
-    [
-        "210186",
-        "aluvpi",
-        "uv visible albedo for direct radiation, isotropic component "
-    ],
-    [
-        "210187",
-        "aluvpv",
-        "uv visible albedo for direct radiation, volumetric component "
-    ],
-    [
-        "210188",
-        "aluvpg",
-        "uv visible albedo for direct radiation, geometric component "
-    ],
-    [
-        "210189",
-        "alnipi",
-        "near ir albedo for direct radiation, isotropic component "
-    ],
-    [
-        "210190",
-        "alnipv",
-        "near ir albedo for direct radiation, volumetric component"
-    ],
-    [
-        "210191",
-        "alnipg",
-        "near ir albedo for direct radiation, geometric component "
-    ],
-    [
-        "210192",
-        "aluvdi",
-        "uv visible albedo for diffuse radiation, isotropic component "
-    ],
-    [
-        "210193",
-        "aluvdv",
-        "uv visible albedo for diffuse radiation, volumetric component "
-    ],
-    [
-        "210194",
-        "aluvdg",
-        "uv visible albedo for diffuse radiation, geometric component "
-    ],
-    [
-        "210195",
-        "alnidi",
-        "near ir albedo for diffuse radiation, isotropic component "
-    ],
-    [
-        "210196",
-        "alnidv",
-        "near ir albedo for diffuse radiation, volumetric component "
-    ],
-    [
-        "210197",
-        "alnidg",
-        "near ir albedo for diffuse radiation, geometric component "
-    ],
-    [
-        "228040",
-        "swi1",
-        "soil wetness index in layer 1"
-    ],
-    [
-        "228041",
-        "swi2",
-        "soil wetness index in layer 2"
-    ],
-    [
-        "228042",
-        "swi3",
-        "soil wetness index in layer 3"
-    ],
-    [
-        "228043",
-        "swi4",
-        "soil wetness index in layer 4"
-    ],
-    [
-        "228255",
-        "tcclw",
-        "surface long wave-effective total cloudiness"
-    ],
-    [
-        "228248",
-        "tccsw",
-        "surface short wave-effective total cloudiness"
-    ],
-    [
-        "260510",
-        "clbt",
-        "cloudy brightness temperature"
-    ],
-    [
-        "260511",
-        "csbt",
-        "clear-sky brightness temperature"
-    ],
-    [
-        "260257",
-        "ccl",
-        "cloud cover"
-    ],
-    [
-        "240011",
-        "chcross",
-        "cross sectional area of flow in channel"
-    ],
-    [
-        "240012",
-        "chside",
-        "side flow into river channel"
-    ],
-    [
-        "240013",
-        "dis",
-        "discharge from rivers or streams"
-    ],
-    [
-        "240014",
-        "rivsto",
-        "river storage of water"
-    ],
-    [
-        "240015",
-        "fldsto",
-        "floodplain storage of water"
-    ],
-    [
-        "240016",
-        "fldfrc",
-        "water fraction"
-    ],
-    [
-        "240017",
-        "dslr",
-        "days since last observation"
-    ],
-    [
-        "240018",
-        "frost",
-        "frost index"
-    ],
-    [
-        "240020",
-        "woss",
-        "depth of water on soil surface"
-    ],
-    [
-        "240021",
-        "tpups",
-        "upstream accumulated precipitation"
-    ],
-    [
-        "240022",
-        "smups",
-        "upstream accumulated snow melt"
-    ],
-    [
-        "260258",
-        "evarate",
-        "evaporation rate"
-    ],
-    [
-        "240026",
-        "sd_elev",
-        "snow depth at elevation bands"
-    ],
-    [
-        "260242",
-        "2r",
-        "surface air relative humidity"
-    ],
-    [
-        "230021",
-        "fdirvar",
-        "total sky direct solar radiation at surface (variable resolution)"
-    ],
-    [
-        "230022",
-        "cdirvar",
-        "clear-sky direct solar radiation at surface (variable resolution)"
-    ],
-    [
-        "210079",
-        "vafire",
-        "wildfire viewing angle of observation"
-    ],
-    [
-        "228229",
-        "smos_tb_cdfa",
-        "smos first brightness temperature bias correction parameter"
-    ],
-    [
-        "228230",
-        "smos_tb_cdfb",
-        "smos second brightness temperature bias correction parameter"
-    ],
-    [
-        "174186",
-        "vlca",
-        "very low cloud amount"
-    ],
-    [
-        "174142",
-        "lsrrate",
-        "large scale rainfall rate"
-    ],
-    [
-        "174240",
-        "lsfrate",
-        "large scale snowfall rate"
-    ],
-    [
-        "174143",
-        "crfrate",
-        "convective rainfall rate"
-    ],
-    [
-        "174239",
-        "csfrate",
-        "convective snowfall rate"
-    ],
-    [
-        "174052",
-        "rhum",
-        "relative humidity at 1.5m"
-    ],
-    [
-        "174025",
-        "vis15",
-        "visibility at 1.5m"
-    ],
-    [
-        "174248",
-        "tccro",
-        "total cloud amount - random overlap"
-    ],
-    [
-        "174010",
-        "sswcsdown",
-        "clear-sky (ii) down surface sw flux"
-    ],
-    [
-        "174013",
-        "sswcsup",
-        "clear-sky (ii) up surface sw flux"
-    ],
-    [
-        "174249",
-        "tcclwr",
-        "total cloud amount in lw radiation"
-    ],
-    [
-        "174051",
-        "mx15t",
-        "maximum temperature at 1.5m since previous post-processing"
-    ],
-    [
-        "174050",
-        "mn15t",
-        "minimum temperature at 1.5m since previous post-processing"
-    ],
-    [
-        "174116",
-        "swrsurf",
-        "short wave radiation flux at surface"
-    ],
-    [
-        "174117",
-        "swrtop",
-        "short wave radiation flux at top of atmosphere"
-    ],
-    [
-        "174137",
-        "tcwvap",
-        "total column water vapour"
-    ],
-    [
-        "140080",
-        "wx1",
-        "wave experimental parameter 1"
-    ],
-    [
-        "140081",
-        "wx2",
-        "wave experimental parameter 2"
-    ],
-    [
-        "140082",
-        "wx3",
-        "wave experimental parameter 3"
-    ],
-    [
-        "140083",
-        "wx4",
-        "wave experimental parameter 4"
-    ],
-    [
-        "140084",
-        "wx5",
-        "wave experimental parameter 5"
-    ],
-    [
-        "140121",
-        "swh1",
-        "significant wave height of first swell partition"
-    ],
-    [
-        "140122",
-        "mwd1",
-        "mean wave direction of first swell partition"
-    ],
-    [
-        "140123",
-        "mwp1",
-        "mean wave period of first swell partition"
-    ],
-    [
-        "140124",
-        "swh2",
-        "significant wave height of second swell partition"
-    ],
-    [
-        "260256",
-        "hindex",
-        "haines index"
-    ],
-    [
-        "140125",
-        "mwd2",
-        "mean wave direction of second swell partition"
-    ],
-    [
-        "140126",
-        "mwp2",
-        "mean wave period of second swell partition"
-    ],
-    [
-        "140127",
-        "swh3",
-        "significant wave height of third swell partition"
-    ],
-    [
-        "260255",
-        "aptmp",
-        "apparent temperature"
-    ],
-    [
-        "140128",
-        "mwd3",
-        "mean wave direction of third swell partition"
-    ],
-    [
-        "140129",
-        "mwp3",
-        "mean wave period of third swell partition"
-    ],
-    [
-        "140208",
-        "wstar",
-        "free convective velocity over the oceans"
-    ],
-    [
-        "140209",
-        "rhoao",
-        "air density over the oceans"
-    ],
-    [
-        "140210",
-        "mswsi",
-        "mean square wave strain in sea ice"
-    ],
-    [
-        "260530",
-        "scaled radiance"
-    ],
-    [
-        "260531",
-        "scaled albedo"
-    ],
-    [
-        "260532",
-        "scaled brightness temperature"
-    ],
-    [
-        "260533",
-        "scaled precipitable water"
-    ],
-    [
-        "260534",
-        "scaled lifted index"
-    ],
-    [
-        "260535",
-        "scaled cloud top pressure"
-    ],
-    [
-        "260536",
-        "scaled skin temperature"
-    ],
-    [
-        "260537",
-        "cloud mask"
-    ],
-    [
-        "260538",
-        "pixel scene type"
-    ],
-    [
-        "260539",
-        "fire detection indicator"
-    ],
-    [
-        "260550",
-        "cloudy radiance (with respect to wave number)"
-    ],
-    [
-        "260551",
-        "clear-sky radiance (with respect to wave number)"
-    ],
-    [
-        "260552",
-        "wind speed"
-    ],
-    [
-        "260553",
-        "aerosol optical thickness at 0.635 um"
-    ],
-    [
-        "260554",
-        "aerosol optical thickness at 0.810 um"
-    ],
-    [
-        "260555",
-        "aerosol optical thickness at 1.640 um"
-    ],
-    [
-        "260556",
-        "angstrom coefficient"
-    ],
-    [
-        "228032",
-        "asn",
-        "snow albedo"
-    ],
-    [
-        "228205",
-        "ro",
-        "water runoff and drainage"
-    ],
-    [
-        "228086",
-        "sm20",
-        "soil moisture top 20 cm"
-    ],
-    [
-        "228087",
-        "sm100",
-        "soil moisture top 100 cm"
-    ],
-    [
-        "228095",
-        "st20",
-        "soil temperature top 20 cm"
-    ],
-    [
-        "228096",
-        "st100",
-        "soil temperature top 100 cm"
-    ],
-    [
-        "217003",
-        "h2o2",
-        "hydrogen peroxide"
-    ],
-    [
-        "217004",
-        "ch4",
-        "methane"
-    ],
-    [
-        "217006",
-        "hno3",
-        "nitric acid"
-    ],
-    [
-        "217007",
-        "ch3ooh",
-        "methyl peroxide"
-    ],
-    [
-        "217009",
-        "par",
-        "paraffins"
-    ],
-    [
-        "217010",
-        "c2h4",
-        "ethene"
-    ],
-    [
-        "217011",
-        "ole",
-        "olefins"
-    ],
-    [
-        "217012",
-        "ald2",
-        "aldehydes"
-    ],
-    [
-        "217013",
-        "pan",
-        "peroxyacetyl nitrate"
-    ],
-    [
-        "217014",
-        "rooh",
-        "peroxides"
-    ],
-    [
-        "217015",
-        "onit",
-        "organic nitrates"
-    ],
-    [
-        "217016",
-        "c5h8",
-        "isoprene"
-    ],
-    [
-        "217018",
-        "dms",
-        "dimethyl sulfide"
-    ],
-    [
-        "217019",
-        "nh3",
-        "ammonia"
-    ],
-    [
-        "217020",
-        "so4",
-        "sulfate"
-    ],
-    [
-        "217021",
-        "nh4",
-        "ammonium"
-    ],
-    [
-        "217022",
-        "msa",
-        "methane sulfonic acid"
-    ],
-    [
-        "217023",
-        "ch3cocho",
-        "methyl glyoxal"
-    ],
-    [
-        "217024",
-        "o3s",
-        "stratospheric ozone"
-    ],
-    [
-        "217026",
-        "pb",
-        "lead"
-    ],
-    [
-        "217027",
-        "no",
-        "nitrogen monoxide"
-    ],
-    [
-        "217028",
-        "ho2",
-        "hydroperoxy radical"
-    ],
-    [
-        "217029",
-        "ch3o2",
-        "methylperoxy radical"
-    ],
-    [
-        "217030",
-        "oh",
-        "hydroxyl radical"
-    ],
-    [
-        "217032",
-        "no3",
-        "nitrate radical"
-    ],
-    [
-        "217033",
-        "n2o5",
-        "dinitrogen pentoxide"
-    ],
-    [
-        "217034",
-        "ho2no2",
-        "pernitric acid"
-    ],
-    [
-        "217035",
-        "c2o3",
-        "peroxy acetyl radical"
-    ],
-    [
-        "217036",
-        "ror",
-        "organic ethers"
-    ],
-    [
-        "217037",
-        "rxpar",
-        "par budget corrector"
-    ],
-    [
-        "217038",
-        "xo2",
-        "no to no2 operator"
-    ],
-    [
-        "217039",
-        "xo2n",
-        "no to alkyl nitrate operator"
-    ],
-    [
-        "217040",
-        "nh2",
-        "amine"
-    ],
-    [
-        "217041",
-        "psc",
-        "polar stratospheric cloud"
-    ],
-    [
-        "217042",
-        "ch3oh",
-        "methanol"
-    ],
-    [
-        "217043",
-        "hcooh",
-        "formic acid"
-    ],
-    [
-        "217044",
-        "mcooh",
-        "methacrylic acid"
-    ],
-    [
-        "217045",
-        "c2h6",
-        "ethane"
-    ],
-    [
-        "217046",
-        "c2h5oh",
-        "ethanol"
-    ],
-    [
-        "217047",
-        "c3h8",
-        "propane"
-    ],
-    [
-        "217048",
-        "c3h6",
-        "propene"
-    ],
-    [
-        "217049",
-        "c10h16",
-        "terpenes"
-    ],
-    [
-        "217050",
-        "ispd",
-        "methacrolein mvk"
-    ],
-    [
-        "217051",
-        "no3_a",
-        "nitrate"
-    ],
-    [
-        "217052",
-        "ch3coch3",
-        "acetone"
-    ],
-    [
-        "217053",
-        "aco2",
-        "acetone product"
-    ],
-    [
-        "217054",
-        "ic3h7o2",
-        "ic3h7o2"
-    ],
-    [
-        "217055",
-        "hypropo2",
-        "hypropo2"
-    ],
-    [
-        "217056",
-        "noxa",
-        "nitrogen oxides transp"
-    ],
-    [
-        "218003",
-        "tc_h2o2",
-        "total column hydrogen peroxide"
-    ],
-    [
-        "218004",
-        "tc_ch4",
-        "total column methane"
-    ],
-    [
-        "218006",
-        "tc_hno3",
-        "total column nitric acid"
-    ],
-    [
-        "218007",
-        "tc_ch3ooh",
-        "total column methyl peroxide"
-    ],
-    [
-        "218009",
-        "tc_par",
-        "total column paraffins"
-    ],
-    [
-        "218010",
-        "tc_c2h4",
-        "total column ethene"
-    ],
-    [
-        "218011",
-        "tc_ole",
-        "total column olefins"
-    ],
-    [
-        "218012",
-        "tc_ald2",
-        "total column aldehydes"
-    ],
-    [
-        "218013",
-        "tc_pan",
-        "total column  peroxyacetyl nitrate"
-    ],
-    [
-        "218014",
-        "tc_rooh",
-        "total column peroxides"
-    ],
-    [
-        "218015",
-        "tc_onit",
-        "total column organic nitrates"
-    ],
-    [
-        "218016",
-        "tc_c5h8",
-        "total column  isoprene"
-    ],
-    [
-        "218018",
-        "tc_dms",
-        "total column dimethyl sulfide"
-    ],
-    [
-        "218019",
-        "tc_nh3",
-        "total column ammonia"
-    ],
-    [
-        "218020",
-        "tc_so4",
-        "total column  sulfate"
-    ],
-    [
-        "218021",
-        "tc_nh4",
-        "total column ammonium"
-    ],
-    [
-        "218022",
-        "tc_msa",
-        "total column  methane sulfonic acid"
-    ],
-    [
-        "218023",
-        "tc_ch3cocho",
-        "total column methyl glyoxal"
-    ],
-    [
-        "218024",
-        "tc_o3s",
-        "total column stratospheric ozone"
-    ],
-    [
-        "218026",
-        "tc_pb",
-        "total column  lead"
-    ],
-    [
-        "218027",
-        "tc_no",
-        "total column nitrogen monoxide"
-    ],
-    [
-        "218028",
-        "tc_ho2",
-        "total column hydroperoxy radical"
-    ],
-    [
-        "218029",
-        "tc_ch3o2",
-        "total column methylperoxy radical"
-    ],
-    [
-        "218030",
-        "tc_oh",
-        "total column hydroxyl radical"
-    ],
-    [
-        "218032",
-        "tc_no3",
-        "total column nitrate radical"
-    ],
-    [
-        "218033",
-        "tc_n2o5",
-        "total column dinitrogen pentoxide"
-    ],
-    [
-        "218034",
-        "tc_ho2no2",
-        "total column pernitric acid"
-    ],
-    [
-        "218035",
-        "tc_c2o3",
-        "total column peroxy acetyl radical"
-    ],
-    [
-        "218036",
-        "tc_ror",
-        "total column  organic ethers"
-    ],
-    [
-        "218037",
-        "tc_rxpar",
-        "total column par budget corrector"
-    ],
-    [
-        "218038",
-        "tc_xo2",
-        "total column no to no2 operator"
-    ],
-    [
-        "218039",
-        "tc_xo2n",
-        "total column no to alkyl nitrate operator"
-    ],
-    [
-        "218040",
-        "tc_nh2",
-        "total column amine"
-    ],
-    [
-        "218041",
-        "tc_psc",
-        "total column  polar stratospheric cloud"
-    ],
-    [
-        "218042",
-        "tc_ch3oh",
-        "total column methanol"
-    ],
-    [
-        "218043",
-        "tc_hcooh",
-        "total column formic acid"
-    ],
-    [
-        "218044",
-        "tc_mcooh",
-        "total column  methacrylic acid"
-    ],
-    [
-        "218045",
-        "tc_c2h6",
-        "total column  ethane"
-    ],
-    [
-        "218046",
-        "tc_c2h5oh",
-        "total column ethanol"
-    ],
-    [
-        "218047",
-        "tc_c3h8",
-        "total column propane"
-    ],
-    [
-        "218048",
-        "tc_c3h6",
-        "total column propene"
-    ],
-    [
-        "218049",
-        "tc_c10h16",
-        "total column terpenes"
-    ],
-    [
-        "218050",
-        "tc_ispd",
-        "total column methacrolein mvk"
-    ],
-    [
-        "218051",
-        "tc_no3_a",
-        "total column nitrate"
-    ],
-    [
-        "218052",
-        "tc_ch3coch3",
-        "total column acetone"
-    ],
-    [
-        "218053",
-        "tc_aco2",
-        "total column acetone product"
-    ],
-    [
-        "218054",
-        "tc_ic3h7o2",
-        "total column ic3h7o2"
-    ],
-    [
-        "218055",
-        "tc_hypropo2",
-        "total column hypropo2"
-    ],
-    [
-        "218056",
-        "tc_noxa",
-        "total column nitrogen oxides transp"
-    ],
-    [
-        "219001",
-        "e_go3",
-        "ozone emissions"
-    ],
-    [
-        "219002",
-        "e_nox",
-        "nitrogen oxides emissions"
-    ],
-    [
-        "219003",
-        "e_h2o2",
-        "hydrogen peroxide emissions"
-    ],
-    [
-        "219004",
-        "e_ch4",
-        "methane emissions"
-    ],
-    [
-        "219005",
-        "e_co",
-        "carbon monoxide emissions"
-    ],
-    [
-        "219006",
-        "e_hno3",
-        "nitric acid emissions"
-    ],
-    [
-        "219007",
-        "e_ch3ooh",
-        "methyl peroxide emissions"
-    ],
-    [
-        "219008",
-        "e_hcho",
-        "formaldehyde emissions"
-    ],
-    [
-        "219009",
-        "e_par",
-        "paraffins emissions"
-    ],
-    [
-        "219010",
-        "e_c2h4",
-        "ethene emissions"
-    ],
-    [
-        "219011",
-        "e_ole",
-        "olefins emissions"
-    ],
-    [
-        "219012",
-        "e_ald2",
-        "aldehydes emissions"
-    ],
-    [
-        "219013",
-        "e_pan",
-        "peroxyacetyl nitrate emissions"
-    ],
-    [
-        "219014",
-        "e_rooh",
-        "peroxides emissions"
-    ],
-    [
-        "219015",
-        "e_onit",
-        "organic nitrates emissions"
-    ],
-    [
-        "219016",
-        "e_c5h8",
-        "isoprene emissions"
-    ],
-    [
-        "219017",
-        "e_so2",
-        "sulfur dioxide emissions"
-    ],
-    [
-        "219018",
-        "e_dms",
-        "dimethyl sulfide emissions"
-    ],
-    [
-        "219019",
-        "e_nh3",
-        "ammonia emissions"
-    ],
-    [
-        "219020",
-        "e_so4",
-        "sulfate emissions"
-    ],
-    [
-        "219021",
-        "e_nh4",
-        "ammonium emissions"
-    ],
-    [
-        "219022",
-        "e_msa",
-        "methane sulfonic acid emissions"
-    ],
-    [
-        "219023",
-        "e_ch3cocho",
-        "methyl glyoxal emissions"
-    ],
-    [
-        "219024",
-        "e_o3s",
-        "stratospheric ozone emissions"
-    ],
-    [
-        "219025",
-        "e_ra",
-        "radon emissions"
-    ],
-    [
-        "219026",
-        "e_pb",
-        "lead emissions"
-    ],
-    [
-        "219027",
-        "e_no",
-        "nitrogen monoxide emissions"
-    ],
-    [
-        "219028",
-        "e_ho2",
-        "hydroperoxy radical emissions"
-    ],
-    [
-        "219029",
-        "e_ch3o2",
-        "methylperoxy radical emissions"
-    ],
-    [
-        "219030",
-        "e_oh",
-        "hydroxyl radical emissions"
-    ],
-    [
-        "219031",
-        "e_no2",
-        "nitrogen dioxide emissions"
-    ],
-    [
-        "219032",
-        "e_no3",
-        "nitrate radical emissions"
-    ],
-    [
-        "219033",
-        "e_n2o5",
-        "dinitrogen pentoxide emissions"
-    ],
-    [
-        "219034",
-        "e_ho2no2",
-        "pernitric acid emissions"
-    ],
-    [
-        "219035",
-        "e_c2o3",
-        "peroxy acetyl radical emissions"
-    ],
-    [
-        "219036",
-        "e_ror",
-        "organic ethers emissions"
-    ],
-    [
-        "219037",
-        "e_rxpar",
-        "par budget corrector emissions"
-    ],
-    [
-        "219038",
-        "e_xo2",
-        "no to no2 operator emissions"
-    ],
-    [
-        "219039",
-        "e_xo2n",
-        "no to alkyl nitrate operator emissions"
-    ],
-    [
-        "219040",
-        "e_nh2",
-        "amine emissions"
-    ],
-    [
-        "219041",
-        "e_psc",
-        "polar stratospheric cloud emissions"
-    ],
-    [
-        "219042",
-        "e_ch3oh",
-        "methanol emissions"
-    ],
-    [
-        "219043",
-        "e_hcooh",
-        "formic acid emissions"
-    ],
-    [
-        "219044",
-        "e_mcooh",
-        "methacrylic acid emissions"
-    ],
-    [
-        "219045",
-        "e_c2h6",
-        "ethane emissions"
-    ],
-    [
-        "219046",
-        "e_c2h5oh",
-        "ethanol emissions"
-    ],
-    [
-        "219047",
-        "e_c3h8",
-        "propane emissions"
-    ],
-    [
-        "219048",
-        "e_c3h6",
-        "propene emissions"
-    ],
-    [
-        "219049",
-        "e_c10h16",
-        "terpenes emissions"
-    ],
-    [
-        "219050",
-        "e_ispd",
-        "methacrolein mvk  emissions"
-    ],
-    [
-        "219051",
-        "e_no3_a",
-        "nitrate emissions"
-    ],
-    [
-        "219052",
-        "e_ch3coch3",
-        "acetone emissions"
-    ],
-    [
-        "219053",
-        "e_aco2",
-        "acetone product emissions"
-    ],
-    [
-        "219054",
-        "e_ic3h7o2",
-        "ic3h7o2 emissions"
-    ],
-    [
-        "219055",
-        "e_hypropo2",
-        "hypropo2 emissions"
-    ],
-    [
-        "219056",
-        "e_noxa",
-        "nitrogen oxides transp emissions"
-    ],
-    [
-        "221001",
-        "dv_go3",
-        "ozone deposition velocity"
-    ],
-    [
-        "221002",
-        "dv_nox",
-        "nitrogen oxides deposition velocity"
-    ],
-    [
-        "221003",
-        "dv_h2o2",
-        "hydrogen peroxide deposition velocity"
-    ],
-    [
-        "221004",
-        "dv_ch4",
-        "methane deposition velocity"
-    ],
-    [
-        "221005",
-        "dv_co",
-        "carbon monoxide deposition velocity"
-    ],
-    [
-        "221006",
-        "dv_hno3",
-        "nitric acid deposition velocity"
-    ],
-    [
-        "221007",
-        "dv_ch3ooh",
-        "methyl peroxide deposition velocity"
-    ],
-    [
-        "221008",
-        "dv_hcho",
-        "formaldehyde deposition velocity"
-    ],
-    [
-        "221009",
-        "dv_par",
-        "paraffins deposition velocity"
-    ],
-    [
-        "221010",
-        "dv_c2h4",
-        "ethene deposition velocity"
-    ],
-    [
-        "221011",
-        "dv_ole",
-        "olefins deposition velocity"
-    ],
-    [
-        "221012",
-        "dv_ald2",
-        "aldehydes deposition velocity"
-    ],
-    [
-        "221013",
-        "dv_pan",
-        "peroxyacetyl nitrate deposition velocity"
-    ],
-    [
-        "221014",
-        "dv_rooh",
-        "peroxides deposition velocity"
-    ],
-    [
-        "221015",
-        "dv_onit",
-        "organic nitrates deposition velocity"
-    ],
-    [
-        "221016",
-        "dv_c5h8",
-        "isoprene deposition velocity"
-    ],
-    [
-        "221017",
-        "dv_so2",
-        "sulfur dioxide deposition velocity"
-    ],
-    [
-        "221018",
-        "dv_dms",
-        "dimethyl sulfide deposition velocity"
-    ],
-    [
-        "221019",
-        "dv_nh3",
-        "ammonia deposition velocity"
-    ],
-    [
-        "221020",
-        "dv_so4",
-        "sulfate deposition velocity"
-    ],
-    [
-        "221021",
-        "dv_nh4",
-        "ammonium deposition velocity"
-    ],
-    [
-        "221022",
-        "dv_msa",
-        "methane sulfonic acid deposition velocity"
-    ],
-    [
-        "221023",
-        "dv_ch3cocho",
-        "methyl glyoxal deposition velocity"
-    ],
-    [
-        "221024",
-        "dv_o3s",
-        "stratospheric ozone deposition velocity"
-    ],
-    [
-        "221025",
-        "dv_ra",
-        "radon deposition velocity"
-    ],
-    [
-        "221026",
-        "dv_pb",
-        "lead deposition velocity"
-    ],
-    [
-        "221027",
-        "dv_no",
-        "nitrogen monoxide deposition velocity"
-    ],
-    [
-        "221028",
-        "dv_ho2",
-        "hydroperoxy radical deposition velocity"
-    ],
-    [
-        "221029",
-        "dv_ch3o2",
-        "methylperoxy radical deposition velocity"
-    ],
-    [
-        "221030",
-        "dv_oh",
-        "hydroxyl radical deposition velocity"
-    ],
-    [
-        "221031",
-        "dv_no2",
-        "nitrogen dioxide deposition velocity"
-    ],
-    [
-        "221032",
-        "dv_no3",
-        "nitrate radical deposition velocity"
-    ],
-    [
-        "221033",
-        "dv_n2o5",
-        "dinitrogen pentoxide deposition velocity"
-    ],
-    [
-        "221034",
-        "dv_ho2no2",
-        "pernitric acid deposition velocity"
-    ],
-    [
-        "221035",
-        "dv_c2o3",
-        "peroxy acetyl radical deposition velocity"
-    ],
-    [
-        "221036",
-        "dv_ror",
-        "organic ethers deposition velocity"
-    ],
-    [
-        "221037",
-        "dv_rxpar",
-        "par budget corrector deposition velocity"
-    ],
-    [
-        "221038",
-        "dv_xo2",
-        "no to no2 operator deposition velocity"
-    ],
-    [
-        "221039",
-        "dv_xo2n",
-        "no to alkyl nitrate operator deposition velocity"
-    ],
-    [
-        "221040",
-        "dv_nh2",
-        "amine deposition velocity"
-    ],
-    [
-        "221041",
-        "dv_psc",
-        "polar stratospheric cloud deposition velocity"
-    ],
-    [
-        "221042",
-        "dv_ch3oh",
-        "methanol deposition velocity"
-    ],
-    [
-        "221043",
-        "dv_hcooh",
-        "formic acid deposition velocity"
-    ],
-    [
-        "221044",
-        "dv_mcooh",
-        "methacrylic acid deposition velocity"
-    ],
-    [
-        "221045",
-        "dv_c2h6",
-        "ethane deposition velocity"
-    ],
-    [
-        "221046",
-        "dv_c2h5oh",
-        "ethanol deposition velocity"
-    ],
-    [
-        "221047",
-        "dv_c3h8",
-        "propane deposition velocity"
-    ],
-    [
-        "221048",
-        "dv_c3h6",
-        "propene deposition velocity"
-    ],
-    [
-        "221049",
-        "dv_c10h16",
-        "terpenes deposition velocity"
-    ],
-    [
-        "221050",
-        "dv_ispd",
-        "methacrolein mvk  deposition velocity"
-    ],
-    [
-        "221051",
-        "dv_no3_a",
-        "nitrate deposition velocity"
-    ],
-    [
-        "221052",
-        "dv_ch3coch3",
-        "acetone deposition velocity"
-    ],
-    [
-        "221053",
-        "dv_aco2",
-        "acetone product deposition velocity"
-    ],
-    [
-        "221054",
-        "dv_ic3h7o2",
-        "ic3h7o2 deposition velocity"
-    ],
-    [
-        "221055",
-        "dv_hypropo2",
-        "hypropo2 deposition velocity"
-    ],
-    [
-        "221056",
-        "dv_noxa",
-        "nitrogen oxides transp deposition velocity"
-    ],
-    [
-        "210243",
-        "vsuaod550",
-        "volcanic sulphate aerosol optical depth at 550 nm"
-    ],
-    [
-        "210244",
-        "vashaod550",
-        "volcanic ash optical depth at 550 nm"
-    ],
-    [
-        "210245",
-        "taedec550",
-        "profile of total aerosol dry extinction coefficient"
-    ],
-    [
-        "210246",
-        "taedab550",
-        "profile of total aerosol dry absorption coefficient"
-    ],
-    [
-        "210242",
-        "apb",
-        "altitude of plume bottom"
-    ],
-    [
-        "228143",
-        "cp",
-        "convective precipitation"
-    ],
-    [
-        "3066",
-        "sde",
-        "snow depth"
-    ],
-    [
-        "3072",
-        "ccc",
-        "convective cloud cover"
-    ],
-    [
-        "3073",
-        "lcc",
-        "low cloud cover"
-    ],
-    [
-        "3074",
-        "mcc",
-        "medium cloud cover"
-    ],
-    [
-        "3075",
-        "hcc",
-        "high cloud cover"
-    ],
-    [
-        "3079",
-        "lssf",
-        "large scale snow"
-    ],
-    [
-        "260600",
-        "evpsfc",
-        "evaporation"
-    ],
-    [
-        "260601",
-        "tpratsfc",
-        "total precipitation"
-    ],
-    [
-        "260602",
-        "lpratsfc",
-        "large scale precipitation"
-    ],
-    [
-        "260603",
-        "cpratsfc",
-        "convective precipitation"
-    ],
-    [
-        "260604",
-        "srweqsfc",
-        "snowfall rate water equivalent"
-    ],
-    [
-        "260605",
-        "rofsfc",
-        "water run-off"
-    ],
-    [
-        "260606",
-        "bvf2tht",
-        "square of brunt-vaisala frequency"
-    ],
-    [
-        "260607",
-        "aduahbl",
-        "adiabatic zonal acceleration"
-    ],
-    [
-        "260608",
-        "vwvclm",
-        "meridional water vapour flux"
-    ],
-    [
-        "260609",
-        "advaprs",
-        "adiabatic meridional acceleration"
-    ],
-    [
-        "260610",
-        "frcvsfc",
-        "frequency of deep convection"
-    ],
-    [
-        "260611",
-        "frcvssfc",
-        "frequency of shallow convection"
-    ],
-    [
-        "260612",
-        "frscsfc",
-        "frequency of stratocumulus parameterisation"
-    ],
-    [
-        "260613",
-        "gwduahbl",
-        "gravity wave zonal acceleration"
-    ],
-    [
-        "260614",
-        "gwdvahbl",
-        "gravity wave meridional acceleration"
-    ],
-    [
-        "260615",
-        "ltrssfc",
-        "evapotranspiration"
-    ],
-    [
-        "260616",
-        "adhrhbl",
-        "adiabatic heating rate"
-    ],
-    [
-        "260617",
-        "mscsfc",
-        "moisture storage on canopy"
-    ],
-    [
-        "260618",
-        "msgsfc",
-        "moisture storage on ground or cover"
-    ],
-    [
-        "260619",
-        "smcugl",
-        "mass concentration of condensed water in soil"
-    ],
-    [
-        "260620",
-        "cwclm",
-        "cloud liquid water"
-    ],
-    [
-        "260621",
-        "mflxbhbl",
-        "upward mass flux at cloud base"
-    ],
-    [
-        "260622",
-        "mfluxhbl",
-        "upward mass flux"
-    ],
-    [
-        "260623",
-        "admrhbl",
-        "adiabatic moistening rate"
-    ],
-    [
-        "260624",
-        "ozonehbl",
-        "ozone mixing ratio"
-    ],
-    [
-        "260625",
-        "cnvuahbl",
-        "convective zonal acceleration"
-    ],
-    [
-        "3121",
-        "lhf",
-        "latent heat flux"
-    ],
-    [
-        "3122",
-        "shf",
-        "sensible heat flux"
-    ],
-    [
-        "3123",
-        "bld",
-        "boundary layer dissipation"
-    ],
-    [
-        "260626",
-        "fglusfc",
-        "zonal momentum flux by long gravity wave"
-    ],
-    [
-        "260627",
-        "fglvsfc",
-        "meridional momentum flux by long gravity wave"
-    ],
-    [
-        "260628",
-        "fgsvsfc",
-        "meridional momentum flux by short gravity wave"
-    ],
-    [
-        "260629",
-        "fgsusfc",
-        "zonal momentum flux by short gravity wave"
-    ],
-    [
-        "260630",
-        "utheclm",
-        "zonal thermal energy flux"
-    ],
-    [
-        "260631",
-        "vtheclm",
-        "meridional thermal energy flux"
-    ],
-    [
-        "260632",
-        "cnvvahbl",
-        "convective meridional acceleration"
-    ],
-    [
-        "260633",
-        "lrghrhbl",
-        "large scale condensation heating rate"
-    ],
-    [
-        "260634",
-        "cnvhrhbl",
-        "convective heating rate"
-    ],
-    [
-        "260635",
-        "cnvmrhbl",
-        "convective moistening rate"
-    ],
-    [
-        "260636",
-        "vdfhrhbl",
-        "vertical diffusion heating rate"
-    ],
-    [
-        "260637",
-        "vdfuahbl",
-        "vertical diffusion zonal acceleration"
-    ],
-    [
-        "260638",
-        "vdfvahbl",
-        "vertical diffusion meridional acceleration"
-    ],
-    [
-        "260639",
-        "vdfmrhbl",
-        "vertical diffusion moistening rate"
-    ],
-    [
-        "260640",
-        "swhrhbl",
-        "solar radiative heating rate"
-    ],
-    [
-        "260641",
-        "lwhrhbl",
-        "long wave radiative heating rate"
-    ],
-    [
-        "260642",
-        "lrgmrhbl",
-        "large scale moistening rate"
-    ],
-    [
-        "260643",
-        "tovg",
-        "type of vegetation"
-    ],
-    [
-        "228029",
-        "i10fg",
-        "instantaneous 10 metre wind gust"
-    ],
-    [
-        "228222",
-        "mxtpr3",
-        "maximum total precipitation rate in the last 3 hours"
-    ],
-    [
-        "228223",
-        "mntpr3",
-        "minimum total precipitation rate in the last 3 hours"
-    ],
-    [
-        "228224",
-        "mxtpr6",
-        "maximum total precipitation rate in the last 6 hours"
-    ],
-    [
-        "228225",
-        "mntpr6",
-        "minimum total precipitation rate in the last 6 hours"
-    ],
-    [
-        "228226",
-        "mxtpr",
-        "maximum total precipitation rate since previous post-processing"
-    ],
-    [
-        "228227",
-        "mntpr",
-        "minimum total precipitation rate since previous post-processing"
-    ],
-    [
-        "228218",
-        "crr",
-        "convective rain rate"
-    ],
-    [
-        "228219",
-        "lsrr",
-        "large scale rain rate"
-    ],
-    [
-        "228220",
-        "csfr",
-        "convective snowfall rate water equivalent"
-    ],
-    [
-        "228221",
-        "lssfr",
-        "large scale snowfall rate water equivalent"
-    ],
-    [
-        "228217",
-        "ilspf",
-        "instantaneous large-scale surface precipitation fraction"
-    ],
-    [
-        "228088",
-        "tcslw",
-        "total column supercooled liquid water"
-    ],
-    [
-        "140207",
-        "wss",
-        "wave spectral skewness"
-    ],
-    [
-        "228030",
-        "rhw",
-        "relative humidity with respect to water"
-    ],
-    [
-        "228031",
-        "rhi",
-        "relative humidity with respect to ice"
-    ],
-    [
-        "228033",
-        "fspc",
-        "fraction of stratiform precipitation cover"
-    ],
-    [
-        "228034",
-        "fcpc",
-        "fraction of convective precipitation cover"
-    ],
-    [
-        "230020",
-        "parcsvar",
-        "clear sky surface photosynthetically active radiation (variable resolution)"
-    ],
-    [
-        "230050",
-        "lspfvar",
-        "large-scale precipitation fraction (variable resolution)"
-    ],
-    [
-        "230213",
-        "vimdvar",
-        "vertically integrated moisture divergence (variable resolution)"
-    ],
-    [
-        "230239",
-        "csfvar",
-        "convective snowfall (variable resolution)"
-    ],
-    [
-        "230240",
-        "lsfvar",
-        "large-scale snowfall (variable resolution)"
-    ],
-    [
-        "230080",
-        "aco2neevar",
-        "accumulated carbon dioxide net ecosystem exchange (variable resolution)"
-    ],
-    [
-        "230081",
-        "aco2gppvar",
-        "accumulated carbon dioxide gross primary production (variable resolution)"
-    ],
-    [
-        "230082",
-        "aco2recvar",
-        "accumulated carbon dioxide ecosystem respiration (variable resolution)"
-    ],
-    [
-        "230129",
-        "ssrdcvar",
-        "surface solar radiation downward clear-sky (variable resolution)"
-    ],
-    [
-        "230130",
-        "strdcvar",
-        "surface thermal radiation downward clear-sky (variable resolution)"
-    ],
-    [
-        "230251",
-        "pevvar",
-        "potential evaporation (variable resolution)"
-    ],
-    [
-        "228216",
-        "fzra",
-        "accumulated freezing rain"
-    ],
-    [
-        "174097",
-        "sist",
-        "sea-ice snow thickness"
-    ],
-    [
-        "228078",
-        "gppbfas",
-        "gpp coefficient from biogenic flux adjustment system"
-    ],
-    [
-        "228079",
-        "recbfas",
-        "rec coefficient from biogenic flux adjustment system"
-    ],
-    [
-        "215180",
-        "aerext355",
-        "aerosol extinction coefficient at 355 nm"
-    ],
-    [
-        "215181",
-        "aerext532",
-        "aerosol extinction coefficient at 532 nm"
-    ],
-    [
-        "215182",
-        "aerext1064",
-        "aerosol extinction coefficient at 1064 nm"
-    ],
-    [
-        "215183",
-        "aerbackscattoa355",
-        "aerosol backscatter coefficient at 355 nm (from top of atmosphere)"
-    ],
-    [
-        "215184",
-        "aerbackscattoa532",
-        "aerosol backscatter coefficient at 532 nm (from top of atmosphere)"
-    ],
-    [
-        "215185",
-        "aerbackscattoa1064",
-        "aerosol backscatter coefficient at 1064 nm (from top of atmosphere)"
-    ],
-    [
-        "215186",
-        "aerbackscatgnd355",
-        "aerosol backscatter coefficient at 355 nm (from ground)"
-    ],
-    [
-        "215187",
-        "aerbackscatgnd532",
-        "aerosol backscatter coefficient at 532 nm (from ground)"
-    ],
-    [
-        "215188",
-        "aerbackscatgnd1064",
-        "aerosol backscatter coefficient at 1064 nm (from ground)"
-    ],
-    [
-        "230216",
-        "fzravar",
-        "accumulated freezing rain (variable resolution)"
-    ],
-    [
-        "260238",
-        "wz",
-        "geometric vertical velocity"
-    ],
-    [
-        "235001",
-        "mttswr",
-        "mean temperature tendency due to short-wave radiation"
-    ],
-    [
-        "235002",
-        "mttlwr",
-        "mean temperature tendency due to long-wave radiation"
-    ],
-    [
-        "235003",
-        "mttswrcs",
-        "mean temperature tendency due to short-wave radiation, clear sky"
-    ],
-    [
-        "235004",
-        "mttlwrcs",
-        "mean temperature tendency due to long-wave radiation, clear sky"
-    ],
-    [
-        "235005",
-        "mttpm",
-        "mean temperature tendency due to parametrisations"
-    ],
-    [
-        "235006",
-        "mqtpm",
-        "mean specific humidity tendency due to parametrisations"
-    ],
-    [
-        "235007",
-        "mutpm",
-        "mean eastward wind tendency due to parametrisations"
-    ],
-    [
-        "235008",
-        "mvtpm",
-        "mean northward wind tendency due to parametrisations"
-    ],
-    [
-        "235009",
-        "mumf",
-        "mean updraught mass flux"
-    ],
-    [
-        "235010",
-        "mdmf",
-        "mean downdraught mass flux"
-    ],
-    [
-        "235011",
-        "mudr",
-        "mean updraught detrainment rate"
-    ],
-    [
-        "235012",
-        "mddr",
-        "mean downdraught detrainment rate"
-    ],
-    [
-        "235013",
-        "mtpf",
-        "mean total precipitation flux"
-    ],
-    [
-        "235014",
-        "mtdch",
-        "mean turbulent diffusion coefficient for heat"
-    ],
-    [
-        "235020",
-        "msror",
-        "mean surface runoff rate"
-    ],
-    [
-        "235021",
-        "mssror",
-        "mean sub-surface runoff rate"
-    ],
-    [
-        "235022",
-        "msparfcs",
-        "mean surface photosynthetically active radiation flux, clear sky"
-    ],
-    [
-        "235023",
-        "mser",
-        "mean snow evaporation rate"
-    ],
-    [
-        "235024",
-        "msmr",
-        "mean snowmelt rate"
-    ],
-    [
-        "235025",
-        "mmtss",
-        "mean magnitude of turbulent surface stress"
-    ],
-    [
-        "235026",
-        "mlspf",
-        "mean large-scale precipitation fraction"
-    ],
-    [
-        "235027",
-        "msdwuvrf",
-        "mean surface downward uv radiation flux"
-    ],
-    [
-        "235028",
-        "msparf",
-        "mean surface photosynthetically active radiation flux"
-    ],
-    [
-        "235029",
-        "mlspr",
-        "mean large-scale precipitation rate"
-    ],
-    [
-        "235030",
-        "mcpr",
-        "mean convective precipitation rate"
-    ],
-    [
-        "235031",
-        "msr",
-        "mean snowfall rate"
-    ],
-    [
-        "235032",
-        "mbld",
-        "mean boundary layer dissipation"
-    ],
-    [
-        "235033",
-        "msshf",
-        "mean surface sensible heat flux"
-    ],
-    [
-        "235034",
-        "mslhf",
-        "mean surface latent heat flux"
-    ],
-    [
-        "235035",
-        "msdwswrf",
-        "mean surface downward short-wave radiation flux"
-    ],
-    [
-        "235036",
-        "msdwlwrf",
-        "mean surface downward long-wave radiation flux"
-    ],
-    [
-        "235037",
-        "msnswrf",
-        "mean surface net short-wave radiation flux"
-    ],
-    [
-        "235038",
-        "msnlwrf",
-        "mean surface net long-wave radiation flux"
-    ],
-    [
-        "235039",
-        "mtnswrf",
-        "mean top net short-wave radiation flux"
-    ],
-    [
-        "235040",
-        "mtnlwrf",
-        "mean top net long-wave radiation flux"
-    ],
-    [
-        "235041",
-        "metss",
-        "mean eastward turbulent surface stress"
-    ],
-    [
-        "235042",
-        "mntss",
-        "mean northward turbulent surface stress"
-    ],
-    [
-        "235043",
-        "mer",
-        "mean evaporation rate"
-    ],
-    [
-        "235044",
-        "sdf",
-        "sunshine duration fraction"
-    ],
-    [
-        "235045",
-        "megwss",
-        "mean eastward gravity wave surface stress"
-    ],
-    [
-        "235046",
-        "mngwss",
-        "mean northward gravity wave surface stress"
-    ],
-    [
-        "235047",
-        "mgwd",
-        "mean gravity wave dissipation"
-    ],
-    [
-        "235048",
-        "mror",
-        "mean runoff rate"
-    ],
-    [
-        "235049",
-        "mtnswrfcs",
-        "mean top net short-wave radiation flux, clear sky"
-    ],
-    [
-        "235050",
-        "mtnlwrfcs",
-        "mean top net long-wave radiation flux, clear sky"
-    ],
-    [
-        "235051",
-        "msnswrfcs",
-        "mean surface net short-wave radiation flux, clear sky"
-    ],
-    [
-        "235052",
-        "msnlwrfcs",
-        "mean surface net long-wave radiation flux, clear sky"
-    ],
-    [
-        "235053",
-        "mtdwswrf",
-        "mean top downward short-wave radiation flux"
-    ],
-    [
-        "235054",
-        "mvimd",
-        "mean vertically integrated moisture divergence"
-    ],
-    [
-        "235055",
-        "mtpr",
-        "mean total precipitation rate"
-    ],
-    [
-        "235056",
-        "mcsr",
-        "mean convective snowfall rate"
-    ],
-    [
-        "235057",
-        "mlssr",
-        "mean large-scale snowfall rate"
-    ],
-    [
-        "235058",
-        "msdrswrf",
-        "mean surface direct short-wave radiation flux"
-    ],
-    [
-        "235059",
-        "msdrswrfcs",
-        "mean surface direct short-wave radiation flux, clear sky"
-    ],
-    [
-        "235060",
-        "msdfswrf",
-        "mean surface diffuse short-wave radiation flux"
-    ],
-    [
-        "235061",
-        "msdfswrfcs",
-        "mean surface diffuse short-wave radiation flux, clear sky"
-    ],
-    [
-        "235062",
-        "mcdneef",
-        "mean carbon dioxide net ecosystem exchange flux"
-    ],
-    [
-        "235063",
-        "mcdgppf",
-        "mean carbon dioxide gross primary production flux"
-    ],
-    [
-        "235064",
-        "mcderf",
-        "mean carbon dioxide ecosystem respiration flux"
-    ],
-    [
-        "235065",
-        "mrr",
-        "mean rain rate"
-    ],
-    [
-        "235066",
-        "mcrr",
-        "mean convective rain rate"
-    ],
-    [
-        "235067",
-        "mlsrr",
-        "mean large-scale rain rate"
-    ],
-    [
-        "228044",
-        "capes",
-        "convective available potential energy shear"
-    ],
-    [
-        "132059",
-        "capei",
-        "convective available potential energy index"
-    ],
-    [
-        "132044",
-        "capesi",
-        "convective available potential energy shear index"
-    ],
-    [
-        "140120",
-        "sh10",
-        "significant wave height of all waves with period larger than 10s"
-    ],
-    [
-        "228046",
-        "hcct",
-        "height of convective cloud top"
-    ],
-    [
-        "228047",
-        "hwbt0",
-        "height of zero deg wet bulb temperature"
-    ],
-    [
-        "228048",
-        "hwbt1",
-        "height of one deg wet bulb temperature"
-    ],
-    [
-        "228050",
-        "litoti",
-        "instantaneous total lightning density"
-    ],
-    [
-        "228051",
-        "litota",
-        "averaged total lightning density"
-    ],
-    [
-        "228052",
-        "licgi",
-        "instantaneous cloud-to-ground lightning density"
-    ],
-    [
-        "228053",
-        "licga",
-        "averaged cloud-to-ground lightning density"
-    ],
-    [
-        "235068",
-        "msdwswrfcs",
-        "mean surface downward short-wave radiation flux, clear sky"
-    ],
-    [
-        "235069",
-        "msdwlwrfcs",
-        "mean surface downward long-wave radiation flux, clear sky"
-    ],
-    [
-        "235070",
-        "mper",
-        "mean potential evaporation rate"
-    ],
-    [
-        "7001292",
-        "sunsd",
-        "sunshine duration"
-    ],
-    [
-        "7001353",
-        "vrate",
-        "ventilation rate"
-    ],
-    [
-        "240028",
-        "gwus",
-        "groundwater upper storage"
-    ],
-    [
-        "240029",
-        "gwls",
-        "groundwater lower storage"
-    ],
-    [
-        "228054",
-        "ucq",
-        "unbalanced component of specific humidity"
-    ],
-    [
-        "228055",
-        "ucclwc",
-        "unbalanced component of specific cloud liquid water content"
-    ],
-    [
-        "228056",
-        "ucciwc",
-        "unbalanced component of specific cloud ice water content"
-    ],
-    [
-        "230047",
-        "dsrpvar",
-        "direct solar radiation (variable resolution)"
-    ],
-    [
-        "260259",
-        "eva",
-        "evaporation"
-    ],
-    [
-        "260260",
-        "10wdir",
-        "10 metre wind direction"
-    ],
-    [
-        "260360",
-        "sot",
-        "soil temperature"
-    ],
-    [
-        "7001293",
-        "icsev",
-        "icing severity"
-    ],
-    [
-        "140113",
-        "wefxd",
-        "wave energy flux mean direction"
-    ],
-    [
-        "140112",
-        "wefxm",
-        "wave energy flux magnitude"
-    ],
-    [
-        "260262",
-        "dirswrf",
-        "direct short wave radiation flux"
-    ],
-    [
-        "260263",
-        "difswrf",
-        "diffuse short wave radiation flux"
-    ],
-    [
-        "260264",
-        "tidirswrf",
-        "time-integrated surface direct short wave radiation flux"
-    ],
-    [
-        "260361",
-        "dswrf_cs",
-        "downward short-wave radiation flux, clear sky"
-    ],
-    [
-        "260362",
-        "uswrf_cs",
-        "upward short-wave radiation flux, clear sky"
-    ],
-    [
-        "260363",
-        "dlwrf_cs",
-        "downward long-wave radiation flux, clear sky"
-    ],
-    [
-        "260364",
-        "sohf",
-        "soil heat flux"
-    ],
-    [
-        "260365",
-        "percr",
-        "percolation rate"
-    ],
-    [
-        "260367",
-        "sod",
-        "soil depth"
-    ],
-    [
-        "260423",
-        "adswrf_cs",
-        "accumulated surface downward short-wave radiation flux, clear sky"
-    ],
-    [
-        "260427",
-        "auswrf_cs",
-        "accumulated surface upward short-wave radiation flux, clear sky"
-    ],
-    [
-        "260428",
-        "adlwrf_cs",
-        "accumulated surface downward long-wave radiation flux, clear sky"
-    ],
-    [
-        "260430",
-        "perc",
-        "percolation"
-    ],
-    [
-        "174096",
-        "2m specific humidity"
-    ],
-    [
-        "140114",
-        "h1012",
-        "significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds"
-    ],
-    [
-        "140115",
-        "h1214",
-        "significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds"
-    ],
-    [
-        "140116",
-        "h1417",
-        "significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds"
-    ],
-    [
-        "140117",
-        "h1721",
-        "significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds"
-    ],
-    [
-        "140118",
-        "h2125",
-        "significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds"
-    ],
-    [
-        "140119",
-        "h2530",
-        "significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds"
-    ],
-    [
-        "213101",
-        "spp1",
-        "random pattern 1 for spp scheme"
-    ],
-    [
-        "213102",
-        "spp2",
-        "random pattern 2 for spp scheme"
-    ],
-    [
-        "213103",
-        "spp3",
-        "random pattern 3 for spp scheme"
-    ],
-    [
-        "213104",
-        "spp4",
-        "random pattern 4 for spp scheme"
-    ],
-    [
-        "213105",
-        "spp5",
-        "random pattern 5 for spp scheme"
-    ],
-    [
-        "213106",
-        "spp6",
-        "random pattern 6 for spp scheme"
-    ],
-    [
-        "213107",
-        "spp7",
-        "random pattern 7 for spp scheme"
-    ],
-    [
-        "213108",
-        "spp8",
-        "random pattern 8 for spp scheme"
-    ],
-    [
-        "213109",
-        "spp9",
-        "random pattern 9 for spp scheme"
-    ],
-    [
-        "213110",
-        "spp10",
-        "random pattern 10 for spp scheme"
-    ],
-    [
-        "213111",
-        "spp11",
-        "random pattern 11 for spp scheme"
-    ],
-    [
-        "213112",
-        "spp12",
-        "random pattern 12 for spp scheme"
-    ],
-    [
-        "213113",
-        "spp13",
-        "random pattern 13 for spp scheme"
-    ],
-    [
-        "213114",
-        "spp14",
-        "random pattern 14 for spp scheme"
-    ],
-    [
-        "213115",
-        "spp15",
-        "random pattern 15 for spp scheme"
-    ],
-    [
-        "213116",
-        "spp16",
-        "random pattern 16 for spp scheme"
-    ],
-    [
-        "213117",
-        "spp17",
-        "random pattern 17 for spp scheme"
-    ],
-    [
-        "213118",
-        "spp18",
-        "random pattern 18 for spp scheme"
-    ],
-    [
-        "213119",
-        "spp19",
-        "random pattern 19 for spp scheme"
-    ],
-    [
-        "213120",
-        "spp20",
-        "random pattern 20 for spp scheme"
-    ],
-    [
-        "213121",
-        "spp21",
-        "random pattern 21 for spp scheme"
-    ],
-    [
-        "213122",
-        "spp22",
-        "random pattern 22 for spp scheme"
-    ],
-    [
-        "213123",
-        "spp23",
-        "random pattern 23 for spp scheme"
-    ],
-    [
-        "213124",
-        "spp24",
-        "random pattern 24 for spp scheme"
-    ],
-    [
-        "213125",
-        "spp25",
-        "random pattern 25 for spp scheme"
-    ],
-    [
-        "213126",
-        "spp26",
-        "random pattern 26 for spp scheme"
-    ],
-    [
-        "213127",
-        "spp27",
-        "random pattern 27 for spp scheme"
-    ],
-    [
-        "213128",
-        "spp28",
-        "random pattern 28 for spp scheme"
-    ],
-    [
-        "213129",
-        "spp29",
-        "random pattern 29 for spp scheme"
-    ],
-    [
-        "213130",
-        "spp30",
-        "random pattern 30 for spp scheme"
-    ],
-    [
-        "213131",
-        "spp31",
-        "random pattern 31 for spp scheme"
-    ],
-    [
-        "213132",
-        "spp32",
-        "random pattern 32 for spp scheme"
-    ],
-    [
-        "213133",
-        "spp33",
-        "random pattern 33 for spp scheme"
-    ],
-    [
-        "213134",
-        "spp34",
-        "random pattern 34 for spp scheme"
-    ],
-    [
-        "213135",
-        "spp35",
-        "random pattern 35 for spp scheme"
-    ],
-    [
-        "213136",
-        "spp36",
-        "random pattern 36 for spp scheme"
-    ],
-    [
-        "213137",
-        "spp37",
-        "random pattern 37 for spp scheme"
-    ],
-    [
-        "213138",
-        "spp38",
-        "random pattern 38 for spp scheme"
-    ],
-    [
-        "213139",
-        "spp39",
-        "random pattern 39 for spp scheme"
-    ],
-    [
-        "213140",
-        "spp40",
-        "random pattern 40 for spp scheme"
-    ],
-    [
-        "213141",
-        "spp41",
-        "random pattern 41 for spp scheme"
-    ],
-    [
-        "213142",
-        "spp42",
-        "random pattern 42 for spp scheme"
-    ],
-    [
-        "213143",
-        "spp43",
-        "random pattern 43 for spp scheme"
-    ],
-    [
-        "213144",
-        "spp44",
-        "random pattern 44 for spp scheme"
-    ],
-    [
-        "213145",
-        "spp45",
-        "random pattern 45 for spp scheme"
-    ],
-    [
-        "213146",
-        "spp46",
-        "random pattern 46 for spp scheme"
-    ],
-    [
-        "213147",
-        "spp47",
-        "random pattern 47 for spp scheme"
-    ],
-    [
-        "213148",
-        "spp48",
-        "random pattern 48 for spp scheme"
-    ],
-    [
-        "213149",
-        "spp49",
-        "random pattern 49 for spp scheme"
-    ],
-    [
-        "213150",
-        "spp50",
-        "random pattern 50 for spp scheme"
-    ],
-    [
-        "999",
-        "tc",
-        "tropical cyclone"
-    ],
-    [
-        "928",
-        "thk",
-        "thicknes"
-    ],
-    [
-        "956",
-        "thka",
-        "thicknes anomaly"
+{
+    "ids": {
+        "1": [
+            "strf",
+            "stream function"
+        ],
+        "10": [
+            "ws",
+            "wind speed"
+        ],
+        "11": [
+            "udvw",
+            "u component of divergent wind"
+        ],
+        "12": [
+            "vdvw",
+            "v component of divergent wind"
+        ],
+        "121": [
+            "mx2t6",
+            "maximum temperature at 2 metres in the last 6 hours"
+        ],
+        "122": [
+            "mn2t6",
+            "minimum temperature at 2 metres in the last 6 hours"
+        ],
+        "123": [
+            "10fg6",
+            "10 metre wind gust in the last 6 hours"
+        ],
+        "124": [
+            "emis",
+            "surface emissivity"
+        ],
+        "125": [
+            "vite",
+            "vertically integrated total energy"
+        ],
+        "126": [
+            "generic parameter for sensitive area prediction"
+        ],
+        "127": [
+            "at",
+            "atmospheric tide"
+        ],
+        "128": [
+            "bv",
+            "budget values"
+        ],
+        "129": [
+            "z",
+            "geopotential"
+        ],
+        "129001": [
+            "strfgrd",
+            "stream function gradient"
+        ],
+        "129002": [
+            "vpotgrd",
+            "velocity potential gradient"
+        ],
+        "129003": [
+            "ptgrd",
+            "potential temperature gradient"
+        ],
+        "129004": [
+            "eqptgrd",
+            "equivalent potential temperature gradient"
+        ],
+        "129005": [
+            "septgrd",
+            "saturated equivalent potential temperature gradient"
+        ],
+        "129011": [
+            "udvwgrd",
+            "u component of divergent wind gradient"
+        ],
+        "129012": [
+            "vdvwgrd",
+            "v component of divergent wind gradient"
+        ],
+        "129013": [
+            "urtwgrd",
+            "u component of rotational wind gradient"
+        ],
+        "129014": [
+            "vrtwgrd",
+            "v component of rotational wind gradient"
+        ],
+        "129021": [
+            "uctpgrd",
+            "unbalanced component of temperature gradient"
+        ],
+        "129022": [
+            "uclngrd",
+            "unbalanced component of logarithm of surface pressure gradient"
+        ],
+        "129023": [
+            "ucdvgrd",
+            "unbalanced component of divergence gradient"
+        ],
+        "129026": [
+            "clgrd",
+            "lake cover gradient"
+        ],
+        "129027": [
+            "cvlgrd",
+            "low vegetation cover gradient"
+        ],
+        "129028": [
+            "cvhgrd",
+            "high vegetation cover gradient"
+        ],
+        "129029": [
+            "tvlgrd",
+            "type of low vegetation gradient"
+        ],
+        "129030": [
+            "tvhgrd",
+            "type of high vegetation gradient"
+        ],
+        "129031": [
+            "sicgrd",
+            "sea-ice cover gradient"
+        ],
+        "129032": [
+            "asngrd",
+            "snow albedo gradient"
+        ],
+        "129033": [
+            "rsngrd",
+            "snow density gradient"
+        ],
+        "129034": [
+            "sstkgrd",
+            "sea surface temperature gradient"
+        ],
+        "129035": [
+            "istl1grd",
+            "ice surface temperature layer 1 gradient"
+        ],
+        "129036": [
+            "istl2grd",
+            "ice surface temperature layer 2 gradient"
+        ],
+        "129037": [
+            "istl3grd",
+            "ice surface temperature layer 3 gradient"
+        ],
+        "129038": [
+            "istl4grd",
+            "ice surface temperature layer 4 gradient"
+        ],
+        "129039": [
+            "swvl1grd",
+            "volumetric soil water layer 1 gradient"
+        ],
+        "129040": [
+            "swvl2grd",
+            "volumetric soil water layer 2 gradient"
+        ],
+        "129041": [
+            "swvl3grd",
+            "volumetric soil water layer 3 gradient"
+        ],
+        "129042": [
+            "swvl4grd",
+            "volumetric soil water layer 4 gradient"
+        ],
+        "129043": [
+            "sltgrd",
+            "soil type gradient"
+        ],
+        "129044": [
+            "esgrd",
+            "snow evaporation gradient"
+        ],
+        "129045": [
+            "smltgrd",
+            "snowmelt gradient"
+        ],
+        "129046": [
+            "sdurgrd",
+            "solar duration gradient"
+        ],
+        "129047": [
+            "dsrpgrd",
+            "direct solar radiation gradient"
+        ],
+        "129048": [
+            "magssgrd",
+            "magnitude of turbulent surface stress gradient"
+        ],
+        "129049": [
+            "10fggrd",
+            "10 metre wind gust gradient"
+        ],
+        "129050": [
+            "lspfgrd",
+            "large-scale precipitation fraction gradient"
+        ],
+        "129051": [
+            "mx2t24grd",
+            "maximum 2 metre temperature gradient"
+        ],
+        "129052": [
+            "mn2t24grd",
+            "minimum 2 metre temperature gradient"
+        ],
+        "129053": [
+            "montgrd",
+            "montgomery potential gradient"
+        ],
+        "129054": [
+            "presgrd",
+            "pressure gradient"
+        ],
+        "129055": [
+            "mean2t24grd",
+            "mean 2 metre temperature in the last 24 hours gradient"
+        ],
+        "129056": [
+            "mn2d24grd",
+            "mean 2 metre dewpoint temperature in the last 24 hours gradient"
+        ],
+        "129057": [
+            "uvbgrd",
+            "downward uv radiation at the surface gradient"
+        ],
+        "129058": [
+            "pargrd",
+            "photosynthetically active radiation at the surface gradient"
+        ],
+        "129059": [
+            "capegrd",
+            "convective available potential energy gradient"
+        ],
+        "129060": [
+            "pvgrd",
+            "potential vorticity gradient"
+        ],
+        "129061": [
+            "tpogrd",
+            "total precipitation from observations gradient"
+        ],
+        "129062": [
+            "obctgrd",
+            "observation count gradient"
+        ],
+        "129063": [
+            "start time for skin temperature difference"
+        ],
+        "129064": [
+            "finish time for skin temperature difference"
+        ],
+        "129065": [
+            "skin temperature difference"
+        ],
+        "129066": [
+            "leaf area index, low vegetation"
+        ],
+        "129067": [
+            "leaf area index, high vegetation"
+        ],
+        "129068": [
+            "minimum stomatal resistance, low vegetation"
+        ],
+        "129069": [
+            "minimum stomatal resistance, high vegetation"
+        ],
+        "129070": [
+            "biome cover, low vegetation"
+        ],
+        "129071": [
+            "biome cover, high vegetation"
+        ],
+        "129078": [
+            "total column liquid water"
+        ],
+        "129079": [
+            "total column ice water"
+        ],
+        "129121": [
+            "mx2t6grd",
+            "maximum temperature at 2 metres gradient"
+        ],
+        "129122": [
+            "mn2t6grd",
+            "minimum temperature at 2 metres gradient"
+        ],
+        "129123": [
+            "10fg6grd",
+            "10 metre wind gust in the last 6 hours gradient"
+        ],
+        "129125": [
+            "vertically integrated total energy"
+        ],
+        "129126": [
+            "generic parameter for sensitive area prediction"
+        ],
+        "129127": [
+            "atgrd",
+            "atmospheric tide gradient"
+        ],
+        "129128": [
+            "bvgrd",
+            "budget values gradient"
+        ],
+        "129129": [
+            "zgrd",
+            "geopotential gradient"
+        ],
+        "129130": [
+            "tgrd",
+            "temperature gradient"
+        ],
+        "129131": [
+            "ugrd",
+            "u component of wind gradient"
+        ],
+        "129132": [
+            "vgrd",
+            "v component of wind gradient"
+        ],
+        "129133": [
+            "qgrd",
+            "specific humidity gradient"
+        ],
+        "129134": [
+            "spgrd",
+            "surface pressure gradient"
+        ],
+        "129135": [
+            "wgrd",
+            "vertical velocity (pressure) gradient"
+        ],
+        "129136": [
+            "tcwgrd",
+            "total column water gradient"
+        ],
+        "129137": [
+            "tcwvgrd",
+            "total column water vapour gradient"
+        ],
+        "129138": [
+            "vogrd",
+            "vorticity (relative) gradient"
+        ],
+        "129139": [
+            "stl1grd",
+            "soil temperature level 1 gradient"
+        ],
+        "129140": [
+            "swl1grd",
+            "soil wetness level 1 gradient"
+        ],
+        "129141": [
+            "sdgrd",
+            "snow depth gradient"
+        ],
+        "129142": [
+            "lspgrd",
+            "stratiform precipitation (large-scale precipitation) gradient"
+        ],
+        "129143": [
+            "cpgrd",
+            "convective precipitation gradient"
+        ],
+        "129144": [
+            "sfgrd",
+            "snowfall (convective + stratiform) gradient"
+        ],
+        "129145": [
+            "bldgrd",
+            "boundary layer dissipation gradient"
+        ],
+        "129146": [
+            "sshfgrd",
+            "surface sensible heat flux gradient"
+        ],
+        "129147": [
+            "slhfgrd",
+            "surface latent heat flux gradient"
+        ],
+        "129148": [
+            "chnkgrd",
+            "charnock gradient"
+        ],
+        "129149": [
+            "snrgrd",
+            "surface net radiation gradient"
+        ],
+        "129150": [
+            "tnrgrd",
+            "top net radiation gradient"
+        ],
+        "129151": [
+            "mslgrd",
+            "mean sea level pressure gradient"
+        ],
+        "129152": [
+            "lnspgrd",
+            "logarithm of surface pressure gradient"
+        ],
+        "129153": [
+            "swhrgrd",
+            "short-wave heating rate gradient"
+        ],
+        "129154": [
+            "lwhrgrd",
+            "long-wave heating rate gradient"
+        ],
+        "129155": [
+            "dgrd",
+            "divergence gradient"
+        ],
+        "129156": [
+            "ghgrd",
+            "height gradient"
+        ],
+        "129157": [
+            "rgrd",
+            "relative humidity gradient"
+        ],
+        "129158": [
+            "tspgrd",
+            "tendency of surface pressure gradient"
+        ],
+        "129159": [
+            "blhgrd",
+            "boundary layer height gradient"
+        ],
+        "129160": [
+            "sdorgrd",
+            "standard deviation of orography gradient"
+        ],
+        "129161": [
+            "isorgrd",
+            "anisotropy of sub-gridscale orography gradient"
+        ],
+        "129162": [
+            "anorgrd",
+            "angle of sub-gridscale orography gradient"
+        ],
+        "129163": [
+            "slorgrd",
+            "slope of sub-gridscale orography gradient"
+        ],
+        "129164": [
+            "tccgrd",
+            "total cloud cover gradient"
+        ],
+        "129165": [
+            "10ugrd",
+            "10 metre u wind component gradient"
+        ],
+        "129166": [
+            "10vgrd",
+            "10 metre v wind component gradient"
+        ],
+        "129167": [
+            "2tgrd",
+            "2 metre temperature gradient"
+        ],
+        "129168": [
+            "2dgrd",
+            "2 metre dewpoint temperature gradient"
+        ],
+        "129169": [
+            "ssrdgrd",
+            "surface solar radiation downwards gradient"
+        ],
+        "129170": [
+            "stl2grd",
+            "soil temperature level 2 gradient"
+        ],
+        "129171": [
+            "swl2grd",
+            "soil wetness level 2 gradient"
+        ],
+        "129172": [
+            "lsmgrd",
+            "land-sea mask gradient"
+        ],
+        "129173": [
+            "srgrd",
+            "surface roughness gradient"
+        ],
+        "129174": [
+            "algrd",
+            "albedo gradient"
+        ],
+        "129175": [
+            "strdgrd",
+            "surface thermal radiation downwards gradient"
+        ],
+        "129176": [
+            "ssrgrd",
+            "surface net solar radiation gradient"
+        ],
+        "129177": [
+            "strgrd",
+            "surface net thermal radiation gradient"
+        ],
+        "129178": [
+            "tsrgrd",
+            "top net solar radiation gradient"
+        ],
+        "129179": [
+            "ttrgrd",
+            "top net thermal radiation gradient"
+        ],
+        "129180": [
+            "ewssgrd",
+            "east-west surface stress gradient"
+        ],
+        "129181": [
+            "nsssgrd",
+            "north-south surface stress gradient"
+        ],
+        "129182": [
+            "egrd",
+            "evaporation gradient"
+        ],
+        "129183": [
+            "stl3grd",
+            "soil temperature level 3 gradient"
+        ],
+        "129184": [
+            "swl3grd",
+            "soil wetness level 3 gradient"
+        ],
+        "129185": [
+            "cccgrd",
+            "convective cloud cover gradient"
+        ],
+        "129186": [
+            "lccgrd",
+            "low cloud cover gradient"
+        ],
+        "129187": [
+            "mccgrd",
+            "medium cloud cover gradient"
+        ],
+        "129188": [
+            "hccgrd",
+            "high cloud cover gradient"
+        ],
+        "129189": [
+            "sundgrd",
+            "sunshine duration gradient"
+        ],
+        "129190": [
+            "ewovgrd",
+            "east-west component of sub-gridscale orographic variance gradient"
+        ],
+        "129191": [
+            "nsovgrd",
+            "north-south component of sub-gridscale orographic variance gradient"
+        ],
+        "129192": [
+            "nwovgrd",
+            "north-west/south-east component of sub-gridscale orographic variance gradient"
+        ],
+        "129193": [
+            "neovgrd",
+            "north-east/south-west component of sub-gridscale orographic variance gradient"
+        ],
+        "129194": [
+            "btmpgrd",
+            "brightness temperature gradient"
+        ],
+        "129195": [
+            "lgwsgrd",
+            "longitudinal component of gravity wave stress gradient"
+        ],
+        "129196": [
+            "mgwsgrd",
+            "meridional component of gravity wave stress gradient"
+        ],
+        "129197": [
+            "gwdgrd",
+            "gravity wave dissipation gradient"
+        ],
+        "129198": [
+            "srcgrd",
+            "skin reservoir content gradient"
+        ],
+        "129199": [
+            "veggrd",
+            "vegetation fraction gradient"
+        ],
+        "129200": [
+            "vsogrd",
+            "variance of sub-gridscale orography gradient"
+        ],
+        "129201": [
+            "mx2tgrd",
+            "maximum temperature at 2 metres since previous post-processing gradient"
+        ],
+        "129202": [
+            "mn2tgrd",
+            "minimum temperature at 2 metres since previous post-processing gradient"
+        ],
+        "129203": [
+            "o3grd",
+            "ozone mass mixing ratio gradient"
+        ],
+        "129204": [
+            "pawgrd",
+            "precipitation analysis weights gradient"
+        ],
+        "129205": [
+            "rogrd",
+            "runoff gradient"
+        ],
+        "129206": [
+            "tco3grd",
+            "total column ozone gradient"
+        ],
+        "129207": [
+            "10sigrd",
+            "10 metre wind speed gradient"
+        ],
+        "129208": [
+            "tsrcgrd",
+            "top net solar radiation, clear sky gradient"
+        ],
+        "129209": [
+            "ttrcgrd",
+            "top net thermal radiation, clear sky gradient"
+        ],
+        "129210": [
+            "ssrcgrd",
+            "surface net solar radiation, clear sky gradient"
+        ],
+        "129211": [
+            "strcgrd",
+            "surface net thermal radiation, clear sky gradient"
+        ],
+        "129212": [
+            "tisrgrd",
+            "toa incident solar radiation gradient"
+        ],
+        "129214": [
+            "dhrgrd",
+            "diabatic heating by radiation gradient"
+        ],
+        "129215": [
+            "dhvdgrd",
+            "diabatic heating by vertical diffusion gradient"
+        ],
+        "129216": [
+            "dhccgrd",
+            "diabatic heating by cumulus convection gradient"
+        ],
+        "129217": [
+            "dhlcgrd",
+            "diabatic heating large-scale condensation gradient"
+        ],
+        "129218": [
+            "vdzwgrd",
+            "vertical diffusion of zonal wind gradient"
+        ],
+        "129219": [
+            "vdmwgrd",
+            "vertical diffusion of meridional wind gradient"
+        ],
+        "129220": [
+            "ewgdgrd",
+            "east-west gravity wave drag tendency gradient"
+        ],
+        "129221": [
+            "nsgdgrd",
+            "north-south gravity wave drag tendency gradient"
+        ],
+        "129222": [
+            "ctzwgrd",
+            "convective tendency of zonal wind gradient"
+        ],
+        "129223": [
+            "ctmwgrd",
+            "convective tendency of meridional wind gradient"
+        ],
+        "129224": [
+            "vdhgrd",
+            "vertical diffusion of humidity gradient"
+        ],
+        "129225": [
+            "htccgrd",
+            "humidity tendency by cumulus convection gradient"
+        ],
+        "129226": [
+            "htlcgrd",
+            "humidity tendency by large-scale condensation gradient"
+        ],
+        "129227": [
+            "crnhgrd",
+            "change from removal of negative humidity gradient"
+        ],
+        "129228": [
+            "tpgrd",
+            "total precipitation gradient"
+        ],
+        "129229": [
+            "iewsgrd",
+            "instantaneous x surface stress gradient"
+        ],
+        "129230": [
+            "inssgrd",
+            "instantaneous y surface stress gradient"
+        ],
+        "129231": [
+            "ishfgrd",
+            "instantaneous surface heat flux gradient"
+        ],
+        "129232": [
+            "iegrd",
+            "instantaneous moisture flux gradient"
+        ],
+        "129233": [
+            "asqgrd",
+            "apparent surface humidity gradient"
+        ],
+        "129234": [
+            "lsrhgrd",
+            "logarithm of surface roughness length for heat gradient"
+        ],
+        "129235": [
+            "sktgrd",
+            "skin temperature gradient"
+        ],
+        "129236": [
+            "stl4grd",
+            "soil temperature level 4 gradient"
+        ],
+        "129237": [
+            "swl4grd",
+            "soil wetness level 4 gradient"
+        ],
+        "129238": [
+            "tsngrd",
+            "temperature of snow layer gradient"
+        ],
+        "129239": [
+            "csfgrd",
+            "convective snowfall gradient"
+        ],
+        "129240": [
+            "lsfgrd",
+            "large scale snowfall gradient"
+        ],
+        "129241": [
+            "acfgrd",
+            "accumulated cloud fraction tendency gradient"
+        ],
+        "129242": [
+            "alwgrd",
+            "accumulated liquid water tendency gradient"
+        ],
+        "129243": [
+            "falgrd",
+            "forecast albedo gradient"
+        ],
+        "129244": [
+            "fsrgrd",
+            "forecast surface roughness gradient"
+        ],
+        "129245": [
+            "flsrgrd",
+            "forecast logarithm of surface roughness for heat gradient"
+        ],
+        "129246": [
+            "clwcgrd",
+            "specific cloud liquid water content gradient"
+        ],
+        "129247": [
+            "ciwcgrd",
+            "specific cloud ice water content gradient"
+        ],
+        "129248": [
+            "ccgrd",
+            "cloud cover gradient"
+        ],
+        "129249": [
+            "aiwgrd",
+            "accumulated ice water tendency gradient"
+        ],
+        "129250": [
+            "icegrd",
+            "ice age gradient"
+        ],
+        "129251": [
+            "attegrd",
+            "adiabatic tendency of temperature gradient"
+        ],
+        "129252": [
+            "athegrd",
+            "adiabatic tendency of humidity gradient"
+        ],
+        "129253": [
+            "atzegrd",
+            "adiabatic tendency of zonal wind gradient"
+        ],
+        "129254": [
+            "atmwgrd",
+            "adiabatic tendency of meridional wind gradient"
+        ],
+        "13": [
+            "urtw",
+            "u component of rotational wind"
+        ],
+        "130": [
+            "t",
+            "temperature"
+        ],
+        "130208": [
+            "tsru",
+            "top solar radiation upward"
+        ],
+        "130209": [
+            "ttru",
+            "top thermal radiation upward"
+        ],
+        "130210": [
+            "tsuc",
+            "top solar radiation upward, clear sky"
+        ],
+        "130211": [
+            "ttuc",
+            "top thermal radiation upward, clear sky"
+        ],
+        "130212": [
+            "clw",
+            "cloud liquid water"
+        ],
+        "130213": [
+            "cf",
+            "cloud fraction"
+        ],
+        "130214": [
+            "dhr",
+            "diabatic heating by radiation"
+        ],
+        "130215": [
+            "dhvd",
+            "diabatic heating by vertical diffusion"
+        ],
+        "130216": [
+            "dhcc",
+            "diabatic heating by cumulus convection"
+        ],
+        "130217": [
+            "dhlc",
+            "diabatic heating by large-scale condensation"
+        ],
+        "130218": [
+            "vdzw",
+            "vertical diffusion of zonal wind"
+        ],
+        "130219": [
+            "vdmw",
+            "vertical diffusion of meridional wind"
+        ],
+        "130220": [
+            "ewgd",
+            "east-west gravity wave drag"
+        ],
+        "130221": [
+            "nsgd",
+            "north-south gravity wave drag"
+        ],
+        "130224": [
+            "vdh",
+            "vertical diffusion of humidity"
+        ],
+        "130225": [
+            "htcc",
+            "humidity tendency by cumulus convection"
+        ],
+        "130226": [
+            "htlc",
+            "humidity tendency by large-scale condensation"
+        ],
+        "130228": [
+            "att",
+            "adiabatic tendency of temperature"
+        ],
+        "130229": [
+            "ath",
+            "adiabatic tendency of humidity"
+        ],
+        "130230": [
+            "atzw",
+            "adiabatic tendency of zonal wind"
+        ],
+        "130231": [
+            "atmwax",
+            "adiabatic tendency of meridional wind"
+        ],
+        "130232": [
+            "mvv",
+            "mean vertical velocity"
+        ],
+        "131": [
+            "u",
+            "u component of wind"
+        ],
+        "131001": [
+            "2tag2",
+            "2m temperature anomaly of at least +2k"
+        ],
+        "131002": [
+            "2tag1",
+            "2m temperature anomaly of at least +1k"
+        ],
+        "131003": [
+            "2tag0",
+            "2m temperature anomaly of at least 0k"
+        ],
+        "131004": [
+            "2talm1",
+            "2m temperature anomaly of at most -1k"
+        ],
+        "131005": [
+            "2talm2",
+            "2m temperature anomaly of at most -2k"
+        ],
+        "131006": [
+            "tpag20",
+            "total precipitation anomaly of at least 20 mm"
+        ],
+        "131007": [
+            "tpag10",
+            "total precipitation anomaly of at least 10 mm"
+        ],
+        "131008": [
+            "tpag0",
+            "total precipitation anomaly of at least 0 mm"
+        ],
+        "131009": [
+            "stag0",
+            "surface temperature anomaly of at least 0k"
+        ],
+        "131010": [
+            "mslag0",
+            "mean sea level pressure anomaly of at least 0 pa"
+        ],
+        "131015": [
+            "h0dip",
+            "height of 0 degree isotherm probability"
+        ],
+        "131016": [
+            "hslp",
+            "height of snowfall limit probability"
+        ],
+        "131017": [
+            "saip",
+            "showalter index probability"
+        ],
+        "131018": [
+            "whip",
+            "whiting index probability"
+        ],
+        "131020": [
+            "talm2",
+            "temperature anomaly less than -2 k",
+            "temperature anomaly of at most -2 k",
+            "talm2k"
+        ],
+        "131021": [
+            "tag2",
+            "temperature anomaly of at least +2 k",
+            "temperature anomaly of at least 2 k",
+            "tag2k"
+        ],
+        "131022": [
+            "talm8",
+            "temperature anomaly less than -8 k",
+            "temperature anomaly of at most -8 k",
+            "talm8k"
+        ],
+        "131023": [
+            "talm4",
+            "temperature anomaly less than -4 k",
+            "temperature anomaly of at most -4 k",
+            "talm4k"
+        ],
+        "131024": [
+            "tag4",
+            "temperature anomaly greater than +4 k",
+            "temperature anomaly of at least 4 k",
+            "tag4k"
+        ],
+        "131025": [
+            "tag8",
+            "temperature anomaly greater than +8 k",
+            "temperature anomaly of at least 8 k",
+            "tag8k"
+        ],
+        "131049": [
+            "10gp",
+            "10 metre wind gust probability"
+        ],
+        "131059": [
+            "capep",
+            "convective available potential energy probability"
+        ],
+        "131060": [
+            "tpg1",
+            "total precipitation of at least 1 mm"
+        ],
+        "131061": [
+            "tpg5",
+            "total precipitation of at least 5 mm"
+        ],
+        "131062": [
+            "tpg10",
+            "total precipitation of at least 10 mm"
+        ],
+        "131063": [
+            "tpg20",
+            "total precipitation of at least 20 mm"
+        ],
+        "131064": [
+            "tpl01",
+            "total precipitation less than 0.1 mm",
+            "tplo1"
+        ],
+        "131065": [
+            "tprl1",
+            "total precipitation rate less than 1 mm/day"
+        ],
+        "131066": [
+            "tprg3",
+            "total precipitation rate of at least 3 mm/day"
+        ],
+        "131067": [
+            "tprg5",
+            "total precipitation rate of at least 5 mm/day"
+        ],
+        "131068": [
+            "10spg10",
+            "10 metre wind speed of at least 10 m/s"
+        ],
+        "131069": [
+            "10spg15",
+            "10 metre wind speed of at least 15 m/s"
+        ],
+        "131070": [
+            "10fgg15",
+            "10 metre wind gust of at least 15 m/s"
+        ],
+        "131071": [
+            "10fgg20",
+            "10 metre wind gust of at least 20 m/s"
+        ],
+        "131072": [
+            "10fgg25",
+            "10 metre wind gust of at least 25 m/s"
+        ],
+        "131073": [
+            "2tl273",
+            "2 metre temperature less than 273.15 k"
+        ],
+        "131074": [
+            "swhg2",
+            "significant wave height of at least 2 m"
+        ],
+        "131075": [
+            "swhg4",
+            "significant wave height of at least 4 m"
+        ],
+        "131076": [
+            "swhg6",
+            "significant wave height of at least 6 m"
+        ],
+        "131077": [
+            "swhg8",
+            "significant wave height of at least 8 m"
+        ],
+        "131078": [
+            "mwpg8",
+            "mean wave period of at least 8 s"
+        ],
+        "131079": [
+            "mwpg10",
+            "mean wave period of at least 10 s"
+        ],
+        "131080": [
+            "mwpg12",
+            "mean wave period of at least 12 s"
+        ],
+        "131081": [
+            "mwpg15",
+            "mean wave period of at least 15 s"
+        ],
+        "131082": [
+            "tpg40",
+            "total precipitation of at least 40 mm"
+        ],
+        "131083": [
+            "tpg60",
+            "total precipitation of at least 60 mm"
+        ],
+        "131084": [
+            "tpg80",
+            "total precipitation of at least 80 mm"
+        ],
+        "131085": [
+            "tpg100",
+            "total precipitation of at least 100 mm"
+        ],
+        "131086": [
+            "tpg150",
+            "total precipitation of at least 150 mm"
+        ],
+        "131087": [
+            "tpg200",
+            "total precipitation of at least 200 mm"
+        ],
+        "131088": [
+            "tpg300",
+            "total precipitation of at least 300 mm"
+        ],
+        "131089": [
+            "pts",
+            "probability of a tropical storm"
+        ],
+        "131090": [
+            "ph",
+            "probability of a hurricane"
+        ],
+        "131091": [
+            "ptd",
+            "probability of a tropical depression"
+        ],
+        "131092": [
+            "cpts",
+            "climatological probability of a tropical storm"
+        ],
+        "131093": [
+            "cph",
+            "climatological probability of a hurricane"
+        ],
+        "131094": [
+            "cptd",
+            "climatological probability of a tropical depression"
+        ],
+        "131095": [
+            "pats",
+            "probability anomaly of a tropical storm"
+        ],
+        "131096": [
+            "pah",
+            "probability anomaly of a hurricane"
+        ],
+        "131097": [
+            "patd",
+            "probability anomaly of a tropical depression"
+        ],
+        "131129": [
+            "zp",
+            "geopotential probability"
+        ],
+        "131130": [
+            "tap",
+            "temperature anomaly probability"
+        ],
+        "131139": [
+            "stl1p",
+            "soil temperature level 1 probability"
+        ],
+        "131144": [
+            "sfp",
+            "snowfall (convective + stratiform) probability"
+        ],
+        "131151": [
+            "mslpp",
+            "mean sea level pressure probability"
+        ],
+        "131164": [
+            "tccp",
+            "total cloud cover probability"
+        ],
+        "131165": [
+            "10sp",
+            "10 metre speed probability"
+        ],
+        "131167": [
+            "2tp",
+            "2 metre temperature probability"
+        ],
+        "131201": [
+            "mx2tp",
+            "maximum 2 metre temperature probability"
+        ],
+        "131202": [
+            "mn2tp",
+            "minimum 2 metre temperature probability"
+        ],
+        "131228": [
+            "tpp",
+            "total precipitation probability"
+        ],
+        "131229": [
+            "229",
+            "swhp",
+            "significant wave height probability"
+        ],
+        "131232": [
+            "232",
+            "mwpp",
+            "mean wave period probability"
+        ],
+        "132": [
+            "v",
+            "v component of wind"
+        ],
+        "132044": [
+            "capesi",
+            "convective available potential energy shear index"
+        ],
+        "132049": [
+            "10fgi",
+            "10 metre wind gust index",
+            "10gi"
+        ],
+        "132059": [
+            "capei",
+            "convective available potential energy index"
+        ],
+        "132144": [
+            "sfi",
+            "snowfall index"
+        ],
+        "132165": [
+            "10wsi",
+            "10 metre speed index"
+        ],
+        "132167": [
+            "2ti",
+            "2 metre temperature index"
+        ],
+        "132201": [
+            "mx2ti",
+            "maximum temperature at 2 metres index"
+        ],
+        "132202": [
+            "mn2ti",
+            "minimum temperature at 2 metres index"
+        ],
+        "132216": [
+            "216",
+            "maxswhi",
+            "maximum of significant wave height index"
+        ],
+        "132228": [
+            "tpi",
+            "total precipitation index"
+        ],
+        "133": [
+            "q",
+            "specific humidity"
+        ],
+        "133001": [
+            "2tplm10",
+            "2m temperature probability less than -10 c"
+        ],
+        "133002": [
+            "2tplm5",
+            "2m temperature probability less than -5 c"
+        ],
+        "133003": [
+            "2tpl0",
+            "2m temperature probability less than 0 c"
+        ],
+        "133004": [
+            "2tpl5",
+            "2m temperature probability less than 5 c"
+        ],
+        "133005": [
+            "2tpl10",
+            "2m temperature probability less than 10 c"
+        ],
+        "133006": [
+            "2tpg25",
+            "2m temperature probability greater than 25 c"
+        ],
+        "133007": [
+            "2tpg30",
+            "2m temperature probability greater than 30 c"
+        ],
+        "133008": [
+            "2tpg35",
+            "2m temperature probability greater than 35 c"
+        ],
+        "133009": [
+            "2tpg40",
+            "2m temperature probability greater than 40 c"
+        ],
+        "133010": [
+            "2tpg45",
+            "2m temperature probability greater than 45 c"
+        ],
+        "133011": [
+            "mn2tplm10",
+            "minimum 2 metre temperature probability less than -10 c"
+        ],
+        "133012": [
+            "mn2tplm5",
+            "minimum 2 metre temperature probability less than -5 c"
+        ],
+        "133013": [
+            "mn2tpl0",
+            "minimum 2 metre temperature probability less than 0 c"
+        ],
+        "133014": [
+            "mn2tpl5",
+            "minimum 2 metre temperature probability less than 5 c"
+        ],
+        "133015": [
+            "mn2tpl10",
+            "minimum 2 metre temperature probability less than 10 c"
+        ],
+        "133016": [
+            "mx2tpg25",
+            "maximum 2 metre temperature probability greater than 25 c"
+        ],
+        "133017": [
+            "mx2tpg30",
+            "maximum 2 metre temperature probability greater than 30 c"
+        ],
+        "133018": [
+            "mx2tpg35",
+            "maximum 2 metre temperature probability greater than 35 c"
+        ],
+        "133019": [
+            "mx2tpg40",
+            "maximum 2 metre temperature probability greater than 40 c"
+        ],
+        "133020": [
+            "mx2tpg45",
+            "maximum 2 metre temperature probability greater than 45 c"
+        ],
+        "133021": [
+            "10spg10",
+            "10 metre wind speed probability of at least 10 m/s"
+        ],
+        "133022": [
+            "10spg15",
+            "10 metre wind speed probability of at least 15 m/s"
+        ],
+        "133023": [
+            "10spg20",
+            "10 metre wind speed probability of at least 20 m/s"
+        ],
+        "133024": [
+            "10spg35",
+            "10 metre wind speed probability of at least 35 m/s"
+        ],
+        "133025": [
+            "10spg50",
+            "10 metre wind speed probability of at least 50 m/s"
+        ],
+        "133026": [
+            "10gpg20",
+            "10 metre wind gust probability of at least 20 m/s"
+        ],
+        "133027": [
+            "10gpg35",
+            "10 metre wind gust probability of at least 35 m/s"
+        ],
+        "133028": [
+            "10gpg50",
+            "10 metre wind gust probability of at least 50 m/s"
+        ],
+        "133029": [
+            "10gpg75",
+            "10 metre wind gust probability of at least 75 m/s"
+        ],
+        "133030": [
+            "10gpg100",
+            "10 metre wind gust probability of at least 100 m/s"
+        ],
+        "133031": [
+            "tppg1",
+            "total precipitation probability of at least 1 mm"
+        ],
+        "133032": [
+            "tppg5",
+            "total precipitation probability of at least 5 mm"
+        ],
+        "133033": [
+            "tppg10",
+            "total precipitation probability of at least 10 mm"
+        ],
+        "133034": [
+            "tppg20",
+            "total precipitation probability of at least 20 mm"
+        ],
+        "133035": [
+            "tppg40",
+            "total precipitation probability of at least 40 mm"
+        ],
+        "133036": [
+            "tppg60",
+            "total precipitation probability of at least 60 mm"
+        ],
+        "133037": [
+            "tppg80",
+            "total precipitation probability of at least 80 mm"
+        ],
+        "133038": [
+            "tppg100",
+            "total precipitation probability of at least 100 mm"
+        ],
+        "133039": [
+            "tppg150",
+            "total precipitation probability of at least 150 mm"
+        ],
+        "133040": [
+            "tppg200",
+            "total precipitation probability of at least 200 mm"
+        ],
+        "133041": [
+            "tppg300",
+            "total precipitation probability of at least 300 mm"
+        ],
+        "133042": [
+            "sfpg1",
+            "snowfall probability of at least 1 mm"
+        ],
+        "133043": [
+            "sfpg5",
+            "snowfall probability of at least 5 mm"
+        ],
+        "133044": [
+            "sfpg10",
+            "snowfall probability of at least 10 mm"
+        ],
+        "133045": [
+            "sfpg20",
+            "snowfall probability of at least 20 mm"
+        ],
+        "133046": [
+            "sfpg40",
+            "snowfall probability of at least 40 mm"
+        ],
+        "133047": [
+            "sfpg60",
+            "snowfall probability of at least 60 mm"
+        ],
+        "133048": [
+            "sfpg80",
+            "snowfall probability of at least 80 mm"
+        ],
+        "133049": [
+            "sfpg100",
+            "snowfall probability of at least 100 mm"
+        ],
+        "133050": [
+            "sfpg150",
+            "snowfall probability of at least 150 mm"
+        ],
+        "133051": [
+            "sfpg200",
+            "snowfall probability of at least 200 mm"
+        ],
+        "133052": [
+            "sfpg300",
+            "snowfall probability of at least 300 mm"
+        ],
+        "133053": [
+            "tccpg10",
+            "total cloud cover probability greater than 10%"
+        ],
+        "133054": [
+            "tccpg20",
+            "total cloud cover probability greater than 20%"
+        ],
+        "133055": [
+            "tccpg30",
+            "total cloud cover probability greater than 30%"
+        ],
+        "133056": [
+            "tccpg40",
+            "total cloud cover probability greater than 40%"
+        ],
+        "133057": [
+            "tccpg50",
+            "total cloud cover probability greater than 50%"
+        ],
+        "133058": [
+            "tccpg60",
+            "total cloud cover probability greater than 60%"
+        ],
+        "133059": [
+            "tccpg70",
+            "total cloud cover probability greater than 70%"
+        ],
+        "133060": [
+            "tccpg80",
+            "total cloud cover probability greater than 80%"
+        ],
+        "133061": [
+            "tccpg90",
+            "total cloud cover probability greater than 90%"
+        ],
+        "133062": [
+            "tccpg99",
+            "total cloud cover probability greater than 99%"
+        ],
+        "133063": [
+            "hccpg10",
+            "high cloud cover probability greater than 10%"
+        ],
+        "133064": [
+            "hccpg20",
+            "high cloud cover probability greater than 20%"
+        ],
+        "133065": [
+            "hccpg30",
+            "high cloud cover probability greater than 30%"
+        ],
+        "133066": [
+            "hccpg40",
+            "high cloud cover probability greater than 40%"
+        ],
+        "133067": [
+            "hccpg50",
+            "high cloud cover probability greater than 50%"
+        ],
+        "133068": [
+            "hccpg60",
+            "high cloud cover probability greater than 60%"
+        ],
+        "133069": [
+            "hccpg70",
+            "high cloud cover probability greater than 70%"
+        ],
+        "133070": [
+            "hccpg80",
+            "high cloud cover probability greater than 80%"
+        ],
+        "133071": [
+            "hccpg90",
+            "high cloud cover probability greater than 90%"
+        ],
+        "133072": [
+            "hccpg99",
+            "high cloud cover probability greater than 99%"
+        ],
+        "133073": [
+            "mccpg10",
+            "medium cloud cover probability greater than 10%"
+        ],
+        "133074": [
+            "mccpg20",
+            "medium cloud cover probability greater than 20%"
+        ],
+        "133075": [
+            "mccpg30",
+            "medium cloud cover probability greater than 30%"
+        ],
+        "133076": [
+            "mccpg40",
+            "medium cloud cover probability greater than 40%"
+        ],
+        "133077": [
+            "mccpg50",
+            "medium cloud cover probability greater than 50%"
+        ],
+        "133078": [
+            "mccpg60",
+            "medium cloud cover probability greater than 60%"
+        ],
+        "133079": [
+            "mccpg70",
+            "medium cloud cover probability greater than 70%"
+        ],
+        "133080": [
+            "mccpg80",
+            "medium cloud cover probability greater than 80%"
+        ],
+        "133081": [
+            "mccpg90",
+            "medium cloud cover probability greater than 90%"
+        ],
+        "133082": [
+            "mccpg99",
+            "medium cloud cover probability greater than 99%"
+        ],
+        "133083": [
+            "lccpg10",
+            "low cloud cover probability greater than 10%"
+        ],
+        "133084": [
+            "lccpg20",
+            "low cloud cover probability greater than 20%"
+        ],
+        "133085": [
+            "lccpg30",
+            "low cloud cover probability greater than 30%"
+        ],
+        "133086": [
+            "lccpg40",
+            "low cloud cover probability greater than 40%"
+        ],
+        "133087": [
+            "lccpg50",
+            "low cloud cover probability greater than 50%"
+        ],
+        "133088": [
+            "lccpg60",
+            "low cloud cover probability greater than 60%"
+        ],
+        "133089": [
+            "lccpg70",
+            "low cloud cover probability greater than 70%"
+        ],
+        "133090": [
+            "lccpg80",
+            "low cloud cover probability greater than 80%"
+        ],
+        "133091": [
+            "lccpg90",
+            "low cloud cover probability greater than 90%"
+        ],
+        "133092": [
+            "lccpg99",
+            "low cloud cover probability greater than 99%"
+        ],
+        "134": [
+            "sp",
+            "surface pressure"
+        ],
+        "135": [
+            "w",
+            "vertical velocity"
+        ],
+        "136": [
+            "tcw",
+            "total column water"
+        ],
+        "137": [
+            "tcwv",
+            "total column water vapour"
+        ],
+        "138": [
+            "vo",
+            "vorticity (relative)"
+        ],
+        "139": [
+            "stl1",
+            "soil temperature level 1",
+            "st"
+        ],
+        "14": [
+            "vrtw",
+            "v component of rotational wind"
+        ],
+        "140": [
+            "swl1",
+            "soil wetness level 1"
+        ],
+        "140080": [
+            "wx1",
+            "wave experimental parameter 1"
+        ],
+        "140081": [
+            "wx2",
+            "wave experimental parameter 2"
+        ],
+        "140082": [
+            "wx3",
+            "wave experimental parameter 3"
+        ],
+        "140083": [
+            "wx4",
+            "wave experimental parameter 4"
+        ],
+        "140084": [
+            "wx5",
+            "wave experimental parameter 5"
+        ],
+        "140112": [
+            "112",
+            "wefxm",
+            "wave energy flux magnitude"
+        ],
+        "140113": [
+            "113",
+            "wefxd",
+            "wave energy flux mean direction"
+        ],
+        "140114": [
+            "114",
+            "h1012",
+            "significant wave height of all waves with periods within the inclusive range from 10 to 12 seconds"
+        ],
+        "140115": [
+            "115",
+            "h1214",
+            "significant wave height of all waves with periods within the inclusive range from 12 to 14 seconds"
+        ],
+        "140116": [
+            "116",
+            "h1417",
+            "significant wave height of all waves with periods within the inclusive range from 14 to 17 seconds"
+        ],
+        "140117": [
+            "117",
+            "h1721",
+            "significant wave height of all waves with periods within the inclusive range from 17 to 21 seconds"
+        ],
+        "140118": [
+            "118",
+            "h2125",
+            "significant wave height of all waves with periods within the inclusive range from 21 to 25 seconds"
+        ],
+        "140119": [
+            "119",
+            "h2530",
+            "significant wave height of all waves with periods within the inclusive range from 25 to 30 seconds"
+        ],
+        "140120": [
+            "120",
+            "sh10",
+            "significant wave height of all waves with period larger than 10s"
+        ],
+        "140121": [
+            "121",
+            "swh1",
+            "significant wave height of first swell partition"
+        ],
+        "140122": [
+            "122",
+            "mwd1",
+            "mean wave direction of first swell partition"
+        ],
+        "140123": [
+            "123",
+            "mwp1",
+            "mean wave period of first swell partition"
+        ],
+        "140124": [
+            "124",
+            "swh2",
+            "significant wave height of second swell partition"
+        ],
+        "140125": [
+            "125",
+            "mwd2",
+            "mean wave direction of second swell partition"
+        ],
+        "140126": [
+            "126",
+            "mwp2",
+            "mean wave period of second swell partition"
+        ],
+        "140127": [
+            "127",
+            "swh3",
+            "significant wave height of third swell partition"
+        ],
+        "140128": [
+            "128",
+            "mwd3",
+            "mean wave direction of third swell partition"
+        ],
+        "140129": [
+            "129",
+            "mwp3",
+            "mean wave period of third swell partition"
+        ],
+        "140200": [
+            "200",
+            "maxswh",
+            "maximum of significant wave height"
+        ],
+        "140207": [
+            "207",
+            "wss",
+            "wave spectral skewness"
+        ],
+        "140208": [
+            "208",
+            "wstar",
+            "free convective velocity over the oceans"
+        ],
+        "140209": [
+            "209",
+            "rhoao",
+            "air density over the oceans"
+        ],
+        "140210": [
+            "210",
+            "mswsi",
+            "mean square wave strain in sea ice"
+        ],
+        "140211": [
+            "211",
+            "phiaw",
+            "normalized energy flux into waves"
+        ],
+        "140212": [
+            "212",
+            "phioc",
+            "normalized energy flux into ocean"
+        ],
+        "140213": [
+            "213",
+            "tla",
+            "turbulent langmuir number"
+        ],
+        "140214": [
+            "214",
+            "tauoc",
+            "normalized stress into ocean"
+        ],
+        "140215": [
+            "215",
+            "ust",
+            "u-component stokes drift"
+        ],
+        "140216": [
+            "216",
+            "vst",
+            "v-component stokes drift"
+        ],
+        "140217": [
+            "217",
+            "tmax",
+            "period corresponding to maximum individual wave height"
+        ],
+        "140218": [
+            "218",
+            "hmax",
+            "maximum individual wave height"
+        ],
+        "140219": [
+            "219",
+            "wmb",
+            "model bathymetry"
+        ],
+        "140220": [
+            "220",
+            "mp1",
+            "mean wave period based on first moment"
+        ],
+        "140221": [
+            "221",
+            "mp2",
+            "mean wave period based on second moment"
+        ],
+        "140222": [
+            "222",
+            "wdw",
+            "wave spectral directional width"
+        ],
+        "140223": [
+            "223",
+            "p1ww",
+            "mean wave period based on first moment for wind waves"
+        ],
+        "140224": [
+            "224",
+            "p2ww",
+            "mean wave period based on second moment for wind waves"
+        ],
+        "140225": [
+            "225",
+            "dwww",
+            "wave spectral directional width for wind waves"
+        ],
+        "140226": [
+            "226",
+            "p1ps",
+            "mean wave period based on first moment for swell"
+        ],
+        "140227": [
+            "227",
+            "p2ps",
+            "mean wave period based on second moment for swell"
+        ],
+        "140228": [
+            "228",
+            "dwps",
+            "wave spectral directional width for swell"
+        ],
+        "140229": [
+            "229",
+            "swh",
+            "significant height of combined wind waves and swell"
+        ],
+        "140230": [
+            "230",
+            "mwd",
+            "mean wave direction"
+        ],
+        "140231": [
+            "231",
+            "pp1d",
+            "peak period of 1d spectra"
+        ],
+        "140232": [
+            "232",
+            "mwp",
+            "mean wave period"
+        ],
+        "140233": [
+            "233",
+            "cdww",
+            "coefficient of drag with waves"
+        ],
+        "140234": [
+            "234",
+            "shww",
+            "significant height of wind waves"
+        ],
+        "140235": [
+            "235",
+            "mdww",
+            "mean direction of wind waves"
+        ],
+        "140236": [
+            "236",
+            "mpww",
+            "mean period of wind waves"
+        ],
+        "140237": [
+            "237",
+            "shts",
+            "significant height of total swell"
+        ],
+        "140238": [
+            "238",
+            "mdts",
+            "mean direction of total swell"
+        ],
+        "140239": [
+            "239",
+            "mpts",
+            "mean period of total swell"
+        ],
+        "140240": [
+            "240",
+            "sdhs",
+            "standard deviation wave height"
+        ],
+        "140241": [
+            "241",
+            "mu10",
+            "mean of 10 metre wind speed"
+        ],
+        "140242": [
+            "242",
+            "mdwi",
+            "mean wind direction"
+        ],
+        "140243": [
+            "243",
+            "sdu",
+            "standard deviation of 10 metre wind speed"
+        ],
+        "140244": [
+            "244",
+            "msqs",
+            "mean square slope of waves"
+        ],
+        "140245": [
+            "245",
+            "wind",
+            "10 metre wind speed"
+        ],
+        "140246": [
+            "246",
+            "awh",
+            "altimeter wave height"
+        ],
+        "140247": [
+            "247",
+            "acwh",
+            "altimeter corrected wave height"
+        ],
+        "140248": [
+            "248",
+            "arrc",
+            "altimeter range relative correction"
+        ],
+        "140249": [
+            "249",
+            "dwi",
+            "10 metre wind direction"
+        ],
+        "140250": [
+            "250",
+            "2dsp",
+            "2d wave spectra (multiple)"
+        ],
+        "140251": [
+            "251",
+            "2dfd",
+            "2d wave spectra (single)"
+        ],
+        "140252": [
+            "252",
+            "wsk",
+            "wave spectral kurtosis"
+        ],
+        "140253": [
+            "253",
+            "bfi",
+            "benjamin-feir index"
+        ],
+        "140254": [
+            "254",
+            "wsp",
+            "wave spectral peakedness"
+        ],
+        "141": [
+            "sd",
+            "snow depth"
+        ],
+        "142": [
+            "lsp",
+            "large-scale precipitation"
+        ],
+        "143": [
+            "cp",
+            "convective precipitation"
+        ],
+        "144": [
+            "sf",
+            "snowfall"
+        ],
+        "145": [
+            "bld",
+            "boundary layer dissipation"
+        ],
+        "146": [
+            "sshf",
+            "surface sensible heat flux"
+        ],
+        "147": [
+            "slhf",
+            "surface latent heat flux"
+        ],
+        "148": [
+            "chnk",
+            "charnock",
+            "ss"
+        ],
+        "149": [
+            "snr",
+            "surface net radiation"
+        ],
+        "15": [
+            "aluvp",
+            "uv visible albedo for direct radiation"
+        ],
+        "150": [
+            "tnr",
+            "top net radiation"
+        ],
+        "150129": [
+            "ocpt",
+            "ocean potential temperature"
+        ],
+        "150130": [
+            "ocs",
+            "ocean salinity"
+        ],
+        "150131": [
+            "ocpd",
+            "ocean potential density"
+        ],
+        "150133": [
+            "ocu",
+            "ocean u wind component"
+        ],
+        "150134": [
+            "ocv",
+            "ocean v wind component"
+        ],
+        "150135": [
+            "ocw",
+            "ocean w wind component"
+        ],
+        "150137": [
+            "rn",
+            "richardson number"
+        ],
+        "150139": [
+            "uv",
+            "u*v product"
+        ],
+        "150140": [
+            "ut",
+            "u*t product"
+        ],
+        "150141": [
+            "vt",
+            "v*t product"
+        ],
+        "150142": [
+            "uu",
+            "u*u product"
+        ],
+        "150143": [
+            "vv",
+            "v*v product"
+        ],
+        "150144": [
+            "uv - u~v~"
+        ],
+        "150145": [
+            "ut - u~t~"
+        ],
+        "150146": [
+            "vt - v~t~"
+        ],
+        "150147": [
+            "uu - u~u~"
+        ],
+        "150148": [
+            "vv - v~v~"
+        ],
+        "150152": [
+            "sl",
+            "sea level"
+        ],
+        "150153": [
+            "barotropic stream function"
+        ],
+        "150154": [
+            "mld",
+            "mixed layer depth"
+        ],
+        "150155": [
+            "depth"
+        ],
+        "150168": [
+            "u stress"
+        ],
+        "150169": [
+            "v stress"
+        ],
+        "150170": [
+            "turbulent kinetic energy input"
+        ],
+        "150171": [
+            "nsf",
+            "net surface heat flux"
+        ],
+        "150172": [
+            "surface solar radiation"
+        ],
+        "150173": [
+            "p-e"
+        ],
+        "150180": [
+            "diagnosed sea surface temperature error"
+        ],
+        "150181": [
+            "heat flux correction"
+        ],
+        "150182": [
+            "observed sea surface temperature"
+        ],
+        "150183": [
+            "observed heat flux"
+        ],
+        "151": [
+            "msl",
+            "mean sea level pressure"
+        ],
+        "151128": [
+            "in situ temperature"
+        ],
+        "151129": [
+            "ocpt",
+            "ocean potential temperature"
+        ],
+        "151130": [
+            "s",
+            "salinity"
+        ],
+        "151131": [
+            "ocu",
+            "ocean current zonal component"
+        ],
+        "151132": [
+            "ocv",
+            "ocean current meridional component"
+        ],
+        "151133": [
+            "ocw",
+            "ocean current vertical component"
+        ],
+        "151134": [
+            "mst",
+            "modulus of strain rate tensor"
+        ],
+        "151135": [
+            "vvs",
+            "vertical viscosity"
+        ],
+        "151136": [
+            "vdf",
+            "vertical diffusivity"
+        ],
+        "151137": [
+            "dep",
+            "bottom level depth"
+        ],
+        "151138": [
+            "sth",
+            "sigma-theta"
+        ],
+        "151139": [
+            "rn",
+            "richardson number"
+        ],
+        "151140": [
+            "uv",
+            "uv product"
+        ],
+        "151141": [
+            "ut",
+            "ut product"
+        ],
+        "151142": [
+            "vt",
+            "vt product"
+        ],
+        "151143": [
+            "uu",
+            "uu product"
+        ],
+        "151144": [
+            "vv",
+            "vv product"
+        ],
+        "151145": [
+            "sl",
+            "sea level"
+        ],
+        "151146": [
+            "sl_1",
+            "sea level previous timestep"
+        ],
+        "151147": [
+            "bsf",
+            "barotropic stream function"
+        ],
+        "151148": [
+            "mld",
+            "mixed layer depth"
+        ],
+        "151149": [
+            "btp",
+            "bottom pressure (equivalent height)"
+        ],
+        "151150": [
+            "sh",
+            "steric height"
+        ],
+        "151151": [
+            "crl",
+            "curl of wind stress"
+        ],
+        "151152": [
+            "divergence of wind stress"
+        ],
+        "151153": [
+            "tax",
+            "u stress"
+        ],
+        "151154": [
+            "tay",
+            "v stress"
+        ],
+        "151155": [
+            "tki",
+            "turbulent kinetic energy input"
+        ],
+        "151156": [
+            "nsf",
+            "net surface heat flux"
+        ],
+        "151157": [
+            "asr",
+            "absorbed solar radiation"
+        ],
+        "151158": [
+            "pme",
+            "precipitation - evaporation"
+        ],
+        "151159": [
+            "sst",
+            "specified sea surface temperature"
+        ],
+        "151160": [
+            "shf",
+            "specified surface heat flux"
+        ],
+        "151161": [
+            "dte",
+            "diagnosed sea surface temperature error"
+        ],
+        "151162": [
+            "hfc",
+            "heat flux correction"
+        ],
+        "151163": [
+            "20d",
+            "20 degrees isotherm depth"
+        ],
+        "151164": [
+            "tav300",
+            "average potential temperature in the upper 300m"
+        ],
+        "151165": [
+            "uba1",
+            "vertically integrated zonal velocity (previous time step)"
+        ],
+        "151166": [
+            "vba1",
+            "vertically integrated meridional velocity (previous time step)"
+        ],
+        "151167": [
+            "ztr",
+            "vertically integrated zonal volume transport"
+        ],
+        "151168": [
+            "mtr",
+            "vertically integrated meridional volume transport"
+        ],
+        "151169": [
+            "zht",
+            "vertically integrated zonal heat transport"
+        ],
+        "151170": [
+            "mht",
+            "vertically integrated meridional heat transport"
+        ],
+        "151171": [
+            "umax",
+            "u velocity maximum"
+        ],
+        "151172": [
+            "dumax",
+            "depth of the velocity maximum"
+        ],
+        "151173": [
+            "smax",
+            "salinity maximum"
+        ],
+        "151174": [
+            "dsmax",
+            "depth of salinity maximum"
+        ],
+        "151175": [
+            "sav300",
+            "average salinity in the upper 300m"
+        ],
+        "151176": [
+            "ldp",
+            "layer thickness at scalar points"
+        ],
+        "151177": [
+            "ldu",
+            "layer thickness at vector points"
+        ],
+        "151178": [
+            "pti",
+            "potential temperature increment"
+        ],
+        "151179": [
+            "ptae",
+            "potential temperature analysis error"
+        ],
+        "151180": [
+            "bpt",
+            "background potential temperature"
+        ],
+        "151181": [
+            "apt",
+            "analysed potential temperature"
+        ],
+        "151182": [
+            "ptbe",
+            "potential temperature background error"
+        ],
+        "151183": [
+            "as",
+            "analysed salinity"
+        ],
+        "151184": [
+            "sali",
+            "salinity increment"
+        ],
+        "151185": [
+            "ebt",
+            "estimated bias in temperature"
+        ],
+        "151186": [
+            "ebs",
+            "estimated bias in salinity"
+        ],
+        "151187": [
+            "uvi",
+            "zonal velocity increment (from balance operator)"
+        ],
+        "151188": [
+            "vvi",
+            "meridional velocity increment (from balance operator)"
+        ],
+        "151190": [
+            "subi",
+            "salinity increment (from salinity data)"
+        ],
+        "151191": [
+            "sale",
+            "salinity analysis error"
+        ],
+        "151192": [
+            "bsal",
+            "background salinity"
+        ],
+        "151194": [
+            "salbe",
+            "salinity background error"
+        ],
+        "151199": [
+            "ebta",
+            "estimated temperature bias from assimilation"
+        ],
+        "151200": [
+            "ebsa",
+            "estimated salinity bias from assimilation"
+        ],
+        "151201": [
+            "lti",
+            "temperature increment from relaxation term"
+        ],
+        "151202": [
+            "lsi",
+            "salinity increment from relaxation term"
+        ],
+        "151203": [
+            "bzpga",
+            "bias in the zonal pressure gradient (applied)"
+        ],
+        "151204": [
+            "bmpga",
+            "bias in the meridional pressure gradient (applied)"
+        ],
+        "151205": [
+            "ebtl",
+            "estimated temperature bias from relaxation"
+        ],
+        "151206": [
+            "ebsl",
+            "estimated salinity bias from relaxation"
+        ],
+        "151207": [
+            "fgbt",
+            "first guess bias in temperature"
+        ],
+        "151208": [
+            "fgbs",
+            "first guess bias in salinity"
+        ],
+        "151209": [
+            "bpa",
+            "applied bias in pressure"
+        ],
+        "151210": [
+            "fgbp",
+            "fg bias in pressure"
+        ],
+        "151211": [
+            "pta",
+            "bias in temperature(applied)"
+        ],
+        "151212": [
+            "psa",
+            "bias in salinity (applied)"
+        ],
+        "152": [
+            "lnsp",
+            "logarithm of surface pressure"
+        ],
+        "153": [
+            "swhr",
+            "short-wave heating rate"
+        ],
+        "154": [
+            "lwhr",
+            "long-wave heating rate"
+        ],
+        "155": [
+            "d",
+            "divergence"
+        ],
+        "156": [
+            "gh",
+            "geopotential height"
+        ],
+        "157": [
+            "r",
+            "relative humidity"
+        ],
+        "158": [
+            "tsp",
+            "tendency of surface pressure"
+        ],
+        "159": [
+            "blh",
+            "boundary layer height"
+        ],
+        "16": [
+            "aluvd",
+            "uv visible albedo for diffuse radiation"
+        ],
+        "160": [
+            "sdor",
+            "standard deviation of orography"
+        ],
+        "160049": [
+            "10fgrea",
+            "10 metre wind gust during averaging time"
+        ],
+        "160135": [
+            "wrea",
+            "vertical velocity (pressure)"
+        ],
+        "160137": [
+            "pwcrea",
+            "precipitable water content"
+        ],
+        "160140": [
+            "swl1rea",
+            "soil wetness level 1"
+        ],
+        "160141": [
+            "sdrea",
+            "snow depth"
+        ],
+        "160142": [
+            "lsprea",
+            "large-scale precipitation"
+        ],
+        "160143": [
+            "cprea",
+            "convective precipitation"
+        ],
+        "160144": [
+            "sfrea",
+            "snowfall"
+        ],
+        "160156": [
+            "ghrea",
+            "height"
+        ],
+        "160157": [
+            "rrea",
+            "relative humidity"
+        ],
+        "160171": [
+            "swl2rea",
+            "soil wetness level 2"
+        ],
+        "160180": [
+            "ewssrea",
+            "east-west surface stress"
+        ],
+        "160181": [
+            "nsssrea",
+            "north-south surface stress"
+        ],
+        "160182": [
+            "erea",
+            "evaporation"
+        ],
+        "160184": [
+            "swl3rea",
+            "soil wetness level 3"
+        ],
+        "160198": [
+            "srcrea",
+            "skin reservoir content"
+        ],
+        "160199": [
+            "vegrea",
+            "percentage of vegetation"
+        ],
+        "160201": [
+            "mx2trea",
+            "maximum temperature at 2 metres during averaging time"
+        ],
+        "160202": [
+            "mn2trea",
+            "minimum temperature at 2 metres during averaging time"
+        ],
+        "160205": [
+            "rorea",
+            "runoff"
+        ],
+        "160206": [
+            "zzrea",
+            "standard deviation of geopotential"
+        ],
+        "160207": [
+            "tzrea",
+            "covariance of temperature and geopotential"
+        ],
+        "160208": [
+            "ttrea",
+            "standard deviation of temperature"
+        ],
+        "160209": [
+            "qzrea",
+            "covariance of specific humidity and geopotential"
+        ],
+        "160210": [
+            "qtrea",
+            "covariance of specific humidity and temperature"
+        ],
+        "160211": [
+            "qqrea",
+            "standard deviation of specific humidity"
+        ],
+        "160212": [
+            "uzrea",
+            "covariance of u component and geopotential"
+        ],
+        "160213": [
+            "utrea",
+            "covariance of u component and temperature"
+        ],
+        "160214": [
+            "uqrea",
+            "covariance of u component and specific humidity"
+        ],
+        "160215": [
+            "uurea",
+            "standard deviation of u velocity"
+        ],
+        "160216": [
+            "vzrea",
+            "covariance of v component and geopotential"
+        ],
+        "160217": [
+            "vtrea",
+            "covariance of v component and temperature"
+        ],
+        "160218": [
+            "vqrea",
+            "covariance of v component and specific humidity"
+        ],
+        "160219": [
+            "vurea",
+            "covariance of v component and u component"
+        ],
+        "160220": [
+            "vvrea",
+            "standard deviation of v component"
+        ],
+        "160221": [
+            "wzrea",
+            "covariance of w component and geopotential"
+        ],
+        "160222": [
+            "wtrea",
+            "covariance of w component and temperature"
+        ],
+        "160223": [
+            "wqrea",
+            "covariance of w component and specific humidity"
+        ],
+        "160224": [
+            "wurea",
+            "covariance of w component and u component"
+        ],
+        "160225": [
+            "wvrea",
+            "covariance of w component and v component"
+        ],
+        "160226": [
+            "wwrea",
+            "standard deviation of vertical velocity"
+        ],
+        "160231": [
+            "ishfrea",
+            "instantaneous surface heat flux"
+        ],
+        "160239": [
+            "csfrea",
+            "convective snowfall"
+        ],
+        "160240": [
+            "lsfrea",
+            "large scale snowfall"
+        ],
+        "160241": [
+            "clwcerrea",
+            "cloud liquid water content"
+        ],
+        "160242": [
+            "ccrea",
+            "cloud cover"
+        ],
+        "160243": [
+            "falrea",
+            "forecast albedo"
+        ],
+        "160246": [
+            "10wsrea",
+            "10 metre wind speed"
+        ],
+        "160247": [
+            "moflrea",
+            "momentum flux"
+        ],
+        "160249": [
+            "gravity wave dissipation flux"
+        ],
+        "160254": [
+            "hsdrea",
+            "heaviside beta function"
+        ],
+        "161": [
+            "isor",
+            "anisotropy of sub-gridscale orography"
+        ],
+        "162": [
+            "anor",
+            "angle of sub-gridscale orography"
+        ],
+        "162051": [
+            "surface geopotential"
+        ],
+        "162053": [
+            "vima",
+            "vertical integral of mass of atmosphere"
+        ],
+        "162054": [
+            "vit",
+            "vertical integral of temperature"
+        ],
+        "162055": [
+            "viwv",
+            "vertical integral of water vapour"
+        ],
+        "162056": [
+            "vilw",
+            "vertical integral of cloud liquid water"
+        ],
+        "162057": [
+            "viiw",
+            "vertical integral of cloud frozen water"
+        ],
+        "162058": [
+            "vioz",
+            "vertical integral of ozone"
+        ],
+        "162059": [
+            "vike",
+            "vertical integral of kinetic energy"
+        ],
+        "162060": [
+            "vithe",
+            "vertical integral of thermal energy"
+        ],
+        "162061": [
+            "vipie",
+            "vertical integral of potential+internal energy"
+        ],
+        "162062": [
+            "vipile",
+            "vertical integral of potential+internal+latent energy"
+        ],
+        "162063": [
+            "vitoe",
+            "vertical integral of total energy"
+        ],
+        "162064": [
+            "viec",
+            "vertical integral of energy conversion"
+        ],
+        "162065": [
+            "vimae",
+            "vertical integral of eastward mass flux"
+        ],
+        "162066": [
+            "viman",
+            "vertical integral of northward mass flux"
+        ],
+        "162067": [
+            "vikee",
+            "vertical integral of eastward kinetic energy flux"
+        ],
+        "162068": [
+            "viken",
+            "vertical integral of northward kinetic energy flux"
+        ],
+        "162069": [
+            "vithee",
+            "vertical integral of eastward heat flux"
+        ],
+        "162070": [
+            "vithen",
+            "vertical integral of northward heat flux"
+        ],
+        "162071": [
+            "viwve",
+            "vertical integral of eastward water vapour flux"
+        ],
+        "162072": [
+            "viwvn",
+            "vertical integral of northward water vapour flux"
+        ],
+        "162073": [
+            "vige",
+            "vertical integral of eastward geopotential flux"
+        ],
+        "162074": [
+            "vign",
+            "vertical integral of northward geopotential flux"
+        ],
+        "162075": [
+            "vitoee",
+            "vertical integral of eastward total energy flux"
+        ],
+        "162076": [
+            "vitoen",
+            "vertical integral of northward total energy flux"
+        ],
+        "162077": [
+            "vioze",
+            "vertical integral of eastward ozone flux"
+        ],
+        "162078": [
+            "viozn",
+            "vertical integral of northward ozone flux"
+        ],
+        "162079": [
+            "vilwd",
+            "vertical integral of divergence of cloud liquid water flux"
+        ],
+        "162080": [
+            "viiwd",
+            "vertical integral of divergence of cloud frozen water flux"
+        ],
+        "162081": [
+            "vimad",
+            "vertical integral of divergence of mass flux"
+        ],
+        "162082": [
+            "viked",
+            "vertical integral of divergence of kinetic energy flux"
+        ],
+        "162083": [
+            "vithed",
+            "vertical integral of divergence of thermal energy flux"
+        ],
+        "162084": [
+            "viwvd",
+            "vertical integral of divergence of moisture flux"
+        ],
+        "162085": [
+            "vigd",
+            "vertical integral of divergence of geopotential flux"
+        ],
+        "162086": [
+            "vitoed",
+            "vertical integral of divergence of total energy flux"
+        ],
+        "162087": [
+            "viozd",
+            "vertical integral of divergence of ozone flux"
+        ],
+        "162088": [
+            "vilwe",
+            "vertical integral of eastward cloud liquid water flux"
+        ],
+        "162089": [
+            "vilwn",
+            "vertical integral of northward cloud liquid water flux"
+        ],
+        "162090": [
+            "viiwe",
+            "vertical integral of eastward cloud frozen water flux"
+        ],
+        "162091": [
+            "viiwn",
+            "vertical integral of northward cloud frozen water flux "
+        ],
+        "162092": [
+            "vimat",
+            "vertical integral of mass tendency"
+        ],
+        "162100": [
+            "srta",
+            "tendency of short wave radiation"
+        ],
+        "162101": [
+            "trta",
+            "tendency of long wave radiation"
+        ],
+        "162102": [
+            "srtca",
+            "tendency of clear sky short wave radiation"
+        ],
+        "162103": [
+            "trtca",
+            "tendency of clear sky long wave radiation"
+        ],
+        "162104": [
+            "umfa",
+            "updraught mass flux"
+        ],
+        "162105": [
+            "dmfa",
+            "downdraught mass flux"
+        ],
+        "162106": [
+            "udra",
+            "updraught detrainment rate"
+        ],
+        "162107": [
+            "ddra",
+            "downdraught detrainment rate"
+        ],
+        "162108": [
+            "tpfa",
+            "total precipitation flux"
+        ],
+        "162109": [
+            "tdcha",
+            "turbulent diffusion coefficient for heat"
+        ],
+        "162110": [
+            "ttpha",
+            "tendency of temperature due to physics"
+        ],
+        "162111": [
+            "qtpha",
+            "tendency of specific humidity due to physics"
+        ],
+        "162112": [
+            "utpha",
+            "tendency of u component due to physics"
+        ],
+        "162113": [
+            "vtpha",
+            "tendency of v component due to physics"
+        ],
+        "162114": [
+            "utendd",
+            "u-tendency from dynamics"
+        ],
+        "162115": [
+            "vtendd",
+            "v-tendency from dynamics"
+        ],
+        "162116": [
+            "ttendd",
+            "t-tendency from dynamics"
+        ],
+        "162117": [
+            "qtendd",
+            "q-tendency from dynamics"
+        ],
+        "162118": [
+            "ttendr",
+            "t-tendency from radiation"
+        ],
+        "162119": [
+            "utendts",
+            "u-tendency from turbulent diffusion + subgrid orography"
+        ],
+        "162120": [
+            "vtendts",
+            "v-tendency from turbulent diffusion + subgrid orography"
+        ],
+        "162121": [
+            "ttendts",
+            "t-tendency from turbulent diffusion + subgrid orography"
+        ],
+        "162122": [
+            "qtendt",
+            "q-tendency from turbulent diffusion"
+        ],
+        "162123": [
+            "utends",
+            "u-tendency from subgrid orography"
+        ],
+        "162124": [
+            "vtends",
+            "v-tendency from subgrid orography"
+        ],
+        "162125": [
+            "ttends",
+            "t-tendency from subgrid orography"
+        ],
+        "162126": [
+            "utendcds",
+            "u-tendency from convection (deep+shallow)"
+        ],
+        "162127": [
+            "vtendcds",
+            "v-tendency from convection (deep+shallow)"
+        ],
+        "162128": [
+            "ttendcds",
+            "t-tendency from convection (deep+shallow)"
+        ],
+        "162129": [
+            "qtendcds",
+            "q-tendency from convection (deep+shallow)"
+        ],
+        "162130": [
+            "lpc",
+            "liquid precipitation flux from convection"
+        ],
+        "162131": [
+            "ipc",
+            "ice precipitation flux from convection"
+        ],
+        "162132": [
+            "ttendcs",
+            "t-tendency from cloud scheme"
+        ],
+        "162133": [
+            "qtendcs",
+            "q-tendency from cloud scheme"
+        ],
+        "162134": [
+            "qltendcs",
+            "ql-tendency from cloud scheme"
+        ],
+        "162135": [
+            "qitendcs",
+            "qi-tendency from cloud scheme"
+        ],
+        "162136": [
+            "lpcs",
+            "liquid precip flux from cloud scheme (stratiform)"
+        ],
+        "162137": [
+            "ipcs",
+            "ice precip flux from cloud scheme (stratiform)"
+        ],
+        "162138": [
+            "utendcs",
+            "u-tendency from shallow convection"
+        ],
+        "162139": [
+            "vtendcs",
+            "v-tendency from shallow convection"
+        ],
+        "162140": [
+            "ttendsc",
+            "t-tendency from shallow convection"
+        ],
+        "162141": [
+            "qtendsc",
+            "q-tendency from shallow convection"
+        ],
+        "162206": [
+            "variance of geopotential"
+        ],
+        "162207": [
+            "covariance of geopotential/temperature"
+        ],
+        "162208": [
+            "variance of temperature"
+        ],
+        "162209": [
+            "covariance of geopotential/specific humidity"
+        ],
+        "162210": [
+            "covariance of temperature/specific humidity"
+        ],
+        "162211": [
+            "variance of specific humidity"
+        ],
+        "162212": [
+            "covariance of u component/geopotential"
+        ],
+        "162213": [
+            "covariance of u component/temperature"
+        ],
+        "162214": [
+            "covariance of u component/specific humidity"
+        ],
+        "162215": [
+            "variance of u component"
+        ],
+        "162216": [
+            "covariance of v component/geopotential"
+        ],
+        "162217": [
+            "covariance of v component/temperature"
+        ],
+        "162218": [
+            "covariance of v component/specific humidity"
+        ],
+        "162219": [
+            "covariance of v component/u component"
+        ],
+        "162220": [
+            "variance of v component"
+        ],
+        "162221": [
+            "covariance of omega/geopotential"
+        ],
+        "162222": [
+            "covariance of omega/temperature"
+        ],
+        "162223": [
+            "covariance of omega/specific humidity"
+        ],
+        "162224": [
+            "covariance of omega/u component"
+        ],
+        "162225": [
+            "covariance of omega/v component"
+        ],
+        "162226": [
+            "variance of omega"
+        ],
+        "162227": [
+            "variance of surface pressure"
+        ],
+        "162229": [
+            "variance of relative humidity"
+        ],
+        "162230": [
+            "covariance of u component/ozone"
+        ],
+        "162231": [
+            "covariance of v component/ozone"
+        ],
+        "162232": [
+            "covariance of omega/ozone"
+        ],
+        "162233": [
+            "variance of ozone"
+        ],
+        "163": [
+            "slor",
+            "slope of sub-gridscale orography"
+        ],
+        "164": [
+            "tcc",
+            "total cloud cover"
+        ],
+        "165": [
+            "10u",
+            "10 metre u wind component"
+        ],
+        "166": [
+            "10v",
+            "10 metre v wind component"
+        ],
+        "167": [
+            "2t",
+            "2 metre temperature"
+        ],
+        "168": [
+            "2d",
+            "2 metre dewpoint temperature"
+        ],
+        "169": [
+            "ssrd",
+            "surface solar radiation downwards"
+        ],
+        "17": [
+            "alnip",
+            "near ir albedo for direct radiation"
+        ],
+        "170": [
+            "stl2",
+            "soil temperature level 2"
+        ],
+        "170149": [
+            "tsw",
+            "total soil moisture"
+        ],
+        "170171": [
+            "swl2",
+            "soil wetness level 2"
+        ],
+        "170179": [
+            "ttr",
+            "top net thermal radiation"
+        ],
+        "171": [
+            "swl2",
+            "soil wetness level 2"
+        ],
+        "171001": [
+            "strfa",
+            "stream function anomaly"
+        ],
+        "171002": [
+            "vpota",
+            "velocity potential anomaly"
+        ],
+        "171003": [
+            "pta",
+            "potential temperature anomaly"
+        ],
+        "171004": [
+            "epta",
+            "equivalent potential temperature anomaly"
+        ],
+        "171005": [
+            "septa",
+            "saturated equivalent potential temperature anomaly"
+        ],
+        "171006": [
+            "100ua",
+            "100 metre u wind component anomaly"
+        ],
+        "171007": [
+            "100va",
+            "100 metre v wind component anomaly"
+        ],
+        "171011": [
+            "udwa",
+            "u component of divergent wind anomaly"
+        ],
+        "171012": [
+            "vdwa",
+            "v component of divergent wind anomaly"
+        ],
+        "171013": [
+            "urwa",
+            "u component of rotational wind anomaly"
+        ],
+        "171014": [
+            "vrwa",
+            "v component of rotational wind anomaly"
+        ],
+        "171021": [
+            "uctpa",
+            "unbalanced component of temperature anomaly"
+        ],
+        "171022": [
+            "uclna",
+            "unbalanced component of logarithm of surface pressure anomaly"
+        ],
+        "171023": [
+            "ucdva",
+            "unbalanced component of divergence anomaly"
+        ],
+        "171026": [
+            "cla",
+            "lake cover anomaly"
+        ],
+        "171027": [
+            "cvla",
+            "low vegetation cover anomaly"
+        ],
+        "171028": [
+            "cvha",
+            "high vegetation cover anomaly"
+        ],
+        "171029": [
+            "tvla",
+            "type of low vegetation anomaly"
+        ],
+        "171030": [
+            "tvha",
+            "type of high vegetation anomaly"
+        ],
+        "171031": [
+            "sica",
+            "sea-ice cover anomaly"
+        ],
+        "171032": [
+            "asna",
+            "snow albedo anomaly"
+        ],
+        "171033": [
+            "rsna",
+            "snow density anomaly"
+        ],
+        "171034": [
+            "ssta",
+            "sea surface temperature anomaly"
+        ],
+        "171035": [
+            "istal1",
+            "ice surface temperature anomaly layer 1"
+        ],
+        "171036": [
+            "istal2",
+            "ice surface temperature anomaly layer 2"
+        ],
+        "171037": [
+            "istal3",
+            "ice surface temperature anomaly layer 3"
+        ],
+        "171038": [
+            "istal4",
+            "ice surface temperature anomaly layer 4"
+        ],
+        "171039": [
+            "swval1",
+            "volumetric soil water anomaly layer 1",
+            "swv1"
+        ],
+        "171040": [
+            "swval2",
+            "volumetric soil water anomaly layer 2",
+            "swv2"
+        ],
+        "171041": [
+            "swval3",
+            "volumetric soil water anomaly layer 3",
+            "swv3"
+        ],
+        "171042": [
+            "swval4",
+            "volumetric soil water anomaly layer 4",
+            "swv4"
+        ],
+        "171043": [
+            "slta",
+            "soil type anomaly"
+        ],
+        "171044": [
+            "esa",
+            "snow evaporation anomaly"
+        ],
+        "171045": [
+            "smlta",
+            "snowmelt anomaly"
+        ],
+        "171046": [
+            "sdura",
+            "solar duration anomaly"
+        ],
+        "171047": [
+            "dsrpa",
+            "direct solar radiation anomaly"
+        ],
+        "171048": [
+            "magssa",
+            "magnitude of turbulent surface stress anomaly"
+        ],
+        "171049": [
+            "10fga",
+            "10 metre wind gust anomaly"
+        ],
+        "171050": [
+            "lspfa",
+            "large-scale precipitation fraction anomaly"
+        ],
+        "171051": [
+            "mx2t24a",
+            "maximum 2 metre temperature in the last 24 hours anomaly"
+        ],
+        "171052": [
+            "mn2t24a",
+            "minimum 2 metre temperature in the last 24 hours anomaly"
+        ],
+        "171053": [
+            "monta",
+            "montgomery potential anomaly"
+        ],
+        "171054": [
+            "pa",
+            "pressure anomaly"
+        ],
+        "171055": [
+            "mn2t24a",
+            "mean 2 metre temperature in the last 24 hours anomaly"
+        ],
+        "171056": [
+            "mn2d24a",
+            "mean 2 metre dewpoint temperature in the last 24 hours anomaly"
+        ],
+        "171057": [
+            "uvba",
+            "downward uv radiation at the surface anomaly"
+        ],
+        "171058": [
+            "para",
+            "photosynthetically active radiation at the surface anomaly"
+        ],
+        "171059": [
+            "capea",
+            "convective available potential energy anomaly"
+        ],
+        "171060": [
+            "pva",
+            "potential vorticity anomaly"
+        ],
+        "171061": [
+            "tpoa",
+            "total precipitation from observations anomaly"
+        ],
+        "171062": [
+            "obcta",
+            "observation count anomaly"
+        ],
+        "171063": [
+            "stsktda",
+            "start time for skin temperature difference anomaly"
+        ],
+        "171064": [
+            "ftsktda",
+            "finish time for skin temperature difference anomaly"
+        ],
+        "171065": [
+            "sktda",
+            "skin temperature difference anomaly"
+        ],
+        "171078": [
+            "tclwa",
+            "total column liquid water anomaly"
+        ],
+        "171079": [
+            "tciwa",
+            "total column ice water anomaly"
+        ],
+        "171121": [
+            "mx2t6a",
+            "maximum temperature at 2 metres in the last 6 hours anomaly"
+        ],
+        "171122": [
+            "mn2t6a",
+            "minimum temperature at 2 metres in the last 6 hours anomaly"
+        ],
+        "171125": [
+            "vitea",
+            "vertically integrated total energy anomaly"
+        ],
+        "171126": [
+            "generic parameter for sensitive area prediction"
+        ],
+        "171127": [
+            "ata",
+            "atmospheric tide anomaly"
+        ],
+        "171128": [
+            "bva",
+            "budget values anomaly"
+        ],
+        "171129": [
+            "za",
+            "geopotential anomaly",
+            "z"
+        ],
+        "171130": [
+            "ta",
+            "temperature anomaly",
+            "t"
+        ],
+        "171131": [
+            "ua",
+            "u component of wind anomaly",
+            "u"
+        ],
+        "171132": [
+            "va",
+            "v component of wind anomaly",
+            "v"
+        ],
+        "171133": [
+            "qa",
+            "specific humidity anomaly"
+        ],
+        "171134": [
+            "spa",
+            "surface pressure anomaly"
+        ],
+        "171135": [
+            "wa",
+            "vertical velocity (pressure) anomaly"
+        ],
+        "171136": [
+            "tcwa",
+            "total column water anomaly"
+        ],
+        "171137": [
+            "tcwva",
+            "total column water vapour anomaly"
+        ],
+        "171138": [
+            "voa",
+            "relative vorticity anomaly",
+            "vo"
+        ],
+        "171139": [
+            "stal1",
+            "soil temperature anomaly level 1",
+            "stl1",
+            "st"
+        ],
+        "171140": [
+            "swal1",
+            "soil wetness anomaly level 1",
+            "swl1"
+        ],
+        "171141": [
+            "sda",
+            "snow depth anomaly"
+        ],
+        "171142": [
+            "lspa",
+            "stratiform precipitation (large-scale precipitation) anomaly"
+        ],
+        "171143": [
+            "cpa",
+            "convective precipitation anomaly"
+        ],
+        "171144": [
+            "sfa",
+            "snowfall (convective + stratiform) anomaly"
+        ],
+        "171145": [
+            "blda",
+            "boundary layer dissipation anomaly"
+        ],
+        "171146": [
+            "sshfa",
+            "surface sensible heat flux anomaly"
+        ],
+        "171147": [
+            "slhfa",
+            "surface latent heat flux anomaly"
+        ],
+        "171148": [
+            "chnka",
+            "charnock anomaly"
+        ],
+        "171149": [
+            "snra",
+            "surface net radiation anomaly"
+        ],
+        "171150": [
+            "tnra",
+            "top net radiation anomaly"
+        ],
+        "171151": [
+            "msla",
+            "mean sea level pressure anomaly",
+            "msl"
+        ],
+        "171152": [
+            "lspa",
+            "logarithm of surface pressure anomaly"
+        ],
+        "171153": [
+            "swhra",
+            "short-wave heating rate anomaly"
+        ],
+        "171154": [
+            "lwhra",
+            "long-wave heating rate anomaly"
+        ],
+        "171155": [
+            "da",
+            "relative divergence anomaly",
+            "d"
+        ],
+        "171156": [
+            "gha",
+            "height anomaly",
+            "gh"
+        ],
+        "171157": [
+            "ra",
+            "relative humidity anomaly",
+            "r"
+        ],
+        "171158": [
+            "tspa",
+            "tendency of surface pressure anomaly"
+        ],
+        "171159": [
+            "blha",
+            "boundary layer height anomaly"
+        ],
+        "171160": [
+            "sdora",
+            "standard deviation of orography anomaly"
+        ],
+        "171161": [
+            "isora",
+            "anisotropy of sub-gridscale orography anomaly"
+        ],
+        "171162": [
+            "anora",
+            "angle of sub-gridscale orography anomaly"
+        ],
+        "171163": [
+            "slora",
+            "slope of sub-gridscale orography anomaly"
+        ],
+        "171164": [
+            "tcca",
+            "total cloud cover anomaly"
+        ],
+        "171165": [
+            "10ua",
+            "10 metre u wind component anomaly"
+        ],
+        "171166": [
+            "10va",
+            "10 metre v wind component anomaly"
+        ],
+        "171167": [
+            "2ta",
+            "2 metre temperature anomaly"
+        ],
+        "171168": [
+            "2da",
+            "2 metre dewpoint temperature anomaly"
+        ],
+        "171169": [
+            "ssrda",
+            "surface solar radiation downwards anomaly"
+        ],
+        "171170": [
+            "slal2",
+            "soil temperature anomaly level 2",
+            "stl2"
+        ],
+        "171171": [
+            "swal2",
+            "soil wetness anomaly level 2",
+            "swl2"
+        ],
+        "171173": [
+            "sra",
+            "surface roughness anomaly"
+        ],
+        "171174": [
+            "ala",
+            "albedo anomaly"
+        ],
+        "171175": [
+            "strda",
+            "surface thermal radiation downwards anomaly"
+        ],
+        "171176": [
+            "ssra",
+            "surface net solar radiation anomaly"
+        ],
+        "171177": [
+            "stra",
+            "surface net thermal radiation anomaly"
+        ],
+        "171178": [
+            "tsra",
+            "top net solar radiation anomaly"
+        ],
+        "171179": [
+            "ttra",
+            "top net thermal radiation anomaly"
+        ],
+        "171180": [
+            "ewssa",
+            "east-west surface stress anomaly"
+        ],
+        "171181": [
+            "nsssa",
+            "north-south surface stress anomaly"
+        ],
+        "171182": [
+            "ea",
+            "evaporation anomaly"
+        ],
+        "171183": [
+            "stal3",
+            "soil temperature anomaly level 3",
+            "stl3"
+        ],
+        "171184": [
+            "swal3",
+            "soil wetness anomaly level 3",
+            "swl3"
+        ],
+        "171185": [
+            "ccca",
+            "convective cloud cover anomaly"
+        ],
+        "171186": [
+            "lcca",
+            "low cloud cover anomaly"
+        ],
+        "171187": [
+            "mcca",
+            "medium cloud cover anomaly"
+        ],
+        "171188": [
+            "hcca",
+            "high cloud cover anomaly"
+        ],
+        "171189": [
+            "sunda",
+            "sunshine duration anomaly"
+        ],
+        "171190": [
+            "ewova",
+            "east-west component of sub-gridscale orographic variance anomaly"
+        ],
+        "171191": [
+            "nsova",
+            "north-south component of sub-gridscale orographic variance anomaly"
+        ],
+        "171192": [
+            "nwova",
+            "north-west/south-east component of sub-gridscale orographic variance anomaly"
+        ],
+        "171193": [
+            "neova",
+            "north-east/south-west component of sub-gridscale orographic variance anomaly"
+        ],
+        "171194": [
+            "btmpa",
+            "brightness temperature anomaly"
+        ],
+        "171195": [
+            "lgwsa",
+            "longitudinal component of gravity wave stress anomaly"
+        ],
+        "171196": [
+            "mgwsa",
+            "meridional component of gravity wave stress anomaly"
+        ],
+        "171197": [
+            "gwda",
+            "gravity wave dissipation anomaly"
+        ],
+        "171198": [
+            "srca",
+            "skin reservoir content anomaly"
+        ],
+        "171199": [
+            "vfa",
+            "vegetation fraction anomaly"
+        ],
+        "171200": [
+            "vsoa",
+            "variance of sub-gridscale orography anomaly"
+        ],
+        "171201": [
+            "mx2ta",
+            "maximum temperature at 2 metres anomaly"
+        ],
+        "171202": [
+            "mn2ta",
+            "minimum temperature at 2 metres anomaly"
+        ],
+        "171203": [
+            "o3a",
+            "ozone mass mixing ratio anomaly"
+        ],
+        "171204": [
+            "pawa",
+            "precipitation analysis weights anomaly"
+        ],
+        "171205": [
+            "roa",
+            "runoff anomaly"
+        ],
+        "171206": [
+            "tco3a",
+            "total column ozone anomaly"
+        ],
+        "171207": [
+            "10 metre wind speed anomaly",
+            "10si"
+        ],
+        "171208": [
+            "tsrca",
+            "top net solar radiation clear sky anomaly"
+        ],
+        "171209": [
+            "ttrca",
+            "top net thermal radiation clear sky anomaly"
+        ],
+        "171210": [
+            "ssrca",
+            "surface net solar radiation clear sky anomaly"
+        ],
+        "171211": [
+            "strca",
+            "surface net thermal radiation, clear sky anomaly"
+        ],
+        "171212": [
+            "sia",
+            "solar insolation anomaly"
+        ],
+        "171214": [
+            "dhra",
+            "diabatic heating by radiation anomaly"
+        ],
+        "171215": [
+            "dhvda",
+            "diabatic heating by vertical diffusion anomaly"
+        ],
+        "171216": [
+            "dhcca",
+            "diabatic heating by cumulus convection anomaly"
+        ],
+        "171217": [
+            "dhlca",
+            "diabatic heating by large-scale condensation anomaly"
+        ],
+        "171218": [
+            "vdzwa",
+            "vertical diffusion of zonal wind anomaly"
+        ],
+        "171219": [
+            "vdmwa",
+            "vertical diffusion of meridional wind anomaly"
+        ],
+        "171220": [
+            "ewgda",
+            "east-west gravity wave drag tendency anomaly"
+        ],
+        "171221": [
+            "nsgda",
+            "north-south gravity wave drag tendency anomaly"
+        ],
+        "171222": [
+            "ctzwa",
+            "convective tendency of zonal wind anomaly"
+        ],
+        "171223": [
+            "ctmwa",
+            "convective tendency of meridional wind anomaly"
+        ],
+        "171224": [
+            "vdha",
+            "vertical diffusion of humidity anomaly"
+        ],
+        "171225": [
+            "htcca",
+            "humidity tendency by cumulus convection anomaly"
+        ],
+        "171226": [
+            "htlca",
+            "humidity tendency by large-scale condensation anomaly"
+        ],
+        "171227": [
+            "crnha",
+            "change from removal of negative humidity anomaly"
+        ],
+        "171228": [
+            "tpa",
+            "total precipitation anomaly"
+        ],
+        "171229": [
+            "iewsa",
+            "instantaneous x surface stress anomaly"
+        ],
+        "171230": [
+            "inssa",
+            "instantaneous y surface stress anomaly"
+        ],
+        "171231": [
+            "ishfa",
+            "instantaneous surface heat flux anomaly"
+        ],
+        "171232": [
+            "iea",
+            "instantaneous moisture flux anomaly"
+        ],
+        "171233": [
+            "asqa",
+            "apparent surface humidity anomaly"
+        ],
+        "171234": [
+            "lsrha",
+            "logarithm of surface roughness length for heat anomaly"
+        ],
+        "171235": [
+            "skta",
+            "skin temperature anomaly"
+        ],
+        "171236": [
+            "stal4",
+            "soil temperature level 4 anomaly"
+        ],
+        "171237": [
+            "swal4",
+            "soil wetness level 4 anomaly",
+            "swl4"
+        ],
+        "171238": [
+            "tsna",
+            "temperature of snow layer anomaly"
+        ],
+        "171239": [
+            "csfa",
+            "convective snowfall anomaly"
+        ],
+        "171240": [
+            "lsfa",
+            "large scale snowfall anomaly"
+        ],
+        "171241": [
+            "acfa",
+            "accumulated cloud fraction tendency anomaly"
+        ],
+        "171242": [
+            "alwa",
+            "accumulated liquid water tendency anomaly"
+        ],
+        "171243": [
+            "fala",
+            "forecast albedo anomaly"
+        ],
+        "171244": [
+            "fsra",
+            "forecast surface roughness anomaly"
+        ],
+        "171245": [
+            "flsra",
+            "forecast logarithm of surface roughness for heat anomaly"
+        ],
+        "171246": [
+            "clwca",
+            "cloud liquid water content anomaly"
+        ],
+        "171247": [
+            "ciwca",
+            "cloud ice water content anomaly"
+        ],
+        "171248": [
+            "cca",
+            "cloud cover anomaly"
+        ],
+        "171249": [
+            "aiwa",
+            "accumulated ice water tendency anomaly"
+        ],
+        "171250": [
+            "iaa",
+            "ice age anomaly"
+        ],
+        "171251": [
+            "attea",
+            "adiabatic tendency of temperature anomaly"
+        ],
+        "171252": [
+            "athea",
+            "adiabatic tendency of humidity anomaly"
+        ],
+        "171253": [
+            "atzea",
+            "adiabatic tendency of zonal wind anomaly"
+        ],
+        "171254": [
+            "atmwa",
+            "adiabatic tendency of meridional wind anomaly"
+        ],
+        "172": [
+            "lsm",
+            "land-sea mask"
+        ],
+        "172044": [
+            "esrate",
+            "snow evaporation",
+            "es"
+        ],
+        "172045": [
+            "smlt",
+            "snowmelt"
+        ],
+        "172048": [
+            "magss",
+            "magnitude of turbulent surface stress"
+        ],
+        "172050": [
+            "lspf",
+            "large-scale precipitation fraction"
+        ],
+        "172142": [
+            "lsp",
+            "stratiform precipitation (large-scale precipitation)"
+        ],
+        "172143": [
+            "cprate",
+            "convective precipitation",
+            "cp"
+        ],
+        "172144": [
+            "sf",
+            "snowfall (convective + stratiform)"
+        ],
+        "172145": [
+            "bldrate",
+            "boundary layer dissipation"
+        ],
+        "172146": [
+            "sshf",
+            "surface sensible heat flux",
+            "146"
+        ],
+        "172147": [
+            "slhf",
+            "surface latent heat flux",
+            "147"
+        ],
+        "172149": [
+            "snr",
+            "surface net radiation"
+        ],
+        "172153": [
+            "swhr",
+            "short-wave heating rate"
+        ],
+        "172154": [
+            "lwhr",
+            "long-wave heating rate"
+        ],
+        "172169": [
+            "ssrd",
+            "surface solar radiation downwards"
+        ],
+        "172175": [
+            "strd",
+            "surface thermal radiation downwards"
+        ],
+        "172176": [
+            "ssr",
+            "surface solar radiation"
+        ],
+        "172177": [
+            "str",
+            "surface thermal radiation"
+        ],
+        "172178": [
+            "tsr",
+            "top solar radiation"
+        ],
+        "172179": [
+            "ttr",
+            "top thermal radiation"
+        ],
+        "172180": [
+            "ewss",
+            "east-west surface stress"
+        ],
+        "172181": [
+            "nsss",
+            "north-south surface stress"
+        ],
+        "172182": [
+            "erate",
+            "evaporation",
+            "e"
+        ],
+        "172189": [
+            "sund",
+            "sunshine duration"
+        ],
+        "172195": [
+            "longitudinal component of gravity wave stress"
+        ],
+        "172196": [
+            "meridional component of gravity wave stress"
+        ],
+        "172197": [
+            "gwdrate",
+            "gravity wave dissipation"
+        ],
+        "172205": [
+            "ro",
+            "runoff"
+        ],
+        "172208": [
+            "tsrc",
+            "top net solar radiation, clear sky"
+        ],
+        "172209": [
+            "ttrc",
+            "top net thermal radiation, clear sky"
+        ],
+        "172210": [
+            "ssrc",
+            "surface net solar radiation, clear sky"
+        ],
+        "172211": [
+            "strc",
+            "surface net thermal radiation, clear sky"
+        ],
+        "172212": [
+            "solar insolation"
+        ],
+        "172228": [
+            "tprate",
+            "total precipitation",
+            "tp"
+        ],
+        "172239": [
+            "csf",
+            "convective snowfall"
+        ],
+        "172240": [
+            "lsf",
+            "large-scale snowfall"
+        ],
+        "173": [
+            "sr",
+            "surface roughness"
+        ],
+        "173044": [
+            "esa",
+            "snow evaporation anomaly"
+        ],
+        "173045": [
+            "smlta",
+            "snowmelt anomaly"
+        ],
+        "173048": [
+            "magssa",
+            "magnitude of turbulent surface stress anomaly"
+        ],
+        "173050": [
+             "lspfa",
+            "large-scale precipitation fraction anomaly"
+        ],
+        "173142": [
+            "lspa",
+            "stratiform precipitation (large-scale precipitation) anomaly"
+        ],
+        "173143": [
+            "cpa",
+            "convective precipitation anomaly"
+        ],
+        "173144": [
+            "sfara",
+            "snowfall (convective + stratiform) anomalous rate of accumulation"
+        ],
+        "173145": [
+            "blda",
+            "boundary layer dissipation anomaly"
+        ],
+        "173146": [
+            "sshfa",
+            "surface sensible heat flux anomaly"
+        ],
+        "173147": [
+            "slhfa",
+            "surface latent heat flux anomaly"
+        ],
+        "173149": [
+            "snra",
+            "surface net radiation anomaly"
+        ],
+        "173153": [
+             "swhra",
+            "short-wave heating rate anomaly"
+        ],
+        "173154": [
+            "lwhra",
+            "long-wave heating rate anomaly"
+        ],
+        "173169": [
+            "ssrda",
+            "surface solar radiation downwards anomaly"
+        ],
+        "173175": [
+            "strda",
+            "surface thermal radiation downwards anomaly"
+        ],
+        "173176": [
+            "ssra",
+            "surface solar radiation anomaly",
+            "ssr"
+        ],
+        "173177": [
+            "stra",
+            "surface thermal radiation anomaly",
+            "str"
+        ],
+        "173178": [
+            "tsra",
+            "top solar radiation anomaly",
+            "tsr"
+        ],
+        "173179": [
+            "ttra",
+            "top thermal radiation anomaly",
+            "ttr"
+        ],
+        "173180": [
+            "ewssa",
+            "east-west surface stress anomaly"
+        ],
+        "173181": [
+            "nsssa",
+            "north-south surface stress anomaly"
+        ],
+        "173182": [
+            "ea",
+            "evaporation anomaly",
+            "e"
+        ],
+        "173189": [
+            "sundara",
+            "sunshine duration anomalous rate of accumulation"
+        ],
+        "173195": [
+            "lgwsa",
+            "longitudinal component of gravity wave stress anomaly"
+        ],
+        "173196": [
+            "mgwa",
+            "meridional component of gravity wave stress anomaly"
+        ],
+        "173197": [
+            "gwa",
+            "gravity wave dissipation anomaly"
+        ],
+        "173205": [
+            "roa",
+            "runoff anomaly"
+        ],
+        "173208": [
+             "tsrca",
+            "top net solar radiation, clear sky anomaly"
+        ],
+        "173209": [
+            "ttrca",
+            "top net thermal radiation, clear sky anomaly"
+        ],
+        "173210": [
+            "ssrca",
+            "surface net solar radiation, clear sky anomaly"
+        ],
+        "173211": [
+             "strca",
+            "surface net thermal radiation, clear sky anomaly"
+        ],
+        "173212": [
+            "tisra",
+            "solar insolation anomaly"
+        ],
+        "173228": [
+            "tpara",
+            "total precipitation anomalous rate of accumulation"
+        ],
+        "173239": [
+            "csfa",
+            "convective snowfall anomaly"
+        ],
+        "173240": [
+            "lsfa",
+            "large scale snowfall anomaly"
+        ],
+        "174": [
+            "al",
+            "albedo"
+        ],
+        "174006": [
+            "total soil moisture"
+        ],
+        "174008": [
+            "sro",
+            "surface runoff"
+        ],
+        "174009": [
+            "ssro",
+            "sub-surface runoff"
+        ],
+        "174010": [
+            "sswcsdown",
+            "clear-sky (ii) down surface sw flux"
+        ],
+        "174013": [
+            "sswcsup",
+            "clear-sky (ii) up surface sw flux"
+        ],
+        "174025": [
+            "vis15",
+            "visibility at 1.5m"
+        ],
+        "174031": [
+            "fraction of sea-ice in sea"
+        ],
+        "174034": [
+            "open-sea surface temperature"
+        ],
+        "174039": [
+            "volumetric soil water layer 1"
+        ],
+        "174040": [
+            "volumetric soil water layer 2"
+        ],
+        "174041": [
+            "volumetric soil water layer 3"
+        ],
+        "174042": [
+            "volumetric soil water layer 4"
+        ],
+        "174049": [
+            "10 metre wind gust in the last 24 hours"
+        ],
+        "174050": [
+            "mn15t",
+            "minimum temperature at 1.5m since previous post-processing"
+        ],
+        "174051": [
+            "mx15t",
+            "maximum temperature at 1.5m since previous post-processing"
+        ],
+        "174052": [
+            "rhum",
+            "relative humidity at 1.5m"
+        ],
+        "174055": [
+            "1.5m temperature - mean in the last 24 hours"
+        ],
+        "174083": [
+            "net primary productivity"
+        ],
+        "174085": [
+            "10m u wind over land"
+        ],
+        "174086": [
+            "10m v wind over land"
+        ],
+        "174087": [
+            "1.5m temperature over land"
+        ],
+        "174088": [
+            "1.5m dewpoint temperature over land"
+        ],
+        "174089": [
+            "top incoming solar radiation"
+        ],
+        "174090": [
+            "top outgoing solar radiation"
+        ],
+        "174094": [
+            "mean sea surface temperature"
+        ],
+        "174095": [
+            "1.5m specific humidity"
+        ],
+        "174096": [
+            "2m specific humidity"
+        ],
+        "174097": [
+            "sist",
+            "sea-ice snow thickness"
+        ],
+        "174098": [
+            "sit",
+            "sea-ice thickness"
+        ],
+        "174099": [
+            "liquid water potential temperature"
+        ],
+        "174110": [
+            "ocean ice concentration"
+        ],
+        "174111": [
+            "ocean mean ice depth"
+        ],
+        "174116": [
+            "swrsurf",
+            "short wave radiation flux at surface"
+        ],
+        "174117": [
+            "swrtop",
+            "short wave radiation flux at top of atmosphere"
+        ],
+        "174137": [
+            "tcwvap",
+            "total column water vapour"
+        ],
+        "174139": [
+            "soil temperature layer 1"
+        ],
+        "174142": [
+            "lsrrate",
+            "large scale rainfall rate"
+        ],
+        "174143": [
+            "crfrate",
+            "convective rainfall rate"
+        ],
+        "174164": [
+            "average potential temperature in upper 293.4m"
+        ],
+        "174167": [
+            "1.5m temperature"
+        ],
+        "174168": [
+            "1.5m dewpoint temperature"
+        ],
+        "174170": [
+            "soil temperature layer 2"
+        ],
+        "174175": [
+            "average salinity in upper 293.4m"
+        ],
+        "174183": [
+            "soil temperature layer 3"
+        ],
+        "174186": [
+            "vlca",
+            "very low cloud amount"
+        ],
+        "174201": [
+            "1.5m temperature - maximum in the last 24 hours"
+        ],
+        "174202": [
+            "1.5m temperature - minimum in the last 24 hours"
+        ],
+        "174236": [
+            "soil temperature layer 4"
+        ],
+        "174239": [
+            "csfrate",
+            "convective snowfall rate"
+        ],
+        "174240": [
+            "lsfrate",
+            "large scale snowfall rate"
+        ],
+        "174248": [
+            "tccro",
+            "total cloud amount - random overlap"
+        ],
+        "174249": [
+            "tcclwr",
+            "total cloud amount in lw radiation"
+        ],
+        "175": [
+            "strd",
+            "surface thermal radiation downwards"
+        ],
+        "175006": [
+            "total soil moisture"
+        ],
+        "175031": [
+            "fraction of sea-ice in sea"
+        ],
+        "175034": [
+            "open-sea surface temperature"
+        ],
+        "175039": [
+            "volumetric soil water layer 1"
+        ],
+        "175040": [
+            "volumetric soil water layer 2"
+        ],
+        "175041": [
+            "volumetric soil water layer 3"
+        ],
+        "175042": [
+            "volumetric soil water layer 4"
+        ],
+        "175049": [
+            "10m wind gust in the last 24 hours"
+        ],
+        "175055": [
+            "1.5m temperature - mean in the last 24 hours"
+        ],
+        "175083": [
+            "net primary productivity"
+        ],
+        "175085": [
+            "10m u wind over land"
+        ],
+        "175086": [
+            "10m v wind over land"
+        ],
+        "175087": [
+            "1.5m temperature over land"
+        ],
+        "175088": [
+            "1.5m dewpoint temperature over land"
+        ],
+        "175089": [
+            "top incoming solar radiation"
+        ],
+        "175090": [
+            "top outgoing solar radiation"
+        ],
+        "175110": [
+            "ocean ice concentration"
+        ],
+        "175111": [
+            "ocean mean ice depth"
+        ],
+        "175139": [
+            "soil temperature layer 1"
+        ],
+        "175164": [
+            "average potential temperature in upper 293.4m"
+        ],
+        "175167": [
+            "1.5m temperature"
+        ],
+        "175168": [
+            "1.5m dewpoint temperature"
+        ],
+        "175170": [
+            "soil temperature layer 2"
+        ],
+        "175175": [
+            "average salinity in upper 293.4m"
+        ],
+        "175183": [
+            "soil temperature layer 3"
+        ],
+        "175201": [
+            "1.5m temperature - maximum in the last 24 hours"
+        ],
+        "175202": [
+            "1.5m temperature - minimum in the last 24 hours"
+        ],
+        "175236": [
+            "soil temperature layer 4"
+        ],
+        "176": [
+            "ssr",
+            "surface net solar radiation"
+        ],
+        "177": [
+            "str",
+            "surface net thermal radiation"
+        ],
+        "178": [
+            "tsr",
+            "top net solar radiation"
+        ],
+        "179": [
+            "ttr",
+            "top net thermal radiation"
+        ],
+        "18": [
+            "alnid",
+            "near ir albedo for diffuse radiation"
+        ],
+        "180": [
+            "ewss",
+            "eastward turbulent surface stress"
+        ],
+        "180149": [
+            "tsw",
+            "total soil wetness"
+        ],
+        "180176": [
+            "ssr",
+            "surface net solar radiation"
+        ],
+        "180177": [
+            "str",
+            "surface net thermal radiation"
+        ],
+        "180178": [
+            "tsr",
+            "top net solar radiation"
+        ],
+        "180179": [
+            "ttr",
+            "top net thermal radiation"
+        ],
+        "181": [
+            "nsss",
+            "northward turbulent surface stress"
+        ],
+        "182": [
+            "e",
+            "evaporation"
+        ],
+        "183": [
+            "stl3",
+            "soil temperature level 3"
+        ],
+        "184": [
+            "swl3",
+            "soil wetness level 3"
+        ],
+        "185": [
+            "ccc",
+            "convective cloud cover"
+        ],
+        "186": [
+            "lcc",
+            "low cloud cover"
+        ],
+        "187": [
+            "mcc",
+            "medium cloud cover"
+        ],
+        "188": [
+            "hcc",
+            "high cloud cover"
+        ],
+        "189": [
+            "sund",
+            "sunshine duration"
+        ],
+        "19": [
+            "uvcs",
+            "clear sky surface uv"
+        ],
+        "190": [
+            "ewov",
+            "east-west component of sub-gridscale orographic variance"
+        ],
+        "190141": [
+            "sdsien",
+            "snow depth"
+        ],
+        "190170": [
+            "cap",
+            "field capacity"
+        ],
+        "190171": [
+            "wiltsien",
+            "wilting point"
+        ],
+        "190173": [
+            "sr",
+            "roughness length"
+        ],
+        "190229": [
+            "tsm",
+            "total soil moisture"
+        ],
+        "191": [
+            "nsov",
+            "north-south component of sub-gridscale orographic variance"
+        ],
+        "192": [
+            "nwov",
+            "north-west/south-east component of sub-gridscale orographic variance"
+        ],
+        "193": [
+            "neov",
+            "north-east/south-west component of sub-gridscale orographic variance"
+        ],
+        "194": [
+            "btmp",
+            "brightness temperature"
+        ],
+        "195": [
+            "lgws",
+            "eastward gravity wave surface stress"
+        ],
+        "196": [
+            "mgws",
+            "northward gravity wave surface stress"
+        ],
+        "197": [
+            "gwd",
+            "gravity wave dissipation"
+        ],
+        "198": [
+            "src",
+            "skin reservoir content"
+        ],
+        "199": [
+            "veg",
+            "vegetation fraction"
+        ],
+        "2": [
+            "vp",
+            "velocity potential",
+            "vpot"
+        ],
+        "20": [
+            "parcs",
+            "clear sky surface photosynthetically active radiation"
+        ],
+        "200": [
+            "vso",
+            "variance of sub-gridscale orography"
+        ],
+        "200001": [
+            "strfdiff",
+            "stream function difference"
+        ],
+        "200002": [
+            "vpotdiff",
+            "velocity potential difference"
+        ],
+        "200003": [
+            "ptdiff",
+            "potential temperature difference"
+        ],
+        "200004": [
+            "eqptdiff",
+            "equivalent potential temperature difference"
+        ],
+        "200005": [
+            "septdiff",
+            "saturated equivalent potential temperature difference"
+        ],
+        "200011": [
+            "udvwdiff",
+            "u component of divergent wind difference"
+        ],
+        "200012": [
+            "vdvwdiff",
+            "v component of divergent wind difference"
+        ],
+        "200013": [
+            "urtwdiff",
+            "u component of rotational wind difference"
+        ],
+        "200014": [
+            "vrtwdiff",
+            "v component of rotational wind difference"
+        ],
+        "200021": [
+            "uctpdiff",
+            "unbalanced component of temperature difference"
+        ],
+        "200022": [
+            "uclndiff",
+            "unbalanced component of logarithm of surface pressure difference"
+        ],
+        "200023": [
+            "ucdvdiff",
+            "unbalanced component of divergence difference"
+        ],
+        "200026": [
+            "cldiff",
+            "lake cover difference"
+        ],
+        "200027": [
+            "cvldiff",
+            "low vegetation cover difference"
+        ],
+        "200028": [
+            "cvhdiff",
+            "high vegetation cover difference"
+        ],
+        "200029": [
+            "tvldiff",
+            "type of low vegetation difference"
+        ],
+        "200030": [
+            "tvhdiff",
+            "type of high vegetation difference"
+        ],
+        "200031": [
+            "sicdiff",
+            "sea-ice cover difference"
+        ],
+        "200032": [
+            "asndiff",
+            "snow albedo difference"
+        ],
+        "200033": [
+            "rsndiff",
+            "snow density difference"
+        ],
+        "200034": [
+            "sstdiff",
+            "sea surface temperature difference"
+        ],
+        "200035": [
+            "istl1diff",
+            "ice surface temperature layer 1 difference"
+        ],
+        "200036": [
+            "istl2diff",
+            "ice surface temperature layer 2 difference"
+        ],
+        "200037": [
+            "istl3diff",
+            "ice surface temperature layer 3 difference"
+        ],
+        "200038": [
+            "istl4diff",
+            "ice surface temperature layer 4 difference"
+        ],
+        "200039": [
+            "swvl1diff",
+            "volumetric soil water layer 1 difference"
+        ],
+        "200040": [
+            "swvl2diff",
+            "volumetric soil water layer 2 difference"
+        ],
+        "200041": [
+            "swvl3diff",
+            "volumetric soil water layer 3 difference"
+        ],
+        "200042": [
+            "swvl4diff",
+            "volumetric soil water layer 4 difference"
+        ],
+        "200043": [
+            "sltdiff",
+            "soil type difference"
+        ],
+        "200044": [
+            "esdiff",
+            "snow evaporation difference"
+        ],
+        "200045": [
+            "smltdiff",
+            "snowmelt difference"
+        ],
+        "200046": [
+            "sdurdiff",
+            "solar duration difference"
+        ],
+        "200047": [
+            "dsrpdiff",
+            "direct solar radiation difference"
+        ],
+        "200048": [
+            "magssdiff",
+            "magnitude of turbulent surface stress difference"
+        ],
+        "200049": [
+            "10fgdiff",
+            "10 metre wind gust difference"
+        ],
+        "200050": [
+            "lspfdiff",
+            "large-scale precipitation fraction difference"
+        ],
+        "200051": [
+            "mx2t24diff",
+            "maximum 2 metre temperature difference"
+        ],
+        "200052": [
+            "mn2t24diff",
+            "minimum 2 metre temperature difference"
+        ],
+        "200053": [
+            "montdiff",
+            "montgomery potential difference"
+        ],
+        "200054": [
+            "presdiff",
+            "pressure difference"
+        ],
+        "200055": [
+            "mean2t24diff",
+            "mean 2 metre temperature in the last 24 hours difference"
+        ],
+        "200056": [
+            "mn2d24diff",
+            "mean 2 metre dewpoint temperature in the last 24 hours difference"
+        ],
+        "200057": [
+            "uvbdiff",
+            "downward uv radiation at the surface difference"
+        ],
+        "200058": [
+            "pardiff",
+            "photosynthetically active radiation at the surface difference"
+        ],
+        "200059": [
+            "capediff",
+            "convective available potential energy difference"
+        ],
+        "200060": [
+            "pvdiff",
+            "potential vorticity difference"
+        ],
+        "200061": [
+            "tpodiff",
+            "total precipitation from observations difference"
+        ],
+        "200062": [
+            "obctdiff",
+            "observation count difference"
+        ],
+        "200063": [
+            "start time for skin temperature difference"
+        ],
+        "200064": [
+            "finish time for skin temperature difference"
+        ],
+        "200065": [
+            "skin temperature difference"
+        ],
+        "200066": [
+            "leaf area index, low vegetation"
+        ],
+        "200067": [
+            "leaf area index, high vegetation"
+        ],
+        "200068": [
+            "minimum stomatal resistance, low vegetation"
+        ],
+        "200069": [
+            "minimum stomatal resistance, high vegetation"
+        ],
+        "200070": [
+            "biome cover, low vegetation"
+        ],
+        "200071": [
+            "biome cover, high vegetation"
+        ],
+        "200078": [
+            "total column liquid water"
+        ],
+        "200079": [
+            "total column ice water"
+        ],
+        "200121": [
+            "mx2t6diff",
+            "maximum temperature at 2 metres difference"
+        ],
+        "200122": [
+            "mn2t6diff",
+            "minimum temperature at 2 metres difference"
+        ],
+        "200123": [
+            "10fg6diff",
+            "10 metre wind gust in the last 6 hours difference"
+        ],
+        "200125": [
+            "vertically integrated total energy"
+        ],
+        "200126": [
+            "generic parameter for sensitive area prediction"
+        ],
+        "200127": [
+            "atdiff",
+            "atmospheric tide difference"
+        ],
+        "200128": [
+            "bvdiff",
+            "budget values difference"
+        ],
+        "200129": [
+            "zdiff",
+            "geopotential difference"
+        ],
+        "200130": [
+            "tdiff",
+            "temperature difference"
+        ],
+        "200131": [
+            "udiff",
+            "u component of wind difference"
+        ],
+        "200132": [
+            "vdiff",
+            "v component of wind difference"
+        ],
+        "200133": [
+            "qdiff",
+            "specific humidity difference"
+        ],
+        "200134": [
+            "spdiff",
+            "surface pressure difference"
+        ],
+        "200135": [
+            "wdiff",
+            "vertical velocity (pressure) difference"
+        ],
+        "200136": [
+            "tcwdiff",
+            "total column water difference"
+        ],
+        "200137": [
+            "tcwvdiff",
+            "total column water vapour difference"
+        ],
+        "200138": [
+            "vodiff",
+            "vorticity (relative) difference"
+        ],
+        "200139": [
+            "stl1diff",
+            "soil temperature level 1 difference"
+        ],
+        "200140": [
+            "swl1diff",
+            "soil wetness level 1 difference"
+        ],
+        "200141": [
+            "sddiff",
+            "snow depth difference"
+        ],
+        "200142": [
+            "lspdiff",
+            "stratiform precipitation (large-scale precipitation) difference"
+        ],
+        "200143": [
+            "cpdiff",
+            "convective precipitation difference"
+        ],
+        "200144": [
+            "sfdiff",
+            "snowfall (convective + stratiform) difference"
+        ],
+        "200145": [
+            "blddiff",
+            "boundary layer dissipation difference"
+        ],
+        "200146": [
+            "sshfdiff",
+            "surface sensible heat flux difference"
+        ],
+        "200147": [
+            "slhfdiff",
+            "surface latent heat flux difference"
+        ],
+        "200148": [
+            "chnkdiff",
+            "charnock difference"
+        ],
+        "200149": [
+            "snrdiff",
+            "surface net radiation difference"
+        ],
+        "200150": [
+            "tnrdiff",
+            "top net radiation difference"
+        ],
+        "200151": [
+            "msldiff",
+            "mean sea level pressure difference"
+        ],
+        "200152": [
+            "lnspdiff",
+            "logarithm of surface pressure difference"
+        ],
+        "200153": [
+            "swhrdiff",
+            "short-wave heating rate difference"
+        ],
+        "200154": [
+            "lwhrdiff",
+            "long-wave heating rate difference"
+        ],
+        "200155": [
+            "ddiff",
+            "divergence difference"
+        ],
+        "200156": [
+            "ghdiff",
+            "height difference"
+        ],
+        "200157": [
+            "rdiff",
+            "relative humidity difference"
+        ],
+        "200158": [
+            "tspdiff",
+            "tendency of surface pressure difference"
+        ],
+        "200159": [
+            "blhdiff",
+            "boundary layer height difference"
+        ],
+        "200160": [
+            "sdordiff",
+            "standard deviation of orography difference"
+        ],
+        "200161": [
+            "isordiff",
+            "anisotropy of sub-gridscale orography difference"
+        ],
+        "200162": [
+            "anordiff",
+            "angle of sub-gridscale orography difference"
+        ],
+        "200163": [
+            "slordiff",
+            "slope of sub-gridscale orography difference"
+        ],
+        "200164": [
+            "tccdiff",
+            "total cloud cover difference"
+        ],
+        "200165": [
+            "10udiff",
+            "10 metre u wind component difference"
+        ],
+        "200166": [
+            "10vdiff",
+            "10 metre v wind component difference"
+        ],
+        "200167": [
+            "2tdiff",
+            "2 metre temperature difference"
+        ],
+        "200168": [
+            "2ddiff",
+            "2 metre dewpoint temperature difference"
+        ],
+        "200169": [
+            "ssrddiff",
+            "surface solar radiation downwards difference"
+        ],
+        "200170": [
+            "stl2diff",
+            "soil temperature level 2 difference"
+        ],
+        "200171": [
+            "swl2diff",
+            "soil wetness level 2 difference"
+        ],
+        "200172": [
+            "lsmdiff",
+            "land-sea mask difference"
+        ],
+        "200173": [
+            "srdiff",
+            "surface roughness difference"
+        ],
+        "200174": [
+            "aldiff",
+            "albedo difference"
+        ],
+        "200175": [
+            "strddiff",
+            "surface thermal radiation downwards difference"
+        ],
+        "200176": [
+            "ssrdiff",
+            "surface net solar radiation difference"
+        ],
+        "200177": [
+            "strdiff",
+            "surface net thermal radiation difference"
+        ],
+        "200178": [
+            "tsrdiff",
+            "top net solar radiation difference"
+        ],
+        "200179": [
+            "ttrdiff",
+            "top net thermal radiation difference"
+        ],
+        "200180": [
+            "ewssdiff",
+            "east-west surface stress difference"
+        ],
+        "200181": [
+            "nsssdiff",
+            "north-south surface stress difference"
+        ],
+        "200182": [
+            "ediff",
+            "evaporation difference"
+        ],
+        "200183": [
+            "stl3diff",
+            "soil temperature level 3 difference"
+        ],
+        "200184": [
+            "swl3diff",
+            "soil wetness level 3 difference"
+        ],
+        "200185": [
+            "cccdiff",
+            "convective cloud cover difference"
+        ],
+        "200186": [
+            "lccdiff",
+            "low cloud cover difference"
+        ],
+        "200187": [
+            "mccdiff",
+            "medium cloud cover difference"
+        ],
+        "200188": [
+            "hccdiff",
+            "high cloud cover difference"
+        ],
+        "200189": [
+            "sunddiff",
+            "sunshine duration difference"
+        ],
+        "200190": [
+            "ewovdiff",
+            "east-west component of sub-gridscale orographic variance difference"
+        ],
+        "200191": [
+            "nsovdiff",
+            "north-south component of sub-gridscale orographic variance difference"
+        ],
+        "200192": [
+            "nwovdiff",
+            "north-west/south-east component of sub-gridscale orographic variance difference"
+        ],
+        "200193": [
+            "neovdiff",
+            "north-east/south-west component of sub-gridscale orographic variance difference"
+        ],
+        "200194": [
+            "btmpdiff",
+            "brightness temperature difference"
+        ],
+        "200195": [
+            "lgwsdiff",
+            "longitudinal component of gravity wave stress difference"
+        ],
+        "200196": [
+            "mgwsdiff",
+            "meridional component of gravity wave stress difference"
+        ],
+        "200197": [
+            "gwddiff",
+            "gravity wave dissipation difference"
+        ],
+        "200198": [
+            "srcdiff",
+            "skin reservoir content difference"
+        ],
+        "200199": [
+            "vegdiff",
+            "vegetation fraction difference"
+        ],
+        "200200": [
+            "vsodiff",
+            "variance of sub-gridscale orography difference"
+        ],
+        "200201": [
+            "mx2tdiff",
+            "maximum temperature at 2 metres since previous post-processing difference"
+        ],
+        "200202": [
+            "mn2tdiff",
+            "minimum temperature at 2 metres since previous post-processing difference"
+        ],
+        "200203": [
+            "o3diff",
+            "ozone mass mixing ratio difference"
+        ],
+        "200204": [
+            "pawdiff",
+            "precipitation analysis weights difference"
+        ],
+        "200205": [
+            "rodiff",
+            "runoff difference"
+        ],
+        "200206": [
+            "tco3diff",
+            "total column ozone difference"
+        ],
+        "200207": [
+            "10sidiff",
+            "10 metre wind speed difference"
+        ],
+        "200208": [
+            "tsrcdiff",
+            "top net solar radiation, clear sky difference"
+        ],
+        "200209": [
+            "ttrcdiff",
+            "top net thermal radiation, clear sky difference"
+        ],
+        "200210": [
+            "ssrcdiff",
+            "surface net solar radiation, clear sky difference"
+        ],
+        "200211": [
+            "strcdiff",
+            "surface net thermal radiation, clear sky difference"
+        ],
+        "200212": [
+            "tisrdiff",
+            "toa incident solar radiation difference"
+        ],
+        "200214": [
+            "dhrdiff",
+            "diabatic heating by radiation difference"
+        ],
+        "200215": [
+            "dhvddiff",
+            "diabatic heating by vertical diffusion difference"
+        ],
+        "200216": [
+            "dhccdiff",
+            "diabatic heating by cumulus convection difference"
+        ],
+        "200217": [
+            "dhlcdiff",
+            "diabatic heating large-scale condensation difference"
+        ],
+        "200218": [
+            "vdzwdiff",
+            "vertical diffusion of zonal wind difference"
+        ],
+        "200219": [
+            "vdmwdiff",
+            "vertical diffusion of meridional wind difference"
+        ],
+        "200220": [
+            "ewgddiff",
+            "east-west gravity wave drag tendency difference"
+        ],
+        "200221": [
+            "nsgddiff",
+            "north-south gravity wave drag tendency difference"
+        ],
+        "200222": [
+            "ctzwdiff",
+            "convective tendency of zonal wind difference"
+        ],
+        "200223": [
+            "ctmwdiff",
+            "convective tendency of meridional wind difference"
+        ],
+        "200224": [
+            "vdhdiff",
+            "vertical diffusion of humidity difference"
+        ],
+        "200225": [
+            "htccdiff",
+            "humidity tendency by cumulus convection difference"
+        ],
+        "200226": [
+            "htlcdiff",
+            "humidity tendency by large-scale condensation difference"
+        ],
+        "200227": [
+            "crnhdiff",
+            "change from removal of negative humidity difference"
+        ],
+        "200228": [
+            "tpdiff",
+            "total precipitation difference"
+        ],
+        "200229": [
+            "iewsdiff",
+            "instantaneous x surface stress difference"
+        ],
+        "200230": [
+            "inssdiff",
+            "instantaneous y surface stress difference"
+        ],
+        "200231": [
+            "ishfdiff",
+            "instantaneous surface heat flux difference"
+        ],
+        "200232": [
+            "iediff",
+            "instantaneous moisture flux difference"
+        ],
+        "200233": [
+            "asqdiff",
+            "apparent surface humidity difference"
+        ],
+        "200234": [
+            "lsrhdiff",
+            "logarithm of surface roughness length for heat difference"
+        ],
+        "200235": [
+            "sktdiff",
+            "skin temperature difference"
+        ],
+        "200236": [
+            "stl4diff",
+            "soil temperature level 4 difference"
+        ],
+        "200237": [
+            "swl4diff",
+            "soil wetness level 4 difference"
+        ],
+        "200238": [
+            "tsndiff",
+            "temperature of snow layer difference"
+        ],
+        "200239": [
+            "csfdiff",
+            "convective snowfall difference"
+        ],
+        "200240": [
+            "lsfdiff",
+            "large scale snowfall difference"
+        ],
+        "200241": [
+            "acfdiff",
+            "accumulated cloud fraction tendency difference"
+        ],
+        "200242": [
+            "alwdiff",
+            "accumulated liquid water tendency difference"
+        ],
+        "200243": [
+            "faldiff",
+            "forecast albedo difference"
+        ],
+        "200244": [
+            "fsrdiff",
+            "forecast surface roughness difference"
+        ],
+        "200245": [
+            "flsrdiff",
+            "forecast logarithm of surface roughness for heat difference"
+        ],
+        "200246": [
+            "clwcdiff",
+            "specific cloud liquid water content difference"
+        ],
+        "200247": [
+            "ciwcdiff",
+            "specific cloud ice water content difference"
+        ],
+        "200248": [
+            "ccdiff",
+            "cloud cover difference"
+        ],
+        "200249": [
+            "aiwdiff",
+            "accumulated ice water tendency difference"
+        ],
+        "200250": [
+            "icediff",
+            "ice age difference"
+        ],
+        "200251": [
+            "attediff",
+            "adiabatic tendency of temperature difference"
+        ],
+        "200252": [
+            "athediff",
+            "adiabatic tendency of humidity difference"
+        ],
+        "200253": [
+            "atzediff",
+            "adiabatic tendency of zonal wind difference"
+        ],
+        "200254": [
+            "atmwdiff",
+            "adiabatic tendency of meridional wind difference"
+        ],
+        "201": [
+            "mx2t",
+            "maximum temperature at 2 metres since previous post-processing"
+        ],
+        "201001": [
+            "downward shortwave radiant flux density"
+        ],
+        "201002": [
+            "upward shortwave radiant flux density"
+        ],
+        "201003": [
+            "downward longwave radiant flux density"
+        ],
+        "201004": [
+            "upward longwave radiant flux density"
+        ],
+        "201005": [
+            "apab_s",
+            "downwd photosynthetic active radiant flux density"
+        ],
+        "201006": [
+            "net shortwave flux"
+        ],
+        "201007": [
+            "net longwave flux"
+        ],
+        "201008": [
+            "total net radiative flux density"
+        ],
+        "201009": [
+            "downw shortw radiant flux density, cloudfree part"
+        ],
+        "201010": [
+            "upw shortw radiant flux density, cloudy part"
+        ],
+        "201011": [
+            "downw longw radiant flux density, cloudfree part"
+        ],
+        "201012": [
+            "upw longw radiant flux density, cloudy part"
+        ],
+        "201013": [
+            "sohr_rad",
+            "shortwave radiative heating rate"
+        ],
+        "201014": [
+            "thhr_rad",
+            "longwave radiative heating rate"
+        ],
+        "201015": [
+            "total radiative heating rate"
+        ],
+        "201016": [
+            "soil heat flux, surface"
+        ],
+        "201017": [
+            "soil heat flux, bottom of layer"
+        ],
+        "201029": [
+            "clc",
+            "fractional cloud cover"
+        ],
+        "201030": [
+            "cloud cover, grid scale"
+        ],
+        "201031": [
+            "qc",
+            "specific cloud water content"
+        ],
+        "201032": [
+            "cloud water content, grid scale, vert integrated"
+        ],
+        "201033": [
+            "qi",
+            "specific cloud ice content, grid scale"
+        ],
+        "201034": [
+            "cloud ice content, grid scale, vert integrated"
+        ],
+        "201035": [
+            "specific rainwater content, grid scale"
+        ],
+        "201036": [
+            "specific snow content, grid scale"
+        ],
+        "201037": [
+            "specific rainwater content, gs, vert. integrated"
+        ],
+        "201038": [
+            "specific snow content, gs, vert. integrated"
+        ],
+        "201041": [
+            "twater",
+            "total column water"
+        ],
+        "201042": [
+            "vert. integral of divergence of tot. water content"
+        ],
+        "201050": [
+            "ch_cm_cl",
+            "cloud covers ch_cm_cl (000...888)"
+        ],
+        "201051": [
+            "cloud cover ch (0..8)"
+        ],
+        "201052": [
+            "cloud cover cm (0..8)"
+        ],
+        "201053": [
+            "cloud cover cl (0..8)"
+        ],
+        "201054": [
+            "total cloud cover (0..8)"
+        ],
+        "201055": [
+            "fog (0..8)"
+        ],
+        "201056": [
+            "fog"
+        ],
+        "201060": [
+            "cloud cover, convective cirrus"
+        ],
+        "201061": [
+            "specific cloud water content, convective clouds"
+        ],
+        "201062": [
+            "cloud water content, conv clouds, vert integrated"
+        ],
+        "201063": [
+            "specific cloud ice content, convective clouds"
+        ],
+        "201064": [
+            "cloud ice content, conv clouds, vert integrated"
+        ],
+        "201065": [
+            "convective mass flux"
+        ],
+        "201066": [
+            "updraft velocity, convection"
+        ],
+        "201067": [
+            "entrainment parameter, convection"
+        ],
+        "201068": [
+            "hbas_con",
+            "cloud base, convective clouds (above msl)"
+        ],
+        "201069": [
+            "htop_con",
+            "cloud top, convective clouds (above msl)"
+        ],
+        "201070": [
+            "convective layers (00...77)  (bke)"
+        ],
+        "201071": [
+            "ko-index"
+        ],
+        "201072": [
+            "bas_con",
+            "convection base index"
+        ],
+        "201073": [
+            "top_con",
+            "convection top index"
+        ],
+        "201074": [
+            "dt_con",
+            "convective temperature tendency"
+        ],
+        "201075": [
+            "dqv_con",
+            "convective tendency of specific humidity"
+        ],
+        "201076": [
+            "convective tendency of total heat"
+        ],
+        "201077": [
+            "convective tendency of total water"
+        ],
+        "201078": [
+            "du_con",
+            "convective momentum tendency (x-component)"
+        ],
+        "201079": [
+            "dv_con",
+            "convective momentum tendency (y-component)"
+        ],
+        "201080": [
+            "convective vorticity tendency"
+        ],
+        "201081": [
+            "convective divergence tendency"
+        ],
+        "201082": [
+            "htop_dc",
+            "top of dry convection (above msl)"
+        ],
+        "201083": [
+            "dry convection top index"
+        ],
+        "201084": [
+            "hzerocl",
+            "height of 0 degree celsius isotherm above msl"
+        ],
+        "201085": [
+            "snowlmt",
+            "height of snow-fall limit"
+        ],
+        "201099": [
+            "qrs_gsp",
+            "spec. content of precip. particles"
+        ],
+        "201100": [
+            "prr_gsp",
+            "surface precipitation rate, rain, grid scale"
+        ],
+        "201101": [
+            "prs_gsp",
+            "surface precipitation rate, snow, grid scale"
+        ],
+        "201102": [
+            "rain_gsp",
+            "surface precipitation amount, rain, grid scale"
+        ],
+        "201111": [
+            "prr_con",
+            "surface precipitation rate, rain, convective"
+        ],
+        "201112": [
+            "prs_con",
+            "surface precipitation rate, snow, convective"
+        ],
+        "201113": [
+            "rain_con",
+            "surface precipitation amount, rain, convective"
+        ],
+        "201139": [
+            "pp",
+            "deviation of pressure from reference value"
+        ],
+        "201150": [
+            "coefficient of horizontal diffusion"
+        ],
+        "201187": [
+            "vmax_10m",
+            "maximum wind velocity"
+        ],
+        "201200": [
+            "w_i",
+            "water content of interception store"
+        ],
+        "201203": [
+            "t_snow",
+            "snow temperature"
+        ],
+        "201215": [
+            "t_ice",
+            "ice surface temperature"
+        ],
+        "201241": [
+            "cape_con",
+            "convective available potential energy"
+        ],
+        "202": [
+            "mn2t",
+            "minimum temperature at 2 metres since previous post-processing"
+        ],
+        "203": [
+            "o3",
+            "ozone mass mixing ratio"
+        ],
+        "204": [
+            "paw",
+            "precipitation analysis weights"
+        ],
+        "205": [
+            "ro",
+            "runoff"
+        ],
+        "206": [
+            "tco3",
+            "total column ozone"
+        ],
+        "207": [
+            "10si",
+            "10 metre wind speed"
+        ],
+        "208": [
+            "tsrc",
+            "top net solar radiation, clear sky"
+        ],
+        "209": [
+            "ttrc",
+            "top net thermal radiation, clear sky",
+            "ttru"
+        ],
+        "21": [
+            "uctp",
+            "unbalanced component of temperature"
+        ],
+        "210": [
+            "ssrc",
+            "surface net solar radiation, clear sky"
+        ],
+        "210001": [
+            "aermr01",
+            "sea salt aerosol (0.03 - 0.5 um) mixing ratio"
+        ],
+        "210002": [
+            "aermr02",
+            "sea salt aerosol (0.5 - 5 um) mixing ratio"
+        ],
+        "210003": [
+            "aermr03",
+            "sea salt aerosol (5 - 20 um) mixing ratio"
+        ],
+        "210004": [
+            "aermr04",
+            "dust aerosol (0.03 - 0.55 um) mixing ratio"
+        ],
+        "210005": [
+            "aermr05",
+            "dust aerosol (0.55 - 0.9 um) mixing ratio"
+        ],
+        "210006": [
+            "aermr06",
+            "dust aerosol (0.9 - 20 um) mixing ratio"
+        ],
+        "210007": [
+            "aermr07",
+            "hydrophobic organic matter aerosol mixing ratio"
+        ],
+        "210008": [
+            "aermr08",
+            "hydrophilic organic matter aerosol mixing ratio"
+        ],
+        "210009": [
+            "aermr09",
+            "hydrophobic black carbon aerosol mixing ratio"
+        ],
+        "210010": [
+            "aermr10",
+            "hydrophilic black carbon aerosol mixing ratio"
+        ],
+        "210011": [
+            "aermr11",
+            "sulphate aerosol mixing ratio"
+        ],
+        "210012": [
+            "aermr12",
+            "so2 precursor mixing ratio"
+        ],
+        "210013": [
+            "aermr13",
+            "volcanic ash aerosol mixing ratio"
+        ],
+        "210014": [
+            "aermr14",
+            "volcanic sulphate aerosol mixing ratio"
+        ],
+        "210015": [
+            "aermr15",
+            "volcanic so2 precursor mixing ratio"
+        ],
+        "210016": [
+            "aergn01",
+            "aerosol type 1 source/gain accumulated"
+        ],
+        "210017": [
+            "aergn02",
+            "aerosol type 2 source/gain accumulated"
+        ],
+        "210018": [
+            "aergn03",
+            "aerosol type 3 source/gain accumulated"
+        ],
+        "210019": [
+            "aergn04",
+            "aerosol type 4 source/gain accumulated"
+        ],
+        "210020": [
+            "aergn05",
+            "aerosol type 5 source/gain accumulated"
+        ],
+        "210021": [
+            "aergn06",
+            "aerosol type 6 source/gain accumulated"
+        ],
+        "210022": [
+            "aergn07",
+            "aerosol type 7 source/gain accumulated"
+        ],
+        "210023": [
+            "aergn08",
+            "aerosol type 8 source/gain accumulated"
+        ],
+        "210024": [
+            "aergn09",
+            "aerosol type 9 source/gain accumulated"
+        ],
+        "210025": [
+            "aergn10",
+            "aerosol type 10 source/gain accumulated"
+        ],
+        "210026": [
+            "aergn11",
+            "aerosol type 11 source/gain accumulated"
+        ],
+        "210027": [
+            "aergn12",
+            "aerosol type 12 source/gain accumulated"
+        ],
+        "210028": [
+            "aerpr03",
+            "so4 aerosol precursor mass mixing ratio"
+        ],
+        "210029": [
+            "aerwv01",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 1"
+        ],
+        "210030": [
+            "aerwv02",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 2"
+        ],
+        "210031": [
+            "aerls01",
+            "aerosol type 1 sink/loss accumulated"
+        ],
+        "210032": [
+            "aerls02",
+            "aerosol type 2 sink/loss accumulated"
+        ],
+        "210033": [
+            "aerls03",
+            "aerosol type 3 sink/loss accumulated"
+        ],
+        "210034": [
+            "aerls04",
+            "aerosol type 4 sink/loss accumulated"
+        ],
+        "210035": [
+            "aerls05",
+            "aerosol type 5 sink/loss accumulated"
+        ],
+        "210036": [
+            "aerls06",
+            "aerosol type 6 sink/loss accumulated"
+        ],
+        "210037": [
+            "aerls07",
+            "aerosol type 7 sink/loss accumulated"
+        ],
+        "210038": [
+            "aerls08",
+            "aerosol type 8 sink/loss accumulated"
+        ],
+        "210039": [
+            "aerls09",
+            "aerosol type 9 sink/loss accumulated"
+        ],
+        "210040": [
+            "aerls10",
+            "aerosol type 10 sink/loss accumulated"
+        ],
+        "210041": [
+            "aerls11",
+            "aerosol type 11 sink/loss accumulated"
+        ],
+        "210042": [
+            "aerls12",
+            "aerosol type 12 sink/loss accumulated"
+        ],
+        "210043": [
+            "emdms",
+            "dms surface emission"
+        ],
+        "210044": [
+            "aerwv03",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 3"
+        ],
+        "210045": [
+            "aerwv04",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 4"
+        ],
+        "210046": [
+            "aerpr",
+            "aerosol precursor mixing ratio"
+        ],
+        "210047": [
+            "aersm",
+            "aerosol small mode mixing ratio"
+        ],
+        "210048": [
+            "aerlg",
+            "aerosol large mode mixing ratio"
+        ],
+        "210049": [
+            "aodpr",
+            "aerosol precursor optical depth"
+        ],
+        "210050": [
+            "aodsm",
+            "aerosol small mode optical depth"
+        ],
+        "210051": [
+            "aodlg",
+            "aerosol large mode optical depth"
+        ],
+        "210052": [
+            "aerdep",
+            "dust emission potential"
+        ],
+        "210053": [
+            "aerlts",
+            "lifting threshold speed"
+        ],
+        "210054": [
+            "aerscc",
+            "soil clay content"
+        ],
+        "210057": [
+            "ocnuc",
+            "mixing ration of organic carbon aerosol, nucleation mode"
+        ],
+        "210058": [
+            "monot",
+            "monoterpene precursor mixing ratio"
+        ],
+        "210059": [
+            "soapr",
+            "secondary organic precursor mixing ratio"
+        ],
+        "210061": [
+            "co2",
+            "carbon dioxide"
+        ],
+        "210062": [
+            "ch4",
+            "methane"
+        ],
+        "210063": [
+            "n2o",
+            "nitrous oxide"
+        ],
+        "210064": [
+            "tcco2",
+            "total column carbon dioxide"
+        ],
+        "210065": [
+            "tcch4",
+            "total column methane"
+        ],
+        "210066": [
+            "tcn2o",
+            "total column nitrous oxide"
+        ],
+        "210067": [
+            "co2of",
+            "ocean flux of carbon dioxide"
+        ],
+        "210068": [
+            "co2nbf",
+            "natural biosphere flux of carbon dioxide"
+        ],
+        "210069": [
+            "co2apf",
+            "anthropogenic emissions of carbon dioxide"
+        ],
+        "210070": [
+            "ch4f",
+            "methane surface fluxes"
+        ],
+        "210071": [
+            "kch4",
+            "methane loss rate due to radical hydroxyl (oh)"
+        ],
+        "210072": [
+            "pm1",
+            "particulate matter d < 1 um"
+        ],
+        "210073": [
+            "pm2p5",
+            "particulate matter d < 2.5 um"
+        ],
+        "210074": [
+            "pm10",
+            "particulate matter d < 10 um"
+        ],
+        "210079": [
+            "vafire",
+            "wildfire viewing angle of observation"
+        ],
+        "210080": [
+            "co2fire",
+            "wildfire flux of carbon dioxide"
+        ],
+        "210081": [
+            "cofire",
+            "wildfire flux of carbon monoxide"
+        ],
+        "210082": [
+            "ch4fire",
+            "wildfire flux of methane"
+        ],
+        "210083": [
+            "nmhcfire",
+            "wildfire flux of non-methane hydro-carbons"
+        ],
+        "210084": [
+            "h2fire",
+            "wildfire flux of hydrogen"
+        ],
+        "210085": [
+            "noxfire",
+            "wildfire flux of nitrogen oxides nox"
+        ],
+        "210086": [
+            "n2ofire",
+            "wildfire flux of nitrous oxide"
+        ],
+        "210087": [
+            "pm2p5fire",
+            "wildfire flux of particulate matter pm2.5"
+        ],
+        "210088": [
+            "tpmfire",
+            "wildfire flux of total particulate matter"
+        ],
+        "210089": [
+            "tcfire",
+            "wildfire flux of total carbon in aerosols"
+        ],
+        "210090": [
+            "ocfire",
+            "wildfire flux of organic carbon"
+        ],
+        "210091": [
+            "bcfire",
+            "wildfire flux of black carbon"
+        ],
+        "210092": [
+            "cfire",
+            "wildfire overall flux of burnt carbon"
+        ],
+        "210093": [
+            "c4ffire",
+            "wildfire fraction of c4 plants"
+        ],
+        "210094": [
+            "vegfire",
+            "wildfire vegetation map index"
+        ],
+        "210095": [
+            "ccfire",
+            "wildfire combustion completeness"
+        ],
+        "210096": [
+            "flfire",
+            "wildfire fuel load: carbon per unit area"
+        ],
+        "210097": [
+            "offire",
+            "wildfire fraction of area observed"
+        ],
+        "210098": [
+            "nofrp",
+            "number of positive frp pixels per grid cell"
+        ],
+        "210099": [
+            "frpfire",
+            "wildfire radiative power"
+        ],
+        "210100": [
+            "crfire",
+            "wildfire combustion rate"
+        ],
+        "210101": [
+            "maxfrpfire",
+            "wildfire radiative power maximum"
+        ],
+        "210102": [
+            "so2fire",
+            "wildfire flux of sulfur dioxide"
+        ],
+        "210103": [
+            "ch3ohfire",
+            "wildfire flux of methanol (ch3oh)"
+        ],
+        "210104": [
+            "c2h5ohfire",
+            "wildfire flux of ethanol (c2h5oh)"
+        ],
+        "210105": [
+            "c3h8fire",
+            "wildfire flux of propane (c3h8)"
+        ],
+        "210106": [
+            "c2h4fire",
+            "wildfire flux of ethene (c2h4)"
+        ],
+        "210107": [
+            "c3h6fire",
+            "wildfire flux of propene (c3h6)"
+        ],
+        "210108": [
+            "c5h8fire",
+            "wildfire flux of isoprene (c5h8)"
+        ],
+        "210109": [
+            "terpenesfire",
+            "wildfire flux of terpenes (c5h8)n"
+        ],
+        "210110": [
+            "toluenefire",
+            "wildfire flux of toluene_lump (c7h8+ c6h6 + c8h10)"
+        ],
+        "210111": [
+            "hialkenesfire",
+            "wildfire flux of higher alkenes (cnh2n, c>=4)"
+        ],
+        "210112": [
+            "hialkanesfire",
+            "wildfire flux of higher alkanes (cnh2n+2, c>=4)"
+        ],
+        "210113": [
+            "ch2ofire",
+            "wildfire flux of formaldehyde (ch2o)"
+        ],
+        "210114": [
+            "c2h4ofire",
+            "wildfire flux of acetaldehyde (c2h4o)"
+        ],
+        "210115": [
+            "c3h6ofire",
+            "wildfire flux of acetone (c3h6o)"
+        ],
+        "210116": [
+            "nh3fire",
+            "wildfire flux of ammonia (nh3)"
+        ],
+        "210117": [
+            "c2h6sfire",
+            "wildfire flux of dimethyl sulfide (dms) (c2h6s)"
+        ],
+        "210118": [
+            "c2h6fire",
+            "wildfire flux of ethane (c2h6)"
+        ],
+        "210119": [
+            "mami",
+            "mean altitude of maximum injection"
+        ],
+        "210120": [
+            "apt",
+            "altitude of plume top"
+        ],
+        "210121": [
+            "no2",
+            "nitrogen dioxide"
+        ],
+        "210122": [
+            "so2",
+            "sulphur dioxide"
+        ],
+        "210123": [
+            "co",
+            "carbon monoxide"
+        ],
+        "210124": [
+            "hcho",
+            "formaldehyde"
+        ],
+        "210125": [
+            "tcno2",
+            "total column nitrogen dioxide"
+        ],
+        "210126": [
+            "tcso2",
+            "total column sulphur dioxide"
+        ],
+        "210127": [
+            "tcco",
+            "total column carbon monoxide"
+        ],
+        "210128": [
+            "tchcho",
+            "total column formaldehyde"
+        ],
+        "210129": [
+            "nox",
+            "nitrogen oxides"
+        ],
+        "210130": [
+            "tcnox",
+            "total column nitrogen oxides"
+        ],
+        "210131": [
+            "grg1",
+            "reactive tracer 1 mass mixing ratio"
+        ],
+        "210132": [
+            "tcgrg1",
+            "total column grg tracer 1"
+        ],
+        "210133": [
+            "grg2",
+            "reactive tracer 2 mass mixing ratio"
+        ],
+        "210134": [
+            "tcgrg2",
+            "total column grg tracer 2"
+        ],
+        "210135": [
+            "grg3",
+            "reactive tracer 3 mass mixing ratio"
+        ],
+        "210136": [
+            "tcgrg3",
+            "total column grg tracer 3"
+        ],
+        "210137": [
+            "grg4",
+            "reactive tracer 4 mass mixing ratio"
+        ],
+        "210138": [
+            "tcgrg4",
+            "total column grg tracer 4"
+        ],
+        "210139": [
+            "grg5",
+            "reactive tracer 5 mass mixing ratio"
+        ],
+        "210140": [
+            "tcgrg5",
+            "total column grg tracer 5"
+        ],
+        "210141": [
+            "grg6",
+            "reactive tracer 6 mass mixing ratio"
+        ],
+        "210142": [
+            "tcgrg6",
+            "total column grg tracer 6"
+        ],
+        "210143": [
+            "grg7",
+            "reactive tracer 7 mass mixing ratio"
+        ],
+        "210144": [
+            "tcgrg7",
+            "total column grg tracer 7"
+        ],
+        "210145": [
+            "grg8",
+            "reactive tracer 8 mass mixing ratio"
+        ],
+        "210146": [
+            "tcgrg8",
+            "total column grg tracer 8"
+        ],
+        "210147": [
+            "grg9",
+            "reactive tracer 9 mass mixing ratio"
+        ],
+        "210148": [
+            "tcgrg9",
+            "total column grg tracer 9"
+        ],
+        "210149": [
+            "grg10",
+            "reactive tracer 10 mass mixing ratio"
+        ],
+        "210150": [
+            "tcgrg10",
+            "total column grg tracer 10"
+        ],
+        "210151": [
+            "sfnox",
+            "surface flux nitrogen oxides"
+        ],
+        "210152": [
+            "sfno2",
+            "surface flux nitrogen dioxide"
+        ],
+        "210153": [
+            "sfso2",
+            "surface flux sulphur dioxide"
+        ],
+        "210154": [
+            "sfco2",
+            "surface flux carbon monoxide"
+        ],
+        "210155": [
+            "sfhcho",
+            "surface flux formaldehyde"
+        ],
+        "210156": [
+            "sfgo3",
+            "surface flux gems ozone"
+        ],
+        "210157": [
+            "sfgr1",
+            "surface flux reactive tracer 1"
+        ],
+        "210158": [
+            "sfgr2",
+            "surface flux reactive tracer 2"
+        ],
+        "210159": [
+            "sfgr3",
+            "surface flux reactive tracer 3"
+        ],
+        "210160": [
+            "sfgr4",
+            "surface flux reactive tracer 4"
+        ],
+        "210161": [
+            "sfgr5",
+            "surface flux reactive tracer 5"
+        ],
+        "210162": [
+            "sfgr6",
+            "surface flux reactive tracer 6"
+        ],
+        "210163": [
+            "sfgr7",
+            "surface flux reactive tracer 7"
+        ],
+        "210164": [
+            "sfgr8",
+            "surface flux reactive tracer 8"
+        ],
+        "210165": [
+            "sfgr9",
+            "surface flux reactive tracer 9"
+        ],
+        "210166": [
+            "sfgr10",
+            "surface flux reactive tracer 10"
+        ],
+        "210181": [
+            "ra",
+            "radon"
+        ],
+        "210182": [
+            "sf6",
+            "sulphur hexafluoride"
+        ],
+        "210183": [
+            "tcra",
+            "total column radon"
+        ],
+        "210184": [
+            "tcsf6",
+            "total column sulphur hexafluoride"
+        ],
+        "210185": [
+            "sf6apf",
+            "anthropogenic emissions of sulphur hexafluoride"
+        ],
+        "210186": [
+            "aluvpi",
+            "uv visible albedo for direct radiation, isotropic component "
+        ],
+        "210187": [
+            "aluvpv",
+            "uv visible albedo for direct radiation, volumetric component "
+        ],
+        "210188": [
+            "aluvpg",
+            "uv visible albedo for direct radiation, geometric component "
+        ],
+        "210189": [
+            "alnipi",
+            "near ir albedo for direct radiation, isotropic component "
+        ],
+        "210190": [
+            "alnipv",
+            "near ir albedo for direct radiation, volumetric component"
+        ],
+        "210191": [
+            "alnipg",
+            "near ir albedo for direct radiation, geometric component "
+        ],
+        "210192": [
+            "aluvdi",
+            "uv visible albedo for diffuse radiation, isotropic component "
+        ],
+        "210193": [
+            "aluvdv",
+            "uv visible albedo for diffuse radiation, volumetric component "
+        ],
+        "210194": [
+            "aluvdg",
+            "uv visible albedo for diffuse radiation, geometric component "
+        ],
+        "210195": [
+            "alnidi",
+            "near ir albedo for diffuse radiation, isotropic component "
+        ],
+        "210196": [
+            "alnidv",
+            "near ir albedo for diffuse radiation, volumetric component "
+        ],
+        "210197": [
+            "alnidg",
+            "near ir albedo for diffuse radiation, geometric component "
+        ],
+        "210203": [
+            "go3",
+            "gems ozone"
+        ],
+        "210206": [
+            "gtco3",
+            "gems total column ozone"
+        ],
+        "210207": [
+            "aod550",
+            "total aerosol optical depth at 550nm"
+        ],
+        "210208": [
+            "ssaod550",
+            "sea salt aerosol optical depth at 550nm"
+        ],
+        "210209": [
+            "duaod550",
+            "dust aerosol optical depth at 550nm"
+        ],
+        "210210": [
+            "omaod550",
+            "organic matter aerosol optical depth at 550nm"
+        ],
+        "210211": [
+            "bcaod550",
+            "black carbon aerosol optical depth at 550nm"
+        ],
+        "210212": [
+            "suaod550",
+            "sulphate aerosol optical depth at 550nm"
+        ],
+        "210213": [
+            "aod469",
+            "total aerosol optical depth at 469nm"
+        ],
+        "210214": [
+            "aod670",
+            "total aerosol optical depth at 670nm"
+        ],
+        "210215": [
+            "aod865",
+            "total aerosol optical depth at 865nm"
+        ],
+        "210216": [
+            "aod1240",
+            "total aerosol optical depth at 1240nm"
+        ],
+        "210217": [
+            "aod340",
+            "total aerosol optical depth at 340 nm"
+        ],
+        "210218": [
+            "aod355",
+            "total aerosol optical depth at 355 nm"
+        ],
+        "210219": [
+            "aod380",
+            "total aerosol optical depth at 380 nm"
+        ],
+        "210220": [
+            "aod400",
+            "total aerosol optical depth at 400 nm"
+        ],
+        "210221": [
+            "aod440",
+            "total aerosol optical depth at 440 nm"
+        ],
+        "210222": [
+            "aod500",
+            "total aerosol optical depth at 500 nm"
+        ],
+        "210223": [
+            "aod532",
+            "total aerosol optical depth at 532 nm"
+        ],
+        "210224": [
+            "aod645",
+            "total aerosol optical depth at 645 nm"
+        ],
+        "210225": [
+            "aod800",
+            "total aerosol optical depth at 800 nm"
+        ],
+        "210226": [
+            "aod858",
+            "total aerosol optical depth at 858 nm"
+        ],
+        "210227": [
+            "aod1020",
+            "total aerosol optical depth at 1020 nm"
+        ],
+        "210228": [
+            "aod1064",
+            "total aerosol optical depth at 1064 nm"
+        ],
+        "210229": [
+            "aod1640",
+            "total aerosol optical depth at 1640 nm"
+        ],
+        "210230": [
+            "aod2130",
+            "total aerosol optical depth at 2130 nm"
+        ],
+        "210231": [
+            "c7h8fire",
+            "wildfire flux of toluene (c7h8)"
+        ],
+        "210232": [
+            "c6h6fire",
+            "wildfire flux of benzene (c6h6)"
+        ],
+        "210233": [
+            "c8h10fire",
+            "wildfire flux of xylene (c8h10)"
+        ],
+        "210234": [
+            "c4h8fire",
+            "wildfire flux of butenes (c4h8)"
+        ],
+        "210235": [
+            "c5h10fire",
+            "wildfire flux of pentenes (c5h10)"
+        ],
+        "210236": [
+            "c6h12fire",
+            "wildfire flux of hexene (c6h12)"
+        ],
+        "210237": [
+            "c8h16fire",
+            "wildfire flux of octene (c8h16)"
+        ],
+        "210238": [
+            "c4h10fire",
+            "wildfire flux of butanes (c4h10)"
+        ],
+        "210239": [
+            "c5h12fire",
+            "wildfire flux of pentanes (c5h12)"
+        ],
+        "210240": [
+            "c6h14fire",
+            "wildfire flux of hexanes (c6h14)"
+        ],
+        "210241": [
+            "c7h16fire",
+            "wildfire flux of heptane (c7h16)"
+        ],
+        "210242": [
+            "apb",
+            "altitude of plume bottom"
+        ],
+        "210243": [
+            "vsuaod550",
+            "volcanic sulphate aerosol optical depth at 550 nm"
+        ],
+        "210244": [
+            "vashaod550",
+            "volcanic ash optical depth at 550 nm"
+        ],
+        "210245": [
+            "taedec550",
+            "profile of total aerosol dry extinction coefficient"
+        ],
+        "210246": [
+            "taedab550",
+            "profile of total aerosol dry absorption coefficient"
+        ],
+        "211": [
+            "strc",
+            "surface net thermal radiation, clear sky"
+        ],
+        "211001": [
+            "aermr01diff",
+            "sea salt aerosol (0.03 - 0.5 um) mixing ratio"
+        ],
+        "211002": [
+            "aermr02diff",
+            "sea salt aerosol (0.5 - 5 um) mixing ratio"
+        ],
+        "211003": [
+            "aermr03diff",
+            "sea salt aerosol (5 - 20 um) mixing ratio"
+        ],
+        "211004": [
+            "aermr04diff",
+            "dust aerosol (0.03 - 0.55 um) mixing ratio"
+        ],
+        "211005": [
+            "aermr05diff",
+            "dust aerosol (0.55 - 0.9 um) mixing ratio"
+        ],
+        "211006": [
+            "aermr06diff",
+            "dust aerosol (0.9 - 20 um) mixing ratio"
+        ],
+        "211007": [
+            "aermr07diff",
+            "hydrophobic organic matter aerosol mixing ratio"
+        ],
+        "211008": [
+            "aermr08diff",
+            "hydrophilic organic matter aerosol mixing ratio"
+        ],
+        "211009": [
+            "aermr09diff",
+            "hydrophobic black carbon aerosol mixing ratio"
+        ],
+        "211010": [
+            "aermr10diff",
+            "hydrophilic black carbon aerosol mixing ratio"
+        ],
+        "211011": [
+            "aermr11diff",
+            "sulphate aerosol mixing ratio"
+        ],
+        "211012": [
+            "aermr12diff",
+            "aerosol type 12 mixing ratio"
+        ],
+        "211013": [
+            "aermr13diff",
+            "aerosol type 13 mass mixing ratio"
+        ],
+        "211014": [
+            "aermr14diff",
+            "aerosol type 14 mass mixing ratio"
+        ],
+        "211015": [
+            "aermr15diff",
+            "aerosol type 15 mass mixing ratio"
+        ],
+        "211016": [
+            "aergn01diff",
+            "aerosol type 1 source/gain accumulated"
+        ],
+        "211017": [
+            "aergn02diff",
+            "aerosol type 2 source/gain accumulated"
+        ],
+        "211018": [
+            "aergn03diff",
+            "aerosol type 3 source/gain accumulated"
+        ],
+        "211019": [
+            "aergn04diff",
+            "aerosol type 4 source/gain accumulated"
+        ],
+        "211020": [
+            "aergn05diff",
+            "aerosol type 5 source/gain accumulated"
+        ],
+        "211021": [
+            "aergn06diff",
+            "aerosol type 6 source/gain accumulated"
+        ],
+        "211022": [
+            "aergn07diff",
+            "aerosol type 7 source/gain accumulated"
+        ],
+        "211023": [
+            "aergn08diff",
+            "aerosol type 8 source/gain accumulated"
+        ],
+        "211024": [
+            "aergn09diff",
+            "aerosol type 9 source/gain accumulated"
+        ],
+        "211025": [
+            "aergn10diff",
+            "aerosol type 10 source/gain accumulated"
+        ],
+        "211026": [
+            "aergn11diff",
+            "aerosol type 11 source/gain accumulated"
+        ],
+        "211027": [
+            "aergn12diff",
+            "aerosol type 12 source/gain accumulated"
+        ],
+        "211028": [
+            "aerpr03diff",
+            "so4 aerosol precursor mass mixing ratio"
+        ],
+        "211029": [
+            "aerwv01diff",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 1"
+        ],
+        "211030": [
+            "aerwv02diff",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 2"
+        ],
+        "211031": [
+            "aerls01diff",
+            "aerosol type 1 sink/loss accumulated"
+        ],
+        "211032": [
+            "aerls02diff",
+            "aerosol type 2 sink/loss accumulated"
+        ],
+        "211033": [
+            "aerls03diff",
+            "aerosol type 3 sink/loss accumulated"
+        ],
+        "211034": [
+            "aerls04diff",
+            "aerosol type 4 sink/loss accumulated"
+        ],
+        "211035": [
+            "aerls05diff",
+            "aerosol type 5 sink/loss accumulated"
+        ],
+        "211036": [
+            "aerls06diff",
+            "aerosol type 6 sink/loss accumulated"
+        ],
+        "211037": [
+            "aerls07diff",
+            "aerosol type 7 sink/loss accumulated"
+        ],
+        "211038": [
+            "aerls08diff",
+            "aerosol type 8 sink/loss accumulated"
+        ],
+        "211039": [
+            "aerls09diff",
+            "aerosol type 9 sink/loss accumulated"
+        ],
+        "211040": [
+            "aerls10diff",
+            "aerosol type 10 sink/loss accumulated"
+        ],
+        "211041": [
+            "aerls11diff",
+            "aerosol type 11 sink/loss accumulated"
+        ],
+        "211042": [
+            "aerls12diff",
+            "aerosol type 12 sink/loss accumulated"
+        ],
+        "211043": [
+            "emdmsdiff",
+            "dms surface emission"
+        ],
+        "211044": [
+            "aerwv03diff",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 3"
+        ],
+        "211045": [
+            "aerwv04diff",
+            "water vapour mixing ratio for hydrophilic aerosols in mode 4"
+        ],
+        "211046": [
+            "aerprdiff",
+            "aerosol precursor mixing ratio"
+        ],
+        "211047": [
+            "aersmdiff",
+            "aerosol small mode mixing ratio"
+        ],
+        "211048": [
+            "aerlgdiff",
+            "aerosol large mode mixing ratio"
+        ],
+        "211049": [
+            "aodprdiff",
+            "aerosol precursor optical depth"
+        ],
+        "211050": [
+            "aodsmdiff",
+            "aerosol small mode optical depth"
+        ],
+        "211051": [
+            "aodlgdiff",
+            "aerosol large mode optical depth"
+        ],
+        "211052": [
+            "aerdepdiff",
+            "dust emission potential"
+        ],
+        "211053": [
+            "aerltsdiff",
+            "lifting threshold speed"
+        ],
+        "211054": [
+            "aersccdiff",
+            "soil clay content"
+        ],
+        "211061": [
+            "co2diff",
+            "carbon dioxide"
+        ],
+        "211062": [
+            "ch4diff",
+            "methane"
+        ],
+        "211063": [
+            "n2odiff",
+            "nitrous oxide"
+        ],
+        "211064": [
+            "tcco2diff",
+            "total column carbon dioxide"
+        ],
+        "211065": [
+            "tcch4diff",
+            "total column methane"
+        ],
+        "211066": [
+            "tcn2odiff",
+            "total column nitrous oxide"
+        ],
+        "211067": [
+            "co2ofdiff",
+            "ocean flux of carbon dioxide"
+        ],
+        "211068": [
+            "co2nbfdiff",
+            "natural biosphere flux of carbon dioxide"
+        ],
+        "211069": [
+            "co2apfdiff",
+            "anthropogenic emissions of carbon dioxide"
+        ],
+        "211070": [
+            "ch4fdiff",
+            "methane surface fluxes"
+        ],
+        "211071": [
+            "kch4diff",
+            "methane loss rate due to radical hydroxyl (oh)"
+        ],
+        "211080": [
+            "co2firediff",
+            "wildfire flux of carbon dioxide"
+        ],
+        "211081": [
+            "cofirediff",
+            "wildfire flux of carbon monoxide"
+        ],
+        "211082": [
+            "ch4firediff",
+            "wildfire flux of methane"
+        ],
+        "211083": [
+            "nmhcfirediff",
+            "wildfire flux of non-methane hydro-carbons"
+        ],
+        "211084": [
+            "h2firediff",
+            "wildfire flux of hydrogen"
+        ],
+        "211085": [
+            "noxfirediff",
+            "wildfire flux of nitrogen oxides nox"
+        ],
+        "211086": [
+            "n2ofirediff",
+            "wildfire flux of nitrous oxide"
+        ],
+        "211087": [
+            "pm2p5firediff",
+            "wildfire flux of particulate matter pm2.5"
+        ],
+        "211088": [
+            "tpmfirediff",
+            "wildfire flux of total particulate matter"
+        ],
+        "211089": [
+            "tcfirediff",
+            "wildfire flux of total carbon in aerosols"
+        ],
+        "211090": [
+            "ocfirediff",
+            "wildfire flux of organic carbon"
+        ],
+        "211091": [
+            "bcfirediff",
+            "wildfire flux of black carbon"
+        ],
+        "211092": [
+            "cfirediff",
+            "wildfire overall flux of burnt carbon"
+        ],
+        "211093": [
+            "c4ffirediff",
+            "wildfire fraction of c4 plants"
+        ],
+        "211094": [
+            "vegfirediff",
+            "wildfire vegetation map index"
+        ],
+        "211095": [
+            "ccfirediff",
+            "wildfire combustion completeness"
+        ],
+        "211096": [
+            "flfirediff",
+            "wildfire fuel load: carbon per unit area"
+        ],
+        "211097": [
+            "offirediff",
+            "wildfire fraction of area observed"
+        ],
+        "211098": [
+            "oafirediff",
+            "wildfire observed area"
+        ],
+        "211099": [
+            "frpfirediff",
+            "wildfire radiative power"
+        ],
+        "211100": [
+            "crfirediff",
+            "wildfire combustion rate"
+        ],
+        "211101": [
+            "maxfrpfirediff",
+            "wildfire radiative power maximum"
+        ],
+        "211102": [
+            "so2firediff",
+            "wildfire flux of sulfur dioxide"
+        ],
+        "211103": [
+            "ch3ohfirediff",
+            "wildfire flux of methanol (ch3oh)"
+        ],
+        "211104": [
+            "c2h5ohfirediff",
+            "wildfire flux of ethanol (c2h5oh)"
+        ],
+        "211105": [
+            "c3h8firediff",
+            "wildfire flux of propane (c3h8)"
+        ],
+        "211106": [
+            "c2h4firediff",
+            "wildfire flux of ethene (c2h4)"
+        ],
+        "211107": [
+            "c3h6firediff",
+            "wildfire flux of propene (c3h6)"
+        ],
+        "211108": [
+            "c5h8firediff",
+            "wildfire flux of isoprene (c5h8)"
+        ],
+        "211109": [
+            "terpenesfirediff",
+            "wildfire flux of terpenes (c5h8)n"
+        ],
+        "211110": [
+            "toluenefirediff",
+            "wildfire flux of toluene_lump (c7h8+ c6h6 + c8h10)"
+        ],
+        "211111": [
+            "hialkenesfirediff",
+            "wildfire flux of higher alkenes (cnh2n, c>=4)"
+        ],
+        "211112": [
+            "hialkanesfirediff",
+            "wildfire flux of higher alkanes (cnh2n+2, c>=4)"
+        ],
+        "211113": [
+            "ch2ofirediff",
+            "wildfire flux of formaldehyde (ch2o)"
+        ],
+        "211114": [
+            "c2h4ofirediff",
+            "wildfire flux of acetaldehyde (c2h4o)"
+        ],
+        "211115": [
+            "c3h6ofirediff",
+            "wildfire flux of acetone (c3h6o)"
+        ],
+        "211116": [
+            "nh3firediff",
+            "wildfire flux of ammonia (nh3)"
+        ],
+        "211117": [
+            "c2h6sfirediff",
+            "wildfire flux of dimethyl sulfide (dms) (c2h6s)"
+        ],
+        "211118": [
+            "c2h6firediff",
+            "wildfire flux of ethane (c2h6)"
+        ],
+        "211119": [
+            "alediff",
+            "altitude of emitter"
+        ],
+        "211120": [
+            "aptdiff",
+            "altitude of plume top"
+        ],
+        "211121": [
+            "no2diff",
+            "nitrogen dioxide"
+        ],
+        "211122": [
+            "so2diff",
+            "sulphur dioxide"
+        ],
+        "211123": [
+            "codiff",
+            "carbon monoxide"
+        ],
+        "211124": [
+            "hchodiff",
+            "formaldehyde"
+        ],
+        "211125": [
+            "tcno2diff",
+            "total column nitrogen dioxide"
+        ],
+        "211126": [
+            "tcso2diff",
+            "total column sulphur dioxide"
+        ],
+        "211127": [
+            "tccodiff",
+            "total column carbon monoxide"
+        ],
+        "211128": [
+            "tchchodiff",
+            "total column formaldehyde"
+        ],
+        "211129": [
+            "noxdiff",
+            "nitrogen oxides"
+        ],
+        "211130": [
+            "tcnoxdiff",
+            "total column nitrogen oxides"
+        ],
+        "211131": [
+            "grg1diff",
+            "reactive tracer 1 mass mixing ratio"
+        ],
+        "211132": [
+            "tcgrg1diff",
+            "total column grg tracer 1"
+        ],
+        "211133": [
+            "grg2diff",
+            "reactive tracer 2 mass mixing ratio"
+        ],
+        "211134": [
+            "tcgrg2diff",
+            "total column grg tracer 2"
+        ],
+        "211135": [
+            "grg3diff",
+            "reactive tracer 3 mass mixing ratio"
+        ],
+        "211136": [
+            "tcgrg3diff",
+            "total column grg tracer 3"
+        ],
+        "211137": [
+            "grg4diff",
+            "reactive tracer 4 mass mixing ratio"
+        ],
+        "211138": [
+            "tcgrg4diff",
+            "total column grg tracer 4"
+        ],
+        "211139": [
+            "grg5diff",
+            "reactive tracer 5 mass mixing ratio"
+        ],
+        "211140": [
+            "tcgrg5diff",
+            "total column grg tracer 5"
+        ],
+        "211141": [
+            "grg6diff",
+            "reactive tracer 6 mass mixing ratio"
+        ],
+        "211142": [
+            "tcgrg6diff",
+            "total column grg tracer 6"
+        ],
+        "211143": [
+            "grg7diff",
+            "reactive tracer 7 mass mixing ratio"
+        ],
+        "211144": [
+            "tcgrg7diff",
+            "total column grg tracer 7"
+        ],
+        "211145": [
+            "grg8diff",
+            "reactive tracer 8 mass mixing ratio"
+        ],
+        "211146": [
+            "tcgrg8diff",
+            "total column grg tracer 8"
+        ],
+        "211147": [
+            "grg9diff",
+            "reactive tracer 9 mass mixing ratio"
+        ],
+        "211148": [
+            "tcgrg9diff",
+            "total column grg tracer 9"
+        ],
+        "211149": [
+            "grg10diff",
+            "reactive tracer 10 mass mixing ratio"
+        ],
+        "211150": [
+            "tcgrg10diff",
+            "total column grg tracer 10"
+        ],
+        "211151": [
+            "sfnoxdiff",
+            "surface flux nitrogen oxides"
+        ],
+        "211152": [
+            "sfno2diff",
+            "surface flux nitrogen dioxide"
+        ],
+        "211153": [
+            "sfso2diff",
+            "surface flux sulphur dioxide"
+        ],
+        "211154": [
+            "sfco2diff",
+            "surface flux carbon monoxide"
+        ],
+        "211155": [
+            "sfhchodiff",
+            "surface flux formaldehyde"
+        ],
+        "211156": [
+            "sfgo3diff",
+            "surface flux gems ozone"
+        ],
+        "211157": [
+            "sfgr1diff",
+            "surface flux reactive tracer 1"
+        ],
+        "211158": [
+            "sfgr2diff",
+            "surface flux reactive tracer 2"
+        ],
+        "211159": [
+            "sfgr3diff",
+            "surface flux reactive tracer 3"
+        ],
+        "211160": [
+            "sfgr4diff",
+            "surface flux reactive tracer 4"
+        ],
+        "211161": [
+            "sfgr5diff",
+            "surface flux reactive tracer 5"
+        ],
+        "211162": [
+            "sfgr6diff",
+            "surface flux reactive tracer 6"
+        ],
+        "211163": [
+            "sfgr7diff",
+            "surface flux reactive tracer 7"
+        ],
+        "211164": [
+            "sfgr8diff",
+            "surface flux reactive tracer 8"
+        ],
+        "211165": [
+            "sfgr9diff",
+            "surface flux reactive tracer 9"
+        ],
+        "211166": [
+            "sfgr10diff",
+            "surface flux reactive tracer 10"
+        ],
+        "211181": [
+            "radiff",
+            "radon"
+        ],
+        "211182": [
+            "sf6diff",
+            "sulphur hexafluoride"
+        ],
+        "211183": [
+            "tcradiff",
+            "total column radon"
+        ],
+        "211184": [
+            "tcsf6diff",
+            "total column sulphur hexafluoride"
+        ],
+        "211185": [
+            "sf6apfdiff",
+            "anthropogenic emissions of sulphur hexafluoride"
+        ],
+        "211203": [
+            "go3diff",
+            "gems ozone"
+        ],
+        "211206": [
+            "gtco3diff",
+            "gems total column ozone"
+        ],
+        "211207": [
+            "aod550diff",
+            "total aerosol optical depth at 550nm"
+        ],
+        "211208": [
+            "ssaod550diff",
+            "sea salt aerosol optical depth at 550nm"
+        ],
+        "211209": [
+            "duaod550diff",
+            "dust aerosol optical depth at 550nm"
+        ],
+        "211210": [
+            "omaod550diff",
+            "organic matter aerosol optical depth at 550nm"
+        ],
+        "211211": [
+            "bcaod550diff",
+            "black carbon aerosol optical depth at 550nm"
+        ],
+        "211212": [
+            "suaod550diff",
+            "sulphate aerosol optical depth at 550nm"
+        ],
+        "211213": [
+            "aod469diff",
+            "total aerosol optical depth at 469nm"
+        ],
+        "211214": [
+            "aod670diff",
+            "total aerosol optical depth at 670nm"
+        ],
+        "211215": [
+            "aod865diff",
+            "total aerosol optical depth at 865nm"
+        ],
+        "211216": [
+            "aod1240diff",
+            "total aerosol optical depth at 1240nm"
+        ],
+        "212": [
+            "tisr",
+            "toa incident solar radiation"
+        ],
+        "213": [
+            "vimd",
+            "vertically integrated moisture divergence"
+        ],
+        "213001": [
+            "sppt1",
+            "random pattern 1 for sppt"
+        ],
+        "213002": [
+            "sppt2",
+            "random pattern 2 for sppt"
+        ],
+        "213003": [
+            "sppt3",
+            "random pattern 3 for sppt"
+        ],
+        "213004": [
+            "sppt4",
+            "random pattern 4 for sppt"
+        ],
+        "213005": [
+            "sppt5",
+            "random pattern 5 for sppt"
+        ],
+        "213101": [
+            "spp1",
+            "random pattern 1 for spp scheme"
+        ],
+        "213102": [
+            "spp2",
+            "random pattern 2 for spp scheme"
+        ],
+        "213103": [
+            "spp3",
+            "random pattern 3 for spp scheme"
+        ],
+        "213104": [
+            "spp4",
+            "random pattern 4 for spp scheme"
+        ],
+        "213105": [
+            "spp5",
+            "random pattern 5 for spp scheme"
+        ],
+        "213106": [
+            "spp6",
+            "random pattern 6 for spp scheme"
+        ],
+        "213107": [
+            "spp7",
+            "random pattern 7 for spp scheme"
+        ],
+        "213108": [
+            "spp8",
+            "random pattern 8 for spp scheme"
+        ],
+        "213109": [
+            "spp9",
+            "random pattern 9 for spp scheme"
+        ],
+        "213110": [
+            "spp10",
+            "random pattern 10 for spp scheme"
+        ],
+        "213111": [
+            "spp11",
+            "random pattern 11 for spp scheme"
+        ],
+        "213112": [
+            "spp12",
+            "random pattern 12 for spp scheme"
+        ],
+        "213113": [
+            "spp13",
+            "random pattern 13 for spp scheme"
+        ],
+        "213114": [
+            "spp14",
+            "random pattern 14 for spp scheme"
+        ],
+        "213115": [
+            "spp15",
+            "random pattern 15 for spp scheme"
+        ],
+        "213116": [
+            "spp16",
+            "random pattern 16 for spp scheme"
+        ],
+        "213117": [
+            "spp17",
+            "random pattern 17 for spp scheme"
+        ],
+        "213118": [
+            "spp18",
+            "random pattern 18 for spp scheme"
+        ],
+        "213119": [
+            "spp19",
+            "random pattern 19 for spp scheme"
+        ],
+        "213120": [
+            "spp20",
+            "random pattern 20 for spp scheme"
+        ],
+        "213121": [
+            "spp21",
+            "random pattern 21 for spp scheme"
+        ],
+        "213122": [
+            "spp22",
+            "random pattern 22 for spp scheme"
+        ],
+        "213123": [
+            "spp23",
+            "random pattern 23 for spp scheme"
+        ],
+        "213124": [
+            "spp24",
+            "random pattern 24 for spp scheme"
+        ],
+        "213125": [
+            "spp25",
+            "random pattern 25 for spp scheme"
+        ],
+        "213126": [
+            "spp26",
+            "random pattern 26 for spp scheme"
+        ],
+        "213127": [
+            "spp27",
+            "random pattern 27 for spp scheme"
+        ],
+        "213128": [
+            "spp28",
+            "random pattern 28 for spp scheme"
+        ],
+        "213129": [
+            "spp29",
+            "random pattern 29 for spp scheme"
+        ],
+        "213130": [
+            "spp30",
+            "random pattern 30 for spp scheme"
+        ],
+        "213131": [
+            "spp31",
+            "random pattern 31 for spp scheme"
+        ],
+        "213132": [
+            "spp32",
+            "random pattern 32 for spp scheme"
+        ],
+        "213133": [
+            "spp33",
+            "random pattern 33 for spp scheme"
+        ],
+        "213134": [
+            "spp34",
+            "random pattern 34 for spp scheme"
+        ],
+        "213135": [
+            "spp35",
+            "random pattern 35 for spp scheme"
+        ],
+        "213136": [
+            "spp36",
+            "random pattern 36 for spp scheme"
+        ],
+        "213137": [
+            "spp37",
+            "random pattern 37 for spp scheme"
+        ],
+        "213138": [
+            "spp38",
+            "random pattern 38 for spp scheme"
+        ],
+        "213139": [
+            "spp39",
+            "random pattern 39 for spp scheme"
+        ],
+        "213140": [
+            "spp40",
+            "random pattern 40 for spp scheme"
+        ],
+        "213141": [
+            "spp41",
+            "random pattern 41 for spp scheme"
+        ],
+        "213142": [
+            "spp42",
+            "random pattern 42 for spp scheme"
+        ],
+        "213143": [
+            "spp43",
+            "random pattern 43 for spp scheme"
+        ],
+        "213144": [
+            "spp44",
+            "random pattern 44 for spp scheme"
+        ],
+        "213145": [
+            "spp45",
+            "random pattern 45 for spp scheme"
+        ],
+        "213146": [
+            "spp46",
+            "random pattern 46 for spp scheme"
+        ],
+        "213147": [
+            "spp47",
+            "random pattern 47 for spp scheme"
+        ],
+        "213148": [
+            "spp48",
+            "random pattern 48 for spp scheme"
+        ],
+        "213149": [
+            "spp49",
+            "random pattern 49 for spp scheme"
+        ],
+        "213150": [
+            "spp50",
+            "random pattern 50 for spp scheme"
+        ],
+        "214": [
+            "dhr",
+            "diabatic heating by radiation"
+        ],
+        "214001": [
+            "uvcossza",
+            "cosine of solar zenith angle"
+        ],
+        "214002": [
+            "uvbed",
+            "uv biologically effective dose"
+        ],
+        "214003": [
+            "uvbedcs",
+            "uv biologically effective dose clear-sky"
+        ],
+        "214004": [
+            "uvsflxt280285",
+            "total surface uv spectral flux (280-285 nm)"
+        ],
+        "214005": [
+            "uvsflxt285290",
+            "total surface uv spectral flux (285-290 nm)"
+        ],
+        "214006": [
+            "uvsflxt290295",
+            "total surface uv spectral flux (290-295 nm)"
+        ],
+        "214007": [
+            "uvsflxt295300",
+            "total surface uv spectral flux (295-300 nm)"
+        ],
+        "214008": [
+            "uvsflxt300305",
+            "total surface uv spectral flux (300-305 nm)"
+        ],
+        "214009": [
+            "uvsflxt305310",
+            "total surface uv spectral flux (305-310 nm)"
+        ],
+        "214010": [
+            "uvsflxt310315",
+            "total surface uv spectral flux (310-315 nm)"
+        ],
+        "214011": [
+            "uvsflxt315320",
+            "total surface uv spectral flux (315-320 nm)"
+        ],
+        "214012": [
+            "uvsflxt320325",
+            "total surface uv spectral flux (320-325 nm)"
+        ],
+        "214013": [
+            "uvsflxt325330",
+            "total surface uv spectral flux (325-330 nm)"
+        ],
+        "214014": [
+            "uvsflxt330335",
+            "total surface uv spectral flux (330-335 nm)"
+        ],
+        "214015": [
+            "uvsflxt335340",
+            "total surface uv spectral flux (335-340 nm)"
+        ],
+        "214016": [
+            "uvsflxt340345",
+            "total surface uv spectral flux (340-345 nm)"
+        ],
+        "214017": [
+            "uvsflxt345350",
+            "total surface uv spectral flux (345-350 nm)"
+        ],
+        "214018": [
+            "uvsflxt350355",
+            "total surface uv spectral flux (350-355 nm)"
+        ],
+        "214019": [
+            "uvsflxt355360",
+            "total surface uv spectral flux (355-360 nm)"
+        ],
+        "214020": [
+            "uvsflxt360365",
+            "total surface uv spectral flux (360-365 nm)"
+        ],
+        "214021": [
+            "uvsflxt365370",
+            "total surface uv spectral flux (365-370 nm)"
+        ],
+        "214022": [
+            "uvsflxt370375",
+            "total surface uv spectral flux (370-375 nm)"
+        ],
+        "214023": [
+            "uvsflxt375380",
+            "total surface uv spectral flux (375-380 nm)"
+        ],
+        "214024": [
+            "uvsflxt380385",
+            "total surface uv spectral flux (380-385 nm)"
+        ],
+        "214025": [
+            "uvsflxt385390",
+            "total surface uv spectral flux (385-390 nm)"
+        ],
+        "214026": [
+            "uvsflxt390395",
+            "total surface uv spectral flux (390-395 nm)"
+        ],
+        "214027": [
+            "uvsflxt395400",
+            "total surface uv spectral flux (395-400 nm)"
+        ],
+        "214028": [
+            "uvsflxcs280285",
+            "clear-sky surface uv spectral flux (280-285 nm)"
+        ],
+        "214029": [
+            "uvsflxcs285290",
+            "clear-sky surface uv spectral flux (285-290 nm)"
+        ],
+        "214030": [
+            "uvsflxcs290295",
+            "clear-sky surface uv spectral flux (290-295 nm)"
+        ],
+        "214031": [
+            "uvsflxcs295300",
+            "clear-sky surface uv spectral flux (295-300 nm)"
+        ],
+        "214032": [
+            "uvsflxcs300305",
+            "clear-sky surface uv spectral flux (300-305 nm)"
+        ],
+        "214033": [
+            "uvsflxcs305310",
+            "clear-sky surface uv spectral flux (305-310 nm)"
+        ],
+        "214034": [
+            "uvsflxcs310315",
+            "clear-sky surface uv spectral flux (310-315 nm)"
+        ],
+        "214035": [
+            "uvsflxcs315320",
+            "clear-sky surface uv spectral flux (315-320 nm)"
+        ],
+        "214036": [
+            "uvsflxcs320325",
+            "clear-sky surface uv spectral flux (320-325 nm)"
+        ],
+        "214037": [
+            "uvsflxcs325330",
+            "clear-sky surface uv spectral flux (325-330 nm)"
+        ],
+        "214038": [
+            "uvsflxcs330335",
+            "clear-sky surface uv spectral flux (330-335 nm)"
+        ],
+        "214039": [
+            "uvsflxcs335340",
+            "clear-sky surface uv spectral flux (335-340 nm)"
+        ],
+        "214040": [
+            "uvsflxcs340345",
+            "clear-sky surface uv spectral flux (340-345 nm)"
+        ],
+        "214041": [
+            "uvsflxcs345350",
+            "clear-sky surface uv spectral flux (345-350 nm)"
+        ],
+        "214042": [
+            "uvsflxcs350355",
+            "clear-sky surface uv spectral flux (350-355 nm)"
+        ],
+        "214043": [
+            "uvsflxcs355360",
+            "clear-sky surface uv spectral flux (355-360 nm)"
+        ],
+        "214044": [
+            "uvsflxcs360365",
+            "clear-sky surface uv spectral flux (360-365 nm)"
+        ],
+        "214045": [
+            "uvsflxcs365370",
+            "clear-sky surface uv spectral flux (365-370 nm)"
+        ],
+        "214046": [
+            "uvsflxcs370375",
+            "clear-sky surface uv spectral flux (370-375 nm)"
+        ],
+        "214047": [
+            "uvsflxcs375380",
+            "clear-sky surface uv spectral flux (375-380 nm)"
+        ],
+        "214048": [
+            "uvsflxcs380385",
+            "clear-sky surface uv spectral flux (380-385 nm)"
+        ],
+        "214049": [
+            "uvsflxcs385390",
+            "clear-sky surface uv spectral flux (385-390 nm)"
+        ],
+        "214050": [
+            "uvsflxcs390395",
+            "clear-sky surface uv spectral flux (390-395 nm)"
+        ],
+        "214051": [
+            "uvsflxcs395400",
+            "clear-sky surface uv spectral flux (395-400 nm)"
+        ],
+        "214052": [
+            "aot340",
+            "profile of optical thickness at 340 nm"
+        ],
+        "215": [
+            "dhvd",
+            "diabatic heating by vertical diffusion"
+        ],
+        "215001": [
+            "aersrcsss",
+            "source/gain of sea salt aerosol (0.03 - 0.5 um)"
+        ],
+        "215002": [
+            "aersrcssm",
+            "source/gain of sea salt aerosol (0.5 - 5 um)"
+        ],
+        "215003": [
+            "aersrcssl",
+            "source/gain of sea salt aerosol (5 - 20 um)"
+        ],
+        "215004": [
+            "aerddpsss",
+            "dry deposition of sea salt aerosol (0.03 - 0.5 um)"
+        ],
+        "215005": [
+            "aerddpssm",
+            "dry deposition of sea salt aerosol (0.5 - 5 um)"
+        ],
+        "215006": [
+            "aerddpssl",
+            "dry deposition of sea salt aerosol (5 - 20 um)"
+        ],
+        "215007": [
+            "aersdmsss",
+            "sedimentation of sea salt aerosol (0.03 - 0.5 um)"
+        ],
+        "215008": [
+            "aersdmssm",
+            "sedimentation of sea salt aerosol (0.5 - 5 um)"
+        ],
+        "215009": [
+            "aersdmssl",
+            "sedimentation of sea salt aerosol (5 - 20 um)"
+        ],
+        "215010": [
+            "aerwdlssss",
+            "wet deposition of sea salt aerosol (0.03 - 0.5 um) by large-scale precipitation"
+        ],
+        "215011": [
+            "aerwdlsssm",
+            "wet deposition of sea salt aerosol (0.5 - 5 um) by large-scale precipitation"
+        ],
+        "215012": [
+            "aerwdlsssl",
+            "wet deposition of sea salt aerosol (5 - 20 um) by large-scale precipitation"
+        ],
+        "215013": [
+            "aerwdccsss",
+            "wet deposition of sea salt aerosol (0.03 - 0.5 um) by convective precipitation"
+        ],
+        "215014": [
+            "aerwdccssm",
+            "wet deposition of sea salt aerosol (0.5 - 5 um) by convective precipitation"
+        ],
+        "215015": [
+            "aerwdccssl",
+            "wet deposition of sea salt aerosol (5 - 20 um) by convective precipitation"
+        ],
+        "215016": [
+            "aerngtsss",
+            "negative fixer of sea salt aerosol (0.03 - 0.5 um)"
+        ],
+        "215017": [
+            "aerngtssm",
+            "negative fixer of sea salt aerosol (0.5 - 5 um)"
+        ],
+        "215018": [
+            "aerngtssl",
+            "negative fixer of sea salt aerosol (5 - 20 um)"
+        ],
+        "215019": [
+            "aermsssss",
+            "vertically integrated mass of sea salt aerosol (0.03 - 0.5 um)"
+        ],
+        "215020": [
+            "aermssssm",
+            "vertically integrated mass of sea salt aerosol (0.5 - 5 um)"
+        ],
+        "215021": [
+            "aermssssl",
+            "vertically integrated mass of sea salt aerosol (5 - 20 um)"
+        ],
+        "215022": [
+            "aerodsss",
+            "sea salt aerosol (0.03 - 0.5 um) optical depth"
+        ],
+        "215023": [
+            "aerodssm",
+            "sea salt aerosol (0.5 - 5 um) optical depth"
+        ],
+        "215024": [
+            "aerodssl",
+            "sea salt aerosol (5 - 20 um) optical depth"
+        ],
+        "215025": [
+            "aersrcdus",
+            "source/gain of dust aerosol (0.03 - 0.55 um)"
+        ],
+        "215026": [
+            "aersrcdum",
+            "source/gain of dust aerosol (0.55 - 9 um)"
+        ],
+        "215027": [
+            "aersrcdul",
+            "source/gain of dust aerosol (9 - 20 um)"
+        ],
+        "215028": [
+            "aerddpdus",
+            "dry deposition of dust aerosol (0.03 - 0.55 um)"
+        ],
+        "215029": [
+            "aerddpdum",
+            "dry deposition of dust aerosol (0.55 - 9 um)"
+        ],
+        "215030": [
+            "aerddpdul",
+            "dry deposition of dust aerosol (9 - 20 um)"
+        ],
+        "215031": [
+            "aersdmdus",
+            "sedimentation of dust aerosol (0.03 - 0.55 um)"
+        ],
+        "215032": [
+            "aersdmdum",
+            "sedimentation of dust aerosol (0.55 - 9 um)"
+        ],
+        "215033": [
+            "aersdmdul",
+            "sedimentation of dust aerosol (9 - 20 um)"
+        ],
+        "215034": [
+            "aerwdlsdus",
+            "wet deposition of dust aerosol (0.03 - 0.55 um) by large-scale precipitation"
+        ],
+        "215035": [
+            "aerwdlsdum",
+            "wet deposition of dust aerosol (0.55 - 9 um) by large-scale precipitation"
+        ],
+        "215036": [
+            "aerwdlsdul",
+            "wet deposition of dust aerosol (9 - 20 um) by large-scale precipitation"
+        ],
+        "215037": [
+            "aerwdccdus",
+            "wet deposition of dust aerosol (0.03 - 0.55 um) by convective precipitation"
+        ],
+        "215038": [
+            "aerwdccdum",
+            "wet deposition of dust aerosol (0.55 - 9 um) by convective precipitation"
+        ],
+        "215039": [
+            "aerwdccdul",
+            "wet deposition of dust aerosol (9 - 20 um) by convective precipitation"
+        ],
+        "215040": [
+            "aerngtdus",
+            "negative fixer of dust aerosol (0.03 - 0.55 um)"
+        ],
+        "215041": [
+            "aerngtdum",
+            "negative fixer of dust aerosol (0.55 - 9 um)"
+        ],
+        "215042": [
+            "aerngtdul",
+            "negative fixer of dust aerosol (9 - 20 um)"
+        ],
+        "215043": [
+            "aermssdus",
+            "vertically integrated mass of dust aerosol (0.03 - 0.55 um)"
+        ],
+        "215044": [
+            "aermssdum",
+            "vertically integrated mass of dust aerosol (0.55 - 9 um)"
+        ],
+        "215045": [
+            "aermssdul",
+            "vertically integrated mass of dust aerosol (9 - 20 um)"
+        ],
+        "215046": [
+            "aeroddus",
+            "dust aerosol (0.03 - 0.55 um) optical depth"
+        ],
+        "215047": [
+            "aeroddum",
+            "dust aerosol (0.55 - 9 um) optical depth"
+        ],
+        "215048": [
+            "aeroddul",
+            "dust aerosol (9 - 20 um) optical depth"
+        ],
+        "215049": [
+            "aersrcomhphob",
+            "source/gain of hydrophobic organic matter aerosol"
+        ],
+        "215050": [
+            "aersrcomhphil",
+            "source/gain of hydrophilic organic matter aerosol"
+        ],
+        "215051": [
+            "aerddpomhphob",
+            "dry deposition of hydrophobic organic matter aerosol"
+        ],
+        "215052": [
+            "aerddpomhphil",
+            "dry deposition of hydrophilic organic matter aerosol"
+        ],
+        "215053": [
+            "aersdmomhphob",
+            "sedimentation of hydrophobic organic matter aerosol"
+        ],
+        "215054": [
+            "aersdmomhphil",
+            "sedimentation of hydrophilic organic matter aerosol"
+        ],
+        "215055": [
+            "aerwdlsomhphob",
+            "wet deposition of hydrophobic organic matter aerosol by large-scale precipitation"
+        ],
+        "215056": [
+            "aerwdlsomhphil",
+            "wet deposition of hydrophilic organic matter aerosol by large-scale precipitation"
+        ],
+        "215057": [
+            "aerwdccomhphob",
+            "wet deposition of hydrophobic organic matter aerosol by convective precipitation"
+        ],
+        "215058": [
+            "aerwdccomhphil",
+            "wet deposition of hydrophilic organic matter aerosol by convective precipitation"
+        ],
+        "215059": [
+            "aerngtomhphob",
+            "negative fixer of hydrophobic organic matter aerosol"
+        ],
+        "215060": [
+            "aerngtomhphil",
+            "negative fixer of hydrophilic organic matter aerosol"
+        ],
+        "215061": [
+            "aermssomhphob",
+            "vertically integrated mass of hydrophobic organic matter aerosol"
+        ],
+        "215062": [
+            "aermssomhphil",
+            "vertically integrated mass of hydrophilic organic matter aerosol"
+        ],
+        "215063": [
+            "aerodomhphob",
+            "hydrophobic organic matter aerosol optical depth"
+        ],
+        "215064": [
+            "aerodomhphil",
+            "hydrophilic organic matter aerosol optical depth"
+        ],
+        "215065": [
+            "aersrcbchphob",
+            "source/gain of hydrophobic black carbon aerosol"
+        ],
+        "215066": [
+            "aersrcbchphil",
+            "source/gain of hydrophilic black carbon aerosol"
+        ],
+        "215067": [
+            "aerddpbchphob",
+            "dry deposition of hydrophobic black carbon aerosol"
+        ],
+        "215068": [
+            "aerddpbchphil",
+            "dry deposition of hydrophilic black carbon aerosol"
+        ],
+        "215069": [
+            "aersdmbchphob",
+            "sedimentation of hydrophobic black carbon aerosol"
+        ],
+        "215070": [
+            "aersdmbchphil",
+            "sedimentation of hydrophilic black carbon aerosol"
+        ],
+        "215071": [
+            "aerwdlsbchphob",
+            "wet deposition of hydrophobic black carbon aerosol by large-scale precipitation"
+        ],
+        "215072": [
+            "aerwdlsbchphil",
+            "wet deposition of hydrophilic black carbon aerosol by large-scale precipitation"
+        ],
+        "215073": [
+            "aerwdccbchphob",
+            "wet deposition of hydrophobic black carbon aerosol by convective precipitation"
+        ],
+        "215074": [
+            "aerwdccbchphil",
+            "wet deposition of hydrophilic black carbon aerosol by convective precipitation"
+        ],
+        "215075": [
+            "aerngtbchphob",
+            "negative fixer of hydrophobic black carbon aerosol"
+        ],
+        "215076": [
+            "aerngtbchphil",
+            "negative fixer of hydrophilic black carbon aerosol"
+        ],
+        "215077": [
+            "aermssbchphob",
+            "vertically integrated mass of hydrophobic black carbon aerosol"
+        ],
+        "215078": [
+            "aermssbchphil",
+            "vertically integrated mass of hydrophilic black carbon aerosol"
+        ],
+        "215079": [
+            "aerodbchphob",
+            "hydrophobic black carbon aerosol optical depth"
+        ],
+        "215080": [
+            "aerodbchphil",
+            "hydrophilic black carbon aerosol optical depth"
+        ],
+        "215081": [
+            "aersrcsu",
+            "source/gain of sulphate aerosol"
+        ],
+        "215082": [
+            "aerddpsu",
+            "dry deposition of sulphate aerosol"
+        ],
+        "215083": [
+            "aersdmsu",
+            "sedimentation of sulphate aerosol"
+        ],
+        "215084": [
+            "aerwdlssu",
+            "wet deposition of sulphate aerosol by large-scale precipitation"
+        ],
+        "215085": [
+            "aerwdccsu",
+            "wet deposition of sulphate aerosol by convective precipitation"
+        ],
+        "215086": [
+            "aerngtsu",
+            "negative fixer of sulphate aerosol"
+        ],
+        "215087": [
+            "aermsssu",
+            "vertically integrated mass of sulphate aerosol"
+        ],
+        "215088": [
+            "aerodsu",
+            "sulphate aerosol optical depth"
+        ],
+        "215089": [
+            "accaod550",
+            "accumulated total aerosol optical depth at 550 nm"
+        ],
+        "215090": [
+            "aluvpsn",
+            "effective (snow effect included) uv visible albedo for direct radiation"
+        ],
+        "215091": [
+            "aerdep10si",
+            "10 metre wind speed dust emission potential"
+        ],
+        "215092": [
+            "aerdep10fg",
+            "10 metre wind gustiness dust emission potential"
+        ],
+        "215093": [
+            "aot532",
+            "total aerosol optical thickness at 532 nm"
+        ],
+        "215094": [
+            "naot532",
+            "natural (sea-salt and dust) aerosol optical thickness at 532 nm"
+        ],
+        "215095": [
+            "aaot532",
+            "antropogenic (black carbon, organic matter, sulphate) aerosol optical thickness at 532 nm"
+        ],
+        "215096": [
+            "aodabs340",
+            "total absorption aerosol optical depth at 340 nm"
+        ],
+        "215097": [
+            "aodabs355",
+            "total absorption aerosol optical depth at 355 nm"
+        ],
+        "215098": [
+            "aodabs380",
+            "total absorption aerosol optical depth at 380 nm"
+        ],
+        "215099": [
+            "aodabs400",
+            "total absorption aerosol optical depth at 400 nm"
+        ],
+        "215100": [
+            "aodabs440",
+            "total absorption aerosol optical depth at 440 nm"
+        ],
+        "215101": [
+            "aodabs469",
+            "total absorption aerosol optical depth at 469 nm"
+        ],
+        "215102": [
+            "aodabs500",
+            "total absorption aerosol optical depth at 500 nm"
+        ],
+        "215103": [
+            "aodabs532",
+            "total absorption aerosol optical depth at 532 nm"
+        ],
+        "215104": [
+            "aodabs550",
+            "total absorption aerosol optical depth at 550 nm"
+        ],
+        "215105": [
+            "aodabs645",
+            "total absorption aerosol optical depth at 645 nm"
+        ],
+        "215106": [
+            "aodabs670",
+            "total absorption aerosol optical depth at 670 nm"
+        ],
+        "215107": [
+            "aodabs800",
+            "total absorption aerosol optical depth at 800 nm"
+        ],
+        "215108": [
+            "aodabs858",
+            "total absorption aerosol optical depth at 858 nm"
+        ],
+        "215109": [
+            "aodabs865",
+            "total absorption aerosol optical depth at 865 nm"
+        ],
+        "215110": [
+            "aodabs1020",
+            "total absorption aerosol optical depth at 1020 nm"
+        ],
+        "215111": [
+            "aodabs1064",
+            "total absorption aerosol optical depth at 1064 nm"
+        ],
+        "215112": [
+            "aodabs1240",
+            "total absorption aerosol optical depth at 1240 nm"
+        ],
+        "215113": [
+            "aodabs1640",
+            "total absorption aerosol optical depth at 1640 nm"
+        ],
+        "215114": [
+            "aodfm340",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 340 nm"
+        ],
+        "215115": [
+            "aodfm355",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 355 nm"
+        ],
+        "215116": [
+            "aodfm380",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 380 nm"
+        ],
+        "215117": [
+            "aodfm400",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 400 nm"
+        ],
+        "215118": [
+            "aodfm440",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 440 nm"
+        ],
+        "215119": [
+            "aodfm469",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 469 nm"
+        ],
+        "215120": [
+            "aodfm500",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 500 nm"
+        ],
+        "215121": [
+            "aodfm532",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 532 nm"
+        ],
+        "215122": [
+            "aodfm550",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 550 nm"
+        ],
+        "215123": [
+            "aodfm645",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 645 nm"
+        ],
+        "215124": [
+            "aodfm670",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 670 nm"
+        ],
+        "215125": [
+            "aodfm800",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 800 nm"
+        ],
+        "215126": [
+            "aodfm858",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 858 nm"
+        ],
+        "215127": [
+            "aodfm865",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 865 nm"
+        ],
+        "215128": [
+            "aodfm1020",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 1020 nm"
+        ],
+        "215129": [
+            "aodfm1064",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 1064 nm"
+        ],
+        "215130": [
+            "aodfm1240",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 1240 nm"
+        ],
+        "215131": [
+            "aodfm1640",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 1640 nm"
+        ],
+        "215132": [
+            "ssa340",
+            "single scattering albedo at 340 nm"
+        ],
+        "215133": [
+            "ssa355",
+            "single scattering albedo at 355 nm"
+        ],
+        "215134": [
+            "ssa380",
+            "single scattering albedo at 380 nm"
+        ],
+        "215135": [
+            "ssa400",
+            "single scattering albedo at 400 nm"
+        ],
+        "215136": [
+            "ssa440",
+            "single scattering albedo at 440 nm"
+        ],
+        "215137": [
+            "ssa469",
+            "single scattering albedo at 469 nm"
+        ],
+        "215138": [
+            "ssa500",
+            "single scattering albedo at 500 nm"
+        ],
+        "215139": [
+            "ssa532",
+            "single scattering albedo at 532 nm"
+        ],
+        "215140": [
+            "ssa550",
+            "single scattering albedo at 550 nm"
+        ],
+        "215141": [
+            "ssa645",
+            "single scattering albedo at 645 nm"
+        ],
+        "215142": [
+            "ssa670",
+            "single scattering albedo at 670 nm"
+        ],
+        "215143": [
+            "ssa800",
+            "single scattering albedo at 800 nm"
+        ],
+        "215144": [
+            "ssa858",
+            "single scattering albedo at 858 nm"
+        ],
+        "215145": [
+            "ssa865",
+            "single scattering albedo at 865 nm"
+        ],
+        "215146": [
+            "ssa1020",
+            "single scattering albedo at 1020 nm"
+        ],
+        "215147": [
+            "ssa1064",
+            "single scattering albedo at 1064 nm"
+        ],
+        "215148": [
+            "ssa1240",
+            "single scattering albedo at 1240 nm"
+        ],
+        "215149": [
+            "ssa1640",
+            "single scattering albedo at 1640 nm"
+        ],
+        "215150": [
+            "assimetry340",
+            "assimetry factor at 340 nm"
+        ],
+        "215151": [
+            "assimetry355",
+            "assimetry factor at 355 nm"
+        ],
+        "215152": [
+            "assimetry380",
+            "assimetry factor at 380 nm"
+        ],
+        "215153": [
+            "assimetry400",
+            "assimetry factor at 400 nm"
+        ],
+        "215154": [
+            "assimetry440",
+            "assimetry factor at 440 nm"
+        ],
+        "215155": [
+            "assimetry469",
+            "assimetry factor at 469 nm"
+        ],
+        "215156": [
+            "assimetry500",
+            "assimetry factor at 500 nm"
+        ],
+        "215157": [
+            "assimetry532",
+            "assimetry factor at 532 nm"
+        ],
+        "215158": [
+            "assimetry550",
+            "assimetry factor at 550 nm"
+        ],
+        "215159": [
+            "assimetry645",
+            "assimetry factor at 645 nm"
+        ],
+        "215160": [
+            "assimetry670",
+            "assimetry factor at 670 nm"
+        ],
+        "215161": [
+            "assimetry800",
+            "assimetry factor at 800 nm"
+        ],
+        "215162": [
+            "assimetry858",
+            "assimetry factor at 858 nm"
+        ],
+        "215163": [
+            "assimetry865",
+            "assimetry factor at 865 nm"
+        ],
+        "215164": [
+            "assimetry1020",
+            "assimetry factor at 1020 nm"
+        ],
+        "215165": [
+            "assimetry1064",
+            "assimetry factor at 1064 nm"
+        ],
+        "215166": [
+            "assimetry1240",
+            "assimetry factor at 1240 nm"
+        ],
+        "215167": [
+            "assimetry1640",
+            "assimetry factor at 1640 nm"
+        ],
+        "215168": [
+            "aersrcso2",
+            "source/gain of sulphur dioxide"
+        ],
+        "215169": [
+            "aerddpso2",
+            "dry deposition of sulphur dioxide"
+        ],
+        "215170": [
+            "aersdmso2",
+            "sedimentation of sulphur dioxide"
+        ],
+        "215171": [
+            "aerwdlsso2",
+            "wet deposition of sulphur dioxide by large-scale precipitation"
+        ],
+        "215172": [
+            "aerwdccso2",
+            "wet deposition of sulphur dioxide by convective precipitation"
+        ],
+        "215173": [
+            "aerngtso2",
+            "negative fixer of sulphur dioxide"
+        ],
+        "215174": [
+            "aermssso2",
+            "vertically integrated mass of sulphur dioxide"
+        ],
+        "215175": [
+            "aerodso2",
+            "sulphur dioxide optical depth"
+        ],
+        "215176": [
+            "aodabs2130",
+            "total absorption aerosol optical depth at 2130 nm"
+        ],
+        "215177": [
+            "aodfm2130",
+            "total fine mode (r < 0.5 um) aerosol optical depth at 2130 nm"
+        ],
+        "215178": [
+            "ssa2130",
+            "single scattering albedo at 2130 nm"
+        ],
+        "215179": [
+            "assimetry2130",
+            "assimetry factor at 2130 nm"
+        ],
+        "215180": [
+            "aerext355",
+            "aerosol extinction coefficient at 355 nm"
+        ],
+        "215181": [
+            "aerext532",
+            "aerosol extinction coefficient at 532 nm"
+        ],
+        "215182": [
+            "aerext1064",
+            "aerosol extinction coefficient at 1064 nm"
+        ],
+        "215183": [
+            "aerbackscattoa355",
+            "aerosol backscatter coefficient at 355 nm (from top of atmosphere)"
+        ],
+        "215184": [
+            "aerbackscattoa532",
+            "aerosol backscatter coefficient at 532 nm (from top of atmosphere)"
+        ],
+        "215185": [
+            "aerbackscattoa1064",
+            "aerosol backscatter coefficient at 1064 nm (from top of atmosphere)"
+        ],
+        "215186": [
+            "aerbackscatgnd355",
+            "aerosol backscatter coefficient at 355 nm (from ground)"
+        ],
+        "215187": [
+            "aerbackscatgnd532",
+            "aerosol backscatter coefficient at 532 nm (from ground)"
+        ],
+        "215188": [
+            "aerbackscatgnd1064",
+            "aerosol backscatter coefficient at 1064 nm (from ground)"
+        ],
+        "216": [
+            "dhcc",
+            "diabatic heating by cumulus convection"
+        ],
+        "217": [
+            "dhlc",
+            "diabatic heating large-scale condensation"
+        ],
+        "217003": [
+            "h2o2",
+            "hydrogen peroxide"
+        ],
+        "217004": [
+            "ch4",
+            "methane"
+        ],
+        "217006": [
+            "hno3",
+            "nitric acid"
+        ],
+        "217007": [
+            "ch3ooh",
+            "methyl peroxide"
+        ],
+        "217009": [
+            "par",
+            "paraffins"
+        ],
+        "217010": [
+            "c2h4",
+            "ethene"
+        ],
+        "217011": [
+            "ole",
+            "olefins"
+        ],
+        "217012": [
+            "ald2",
+            "aldehydes"
+        ],
+        "217013": [
+            "pan",
+            "peroxyacetyl nitrate"
+        ],
+        "217014": [
+            "rooh",
+            "peroxides"
+        ],
+        "217015": [
+            "onit",
+            "organic nitrates"
+        ],
+        "217016": [
+            "c5h8",
+            "isoprene"
+        ],
+        "217018": [
+            "dms",
+            "dimethyl sulfide"
+        ],
+        "217019": [
+            "nh3",
+            "ammonia"
+        ],
+        "217020": [
+            "so4",
+            "sulfate"
+        ],
+        "217021": [
+            "nh4",
+            "ammonium"
+        ],
+        "217022": [
+            "msa",
+            "methane sulfonic acid"
+        ],
+        "217023": [
+            "ch3cocho",
+            "methyl glyoxal"
+        ],
+        "217024": [
+            "o3s",
+            "stratospheric ozone"
+        ],
+        "217026": [
+            "pb",
+            "lead"
+        ],
+        "217027": [
+            "no",
+            "nitrogen monoxide"
+        ],
+        "217028": [
+            "ho2",
+            "hydroperoxy radical"
+        ],
+        "217029": [
+            "ch3o2",
+            "methylperoxy radical"
+        ],
+        "217030": [
+            "oh",
+            "hydroxyl radical"
+        ],
+        "217032": [
+            "no3",
+            "nitrate radical"
+        ],
+        "217033": [
+            "n2o5",
+            "dinitrogen pentoxide"
+        ],
+        "217034": [
+            "ho2no2",
+            "pernitric acid"
+        ],
+        "217035": [
+            "c2o3",
+            "peroxy acetyl radical"
+        ],
+        "217036": [
+            "ror",
+            "organic ethers"
+        ],
+        "217037": [
+            "rxpar",
+            "par budget corrector"
+        ],
+        "217038": [
+            "xo2",
+            "no to no2 operator"
+        ],
+        "217039": [
+            "xo2n",
+            "no to alkyl nitrate operator"
+        ],
+        "217040": [
+            "nh2",
+            "amine"
+        ],
+        "217041": [
+            "psc",
+            "polar stratospheric cloud"
+        ],
+        "217042": [
+            "ch3oh",
+            "methanol"
+        ],
+        "217043": [
+            "hcooh",
+            "formic acid"
+        ],
+        "217044": [
+            "mcooh",
+            "methacrylic acid"
+        ],
+        "217045": [
+            "c2h6",
+            "ethane"
+        ],
+        "217046": [
+            "c2h5oh",
+            "ethanol"
+        ],
+        "217047": [
+            "c3h8",
+            "propane"
+        ],
+        "217048": [
+            "c3h6",
+            "propene"
+        ],
+        "217049": [
+            "c10h16",
+            "terpenes"
+        ],
+        "217050": [
+            "ispd",
+            "methacrolein mvk"
+        ],
+        "217051": [
+            "no3_a",
+            "nitrate"
+        ],
+        "217052": [
+            "ch3coch3",
+            "acetone"
+        ],
+        "217053": [
+            "aco2",
+            "acetone product"
+        ],
+        "217054": [
+            "ic3h7o2",
+            "ic3h7o2"
+        ],
+        "217055": [
+            "hypropo2",
+            "hypropo2"
+        ],
+        "217056": [
+            "noxa",
+            "nitrogen oxides transp"
+        ],
+        "218": [
+            "vdzw",
+            "vertical diffusion of zonal wind"
+        ],
+        "218003": [
+            "tc_h2o2",
+            "total column hydrogen peroxide"
+        ],
+        "218004": [
+            "tc_ch4",
+            "total column methane"
+        ],
+        "218006": [
+            "tc_hno3",
+            "total column nitric acid"
+        ],
+        "218007": [
+            "tc_ch3ooh",
+            "total column methyl peroxide"
+        ],
+        "218009": [
+            "tc_par",
+            "total column paraffins"
+        ],
+        "218010": [
+            "tc_c2h4",
+            "total column ethene"
+        ],
+        "218011": [
+            "tc_ole",
+            "total column olefins"
+        ],
+        "218012": [
+            "tc_ald2",
+            "total column aldehydes"
+        ],
+        "218013": [
+            "tc_pan",
+            "total column  peroxyacetyl nitrate"
+        ],
+        "218014": [
+            "tc_rooh",
+            "total column peroxides"
+        ],
+        "218015": [
+            "tc_onit",
+            "total column organic nitrates"
+        ],
+        "218016": [
+            "tc_c5h8",
+            "total column  isoprene"
+        ],
+        "218018": [
+            "tc_dms",
+            "total column dimethyl sulfide"
+        ],
+        "218019": [
+            "tc_nh3",
+            "total column ammonia"
+        ],
+        "218020": [
+            "tc_so4",
+            "total column  sulfate"
+        ],
+        "218021": [
+            "tc_nh4",
+            "total column ammonium"
+        ],
+        "218022": [
+            "tc_msa",
+            "total column  methane sulfonic acid"
+        ],
+        "218023": [
+            "tc_ch3cocho",
+            "total column methyl glyoxal"
+        ],
+        "218024": [
+            "tc_o3s",
+            "total column stratospheric ozone"
+        ],
+        "218026": [
+            "tc_pb",
+            "total column  lead"
+        ],
+        "218027": [
+            "tc_no",
+            "total column nitrogen monoxide"
+        ],
+        "218028": [
+            "tc_ho2",
+            "total column hydroperoxy radical"
+        ],
+        "218029": [
+            "tc_ch3o2",
+            "total column methylperoxy radical"
+        ],
+        "218030": [
+            "tc_oh",
+            "total column hydroxyl radical"
+        ],
+        "218032": [
+            "tc_no3",
+            "total column nitrate radical"
+        ],
+        "218033": [
+            "tc_n2o5",
+            "total column dinitrogen pentoxide"
+        ],
+        "218034": [
+            "tc_ho2no2",
+            "total column pernitric acid"
+        ],
+        "218035": [
+            "tc_c2o3",
+            "total column peroxy acetyl radical"
+        ],
+        "218036": [
+            "tc_ror",
+            "total column  organic ethers"
+        ],
+        "218037": [
+            "tc_rxpar",
+            "total column par budget corrector"
+        ],
+        "218038": [
+            "tc_xo2",
+            "total column no to no2 operator"
+        ],
+        "218039": [
+            "tc_xo2n",
+            "total column no to alkyl nitrate operator"
+        ],
+        "218040": [
+            "tc_nh2",
+            "total column amine"
+        ],
+        "218041": [
+            "tc_psc",
+            "total column  polar stratospheric cloud"
+        ],
+        "218042": [
+            "tc_ch3oh",
+            "total column methanol"
+        ],
+        "218043": [
+            "tc_hcooh",
+            "total column formic acid"
+        ],
+        "218044": [
+            "tc_mcooh",
+            "total column  methacrylic acid"
+        ],
+        "218045": [
+            "tc_c2h6",
+            "total column  ethane"
+        ],
+        "218046": [
+            "tc_c2h5oh",
+            "total column ethanol"
+        ],
+        "218047": [
+            "tc_c3h8",
+            "total column propane"
+        ],
+        "218048": [
+            "tc_c3h6",
+            "total column propene"
+        ],
+        "218049": [
+            "tc_c10h16",
+            "total column terpenes"
+        ],
+        "218050": [
+            "tc_ispd",
+            "total column methacrolein mvk"
+        ],
+        "218051": [
+            "tc_no3_a",
+            "total column nitrate"
+        ],
+        "218052": [
+            "tc_ch3coch3",
+            "total column acetone"
+        ],
+        "218053": [
+            "tc_aco2",
+            "total column acetone product"
+        ],
+        "218054": [
+            "tc_ic3h7o2",
+            "total column ic3h7o2"
+        ],
+        "218055": [
+            "tc_hypropo2",
+            "total column hypropo2"
+        ],
+        "218056": [
+            "tc_noxa",
+            "total column nitrogen oxides transp"
+        ],
+        "219": [
+            "vdmw",
+            "vertical diffusion of meridional wind"
+        ],
+        "219001": [
+            "e_go3",
+            "ozone emissions"
+        ],
+        "219002": [
+            "e_nox",
+            "nitrogen oxides emissions"
+        ],
+        "219003": [
+            "e_h2o2",
+            "hydrogen peroxide emissions"
+        ],
+        "219004": [
+            "e_ch4",
+            "methane emissions"
+        ],
+        "219005": [
+            "e_co",
+            "carbon monoxide emissions"
+        ],
+        "219006": [
+            "e_hno3",
+            "nitric acid emissions"
+        ],
+        "219007": [
+            "e_ch3ooh",
+            "methyl peroxide emissions"
+        ],
+        "219008": [
+            "e_hcho",
+            "formaldehyde emissions"
+        ],
+        "219009": [
+            "e_par",
+            "paraffins emissions"
+        ],
+        "219010": [
+            "e_c2h4",
+            "ethene emissions"
+        ],
+        "219011": [
+            "e_ole",
+            "olefins emissions"
+        ],
+        "219012": [
+            "e_ald2",
+            "aldehydes emissions"
+        ],
+        "219013": [
+            "e_pan",
+            "peroxyacetyl nitrate emissions"
+        ],
+        "219014": [
+            "e_rooh",
+            "peroxides emissions"
+        ],
+        "219015": [
+            "e_onit",
+            "organic nitrates emissions"
+        ],
+        "219016": [
+            "e_c5h8",
+            "isoprene emissions"
+        ],
+        "219017": [
+            "e_so2",
+            "sulfur dioxide emissions"
+        ],
+        "219018": [
+            "e_dms",
+            "dimethyl sulfide emissions"
+        ],
+        "219019": [
+            "e_nh3",
+            "ammonia emissions"
+        ],
+        "219020": [
+            "e_so4",
+            "sulfate emissions"
+        ],
+        "219021": [
+            "e_nh4",
+            "ammonium emissions"
+        ],
+        "219022": [
+            "e_msa",
+            "methane sulfonic acid emissions"
+        ],
+        "219023": [
+            "e_ch3cocho",
+            "methyl glyoxal emissions"
+        ],
+        "219024": [
+            "e_o3s",
+            "stratospheric ozone emissions"
+        ],
+        "219025": [
+            "e_ra",
+            "radon emissions"
+        ],
+        "219026": [
+            "e_pb",
+            "lead emissions"
+        ],
+        "219027": [
+            "e_no",
+            "nitrogen monoxide emissions"
+        ],
+        "219028": [
+            "e_ho2",
+            "hydroperoxy radical emissions"
+        ],
+        "219029": [
+            "e_ch3o2",
+            "methylperoxy radical emissions"
+        ],
+        "219030": [
+            "e_oh",
+            "hydroxyl radical emissions"
+        ],
+        "219031": [
+            "e_no2",
+            "nitrogen dioxide emissions"
+        ],
+        "219032": [
+            "e_no3",
+            "nitrate radical emissions"
+        ],
+        "219033": [
+            "e_n2o5",
+            "dinitrogen pentoxide emissions"
+        ],
+        "219034": [
+            "e_ho2no2",
+            "pernitric acid emissions"
+        ],
+        "219035": [
+            "e_c2o3",
+            "peroxy acetyl radical emissions"
+        ],
+        "219036": [
+            "e_ror",
+            "organic ethers emissions"
+        ],
+        "219037": [
+            "e_rxpar",
+            "par budget corrector emissions"
+        ],
+        "219038": [
+            "e_xo2",
+            "no to no2 operator emissions"
+        ],
+        "219039": [
+            "e_xo2n",
+            "no to alkyl nitrate operator emissions"
+        ],
+        "219040": [
+            "e_nh2",
+            "amine emissions"
+        ],
+        "219041": [
+            "e_psc",
+            "polar stratospheric cloud emissions"
+        ],
+        "219042": [
+            "e_ch3oh",
+            "methanol emissions"
+        ],
+        "219043": [
+            "e_hcooh",
+            "formic acid emissions"
+        ],
+        "219044": [
+            "e_mcooh",
+            "methacrylic acid emissions"
+        ],
+        "219045": [
+            "e_c2h6",
+            "ethane emissions"
+        ],
+        "219046": [
+            "e_c2h5oh",
+            "ethanol emissions"
+        ],
+        "219047": [
+            "e_c3h8",
+            "propane emissions"
+        ],
+        "219048": [
+            "e_c3h6",
+            "propene emissions"
+        ],
+        "219049": [
+            "e_c10h16",
+            "terpenes emissions"
+        ],
+        "219050": [
+            "e_ispd",
+            "methacrolein mvk  emissions"
+        ],
+        "219051": [
+            "e_no3_a",
+            "nitrate emissions"
+        ],
+        "219052": [
+            "e_ch3coch3",
+            "acetone emissions"
+        ],
+        "219053": [
+            "e_aco2",
+            "acetone product emissions"
+        ],
+        "219054": [
+            "e_ic3h7o2",
+            "ic3h7o2 emissions"
+        ],
+        "219055": [
+            "e_hypropo2",
+            "hypropo2 emissions"
+        ],
+        "219056": [
+            "e_noxa",
+            "nitrogen oxides transp emissions"
+        ],
+        "22": [
+            "ucln",
+            "unbalanced component of logarithm of surface pressure"
+        ],
+        "220": [
+            "ewgd",
+            "east-west gravity wave drag tendency"
+        ],
+        "220228": [
+            "tpoc",
+            "total precipitation observation count"
+        ],
+        "221": [
+            "nsgd",
+            "north-south gravity wave drag tendency"
+        ],
+        "221001": [
+            "dv_go3",
+            "ozone deposition velocity"
+        ],
+        "221002": [
+            "dv_nox",
+            "nitrogen oxides deposition velocity"
+        ],
+        "221003": [
+            "dv_h2o2",
+            "hydrogen peroxide deposition velocity"
+        ],
+        "221004": [
+            "dv_ch4",
+            "methane deposition velocity"
+        ],
+        "221005": [
+            "dv_co",
+            "carbon monoxide deposition velocity"
+        ],
+        "221006": [
+            "dv_hno3",
+            "nitric acid deposition velocity"
+        ],
+        "221007": [
+            "dv_ch3ooh",
+            "methyl peroxide deposition velocity"
+        ],
+        "221008": [
+            "dv_hcho",
+            "formaldehyde deposition velocity"
+        ],
+        "221009": [
+            "dv_par",
+            "paraffins deposition velocity"
+        ],
+        "221010": [
+            "dv_c2h4",
+            "ethene deposition velocity"
+        ],
+        "221011": [
+            "dv_ole",
+            "olefins deposition velocity"
+        ],
+        "221012": [
+            "dv_ald2",
+            "aldehydes deposition velocity"
+        ],
+        "221013": [
+            "dv_pan",
+            "peroxyacetyl nitrate deposition velocity"
+        ],
+        "221014": [
+            "dv_rooh",
+            "peroxides deposition velocity"
+        ],
+        "221015": [
+            "dv_onit",
+            "organic nitrates deposition velocity"
+        ],
+        "221016": [
+            "dv_c5h8",
+            "isoprene deposition velocity"
+        ],
+        "221017": [
+            "dv_so2",
+            "sulfur dioxide deposition velocity"
+        ],
+        "221018": [
+            "dv_dms",
+            "dimethyl sulfide deposition velocity"
+        ],
+        "221019": [
+            "dv_nh3",
+            "ammonia deposition velocity"
+        ],
+        "221020": [
+            "dv_so4",
+            "sulfate deposition velocity"
+        ],
+        "221021": [
+            "dv_nh4",
+            "ammonium deposition velocity"
+        ],
+        "221022": [
+            "dv_msa",
+            "methane sulfonic acid deposition velocity"
+        ],
+        "221023": [
+            "dv_ch3cocho",
+            "methyl glyoxal deposition velocity"
+        ],
+        "221024": [
+            "dv_o3s",
+            "stratospheric ozone deposition velocity"
+        ],
+        "221025": [
+            "dv_ra",
+            "radon deposition velocity"
+        ],
+        "221026": [
+            "dv_pb",
+            "lead deposition velocity"
+        ],
+        "221027": [
+            "dv_no",
+            "nitrogen monoxide deposition velocity"
+        ],
+        "221028": [
+            "dv_ho2",
+            "hydroperoxy radical deposition velocity"
+        ],
+        "221029": [
+            "dv_ch3o2",
+            "methylperoxy radical deposition velocity"
+        ],
+        "221030": [
+            "dv_oh",
+            "hydroxyl radical deposition velocity"
+        ],
+        "221031": [
+            "dv_no2",
+            "nitrogen dioxide deposition velocity"
+        ],
+        "221032": [
+            "dv_no3",
+            "nitrate radical deposition velocity"
+        ],
+        "221033": [
+            "dv_n2o5",
+            "dinitrogen pentoxide deposition velocity"
+        ],
+        "221034": [
+            "dv_ho2no2",
+            "pernitric acid deposition velocity"
+        ],
+        "221035": [
+            "dv_c2o3",
+            "peroxy acetyl radical deposition velocity"
+        ],
+        "221036": [
+            "dv_ror",
+            "organic ethers deposition velocity"
+        ],
+        "221037": [
+            "dv_rxpar",
+            "par budget corrector deposition velocity"
+        ],
+        "221038": [
+            "dv_xo2",
+            "no to no2 operator deposition velocity"
+        ],
+        "221039": [
+            "dv_xo2n",
+            "no to alkyl nitrate operator deposition velocity"
+        ],
+        "221040": [
+            "dv_nh2",
+            "amine deposition velocity"
+        ],
+        "221041": [
+            "dv_psc",
+            "polar stratospheric cloud deposition velocity"
+        ],
+        "221042": [
+            "dv_ch3oh",
+            "methanol deposition velocity"
+        ],
+        "221043": [
+            "dv_hcooh",
+            "formic acid deposition velocity"
+        ],
+        "221044": [
+            "dv_mcooh",
+            "methacrylic acid deposition velocity"
+        ],
+        "221045": [
+            "dv_c2h6",
+            "ethane deposition velocity"
+        ],
+        "221046": [
+            "dv_c2h5oh",
+            "ethanol deposition velocity"
+        ],
+        "221047": [
+            "dv_c3h8",
+            "propane deposition velocity"
+        ],
+        "221048": [
+            "dv_c3h6",
+            "propene deposition velocity"
+        ],
+        "221049": [
+            "dv_c10h16",
+            "terpenes deposition velocity"
+        ],
+        "221050": [
+            "dv_ispd",
+            "methacrolein mvk  deposition velocity"
+        ],
+        "221051": [
+            "dv_no3_a",
+            "nitrate deposition velocity"
+        ],
+        "221052": [
+            "dv_ch3coch3",
+            "acetone deposition velocity"
+        ],
+        "221053": [
+            "dv_aco2",
+            "acetone product deposition velocity"
+        ],
+        "221054": [
+            "dv_ic3h7o2",
+            "ic3h7o2 deposition velocity"
+        ],
+        "221055": [
+            "dv_hypropo2",
+            "hypropo2 deposition velocity"
+        ],
+        "221056": [
+            "dv_noxa",
+            "nitrogen oxides transp deposition velocity"
+        ],
+        "222": [
+            "ctzw",
+            "convective tendency of zonal wind"
+        ],
+        "223": [
+            "ctmw",
+            "convective tendency of meridional wind"
+        ],
+        "224": [
+            "vdh",
+            "vertical diffusion of humidity"
+        ],
+        "225": [
+            "htcc",
+            "humidity tendency by cumulus convection"
+        ],
+        "226": [
+            "htlc",
+            "humidity tendency by large-scale condensation"
+        ],
+        "227": [
+            "crnh",
+            "tendency due to removal of negative humidity"
+        ],
+        "228": [
+            "tp",
+            "total precipitation"
+        ],
+        "228001": [
+            "cin",
+            "convective inhibition"
+        ],
+        "228002": [
+            "orog",
+            "orography"
+        ],
+        "228003": [
+            "zust",
+            "friction velocity"
+        ],
+        "228004": [
+            "mean2t",
+            "mean temperature at 2 metres"
+        ],
+        "228005": [
+            "mean10ws",
+            "mean of 10 metre wind speed"
+        ],
+        "228006": [
+            "meantcc",
+            "mean total cloud cover"
+        ],
+        "228007": [
+            "dl",
+            "lake depth"
+        ],
+        "228008": [
+            "lmlt",
+            "lake mix-layer temperature"
+        ],
+        "228009": [
+            "lmld",
+            "lake mix-layer depth"
+        ],
+        "228010": [
+            "lblt",
+            "lake bottom temperature"
+        ],
+        "228011": [
+            "ltlt",
+            "lake total layer temperature"
+        ],
+        "228012": [
+            "lshf",
+            "lake shape factor"
+        ],
+        "228013": [
+            "lict",
+            "lake ice temperature"
+        ],
+        "228014": [
+            "licd",
+            "lake ice depth"
+        ],
+        "228015": [
+            "dndzn",
+            "minimum vertical gradient of refractivity inside trapping layer"
+        ],
+        "228016": [
+            "dndza",
+            "mean vertical gradient of refractivity inside trapping layer"
+        ],
+        "228017": [
+            "dctb",
+            "duct base height"
+        ],
+        "228018": [
+            "tplb",
+            "trapping layer base height"
+        ],
+        "228019": [
+            "tplt",
+            "trapping layer top height"
+        ],
+        "228021": [
+            "fdir",
+            "total sky direct solar radiation at surface"
+        ],
+        "228022": [
+            "cdir",
+            "clear-sky direct solar radiation at surface"
+        ],
+        "228023": [
+            "cbh",
+            "cloud base height"
+        ],
+        "228024": [
+            "deg0l",
+            "zero degree level"
+        ],
+        "228025": [
+            "hvis",
+            "horizontal visibility"
+        ],
+        "228026": [
+            "mx2t3",
+            "maximum temperature at 2 metres in the last 3 hours"
+        ],
+        "228027": [
+            "mn2t3",
+            "minimum temperature at 2 metres in the last 3 hours"
+        ],
+        "228028": [
+            "10fg3",
+            "10 metre wind gust in the last 3 hours",
+            "I10FG3"
+        ],
+        "228029": [
+            "i10fg",
+            "instantaneous 10 metre wind gust"
+        ],
+        "228030": [
+            "rhw",
+            "relative humidity with respect to water"
+        ],
+        "228031": [
+            "rhi",
+            "relative humidity with respect to ice"
+        ],
+        "228032": [
+            "asn",
+            "snow albedo"
+        ],
+        "228033": [
+            "fspc",
+            "fraction of stratiform precipitation cover"
+        ],
+        "228034": [
+            "fcpc",
+            "fraction of convective precipitation cover"
+        ],
+        "228039": [
+            "sm",
+            "soil moisture"
+        ],
+        "228040": [
+            "swi1",
+            "soil wetness index in layer 1"
+        ],
+        "228041": [
+            "swi2",
+            "soil wetness index in layer 2"
+        ],
+        "228042": [
+            "swi3",
+            "soil wetness index in layer 3"
+        ],
+        "228043": [
+            "swi4",
+            "soil wetness index in layer 4"
+        ],
+        "228044": [
+            "capes",
+            "convective available potential energy shear"
+        ],
+        "228046": [
+            "hcct",
+            "height of convective cloud top"
+        ],
+        "228047": [
+            "hwbt0",
+            "height of zero deg wet bulb temperature"
+        ],
+        "228048": [
+            "hwbt1",
+            "height of one deg wet bulb temperature"
+        ],
+        "228050": [
+            "litoti",
+            "instantaneous total lightning density"
+        ],
+        "228051": [
+            "litota",
+            "averaged total lightning density"
+        ],
+        "228052": [
+            "licgi",
+            "instantaneous cloud-to-ground lightning density"
+        ],
+        "228053": [
+            "licga",
+            "averaged cloud-to-ground lightning density"
+        ],
+        "228054": [
+            "ucq",
+            "unbalanced component of specific humidity"
+        ],
+        "228055": [
+            "ucclwc",
+            "unbalanced component of specific cloud liquid water content"
+        ],
+        "228056": [
+            "ucciwc",
+            "unbalanced component of specific cloud ice water content"
+        ],
+        "228078": [
+            "gppbfas",
+            "gpp coefficient from biogenic flux adjustment system"
+        ],
+        "228079": [
+            "recbfas",
+            "rec coefficient from biogenic flux adjustment system"
+        ],
+        "228080": [
+            "aco2nee",
+            "accumulated carbon dioxide net ecosystem exchange"
+        ],
+        "228081": [
+            "aco2gpp",
+            "accumulated carbon dioxide gross primary production"
+        ],
+        "228082": [
+            "aco2rec",
+            "accumulated carbon dioxide ecosystem respiration"
+        ],
+        "228083": [
+            "fco2nee",
+            "flux of carbon dioxide net ecosystem exchange"
+        ],
+        "228084": [
+            "fco2gpp",
+            "flux of carbon dioxide gross primary production"
+        ],
+        "228085": [
+            "fco2rec",
+            "flux of carbon dioxide ecosystem respiration"
+        ],
+        "228086": [
+            "sm20",
+            "soil moisture top 20 cm"
+        ],
+        "228087": [
+            "sm100",
+            "soil moisture top 100 cm"
+        ],
+        "228088": [
+            "tcslw",
+            "total column supercooled liquid water"
+        ],
+        "228089": [
+            "tcrw",
+            "total column rain water"
+        ],
+        "228090": [
+            "tcsw",
+            "total column snow water"
+        ],
+        "228091": [
+            "ccf",
+            "canopy cover fraction"
+        ],
+        "228092": [
+            "stf",
+            "soil texture fraction"
+        ],
+        "228093": [
+            "swv",
+            "volumetric soil moisture"
+        ],
+        "228094": [
+            "ist",
+            "ice temperature"
+        ],
+        "228095": [
+            "st20",
+            "soil temperature top 20 cm"
+        ],
+        "228096": [
+            "st100",
+            "soil temperature top 100 cm"
+        ],
+        "228129": [
+            "ssrdc",
+            "surface solar radiation downward clear-sky"
+        ],
+        "228130": [
+            "strdc",
+            "surface thermal radiation downward clear-sky"
+        ],
+        "228131": [
+            "u10n",
+            "neutral wind at 10 m u-component"
+        ],
+        "228132": [
+            "v10n",
+            "neutral wind at 10 m v-component"
+        ],
+        "228134": [
+            "vtnowd",
+            "v-tendency from non-orographic wave drag"
+        ],
+        "228136": [
+            "utnowd",
+            "u-tendency from non-orographic wave drag"
+        ],
+        "228139": [
+            "st",
+            "soil temperature"
+        ],
+        "228141": [
+            "sd",
+            "snow depth water equivalent"
+        ],
+        "228143": [
+            "cp",
+            "convective precipitation"
+        ],
+        "228144": [
+            "sf",
+            "snow fall water equivalent"
+        ],
+        "228164": [
+            "tcc",
+            "total cloud cover"
+        ],
+        "228170": [
+            "cap",
+            "field capacity"
+        ],
+        "228171": [
+            "wilt",
+            "wilting point"
+        ],
+        "228205": [
+            "ro",
+            "water runoff and drainage"
+        ],
+        "228216": [
+            "fzra",
+            "accumulated freezing rain"
+        ],
+        "228217": [
+            "ilspf",
+            "instantaneous large-scale surface precipitation fraction"
+        ],
+        "228218": [
+            "crr",
+            "convective rain rate"
+        ],
+        "228219": [
+            "lsrr",
+            "large scale rain rate"
+        ],
+        "228220": [
+            "csfr",
+            "convective snowfall rate water equivalent"
+        ],
+        "228221": [
+            "lssfr",
+            "large scale snowfall rate water equivalent"
+        ],
+        "228222": [
+            "mxtpr3",
+            "maximum total precipitation rate in the last 3 hours"
+        ],
+        "228223": [
+            "mntpr3",
+            "minimum total precipitation rate in the last 3 hours"
+        ],
+        "228224": [
+            "mxtpr6",
+            "maximum total precipitation rate in the last 6 hours"
+        ],
+        "228225": [
+            "mntpr6",
+            "minimum total precipitation rate in the last 6 hours"
+        ],
+        "228226": [
+            "mxtpr",
+            "maximum total precipitation rate since previous post-processing"
+        ],
+        "228227": [
+            "mntpr",
+            "minimum total precipitation rate since previous post-processing"
+        ],
+        "228228": [
+            "tp",
+            "total precipitation"
+        ],
+        "228229": [
+            "smos_tb_cdfa",
+            "smos first brightness temperature bias correction parameter"
+        ],
+        "228230": [
+            "smos_tb_cdfb",
+            "smos second brightness temperature bias correction parameter"
+        ],
+        "228242": [
+            "fdif",
+            "surface solar radiation diffuse total sky"
+        ],
+        "228243": [
+            "cdif",
+            "surface solar radiation diffuse clear-sky"
+        ],
+        "228244": [
+            "aldr",
+            "surface albedo of direct radiation"
+        ],
+        "228245": [
+            "aldf",
+            "surface albedo of diffuse radiation"
+        ],
+        "228246": [
+            "100u",
+            "100 metre u wind component"
+        ],
+        "228247": [
+            "100v",
+            "100 metre v wind component"
+        ],
+        "228248": [
+            "tccsw",
+            "surface short wave-effective total cloudiness"
+        ],
+        "228249": [
+            "100si",
+            "100 metre wind speed"
+        ],
+        "228250": [
+            "irrfr",
+            "irrigation fraction"
+        ],
+        "228251": [
+            "pev",
+            "potential evaporation"
+        ],
+        "228252": [
+            "irr",
+            "irrigation"
+        ],
+        "228253": [
+            "ascat_sm_cdfa",
+            "ascat first soil moisture cdf matching parameter"
+        ],
+        "228254": [
+            "ascat_sm_cdfb",
+            "ascat second soil moisture cdf matching parameter"
+        ],
+        "228255": [
+            "tcclw",
+            "surface long wave-effective total cloudiness"
+        ],
+        "229": [
+            "iews",
+            "instantaneous eastward turbulent surface stress"
+        ],
+        "23": [
+            "ucdv",
+            "unbalanced component of divergence"
+        ],
+        "230": [
+            "inss",
+            "instantaneous northward turbulent surface stress"
+        ],
+        "230008": [
+            "srovar",
+            "surface runoff (variable resolution)"
+        ],
+        "230009": [
+            "ssrovar",
+            "sub-surface runoff (variable resolution)"
+        ],
+        "230020": [
+            "parcsvar",
+            "clear sky surface photosynthetically active radiation (variable resolution)"
+        ],
+        "230021": [
+            "fdirvar",
+            "total sky direct solar radiation at surface (variable resolution)"
+        ],
+        "230022": [
+            "cdirvar",
+            "clear-sky direct solar radiation at surface (variable resolution)"
+        ],
+        "230044": [
+            "esvar",
+            "snow evaporation (variable resolution)"
+        ],
+        "230045": [
+            "smltvar",
+            "snowmelt (variable resolution)"
+        ],
+        "230046": [
+            "sdurvar",
+            "solar duration (variable resolution)"
+        ],
+        "230047": [
+            "dsrpvar",
+            "direct solar radiation (variable resolution)"
+        ],
+        "230050": [
+            "lspfvar",
+            "large-scale precipitation fraction (variable resolution)"
+        ],
+        "230057": [
+            "uvbvar",
+            "downward uv radiation at the surface (variable resolution)"
+        ],
+        "230058": [
+            "parvar",
+            "photosynthetically active radiation at the surface (variable resolution)"
+        ],
+        "230080": [
+            "aco2neevar",
+            "accumulated carbon dioxide net ecosystem exchange (variable resolution)"
+        ],
+        "230081": [
+            "aco2gppvar",
+            "accumulated carbon dioxide gross primary production (variable resolution)"
+        ],
+        "230082": [
+            "aco2recvar",
+            "accumulated carbon dioxide ecosystem respiration (variable resolution)"
+        ],
+        "230129": [
+            "ssrdcvar",
+            "surface solar radiation downward clear-sky (variable resolution)"
+        ],
+        "230130": [
+            "strdcvar",
+            "surface thermal radiation downward clear-sky (variable resolution)"
+        ],
+        "230142": [
+            "lspvar",
+            "stratiform precipitation (large-scale precipitation) (variable resolution)"
+        ],
+        "230143": [
+            "cpvar",
+            "convective precipitation (variable resolution)"
+        ],
+        "230144": [
+            "sfvar",
+            "snowfall (convective + stratiform) (variable resolution)"
+        ],
+        "230145": [
+            "bldvar",
+            "boundary layer dissipation (variable resolution)"
+        ],
+        "230146": [
+            "sshfvar",
+            "surface sensible heat flux (variable resolution)"
+        ],
+        "230147": [
+            "slhfvar",
+            "surface latent heat flux (variable resolution)"
+        ],
+        "230169": [
+            "ssrdvar",
+            "surface solar radiation downwards (variable resolution)"
+        ],
+        "230174": [
+            "alvar",
+            "albedo (variable resolution)"
+        ],
+        "230175": [
+            "strdvar",
+            "surface thermal radiation downwards (variable resolution)"
+        ],
+        "230176": [
+            "ssrvar",
+            "surface net solar radiation (variable resolution)"
+        ],
+        "230177": [
+            "strvar",
+            "surface net thermal radiation (variable resolution)"
+        ],
+        "230178": [
+            "tsrvar",
+            "top net solar radiation (variable resolution)"
+        ],
+        "230179": [
+            "ttrvar",
+            "top net thermal radiation (variable resolution)"
+        ],
+        "230180": [
+            "ewssvar",
+            "east-west surface stress (variable resolution)"
+        ],
+        "230181": [
+            "nsssvar",
+            "north-south surface stress (variable resolution)"
+        ],
+        "230182": [
+            "evar",
+            "evaporation (variable resolution)"
+        ],
+        "230189": [
+            "sundvar",
+            "sunshine duration (variable resolution)"
+        ],
+        "230195": [
+            "lgwsvar",
+            "longitudinal component of gravity wave stress (variable resolution)"
+        ],
+        "230196": [
+            "mgwsvar",
+            "meridional component of gravity wave stress (variable resolution)"
+        ],
+        "230197": [
+            "gwdvar",
+            "gravity wave dissipation (variable resolution)"
+        ],
+        "230198": [
+            "srcvar",
+            "skin reservoir content (variable resolution)"
+        ],
+        "230205": [
+            "rovar",
+            "runoff (variable resolution)"
+        ],
+        "230208": [
+            "tsrcvar",
+            "top net solar radiation, clear sky (variable resolution)"
+        ],
+        "230209": [
+            "ttrcvar",
+            "top net thermal radiation, clear sky (variable resolution)"
+        ],
+        "230210": [
+            "ssrcvar",
+            "surface net solar radiation, clear sky (variable resolution)"
+        ],
+        "230211": [
+            "strcvar",
+            "surface net thermal radiation, clear sky (variable resolution)"
+        ],
+        "230212": [
+            "tisrvar",
+            "toa incident solar radiation (variable resolution)"
+        ],
+        "230213": [
+            "vimdvar",
+            "vertically integrated moisture divergence (variable resolution)"
+        ],
+        "230216": [
+            "fzravar",
+            "accumulated freezing rain (variable resolution)"
+        ],
+        "230228": [
+            "tpvar",
+            "total precipitation (variable resolution)"
+        ],
+        "230239": [
+            "csfvar",
+            "convective snowfall (variable resolution)"
+        ],
+        "230240": [
+            "lsfvar",
+            "large-scale snowfall (variable resolution)"
+        ],
+        "230251": [
+            "pevvar",
+            "potential evaporation (variable resolution)"
+        ],
+        "231": [
+            "ishf",
+            "instantaneous surface sensible heat flux"
+        ],
+        "232": [
+            "ie",
+            "instantaneous moisture flux"
+        ],
+        "233": [
+            "asq",
+            "apparent surface humidity"
+        ],
+        "234": [
+            "lsrh",
+            "logarithm of surface roughness length for heat"
+        ],
+        "234139": [
+            "sts",
+            "surface temperature significance"
+        ],
+        "234151": [
+            "msls",
+            "mean sea level pressure significance"
+        ],
+        "234167": [
+            "2ts",
+            "2 metre temperature significance"
+        ],
+        "234228": [
+            "tps",
+            "total precipitation significance"
+        ],
+        "235": [
+            "skt",
+            "skin temperature"
+        ],
+        "235001": [
+            "mttswr",
+            "mean temperature tendency due to short-wave radiation"
+        ],
+        "235002": [
+            "mttlwr",
+            "mean temperature tendency due to long-wave radiation"
+        ],
+        "235003": [
+            "mttswrcs",
+            "mean temperature tendency due to short-wave radiation, clear sky"
+        ],
+        "235004": [
+            "mttlwrcs",
+            "mean temperature tendency due to long-wave radiation, clear sky"
+        ],
+        "235005": [
+            "mttpm",
+            "mean temperature tendency due to parametrisations"
+        ],
+        "235006": [
+            "mqtpm",
+            "mean specific humidity tendency due to parametrisations"
+        ],
+        "235007": [
+            "mutpm",
+            "mean eastward wind tendency due to parametrisations"
+        ],
+        "235008": [
+            "mvtpm",
+            "mean northward wind tendency due to parametrisations"
+        ],
+        "235009": [
+            "mumf",
+            "mean updraught mass flux"
+        ],
+        "235010": [
+            "mdmf",
+            "mean downdraught mass flux"
+        ],
+        "235011": [
+            "mudr",
+            "mean updraught detrainment rate"
+        ],
+        "235012": [
+            "mddr",
+            "mean downdraught detrainment rate"
+        ],
+        "235013": [
+            "mtpf",
+            "mean total precipitation flux"
+        ],
+        "235014": [
+            "mtdch",
+            "mean turbulent diffusion coefficient for heat"
+        ],
+        "235020": [
+            "msror",
+            "mean surface runoff rate"
+        ],
+        "235021": [
+            "mssror",
+            "mean sub-surface runoff rate"
+        ],
+        "235022": [
+            "msparfcs",
+            "mean surface photosynthetically active radiation flux, clear sky"
+        ],
+        "235023": [
+            "mser",
+            "mean snow evaporation rate"
+        ],
+        "235024": [
+            "msmr",
+            "mean snowmelt rate"
+        ],
+        "235025": [
+            "mmtss",
+            "mean magnitude of turbulent surface stress"
+        ],
+        "235026": [
+            "mlspf",
+            "mean large-scale precipitation fraction"
+        ],
+        "235027": [
+            "msdwuvrf",
+            "mean surface downward uv radiation flux"
+        ],
+        "235028": [
+            "msparf",
+            "mean surface photosynthetically active radiation flux"
+        ],
+        "235029": [
+            "mlspr",
+            "mean large-scale precipitation rate"
+        ],
+        "235030": [
+            "mcpr",
+            "mean convective precipitation rate"
+        ],
+        "235031": [
+            "msr",
+            "mean snowfall rate"
+        ],
+        "235032": [
+            "mbld",
+            "mean boundary layer dissipation"
+        ],
+        "235033": [
+            "msshf",
+            "mean surface sensible heat flux"
+        ],
+        "235034": [
+            "mslhf",
+            "mean surface latent heat flux"
+        ],
+        "235035": [
+            "msdwswrf",
+            "mean surface downward short-wave radiation flux"
+        ],
+        "235036": [
+            "msdwlwrf",
+            "mean surface downward long-wave radiation flux"
+        ],
+        "235037": [
+            "msnswrf",
+            "mean surface net short-wave radiation flux"
+        ],
+        "235038": [
+            "msnlwrf",
+            "mean surface net long-wave radiation flux"
+        ],
+        "235039": [
+            "mtnswrf",
+            "mean top net short-wave radiation flux"
+        ],
+        "235040": [
+            "mtnlwrf",
+            "mean top net long-wave radiation flux"
+        ],
+        "235041": [
+            "metss",
+            "mean eastward turbulent surface stress"
+        ],
+        "235042": [
+            "mntss",
+            "mean northward turbulent surface stress"
+        ],
+        "235043": [
+            "mer",
+            "mean evaporation rate"
+        ],
+        "235044": [
+            "sdf",
+            "sunshine duration fraction"
+        ],
+        "235045": [
+            "megwss",
+            "mean eastward gravity wave surface stress"
+        ],
+        "235046": [
+            "mngwss",
+            "mean northward gravity wave surface stress"
+        ],
+        "235047": [
+            "mgwd",
+            "mean gravity wave dissipation"
+        ],
+        "235048": [
+            "mror",
+            "mean runoff rate"
+        ],
+        "235049": [
+            "mtnswrfcs",
+            "mean top net short-wave radiation flux, clear sky"
+        ],
+        "235050": [
+            "mtnlwrfcs",
+            "mean top net long-wave radiation flux, clear sky"
+        ],
+        "235051": [
+            "msnswrfcs",
+            "mean surface net short-wave radiation flux, clear sky"
+        ],
+        "235052": [
+            "msnlwrfcs",
+            "mean surface net long-wave radiation flux, clear sky"
+        ],
+        "235053": [
+            "mtdwswrf",
+            "mean top downward short-wave radiation flux"
+        ],
+        "235054": [
+            "mvimd",
+            "mean vertically integrated moisture divergence"
+        ],
+        "235055": [
+            "mtpr",
+            "mean total precipitation rate"
+        ],
+        "235056": [
+            "mcsr",
+            "mean convective snowfall rate"
+        ],
+        "235057": [
+            "mlssr",
+            "mean large-scale snowfall rate"
+        ],
+        "235058": [
+            "msdrswrf",
+            "mean surface direct short-wave radiation flux"
+        ],
+        "235059": [
+            "msdrswrfcs",
+            "mean surface direct short-wave radiation flux, clear sky"
+        ],
+        "235060": [
+            "msdfswrf",
+            "mean surface diffuse short-wave radiation flux"
+        ],
+        "235061": [
+            "msdfswrfcs",
+            "mean surface diffuse short-wave radiation flux, clear sky"
+        ],
+        "235062": [
+            "mcdneef",
+            "mean carbon dioxide net ecosystem exchange flux"
+        ],
+        "235063": [
+            "mcdgppf",
+            "mean carbon dioxide gross primary production flux"
+        ],
+        "235064": [
+            "mcderf",
+            "mean carbon dioxide ecosystem respiration flux"
+        ],
+        "235065": [
+            "mrr",
+            "mean rain rate"
+        ],
+        "235066": [
+            "mcrr",
+            "mean convective rain rate"
+        ],
+        "235067": [
+            "mlsrr",
+            "mean large-scale rain rate"
+        ],
+        "235068": [
+            "msdwswrfcs",
+            "mean surface downward short-wave radiation flux, clear sky"
+        ],
+        "235069": [
+            "msdwlwrfcs",
+            "mean surface downward long-wave radiation flux, clear sky"
+        ],
+        "235070": [
+            "mper",
+            "mean potential evaporation rate"
+        ],
+        "236": [
+            "stl4",
+            "soil temperature level 4"
+        ],
+        "237": [
+            "swl4",
+            "soil wetness level 4"
+        ],
+        "238": [
+            "tsn",
+            "temperature of snow layer"
+        ],
+        "239": [
+            "csf",
+            "convective snowfall"
+        ],
+        "240": [
+            "lsf",
+            "large-scale snowfall"
+        ],
+        "240011": [
+            "chcross",
+            "cross sectional area of flow in channel"
+        ],
+        "240012": [
+            "chside",
+            "side flow into river channel"
+        ],
+        "240013": [
+            "dis",
+            "discharge from rivers or streams"
+        ],
+        "240014": [
+            "rivsto",
+            "river storage of water"
+        ],
+        "240015": [
+            "fldsto",
+            "floodplain storage of water"
+        ],
+        "240016": [
+            "fldfrc",
+            "water fraction"
+        ],
+        "240017": [
+            "dslr",
+            "days since last observation"
+        ],
+        "240018": [
+            "frost",
+            "frost index"
+        ],
+        "240020": [
+            "woss",
+            "depth of water on soil surface"
+        ],
+        "240021": [
+            "tpups",
+            "upstream accumulated precipitation"
+        ],
+        "240022": [
+            "smups",
+            "upstream accumulated snow melt"
+        ],
+        "240026": [
+            "sd_elev",
+            "snow depth at elevation bands"
+        ],
+        "240028": [
+            "gwus",
+            "groundwater upper storage"
+        ],
+        "240029": [
+            "gwls",
+            "groundwater lower storage"
+        ],
+        "241": [
+            "acf",
+            "accumulated cloud fraction tendency"
+        ],
+        "242": [
+            "alw",
+            "accumulated liquid water tendency"
+        ],
+        "243": [
+            "fal",
+            "forecast albedo"
+        ],
+        "244": [
+            "fsr",
+            "forecast surface roughness"
+        ],
+        "245": [
+            "flsr",
+            "forecast logarithm of surface roughness for heat"
+        ],
+        "246": [
+            "clwc",
+            "specific cloud liquid water content"
+        ],
+        "247": [
+            "ciwc",
+            "specific cloud ice water content"
+        ],
+        "248": [
+            "cc",
+            "fraction of cloud cover"
+        ],
+        "249": [
+            "aiw",
+            "accumulated ice water tendency"
+        ],
+        "250": [
+            "ice",
+            "ice age"
+        ],
+        "251": [
+            "atte",
+            "adiabatic tendency of temperature"
+        ],
+        "252": [
+            "athe",
+            "adiabatic tendency of humidity"
+        ],
+        "253": [
+            "atze",
+            "adiabatic tendency of zonal wind"
+        ],
+        "254": [
+            "atmw",
+            "adiabatic tendency of meridional wind"
+        ],
+        "26": [
+            "cl",
+            "lake cover"
+        ],
+        "260002": [
+            "lhtfl",
+            "latent heat net flux"
+        ],
+        "260003": [
+            "shtfl",
+            "sensible heat net flux"
+        ],
+        "260004": [
+            "heatx",
+            "heat index"
+        ],
+        "260005": [
+            "wcf",
+            "wind chill factor"
+        ],
+        "260006": [
+            "mindpd",
+            "minimum dew point depression"
+        ],
+        "260007": [
+            "snohf",
+            "snow phase change heat flux"
+        ],
+        "260008": [
+            "vapp",
+            "vapor pressure"
+        ],
+        "260009": [
+            "ncpcp",
+            "large scale precipitation (non-convective)"
+        ],
+        "260010": [
+            "srweq",
+            "snowfall rate water equivalent"
+        ],
+        "260011": [
+            "snoc",
+            "convective snow"
+        ],
+        "260012": [
+            "snol",
+            "large scale snow"
+        ],
+        "260013": [
+            "snoag",
+            "snow age"
+        ],
+        "260014": [
+            "absh",
+            "absolute humidity"
+        ],
+        "260015": [
+            "ptype",
+            "precipitation type"
+        ],
+        "260016": [
+            "iliqw",
+            "integrated liquid water"
+        ],
+        "260017": [
+            "tcond",
+            "condensate"
+        ],
+        "260018": [
+            "clwmr",
+            "cloud mixing ratio"
+        ],
+        "260019": [
+            "icmr",
+            "ice water mixing ratio"
+        ],
+        "260020": [
+            "rwmr",
+            "rain mixing ratio"
+        ],
+        "260021": [
+            "snmr",
+            "snow mixing ratio"
+        ],
+        "260022": [
+            "mconv",
+            "horizontal moisture convergence"
+        ],
+        "260023": [
+            "maxrh",
+            "maximum relative humidity"
+        ],
+        "260024": [
+            "maxah",
+            "maximum absolute humidity"
+        ],
+        "260025": [
+            "asnow",
+            "total snowfall"
+        ],
+        "260026": [
+            "pwcat",
+            "precipitable water category"
+        ],
+        "260027": [
+            "hail",
+            "hail"
+        ],
+        "260028": [
+            "grle",
+            "graupel (snow pellets)"
+        ],
+        "260029": [
+            "crain",
+            "categorical rain"
+        ],
+        "260030": [
+            "cfrzr",
+            "categorical freezing rain"
+        ],
+        "260031": [
+            "cicep",
+            "categorical ice pellets"
+        ],
+        "260032": [
+            "csnow",
+            "categorical snow"
+        ],
+        "260033": [
+            "cprat",
+            "convective precipitation rate"
+        ],
+        "260034": [
+            "mdiv",
+            "horizontal moisture divergence"
+        ],
+        "260035": [
+            "cpofp",
+            "percent frozen precipitation"
+        ],
+        "260036": [
+            "pevap",
+            "potential evaporation"
+        ],
+        "260037": [
+            "pevpr",
+            "potential evaporation rate"
+        ],
+        "260038": [
+            "snowc",
+            "snow cover"
+        ],
+        "260039": [
+            "frain",
+            "rain fraction of total cloud water"
+        ],
+        "260040": [
+            "rime",
+            "rime factor"
+        ],
+        "260041": [
+            "tcolr",
+            "total column integrated rain"
+        ],
+        "260042": [
+            "tcols",
+            "total column integrated snow"
+        ],
+        "260043": [
+            "lswp",
+            "large scale water precipitation (non-convective)"
+        ],
+        "260044": [
+            "cwp",
+            "convective water precipitation"
+        ],
+        "260045": [
+            "twatp",
+            "total water precipitation"
+        ],
+        "260046": [
+            "tsnowp",
+            "total snow precipitation"
+        ],
+        "260047": [
+            "tcwat",
+            "total column water (vertically integrated total water (vapour + cloud water/ice))"
+        ],
+        "260048": [
+            "tprate",
+            "total precipitation rate"
+        ],
+        "260049": [
+            "tsrwe",
+            "total snowfall rate water equivalent"
+        ],
+        "260050": [
+            "lsprate",
+            "large scale precipitation rate"
+        ],
+        "260051": [
+            "csrwe",
+            "convective snowfall rate water equivalent"
+        ],
+        "260052": [
+            "lssrwe",
+            "large scale snowfall rate water equivalent"
+        ],
+        "260053": [
+            "tsrate",
+            "total snowfall rate"
+        ],
+        "260054": [
+            "csrate",
+            "convective snowfall rate"
+        ],
+        "260055": [
+            "lssrate",
+            "large scale snowfall rate"
+        ],
+        "260056": [
+            "sdwe",
+            "water equivalent of accumulated snow depth"
+        ],
+        "260057": [
+            "tciwv",
+            "total column integrated water vapour"
+        ],
+        "260058": [
+            "rprate",
+            "rain precipitation rate"
+        ],
+        "260059": [
+            "sprate",
+            "snow precipitation rate"
+        ],
+        "260060": [
+            "fprate",
+            "freezing rain precipitation rate"
+        ],
+        "260061": [
+            "iprate",
+            "ice pellets precipitation rate"
+        ],
+        "260062": [
+            "uflx",
+            "momentum flux, u component"
+        ],
+        "260063": [
+            "vflx",
+            "momentum flux, v component"
+        ],
+        "260064": [
+            "maxgust",
+            "maximum wind speed"
+        ],
+        "260065": [
+            "gust",
+            "wind speed (gust)"
+        ],
+        "260066": [
+            "ugust",
+            "u-component of wind (gust)"
+        ],
+        "260067": [
+            "vgust",
+            "v-component of wind (gust)"
+        ],
+        "260068": [
+            "vwsh",
+            "vertical speed shear"
+        ],
+        "260069": [
+            "mflx",
+            "horizontal momentum flux"
+        ],
+        "260070": [
+            "ustm",
+            "u-component storm motion"
+        ],
+        "260071": [
+            "vstm",
+            "v-component storm motion"
+        ],
+        "260072": [
+            "cd",
+            "drag coefficient"
+        ],
+        "260073": [
+            "fricv",
+            "frictional velocity"
+        ],
+        "260074": [
+            "prmsl",
+            "pressure reduced to msl"
+        ],
+        "260075": [
+            "dist",
+            "geometric height"
+        ],
+        "260076": [
+            "alts",
+            "altimeter setting"
+        ],
+        "260077": [
+            "thick",
+            "thickness"
+        ],
+        "260078": [
+            "presalt",
+            "pressure altitude"
+        ],
+        "260079": [
+            "denalt",
+            "density altitude"
+        ],
+        "260080": [
+            "5wavh",
+            "5-wave geopotential height"
+        ],
+        "260081": [
+            "u-gwd",
+            "zonal flux of gravity wave stress"
+        ],
+        "260082": [
+            "v-gwd",
+            "meridional flux of gravity wave stress"
+        ],
+        "260083": [
+            "hpbl",
+            "planetary boundary layer height"
+        ],
+        "260084": [
+            "5wava",
+            "5-wave geopotential height anomaly"
+        ],
+        "260085": [
+            "sdsgso",
+            "standard deviation of sub-grid scale orography"
+        ],
+        "260086": [
+            "nswrt",
+            "net short-wave radiation flux (top of atmosphere)"
+        ],
+        "260087": [
+            "dswrf",
+            "downward short-wave radiation flux"
+        ],
+        "260088": [
+            "uswrf",
+            "upward short-wave radiation flux"
+        ],
+        "260089": [
+            "nswrf",
+            "net short wave radiation flux"
+        ],
+        "260090": [
+            "photar",
+            "photosynthetically active radiation"
+        ],
+        "260091": [
+            "nswrfcs",
+            "net short-wave radiation flux, clear sky"
+        ],
+        "260092": [
+            "dwuvr",
+            "downward uv radiation"
+        ],
+        "260093": [
+            "uviucs",
+            "uv index (under clear sky)"
+        ],
+        "260094": [
+            "uvi",
+            "uv index "
+        ],
+        "260095": [
+            "nlwrs",
+            "net long wave radiation flux (surface)"
+        ],
+        "260096": [
+            "nlwrt",
+            "net long wave radiation flux (top of atmosphere)"
+        ],
+        "260097": [
+            "dlwrf",
+            "downward long-wave radiation flux"
+        ],
+        "260098": [
+            "ulwrf",
+            "upward long-wave radiation flux"
+        ],
+        "260099": [
+            "nlwrf",
+            "net long wave radiation flux"
+        ],
+        "260100": [
+            "nlwrcs",
+            "net long-wave radiation flux, clear sky"
+        ],
+        "260101": [
+            "cice",
+            "cloud ice"
+        ],
+        "260102": [
+            "cwat",
+            "cloud water"
+        ],
+        "260103": [
+            "cdca",
+            "cloud amount"
+        ],
+        "260104": [
+            "cdct",
+            "cloud type"
+        ],
+        "260105": [
+            "tmaxt",
+            "thunderstorm maximum tops"
+        ],
+        "260106": [
+            "thunc",
+            "thunderstorm coverage"
+        ],
+        "260107": [
+            "cdcb",
+            "cloud base"
+        ],
+        "260108": [
+            "cdct",
+            "cloud top"
+        ],
+        "260109": [
+            "ceil",
+            "ceiling"
+        ],
+        "260110": [
+            "cdlyr",
+            "non-convective cloud cover"
+        ],
+        "260111": [
+            "cwork",
+            "cloud work function"
+        ],
+        "260112": [
+            "cuefi",
+            "convective cloud efficiency"
+        ],
+        "260113": [
+            "tcond",
+            "total condensate"
+        ],
+        "260114": [
+            "tcolw",
+            "total column-integrated cloud water"
+        ],
+        "260115": [
+            "tcoli",
+            "total column-integrated cloud ice"
+        ],
+        "260116": [
+            "tcolc",
+            "total column-integrated condensate"
+        ],
+        "260117": [
+            "fice",
+            "ice fraction of total condensate"
+        ],
+        "260118": [
+            "cdcimr",
+            "cloud ice mixing ratio"
+        ],
+        "260119": [
+            "suns",
+            "sunshine"
+        ],
+        "260120": [
+            "horizontal extent of cumulonimbus (cb)"
+        ],
+        "260121": [
+            "kx",
+            "k index"
+        ],
+        "260122": [
+            "kox",
+            "ko index"
+        ],
+        "260123": [
+            "totalx",
+            "total totals index"
+        ],
+        "260124": [
+            "sx",
+            "sweat index"
+        ],
+        "260125": [
+            "hlcy",
+            "storm relative helicity"
+        ],
+        "260126": [
+            "ehlx",
+            "energy helicity index"
+        ],
+        "260127": [
+            "lftx",
+            "surface lifted index"
+        ],
+        "260128": [
+            "4lftx",
+            "best (4-layer) lifted index"
+        ],
+        "260129": [
+            "aerot",
+            "aerosol type"
+        ],
+        "260130": [
+            "tozne",
+            "total ozone"
+        ],
+        "260131": [
+            "o3mr",
+            "ozone mixing ratio"
+        ],
+        "260132": [
+            "tcioz",
+            "total column integrated ozone"
+        ],
+        "260133": [
+            "bswid",
+            "base spectrum width"
+        ],
+        "260134": [
+            "bref",
+            "base reflectivity"
+        ],
+        "260135": [
+            "brvel",
+            "base radial velocity"
+        ],
+        "260136": [
+            "veril",
+            "vertically-integrated liquid"
+        ],
+        "260137": [
+            "lmaxbr",
+            "layer-maximum base reflectivity"
+        ],
+        "260138": [
+            "prec",
+            "precipitation"
+        ],
+        "260139": [
+            "acces",
+            "air concentration of caesium 137"
+        ],
+        "260140": [
+            "aciod",
+            "air concentration of iodine 131"
+        ],
+        "260141": [
+            "acradp",
+            "air concentration of radioactive pollutant"
+        ],
+        "260142": [
+            "gdces",
+            "ground deposition of caesium 137"
+        ],
+        "260143": [
+            "gdiod",
+            "ground deposition of iodine 131"
+        ],
+        "260144": [
+            "gdradp",
+            "ground deposition of radioactive pollutant"
+        ],
+        "260145": [
+            "tiaccp",
+            "time-integrated air concentration of caesium pollutant"
+        ],
+        "260146": [
+            "tiacip",
+            "time-integrated air concentration of iodine pollutant"
+        ],
+        "260147": [
+            "tiacrp",
+            "time-integrated air concentration of radioactive pollutant"
+        ],
+        "260148": [
+            "volash",
+            "volcanic ash"
+        ],
+        "260149": [
+            "icit",
+            "icing top"
+        ],
+        "260150": [
+            "icib",
+            "icing base"
+        ],
+        "260151": [
+            "ici",
+            "icing"
+        ],
+        "260152": [
+            "turbt",
+            "turbulence top"
+        ],
+        "260153": [
+            "turbb",
+            "turbulence base"
+        ],
+        "260154": [
+            "turb",
+            "turbulence"
+        ],
+        "260155": [
+            "tke",
+            "turbulent kinetic energy"
+        ],
+        "260156": [
+            "pblreg",
+            "planetary boundary layer regime"
+        ],
+        "260157": [
+            "conti",
+            "contrail intensity"
+        ],
+        "260158": [
+            "contet",
+            "contrail engine type"
+        ],
+        "260159": [
+            "contt",
+            "contrail top"
+        ],
+        "260160": [
+            "contb",
+            "contrail base"
+        ],
+        "260161": [
+            "mxsalb",
+            "maximum snow albedo"
+        ],
+        "260162": [
+            "snfalb",
+            "snow free albedo"
+        ],
+        "260163": [
+            "icing"
+        ],
+        "260164": [
+            "in-cloud turbulence"
+        ],
+        "260165": [
+            "cat",
+            "clear air turbulence (cat)"
+        ],
+        "260166": [
+            "supercooled large droplet probability (see note 4)"
+        ],
+        "260167": [
+            "var190m0",
+            "arbitrary text string"
+        ],
+        "260168": [
+            "tsec",
+            "seconds prior to initial reference time (defined in section 1)"
+        ],
+        "260169": [
+            "ffldg",
+            "flash flood guidance (encoded as an accumulation over a floating subinterval of time between the ref"
+        ],
+        "260170": [
+            "ffldro",
+            "flash flood runoff (encoded as an accumulation over a floating subinterval of time)"
+        ],
+        "260171": [
+            "rssc",
+            "remotely sensed snow cover"
+        ],
+        "260172": [
+            "esct",
+            "elevation of snow covered terrain"
+        ],
+        "260173": [
+            "swepon",
+            "snow water equivalent percent of normal"
+        ],
+        "260174": [
+            "bgrun",
+            "baseflow-groundwater runoff"
+        ],
+        "260175": [
+            "ssrun",
+            "storm surface runoff"
+        ],
+        "260176": [
+            "cppop",
+            "conditional percent precipitation amount fractile for an overall period (encoded as an accumulation)"
+        ],
+        "260177": [
+            "pposp",
+            "percent precipitation in a sub-period of an overall period (encoded as per cent accumulation over th"
+        ],
+        "260178": [
+            "pop",
+            "probability of 0.01 inch of precipitation (pop)"
+        ],
+        "260179": [
+            "land",
+            "land cover (1=land, 0=sea)"
+        ],
+        "260180": [
+            "veg",
+            "vegetation"
+        ],
+        "260181": [
+            "watr",
+            "water runoff"
+        ],
+        "260182": [
+            "evapt",
+            "evapotranspiration"
+        ],
+        "260183": [
+            "mterh",
+            "model terrain height"
+        ],
+        "260184": [
+            "landu",
+            "land use"
+        ],
+        "260185": [
+            "soilw",
+            "volumetric soil moisture content"
+        ],
+        "260186": [
+            "gflux",
+            "ground heat flux"
+        ],
+        "260187": [
+            "mstav",
+            "moisture availability"
+        ],
+        "260188": [
+            "sfexc",
+            "exchange coefficient"
+        ],
+        "260189": [
+            "cnwat",
+            "plant canopy surface water"
+        ],
+        "260190": [
+            "bmixl",
+            "blackadar mixing length scale"
+        ],
+        "260191": [
+            "ccond",
+            "canopy conductance"
+        ],
+        "260192": [
+            "rsmin",
+            "minimal stomatal resistance"
+        ],
+        "260193": [
+            "rcs",
+            "solar parameter in canopy conductance"
+        ],
+        "260194": [
+            "rct",
+            "temperature parameter in canopy conductance"
+        ],
+        "260195": [
+            "rcsol",
+            "soil moisture parameter in canopy conductance"
+        ],
+        "260196": [
+            "rcq",
+            "humidity parameter in canopy conductance"
+        ],
+        "260197": [
+            "cisoilw",
+            "column-integrated soil water"
+        ],
+        "260198": [
+            "hflux",
+            "heat flux"
+        ],
+        "260199": [
+            "vsw",
+            "volumetric soil moisture"
+        ],
+        "260200": [
+            "vwiltm",
+            "volumetric wilting point"
+        ],
+        "260201": [
+            "uplst",
+            "upper layer soil temperature"
+        ],
+        "260202": [
+            "uplsm",
+            "upper layer soil moisture"
+        ],
+        "260203": [
+            "lowlsm",
+            "lower layer soil moisture"
+        ],
+        "260204": [
+            "botlst",
+            "bottom layer soil temperature"
+        ],
+        "260205": [
+            "soill",
+            "liquid volumetric soil moisture (non-frozen)"
+        ],
+        "260206": [
+            "rlyrs",
+            "number of soil layers in root zone"
+        ],
+        "260207": [
+            "smref",
+            "transpiration stress-onset (soil moisture)"
+        ],
+        "260208": [
+            "smdry",
+            "direct evaporation cease (soil moisture)"
+        ],
+        "260209": [
+            "poros",
+            "soil porosity"
+        ],
+        "260210": [
+            "liqvsm",
+            "liquid volumetric soil moisture (non-frozen)"
+        ],
+        "260211": [
+            "voltso",
+            "volumetric transpiration stress-onset (soil moisture)"
+        ],
+        "260212": [
+            "transo",
+            "transpiration stress-onset (soil moisture)"
+        ],
+        "260213": [
+            "voldec",
+            "volumetric direct evaporation cease (soil moisture)"
+        ],
+        "260214": [
+            "direc",
+            "direct evaporation cease (soil moisture)"
+        ],
+        "260215": [
+            "soilp",
+            "soil porosity"
+        ],
+        "260216": [
+            "vsosm",
+            "volumetric saturation of soil moisture"
+        ],
+        "260217": [
+            "satosm",
+            "saturation of soil moisture"
+        ],
+        "260218": [
+            "estp",
+            "estimated precipitation"
+        ],
+        "260219": [
+            "irrate",
+            "instantaneous rain rate"
+        ],
+        "260220": [
+            "ctoph",
+            "cloud top height"
+        ],
+        "260221": [
+            "ctophqi",
+            "cloud top height quality indicator"
+        ],
+        "260222": [
+            "estu",
+            "estimated u component of wind "
+        ],
+        "260223": [
+            "estv",
+            "estimated v component of wind"
+        ],
+        "260224": [
+            "npixu",
+            "number of pixels used"
+        ],
+        "260225": [
+            "solza",
+            "solar zenith angle"
+        ],
+        "260226": [
+            "raza",
+            "relative azimuth angle"
+        ],
+        "260227": [
+            "rfl06",
+            "reflectance in 0.6 micron channel"
+        ],
+        "260228": [
+            "rfl08",
+            "reflectance in 0.8 micron channel"
+        ],
+        "260229": [
+            "rfl16",
+            "reflectance in 1.6 micron channel"
+        ],
+        "260230": [
+            "rfl39",
+            "reflectance in 3.9 micron channel"
+        ],
+        "260231": [
+            "atmdiv",
+            "atmospheric divergence"
+        ],
+        "260232": [
+            "wvdir",
+            "direction of wind waves"
+        ],
+        "260233": [
+            "dirpw",
+            "primary wave direction"
+        ],
+        "260234": [
+            "perpw",
+            "primary wave mean period"
+        ],
+        "260235": [
+            "persw",
+            "secondary wave mean period"
+        ],
+        "260236": [
+            "dirc",
+            "current direction"
+        ],
+        "260237": [
+            "spc",
+            "current speed"
+        ],
+        "260238": [
+            "wz",
+            "geometric vertical velocity"
+        ],
+        "260239": [
+            "ist",
+            "ice temperature"
+        ],
+        "260240": [
+            "dslm",
+            "deviation of sea level from mean"
+        ],
+        "260241": [
+            "tsec",
+            "seconds prior to initial reference time (defined in section 1)"
+        ],
+        "260242": [
+            "2r",
+            "surface air relative humidity"
+        ],
+        "260243": [
+            "ttrad",
+            "temperature tendency by all radiation"
+        ],
+        "260244": [
+            "rev",
+            "relative error variance"
+        ],
+        "260245": [
+            "lrghr",
+            "large scale condensate heating rate"
+        ],
+        "260246": [
+            "cnvhr",
+            "deep convective heating rate"
+        ],
+        "260247": [
+            "thflx",
+            "total downward heat flux at surface"
+        ],
+        "260248": [
+            "ttdia",
+            "temperature tendency by all physics"
+        ],
+        "260249": [
+            "ttphy",
+            "temperature tendency by non-radiation physics"
+        ],
+        "260250": [
+            "tsd1d",
+            "standard dev. of ir temp. over 1x1 deg. area"
+        ],
+        "260251": [
+            "shahr",
+            "shallow convective heating rate"
+        ],
+        "260252": [
+            "vdfhr",
+            "vertical diffusion heating rate"
+        ],
+        "260253": [
+            "thz0",
+            "potential temperature at top of viscous sublayer"
+        ],
+        "260254": [
+            "tchp",
+            "tropical cyclone heat potential"
+        ],
+        "260255": [
+            "aptmp",
+            "apparent temperature"
+        ],
+        "260256": [
+            "hindex",
+            "haines index"
+        ],
+        "260257": [
+            "ccl",
+            "cloud cover"
+        ],
+        "260258": [
+            "evarate",
+            "evaporation rate"
+        ],
+        "260259": [
+            "eva",
+            "evaporation"
+        ],
+        "260260": [
+            "10wdir",
+            "10 metre wind direction"
+        ],
+        "260261": [
+            "minrh",
+            "minimum relative humidity"
+        ],
+        "260262": [
+            "dirswrf",
+            "direct short wave radiation flux"
+        ],
+        "260263": [
+            "difswrf",
+            "diffuse short wave radiation flux"
+        ],
+        "260264": [
+            "tidirswrf",
+            "time-integrated surface direct short wave radiation flux"
+        ],
+        "260269": [
+            "tipd",
+            "total icing potential diagnostic"
+        ],
+        "260270": [
+            "ncip",
+            "number concentration for ice particles"
+        ],
+        "260271": [
+            "snot",
+            "snow temperature"
+        ],
+        "260272": [
+            "tclsw",
+            "total column-integrated supercooled liquid water"
+        ],
+        "260273": [
+            "tcolm",
+            "total column-integrated melting ice"
+        ],
+        "260274": [
+            "emnp",
+            "evaporation - precipitation"
+        ],
+        "260275": [
+            "sbsno",
+            "sublimation (evaporation from snow)"
+        ],
+        "260276": [
+            "cnvmr",
+            "deep convective moistening rate"
+        ],
+        "260277": [
+            "shamr",
+            "shallow convective moistening rate"
+        ],
+        "260278": [
+            "vdfmr",
+            "vertical diffusion moistening rate"
+        ],
+        "260279": [
+            "condp",
+            "condensation pressure of parcali lifted from indicate surface"
+        ],
+        "260280": [
+            "lrgmr",
+            "large scale moistening rate"
+        ],
+        "260281": [
+            "qz0",
+            "specific humidity at top of viscous sublayer"
+        ],
+        "260282": [
+            "qmax",
+            "maximum specific humidity at 2m"
+        ],
+        "260283": [
+            "qmin",
+            "minimum specific humidity at 2m"
+        ],
+        "260284": [
+            "arain",
+            "liquid precipitation (rainfall)"
+        ],
+        "260285": [
+            "snowt",
+            "snow temperature, depth-avg"
+        ],
+        "260286": [
+            "apcpn",
+            "total precipitation (nearest grid point)"
+        ],
+        "260287": [
+            "acpcpn",
+            "convective precipitation (nearest grid point)"
+        ],
+        "260288": [
+            "frzr",
+            "freezing rain"
+        ],
+        "260295": [
+            "lauv",
+            "latitude of u wind component of velocity"
+        ],
+        "260296": [
+            "louv",
+            "longitude of u wind component of velocity"
+        ],
+        "260297": [
+            "lavv",
+            "latitude of v wind component of velocity"
+        ],
+        "260298": [
+            "lovv",
+            "longitude of v wind component of velocity"
+        ],
+        "260299": [
+            "lapp",
+            "latitude of presure point"
+        ],
+        "260300": [
+            "lopp",
+            "longitude of presure point"
+        ],
+        "260301": [
+            "vedh",
+            "vertical eddy diffusivity heat exchange"
+        ],
+        "260302": [
+            "covmz",
+            "covariance between meridional and zonal components of the wind."
+        ],
+        "260303": [
+            "covtz",
+            "covariance between temperature and zonal components of the wind."
+        ],
+        "260304": [
+            "covtm",
+            "covariance between temperature and meridional components of the wind."
+        ],
+        "260305": [
+            "vdfua",
+            "vertical diffusion zonal acceleration"
+        ],
+        "260306": [
+            "vdfva",
+            "vertical diffusion meridional acceleration"
+        ],
+        "260307": [
+            "gwdu",
+            "gravity wave drag zonal acceleration"
+        ],
+        "260308": [
+            "gwdv",
+            "gravity wave drag meridional acceleration"
+        ],
+        "260309": [
+            "cnvu",
+            "convective zonal momentum mixing acceleration"
+        ],
+        "260310": [
+            "cnvv",
+            "convective meridional momentum mixing acceleration"
+        ],
+        "260311": [
+            "wtend",
+            "tendency of vertical velocity"
+        ],
+        "260312": [
+            "omgalf",
+            "omega (dp/dt) divide by density"
+        ],
+        "260313": [
+            "cngwdu",
+            "convective gravity wave drag zonal acceleration"
+        ],
+        "260314": [
+            "cngwdv",
+            "convective gravity wave drag meridional acceleration"
+        ],
+        "260315": [
+            "lmv",
+            "velocity point model surface"
+        ],
+        "260316": [
+            "pvmww",
+            "potential vorticity (mass-weighted)"
+        ],
+        "260317": [
+            "mslet",
+            "mslp (eta model reduction)"
+        ],
+        "260323": [
+            "mslma",
+            "mslp (maps system reduction)"
+        ],
+        "260324": [
+            "tslsa",
+            "3-hr pressure tendency (std. atmos. reduction)"
+        ],
+        "260325": [
+            "plpl",
+            "pressure of level from which parcel was lifted"
+        ],
+        "260326": [
+            "lpsx",
+            "x-gradient of log pressure"
+        ],
+        "260327": [
+            "lpsy",
+            "y-gradient of log pressure"
+        ],
+        "260328": [
+            "hgtx",
+            "x-gradient of height"
+        ],
+        "260329": [
+            "hgty",
+            "y-gradient of height"
+        ],
+        "260330": [
+            "layth",
+            "layer thickness"
+        ],
+        "260331": [
+            "nlgsp",
+            "natural log of surface pressure"
+        ],
+        "260332": [
+            "cnvumf",
+            "convective updraft mass flux"
+        ],
+        "260333": [
+            "cnvdmf",
+            "convective downdraft mass flux"
+        ],
+        "260334": [
+            "cnvdemf",
+            "convective detrainment mass flux"
+        ],
+        "260335": [
+            "lmh",
+            "mass point model surface"
+        ],
+        "260336": [
+            "hgtn",
+            "geopotential height (nearest grid point)"
+        ],
+        "260337": [
+            "presn",
+            "pressure (nearest grid point)"
+        ],
+        "260340": [
+            "duvb",
+            "uv-b downward solar flux"
+        ],
+        "260341": [
+            "cduvb",
+            "clear sky uv-b downward solar flux"
+        ],
+        "260342": [
+            "csdsf",
+            "clear sky downward solar flux"
+        ],
+        "260343": [
+            "swhr",
+            "solar radiative heating rate"
+        ],
+        "260344": [
+            "csusf",
+            "clear sky upward solar flux"
+        ],
+        "260345": [
+            "cfnsf",
+            "cloud forcing net solar flux"
+        ],
+        "260346": [
+            "vbdsf",
+            "visible beam downward solar flux"
+        ],
+        "260347": [
+            "vddsf",
+            "visible diffuse downward solar flux"
+        ],
+        "260348": [
+            "nbdsf",
+            "near ir beam downward solar flux"
+        ],
+        "260349": [
+            "nddsf",
+            "near ir diffuse downward solar flux"
+        ],
+        "260350": [
+            "dtrf",
+            "downward total radiation flux"
+        ],
+        "260351": [
+            "utrf",
+            "upward total radiation flux"
+        ],
+        "260354": [
+            "lwhr",
+            "long-wave radiative heating rate"
+        ],
+        "260355": [
+            "csulf",
+            "clear sky upward long wave flux"
+        ],
+        "260356": [
+            "csdlf",
+            "clear sky downward long wave flux"
+        ],
+        "260357": [
+            "cfnlf",
+            "cloud forcing net long wave flux"
+        ],
+        "260360": [
+            "sot",
+            "soil temperature"
+        ],
+        "260361": [
+            "dswrf_cs",
+            "downward short-wave radiation flux, clear sky"
+        ],
+        "260362": [
+            "uswrf_cs",
+            "upward short-wave radiation flux, clear sky"
+        ],
+        "260363": [
+            "dlwrf_cs",
+            "downward long-wave radiation flux, clear sky"
+        ],
+        "260364": [
+            "sohf",
+            "soil heat flux"
+        ],
+        "260365": [
+            "percr",
+            "percolation rate"
+        ],
+        "260366": [
+            "mflux",
+            "convective cloud mass flux"
+        ],
+        "260367": [
+            "sod",
+            "soil depth"
+        ],
+        "260369": [
+            "ri",
+            "richardson number"
+        ],
+        "260370": [
+            "cwdi",
+            "convective weather detection index"
+        ],
+        "260372": [
+            "uphl",
+            "updraft helicity"
+        ],
+        "260373": [
+            "lai",
+            "leaf area index"
+        ],
+        "260374": [
+            "pmtc",
+            "particulate matter (coarse)"
+        ],
+        "260375": [
+            "pmtf",
+            "particulate matter (fine)"
+        ],
+        "260376": [
+            "lpmtf",
+            "particulate matter (fine)"
+        ],
+        "260377": [
+            "lipmf",
+            "integrated column particulate matter (fine)"
+        ],
+        "260379": [
+            "ozcon",
+            "ozone concentration (ppb)"
+        ],
+        "260380": [
+            "ozcat",
+            "categorical ozone concentration"
+        ],
+        "260381": [
+            "vdfoz",
+            "ozone vertical diffusion"
+        ],
+        "260382": [
+            "poz",
+            "ozone production"
+        ],
+        "260383": [
+            "toz",
+            "ozone tendency"
+        ],
+        "260384": [
+            "pozt",
+            "ozone production from temperature term"
+        ],
+        "260385": [
+            "pozo",
+            "ozone production from col ozone term"
+        ],
+        "260386": [
+            "refzr",
+            "derived radar reflectivity backscatter from rain"
+        ],
+        "260387": [
+            "refzi",
+            "derived radar reflectivity backscatter from ice"
+        ],
+        "260388": [
+            "refzc",
+            "derived radar reflectivity backscatter from parameterized convection"
+        ],
+        "260389": [
+            "refd",
+            "derived radar reflectivity"
+        ],
+        "260390": [
+            "refc",
+            "maximum/composite radar reflectivity"
+        ],
+        "260391": [
+            "ltng",
+            "lightning"
+        ],
+        "260394": [
+            "srcono",
+            "slight risk convective outlook"
+        ],
+        "260395": [
+            "mrcono",
+            "moderate risk convective outlook"
+        ],
+        "260396": [
+            "hrcono",
+            "high risk convective outlook"
+        ],
+        "260397": [
+            "torprob",
+            "tornado probability"
+        ],
+        "260398": [
+            "hailprob",
+            "hail probability"
+        ],
+        "260399": [
+            "windprob",
+            "wind probability"
+        ],
+        "260400": [
+            "storprob",
+            "significant tornado probability"
+        ],
+        "260401": [
+            "shailpro",
+            "significant hail probability"
+        ],
+        "260402": [
+            "swindpro",
+            "significant wind probability"
+        ],
+        "260403": [
+            "tstmc",
+            "categorical thunderstorm (1-yes, 0-no)"
+        ],
+        "260404": [
+            "mixly",
+            "number of mixed layers next to surface"
+        ],
+        "260405": [
+            "flght",
+            "flight category"
+        ],
+        "260406": [
+            "cicel",
+            "confidence - ceiling"
+        ],
+        "260407": [
+            "civis",
+            "confidence - visibility"
+        ],
+        "260408": [
+            "ciflt",
+            "confidence - flight category"
+        ],
+        "260409": [
+            "lavni",
+            "low-level aviation interest"
+        ],
+        "260410": [
+            "havni",
+            "high-level aviation interest"
+        ],
+        "260411": [
+            "sbsalb",
+            "visible, black sky albedo"
+        ],
+        "260412": [
+            "swsalb",
+            "visible, white sky albedo"
+        ],
+        "260413": [
+            "nbsalb",
+            "near ir, black sky albedo"
+        ],
+        "260414": [
+            "nwsalb",
+            "near ir, white sky albedo"
+        ],
+        "260415": [
+            "prsvr",
+            "total probability of severe thunderstorms (days 2,3)"
+        ],
+        "260416": [
+            "prsigsvr",
+            "total probability of extreme severe thunderstorms (days 2,3)"
+        ],
+        "260417": [
+            "sipd",
+            "supercooled large droplet (sld) potential"
+        ],
+        "260418": [
+            "epsr",
+            "radiative emissivity"
+        ],
+        "260419": [
+            "tpfi",
+            "turbulence potential forecast index"
+        ],
+        "260420": [
+            "vaftd",
+            "volcanic ash forecast transport and dispersion"
+        ],
+        "260421": [
+            "nlat",
+            "latitude (-90 to +90)"
+        ],
+        "260422": [
+            "elon",
+            "east longitude (0 - 360)"
+        ],
+        "260423": [
+            "adswrf_cs",
+            "accumulated surface downward short-wave radiation flux, clear sky"
+        ],
+        "260424": [
+            "mlyno",
+            "model layer number (from bottom up)"
+        ],
+        "260425": [
+            "nlatn",
+            "latitude (nearest neighbor) (-90 to +90)"
+        ],
+        "260426": [
+            "elonn",
+            "east longitude (nearest neighbor) (0 - 360)"
+        ],
+        "260427": [
+            "auswrf_cs",
+            "accumulated surface upward short-wave radiation flux, clear sky"
+        ],
+        "260428": [
+            "adlwrf_cs",
+            "accumulated surface downward long-wave radiation flux, clear sky"
+        ],
+        "260429": [
+            "cpozp",
+            "probability of freezing precipitation"
+        ],
+        "260430": [
+            "perc",
+            "percolation"
+        ],
+        "260431": [
+            "ppffg",
+            "probability of precipitation exceeding flash flood guidance values"
+        ],
+        "260432": [
+            "cwr",
+            "probability of wetting rain, exceeding in 0.10 in a given time period"
+        ],
+        "260439": [
+            "vgtyp",
+            "vegetation type"
+        ],
+        "260442": [
+            "wilt",
+            "wilting point"
+        ],
+        "260447": [
+            "rdrip",
+            "rate of water dropping from canopy to ground"
+        ],
+        "260448": [
+            "icwat",
+            "ice-free water surface"
+        ],
+        "260449": [
+            "akhs",
+            "surface exchange coefficients for t and q divided by delta z"
+        ],
+        "260450": [
+            "akms",
+            "surface exchange coefficients for u and v divided by delta z"
+        ],
+        "260451": [
+            "vegt",
+            "vegetation canopy temperature"
+        ],
+        "260452": [
+            "sstor",
+            "surface water storage"
+        ],
+        "260453": [
+            "lsoil",
+            "liquid soil moisture content (non-frozen)"
+        ],
+        "260454": [
+            "ewatr",
+            "open water evaporation (standing water)"
+        ],
+        "260455": [
+            "gwrec",
+            "groundwater recharge"
+        ],
+        "260456": [
+            "qrec",
+            "flood plain recharge"
+        ],
+        "260457": [
+            "sfcrh",
+            "roughness length for heat"
+        ],
+        "260458": [
+            "ndvi",
+            "normalized difference vegetation index"
+        ],
+        "260459": [
+            "landn",
+            "land-sea coverage (nearest neighbor) [land=1,sea=0]"
+        ],
+        "260460": [
+            "amixl",
+            "asymptotic mixing length scale"
+        ],
+        "260461": [
+            "wvinc",
+            "water vapor added by precip assimilation"
+        ],
+        "260462": [
+            "wcinc",
+            "water condensate added by precip assimilation"
+        ],
+        "260463": [
+            "wvconv",
+            "water vapor flux convergance (vertical int)"
+        ],
+        "260464": [
+            "wcconv",
+            "water condensate flux convergance (vertical int)"
+        ],
+        "260465": [
+            "wvuflx",
+            "water vapor zonal flux (vertical int)"
+        ],
+        "260466": [
+            "wvvflx",
+            "water vapor meridional flux (vertical int)"
+        ],
+        "260467": [
+            "wcuflx",
+            "water condensate zonal flux (vertical int)"
+        ],
+        "260468": [
+            "wcvflx",
+            "water condensate meridional flux (vertical int)"
+        ],
+        "260469": [
+            "acond",
+            "aerodynamic conductance"
+        ],
+        "260470": [
+            "evcw",
+            "canopy water evaporation"
+        ],
+        "260471": [
+            "trans",
+            "transpiration"
+        ],
+        "260474": [
+            "sltyp",
+            "surface slope type"
+        ],
+        "260478": [
+            "evbs",
+            "direct evaporation from bare soil"
+        ],
+        "260479": [
+            "lspa",
+            "land surface precipitation accumulation"
+        ],
+        "260480": [
+            "baret",
+            "bare soil surface skin temperature"
+        ],
+        "260481": [
+            "avsft",
+            "average surface skin temperature"
+        ],
+        "260482": [
+            "radt",
+            "effective radiative skin temperature"
+        ],
+        "260483": [
+            "fldcp",
+            "field capacity"
+        ],
+        "260484": [
+            "usct",
+            "scatterometer estimated u wind component"
+        ],
+        "260485": [
+            "vsct",
+            "scatterometer estimated v wind component"
+        ],
+        "260486": [
+            "wstp",
+            "wave steepness"
+        ],
+        "260487": [
+            "omlu",
+            "ocean mixed layer u velocity"
+        ],
+        "260488": [
+            "omlv",
+            "ocean mixed layer v velocity"
+        ],
+        "260489": [
+            "ubaro",
+            "barotropic u velocity"
+        ],
+        "260490": [
+            "vbaro",
+            "barotropic v velocity"
+        ],
+        "260491": [
+            "surge",
+            "storm surge"
+        ],
+        "260492": [
+            "etsrg",
+            "extra tropical storm surge"
+        ],
+        "260493": [
+            "elevhtml",
+            "ocean surface elevation relative to geoid"
+        ],
+        "260494": [
+            "sshg",
+            "sea surface height relative to geoid"
+        ],
+        "260495": [
+            "p2omlt",
+            "ocean mixed layer potential density (reference 2000m)<br"
+        ],
+        "260496": [
+            "aohflx",
+            "net air-ocean heat flux"
+        ],
+        "260497": [
+            "ashfl",
+            "assimilative heat flux"
+        ],
+        "260498": [
+            "sstt",
+            "surface temperature trend"
+        ],
+        "260499": [
+            "ssst",
+            "surface salinity trend"
+        ],
+        "260500": [
+            "keng",
+            "kinetic energy"
+        ],
+        "260501": [
+            "sltfl",
+            "salt flux"
+        ],
+        "260502": [
+            "wtmpc",
+            "3-d temperature"
+        ],
+        "260503": [
+            "salin",
+            "3-d salinity"
+        ],
+        "260504": [
+            "bkeng",
+            "barotropic kinectic energy"
+        ],
+        "260505": [
+            "dbss",
+            "geometric depth below sea surface"
+        ],
+        "260506": [
+            "intfd",
+            "interface depths"
+        ],
+        "260507": [
+            "ohc",
+            "ocean heat content"
+        ],
+        "260508": [
+            "imgd",
+            "image data"
+        ],
+        "260509": [
+            "al",
+            "albedo"
+        ],
+        "260510": [
+            "clbt",
+            "cloudy brightness temperature"
+        ],
+        "260511": [
+            "csbt",
+            "clear-sky brightness temperature"
+        ],
+        "260530": [
+            "scaled radiance"
+        ],
+        "260531": [
+            "scaled albedo"
+        ],
+        "260532": [
+            "scaled brightness temperature"
+        ],
+        "260533": [
+            "scaled precipitable water"
+        ],
+        "260534": [
+            "scaled lifted index"
+        ],
+        "260535": [
+            "scaled cloud top pressure"
+        ],
+        "260536": [
+            "scaled skin temperature"
+        ],
+        "260537": [
+            "cloud mask"
+        ],
+        "260538": [
+            "pixel scene type"
+        ],
+        "260539": [
+            "fire detection indicator"
+        ],
+        "260550": [
+            "cloudy radiance (with respect to wave number)"
+        ],
+        "260551": [
+            "clear-sky radiance (with respect to wave number)"
+        ],
+        "260552": [
+            "wind speed"
+        ],
+        "260553": [
+            "aerosol optical thickness at 0.635 um"
+        ],
+        "260554": [
+            "aerosol optical thickness at 0.810 um"
+        ],
+        "260555": [
+            "aerosol optical thickness at 1.640 um"
+        ],
+        "260556": [
+            "angstrom coefficient"
+        ],
+        "260600": [
+            "evpsfc",
+            "evaporation"
+        ],
+        "260601": [
+            "tpratsfc",
+            "total precipitation"
+        ],
+        "260602": [
+            "lpratsfc",
+            "large scale precipitation"
+        ],
+        "260603": [
+            "cpratsfc",
+            "convective precipitation"
+        ],
+        "260604": [
+            "srweqsfc",
+            "snowfall rate water equivalent"
+        ],
+        "260605": [
+            "rofsfc",
+            "water run-off"
+        ],
+        "260606": [
+            "bvf2tht",
+            "square of brunt-vaisala frequency"
+        ],
+        "260607": [
+            "aduahbl",
+            "adiabatic zonal acceleration"
+        ],
+        "260608": [
+            "vwvclm",
+            "meridional water vapour flux"
+        ],
+        "260609": [
+            "advaprs",
+            "adiabatic meridional acceleration"
+        ],
+        "260610": [
+            "frcvsfc",
+            "frequency of deep convection"
+        ],
+        "260611": [
+            "frcvssfc",
+            "frequency of shallow convection"
+        ],
+        "260612": [
+            "frscsfc",
+            "frequency of stratocumulus parameterisation"
+        ],
+        "260613": [
+            "gwduahbl",
+            "gravity wave zonal acceleration"
+        ],
+        "260614": [
+            "gwdvahbl",
+            "gravity wave meridional acceleration"
+        ],
+        "260615": [
+            "ltrssfc",
+            "evapotranspiration"
+        ],
+        "260616": [
+            "adhrhbl",
+            "adiabatic heating rate"
+        ],
+        "260617": [
+            "mscsfc",
+            "moisture storage on canopy"
+        ],
+        "260618": [
+            "msgsfc",
+            "moisture storage on ground or cover"
+        ],
+        "260619": [
+            "smcugl",
+            "mass concentration of condensed water in soil"
+        ],
+        "260620": [
+            "cwclm",
+            "cloud liquid water"
+        ],
+        "260621": [
+            "mflxbhbl",
+            "upward mass flux at cloud base"
+        ],
+        "260622": [
+            "mfluxhbl",
+            "upward mass flux"
+        ],
+        "260623": [
+            "admrhbl",
+            "adiabatic moistening rate"
+        ],
+        "260624": [
+            "ozonehbl",
+            "ozone mixing ratio"
+        ],
+        "260625": [
+            "cnvuahbl",
+            "convective zonal acceleration"
+        ],
+        "260626": [
+            "fglusfc",
+            "zonal momentum flux by long gravity wave"
+        ],
+        "260627": [
+            "fglvsfc",
+            "meridional momentum flux by long gravity wave"
+        ],
+        "260628": [
+            "fgsvsfc",
+            "meridional momentum flux by short gravity wave"
+        ],
+        "260629": [
+            "fgsusfc",
+            "zonal momentum flux by short gravity wave"
+        ],
+        "260630": [
+            "utheclm",
+            "zonal thermal energy flux"
+        ],
+        "260631": [
+            "vtheclm",
+            "meridional thermal energy flux"
+        ],
+        "260632": [
+            "cnvvahbl",
+            "convective meridional acceleration"
+        ],
+        "260633": [
+            "lrghrhbl",
+            "large scale condensation heating rate"
+        ],
+        "260634": [
+            "cnvhrhbl",
+            "convective heating rate"
+        ],
+        "260635": [
+            "cnvmrhbl",
+            "convective moistening rate"
+        ],
+        "260636": [
+            "vdfhrhbl",
+            "vertical diffusion heating rate"
+        ],
+        "260637": [
+            "vdfuahbl",
+            "vertical diffusion zonal acceleration"
+        ],
+        "260638": [
+            "vdfvahbl",
+            "vertical diffusion meridional acceleration"
+        ],
+        "260639": [
+            "vdfmrhbl",
+            "vertical diffusion moistening rate"
+        ],
+        "260640": [
+            "swhrhbl",
+            "solar radiative heating rate"
+        ],
+        "260641": [
+            "lwhrhbl",
+            "long wave radiative heating rate"
+        ],
+        "260642": [
+            "lrgmrhbl",
+            "large scale moistening rate"
+        ],
+        "260643": [
+            "tovg",
+            "type of vegetation"
+        ],
+        "27": [
+            "cvl",
+            "low vegetation cover"
+        ],
+        "28": [
+            "cvh",
+            "high vegetation cover"
+        ],
+        "29": [
+            "tvl",
+            "type of low vegetation"
+        ],
+        "3": [
+            "pt",
+            "potential temperature"
+        ],
+        "30": [
+            "tvh",
+            "type of high vegetation"
+        ],
+        "300001": [
+            "pres",
+            "pressure"
+        ],
+        "300002": [
+            "psnm",
+            "pressure reduced to msl"
+        ],
+        "300003": [
+            "tsps",
+            "pressure tendency"
+        ],
+        "300006": [
+            "geop",
+            "geopotential"
+        ],
+        "300007": [
+            "zgeo",
+            "geopotential height"
+        ],
+        "300008": [
+            "gzge",
+            "geometric height"
+        ],
+        "300011": [
+            "temp",
+            "absolute temperature"
+        ],
+        "300012": [
+            "vtmp",
+            "virtual temperature"
+        ],
+        "300013": [
+            "ptmp",
+            "potential temperature"
+        ],
+        "300014": [
+            "psat",
+            "pseudo-adiabatic potential temperature"
+        ],
+        "300015": [
+            "mxtp",
+            "maximum temperature"
+        ],
+        "300016": [
+            "mntp",
+            "minimum temperature"
+        ],
+        "300017": [
+            "tpor",
+            "dew point temperature"
+        ],
+        "300018": [
+            "dptd",
+            "dew point depression"
+        ],
+        "300019": [
+            "lpsr",
+            "lapse rate"
+        ],
+        "300021": [
+            "rds1",
+            "radar spectra(1)"
+        ],
+        "300022": [
+            "rds2",
+            "radar spectra(2)"
+        ],
+        "300023": [
+            "rds3",
+            "radar spectra(3)"
+        ],
+        "300025": [
+            "tpan",
+            "temperature anomaly"
+        ],
+        "300026": [
+            "psan",
+            "pressure anomaly"
+        ],
+        "300027": [
+            "zgan",
+            "geopot height anomaly"
+        ],
+        "300028": [
+            "wvs1",
+            "wave spectra(1)"
+        ],
+        "300029": [
+            "wvs2",
+            "wave spectra(2)"
+        ],
+        "300030": [
+            "wvs3",
+            "wave spectra(3)"
+        ],
+        "300031": [
+            "wind",
+            "wind direction"
+        ],
+        "300032": [
+            "wins",
+            "wind speed"
+        ],
+        "300033": [
+            "uvel",
+            "zonal wind (u)"
+        ],
+        "300034": [
+            "vvel",
+            "meridional wind (v)"
+        ],
+        "300035": [
+            "fcor",
+            "stream function"
+        ],
+        "300036": [
+            "potv",
+            "velocity potential"
+        ],
+        "300038": [
+            "sgvv",
+            "sigma coord vert vel"
+        ],
+        "300039": [
+            "omeg",
+            "omega"
+        ],
+        "300040": [
+            "omg2",
+            "vertical velocity"
+        ],
+        "300041": [
+            "abvo",
+            "absolute vorticity"
+        ],
+        "300042": [
+            "abdv",
+            "absolute divergence"
+        ],
+        "300043": [
+            "vort",
+            "vorticity"
+        ],
+        "300044": [
+            "divg",
+            "divergence"
+        ],
+        "300045": [
+            "vucs",
+            "vertical u-comp shear"
+        ],
+        "300046": [
+            "vvcs",
+            "vert v-comp shear"
+        ],
+        "300047": [
+            "dirc",
+            "direction of current"
+        ],
+        "300048": [
+            "spdc",
+            "speed of current"
+        ],
+        "300049": [
+            "ucpc",
+            "u-component of current"
+        ],
+        "300050": [
+            "vcpc",
+            "v-component of current"
+        ],
+        "300051": [
+            "umes",
+            "specific humidity"
+        ],
+        "300052": [
+            "umrl",
+            "relative humidity"
+        ],
+        "300053": [
+            "hmxr",
+            "humidity mixing ratio"
+        ],
+        "300054": [
+            "agpl",
+            "inst. precipitable water"
+        ],
+        "300055": [
+            "vapp",
+            "vapour pressure"
+        ],
+        "300056": [
+            "sadf",
+            "saturation deficit"
+        ],
+        "300057": [
+            "evap",
+            "evaporation"
+        ],
+        "300059": [
+            "prcr",
+            "precipitation rate"
+        ],
+        "300060": [
+            "thpb",
+            "thunder probability"
+        ],
+        "300061": [
+            "prec",
+            "total precipitation"
+        ],
+        "300062": [
+            "prge",
+            "large scale precipitation"
+        ],
+        "300063": [
+            "prcv",
+            "convective precipitation"
+        ],
+        "300064": [
+            "neve",
+            "snowfall"
+        ],
+        "300065": [
+            "wenv",
+            "wat equiv acc snow depth"
+        ],
+        "300066": [
+            "nvde",
+            "snow depth"
+        ],
+        "300067": [
+            "mxld",
+            "mixed layer depth"
+        ],
+        "300068": [
+            "tthd",
+            "trans thermocline depth"
+        ],
+        "300069": [
+            "mthd",
+            "main thermocline depth"
+        ],
+        "300070": [
+            "mtha",
+            "main thermocline anom"
+        ],
+        "300071": [
+            "cbnv",
+            "cloud cover"
+        ],
+        "300072": [
+            "cvnv",
+            "convective cloud cover"
+        ],
+        "300073": [
+            "lwnv",
+            "low cloud cover"
+        ],
+        "300074": [
+            "mdnv",
+            "medium cloud cover"
+        ],
+        "300075": [
+            "hinv",
+            "high cloud cover"
+        ],
+        "300076": [
+            "wtnv",
+            "cloud water"
+        ],
+        "300077": [
+            "bli",
+            "best lifted index (to 500 hpa)"
+        ],
+        "300081": [
+            "lsmk",
+            "land sea mask"
+        ],
+        "300082": [
+            "dslm",
+            "dev sea_lev from mean"
+        ],
+        "300083": [
+            "zorl",
+            "roughness length"
+        ],
+        "300084": [
+            "albe",
+            "albedo"
+        ],
+        "300085": [
+            "dstp",
+            "deep soil temperature"
+        ],
+        "300086": [
+            "soic",
+            "soil moisture content"
+        ],
+        "300087": [
+            "vege",
+            "vegetation"
+        ],
+        "300089": [
+            "dens",
+            "density"
+        ],
+        "300091": [
+            "icec",
+            "ice concentration"
+        ],
+        "300092": [
+            "icet",
+            "ice thickness"
+        ],
+        "300093": [
+            "iced",
+            "direction of ice drift"
+        ],
+        "300094": [
+            "ices",
+            "speed of ice drift"
+        ],
+        "300095": [
+            "iceu",
+            "u-comp of ice drift"
+        ],
+        "300096": [
+            "icev",
+            "v-comp of ice drift"
+        ],
+        "300097": [
+            "iceg",
+            "ice growth"
+        ],
+        "300098": [
+            "icdv",
+            "ice divergence"
+        ],
+        "300100": [
+            "shcw",
+            "sig hgt com wave/swell"
+        ],
+        "300101": [
+            "wwdi",
+            "direction of wind wave"
+        ],
+        "300102": [
+            "wwsh",
+            "sig hght of wind waves"
+        ],
+        "300103": [
+            "wwmp",
+            "mean period wind waves"
+        ],
+        "300104": [
+            "swdi",
+            "direction of swell wave"
+        ],
+        "300105": [
+            "swsh",
+            "sig height swell waves"
+        ],
+        "300106": [
+            "swmp",
+            "mean period swell waves"
+        ],
+        "300107": [
+            "prwd",
+            "primary wave direction"
+        ],
+        "300108": [
+            "prmp",
+            "prim wave mean period"
+        ],
+        "300109": [
+            "swdi",
+            "second wave direction"
+        ],
+        "300110": [
+            "swmp",
+            "second wave mean period"
+        ],
+        "300111": [
+            "ocas",
+            "short wave absorbed at ground"
+        ],
+        "300112": [
+            "slds",
+            "net long wave at bottom"
+        ],
+        "300113": [
+            "nswr",
+            "net short-wav rad(top)"
+        ],
+        "300114": [
+            "role",
+            "outgoing long wave at top"
+        ],
+        "300115": [
+            "lwrd",
+            "long-wav rad"
+        ],
+        "300116": [
+            "swea",
+            "short wave absorbed by earth/atmosphere"
+        ],
+        "300117": [
+            "glbr",
+            "global radiation"
+        ],
+        "300121": [
+            "clsf",
+            "latent heat flux from surface"
+        ],
+        "300122": [
+            "cssf",
+            "sensible heat flux from surface"
+        ],
+        "300123": [
+            "blds",
+            "bound layer dissipation"
+        ],
+        "300127": [
+            "imag",
+            "image"
+        ],
+        "300128": [
+            "tp2m",
+            "2 metre temperature"
+        ],
+        "300129": [
+            "dp2m",
+            "2 metre dewpoint temperature"
+        ],
+        "300130": [
+            "u10m",
+            "10 metre u-wind component"
+        ],
+        "300131": [
+            "v10m",
+            "10 metre v-wind component"
+        ],
+        "300132": [
+            "topo",
+            "topography"
+        ],
+        "300133": [
+            "gsfp",
+            "geometric mean surface pressure"
+        ],
+        "300134": [
+            "lnsp",
+            "ln surface pressure"
+        ],
+        "300135": [
+            "pslc",
+            "surface pressure"
+        ],
+        "300136": [
+            "pslm",
+            "m s l pressure (mesinger method)"
+        ],
+        "300137": [
+            "mask",
+            "mask"
+        ],
+        "300138": [
+            "mxwu",
+            "maximum u-wind"
+        ],
+        "300139": [
+            "mxwv",
+            "maximum v-wind"
+        ],
+        "300140": [
+            "cape",
+            "convective avail. pot.energy"
+        ],
+        "300141": [
+            "cine",
+            "convective inhib. energy"
+        ],
+        "300142": [
+            "lhcv",
+            "convective latent heating"
+        ],
+        "300143": [
+            "mscv",
+            "convective moisture source"
+        ],
+        "300144": [
+            "scvm",
+            "shallow conv. moisture source"
+        ],
+        "300145": [
+            "scvh",
+            "shallow convective heating"
+        ],
+        "300146": [
+            "mxwp",
+            "maximum wind press. lvl"
+        ],
+        "300147": [
+            "ustr",
+            "storm motion u-component"
+        ],
+        "300148": [
+            "vstr",
+            "storm motion v-component"
+        ],
+        "300149": [
+            "cbnt",
+            "mean cloud cover"
+        ],
+        "300150": [
+            "pcbs",
+            "pressure at cloud base"
+        ],
+        "300151": [
+            "pctp",
+            "pressure at cloud top"
+        ],
+        "300152": [
+            "fzht",
+            "freezing level height"
+        ],
+        "300153": [
+            "fzrh",
+            "freezing level relative humidity"
+        ],
+        "300154": [
+            "fdlt",
+            "flight levels temperature"
+        ],
+        "300155": [
+            "fdlu",
+            "flight levels u-wind"
+        ],
+        "300156": [
+            "fdlv",
+            "flight levels v-wind"
+        ],
+        "300157": [
+            "tppp",
+            "tropopause pressure"
+        ],
+        "300158": [
+            "tppt",
+            "tropopause temperature"
+        ],
+        "300159": [
+            "tppu",
+            "tropopause u-wind component"
+        ],
+        "300160": [
+            "tppv",
+            "tropopause v-wind component"
+        ],
+        "300162": [
+            "gvdu",
+            "gravity wave drag du/dt"
+        ],
+        "300163": [
+            "gvdv",
+            "gravity wave drag dv/dt"
+        ],
+        "300164": [
+            "gvus",
+            "gravity wave drag sfc zonal stress"
+        ],
+        "300165": [
+            "gvvs",
+            "gravity wave drag sfc meridional stress"
+        ],
+        "300167": [
+            "dvsh",
+            "divergence of specific humidity"
+        ],
+        "300168": [
+            "hmfc",
+            "horiz. moisture flux conv."
+        ],
+        "300169": [
+            "vmfl",
+            "vert. integrated moisture flux conv."
+        ],
+        "300170": [
+            "vadv",
+            "vertical moisture advection"
+        ],
+        "300171": [
+            "nhcm",
+            "neg. hum. corr. moisture source"
+        ],
+        "300172": [
+            "lglh",
+            "large scale latent heating"
+        ],
+        "300173": [
+            "lgms",
+            "large scale moisture source"
+        ],
+        "300174": [
+            "smav",
+            "soil moisture availability"
+        ],
+        "300175": [
+            "tgrz",
+            "soil temperature of root zone"
+        ],
+        "300176": [
+            "bslh",
+            "bare soil latent heat"
+        ],
+        "300177": [
+            "evpp",
+            "potential sfc evaporation"
+        ],
+        "300178": [
+            "rnof",
+            "runoff"
+        ],
+        "300179": [
+            "pitp",
+            "interception loss"
+        ],
+        "300180": [
+            "vpca",
+            "vapor pressure of canopy air space"
+        ],
+        "300181": [
+            "qsfc",
+            "surface spec humidity"
+        ],
+        "300182": [
+            "ussl",
+            "soil wetness of surface"
+        ],
+        "300183": [
+            "uzrs",
+            "soil wetness of root zone"
+        ],
+        "300184": [
+            "uzds",
+            "soil wetness of drainage zone"
+        ],
+        "300185": [
+            "amdl",
+            "storage on canopy"
+        ],
+        "300186": [
+            "amsl",
+            "storage on ground"
+        ],
+        "300187": [
+            "tsfc",
+            "surface temperature"
+        ],
+        "300188": [
+            "tems",
+            "surface absolute temperature"
+        ],
+        "300189": [
+            "tcas",
+            "temperature of canopy air space"
+        ],
+        "300190": [
+            "ctmp",
+            "temperature at canopy"
+        ],
+        "300191": [
+            "tgsc",
+            "ground/surface cover temperature"
+        ],
+        "300192": [
+            "uves",
+            "surface zonal wind (u)"
+        ],
+        "300193": [
+            "usst",
+            "surface zonal wind stress"
+        ],
+        "300194": [
+            "vves",
+            "surface meridional wind (v)"
+        ],
+        "300195": [
+            "vsst",
+            "surface meridional wind stress"
+        ],
+        "300196": [
+            "suvf",
+            "surface momentum flux"
+        ],
+        "300197": [
+            "iswf",
+            "incident short wave flux"
+        ],
+        "300198": [
+            "ghfl",
+            "time ave ground ht flx"
+        ],
+        "300200": [
+            "lwbc",
+            "net long wave at bottom (clear)"
+        ],
+        "300201": [
+            "lwtc",
+            "outgoing long wave at top (clear)"
+        ],
+        "300202": [
+            "swec",
+            "short wv absrbd by earth/atmos (clear)"
+        ],
+        "300203": [
+            "ocac",
+            "short wave absorbed at ground (clear)"
+        ],
+        "300205": [
+            "lwrh",
+            "long wave radiative heating"
+        ],
+        "300206": [
+            "swrh",
+            "short wave radiative heating"
+        ],
+        "300207": [
+            "olis",
+            "downward long wave at bottom"
+        ],
+        "300208": [
+            "olic",
+            "downward long wave at bottom (clear)"
+        ],
+        "300209": [
+            "ocis",
+            "downward short wave at ground"
+        ],
+        "300210": [
+            "ocic",
+            "downward short wave at ground (clear)"
+        ],
+        "300211": [
+            "oles",
+            "upward long wave at bottom"
+        ],
+        "300212": [
+            "oces",
+            "upward short wave at ground"
+        ],
+        "300213": [
+            "swgc",
+            "upward short wave at ground (clear)"
+        ],
+        "300214": [
+            "roce",
+            "upward short wave at top"
+        ],
+        "300215": [
+            "swtc",
+            "upward short wave at top (clear)"
+        ],
+        "300218": [
+            "hhdf",
+            "horizontal heating diffusion"
+        ],
+        "300219": [
+            "hmdf",
+            "horizontal moisture diffusion"
+        ],
+        "300220": [
+            "hddf",
+            "horizontal divergence diffusion"
+        ],
+        "300221": [
+            "hvdf",
+            "horizontal vorticity diffusion"
+        ],
+        "300222": [
+            "vdms",
+            "vertical diff. moisture source"
+        ],
+        "300223": [
+            "vdfu",
+            "vertical diffusion du/dt"
+        ],
+        "300224": [
+            "vdfv",
+            "vertical diffusion dv/dt"
+        ],
+        "300225": [
+            "vdfh",
+            "vertical diffusion heating"
+        ],
+        "300226": [
+            "umrs",
+            "surface relative humidity"
+        ],
+        "300227": [
+            "vdcc",
+            "vertical dist total cloud cover"
+        ],
+        "300230": [
+            "usmt",
+            "time mean surface zonal wind (u)"
+        ],
+        "300231": [
+            "vsmt",
+            "time mean surface meridional wind (v)"
+        ],
+        "300232": [
+            "tsmt",
+            "time mean surface absolute temperature"
+        ],
+        "300233": [
+            "rsmt",
+            "time mean surface relative humidity"
+        ],
+        "300234": [
+            "atmt",
+            "time mean absolute temperature"
+        ],
+        "300235": [
+            "stmt",
+            "time mean deep soil temperature"
+        ],
+        "300236": [
+            "ommt",
+            "time mean derived omega"
+        ],
+        "300237": [
+            "dvmt",
+            "time mean divergence"
+        ],
+        "300238": [
+            "zhmt",
+            "time mean geopotential height"
+        ],
+        "300239": [
+            "lnmt",
+            "time mean log surface pressure"
+        ],
+        "300240": [
+            "mkmt",
+            "time mean mask"
+        ],
+        "300241": [
+            "vvmt",
+            "time mean meridional wind (v)"
+        ],
+        "300242": [
+            "omtm",
+            "time mean omega"
+        ],
+        "300243": [
+            "ptmt",
+            "time mean potential temperature"
+        ],
+        "300244": [
+            "pcmt",
+            "time mean precip. water"
+        ],
+        "300245": [
+            "rhmt",
+            "time mean relative humidity"
+        ],
+        "300246": [
+            "mpmt",
+            "time mean sea level pressure"
+        ],
+        "300247": [
+            "simt",
+            "time mean sigmadot"
+        ],
+        "300248": [
+            "uemt",
+            "time mean specific humidity"
+        ],
+        "300249": [
+            "fcmt",
+            "time mean stream function"
+        ],
+        "300250": [
+            "psmt",
+            "time mean surface pressure"
+        ],
+        "300251": [
+            "tmmt",
+            "time mean surface temperature"
+        ],
+        "300252": [
+            "pvmt",
+            "time mean velocity potential"
+        ],
+        "300253": [
+            "tvmt",
+            "time mean virtual temperature"
+        ],
+        "300254": [
+            "vtmt",
+            "time mean vorticity"
+        ],
+        "300255": [
+            "uvmt",
+            "time mean zonal wind (u)"
+        ],
+        "3003": [
+            "ptend",
+            "pressure tendency"
+        ],
+        "3005": [
+            "icaht",
+            "icao standard atmosphere reference height"
+        ],
+        "3008": [
+            "h",
+            "geometrical height"
+        ],
+        "3009": [
+            "hstdv",
+            "standard deviation of height"
+        ],
+        "3012": [
+            "vptmp",
+            "virtual potential temperature"
+        ],
+        "3014": [
+            "papt",
+            "pseudo-adiabatic potential temperature"
+        ],
+        "3015": [
+            "tmax",
+            "maximum temperature"
+        ],
+        "3016": [
+            "tmin",
+            "minimum temperature"
+        ],
+        "3017": [
+            "dpt",
+            "dew point temperature"
+        ],
+        "3018": [
+            "depr",
+            "dew point depression (or deficit)"
+        ],
+        "3019": [
+            "lapr",
+            "lapse rate"
+        ],
+        "3020": [
+            "vis",
+            "visibility"
+        ],
+        "3021": [
+            "rdsp1",
+            "radar spectra (1)"
+        ],
+        "3022": [
+            "rdsp2",
+            "radar spectra (2)"
+        ],
+        "3023": [
+            "rdsp3",
+            "radar spectra (3)"
+        ],
+        "3024": [
+            "pli",
+            "parcel lifted index (to 500 hpa)"
+        ],
+        "3025": [
+            "ta",
+            "temperature anomaly"
+        ],
+        "3026": [
+            "presa",
+            "pressure anomaly"
+        ],
+        "3027": [
+            "gpa",
+            "geopotential height anomaly"
+        ],
+        "3028": [
+            "wvsp1",
+            "wave spectra (1)"
+        ],
+        "3029": [
+            "wvsp2",
+            "wave spectra (2)"
+        ],
+        "3030": [
+            "wvsp3",
+            "wave spectra (3)"
+        ],
+        "3031": [
+            "wdir",
+            "wind direction"
+        ],
+        "3037": [
+            "mntsf",
+            "montgomery stream function"
+        ],
+        "3038": [
+            "sgcvv",
+            "sigma coordinate vertical velocity"
+        ],
+        "3041": [
+            "absv",
+            "absolute vorticity"
+        ],
+        "3042": [
+            "absd",
+            "absolute divergence"
+        ],
+        "3045": [
+            "vucsh",
+            "vertical u-component shear"
+        ],
+        "3046": [
+            "vvcsh",
+            "vertical v-component shear"
+        ],
+        "3047": [
+            "dirc",
+            "direction of current"
+        ],
+        "3048": [
+            "spc",
+            "speed of current"
+        ],
+        "3049": [
+            "ucurr",
+            "u-component of current "
+        ],
+        "3050": [
+            "vcurr",
+            "v-component of current "
+        ],
+        "3053": [
+            "mixr",
+            "humidity mixing ratio"
+        ],
+        "3054": [
+            "pwat",
+            "precipitable water"
+        ],
+        "3055": [
+            "vp",
+            "vapour pressure"
+        ],
+        "3056": [
+            "satd",
+            "saturation deficit"
+        ],
+        "3059": [
+            "prate",
+            "precipitation rate"
+        ],
+        "3060": [
+            "tstm",
+            "thunderstorm probability"
+        ],
+        "3062": [
+            "lsp",
+            "large scale precipitation"
+        ],
+        "3063": [
+            "acpcp",
+            "convective precipitation (water)"
+        ],
+        "3064": [
+            "srweq",
+            "snow fall rate water equivalent"
+        ],
+        "3066": [
+            "sde",
+            "snow depth"
+        ],
+        "3067": [
+            "mld",
+            "mixed layer depth"
+        ],
+        "3068": [
+            "tthdp",
+            "transient thermocline depth"
+        ],
+        "3069": [
+            "mthd",
+            "main thermocline depth"
+        ],
+        "3070": [
+            "mtha",
+            "main thermocline anomaly"
+        ],
+        "3072": [
+            "ccc",
+            "convective cloud cover"
+        ],
+        "3073": [
+            "lcc",
+            "low cloud cover"
+        ],
+        "3074": [
+            "mcc",
+            "medium cloud cover"
+        ],
+        "3075": [
+            "hcc",
+            "high cloud cover"
+        ],
+        "3077": [
+            "bli",
+            "best lifted index (to 500 hpa)"
+        ],
+        "3079": [
+            "lssf",
+            "large scale snow"
+        ],
+        "3080": [
+            "wtmp",
+            "water temperature"
+        ],
+        "3082": [
+            "dslm",
+            "deviation of sea-level from mean"
+        ],
+        "3086": [
+            "ssw",
+            "soil moisture content"
+        ],
+        "3088": [
+            "s",
+            "salinity"
+        ],
+        "3089": [
+            "den",
+            "density"
+        ],
+        "3091": [
+            "icec",
+            "ice cover (1=ice, 0=no ice)"
+        ],
+        "3092": [
+            "icetk",
+            "ice thickness"
+        ],
+        "3093": [
+            "diced",
+            "direction of ice drift"
+        ],
+        "3094": [
+            "siced",
+            "speed of ice drift"
+        ],
+        "3095": [
+            "uice",
+            "u-component of ice drift"
+        ],
+        "3096": [
+            "vice",
+            "v-component of ice drift"
+        ],
+        "3097": [
+            "iceg",
+            "ice growth rate"
+        ],
+        "3098": [
+            "iced",
+            "ice divergence"
+        ],
+        "3099": [
+            "snom",
+            "snow melt"
+        ],
+        "31": [
+            "ci",
+            "sea-ice cover"
+        ],
+        "3100": [
+            "swh",
+            "signific.height,combined wind waves+swell"
+        ],
+        "3101": [
+            "mdww",
+            "mean direction of wind waves"
+        ],
+        "3102": [
+            "shww",
+            "significant height of wind waves"
+        ],
+        "3103": [
+            "mpww",
+            "mean period of wind waves"
+        ],
+        "3104": [
+            "swdir",
+            "direction of swell waves"
+        ],
+        "3105": [
+            "swell",
+            "significant height of swell waves"
+        ],
+        "3106": [
+            "swper",
+            "mean period of swell waves"
+        ],
+        "3107": [
+            "mdps",
+            "primary wave direction"
+        ],
+        "3108": [
+            "mpps",
+            "primary wave mean period"
+        ],
+        "3109": [
+            "dirsw",
+            "secondary wave direction"
+        ],
+        "3110": [
+            "swp",
+            "secondary wave mean period"
+        ],
+        "3111": [
+            "nswrs",
+            "net short-wave radiation flux (surface)"
+        ],
+        "3112": [
+            "nlwrs",
+            "net long-wave radiation flux (surface)"
+        ],
+        "3113": [
+            "nswrt",
+            "net short-wave radiation flux(atmosph.top)"
+        ],
+        "3114": [
+            "nlwrt",
+            "net long-wave radiation flux(atmosph.top)"
+        ],
+        "3115": [
+            "lwavr",
+            "long wave radiation flux"
+        ],
+        "3116": [
+            "swavr",
+            "short wave radiation flux"
+        ],
+        "3117": [
+            "grad",
+            "global radiation flux"
+        ],
+        "3119": [
+            "lwrad",
+            "radiance (with respect to wave number)"
+        ],
+        "3120": [
+            "swrad",
+            "radiance (with respect to wave length)"
+        ],
+        "3121": [
+            "lhf",
+            "latent heat flux"
+        ],
+        "3122": [
+            "shf",
+            "sensible heat flux"
+        ],
+        "3123": [
+            "bld",
+            "boundary layer dissipation"
+        ],
+        "3124": [
+            "uflx",
+            "momentum flux, u-component"
+        ],
+        "3125": [
+            "vflx",
+            "momentum flux, v-component"
+        ],
+        "3126": [
+            "wmixe",
+            "wind mixing energy"
+        ],
+        "3127": [
+            "imgd",
+            "image data"
+        ],
+        "32": [
+            "asn",
+            "snow albedo"
+        ],
+        "33": [
+            "rsn",
+            "snow density"
+        ],
+        "34": [
+            "sst",
+            "sea surface temperature",
+            "sstk"
+        ],
+        "35": [
+            "istl1",
+            "ice temperature layer 1"
+        ],
+        "36": [
+            "istl2",
+            "ice temperature layer 2"
+        ],
+        "37": [
+            "istl3",
+            "ice temperature layer 3"
+        ],
+        "38": [
+            "istl4",
+            "ice temperature layer 4"
+        ],
+        "39": [
+            "swvl1",
+            "volumetric soil water layer 1",
+            "swv1"
+        ],
+        "4": [
+            "eqpt",
+            "equivalent potential temperature"
+        ],
+        "40": [
+            "swvl2",
+            "volumetric soil water layer 2",
+            "swv2"
+        ],
+        "41": [
+            "swvl3",
+            "volumetric soil water layer 3",
+            "swv3"
+        ],
+        "42": [
+            "swvl4",
+            "volumetric soil water layer 4",
+            "swv4"
+        ],
+        "43": [
+            "slt",
+            "soil type"
+        ],
+        "44": [
+            "es",
+            "snow evaporation"
+        ],
+        "45": [
+            "smlt",
+            "snowmelt"
+        ],
+        "46": [
+            "sdur",
+            "solar duration"
+        ],
+        "47": [
+            "dsrp",
+            "direct solar radiation"
+        ],
+        "48": [
+            "magss",
+            "magnitude of turbulent surface stress"
+        ],
+        "49": [
+            "10fg",
+            "10 metre wind gust since previous post-processing"
+        ],
+        "5": [
+            "sept",
+            "saturated equivalent potential temperature"
+        ],
+        "50": [
+            "lspf",
+            "large-scale precipitation fraction"
+        ],
+        "500000": [
+            "ps",
+            "pressure (s) (not reduced)"
+        ],
+        "500001": [
+            "p",
+            "pressure"
+        ],
+        "500002": [
+            "pmsl",
+            "pressure reduced to msl"
+        ],
+        "500003": [
+            "dpsdt",
+            "pressure tendency (s)"
+        ],
+        "500004": [
+            "fis",
+            "geopotential (s)"
+        ],
+        "500005": [
+            "fif",
+            "geopotential (full lev)"
+        ],
+        "500006": [
+            "fi",
+            "geopotential"
+        ],
+        "500007": [
+            "hsurf",
+            "geometric height of the earths surface above sea level"
+        ],
+        "500008": [
+            "hhl",
+            "geometric height of the layer limits above sea level(nn)"
+        ],
+        "500009": [
+            "to3",
+            "total column integrated ozone"
+        ],
+        "500010": [
+            "t_g",
+            "temperature (g)"
+        ],
+        "500011": [
+            "t_2m",
+            "2m temperature"
+        ],
+        "500012": [
+            "t_2m_av",
+            "2m temperature (av)"
+        ],
+        "500013": [
+            "t_2m_cl",
+            "climat. temperature, 2m temperature"
+        ],
+        "500015": [
+            "tmax_2m",
+            "max 2m temperature (i)"
+        ],
+        "500016": [
+            "tmin_2m",
+            "min 2m temperature (i)"
+        ],
+        "500017": [
+            "td_2m",
+            "2m dew point temperature"
+        ],
+        "500018": [
+            "td_2m_av",
+            "2m dew point temperature (av)"
+        ],
+        "500019": [
+            "dbz_max",
+            "radar spectra (1)"
+        ],
+        "500020": [
+            "wvsp1",
+            "wave spectra (1)"
+        ],
+        "500021": [
+            "wvsp2",
+            "wave spectra (2)"
+        ],
+        "500022": [
+            "wvsp3",
+            "wave spectra (3)"
+        ],
+        "500023": [
+            "dd_10m",
+            "wind direction (dd_10m)"
+        ],
+        "500024": [
+            "dd",
+            "wind direction (dd)"
+        ],
+        "500025": [
+            "sp_10m",
+            "wind speed (sp_10m)"
+        ],
+        "500026": [
+            "sp",
+            "wind speed (sp)"
+        ],
+        "500027": [
+            "u_10m",
+            "u component of wind"
+        ],
+        "500028": [
+            "u",
+            "u component of wind"
+        ],
+        "500029": [
+            "v_10m",
+            "v component of wind"
+        ],
+        "500030": [
+            "v",
+            "v component of wind"
+        ],
+        "500031": [
+            "omega",
+            "vertical velocity (pressure) ( omega=dp/dt )"
+        ],
+        "500032": [
+            "w",
+            "vertical velocity (geometric) (w)"
+        ],
+        "500033": [
+            "qv_s",
+            "specific humidity (s)"
+        ],
+        "500034": [
+            "qv_2m",
+            "specific humidity (2m)"
+        ],
+        "500035": [
+            "qv",
+            "specific humidity"
+        ],
+        "500036": [
+            "relhum_2m",
+            "2m relative humidity"
+        ],
+        "500037": [
+            "relhum",
+            "relative humidity"
+        ],
+        "500038": [
+            "tqv",
+            "total column integrated water vapour"
+        ],
+        "500039": [
+            "aevap_s",
+            "evaporation (s)"
+        ],
+        "500040": [
+            "tqi",
+            "total column-integrated cloud ice"
+        ],
+        "500041": [
+            "tot_prec",
+            "total precipitation rate (s)"
+        ],
+        "500042": [
+            "prec_gsp",
+            "large-scale precipitation rate"
+        ],
+        "500043": [
+            "prec_con",
+            "convective precipitation rate"
+        ],
+        "500044": [
+            "w_snow",
+            "snow depth water equivalent"
+        ],
+        "500045": [
+            "h_snow",
+            "snow depth"
+        ],
+        "500046": [
+            "clct",
+            "total cloud cover"
+        ],
+        "500047": [
+            "clc_con",
+            "convective cloud cover"
+        ],
+        "500048": [
+            "clcl",
+            "cloud cover (800 hpa - soil)"
+        ],
+        "500049": [
+            "clcm",
+            "cloud cover (400 - 800 hpa)"
+        ],
+        "500050": [
+            "clch",
+            "cloud cover (0 - 400 hpa)"
+        ],
+        "500051": [
+            "tqc",
+            "total column-integrated cloud water"
+        ],
+        "500052": [
+            "snow_con",
+            "convective snowfall rate water equivalent (s)"
+        ],
+        "500053": [
+            "snow_gsp",
+            "large-scale snowfall rate water equivalent (s)"
+        ],
+        "500054": [
+            "fr_land",
+            "land cover (1=land, 0=sea)"
+        ],
+        "500055": [
+            "z0",
+            "surface roughness length surface roughness"
+        ],
+        "500056": [
+            "alb_rad",
+            "albedo (in short-wave)"
+        ],
+        "500057": [
+            "albedo_b",
+            "albedo (in short-wave)"
+        ],
+        "500058": [
+            "t_cl",
+            "soil temperature  ( 36 cm depth, vv=0h)"
+        ],
+        "500059": [
+            "t_cl_lm",
+            "soil temperature (41 cm depth)"
+        ],
+        "500060": [
+            "t_m",
+            "soil temperature"
+        ],
+        "500061": [
+            "t_s",
+            "soil temperature"
+        ],
+        "500062": [
+            "w_cl",
+            "column-integrated soil moisture"
+        ],
+        "500063": [
+            "w_g1",
+            "column-integrated soil moisture (1) 0 -10 cm"
+        ],
+        "500064": [
+            "w_g2",
+            "column-integrated soil moisture (2) 10-100cm"
+        ],
+        "500065": [
+            "plcov",
+            "plant cover"
+        ],
+        "500066": [
+            "runoff_g",
+            "water runoff (10-100)"
+        ],
+        "500067": [
+            "runoff_g_lm",
+            "water runoff (10-190)"
+        ],
+        "500068": [
+            "runoff_s",
+            "water runoff (s)"
+        ],
+        "500069": [
+            "fr_ice",
+            "sea ice cover ( 0= free, 1=cover)"
+        ],
+        "500070": [
+            "h_ice",
+            "sea ice thickness"
+        ],
+        "500071": [
+            "swh",
+            "significant height of combined wind waves and swell"
+        ],
+        "500072": [
+            "mdww",
+            "direction of wind waves"
+        ],
+        "500073": [
+            "shww",
+            "significant height of wind waves"
+        ],
+        "500074": [
+            "mpww",
+            "mean period of wind waves"
+        ],
+        "500075": [
+            "mdps",
+            "direction of swell waves"
+        ],
+        "500076": [
+            "shps",
+            "significant height of swell waves"
+        ],
+        "500077": [
+            "mpps",
+            "mean period of swell waves"
+        ],
+        "500078": [
+            "asob_s",
+            "net short wave radiation flux (m) (at the surface)"
+        ],
+        "500079": [
+            "sobs_rad",
+            "net short wave radiation flux"
+        ],
+        "500080": [
+            "athb_s",
+            "net long wave radiation flux (m) (at the surface)"
+        ],
+        "500081": [
+            "thbs_rad",
+            "net long wave radiation flux"
+        ],
+        "500082": [
+            "asob_t",
+            "net short wave radiation flux (m) (on the model top)"
+        ],
+        "500083": [
+            "sobt_rad",
+            "net short wave radiation flux"
+        ],
+        "500084": [
+            "athb_t",
+            "net long wave radiation flux (m) (on the model top)"
+        ],
+        "500085": [
+            "thbt_rad",
+            "net long wave radiation flux"
+        ],
+        "500086": [
+            "alhfl_s",
+            "latent heat net flux (m)"
+        ],
+        "500087": [
+            "ashfl_s",
+            "sensible heat net flux (m)"
+        ],
+        "500088": [
+            "aumfl_s",
+            "momentum flux, u-component (m)"
+        ],
+        "500089": [
+            "avmfl_s",
+            "momentum flux, v-component (m)"
+        ],
+        "500090": [
+            "apab_s",
+            "photosynthetically active radiation (m) (at the surface)"
+        ],
+        "500091": [
+            "pabs_rad",
+            "photosynthetically active radiation"
+        ],
+        "500092": [
+            "sohr_rad",
+            "solar radiation heating rate"
+        ],
+        "500093": [
+            "thhr_rad",
+            "thermal radiation heating rate"
+        ],
+        "500094": [
+            "alhfl_bs",
+            "latent heat flux from bare soil"
+        ],
+        "500095": [
+            "alhfl_pl",
+            "latent heat flux from plants"
+        ],
+        "500096": [
+            "dursun",
+            "sunshine"
+        ],
+        "500097": [
+            "rstom",
+            "stomatal resistance"
+        ],
+        "500098": [
+            "clc",
+            "cloud cover"
+        ],
+        "500099": [
+            "clc_sgs",
+            "non-convective cloud cover, grid scale"
+        ],
+        "500100": [
+            "qc",
+            "cloud mixing ratio"
+        ],
+        "500101": [
+            "qi",
+            "cloud ice mixing ratio"
+        ],
+        "500102": [
+            "qr",
+            "rain mixing ratio"
+        ],
+        "500103": [
+            "qs",
+            "snow mixing ratio"
+        ],
+        "500104": [
+            "tqr",
+            "total column integrated rain"
+        ],
+        "500105": [
+            "tqs",
+            "total column integrated snow"
+        ],
+        "500106": [
+            "qg",
+            "grauple"
+        ],
+        "500107": [
+            "tqg",
+            "total column integrated grauple"
+        ],
+        "500108": [
+            "twater",
+            "total column integrated water (all components incl. precipitation)"
+        ],
+        "500109": [
+            "tdiv_hum",
+            "vertical integral of divergence of total water content (s)"
+        ],
+        "500110": [
+            "qc_rad",
+            "subgrid scale cloud water"
+        ],
+        "500111": [
+            "qi_rad",
+            "subgridscale cloud ice"
+        ],
+        "500112": [
+            "clch_8",
+            "cloud cover ch (0..8)"
+        ],
+        "500113": [
+            "clcm_8",
+            "cloud cover cm (0..8)"
+        ],
+        "500114": [
+            "clcl_8",
+            "cloud cover cl (0..8)"
+        ],
+        "500115": [
+            "hbas_sc",
+            "cloud base above msl, shallow convection"
+        ],
+        "500116": [
+            "htop_sc",
+            "cloud top above msl, shallow convection"
+        ],
+        "500117": [
+            "clw_con",
+            "specific cloud water content, convective cloud"
+        ],
+        "500118": [
+            "hbas_con",
+            "height of convective cloud base (i)"
+        ],
+        "500119": [
+            "htop_con",
+            "height of convective cloud top (i)"
+        ],
+        "500120": [
+            "bas_con",
+            "base index (vertical level) of main convective cloud (i)"
+        ],
+        "500121": [
+            "top_con",
+            "top index (vertical level) of main convective cloud (i)"
+        ],
+        "500122": [
+            "dt_con",
+            "temperature tendency due to convection"
+        ],
+        "500123": [
+            "dqv_con",
+            "specific humitiy tendency due to convection"
+        ],
+        "500124": [
+            "du_con",
+            "zonal wind tendency due to convection"
+        ],
+        "500125": [
+            "dv_con",
+            "meridional wind tendency due to convection"
+        ],
+        "500126": [
+            "htop_dc",
+            "height of top of dry convection"
+        ],
+        "500127": [
+            "hzerocl",
+            "height of 0 degree celsius level code 0,3,6 ?"
+        ],
+        "500128": [
+            "snowlmt",
+            "height of snow fall limit"
+        ],
+        "500129": [
+            "dqc_con",
+            "tendency of specific cloud liquid water content due to conversion"
+        ],
+        "500130": [
+            "dqi_con",
+            "tendency of  specific cloud ice content due to convection"
+        ],
+        "500131": [
+            "q_sedim",
+            "specific content of precipitation particles (needed for water loadin)g"
+        ],
+        "500132": [
+            "prr_gsp",
+            "large scale rain rate"
+        ],
+        "500133": [
+            "prs_gsp",
+            "large scale snowfall rate water equivalent"
+        ],
+        "500134": [
+            "rain_gsp",
+            "large scale rain rate (s)"
+        ],
+        "500135": [
+            "prr_con",
+            "convective rain rate"
+        ],
+        "500136": [
+            "prs_con",
+            "convective snowfall rate water equivalent"
+        ],
+        "500137": [
+            "rain_con",
+            "convective rain rate (s)"
+        ],
+        "500138": [
+            "rr_f",
+            "rain amount, grid-scale plus convective"
+        ],
+        "500139": [
+            "rr_c",
+            "snow amount, grid-scale plus convective"
+        ],
+        "500140": [
+            "dt_gsp",
+            "temperature tendency due to grid scale precipation"
+        ],
+        "500141": [
+            "dqv_gsp",
+            "specific humitiy tendency due to grid scale precipitation"
+        ],
+        "500142": [
+            "dqc_gsp",
+            "tendency of specific cloud liquid water content due to grid scale precipitation"
+        ],
+        "500143": [
+            "freshsnw",
+            "fresh snow factor (weighting function for albedo indicating freshness of snow)"
+        ],
+        "500144": [
+            "dqi_gsp",
+            "tendency of specific cloud ice content due to grid scale precipitation"
+        ],
+        "500145": [
+            "prg_gsp",
+            "graupel (snow pellets) precipitation rate"
+        ],
+        "500146": [
+            "grau_gsp",
+            "graupel (snow pellets) precipitation rate"
+        ],
+        "500147": [
+            "rho_snow",
+            "snow density"
+        ],
+        "500148": [
+            "pp",
+            "pressure perturbation"
+        ],
+        "500149": [
+            "sdi_1",
+            "supercell detection index 1 (rot. up+down drafts)"
+        ],
+        "500150": [
+            "sdi_2",
+            "supercell detection index 2 (only rot. up drafts)"
+        ],
+        "500151": [
+            "cape_mu",
+            "convective available potential energy, most unstable"
+        ],
+        "500152": [
+            "cin_mu",
+            "convective inhibition, most unstable"
+        ],
+        "500153": [
+            "cape_ml",
+            "convective available potential energy, mean layer"
+        ],
+        "500154": [
+            "cin_ml",
+            "convective inhibition, mean layer"
+        ],
+        "500155": [
+            "tke_con",
+            "convective turbulent kinetic enery"
+        ],
+        "500156": [
+            "tketens",
+            "tendency of turbulent kinetic energy"
+        ],
+        "500157": [
+            "ke",
+            "kinetic energy"
+        ],
+        "500158": [
+            "tke",
+            "turbulent kinetic energy"
+        ],
+        "500159": [
+            "tkvm",
+            "turbulent diffusioncoefficient for momentum"
+        ],
+        "500160": [
+            "tkvh",
+            "turbulent diffusion coefficient for heat (and moisture)"
+        ],
+        "500161": [
+            "tcm",
+            "turbulent transfer coefficient for impulse"
+        ],
+        "500162": [
+            "tch",
+            "turbulent transfer coefficient for heat (and moisture)"
+        ],
+        "500163": [
+            "mh",
+            "mixed layer depth"
+        ],
+        "500164": [
+            "vmax_10m",
+            "maximum wind 10m"
+        ],
+        "500165": [
+            "ru-103",
+            "air concentration of ruthenium 103"
+        ],
+        "500166": [
+            "t_so",
+            "soil temperature (multilayers)"
+        ],
+        "500167": [
+            "w_so",
+            "column-integrated soil moisture (multilayers)"
+        ],
+        "500168": [
+            "w_so_ice",
+            "soil ice content (multilayers)"
+        ],
+        "500169": [
+            "w_i",
+            "plant canopy surface water"
+        ],
+        "500170": [
+            "t_snow",
+            "snow temperature (top of snow)"
+        ],
+        "500171": [
+            "prs_min",
+            "minimal stomatal resistance"
+        ],
+        "500172": [
+            "t_ice",
+            "sea ice temperature"
+        ],
+        "500173": [
+            "dbz_850",
+            "base reflectivity"
+        ],
+        "500174": [
+            "dbz",
+            "base reflectivity"
+        ],
+        "500175": [
+            "dbz_cmax",
+            "base reflectivity (cmax)"
+        ],
+        "500176": [
+            "dttdiv",
+            "unknown"
+        ],
+        "500177": [
+            "sotr_rad",
+            "effective transmissivity of solar radiation"
+        ],
+        "500178": [
+            "evatra_sum",
+            "sum of contributions to evaporation"
+        ],
+        "500179": [
+            "tra_sum",
+            "total transpiration from all soil layers"
+        ],
+        "500180": [
+            "totforce_s",
+            "total forcing at soil surface"
+        ],
+        "500181": [
+            "resid_wso",
+            "residuum of soil moisture"
+        ],
+        "500182": [
+            "mflx_con",
+            "massflux at convective cloud base"
+        ],
+        "500183": [
+            "cape_con",
+            "convective available potential energy"
+        ],
+        "500184": [
+            "qcvg_con",
+            "moisture convergence for kuo-type closure"
+        ],
+        "500185": [
+            "mwd",
+            "total wave direction"
+        ],
+        "500186": [
+            "mwp_x",
+            "wind sea mean period"
+        ],
+        "500187": [
+            "ppww",
+            "wind sea peak period"
+        ],
+        "500188": [
+            "mpp_s",
+            "swell mean period"
+        ],
+        "500189": [
+            "ppps",
+            "swell peak period"
+        ],
+        "500190": [
+            "pp1d",
+            "total wave peak period"
+        ],
+        "500191": [
+            "tm10",
+            "total wave mean period"
+        ],
+        "500192": [
+            "tm01",
+            "total tm1 period"
+        ],
+        "500193": [
+            "tm02",
+            "total tm2 period"
+        ],
+        "500194": [
+            "sprd",
+            "total directional spread"
+        ],
+        "500195": [
+            "ana_err_fi",
+            "analysis error(standard deviation), geopotential(gpm)"
+        ],
+        "500196": [
+            "ana_err_u",
+            "analysis error(standard deviation), u-comp. of wind"
+        ],
+        "500197": [
+            "ana_err_v",
+            "analysis error(standard deviation), v-comp. of wind"
+        ],
+        "500198": [
+            "du_sso",
+            "zonal wind tendency due to subgrid scale oro."
+        ],
+        "500199": [
+            "dv_sso",
+            "meridional wind tendency due to subgrid scale oro."
+        ],
+        "500200": [
+            "sso_stdh",
+            "standard deviation of sub-grid scale orography"
+        ],
+        "500201": [
+            "sso_gamma",
+            "anisotropy of sub-gridscale orography"
+        ],
+        "500202": [
+            "sso_theta",
+            "angle of sub-gridscale orography"
+        ],
+        "500203": [
+            "sso_sigma",
+            "slope of sub-gridscale orography"
+        ],
+        "500204": [
+            "emis_rad",
+            "surface emissivity"
+        ],
+        "500205": [
+            "soiltyp",
+            "soil type"
+        ],
+        "500206": [
+            "lai",
+            "leaf area index"
+        ],
+        "500207": [
+            "rootdp",
+            "root depth of vegetation"
+        ],
+        "500208": [
+            "hmo3",
+            "height of ozone maximum (climatological)"
+        ],
+        "500209": [
+            "vio3",
+            "vertically integrated ozone content (climatological)"
+        ],
+        "500210": [
+            "plcov_mx",
+            "plant covering degree in the vegetation phase"
+        ],
+        "500211": [
+            "plcov_mn",
+            "plant covering degree in the quiescent phas"
+        ],
+        "500212": [
+            "lai_mx",
+            "max leaf area index"
+        ],
+        "500213": [
+            "lai_mn",
+            "min leaf area index"
+        ],
+        "500214": [
+            "oro_mod",
+            "orographie + land-meer-verteilung"
+        ],
+        "500215": [
+            "wvar1",
+            "variance of soil moisture content (0-10)"
+        ],
+        "500216": [
+            "wvar2",
+            "variance of soil moisture content (10-100)"
+        ],
+        "500217": [
+            "for_e",
+            "evergreen forest"
+        ],
+        "500218": [
+            "for_d",
+            "deciduous forest"
+        ],
+        "500219": [
+            "ndvi",
+            "normalized differential vegetation index"
+        ],
+        "500220": [
+            "ndvi_max",
+            "normalized differential vegetation index (ndvi)"
+        ],
+        "500221": [
+            "ndvi_mrat",
+            "ratio of monthly mean ndvi (normalized differential vegetation index) to annual maximum"
+        ],
+        "500222": [
+            "ndviratio",
+            "ratio of monthly mean ndvi (normalized differential vegetation index) to annual maximum"
+        ],
+        "500223": [
+            "aer_so4",
+            "total sulfate aerosol"
+        ],
+        "500224": [
+            "aer_so412",
+            "total sulfate aerosol (12m)"
+        ],
+        "500225": [
+            "aer_dust",
+            "total soil dust aerosol"
+        ],
+        "500226": [
+            "aer_dust12",
+            "total soil dust aerosol (12m)"
+        ],
+        "500227": [
+            "aer_org",
+            "organic aerosol"
+        ],
+        "500228": [
+            "aer_org12",
+            "organic aerosol (12m)"
+        ],
+        "500229": [
+            "aer_bc",
+            "black carbon aerosol"
+        ],
+        "500230": [
+            "aer_bc12",
+            "black carbon aerosol (12m)"
+        ],
+        "500231": [
+            "aer_ss",
+            "sea salt aerosol"
+        ],
+        "500232": [
+            "aer_ss12",
+            "sea salt aerosol (12m)"
+        ],
+        "500233": [
+            "dqvdt",
+            "tendency of specific humidity"
+        ],
+        "500234": [
+            "qvsflx",
+            "water vapor flux"
+        ],
+        "500235": [
+            "fc",
+            "coriolis parameter"
+        ],
+        "500236": [
+            "rlat",
+            "geographical latitude"
+        ],
+        "500237": [
+            "rlon",
+            "geographical longitude"
+        ],
+        "500238": [
+            "ustr",
+            "friction velocity"
+        ],
+        "500239": [
+            "ztd",
+            "delay of the gps signal trough the (total) atm."
+        ],
+        "500240": [
+            "zwd",
+            "delay of the gps signal trough wet atmos."
+        ],
+        "500241": [
+            "zhd",
+            "delay of the gps signal trough dry atmos."
+        ],
+        "500242": [
+            "o3",
+            "ozone mixing ratio"
+        ],
+        "500243": [
+            "ru-103",
+            "air concentration of ruthenium 103 (ru103- concentration)"
+        ],
+        "500244": [
+            "ru-103d",
+            "ru103-dry deposition"
+        ],
+        "500245": [
+            "ru-103w",
+            "ru103-wet deposition"
+        ],
+        "500246": [
+            "sr-90",
+            "air concentration of strontium 90"
+        ],
+        "500247": [
+            "sr-90d",
+            "sr90-dry deposition"
+        ],
+        "500248": [
+            "sr-90w",
+            "sr90-wet deposition"
+        ],
+        "500249": [
+            "i-131a",
+            "i131-concentration"
+        ],
+        "500250": [
+            "i-131ad",
+            "i131-dry deposition"
+        ],
+        "500251": [
+            "i-131aw",
+            "i131-wet deposition"
+        ],
+        "500252": [
+            "cs-137",
+            "cs137-concentration"
+        ],
+        "500253": [
+            "cs-137d",
+            "cs137-dry deposition"
+        ],
+        "500254": [
+            "cs-137w",
+            "cs137-wet deposition"
+        ],
+        "500255": [
+            "te-132",
+            "air concentration of tellurium 132 (te132-concentration)"
+        ],
+        "500256": [
+            "te-132d",
+            "te132-dry deposition"
+        ],
+        "500257": [
+            "te-132w",
+            "te132-wet deposition"
+        ],
+        "500258": [
+            "zr-95",
+            "air concentration of zirconium 95 (zr95-concentration)"
+        ],
+        "500259": [
+            "zr-95d",
+            "zr95-dry deposition"
+        ],
+        "500260": [
+            "zr-95w",
+            "zr95-wet deposition"
+        ],
+        "500261": [
+            "kr-85",
+            "air concentration of krypton 85  (kr85-concentration)"
+        ],
+        "500262": [
+            "kr-85d",
+            "kr85-dry deposition"
+        ],
+        "500263": [
+            "kr-85w",
+            "kr85-wet deposition"
+        ],
+        "500264": [
+            "tr-2",
+            "tracer - concentration"
+        ],
+        "500265": [
+            "tr-2d",
+            "tracer - dry deposition"
+        ],
+        "500266": [
+            "tr-2w",
+            "tracer - wet deposition"
+        ],
+        "500267": [
+            "xe-133",
+            "air concentration of xenon 133 (xe133  - concentration)"
+        ],
+        "500268": [
+            "xe-133d",
+            "xe133  - dry deposition"
+        ],
+        "500269": [
+            "xe-133w",
+            "xe133  - wet deposition"
+        ],
+        "500270": [
+            "i-131g",
+            "i131g - concentration"
+        ],
+        "500271": [
+            "i-131gd",
+            "xe133  - wet deposition"
+        ],
+        "500272": [
+            "i-131gw",
+            "i131g  - wet deposition"
+        ],
+        "500273": [
+            "i-131o",
+            "i131o  - concentration"
+        ],
+        "500274": [
+            "i-131od",
+            "i131o  - dry deposition"
+        ],
+        "500275": [
+            "i-131ow",
+            "i131o  - wet deposition"
+        ],
+        "500276": [
+            "ba-140",
+            "air concentration of barium 40"
+        ],
+        "500277": [
+            "ba-140d",
+            "ba140 - dry deposition"
+        ],
+        "500278": [
+            "ba-140w",
+            "ba140  - wet deposition"
+        ],
+        "500279": [
+            "austr_sso",
+            "u-momentum flux due to sso-effects"
+        ],
+        "500280": [
+            "ustr_sso",
+            "u-momentum flux due to sso-effects"
+        ],
+        "500281": [
+            "avstr_sso",
+            "v-momentum flux due to sso-effects"
+        ],
+        "500282": [
+            "vstr_sso",
+            "v-momentum flux due to sso-effects"
+        ],
+        "500283": [
+            "avdis_sso",
+            "gravity wave dissipation (vertical integral)"
+        ],
+        "500284": [
+            "vdis_sso",
+            "gravity wave dissipation (vertical integral)"
+        ],
+        "500285": [
+            "uv_max",
+            "uv_index_maximum_w  uv_index clouded (w), daily maximum"
+        ],
+        "500286": [
+            "w_shaer",
+            "wind shear"
+        ],
+        "500287": [
+            "srh",
+            "storm relative helicity"
+        ],
+        "500288": [
+            "vabs",
+            "absolute vorticity advection"
+        ],
+        "500289": [
+            "cl_typ",
+            "niederschlagbew.-artkombination niederschl.-bew.-blautherm. (283..407)"
+        ],
+        "500290": [
+            "ccl_gnd",
+            "konvektions-u-grenzehoehe der konvektionsuntergrenze ueber grund"
+        ],
+        "500291": [
+            "ccl_nn",
+            "konv.-u-grenze-nn   hoehe der konvektionsuntergrenze ueber nn"
+        ],
+        "500292": [
+            "ww",
+            "weather interpretation (wmo)"
+        ],
+        "500293": [
+            "advorg",
+            "geostrophische  vorticityadvektion"
+        ],
+        "500294": [
+            "advor",
+            "geo temperatur adv  geostrophische schichtdickenadvektion"
+        ],
+        "500295": [
+            "adrtg",
+            "schichtdicken-advektion"
+        ],
+        "500296": [
+            "wdiv",
+            "winddivergenz"
+        ],
+        "500297": [
+            "fqn",
+            "qn-vektor q isother-senkr-kompqn ,komp. q-vektor senkrecht zu den isothermen"
+        ],
+        "500298": [
+            "ipv",
+            "isentrope potentielle vorticity"
+        ],
+        "500299": [
+            "up",
+            "xipv wind x-komp     wind x-komponente auf isentropen flaechen"
+        ],
+        "500300": [
+            "vp",
+            "yipv wind y-komp     wind y-komponente auf isentropen flaechen"
+        ],
+        "500301": [
+            "ptheta",
+            "druck einer isentropen flaeche"
+        ],
+        "500302": [
+            "ko",
+            "ko index"
+        ],
+        "500303": [
+            "thetae",
+            "aequivalentpotentielle temperatur"
+        ],
+        "500304": [
+            "ceiling",
+            "ceiling"
+        ],
+        "500305": [
+            "ice_grd",
+            "icing grade (1=lgt,2=mod,3=sev)"
+        ],
+        "500306": [
+            "cldepth",
+            "modified cloud depth for media"
+        ],
+        "500307": [
+            "clct_mod",
+            "modified cloud cover for media"
+        ],
+        "500308": [
+            "efa-ps",
+            "monthly mean of rms of difference fg-an of pressure reduced to msl"
+        ],
+        "500309": [
+            "eia-ps",
+            "monthly mean of rms of difference ia-an of pressure reduced to msl"
+        ],
+        "500310": [
+            "efa-u",
+            "monthly mean of rms of difference fg-an of u-component of wind"
+        ],
+        "500311": [
+            "eia-u",
+            "monthly mean of rms of difference ia-an of u-component of wind"
+        ],
+        "500312": [
+            "efa-v",
+            "monthly mean of rms of difference fg-an of v-component of wind"
+        ],
+        "500313": [
+            "eia-v",
+            "monthly mean of rms of difference ia-an of v-component of wind"
+        ],
+        "500314": [
+            "efa-fi",
+            "monthly mean of rms of difference fg-an of geopotential"
+        ],
+        "500315": [
+            "eia-fi",
+            "monthly mean of rms of difference ia-an of geopotential"
+        ],
+        "500316": [
+            "efa-rh",
+            "monthly mean of rms of difference fg-an of relative humidity"
+        ],
+        "500317": [
+            "eia-rh",
+            "monthly mean of rms of difference ia-an of relative humidity"
+        ],
+        "500318": [
+            "efa-t",
+            "monthly mean of rms of difference fg-an of temperature"
+        ],
+        "500319": [
+            "eia-t",
+            "monthly mean of rms of difference ia-an of temperature"
+        ],
+        "500320": [
+            "efa-om",
+            "monthly mean of rms of difference fg-an of vert.velocity (pressure)"
+        ],
+        "500321": [
+            "eia-om",
+            "monthly mean of rms of difference ia-an of vert.velocity (pressure)"
+        ],
+        "500322": [
+            "efa-ke",
+            "monthly mean of rms of difference fg-an of kinetic energy"
+        ],
+        "500323": [
+            "eia-ke",
+            "monthly mean of rms of difference ia-an of kinetic energy"
+        ],
+        "500324": [
+            "synme5_bt_cl",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500325": [
+            "synme5_bt_cs",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500326": [
+            "synme5_rad_cl",
+            "synth. sat. radiance cloudy"
+        ],
+        "500327": [
+            "synme5_rad_cs",
+            "synth. sat. radiance cloudy"
+        ],
+        "500328": [
+            "synme6_bt_cl",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500329": [
+            "synme6_bt_cs",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500330": [
+            "synme6_rad_cl",
+            "synth. sat. radiance cloudy"
+        ],
+        "500331": [
+            "synme6_rad_cs",
+            "synth. sat. radiance cloudy"
+        ],
+        "500332": [
+            "synme7_bt_cl_ir11.5",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500333": [
+            "synme7_bt_cl_wv6.4",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500334": [
+            "synme7_bt_cs_ir11.5",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500335": [
+            "synme7_bt_cs_wv6.4",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500336": [
+            "synme7_rad_cl_ir11.5",
+            "synth. sat. radiance clear sky"
+        ],
+        "500337": [
+            "synme7_rad_cl_wv6.4",
+            "synth. sat. radiance cloudy"
+        ],
+        "500338": [
+            "synme7_rad_cs_ir11.5",
+            "synth. sat. radiance clear sky"
+        ],
+        "500339": [
+            "synme7_rad_cs_wv6.4",
+            "synth. sat. radiance cloudy"
+        ],
+        "500340": [
+            "synmsg_bt_cl_ir10.8",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500341": [
+            "synmsg_bt_cl_ir12.1",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500342": [
+            "synmsg_bt_cl_ir13.4",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500343": [
+            "synmsg_bt_cl_ir3.9",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500344": [
+            "synmsg_bt_cl_ir8.7",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500345": [
+            "synmsg_bt_cl_ir9.7",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500346": [
+            "synmsg_bt_cl_wv6.2",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500347": [
+            "synmsg_bt_cl_wv7.3",
+            "synth. sat. brightness temperature cloudy"
+        ],
+        "500348": [
+            "synmsg_bt_cs_ir8.7",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500349": [
+            "synmsg_bt_cs_ir10.8",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500350": [
+            "synmsg_bt_cs_ir12.1",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500351": [
+            "synmsg_bt_cs_ir13.4",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500352": [
+            "synmsg_bt_cs_ir3.9",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500353": [
+            "synmsg_bt_cs_ir9.7",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500354": [
+            "synmsg_bt_cs_wv6.2",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500355": [
+            "synmsg_bt_cs_wv7.3",
+            "synth. sat. brightness temperature clear sky"
+        ],
+        "500356": [
+            "synmsg_rad_cl_ir10.8",
+            "synth. sat. radiance cloudy"
+        ],
+        "500357": [
+            "synmsg_rad_cl_ir12.1",
+            "synth. sat. radiance cloudy"
+        ],
+        "500358": [
+            "synmsg_rad_cl_ir13.4",
+            "synth. sat. radiance cloudy"
+        ],
+        "500359": [
+            "synmsg_rad_cl_ir3.9",
+            "synth. sat. radiance cloudy"
+        ],
+        "500360": [
+            "synmsg_rad_cl_ir8.7",
+            "synth. sat. radiance cloudy"
+        ],
+        "500361": [
+            "synmsg_rad_cl_ir9.7",
+            "synth. sat. radiance cloudy"
+        ],
+        "500362": [
+            "synmsg_rad_cl_wv6.2",
+            "synth. sat. radiance cloudy"
+        ],
+        "500363": [
+            "synmsg_rad_cl_wv7.3",
+            "synth. sat. radiance cloudy"
+        ],
+        "500364": [
+            "synmsg_rad_cs_ir10.8",
+            "synth. sat. radiance clear sky"
+        ],
+        "500365": [
+            "synmsg_rad_cs_ir12.1",
+            "synth. sat. radiance clear sky"
+        ],
+        "500366": [
+            "synmsg_rad_cs_ir13.4",
+            "synth. sat. radiance clear sky"
+        ],
+        "500367": [
+            "synmsg_rad_cs_ir3.9",
+            "synth. sat. radiance clear sky"
+        ],
+        "500368": [
+            "synmsg_rad_cs_ir8.7",
+            "synth. sat. radiance clear sky"
+        ],
+        "500369": [
+            "synmsg_rad_cs_ir9.7",
+            "synth. sat. radiance clear sky"
+        ],
+        "500370": [
+            "synmsg_rad_cs_wv6.2",
+            "synth. sat. radiance clear sky"
+        ],
+        "500371": [
+            "synmsg_rad_cs_wv7.3",
+            "synth. sat. radiance clear sky"
+        ],
+        "500372": [
+            "t_2m_s",
+            "smoothed forecast, temperature"
+        ],
+        "500373": [
+            "tmax_2m_s",
+            "smoothed forecast, maximum temp."
+        ],
+        "500374": [
+            "tmin_2m_s",
+            "smoothed forecast, minimum temp."
+        ],
+        "500375": [
+            "td_2m_s",
+            "smoothed forecast, dew point temp."
+        ],
+        "500376": [
+            "u_10m_s",
+            "smoothed forecast, u comp. of wind"
+        ],
+        "500377": [
+            "v_10m_s",
+            "smoothed forecast, v comp. of wind"
+        ],
+        "500378": [
+            "tot_prec_s",
+            "smoothed forecast, total precipitation rate"
+        ],
+        "500379": [
+            "clct_s",
+            "smoothed forecast, total cloud cover"
+        ],
+        "500380": [
+            "clcl_s",
+            "smoothed forecast, cloud cover low"
+        ],
+        "500381": [
+            "clcm_s",
+            "smoothed forecast, cloud cover medium"
+        ],
+        "500382": [
+            "clch_s",
+            "smoothed forecast, cloud cover high"
+        ],
+        "500383": [
+            "snow_gsp_s",
+            "smoothed forecast, large-scale snowfall rate w.e."
+        ],
+        "500384": [
+            "t_s_s",
+            "smoothed forecast, soil temperature"
+        ],
+        "500385": [
+            "vmax_10m_s",
+            "smoothed forecast, wind speed (gust)"
+        ],
+        "500386": [
+            "tot_prec_c",
+            "calibrated forecast, total precipitation rate"
+        ],
+        "500387": [
+            "snow_gsp_c",
+            "calibrated forecast, large-scale snowfall rate w.e."
+        ],
+        "500388": [
+            "vmax_10m_c",
+            "calibrated forecast, wind speed (gust)"
+        ],
+        "500389": [
+            "obsmsg_alb_hrv",
+            "obser. sat. meteosat sec. generation albedo (scaled)"
+        ],
+        "500390": [
+            "obsmsg_alb_nir1.6",
+            "obser. sat. meteosat sec. generation albedo (scaled)"
+        ],
+        "500391": [
+            "obsmsg_alb_vis0.6",
+            "obser. sat. meteosat sec. generation albedo (scaled)"
+        ],
+        "500392": [
+            "obsmsg_alb_vis0.8",
+            "obser. sat. meteosat sec. generation albedo (scaled)"
+        ],
+        "500393": [
+            "obsmsg_bt_ir10.8",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500394": [
+            "obsmsg_bt_ir12.0",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500395": [
+            "obsmsg_bt_ir13.4",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500396": [
+            "obsmsg_bt_ir3.9",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500397": [
+            "obsmsg_bt_ir8.7",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500398": [
+            "obsmsg_bt_ir9.7",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500399": [
+            "obsmsg_bt_wv6.2",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "500400": [
+            "obsmsg_bt_wv7.3",
+            "obser. sat. meteosat sec. generation brightness temperature"
+        ],
+        "51": [
+            "mx2t24",
+            "maximum temperature at 2 metres in the last 24 hours"
+        ],
+        "52": [
+            "mn2t24",
+            "minimum temperature at 2 metres in the last 24 hours"
+        ],
+        "53": [
+            "mont",
+            "montgomery potential"
+        ],
+        "54": [
+            "pres",
+            "pressure"
+        ],
+        "55": [
+            "mean2t24",
+            "mean temperature at 2 metres in the last 24 hours"
+        ],
+        "56": [
+            "mn2d24",
+            "mean 2 metre dewpoint temperature in the last 24 hours"
+        ],
+        "57": [
+            "uvb",
+            "downward uv radiation at the surface"
+        ],
+        "58": [
+            "par",
+            "photosynthetically active radiation at the surface"
+        ],
+        "59": [
+            "cape",
+            "convective available potential energy"
+        ],
+        "6": [
+            "ssfr",
+            "soil sand fraction"
+        ],
+        "60": [
+            "pv",
+            "potential vorticity"
+        ],
+        "62": [
+            "obct",
+            "observation count"
+        ],
+        "63": [
+            "stsktd",
+            "start time for skin temperature difference"
+        ],
+        "64": [
+            "ftsktd",
+            "finish time for skin temperature difference"
+        ],
+        "65": [
+            "sktd",
+            "skin temperature difference"
+        ],
+        "66": [
+            "lai_lv",
+            "leaf area index, low vegetation",
+            "lailv"
+        ],
+        "67": [
+            "lai_hv",
+            "leaf area index, high vegetation",
+            "laihv"
+        ],
+        "68": [
+            "msr_lv",
+            "minimum stomatal resistance, low vegetation"
+        ],
+        "69": [
+            "msr_hv",
+            "minimum stomatal resistance, high vegetation"
+        ],
+        "7": [
+            "scfr",
+            "soil clay fraction"
+        ],
+        "70": [
+            "bc_lv",
+            "biome cover, low vegetation"
+        ],
+        "7001292": [
+            "sunsd",
+            "sunshine duration"
+        ],
+        "7001293": [
+            "icsev",
+            "icing severity"
+        ],
+        "7001353": [
+            "vrate",
+            "ventilation rate"
+        ],
+        "71": [
+            "bc_hv",
+            "biome cover, high vegetation"
+        ],
+        "72": [
+            "issrd",
+            "instantaneous surface solar radiation downwards"
+        ],
+        "73": [
+            "istrd",
+            "instantaneous surface thermal radiation downwards"
+        ],
+        "74": [
+            "sdfor",
+            "standard deviation of filtered subgrid orography"
+        ],
+        "75": [
+            "crwc",
+            "specific rain water content"
+        ],
+        "76": [
+            "cswc",
+            "specific snow water content"
+        ],
+        "77": [
+            "etadot",
+            "eta-coordinate vertical velocity",
+            "etad"
+        ],
+        "78": [
+            "tclw",
+            "total column liquid water"
+        ],
+        "79": [
+            "tciw",
+            "total column ice water"
+        ],
+        "8": [
+            "sro",
+            "surface runoff"
+        ],
+        "85001156": [
+            "prec_convec",
+            "total convective precipitation"
+        ],
+        "85001157": [
+            "prec_gde_ech",
+            "total large scale precipitation"
+        ],
+        "85001160": [
+            "cape_ins",
+            "convective available potential energy instantaneous"
+        ],
+        "9": [
+            "ssro",
+            "sub-surface runoff"
+        ],
+        "928": [
+            "thk",
+            "thicknes"
+        ],
+        "956": [
+            "thka",
+            "thicknes anomaly"
+        ],
+        "999": [
+            "tc",
+            "tropical cyclone"
+        ]
+    },
+    "parameters": [
+        [
+            {
+                "file": "bin",
+                "repres": "np"
+            },
+            [
+                "167",
+                "166",
+                "164",
+                "156",
+                "129",
+                "130",
+                "135",
+                "157",
+                "131",
+                "132",
+                "133",
+                "152",
+                "228",
+                "151",
+                "3025",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "efhs",
+                "type": "em"
+            },
+            [
+                "129",
+                "130",
+                "156",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "efhs",
+                "type": "es"
+            },
+            [
+                "129",
+                "130",
+                "156",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "efhs",
+                "type": "taem"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "172142",
+                "172143",
+                "172144",
+                "172189",
+                "172228",
+                "2",
+                "201",
+                "202",
+                "228246",
+                "228247",
+                "33",
+                "34",
+                "59",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "efhs",
+                "type": "taes"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "172142",
+                "172143",
+                "172144",
+                "172189",
+                "172228",
+                "2",
+                "201",
+                "202",
+                "228246",
+                "228247",
+                "33",
+                "34",
+                "59",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "efov",
+                "type": [
+                    "cf",
+                    "pf",
+                    "wp",
+                    "cv"
+                ]
+            },
+            [
+                "121",
+                "122",
+                "123",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "134",
+                "135",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "142",
+                "143",
+                "144",
+                "146",
+                "147",
+                "151",
+                "151131",
+                "151132",
+                "155",
+                "156",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172",
+                "173",
+                "175",
+                "176",
+                "177",
+                "179",
+                "180",
+                "181",
+                "182",
+                "183",
+                "189",
+                "201",
+                "202",
+                "205",
+                "228",
+                "228001",
+                "228008",
+                "228009",
+                "228010",
+                "228011",
+                "228012",
+                "228013",
+                "228014",
+                "228021",
+                "228022",
+                "228023",
+                "228024",
+                "228029",
+                "228044",
+                "228046",
+                "228047",
+                "228048",
+                "228089",
+                "228090",
+                "228224",
+                "228225",
+                "228226",
+                "228227",
+                "228246",
+                "228247",
+                "228251",
+                "230008",
+                "230009",
+                "230021",
+                "230022",
+                "230047",
+                "230057",
+                "230080",
+                "230081",
+                "230082",
+                "230142",
+                "230143",
+                "230144",
+                "230145",
+                "230146",
+                "230147",
+                "230169",
+                "230175",
+                "230176",
+                "230177",
+                "230178",
+                "230179",
+                "230180",
+                "230181",
+                "230182",
+                "230189",
+                "230195",
+                "230196",
+                "230197",
+                "230205",
+                "230210",
+                "230216",
+                "230228",
+                "230251",
+                "235",
+                "236",
+                "260109",
+                "260121",
+                "260123",
+                "3",
+                "3020",
+                "31",
+                "32",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "43",
+                "47",
+                "49",
+                "57",
+                "59",
+                "60",
+                "78",
+                "79",
+                "8",
+                "9",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "ehmm",
+                "type": "em"
+            },
+            [
+                "171034",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171151",
+                "171156",
+                "171167",
+                "171228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfh",
+                "type": [
+                    "cf",
+                    "pf",
+                    "wp",
+                    "cv"
+                ]
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "123",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "134",
+                "135",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "142",
+                "143",
+                "144",
+                "146",
+                "147",
+                "151",
+                "151131",
+                "151132",
+                "152",
+                "155",
+                "156",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172",
+                "173",
+                "174",
+                "175",
+                "176",
+                "177",
+                "178",
+                "179",
+                "180",
+                "181",
+                "182",
+                "183",
+                "189",
+                "2",
+                "201",
+                "202",
+                "205",
+                "228",
+                "228001",
+                "228008",
+                "228009",
+                "228010",
+                "228011",
+                "228012",
+                "228013",
+                "228014",
+                "228021",
+                "228029",
+                "228044",
+                "228046",
+                "228047",
+                "228048",
+                "228080",
+                "228081",
+                "228082",
+                "228224",
+                "228225",
+                "228226",
+                "228227",
+                "228246",
+                "228247",
+                "228251",
+                "235",
+                "236",
+                "246",
+                "247",
+                "248",
+                "260109",
+                "260121",
+                "260123",
+                "3",
+                "3020",
+                "31",
+                "32",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "43",
+                "47",
+                "49",
+                "57",
+                "59",
+                "60",
+                "75",
+                "76",
+                "78",
+                "79",
+                "8",
+                "9",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfh",
+                "type": "fcmax"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "enfh",
+                "type": "fcmean"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "151",
+                "155",
+                "156",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "2",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "3",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "60",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfh",
+                "type": "fcmin"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59"
+            ]
+        ],
+        [
+            {
+                "stream": "enfh",
+                "type": "fcstdev"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": [
+                    "cf",
+                    "pf",
+                    "wp",
+                    "cv"
+                ]
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "123",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "134",
+                "135",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "142",
+                "143",
+                "144",
+                "145",
+                "146",
+                "147",
+                "148",
+                "151",
+                "151131",
+                "151132",
+                "152",
+                "155",
+                "156",
+                "157",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172",
+                "173",
+                "174",
+                "175",
+                "176",
+                "177",
+                "178",
+                "179",
+                "180",
+                "181",
+                "182",
+                "183",
+                "186",
+                "187",
+                "188",
+                "189",
+                "195",
+                "196",
+                "197",
+                "198",
+                "2",
+                "201",
+                "202",
+                "203",
+                "205",
+                "206",
+                "210",
+                "228",
+                "228001",
+                "228008",
+                "228009",
+                "228010",
+                "228011",
+                "228012",
+                "228013",
+                "228014",
+                "228021",
+                "228022",
+                "228023",
+                "228024",
+                "228026",
+                "228027",
+                "228028",
+                "228029",
+                "228044",
+                "228046",
+                "228047",
+                "228048",
+                "228080",
+                "228081",
+                "228082",
+                "228083",
+                "228084",
+                "228085",
+                "228088",
+                "228089",
+                "228090",
+                "228216",
+                "228217",
+                "228218",
+                "228219",
+                "228220",
+                "228221",
+                "228222",
+                "228223",
+                "228224",
+                "228225",
+                "228226",
+                "228227",
+                "228246",
+                "228247",
+                "228251",
+                "235",
+                "236",
+                "238",
+                "243",
+                "244",
+                "245",
+                "246",
+                "247",
+                "248",
+                "260015",
+                "260109",
+                "260121",
+                "260123",
+                "27",
+                "28",
+                "29",
+                "3",
+                "30",
+                "3020",
+                "31",
+                "32",
+                "33",
+                "34",
+                "35",
+                "36",
+                "37",
+                "38",
+                "39",
+                "40",
+                "41",
+                "42",
+                "43",
+                "47",
+                "49",
+                "54",
+                "57",
+                "59",
+                "60",
+                "75",
+                "76",
+                "78",
+                "79",
+                "8",
+                "9",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "cm"
+            },
+            [
+                "129",
+                "156",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "cr"
+            },
+            [
+                "129",
+                "156",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "cs"
+            },
+            [
+                "129",
+                "130"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "efi"
+            },
+            [
+                "132044",
+                "132049",
+                "132059",
+                "132144",
+                "132165",
+                "132167",
+                "132201",
+                "132202",
+                "132228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "efic"
+            },
+            [
+                "132044",
+                "132049",
+                "132059",
+                "132144",
+                "132165",
+                "132167",
+                "132201",
+                "132202",
+                "132228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "em"
+            },
+            [
+                "10",
+                "129",
+                "130",
+                "151",
+                "156",
+                "167",
+                "207",
+                "228249",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "ep"
+            },
+            [
+                "131001",
+                "131002",
+                "131003",
+                "131004",
+                "131005",
+                "131006",
+                "131007",
+                "131008",
+                "131009",
+                "131010",
+                "131020",
+                "131021",
+                "131022",
+                "131023",
+                "131024",
+                "131025",
+                "131060",
+                "131061",
+                "131062",
+                "131063",
+                "131064",
+                "131065",
+                "131066",
+                "131067",
+                "131068",
+                "131069",
+                "131070",
+                "131071",
+                "131072",
+                "131073",
+                "131089",
+                "131090",
+                "131091"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "es"
+            },
+            [
+                "10",
+                "129",
+                "130",
+                "151",
+                "156",
+                "167",
+                "207",
+                "228249",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "fcmax"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "fcmean"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "151",
+                "155",
+                "156",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "171001",
+                "171002",
+                "171006",
+                "171007",
+                "171033",
+                "171059",
+                "171078",
+                "171079",
+                "171121",
+                "171122",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171133",
+                "171136",
+                "171137",
+                "171139",
+                "171141",
+                "171151",
+                "171156",
+                "171164",
+                "171165",
+                "171166",
+                "171167",
+                "171168",
+                "171201",
+                "171202",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "173144",
+                "173189",
+                "173228",
+                "2",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "3",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "60",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "fcmin"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "fcstdev"
+            },
+            [
+                "121",
+                "122",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "159",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172228",
+                "201",
+                "202",
+                "207",
+                "228246",
+                "228247",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "59",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "fp"
+            },
+            [
+                "131130"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "pb"
+            },
+            [
+                "171129",
+                "171139",
+                "171151",
+                "171156",
+                "171167",
+                "173228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "pd"
+            },
+            [
+                "131129",
+                "131139",
+                "131151",
+                "131167",
+                "131228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "sot"
+            },
+            [
+                "132044",
+                "132049",
+                "132059",
+                "132144",
+                "132165",
+                "132167",
+                "132201",
+                "132202",
+                "132228"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "taem"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "171001",
+                "171002",
+                "171006",
+                "171007",
+                "171033",
+                "171034",
+                "171059",
+                "171078",
+                "171079",
+                "171121",
+                "171122",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171133",
+                "171136",
+                "171137",
+                "171139",
+                "171141",
+                "171151",
+                "171156",
+                "171164",
+                "171165",
+                "171166",
+                "171167",
+                "171168",
+                "171201",
+                "171202",
+                "172142",
+                "172143",
+                "172144",
+                "172189",
+                "172228",
+                "173144",
+                "173189",
+                "173228",
+                "2",
+                "201",
+                "202",
+                "228246",
+                "228247",
+                "234139",
+                "234151",
+                "234167",
+                "234228",
+                "33",
+                "34",
+                "59",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "taes"
+            },
+            [
+                "1",
+                "121",
+                "122",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "136",
+                "137",
+                "139",
+                "141",
+                "151",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "172142",
+                "172143",
+                "172144",
+                "172189",
+                "172228",
+                "2",
+                "201",
+                "202",
+                "228246",
+                "228247",
+                "33",
+                "34",
+                "59",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "enfo",
+                "type": "tf"
+            },
+            [
+                "129",
+                "999"
+            ]
+        ],
+        [
+            {
+                "stream": "enwh",
+                "type": [
+                    "cf",
+                    "pf",
+                    "wp",
+                    "cv"
+                ]
+            },
+            [
+                "140112",
+                "140113",
+                "140114",
+                "140115",
+                "140116",
+                "140117",
+                "140118",
+                "140119",
+                "140120",
+                "140121",
+                "140122",
+                "140123",
+                "140124",
+                "140125",
+                "140126",
+                "140127",
+                "140128",
+                "140129",
+                "140207",
+                "140208",
+                "140209",
+                "140215",
+                "140216",
+                "140217",
+                "140218",
+                "140219",
+                "140220",
+                "140221",
+                "140222",
+                "140223",
+                "140224",
+                "140225",
+                "140226",
+                "140227",
+                "140228",
+                "140229",
+                "140230",
+                "140231",
+                "140232",
+                "140233",
+                "140234",
+                "140235",
+                "140236",
+                "140237",
+                "140238",
+                "140239",
+                "140244",
+                "140245",
+                "140249",
+                "140252",
+                "140253",
+                "140254"
+            ]
+        ],
+        [
+            {
+                "stream": "enwh",
+                "type": "fcmax"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "enwh",
+                "type": "fcmean"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "enwh",
+                "type": "fcmin"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "enwh",
+                "type": "fcstdev"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "esmm",
+                "type": "em"
+            },
+            [
+                "171034",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171151",
+                "171156",
+                "171167",
+                "171228"
+            ]
+        ],
+        [
+            {
+                "stream": "mmsa",
+                "type": "em"
+            },
+            [
+                "171003",
+                "171031",
+                "171033",
+                "171034",
+                "171039",
+                "171040",
+                "171041",
+                "171042",
+                "171049",
+                "171051",
+                "171052",
+                "171060",
+                "171078",
+                "171079",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171133",
+                "171137",
+                "171138",
+                "171139",
+                "171141",
+                "171151",
+                "171155",
+                "171156",
+                "171164",
+                "171165",
+                "171166",
+                "171167",
+                "171168",
+                "171169",
+                "171170",
+                "171183",
+                "171186",
+                "171203",
+                "171206",
+                "171207",
+                "171236",
+                "171243",
+                "173142",
+                "173143",
+                "173144",
+                "173146",
+                "173147",
+                "173169",
+                "173175",
+                "173176",
+                "173177",
+                "173178",
+                "173179",
+                "173180",
+                "173181",
+                "173182",
+                "173189",
+                "173205",
+                "173228",
+                "175006",
+                "175167"
+            ]
+        ],
+        [
+            {
+                "stream": "mmsa",
+                "type": "fcmean"
+            },
+            [
+                "171003",
+                "171031",
+                "171033",
+                "171034",
+                "171039",
+                "171040",
+                "171041",
+                "171042",
+                "171049",
+                "171051",
+                "171052",
+                "171060",
+                "171078",
+                "171079",
+                "171129",
+                "171130",
+                "171131",
+                "171132",
+                "171133",
+                "171137",
+                "171138",
+                "171139",
+                "171141",
+                "171151",
+                "171155",
+                "171156",
+                "171164",
+                "171165",
+                "171166",
+                "171167",
+                "171168",
+                "171169",
+                "171170",
+                "171183",
+                "171186",
+                "171203",
+                "171206",
+                "171207",
+                "171236",
+                "171243",
+                "173142",
+                "173143",
+                "173144",
+                "173146",
+                "173147",
+                "173169",
+                "173175",
+                "173176",
+                "173177",
+                "173178",
+                "173179",
+                "173180",
+                "173181",
+                "173182",
+                "173189",
+                "173205",
+                "173228",
+                "175006",
+                "175167"
+            ]
+        ],
+        [
+            {
+                "stream": "mmsf",
+                "type": [
+                    "an",
+                    "fc",
+                    "wp"
+                ]
+            },
+            [
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "137",
+                "138",
+                "139",
+                "141",
+                "142",
+                "143",
+                "144",
+                "146",
+                "147",
+                "151",
+                "152",
+                "155",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172",
+                "174006",
+                "175",
+                "176",
+                "177",
+                "178",
+                "179",
+                "180",
+                "181",
+                "182",
+                "183",
+                "186",
+                "189",
+                "201",
+                "202",
+                "203",
+                "205",
+                "206",
+                "228",
+                "236",
+                "243",
+                "246",
+                "247",
+                "3",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "55",
+                "60",
+                "78",
+                "79",
+                "8",
+                "9",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "mnfc",
+                "type": [
+                    "an",
+                    "fc",
+                    "wp"
+                ]
+            },
+            [
+                "129",
+                "151",
+                "2",
+                "228"
+            ]
+        ],
+        [
+            {
+                "stream": "msmm",
+                "type": "em"
+            },
+            [
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "137",
+                "138",
+                "139",
+                "141",
+                "151",
+                "155",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172205",
+                "172228",
+                "174006",
+                "174167",
+                "183",
+                "186",
+                "203",
+                "206",
+                "207",
+                "236",
+                "243",
+                "3",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "60",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "msmm",
+                "type": "fcmax"
+            },
+            [
+                "137",
+                "139",
+                "141",
+                "151",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172008",
+                "172009",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172205",
+                "172228",
+                "174006",
+                "183",
+                "186",
+                "206",
+                "207",
+                "236",
+                "243",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "msmm",
+                "type": "fcmean"
+            },
+            [
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "137",
+                "138",
+                "139",
+                "141",
+                "151",
+                "151129",
+                "155",
+                "156",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "170",
+                "172",
+                "172008",
+                "172009",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172205",
+                "172228",
+                "174006",
+                "174096",
+                "174167",
+                "183",
+                "186",
+                "203",
+                "206",
+                "207",
+                "236",
+                "243",
+                "3",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "60",
+                "78",
+                "79",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": "msmm",
+                "type": "fcmin"
+            },
+            [
+                "137",
+                "139",
+                "141",
+                "151",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172008",
+                "172009",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172205",
+                "174006",
+                "183",
+                "186",
+                "206",
+                "207",
+                "236",
+                "243",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": "msmm",
+                "type": "fcstdev"
+            },
+            [
+                "137",
+                "139",
+                "141",
+                "151",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "170",
+                "172008",
+                "172009",
+                "172142",
+                "172143",
+                "172144",
+                "172146",
+                "172147",
+                "172169",
+                "172175",
+                "172176",
+                "172177",
+                "172178",
+                "172179",
+                "172180",
+                "172181",
+                "172182",
+                "172189",
+                "172205",
+                "172228",
+                "174006",
+                "183",
+                "186",
+                "206",
+                "207",
+                "236",
+                "243",
+                "31",
+                "33",
+                "34",
+                "39",
+                "40",
+                "41",
+                "42",
+                "49",
+                "51",
+                "52",
+                "78",
+                "79"
+            ]
+        ],
+        [
+            {
+                "stream": [
+                    "oper",
+                    "scda"
+                ],
+                "type": [
+                    "an",
+                    "fc",
+                    "wp"
+                ]
+            },
+            [
+                "121",
+                "122",
+                "123",
+                "129",
+                "130",
+                "131",
+                "132",
+                "133",
+                "134",
+                "135",
+                "136",
+                "137",
+                "138",
+                "139",
+                "141",
+                "142",
+                "143",
+                "144",
+                "145",
+                "146",
+                "147",
+                "148",
+                "15",
+                "151",
+                "152",
+                "155",
+                "156",
+                "157",
+                "159",
+                "16",
+                "160",
+                "161",
+                "162",
+                "163",
+                "164",
+                "165",
+                "166",
+                "167",
+                "168",
+                "169",
+                "17",
+                "170",
+                "172",
+                "173",
+                "174",
+                "175",
+                "176",
+                "177",
+                "178",
+                "179",
+                "18",
+                "180",
+                "181",
+                "182",
+                "183",
+                "186",
+                "187",
+                "188",
+                "189",
+                "195",
+                "196",
+                "197",
+                "198",
+                "20",
+                "201",
+                "202",
+                "203",
+                "205",
+                "206",
+                "208",
+                "209",
+                "210",
+                "211",
+                "212",
+                "213",
+                "228",
+                "228001",
+                "228003",
+                "228007",
+                "228008",
+                "228009",
+                "228010",
+                "228011",
+                "228012",
+                "228013",
+                "228014",
+                "228021",
+                "228022",
+                "228023",
+                "228024",
+                "228026",
+                "228027",
+                "228028",
+                "228029",
+                "228044",
+                "228046",
+                "228047",
+                "228048",
+                "228080",
+                "228081",
+                "228082",
+                "228083",
+                "228084",
+                "228085",
+                "228088",
+                "228089",
+                "228090",
+                "228131",
+                "228132",
+                "228216",
+                "228217",
+                "228218",
+                "228219",
+                "228220",
+                "228221",
+                "228222",
+                "228223",
+                "228224",
+                "228225",
+                "228226",
+                "228227",
+                "228246",
+                "228247",
+                "228251",
+                "229",
+                "230",
+                "231",
+                "232",
+                "234",
+                "235",
+                "236",
+                "238",
+                "243",
+                "244",
+                "245",
+                "246",
+                "247",
+                "248",
+                "26",
+                "260015",
+                "260109",
+                "260121",
+                "260123",
+                "27",
+                "28",
+                "29",
+                "3",
+                "30",
+                "3020",
+                "3041",
+                "31",
+                "32",
+                "33",
+                "34",
+                "35",
+                "36",
+                "37",
+                "38",
+                "39",
+                "40",
+                "41",
+                "42",
+                "43",
+                "44",
+                "45",
+                "47",
+                "49",
+                "50",
+                "53",
+                "54",
+                "57",
+                "58",
+                "59",
+                "60",
+                "66",
+                "67",
+                "74",
+                "75",
+                "76",
+                "77",
+                "78",
+                "79",
+                "8",
+                "9",
+                "928"
+            ]
+        ],
+        [
+            {
+                "stream": [
+                    "oper",
+                    "scda"
+                ],
+                "type": "ssd"
+            },
+            [
+                "260510"
+            ]
+        ],
+        [
+            {
+                "stream": [
+                    "oper",
+                    "scda"
+                ],
+                "type": "tf"
+            },
+            [
+                "129",
+                "999"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": [
+                    "cf",
+                    "pf",
+                    "wp",
+                    "cv"
+                ]
+            },
+            [
+                "140112",
+                "140113",
+                "140114",
+                "140115",
+                "140116",
+                "140117",
+                "140118",
+                "140119",
+                "140120",
+                "140121",
+                "140122",
+                "140123",
+                "140124",
+                "140125",
+                "140126",
+                "140127",
+                "140128",
+                "140129",
+                "140207",
+                "140208",
+                "140209",
+                "140211",
+                "140212",
+                "140214",
+                "140215",
+                "140216",
+                "140217",
+                "140218",
+                "140219",
+                "140220",
+                "140221",
+                "140222",
+                "140223",
+                "140224",
+                "140225",
+                "140226",
+                "140227",
+                "140228",
+                "140229",
+                "140230",
+                "140231",
+                "140232",
+                "140233",
+                "140234",
+                "140235",
+                "140236",
+                "140237",
+                "140238",
+                "140239",
+                "140244",
+                "140245",
+                "140249",
+                "140251",
+                "140252",
+                "140253",
+                "140254"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "efi"
+            },
+            [
+                "132216"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "efic"
+            },
+            [
+                "132216"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "ep"
+            },
+            [
+                "131074",
+                "131075",
+                "131076",
+                "131077",
+                "131078",
+                "131079",
+                "131080",
+                "131081"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "fcmax"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "fcmean"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "fcmin"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "fcstdev"
+            },
+            [
+                "140229",
+                "140231",
+                "140232",
+                "140233",
+                "140245"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "fp"
+            },
+            [
+                "131229",
+                "131232"
+            ]
+        ],
+        [
+            {
+                "stream": "waef",
+                "type": "sot"
+            },
+            [
+                "132216"
+            ]
+        ],
+        [
+            {
+                "stream": [
+                    "wave",
+                    "scwv"
+                ],
+                "type": [
+                    "an",
+                    "fc",
+                    "wp"
+                ]
+            },
+            [
+                "140112",
+                "140113",
+                "140114",
+                "140115",
+                "140116",
+                "140117",
+                "140118",
+                "140119",
+                "140120",
+                "140121",
+                "140122",
+                "140123",
+                "140124",
+                "140125",
+                "140126",
+                "140127",
+                "140128",
+                "140129",
+                "140207",
+                "140208",
+                "140209",
+                "140211",
+                "140212",
+                "140214",
+                "140215",
+                "140216",
+                "140217",
+                "140218",
+                "140219",
+                "140220",
+                "140221",
+                "140222",
+                "140223",
+                "140224",
+                "140225",
+                "140226",
+                "140227",
+                "140228",
+                "140229",
+                "140230",
+                "140231",
+                "140232",
+                "140233",
+                "140234",
+                "140235",
+                "140236",
+                "140237",
+                "140238",
+                "140239",
+                "140244",
+                "140245",
+                "140246",
+                "140247",
+                "140248",
+                "140249",
+                "140251",
+                "140252",
+                "140253",
+                "140254",
+                "151131",
+                "151132"
+            ]
+        ]
     ]
-]
+}
diff --git a/metkit/metkit.sublime-project b/metkit/metkit.sublime-project
index 977875e..e6d4f35 100644
--- a/metkit/metkit.sublime-project
+++ b/metkit/metkit.sublime-project
@@ -6,16 +6,37 @@
             "follow_symlinks": true
         }
     ],
-    "build_systems": [
+   "build_systems":
+    [
         {
-            "working_dir": "${project_path}/../../build/metkit",
-            "cmd": [
-                "make"
-            ],
             "file_regex": "([/\\w\\-\\.]+):(\\d+):(\\d+:)?",
-            "name": "ecbuild"
-        }
+            "name": "metkit",
+            "shell_cmd": "make",
+            "syntax": "Packages/CMakeBuilder/Syntax/Make.sublime-syntax",
+            "working_dir": "${project_path}/../../build/metkit",
+            "variants" : [
+                {
+                    "name":"clean",
+                    "shell_cmd": "make clean",
+                }
+            ]
+        },
+        {
+            "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
+            "name": "Anaconda Python Builder",
+            "selector": "source.python",
+            "shell_cmd": "\"python\" -u \"$file\""
+        },
+
     ],
+    "cmake":
+    {
+        "build_folder": "${project_path}/../../build/metkit",
+        "command_line_overrides":
+        {
+            "DEVELOPER_MODE": 1
+        }
+    },
     "SublimeLinter":
     {
         "linters":
diff --git a/metkit/src/metkit/MarsLanguage.cc b/metkit/src/metkit/MarsLanguage.cc
index 17833fe..8835833 100644
--- a/metkit/src/metkit/MarsLanguage.cc
+++ b/metkit/src/metkit/MarsLanguage.cc
@@ -55,7 +55,6 @@ static void init() {
 }
 
 
-
 namespace metkit {
 
 MarsLanguage::MarsLanguage(const std::string& verb):
@@ -111,17 +110,31 @@ eckit::Value MarsLanguage::jsonFile(const std::string& name) {
     return parser.parse();
 }
 
+static bool isnumber(const std::string& s) {
+    for (size_t i = 0; i < s.length(); i++) {
+        if (!::isdigit(s[i])) {
+            return false;
+        }
+    }
+
+    return s.length() > 0;
+}
+
 std::string MarsLanguage::bestMatch(const std::string& name,
                                     const std::vector<std::string>& values,
                                     bool fail,
-                                    const std::map<std::string, std::string>& aliases) {
+                                    bool quiet,
+                                    const std::map<std::string, std::string>& aliases,
+                                    const ExpandContext* ctx) {
 
-    size_t score = 0;
+    size_t score = 1;
     std::vector<std::string> best;
 
     for (size_t i = 0; i < values.size(); ++i) {
         const std::string& value = values[i];
 
+        // std::cout << name << " " << value << " " << dist << std::endl;
+
         size_t len = std::min(name.length(), value.length());
         size_t s = 0;
 
@@ -141,7 +154,7 @@ std::string MarsLanguage::bestMatch(const std::string& name,
             return value;
         }
 
-        if (s > 0 && s >= score) {
+        if (s >= score) {
             if (s > score) {
                 best.clear();
             }
@@ -150,19 +163,42 @@ std::string MarsLanguage::bestMatch(const std::string& name,
         }
     }
 
-    size_t max = 3;
-    if (best.size() > 0 && score < max) {
+    if (!quiet && best.size() > 0) {
         std::cerr << "Matching '"
                   << name
                   << "' with "
                   << best
-                  << " "
-                  << "Please give at least " << max << " first letters"
-                  << std::endl;
+                  ;
+        if (ctx) {
+            std::cerr << " ";
+            ctx->print(std::cerr);
+        }
+        std::cerr << std::endl;
     }
 
+    // size_t max = 3;
+    // if (best.size() > 0 && score < max) {
+    //     std::cerr << "Matching '"
+    //               << name
+    //               << "' with "
+    //               << best
+    //               << " "
+    //               << "Please give at least " << max << " first letters"
+    //               << std::endl;
+    // }
 
     if (best.size() == 1) {
+
+        if (isnumber(name) && isnumber(best[0])) {
+            std::ostringstream oss;
+            oss << "Cannot match '" << name << "' and " << best[0];
+            if (ctx) {
+                oss << " ";
+                ctx->print(oss);
+            }
+            throw eckit::UserError(oss.str());
+        }
+
         if (aliases.find(best[0]) != aliases.end()) {
             return aliases.find(best[0])->second;
         }
@@ -178,6 +214,10 @@ std::string MarsLanguage::bestMatch(const std::string& name,
 
         std::ostringstream oss;
         oss << "Cannot match '" << name << "' in " << values;
+        if (ctx) {
+            oss << " ";
+            ctx->print(oss);
+        }
         throw eckit::UserError(oss.str());
     }
 
@@ -196,8 +236,27 @@ std::string MarsLanguage::bestMatch(const std::string& name,
         return best[0];
     }
 
+
     std::ostringstream oss;
-    oss << "Ambiguous value '" << name << "' could be " << best;
+    oss << "Ambiguous value '" << name << "' could be";
+
+    for (std::vector<std::string>::const_iterator j = best.begin(); j != best.end(); ++j) {
+        std::map<std::string, std::string>::const_iterator k = aliases.find(*j);
+        if (k == aliases.end()) {
+            oss << " '" << *j << "'";
+        }
+        else {
+            oss << " '" << *j << "' (";
+            oss << (*k).second;
+            oss << ")";
+        }
+    }
+    if (ctx) {
+        oss << " ";
+        ctx->print(oss);
+    }
+
+
     throw eckit::UserError(oss.str());
 }
 
@@ -209,7 +268,7 @@ std::string MarsLanguage::expandVerb(const std::string& verb) {
     // }
 
     // return cache_[verb] = bestMatch(verb, verbs_, true);
-    return bestMatch(verb, verbs_, true);
+    return bestMatch(verb, verbs_, true, true);
 }
 
 Type* MarsLanguage::type(const std::string& name) const {
@@ -226,74 +285,80 @@ MarsRequest MarsLanguage::expand(const MarsRequest& r, bool inherit)  {
 
     MarsRequest result(verb_);
 
-    std::vector<std::string> params = r.params();
-    std::set<std::string> seen;
+    try {
 
-    for (std::vector<std::string>::iterator j = params.begin(); j != params.end(); ++j) {
-        std::string p;
+        std::vector<std::string> params = r.params();
+        std::set<std::string> seen;
 
+        for (std::vector<std::string>::iterator j = params.begin(); j != params.end(); ++j) {
+            std::string p;
 
-        std::map<std::string, std::string>::iterator c = cache_.find(*j);
-        if (c != cache_.end()) {
-            p = (*c).second;
-        } else {
-            p =  cache_[*j] = bestMatch(*j, keywords_, true, aliases_);
-        }
 
-        // if (seen.find(p) != seen.end()) {
-        //     std::cout << "Duplicate " << p << " " << *j << std::endl;
-        //     std::cout << r << std::endl;
-        //     if (result.countValues(p)) {
-        //         std::cout << result.values(p) << std::endl;
-        //     }
-        //     else {
-        //         std::cout << "off" << std::endl;
-        //     }
-        //     std::cout << r.values(*j) << std::endl;
-        // }
-
-        // seen.insert(p);
-
-        std::vector<std::string> values = r.values(*j);
-
-        if (values.size() == 1) {
-            const std::string& s = values[0];
-            if (s == "off" || s == "OFF") {
-                result.unsetValues(p);
-                type(p)->clearDefaults();
-                continue;
+            std::map<std::string, std::string>::iterator c = cache_.find(*j);
+            if (c != cache_.end()) {
+                p = (*c).second;
+            } else {
+                p =  cache_[*j] = bestMatch(*j, keywords_, true, false, aliases_);
             }
-        }
 
-        type(p)->expand(values);
-        result.setValuesTyped(type(p), values);
+            // if (seen.find(p) != seen.end()) {
+            //     std::cerr << "Duplicate " << p << " " << *j << std::endl;
+            // }
 
-        // result.setValues(p, values);
+            // seen.insert(p);
 
-    }
+            std::vector<std::string> values = r.values(*j);
+
+            if (values.size() == 1) {
+                const std::string& s = values[0];
+                if (s == "off" || s == "OFF") {
+                    result.unsetValues(p);
+                    type(p)->clearDefaults();
+                    continue;
+                }
+            }
+
+            type(p)->expand(values);
+            result.setValuesTyped(type(p), values);
+            type(p)->check(values);
+            // result.setValues(p, values);
+
+        }
 
 
 
-    if (inherit) {
-        for (std::map<std::string, Type*>::iterator k = types_.begin(); k != types_.end(); ++k) {
-            const std::string& name = (*k).first;
-            if (result.countValues(name) == 0) {
-                (*k).second->setDefaults(result);
+        if (inherit) {
+            for (std::map<std::string, Type*>::iterator k = types_.begin(); k != types_.end(); ++k) {
+                const std::string& name = (*k).first;
+                if (result.countValues(name) == 0) {
+                    (*k).second->setDefaults(result);
+                }
+            }
+
+            result.getParams(params);
+            for (std::vector<std::string>::const_iterator k = params.begin(); k != params.end(); ++k) {
+                type(*k)->setDefaults(result.values(*k));
             }
         }
 
         result.getParams(params);
+
         for (std::vector<std::string>::const_iterator k = params.begin(); k != params.end(); ++k) {
-            type(*k)->setDefaults(result.values(*k));
+            type(*k)->pass2(result);
         }
-    }
 
-    result.getParams(params);
-    for (std::vector<std::string>::const_iterator k = params.begin(); k != params.end(); ++k) {
-        type(*k)->finalise(result);
-    }
+        for (std::vector<std::string>::const_iterator k = params.begin(); k != params.end(); ++k) {
+            type(*k)->finalise(result);
+        }
 
+    }
+    catch (Exception& e) {
+        std::ostringstream oss;
+        oss << e.what() << " request=" << r << ", expanded=" << result;
+        throw eckit::UserError(oss.str());
+    }
     return result;
+
 }
 
 
diff --git a/metkit/src/metkit/MarsLanguage.h b/metkit/src/metkit/MarsLanguage.h
index 7dacd59..52cd47a 100644
--- a/metkit/src/metkit/MarsLanguage.h
+++ b/metkit/src/metkit/MarsLanguage.h
@@ -28,6 +28,12 @@ class FlattenCallback;
 
 //----------------------------------------------------------------------------------------------------------------------
 
+class ExpandContext {
+public:
+    virtual void print(std::ostream&) const = 0;
+};
+
+
 class MarsLanguage : private eckit::NonCopyable {
     typedef std::map<std::string, std::string> StringMap;
 
@@ -52,7 +58,9 @@ public:
     static std::string bestMatch(const std::string& what,
                                  const std::vector<std::string>& values,
                                  bool fail,
-                                 const StringMap& aliases = StringMap());
+                                 bool quiet,
+                                 const StringMap& aliases = StringMap(),
+                                 const ExpandContext* = 0);
 
     static eckit::Value jsonFile(const std::string& name);
 
diff --git a/metkit/src/metkit/MarsParser.h b/metkit/src/metkit/MarsParser.h
index e727d00..3cafc98 100644
--- a/metkit/src/metkit/MarsParser.h
+++ b/metkit/src/metkit/MarsParser.h
@@ -11,8 +11,8 @@
 /// @author Baudouin Raoult
 /// @date Jun 2012
 
-#ifndef eckit_JSONParser_h
-#define eckit_JSONParser_h
+#ifndef metkit_MARSParser_h
+#define metkit_MARSParser_h
 
 #include "eckit/parser/StreamParser.h"
 #include "eckit/types/Types.h"
diff --git a/metkit/src/metkit/MarsRequest.h b/metkit/src/metkit/MarsRequest.h
index 91938c8..b3258af 100644
--- a/metkit/src/metkit/MarsRequest.h
+++ b/metkit/src/metkit/MarsRequest.h
@@ -21,6 +21,7 @@
 #include "eckit/types/Double.h"
 #include "eckit/types/Time.h"
 #include "eckit/value/Value.h"
+#include "eckit/utils/Translator.h"
 
 namespace eckit {
 class JSON;
@@ -108,6 +109,21 @@ public: // methods
 
     const std::vector<std::string> &values(const std::string&, bool emptyOk = false) const;
 
+
+    template<class T>
+    void getValues(const std::string& name, std::vector<T>& v) const {
+        const std::vector< std::string >& s = values(name);
+
+        eckit::Translator<std::string, T> t;
+
+        v.clear();
+
+        for (std::vector<std::string>::const_iterator j = s.begin(); j != s.end(); ++j) {
+            v.push_back(t(*j));
+        }
+    }
+
+
     void getParams(std::vector<std::string>&) const;
     std::vector<std::string> params() const;
 
diff --git a/metkit/src/metkit/config/LibMetkit.cc b/metkit/src/metkit/config/LibMetkit.cc
index 5728caa..3da390a 100644
--- a/metkit/src/metkit/config/LibMetkit.cc
+++ b/metkit/src/metkit/config/LibMetkit.cc
@@ -24,12 +24,12 @@ namespace metkit {
 
 //----------------------------------------------------------------------------------------------------------------------
 
-static LibMetkit libmetkit;
+REGISTER_LIBRARY(LibMetkit);
 
 LibMetkit::LibMetkit() : Library("metkit") {}
 
-const LibMetkit& LibMetkit::instance()
-{
+const LibMetkit& LibMetkit::instance() {
+    static LibMetkit libmetkit;
     return libmetkit;
 }
 
diff --git a/metkit/src/metkit/types/Type.cc b/metkit/src/metkit/types/Type.cc
index 07dcc12..669d20b 100644
--- a/metkit/src/metkit/types/Type.cc
+++ b/metkit/src/metkit/types/Type.cc
@@ -195,6 +195,9 @@ const std::string& Type::name() const {
     return name_;
 }
 
+void Type::pass2(MarsRequest& request) {
+}
+
 void Type::finalise(MarsRequest& request) {
     bool ok = true;
 
@@ -237,6 +240,15 @@ void Type::finalise(MarsRequest& request) {
 
 }
 
+void Type::check(const std::vector<std::string>& values) const {
+    if (flatten_) {
+        std::set<std::string> s(values.begin(), values.end());
+        if (values.size() != s.size()) {
+            std::cerr << "Duplicate values in " << values << std::endl;
+        }
+    }
+}
+
 
 //----------------------------------------------------------------------------------------------------------------------
 
diff --git a/metkit/src/metkit/types/Type.h b/metkit/src/metkit/types/Type.h
index 23de94c..e4b152a 100644
--- a/metkit/src/metkit/types/Type.h
+++ b/metkit/src/metkit/types/Type.h
@@ -41,9 +41,11 @@ public: // methods
     virtual void expand(std::vector<std::string>& values) const;
     virtual void setDefaults(MarsRequest& request);
     virtual void setDefaults(const std::vector<std::string>& defaults);
+    virtual void check(const std::vector<std::string>& values) const;
     virtual void clearDefaults();
     virtual void reset();
 
+    virtual void pass2(MarsRequest& request);
     virtual void finalise(MarsRequest& request);
 
     virtual const std::vector<std::string>& flattenValues(const MarsRequest& request);
diff --git a/metkit/src/metkit/types/TypeEnum.cc b/metkit/src/metkit/types/TypeEnum.cc
index 5f13ab4..abec9c0 100644
--- a/metkit/src/metkit/types/TypeEnum.cc
+++ b/metkit/src/metkit/types/TypeEnum.cc
@@ -91,7 +91,7 @@ bool TypeEnum::expand(std::vector<std::string>& values, bool fail) const {
             continue;
         }
 
-        std::string v = MarsLanguage::bestMatch((*j), values_, fail, mapping_);
+        std::string v = MarsLanguage::bestMatch((*j), values_, fail, false, mapping_);
         if (v.empty()) {
             return false;
         }
diff --git a/metkit/src/metkit/types/TypeParam.cc b/metkit/src/metkit/types/TypeParam.cc
index 7fc38e3..0131c71 100644
--- a/metkit/src/metkit/types/TypeParam.cc
+++ b/metkit/src/metkit/types/TypeParam.cc
@@ -15,76 +15,192 @@
 #include "eckit/parser/JSONParser.h"
 #include "eckit/types/Types.h"
 #include "eckit/parser/StringTools.h"
+#include "metkit/MarsLanguage.h"
 
 #include "eckit/thread/AutoLock.h"
 
+namespace {
+
 static eckit::Mutex *local_mutex = 0;
 static pthread_once_t once = PTHREAD_ONCE_INIT;
-static std::map<std::string, std::string> *m = 0;
 
-static void init() {
 
-    local_mutex = new eckit::Mutex();
-    m = new std::map<std::string, std::string>();
 
-    eckit::PathName language("~metkit/etc/param.json");
+class Matcher {
 
-    std::ifstream in(language.asString().c_str());
-    if (!in) {
-        throw eckit::CantOpenFile(language);
+    std::string name_;
+    eckit::Value values_;
+public:
+
+    Matcher(const std::string& name,
+            const eckit::Value values);
+
+    bool match(const metkit::MarsRequest& request) const ;
+
+    friend std::ostream& operator<<(std::ostream& out, const Matcher& matcher) {
+        out << matcher.name_ << "=" << matcher.values_;
+        return out;
     }
+};
 
-    eckit::JSONParser parser(in);
+Matcher::Matcher(const std::string& name,
+                 const eckit::Value values):
+    name_(name),
+    values_(values) {
+
+    if (!values_.isList()) {
+        values_ = eckit::Value::makeList(values_);
+    }
+
+}
+
+bool Matcher::match(const metkit::MarsRequest& request) const {
+
+    std::vector<std::string> vals = request.values(name_, true);
+    if (vals.size() == 0) {
+        return false;
+    }
+
+    // std::cout << vals << std::endl;
+
+
+    for (size_t i = 0; i < values_.size(); i++) {
+        std::string v = values_[i];
+
+        if (v == vals[0]) {
+            return true;
+        }
+    }
 
-    const eckit::Value values = parser.parse();
-    std::map<std::string, std::string>& mapping = *m;
+    return false;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class Rule : private metkit::ExpandContext {
+
+    std::vector<Matcher> matchers_;
+    std::vector<std::string> values_;
+
+    mutable std::map<std::string, std::string> mapping_;
+
+public:
+
+    bool match(const metkit::MarsRequest& request) const;
+    std::string lookup(const std::string & s, bool fail) const;
+
+    Rule(const eckit::Value& matchers, const eckit::Value& setters, const eckit::Value& ids);
+
+    void print(std::ostream& out) const {
+        out << "{";
+        const char* sep = "";
+        for (std::vector<Matcher>::const_iterator j = matchers_.begin(); j != matchers_.end(); ++j) {
+            out << sep << (*j);
+            sep = ",";
+        }
+        out << "}";
+    }
+
+    friend std::ostream& operator<<(std::ostream& out, const Rule& rule) {
+        rule.print(out);
+        return out;
+    }
+
+};
+
+
+Rule::Rule(const eckit::Value& matchers, const eckit::Value& values, const eckit::Value& ids) {
+
+    std::map<std::string, size_t> precedence;
+
+    const eckit::Value& keys = matchers.keys();
+    for (size_t i = 0; i < keys.size(); ++i) {
+        std::string name = keys[i];
+        matchers_.push_back(Matcher(name, matchers[name]));
+    }
 
     for (size_t i = 0; i < values.size(); ++i) {
 
-        const eckit::Value& val = values[i];
+        const eckit::Value& id = values[i];
+
+        std::string first = id;
+        values_.push_back(first);
+
+        const eckit::Value& aliases = ids[id];
 
-        ASSERT (val.isList()) ;
-        ASSERT(val.size() > 0);
+        if (aliases.isNil()) {
+            std::cerr << "No aliases for "
+                      << id
+                      << " "
+                      << *this
+                      << std::endl;
+            continue;
+        }
 
-        std::string first = val[0];
 
-        for (size_t j = 0; j < val.size(); ++j) {
-            std::string v = val[j];
 
-            if (mapping.find(v) != mapping.end()) {
-                std::cerr << "Redefined param '" << v << "', '" << first << "' and '" << mapping[v] << "'" << std::endl;
-                continue;
+        for (size_t j = 0; j < aliases.size(); ++j) {
+            std::string v = aliases[j];
+
+            if (mapping_.find(v) != mapping_.end()) {
+
+                if (precedence[v] <= j) {
+
+                    std::cerr << "Redefinition ignored: param "
+                              << v
+                              << "='"
+                              << first
+                              << "', keeping previous value of '"
+                              << mapping_[v]
+                              << "' "
+                              << *this
+                              << std::endl;
+                    continue;
+                }
+                else {
+
+                    std::cerr << "Redefinition of param "
+                              << v
+                              << "='"
+                              << first
+                              << "', overriding previous value of '"
+                              << mapping_[v]
+                              << "' "
+                              << *this
+                              << std::endl;
+
+                    precedence[v] = j;
+                }
+            } else {
+                precedence[v] = j;
             }
 
-            mapping[v] = first;
+            mapping_[v] = first;
+            values_.push_back(v);
         }
     }
 }
 
-static const std::string& lookup(const std::string & s, bool fail) {
-    pthread_once(&once, init);
-    eckit::AutoLock<eckit::Mutex> lock(local_mutex);
 
-    std::map<std::string, std::string>& mapping = *m;
 
-    std::map<std::string, std::string>::const_iterator j = mapping.find(s);
-    if (j != mapping.end()) {
-        return (*j).second;
+bool Rule::match(const metkit::MarsRequest& request) const {
+    for (std::vector<Matcher>::const_iterator j = matchers_.begin(); j != matchers_.end(); ++j) {
+        if (!(*j).match(request)) {
+            return false;
+        }
     }
+    return true;
+}
 
-    std::string low = eckit::StringTools::lower(s);
-    j = mapping.find(low);
-    if (j != mapping.end()) {
-        mapping[low] = (*j).second;
-        return (*j).second;
-    }
+
+std::string Rule::lookup(const std::string & s, bool fail) const {
 
     size_t table = 0;
     size_t param = 0;
     size_t *n = ¶m;
     bool ok = true;
 
-    for (std::string::const_iterator k = low.begin(); k != low.end(); ++k) {
+    for (std::string::const_iterator k = s.begin(); k != s.end(); ++k) {
         switch (*k) {
         case '0':
         case '1':
@@ -98,10 +214,10 @@ static const std::string& lookup(const std::string & s, bool fail) {
         case '9':
             (*n) *= 10;
             (*n) += (*k) - '0';
-             break;
+            break;
 
         case '.':
-            if(n == &param) {
+            if (n == &param) {
                 n = &table;
             }
             else {
@@ -115,23 +231,62 @@ static const std::string& lookup(const std::string & s, bool fail) {
         }
     }
 
-    if(ok && param > 0) {
+    if (ok && param > 0) {
         std::ostringstream oss;
+        if (table == 128) {
+            table = 0;
+        }
+
+        // std::cerr << "Param " << param << " " << table << std::endl;
+
         oss <<  table * 1000 + param;
-        mapping[s] = oss.str();
-        return mapping[s];
+        return  metkit::MarsLanguage::bestMatch(oss.str(), values_, fail, false, mapping_, this);
+    }
+
+    return metkit::MarsLanguage::bestMatch(s, values_, fail, false, mapping_, this);
+}
+
+static std::vector<Rule>* rules = 0;
 
+}
+
+static void init() {
+
+    local_mutex = new eckit::Mutex();
+    rules = new std::vector<Rule>();
+
+    eckit::PathName language("~metkit/etc/param.json");
+
+    std::ifstream in(language.asString().c_str());
+    if (!in) {
+        throw eckit::CantOpenFile(language);
     }
 
-    if(fail) {
-        throw eckit::UserError("Invalid parameter '" + s + "'");
+    eckit::JSONParser parser(in);
+
+    const eckit::Value parsed = parser.parse();
+
+
+    const eckit::Value ids = parsed["ids"];
+    ASSERT(ids.isMap());
+
+
+    const eckit::Value r = parsed["parameters"];
+
+    ASSERT(r.isList());
+
+    for (size_t i = 0; i < r.size(); ++i) {
+        const eckit::Value& rule = r[i];
+        ASSERT(rule.isList());
+        ASSERT(rule.size() == 2);
+        (*rules).push_back(Rule(rule[0], rule[1], ids));
     }
 
-    static std::string empty;
-    return empty;
+
 }
 
 
+
 namespace metkit {
 
 //----------------------------------------------------------------------------------------------------------------------
@@ -150,20 +305,51 @@ void TypeParam::print(std::ostream &out) const {
     out << "TypeParam[name=" << name_ << "]";
 }
 
-bool TypeParam::expand(std::vector<std::string>& values, bool fail) const {
+bool TypeParam::expand(const MarsRequest& request, std::vector<std::string>& values, bool fail) const {
+
+    pthread_once(&once, init);
+    eckit::AutoLock<eckit::Mutex> lock(local_mutex);
+
+    const Rule* rule = 0;
+
+    for (std::vector<Rule>::const_iterator j = rules->begin(); j != rules->end(); ++j) {
+        if ((*j).match(request)) {
+            rule = &(*j);
+            break;
+        }
+    }
+
+
+    if (!rule) {
+        std::cerr << "Not rule for " << request << std::endl;
+    }
+    ASSERT(rule);
 
 
     for (std::vector<std::string>::iterator j = values.begin(); j != values.end(); ++j) {
         std::string& s = (*j);
-        s = ::lookup(s, fail);
+        try {
+            s = rule->lookup(s, fail);
+        } catch (...) {
+            std::cerr << *rule << std::endl;
+            throw;
+        }
     }
 
     return true;
 }
 
 
+void TypeParam::pass2(MarsRequest& request) {
+    // std::cout << request << std::endl;
+    std::vector<std::string> values = request.values(name_, true);
+    expand(request, values, true);
+    request.setValuesTyped(this, values);
+}
+
+
 void TypeParam::expand(std::vector<std::string>& values) const {
-    expand(values, true);
+// Work done on pass2()
 }
 
 void TypeParam::reset() {
diff --git a/metkit/src/metkit/types/TypeParam.h b/metkit/src/metkit/types/TypeParam.h
index 747ac17..5092cac 100644
--- a/metkit/src/metkit/types/TypeParam.h
+++ b/metkit/src/metkit/types/TypeParam.h
@@ -33,12 +33,14 @@ public: // methods
     virtual void expand(std::vector<std::string>& values) const;
 
 protected:
-    virtual bool expand(std::vector<std::string>& values, bool fail) const;
+    virtual bool expand(const MarsRequest& request, std::vector<std::string>& values, bool fail) const;
 
 private: // methods
 
     virtual void print( std::ostream &out ) const;
     virtual void reset();
+    virtual void pass2(MarsRequest& request);
+
 
 };
 
diff --git a/metkit/src/tests/CMakeLists.txt b/metkit/src/tests/CMakeLists.txt
index ef38a05..dae3d11 100644
--- a/metkit/src/tests/CMakeLists.txt
+++ b/metkit/src/tests/CMakeLists.txt
@@ -20,6 +20,10 @@ ecbuild_add_test( TARGET        metkit_test_emosfile
                   TEST_DEPENDS  grib_get_data
 )
 
+if( IS_DIRECTORY "${CMAKE_BINARY_DIR}/share/${grib_handling_pkg}/definitions" )
+  set( eccodes_env "ECCODES_DEFINITION_PATH=${CMAKE_BINARY_DIR}/share/${grib_handling_pkg}/definitions" )
+endif()
+
 ecbuild_add_test( TARGET        metkit_test_multihandle
                   BOOST
                   CONDITION     HAVE_GRIB
@@ -27,6 +31,7 @@ ecbuild_add_test( TARGET        metkit_test_multihandle
                   SOURCES       test_multihandle.cc
                   LIBS          metkit
                   TEST_DEPENDS  grib_get_data
+                  ENVIRONMENT   "${eccodes_env}"
 )
 
 ecbuild_add_test( TARGET    test_typesfactory
diff --git a/odb-tools/.gitignore b/odb-tools/.gitignore
new file mode 100644
index 0000000..14b93b5
--- /dev/null
+++ b/odb-tools/.gitignore
@@ -0,0 +1,8 @@
+*.swp
+*.sublime-workspace
+.tags*
+CMakeLists.txt.user*
+*.autosave
+*.sublime-workspace
+.*.sw*
+.*un~
diff --git a/odb-tools/CMakeLists.txt b/odb-tools/CMakeLists.txt
new file mode 100644
index 0000000..687311e
--- /dev/null
+++ b/odb-tools/CMakeLists.txt
@@ -0,0 +1,93 @@
+##
+# This package exists to contain odb_api tools that make use of ODB1, to break the circular
+# dependency when building with IFS.
+
+cmake_minimum_required( VERSION 2.8.11 FATAL_ERROR )
+
+project( odb_tools CXX Fortran )
+
+set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 2.0 )
+
+###############################################################################
+# local project
+
+ecbuild_declare_project()
+
+ecbuild_use_package( PROJECT eckit   VERSION 0.9 REQUIRED )
+ecbuild_use_package( PROJECT odb_api VERSION ${odb_tools_VERSION_STR} REQUIRED )
+ecbuild_use_package( PROJECT odb     VERSION 1.0.5 REQUIRED )
+
+###############################################################################
+# some variables/options of this project
+
+ecbuild_add_option( FEATURE MIGRATOR
+                    DESCRIPTION "whether or not to build the ODB migrator tool"
+                    DEFAULT ON
+                    REQUIRED_PACKAGES "PROJECT odb VERSION 1.0 QUIET" )
+
+#ecbuild_add_option( FEATURE FORTRAN
+#                    DESCRIPTION "whether or not to build the Fortran interface"
+#                    DEFAULT OFF )
+set( HAVE_FORTRAN ON )
+
+if( HAVE_FORTRAN OR HAVE_MIGRATOR )
+
+    set( Fortran Fortran )
+    ecbuild_enable_fortran( REQUIRED MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/module )
+    ecbuild_find_fortranlibs( REQUIRED )
+    message( "Fortran libraries: [${FORTRAN_LIBRARIES}]" )
+
+endif()
+
+if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
+  ecbuild_add_fortran_flags("-fPIC -ffree-line-length-none")
+endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+  ecbuild_add_cxx_flags("-fPIC -Wl,--as-needed")
+endif()
+
+ecbuild_add_option( FEATURE OMP
+                    DESCRIPTION "Support for OpenMP threaded parallelism"
+                    REQUIRED_PACKAGES "OMP COMPONENTS CXX ${Fortran}" )
+
+if( HAVE_OMP )
+  ecbuild_enable_omp()
+else()
+  ecbuild_enable_ompstubs()
+endif()
+
+ecbuild_add_option( FEATURE PYTHON
+                    DESCRIPTION "whether or not to build the Python interface"
+                    DEFAULT OFF
+                    REQUIRED_PACKAGES "Python VERSION 2.7 NO_LIBS" SWIG )
+
+###############################################################################
+# contents
+
+set_directory_properties( PROPERTIES COMPILE_DEFINITIONS "${ECKIT_DEFINITIONS}" )
+
+get_directory_property( ODB_API_DEFINITIONS COMPILE_DEFINITIONS )
+
+set( ODB_TOOLS_INCLUDE_DIRS   ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src )
+
+#if( HAVE_FORTRAN )
+  list( APPEND ODB_API_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/module )
+  list( INSERT ODB_API_LIBRARIES 0 Odb_fortran )
+#endif()
+
+include_directories( ${ODB_API_INCLUDE_DIRS} ${ODB_TOOLS_INCLUDE_DIRS} )
+
+add_subdirectory( src )
+
+############################################################################################
+# finalize
+
+ecbuild_install_project( NAME OdbTools )
+
+ecbuild_print_summary()
+
diff --git a/odb-tools/VERSION.cmake b/odb-tools/VERSION.cmake
new file mode 100644
index 0000000..bc32f90
--- /dev/null
+++ b/odb-tools/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "0.17.1" )
diff --git a/odb-tools/bamboo/CLANG-env.sh b/odb-tools/bamboo/CLANG-env.sh
new file mode 100644
index 0000000..14e05f9
--- /dev/null
+++ b/odb-tools/bamboo/CLANG-env.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# No module environment on the Mac
+[[ $(uname) == "Darwin" ]] && return
+
+# Initialise module environment if it is not
+if [[ ! $(command -v module > /dev/null 2>&1) ]]; then
+  . /usr/local/apps/module/init/bash
+fi
+module unload grib_api
+module switch gnu clang/3.6.2
diff --git a/odb-tools/bamboo/INTEL-env.sh b/odb-tools/bamboo/INTEL-env.sh
new file mode 100644
index 0000000..260e756
--- /dev/null
+++ b/odb-tools/bamboo/INTEL-env.sh
@@ -0,0 +1,11 @@
+# Initialise module environment if it is not
+if [[ ! $(command -v module > /dev/null 2>&1) ]]; then
+  . /usr/local/apps/module/init/bash
+fi
+# Unload modules not available for Intel
+module unload grib_api
+module unload eccodes
+module unload emos
+module unload fftw
+module unload libemos
+module switch gnu intel/16.0.3
diff --git a/odb-tools/bamboo/env.sh b/odb-tools/bamboo/env.sh
new file mode 100644
index 0000000..d6827b6
--- /dev/null
+++ b/odb-tools/bamboo/env.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+ctest_parallel="no"
+
diff --git a/odb-tools/bamboo/flags.cmake b/odb-tools/bamboo/flags.cmake
new file mode 100644
index 0000000..9892d75
--- /dev/null
+++ b/odb-tools/bamboo/flags.cmake
@@ -0,0 +1 @@
+SET(ENABLE_MIGRATOR ON CACHE BOOL "Build migrator tool")
diff --git a/odb-tools/src/CMakeLists.txt b/odb-tools/src/CMakeLists.txt
new file mode 100644
index 0000000..5a80538
--- /dev/null
+++ b/odb-tools/src/CMakeLists.txt
@@ -0,0 +1,16 @@
+## check if all sources are used
+
+ecbuild_find_project_files()
+
+### include directories
+
+
+### libs
+
+if( HAVE_MIGRATOR )
+    add_subdirectory( migrator )
+endif()
+
+add_subdirectory( odb2_to_odb1 )
+
+add_subdirectory( tests )
diff --git a/odb_api/src/odb_api/migrator/2oda b/odb-tools/src/migrator/2oda
similarity index 100%
copy from odb_api/src/odb_api/migrator/2oda
copy to odb-tools/src/migrator/2oda
diff --git a/odb-tools/src/migrator/CMakeLists.txt b/odb-tools/src/migrator/CMakeLists.txt
new file mode 100644
index 0000000..f230639
--- /dev/null
+++ b/odb-tools/src/migrator/CMakeLists.txt
@@ -0,0 +1,112 @@
+
+list( APPEND migrator_srcs
+    FakeODBIterator.cc
+    FakeODBIterator.h
+    ImportODBTool.cc
+    ImportODBTool.h
+    ODB2ODATool.cc
+    ODB2ODATool.h
+    MigratorTool.h
+    MigratorTool.cc
+    ODBIterator.cc
+    ODBIterator.h
+    OldODBReader.h
+    ReptypeGenIterator.cc
+    ReptypeGenIterator.h
+    TSQLReader.cc
+    TSQLReader.h
+    ODBMigratorModule.h
+    ODBMigratorModule.cc
+    MigrateHandler.h
+    MigrateHandler.cc
+    migrator_api.cc
+    migrator_api.h
+    odbdump.h
+)
+
+
+ecbuild_add_library(
+
+    TARGET Odbmigrator
+    SOURCES ${migrator_srcs}
+
+    TEMPLATES
+        ImportODBTool.cc
+        TSQLReader.cc
+
+    PRIVATE_INCLUDES
+        ${ODB_INCLUDE_DIRS}
+        ${ECKIT_INCLUDE_DIRS}
+
+    INSTALL_HEADERS LISTED
+    HEADER_DESTINATION
+        ${INSTALL_INCLUDE_DIR}/odb_api/migrator
+
+    LIBS
+        Odb
+        odbtools
+        ${ODB_LIBRARIES}
+        ${FORTRAN_LIBRARIES}
+        ${DL_LIBRARIES}
+        ${EXTRA_ODB_MIGRATOR_LIBS} ) #FIXME: add gomp for gfortran 
+                        
+
+ecbuild_add_executable(
+    
+    TARGET odb_migrator
+    SOURCES odb2oda.cc
+    INCLUDES ${ODB_INCLUDE_DIRS}
+    # LINKER_LANGUAGE Fortran
+
+    LIBS
+        Odbmigrator
+        odbtools
+        ${ODB_LIBRARIES}
+        ${FORTRAN_LIBRARIES}
+        ${DL_LIBRARIES} )
+
+
+set( test_environment
+
+    ODB_API_CODES=${PROJECT_SOURCE_DIR}/etc
+    ODB_API_HOME=${PROJECT_SOURCE_DIR}
+    ODB_API_TEST_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}
+    PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+    ODB_RTABLE_PATH=${PROJECT_SOURCE_DIR}/etc )
+
+
+if( HAVE_MIGRATOR AND ODB_FOUND AND DEFINED FORTRAN_LIBRARIES )
+
+    get_target_property( migrator_bin odb_migrator LOCATION )
+
+    list( APPEND odb_migrator_data_files  2000010106.old.ECMA.tar.gz )
+
+    ecbuild_get_test_multidata( TARGET get_odb_migrator_test_data
+                                DIRNAME odb_api/tests 
+                                NAMES ${odb_migrator_data_files} 
+                                NOCHECK )
+
+      #ecbuild_add_test( TARGET     test_migrator.ecml
+      #                COMMAND      ${migrator_bin} 
+      #                ARGS         ecml ${CMAKE_CURRENT_SOURCE_DIR}/test_migrator.ecml
+      #                CONDITION    HAVE_MIGRATOR
+      #                ENVIRONMENT  ${test_environment}
+      #                LABELS       odb_api odb_api_ecml
+      #                TEST_DEPENDS get_odb_migrator_test_data
+      #                )
+endif()
+
+
+if( HAVE_PYTHON AND SWIG_FOUND AND PYTHONLIBS_FOUND )
+    set(CMAKE_SWIG_FLAGS "")
+    include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${PYTHON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../odb_api )
+    set_source_files_properties( pyodbdump.i PROPERTIES CPLUSPLUS ON )
+    # set_source_files_properties( pyodbapi.i PROPERTIES SWIG_FLAGS "-includeall")
+    swig_add_module( pyodbdump python pyodbdump.i )
+    swig_link_libraries( pyodbdump Odbmigrator Odb ${ODB_LIBRARIES} ${FORTRAN_LIBRARIES} ${DL_LIBRARIES} ${PYTHON_LIBRARIES} )
+        
+    set(PYTHON_SITE "${INSTALL_LIB_DIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages" )
+    set(PYTHON_DEST "${PYTHON_SITE}" )
+    install(TARGETS _pyodbdump DESTINATION ${PYTHON_DEST} )
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyodbdump.py  DESTINATION ${PYTHON_DEST})
+endif()
diff --git a/odb-tools/src/migrator/FakeODBIterator.cc b/odb-tools/src/migrator/FakeODBIterator.cc
new file mode 100644
index 0000000..dcebf2d
--- /dev/null
+++ b/odb-tools/src/migrator/FakeODBIterator.cc
@@ -0,0 +1,160 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file FakeODBIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <strings.h>
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "eckit/parser/Tokenizer.h"
+#include "eckit/utils/Translator.h"
+
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ODBIterator.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+FakeODBIterator::ConstParameters FakeODBIterator::ConstParameters::instance_ = FakeODBIterator::ConstParameters();
+
+Assignments::Assignments(const std::string& s)
+{
+    Tokenizer splitAssignments(",");
+    std::vector<std::string> assignments;
+    splitAssignments(s, assignments);
+	
+    Tokenizer splitEq("=");
+	for (size_t i = 0; i < assignments.size(); ++i)
+	{
+		std::vector<std::string> assignment;
+		splitEq(assignments[i], assignment);
+		ASSERT(assignment.size() == 2);
+
+		push_back(make_pair(assignment[0], assignment[1]));
+	}
+}
+
+void FakeODBIterator::ConstParameters::add(const Assignments& ass)
+{
+	Log::debug() << "FakeODBIterator::ConstParameters::add(const Assignments& ass)" << std::endl;
+	for (size_t i = 0; i < ass.size(); ++i)
+	{
+		const Assignment &as = ass[i];
+		std::string columnName = as.first;
+		std::string value = as.second;
+
+		ASSERT(value.size() > 0);
+
+		if (Tool::isInQuotes(value))
+			addString(columnName, Tool::unQuote(value));
+		else if (value.find('.') == std::string::npos)
+			addInteger(columnName, Translator<std::string, long>()(value));
+		else
+			addReal(columnName, Translator<std::string, double>()(value));
+	}
+}
+
+void FakeODBIterator::ConstParameters::addInteger(const std::string& name, long v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addInteger: " << name << " = " << v << std::endl;
+	push_back(ConstParameter(name, v, odb::INTEGER));
+}
+
+void FakeODBIterator::ConstParameters::addReal(const std::string& name, double v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addReal: " << name << " = " << v << std::endl;
+	push_back(ConstParameter(name, v, odb::REAL));
+}
+
+void FakeODBIterator::ConstParameters::addString(const std::string& name, std::string v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addString: " << name << " = '" << v << "'" << std::endl;
+	push_back(ConstParameter(name, Tool::cast_as_double(v), odb::STRING));
+}
+
+FakeODBIterator::FakeODBIterator(const PathName& db, const std::string& sql)
+: iterator_(db, sql),
+  columns_(0),
+  data_(0),
+  constParameters_(FakeODBIterator::ConstParameters::instance())
+{}
+
+FakeODBIterator::~FakeODBIterator()
+{
+	delete [] data_;
+}
+
+odb::MetaData& FakeODBIterator::columns() {
+	if (columns_.size() == 0)
+	{
+		columns_ = iterator_.columns();
+
+		size_t i = constParameters_.size();
+		while (i-- > 0)
+		{
+			std::string name = constParameters_[i].name;
+			odb::ColumnType type = constParameters_[i].type;
+
+			Log::debug() << "FakeODBIterator::columns: i = " << i << ", name=" << name << std::endl;
+
+			odb::Column* col = new odb::Column(columns_);
+			col->name(name);
+			col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
+
+			columns_.insert(columns_.begin(), col);
+		}
+
+	}
+	return columns_;
+}
+
+double* FakeODBIterator::data()
+{
+	if (data_ == 0)
+		data_ = new double[columns_.size()];
+
+	double* trueData = iterator_.data();
+
+	size_t count = constParameters_.size();
+	memcpy(data_ + count, trueData, (columns_.size() - count) * sizeof(double));
+
+	for (size_t i = 0; i < count; ++i)
+		data_[i] = constParameters_[i].value;
+	
+	return data_;
+}
+
+bool FakeODBIterator::isNewDataset()
+{
+	return iterator_.isNewDataset();
+}
+
+bool FakeODBIterator::next(eckit::ExecutionContext* context)
+{
+	bool r = iterator_.next(context);
+	noMore_ = !r;
+	return r;
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb-tools/src/migrator/FakeODBIterator.h b/odb-tools/src/migrator/FakeODBIterator.h
new file mode 100644
index 0000000..c7e9bd2
--- /dev/null
+++ b/odb-tools/src/migrator/FakeODBIterator.h
@@ -0,0 +1,96 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file FakeODBIterator.h
+/// @author Piotr Kuchta, ECMWF, March 2009
+
+#ifndef FakeODBIterator_H
+#define FakeODBIterator_H
+
+
+#include <eckit/eckit.h>
+#include "odb_api/MetaData.h"
+#include "migrator/ODBIterator.h"
+
+namespace eckit { class PathName; }
+namespace eckit { class ExecutionContext; }
+
+namespace odb {
+namespace tool {
+
+class ODBIterator;
+
+typedef std::pair<std::string, std::string> Assignment;
+typedef std::vector<Assignment> AssignmentsBase;
+
+struct Assignments : public AssignmentsBase {
+	Assignments(const std::string&);
+};
+
+struct ConstParameter {
+	ConstParameter(std::string name, double value, odb::ColumnType type)
+	: name(name), value(value), type(type)
+	{}
+
+	std::string name;
+	double      value;
+	odb::ColumnType  type;
+};
+
+class FakeODBIterator //: public odb::RowsReaderIterator
+{
+public:
+    struct ConstParameters : public std::vector<ConstParameter>
+	{
+		// Not thread safe.
+		static ConstParameters& instance() { return instance_; }
+
+		void addInteger(const std::string& name, long);
+		void addReal(const std::string& name, double);
+		void addString(const std::string& name, std::string value);
+
+		void add(const Assignments&);
+	private:
+		static ConstParameters instance_;
+	};
+
+
+	FakeODBIterator(const eckit::PathName& db, const std::string& sql); 
+	~FakeODBIterator ();
+
+	const FakeODBIterator& end() { return *reinterpret_cast<FakeODBIterator*>(0); }
+	//bool operator!=(const FakeODBIterator& o) { ASSERT(&o == 0); return iterator_ != iterator_.end(); }
+	//FakeODBIterator& operator++() { next(); return *this; }
+
+	odb::MetaData& columns();
+
+	virtual bool isNewDataset();
+	virtual double* data();
+
+//protected:
+	virtual bool next(eckit::ExecutionContext*);
+
+	int refCount_;
+	bool noMore_;
+    eckit::ExecutionContext* context_;
+
+private:
+	ODBIterator iterator_;
+
+	odb::MetaData columns_;
+	double* data_;
+
+	ConstParameters& constParameters_;
+};
+
+} // namespace tool 
+} //namespace odb 
+
+#endif
diff --git a/odb-tools/src/migrator/ImportODBTool.cc b/odb-tools/src/migrator/ImportODBTool.cc
new file mode 100644
index 0000000..0bfb109
--- /dev/null
+++ b/odb-tools/src/migrator/ImportODBTool.cc
@@ -0,0 +1,207 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include "eckit/filesystem/LocalPathName.h"
+#include "eckit/io/FileHandle.h"
+#include "eckit/log/BigNum.h"
+#include "eckit/log/Timer.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/Comparator.h"
+#include "odb_api/DispatchingWriter.h"
+#include "odb_api/SQLDatabase.h"
+#include "odb_api/SQLInteractiveSession.h"
+#include "odb_api/SchemaAnalyzer.h"
+#include "odb_api/SchemaAnalyzer.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/RowsCounter.h"
+#include "odb_api/tools/ODA2RequestTool.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "ODBIterator.h"
+#include "FakeODBIterator.h"
+
+namespace odb {
+namespace tool {
+
+typedef std::string str;   // string is a typedef in an ODB header.
+
+template <typename IN>
+ImportODBTool<IN>::ImportODBTool (int argc, char *argv[])
+: Tool(argc, argv),
+  noVerification_ (optionIsSet("-no_verification"))
+{}
+
+template <typename IN>
+ImportODBTool<IN>::ImportODBTool (const CommandLineParser& clp)
+: Tool(clp),
+  noVerification_ (optionIsSet("-no_verification"))
+{}
+
+template <typename IN>
+std::pair<unsigned long long, const std::vector<eckit::PathName> > ImportODBTool<IN>::importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile)
+{    
+    using namespace eckit;
+
+    Timer importingAndDipatching("Importing and dipatching");
+
+    Log::info() << "Importing data from '" << db
+        << "', query is '" << sql << "', into '"
+        << dumpFile << "' template." << std::endl;
+
+    odb::DispatchingWriter writer(dumpFile);
+    odb::DispatchingWriter::iterator w = writer.begin();
+
+    unsigned long long inRowsNumber = saveData<>(w, db, sql);
+
+    std::vector<eckit::PathName> files = (**w).outputFiles();
+    return std::make_pair(inRowsNumber, files);
+}
+
+template <typename IN>
+void ImportODBTool<IN>::validate(const eckit::PathName &db, const std::string& sql, const eckit::PathName& file)
+{
+    eckit::Timer verification("Validating dispatched output");
+
+    odb::Reader odaReader(file);
+    odb::Reader::iterator r(odaReader.begin());
+
+    IN reader(db, sql);
+    typename IN::iterator begin (reader.begin());
+    const typename IN::iterator end (reader.end());
+
+    // don't check missing value as the old ODB is not giving correct info for that some times (e.g.  sortbox)
+    odb::Comparator(false)
+        .compare(begin, end, r, odaReader.end(),
+            std::string("ODB input ") + db, std::string("converted output ") + file);
+}
+
+
+template <typename IN>
+void ImportODBTool<IN>::validateRowsNumber(unsigned long long inRowsNumber, const std::vector<eckit::PathName>& files)
+{
+    using namespace eckit;
+    
+	Timer verification("Validating dispatched output");
+
+	Log::info() << "ImportODBTool::validateRowsNumber: Validating output. " << std::endl;
+	Log::info() << "ImportODBTool::validateRowsNumber: input rows number: " << BigNum(inRowsNumber) << std::endl;
+
+	unsigned long long outRowsNumber (0);
+	unsigned long long outFilesSize (0);
+	for (size_t i = 0; i < files.size(); ++i)
+	{
+		const PathName &fn (files[i]);
+		unsigned long long n (RowsCounter::rowCount(fn));
+		unsigned long long fileSize (fn.size());
+
+		outRowsNumber += n;
+		outFilesSize += fileSize;
+
+		Log::info() << "ImportODBTool::validateRowsNumber: " << fn << ": " << BigNum(n) << " rows, file size: " << BigNum(fileSize) << "." << std::endl;
+	}
+	Log::info() << "ImportODBTool::validateRowsNumber: sum of output rows number: " << BigNum(outRowsNumber) << ", sum of file sizes: " << BigNum(outFilesSize) << std::endl;
+	ASSERT(inRowsNumber == outRowsNumber);
+}
+
+
+template <typename IN>
+void ImportODBTool<IN>::run()
+{
+    using namespace eckit;
+    
+    ASSERT("Wrong number of parameters. odb2oda.cc:main should check this."
+        && !(parameters().size() < 2 || parameters().size() > 4));
+
+    str db (parameters(1));
+    str sql (parameters().size() > 2 && parameters(2) != "." ? readFile(parameters(2)) : "");
+
+    Log::info() << "ImportODBTool::run: sql='" << sql << "'" << std::endl;
+
+    str dumpFile ((parameters().size() > 3) ? parameters(3) : (db + ".odb"));
+    if (dumpFile.substr(dumpFile.size() - 4) != ".odb")
+        dumpFile.append(".odb");
+
+    Log::info() << "Importing data from '" << db << "', query is '" << sql << "', into '" << dumpFile << "'." << std::endl;
+
+    odb::TemplateParameters params;
+    if (odb::TemplateParameters::parse(dumpFile, params).size() != 0)
+    {
+        DispatchResult r (importDispatching(db, sql, dumpFile));
+
+        unsigned long long importedRowsNumber (r.first);
+        const std::vector<eckit::PathName>& outFiles (r.second);
+
+        if (! noVerification_ )
+        {
+            Timer verification("Verification");
+            validateRowsNumber(importedRowsNumber, outFiles);
+        }
+    }
+    else
+    {
+        odb::Writer<> writer(dumpFile);
+        odb::Writer<>::iterator w (writer.begin());
+
+        unsigned long long importedRowsNumber (saveData<>(w, db, sql)); 
+        Log::info() << "Imported " << BigNum(importedRowsNumber) << " row(s)." << std::endl;
+
+        Timer verification("Verification");
+        Log::info() << "Verifying." << std::endl;
+        Log::info() << "Comparing data from: 1) ODB, and 2) ODA" << std::endl;
+
+        if (importedRowsNumber && ! noVerification_) 
+            validate(db, sql, dumpFile);
+    }
+    Log::info() << "ImportODBTool: Finished OK" << std::endl;
+}
+
+template <typename IN>
+template <typename OUT_ITERATOR>
+unsigned long long ImportODBTool<IN>::saveData(OUT_ITERATOR w, eckit::PathName odb, str sql) //, const SchemaAnalyzer &schema)
+{
+    using namespace eckit;
+    
+    Log::info() << "ImportODBTool<IN>::saveData: odb='" << odb << "', sql='" << sql << "'" << std::endl;
+    unsigned long long n (0);
+	try {
+        (**w).property("ODB_DATABASE", odb);
+        IN reader (odb, sql);
+        typename IN::iterator begin (reader.begin());
+        const typename IN::iterator end (reader.end());
+		
+        if (begin->columns().empty())
+        {
+            Log::warning() << "ImportODBTool<IN>::saveData: empty input data set." << std::endl;
+            return 0;
+        }
+
+        n = w->pass1(begin, end);
+        //w->close();
+    } catch (...) {
+        shell("[ -f odbdump.stderr ] && cat odbdump.stderr && cp odbdump.stderr " + odb + ".odb.log || echo odbdump.stderr not found", Here()); 
+        throw;
+    }
+    return n;
+}
+
+
+} // namespace tool 
+} // namespace odb 
+
+
diff --git a/odb-tools/src/migrator/ImportODBTool.h b/odb-tools/src/migrator/ImportODBTool.h
new file mode 100644
index 0000000..c556583
--- /dev/null
+++ b/odb-tools/src/migrator/ImportODBTool.h
@@ -0,0 +1,66 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef odb_api_ImportODBTool_H
+#define odb_api_ImportODBTool_H
+
+#include <eckit/eckit.h>
+
+#include "eckit/filesystem/PathName.h"
+#include "migrator/OldODBReader.h"
+#include "odb_api/tools/Tool.h"
+
+
+class ODBIterator;
+class CommandLineParser;
+
+
+namespace odb {
+namespace tool {
+
+template <typename IN = odb::tool::OldODBReader>
+class ImportODBTool : public Tool {
+public:
+	ImportODBTool (int argc, char *argv[]); 
+	ImportODBTool (const CommandLineParser&); 
+
+	void run(); 
+
+protected:
+
+	template <typename OUT_ITERATOR>
+	unsigned long long saveData(OUT_ITERATOR w, eckit::PathName odb, std::string sql);
+	
+    typedef std::pair<unsigned long long, const std::vector<eckit::PathName> > DispatchResult;
+
+	DispatchResult importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile);
+
+    void validate(const eckit::PathName& db, const std::string& sql, const eckit::PathName& file);
+    void validateRowsNumber(unsigned long long, const std::vector<eckit::PathName>&);
+
+    void archiveFiles(const std::vector<eckit::PathName>&);
+private:
+
+// No copy allowed
+    ImportODBTool(const ImportODBTool&);
+    ImportODBTool& operator=(const ImportODBTool&);
+
+	bool isECFSPathName(const eckit::PathName fileName);
+	eckit::PathName readFromECFS(const eckit::PathName fileName);
+
+    bool noVerification_;
+};
+
+} // namespace tool 
+} //namespace odb 
+
+#include "ImportODBTool.cc"
+
+#endif 
diff --git a/odb_api/src/odb_api/migrator/Makefile b/odb-tools/src/migrator/Makefile
similarity index 100%
copy from odb_api/src/odb_api/migrator/Makefile
copy to odb-tools/src/migrator/Makefile
diff --git a/odb_api/src/odb_api/migrator/Makefile.old b/odb-tools/src/migrator/Makefile.old
similarity index 100%
copy from odb_api/src/odb_api/migrator/Makefile.old
copy to odb-tools/src/migrator/Makefile.old
diff --git a/odb_api/src/odb_api/migrator/MigrateHandler.cc b/odb-tools/src/migrator/MigrateHandler.cc
similarity index 100%
copy from odb_api/src/odb_api/migrator/MigrateHandler.cc
copy to odb-tools/src/migrator/MigrateHandler.cc
diff --git a/odb_api/src/odb_api/migrator/MigrateHandler.h b/odb-tools/src/migrator/MigrateHandler.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/MigrateHandler.h
copy to odb-tools/src/migrator/MigrateHandler.h
diff --git a/odb-tools/src/migrator/MigratorTool.cc b/odb-tools/src/migrator/MigratorTool.cc
new file mode 100644
index 0000000..023b7d2
--- /dev/null
+++ b/odb-tools/src/migrator/MigratorTool.cc
@@ -0,0 +1,144 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file MigratorTool.cc
+///
+/// @author Piotr Kuchta, ECMWF, July 2009
+///
+
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+
+#include "eckit/parser//StringTools.h"
+
+#include "ecml/core/ExecutionContext.h"
+
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/MigratorTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/OldODBReader.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/MDI.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+#include "odb_api/ODBModule.h"
+
+#include "ODBMigratorModule.h"
+
+using namespace eckit;
+using namespace std;
+
+namespace odb {
+namespace tool {
+
+
+int gdb(const std::vector<std::string>& params)
+{
+    std::cout << "gdb: params: " << params << std::endl;
+	str cmd(params[0]);
+	str args;
+	for (size_t i = 1; i < params.size(); ++i)
+		args += str(" ") + params[i];
+
+    eckit::PathName scriptFile = str(".gdb_") + params[2];
+	if (! scriptFile.exists())
+	{
+		str s = str("file ") + cmd + "\nbreak main\nrun " + args + "\n";
+        s += "catch throw\n";
+        eckit::FileHandle f(scriptFile);
+		f.openForWrite(1024);
+		f.write(s.c_str(), s.size());
+		f.close();
+	}
+	str vi = str("vi ") + scriptFile;
+	std::cout << "Executing '" << vi << "'" << std::endl;
+	system(vi.c_str());
+
+	str gdbCmd = str("gdb -x ") + scriptFile;
+	std::cout << "Executing '" << gdbCmd << "'" << std::endl;
+	return system(gdbCmd.c_str());
+}
+
+// valgrind --log-file=v.log --show-reachable=yes --leak-check=full ./oda test 
+int valgrind(const std::vector<std::string>& params)
+{
+    std::cout << "valgrind: params: " << params << std::endl;
+	str cmd(params[0]);
+	str args;
+	for (size_t i = 1; i < params.size(); ++i)
+		args += str(" ") + params[i];
+
+	str logFile = str("vg.log");
+	str vg = str("valgrind --log-file=") + logFile + " --show-reachable=yes --leak-check=full " + cmd + " " + args;
+	std::cout << "Executing '" << vg << "'" << std::endl;
+	return system(vg.c_str());
+}
+
+//MigratorTool::MigratorTool (int argc, char *argv[]) : Tool(argc, argv) { } 
+
+MigratorTool::MigratorTool (const CommandLineParser &clp) : Tool(clp) { } 
+
+void MigratorTool::runECML()
+{
+    ecml::ExecutionContext context;
+    ODBModule odbModule;
+    ODBMigratorModule migratorModule;
+    context.import(odbModule);
+    context.import(migratorModule);
+
+    std::vector<std::string> params(parameters());
+    params.erase(params.begin());
+    params.erase(params.begin());
+    for (size_t i (0); i < params.size(); ++i)
+    {
+        Log::info() << "*** Executing " << params[i] << endl;
+        context.executeScriptFile(params[i]);
+    }
+
+}
+
+void MigratorTool::run()
+{
+    if (parameters().size() > 1)
+    {
+        if (parameters(1) == "g" || parameters(1) == "vg")
+        {
+            std::vector<std::string> params;
+            for (size_t i(0); i < parameters().size(); ++i)
+                if (i != 1)
+                    params.push_back(parameters()[i]);
+
+            if (parameters(1) == "g")
+                gdb(params);
+            else valgrind(params);
+
+            return;
+        }
+        if (parameters(1) == "ecml")
+            return runECML();
+
+        if (parameters(1) == "test")
+        {
+            //odb::tool::test::TestRunnerApplication(argc(), argv()).start();
+            return; // TODO: Retrieve a status from the test runner
+        }
+    }
+
+    ODB2ODATool odb2oda(*this);
+    odb2oda.run();
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/MigratorTool.h b/odb-tools/src/migrator/MigratorTool.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/MigratorTool.h
copy to odb-tools/src/migrator/MigratorTool.h
diff --git a/odb-tools/src/migrator/ODB2ODATool.cc b/odb-tools/src/migrator/ODB2ODATool.cc
new file mode 100644
index 0000000..ae37b37
--- /dev/null
+++ b/odb-tools/src/migrator/ODB2ODATool.cc
@@ -0,0 +1,139 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file ODB2ODATool.cc
+///
+/// @author Piotr Kuchta, ECMWF, July 2009
+///
+
+#include <iostream>
+#include <fstream>
+
+#include "eckit/parser/StringTools.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/OldODBReader.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/MDI.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+ODB2ODATool::ODB2ODATool (int argc, char *argv[])
+: Tool(argc, argv)
+{}
+
+ODB2ODATool::ODB2ODATool (const CommandLineParser &clp)
+: Tool(clp)
+{}
+
+
+/// -mdi <type1:MDI1,type2:MDI2,...>
+void ODB2ODATool::resetMDI(const std::string& s)
+{
+    typedef eckit::StringTools S;
+    std::vector<std::string> columns(S::split(",", s));
+    for (size_t i = 0; i < columns.size(); ++i)
+    {
+        std::vector<std::string> ass(S::split(":", columns[i]));
+
+        if (ass.size() != 2)
+            throw UserError("Error parsing option -mdi");
+
+        const std::string typeName(S::upper(ass[0]));
+        double value(StringTool::translate(ass[1]));
+
+        Log::info() << "  typeName: " << typeName << " value: " << value << std::endl;
+
+        if (typeName == "REAL")
+            odb::MDI::realMDI(value);
+        else if (typeName == "INTEGER" || typeName == "INT")
+            odb::MDI::integerMDI(value);
+        else
+            throw UserError("Changing MDI of types different than INTEGER or REAL not supported yet.");
+    }
+}
+
+void ODB2ODATool::run()
+{
+	if (parameters().size() < 2 || parameters().size() > 4)
+	{
+        std::cerr << "Usage:" << std::endl
+			<< "	" << parameters(0)
+
+            << " [<options>] <odb_database> [<file-with-select-statement-defining-dump> [<output.odb>]]" << std::endl
+
+            << "Options: " << std::endl << std::endl
+
+            << "\t[-genreptype <list-of-columns>]" << std::endl
+            << "\t[-reptypecfg <reptype-generation-config-file>]" << std::endl
+            << "\t[-addcolumns <list-of-assignments>]" << std::endl
+            << "\t[-mdi <type1:MDI1,type2:MDI2,...>]              Provide values of missing data indicators, e.g.: -mdi REAL:2147483647,INTEGER:2147483647" << std::endl
+            << "\t[-no_verification]                              Do not verify the conversion" << std::endl
+
+			<< std::endl;
+		return;
+	}
+
+    std::string nonDefaultMDIS(optionArgument<std::string>("-mdi", ""));
+    if (nonDefaultMDIS.size())
+        Log::info() << "Using non default missing data indicators: " << nonDefaultMDIS << std::endl;
+
+	bool addColumns (optionIsSet("-addcolumns"));
+	if (addColumns)
+		FakeODBIterator::ConstParameters::instance().add(Assignments(optionArgument<std::string>("-addcolumns", "")));
+ 
+	bool genReptype (optionIsSet("-genreptype"));
+	bool reptypeCfg (optionIsSet("-reptypecfg"));
+    if (optionIsSet("-mdi"))
+        resetMDI(optionArgument<std::string>("-mdi", ""));
+
+	ASSERT("Only one of -genreptype and -reptypecfg can be choosen at a time." && !(genReptype && reptypeCfg));
+
+	if (genReptype) {
+        std::vector<std::string> columns = StringTools::split(",", optionArgument<std::string>("-genreptype", ""));
+		ReptypeTableConfig::addColumns(columns.begin(), columns.end());
+	}
+
+	if (reptypeCfg) ReptypeTableConfig::load(optionArgument<std::string>("-reptypecfg", ""));
+
+	if (addColumns && (genReptype || reptypeCfg)) {
+		typedef odb::tool::TSQLReader<ReptypeGenIterator<FakeODBIterator> > R;
+		ImportODBTool<R>(*this).run();
+		return;
+	}
+
+	if (addColumns) {
+		ImportODBTool<odb::tool::TSQLReader<FakeODBIterator> >(*this).run();
+		return;
+	}
+
+	if (genReptype || reptypeCfg) {
+		ImportODBTool<odb::tool::TSQLReader<ReptypeGenIterator<ODBIterator> > >(*this).run();
+		return;
+	}
+
+	{	
+		ImportODBTool<odb::tool::OldODBReader>(*this).run();
+		Log::info() << "ImportODBTool<ODBIterator> finished OK" << std::endl;
+	}
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/ODB2ODATool.h b/odb-tools/src/migrator/ODB2ODATool.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/ODB2ODATool.h
copy to odb-tools/src/migrator/ODB2ODATool.h
diff --git a/odb-tools/src/migrator/ODBIterator.cc b/odb-tools/src/migrator/ODBIterator.cc
new file mode 100644
index 0000000..67d679a
--- /dev/null
+++ b/odb-tools/src/migrator/ODBIterator.cc
@@ -0,0 +1,253 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file ODBIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <map>
+
+#include "eckit/config/Resource.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/parser/StringTools.h"
+#include "migrator/ODBIterator.h"
+#include "odb_api/MetaData.h"
+#include "odb_api/SQLDatabase.h"
+#include "odb_api/SQLParser.h"
+#include "odb_api/SQLSelectFactory.h"
+#include "odb_api/StringTool.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+
+namespace odb { namespace sql { class SQLInteractiveSession; } }
+
+extern "C" {
+#include "odbdump.h"
+}
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+//ODBIterator::ODBIterator(const PathName& db, const std::string& sql)
+ODBIterator::ODBIterator(const std::string& db, const std::string& sql)
+: db_(db),
+  odbHandle_(0),
+  noOfColumns_(0),
+  ci_(0),
+  columns_(new odb::MetaData(0, (odb::Column *) 0)),
+  newDataset_(false),
+  data_(0),
+  nd_(0),
+  schemaParsed_(false),
+  refCount_(0),
+  noMore_(true),
+  context_(0)
+{
+	Log::info() << "ODBIterator::ODBIterator: @" << this << " db=" << db << std::endl;
+
+	const std::string odbDirectory = db; //.asString();
+	Log::info() << "Opening ODB in '" << odbDirectory << "'" << std::endl;
+	if (! PathName(odbDirectory).exists())
+        throw CantOpenFile(odbDirectory);
+	
+	std::string select = sql.size() ? sql : defaultSQL(db);
+
+	ASSERT(select.size() != 0 && select != "");
+
+	const std::string dbPath = db; //.asString();
+	const char *db_path = dbPath.c_str();
+	const char *sql_select = select.c_str();
+
+	Log::info() << "ODBIterator::ODBIterator: Calling odbdump_open(\"" << db_path << "\",\"" << sql_select << "\", NULL, NULL, NULL, &" << nd_ << ")" << std::endl;
+
+	odbHandle_ = odbdump_open(db_path, sql_select, NULL, NULL, NULL, &nd_);
+	ASSERT("odbdump_open returned NULL" && odbHandle_);
+	ASSERT("odbdump_open returned nd_ <= 0" && nd_ > 0);
+
+	data_ = new double[nd_];
+
+	//next();
+	//if (noMore_) Log::warning() << "ODBIterator::ODBIterator: result set empty, no data." << std::endl;
+}
+
+bool ODBIterator::next(eckit::ExecutionContext*)
+{
+	newDataset_ = false;
+	noOfColumns_ = odbdump_nextrow(odbHandle_, data_, nd_, &newDataset_);
+	if (noOfColumns_ == 0)
+	{
+		return !(noMore_ = true);
+	}
+
+	if (newDataset_)
+	{
+		Log::info() << "ODBIterator::readRow: new data set" << std::endl;
+		createColumns();
+	}
+
+	ASSERT(noOfColumns_ <= nd_);
+    // FIXME: read the missing values for a given constant from somewhere
+	// This is because sometime ODB has MISSING_VALUE_REAL in INTEGER columns...
+	// for example station_type at hdr in ECMA.conv
+	for (int i = 0; i < noOfColumns_; ++i)
+		if ((*columns_)[i]->type() == odb::INTEGER && data_[i] == odb::MDI::realMDI())
+			data_[i] = odb::MDI::integerMDI();
+
+	return !(noMore_ = false);
+}
+
+void ODBIterator::createColumns()
+{
+	Log::debug() << " => ODBIterator::createColumns: " << std::endl;
+
+	delete columns_;
+	columns_ = new odb::MetaData(noOfColumns_, (odb::Column *) 0);
+
+	bool preservePrecision = Resource<bool>("$ODB2ODA_PRESERVE_PRECISION", false);
+	
+	ci_ = (colinfo_t *) odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
+	int nci = 0;
+	ci_ = (colinfo_t *) odbdump_create_colinfo(odbHandle_, &nci); 
+
+    std::map<std::string, std::string> truenames;
+	for (int i = 0; i < noOfColumns_; i++)
+	{
+		colinfo_t *pci = &((colinfo_t *) ci_)[i];
+		std::string name = pci->nickname ? pci->nickname : pci->name;
+        truenames[name] = pci->name;
+
+		odb::ColumnType type = odb::REAL;
+		double missing = odb::MDI::integerMDI(); 
+
+		switch(pci->dtnum)
+		{
+			case DATATYPE_REAL4:
+				type = odb::REAL;
+				missing = odb::MDI::realMDI(); 
+				break;
+
+			case DATATYPE_REAL8:
+				type = preservePrecision ? odb::DOUBLE : odb::REAL;
+				missing = odb::MDI::realMDI(); 
+				break;
+
+			case DATATYPE_STRING:
+				type = odb::STRING;
+				break;
+
+			case DATATYPE_INT4:
+			case DATATYPE_YYYYMMDD:
+			case DATATYPE_HHMMSS:
+				type = odb::INTEGER;
+				break;
+
+			case DATATYPE_BITFIELD:
+				type = odb::BITFIELD;
+				break;
+
+			default:
+				Log::error() << "Unsupported type: [" << pci->type_name << "] " << name
+							<< std::endl;
+				break;
+		}
+		setColumn(i, name, type, missing);
+	}
+	getSchema(db_).updateBitfieldsDefs(columns(), truenames);
+	Log::debug() << " <= ODBIterator::createColumns: " << std::endl;
+}
+
+void ODBIterator::destroy()
+{
+	Log::debug() << "ODBIterator::destroy: @" << this << std::endl;
+	odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
+	odbdump_close(odbHandle_);
+	delete columns_;
+	delete [] data_;
+}
+
+ODBIterator::~ODBIterator ()
+{
+	Log::info() << "ODBIterator::~ODBIterator: @" << this << std::endl;
+	destroy();
+}
+
+odb::MetaData& ODBIterator::columns() { return *columns_; }
+
+double* ODBIterator::data() { return data_; }
+
+bool ODBIterator::isNewDataset() { return newDataset_; }
+
+int ODBIterator::setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue)
+{
+	//Log::debug() << "ODBIterator::setColumn: " << index << ", " << name << ", " << columnTypeName(type) << ", " << missingValue << std::endl;
+
+	ASSERT(int(index) < noOfColumns_);
+	ASSERT(columns_);
+	odb::Column* col = (*columns_)[index];
+	delete col;
+	col = new odb::Column(*columns_);
+	ASSERT(col);
+
+	col->name(name); 
+	col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
+	col->missingValue(missingValue);
+
+	(*columns_)[index] = col;
+	return 0;
+}
+
+
+//const char* defaultSQL = "select {!/LINK/} from hdr,body,errstat";
+PathName ODBIterator::schemaFile(const PathName& db)
+{
+    Log::info() << "ODBIterator::schemaFile: db=" << db << std::endl;
+
+	std::string d = db;
+
+	if (d[d.size() - 1] != '/')
+		d += "//";
+
+	std::string s = StringTools::split(".", StringTools::split("//", d).back())[0];
+
+	return d + s + ".sch";
+}
+
+const odb::sql::SchemaAnalyzer& ODBIterator::getSchema(const PathName& db)
+{
+	//odb::sql::SQLSelectFactory::instance().config(); //odb::sql::SQLOutputConfig());
+	// FIXME: this is not good cause when you call the method several times with different db it will fail...
+	// It's not used like that at the moment, anyway. So perhaps I should make db a member (db_).
+	if (!schemaParsed_)
+	{
+		PathName schemaFile = this->schemaFile(db);
+		Log::info() << "ImportODBTool::getSchema: parsing '" << schemaFile << "'" << std::endl;
+	
+		odb::sql::SQLParser p;
+		p.parseString(session_, StringTool::readFile(schemaFile), static_cast<DataHandle*>(0), session_.selectFactory().config());
+		schemaParsed_ = true;
+	}
+
+	return session_
+			.currentDatabase()
+			.schemaAnalyzer();
+}
+
+std::string ODBIterator::defaultSQL(const PathName& db)
+{
+	return getSchema(db).generateSELECT();
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb-tools/src/migrator/ODBIterator.h b/odb-tools/src/migrator/ODBIterator.h
new file mode 100644
index 0000000..18b5a0b
--- /dev/null
+++ b/odb-tools/src/migrator/ODBIterator.h
@@ -0,0 +1,97 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef ODBIterator_H
+#define ODBIterator_H
+
+#include "eckit/filesystem/PathName.h"
+#include "odb_api/SQLInteractiveSession.h"
+#include "odb_api/ColumnType.h"
+
+namespace eckit { class PathName; }
+namespace eckit { class ExecutionContext; }
+
+namespace odb { namespace sql { class SchemaAnalyzer; class SQLInteractiveSession; } }
+
+namespace odb {
+
+class MetaData;
+
+namespace tool {
+
+class ODBIterator 
+{
+public:
+    ODBIterator(const std::string& db, const std::string& sql); 
+    virtual ~ODBIterator ();
+
+    void destroy();
+
+    const ODBIterator& end() { return *reinterpret_cast<ODBIterator*>(0); }
+
+    ODBIterator& operator++() { next(context_); return *this; }
+
+    bool operator!=(const ODBIterator& o) {
+        /* SDS: I have no idea what the purpose of this operator is,
+         *      but returning uninitialised memory
+         *      seems a bad plan. Check that it is never being used. */
+        throw eckit::SeriousBug("Non-functional operator!= must never be called", Here());
+        /*ASSERT(&o == 0); return hasNext_;*/
+    }
+
+    odb::MetaData& columns();
+
+    virtual bool isNewDataset();
+    virtual double* data();
+
+    static eckit::PathName schemaFile(const eckit::PathName& db);
+
+    virtual bool next(eckit::ExecutionContext*);
+
+protected:
+    int setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue);
+
+private: // methods
+
+	void createColumns();
+
+    std::string defaultSQL(const eckit::PathName& db);
+    const odb::sql::SchemaAnalyzer& getSchema(const eckit::PathName& db);
+
+private: // members
+
+	eckit::PathName db_;
+
+	void *odbHandle_;
+	int noOfColumns_;
+	//colinfo_t *ci_;
+	void *ci_;
+	odb::MetaData *columns_;
+	int newDataset_;
+	double* data_;
+	int nd_;
+
+	bool schemaParsed_;
+	odb::sql::SQLInteractiveSession session_;
+
+	friend class FakeODBIterator;
+	//friend class ReptypeGenIterator;
+
+public: // members
+
+	int refCount_;
+	bool noMore_;
+    eckit::ExecutionContext* context_;
+};
+
+} // namespace tool 
+} // namespace odb 
+
+#endif
diff --git a/odb_api/src/odb_api/migrator/ODBMigratorModule.cc b/odb-tools/src/migrator/ODBMigratorModule.cc
similarity index 100%
copy from odb_api/src/odb_api/migrator/ODBMigratorModule.cc
copy to odb-tools/src/migrator/ODBMigratorModule.cc
diff --git a/odb_api/src/odb_api/migrator/ODBMigratorModule.h b/odb-tools/src/migrator/ODBMigratorModule.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/ODBMigratorModule.h
copy to odb-tools/src/migrator/ODBMigratorModule.h
diff --git a/odb_api/src/odb_api/migrator/Odb2_to_odb1_era.f90 b/odb-tools/src/migrator/Odb2_to_odb1_era.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/Odb2_to_odb1_era.f90
copy to odb-tools/src/migrator/Odb2_to_odb1_era.f90
diff --git a/odb-tools/src/migrator/OldODBReader.h b/odb-tools/src/migrator/OldODBReader.h
new file mode 100644
index 0000000..0aeb8ed
--- /dev/null
+++ b/odb-tools/src/migrator/OldODBReader.h
@@ -0,0 +1,25 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef odb_api_OldODBReader_H
+#define odb_api_OldODBReader_H
+
+#include "migrator/TSQLReader.h"
+#include "migrator/ODBIterator.h"
+
+namespace odb {
+namespace tool {
+
+typedef odb::tool::TSQLReader<ODBIterator> OldODBReader;
+
+} // namespace tool 
+} // namespace odb 
+
+#endif
diff --git a/odb-tools/src/migrator/ReptypeGenIterator.cc b/odb-tools/src/migrator/ReptypeGenIterator.cc
new file mode 100644
index 0000000..f0f5c8b
--- /dev/null
+++ b/odb-tools/src/migrator/ReptypeGenIterator.cc
@@ -0,0 +1,234 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file ReptypeGenIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <strings.h>
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "eckit/parser/StringTools.h"
+#include "eckit/parser/Tokenizer.h"
+#include "eckit/types/Types.h"
+#include "eckit/utils/Translator.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+std::ostream& operator<<(std::ostream& s, const ReptypeTable& m)
+{
+	s << "{";
+	for (ReptypeTable::const_iterator it = m.begin(); it != m.end(); ++it)
+	{
+		s << "[";
+		const Values& vals = it->first;
+		for (Values::const_iterator i = vals.begin(); i != vals.end(); ++i)
+			s << *i;
+		s << "]";
+
+		s << " : " << it->second << "," << std::endl;
+	}
+	s << "}";
+	return s;
+}
+
+/*
+Hi Peter,
+
+most of the columns given by Manuel do not exist yet.
+
+As a first attempt, you can use
+sensor at hdr,
+satname_1 at hdr,
+satname_2 at hdr,
+satname_3 at hdr,
+satname_4 at hdr,
+bufrtype at hdr,
+subtype at hdr,
+obstype at hdr,
+codetype at hdr
+(when sat.len > 0 you can add satid at sat).
+
+Anne. 
+*/
+
+std::vector<std::string> ReptypeTableConfig::columns_ = std::vector<std::string>();
+ReptypeTable ReptypeTableConfig::reptypeTable_ = ReptypeTable();
+
+void ReptypeTableConfig::load(const PathName& fileName)
+{
+	std::string s = Tool::readFile(fileName, false);
+	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << std::endl;
+	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << "'" << s << "'" << std::endl;
+
+    std::vector<std::string> lines = StringTools::split("\n", s);
+
+	size_t i = 0;
+	while (lines[i] == "")
+		++i;
+
+    std::vector<std::string> firstLine = StringTools::split(":", lines[i]);
+	ASSERT(firstLine[0] == "reptype");
+
+    std::vector<std::string> columnNames = StringTools::split(",", firstLine[1]);
+	std::for_each(columnNames.begin(), columnNames.end(), Tool::trimInPlace);
+
+	columns_.insert(columns_.end(), columnNames.begin(), columnNames.end());
+	++i;
+
+    for (; i < lines.size(); ++i)
+    {
+        std::vector<std::string> lr;
+        Tokenizer(":")(lines[i], lr);
+
+        // Skip empty lines.
+        if (lr.size() == 0) continue;
+
+		ASSERT(lr.size() == 2);
+
+		int reptype_value = Translator<std::string, int>()(lr[0]);
+
+        std::vector<std::string> rvalues = StringTools::split(",", lr[1]);
+		//Log::debug() << "ReptypeTableConfig::load: rvalues = " << rvalues << std::endl;
+
+		ASSERT("Number of values must be equal to number of column names (first line)"
+			&& columnNames.size() == rvalues.size());
+
+		std::for_each(rvalues.begin(), rvalues.end(), Tool::trimInPlace);
+		Values vals;
+		Log::debug() << "ReptypeTableConfig::load: " << reptype_value << " = ";
+		for (size_t j = 0; j < rvalues.size(); ++j)
+		{
+			std::string &vs(rvalues[j]);
+
+			Log::debug() << "{" << vs << ":" << Tool::isInQuotes(vs) << "}";
+			double v = Tool::isInQuotes(vs)
+				? Tool::cast_as_double(Tool::unQuote(vs))
+				: Translator<std::string, double>()(vs);
+			vals.push_back(v);
+			Log::debug() << "[" << rvalues[j] << "] '" << Tool::double_as_string(v) << "', " << std::endl;
+		}
+		Log::debug() << std::endl;
+		//at(vals) = reptype_value;
+		reptypeTable_[vals] = reptype_value;
+	}
+
+	//Log::debug() << "ReptypeTableConfig::load: columns_ = " << columns_ << std::endl; 
+	//Log::debug() << "ReptypeTableConfig::load: reptypeTable_ = " << reptypeTable_ << std::endl;
+}
+
+template<typename ITERATOR, typename CONFIG>
+ReptypeGenIterator<ITERATOR, CONFIG>::ReptypeGenIterator(const PathName& db, const std::string& sql)
+: iterator_(db, sql),
+  data_(0),
+  reptypeTable_(CONFIG::reptypeTable())
+{
+	odb::MetaData &md = iterator_.columns();
+	data_ = new double[md.size()];
+	reptypeIndex_ = md.columnIndex("reptype");
+
+	const std::vector<std::string>& columnNames = CONFIG::columns();
+	for (std::vector<std::string>::const_iterator i = columnNames.begin(); i != columnNames.end(); ++i)
+	{
+		std::string name = *i;
+
+		Log::debug() << "ReptypeGenIterator<ITERATOR>::ctor: " << name << std::endl;
+
+		indices_.push_back(iterator_.columns().columnIndex(name));
+		values_.push_back(0);
+	}
+	Log::debug() << "ReptypeGenIterator::ReptypeGenIterator: Reptype table:" << std::endl;
+	Log::debug() << "reptypeTable_ = " << reptypeTable_ << std::endl;
+}
+
+template<typename ITERATOR, typename CONFIG>
+ReptypeGenIterator<ITERATOR, CONFIG>::~ReptypeGenIterator()
+{
+	Log::debug() << "ReptypeGenIterator::~ReptypeGenIterator: Reptype table:" << std::endl;
+	Log::debug() << "reptypeTable_.size() = " << reptypeTable_.size() << std::endl;
+	Log::debug() << "reptypeTable_ =" << reptypeTable_ << std::endl;
+	delete [] data_;
+}
+
+template<typename ITERATOR, typename CONFIG>
+odb::MetaData& ReptypeGenIterator<ITERATOR, CONFIG>::columns()
+{
+	return iterator_.columns();
+}
+
+template<typename ITERATOR, typename CONFIG>
+double* ReptypeGenIterator<ITERATOR, CONFIG>::data()
+{
+	return data_;
+}
+
+template<typename ITERATOR, typename CONFIG>
+bool ReptypeGenIterator<ITERATOR, CONFIG>::isNewDataset()
+{
+	return iterator_.isNewDataset();
+}
+
+template<typename ITERATOR, typename CONFIG>
+bool ReptypeGenIterator<ITERATOR, CONFIG>::next(eckit::ExecutionContext* context)
+{
+	bool r = iterator_.next(context);
+	if (r)
+	{
+		double* trueData = iterator_.data();
+
+        std::copy(trueData, trueData + iterator_.columns().size(), data_);
+
+		for (size_t i = 0; i < indices_.size(); ++i)
+			values_[i] = data_[indices_[i]];
+
+		ReptypeTable::const_iterator it = reptypeTable_.find(values_); 
+		if (it != reptypeTable_.end())
+			data_[reptypeIndex_] = it->second;
+		else
+		{
+			// TODO: rethink!
+			Log::info() << "ReptypeGenIterator::next(): No matching report type, creating new one." << std::endl;
+
+			size_t newRT = reptypeTable_.size();
+			for (ReptypeTable::const_iterator i = reptypeTable_.begin(); i != reptypeTable_.end(); ++i)
+			{
+				size_t rt = i->second;
+				if (newRT <= rt)
+					newRT = rt + 1;
+			}
+
+			Log::info() << "ReptypeGenIterator::next(): New report type: " << newRT << std::endl;
+
+			data_[reptypeIndex_] = reptypeTable_[values_] = newRT;
+		}
+	}
+	noMore_ = !r;
+	return r;
+}
+
+template class ReptypeGenIterator<>;
+template class ReptypeGenIterator<FakeODBIterator>;
+
+} // namespace tool 
+} // namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/ReptypeGenIterator.h b/odb-tools/src/migrator/ReptypeGenIterator.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/ReptypeGenIterator.h
copy to odb-tools/src/migrator/ReptypeGenIterator.h
diff --git a/odb_api/src/odb_api/migrator/TSQLReader.cc b/odb-tools/src/migrator/TSQLReader.cc
similarity index 100%
copy from odb_api/src/odb_api/migrator/TSQLReader.cc
copy to odb-tools/src/migrator/TSQLReader.cc
diff --git a/odb_api/src/odb_api/migrator/TSQLReader.h b/odb-tools/src/migrator/TSQLReader.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/TSQLReader.h
copy to odb-tools/src/migrator/TSQLReader.h
diff --git a/odb_api/src/odb_api/migrator/all b/odb-tools/src/migrator/all
similarity index 100%
copy from odb_api/src/odb_api/migrator/all
copy to odb-tools/src/migrator/all
diff --git a/odb_api/src/odb_api/migrator/diurnal.f90 b/odb-tools/src/migrator/diurnal.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/diurnal.f90
copy to odb-tools/src/migrator/diurnal.f90
diff --git a/odb-tools/src/migrator/migrator_api.cc b/odb-tools/src/migrator/migrator_api.cc
new file mode 100644
index 0000000..c90753e
--- /dev/null
+++ b/odb-tools/src/migrator/migrator_api.cc
@@ -0,0 +1,38 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "migrator/ImportODBTool.h"
+#include "migrator/migrator_api.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/odbcapi.h"
+#include "odb_api/tools/Tool.h"
+
+
+namespace odb {
+namespace tool {
+
+int import_odb_with_sql_in_file(const char* odb_database, const char* sql_file, const char* output_file)
+{
+    try {
+        const char *argv[] = {"importodb",  odb_database, sql_file, output_file, 0 };
+        odb_start_with_args(1, const_cast<char **>(argv));
+        ImportODBTool<> importer(4, const_cast<char **>(argv));
+        importer.run();
+        return 0;
+    } catch (...) {
+        return 1;
+    }
+}
+
+
+} // namespace tool 
+} //namespace odb 
+
+
diff --git a/odb_api/src/odb_api/migrator/migrator_api.h b/odb-tools/src/migrator/migrator_api.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/migrator_api.h
copy to odb-tools/src/migrator/migrator_api.h
diff --git a/odb_api/src/odb_api/migrator/odb1.f90 b/odb-tools/src/migrator/odb1.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/odb1.f90
copy to odb-tools/src/migrator/odb1.f90
diff --git a/odb_api/src/odb_api/migrator/odb2.f90 b/odb-tools/src/migrator/odb2.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/odb2.f90
copy to odb-tools/src/migrator/odb2.f90
diff --git a/odb_api/src/odb_api/migrator/odb2_flag_definitions.f90 b/odb-tools/src/migrator/odb2_flag_definitions.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/odb2_flag_definitions.f90
copy to odb-tools/src/migrator/odb2_flag_definitions.f90
diff --git a/odb-tools/src/migrator/odb2oda.cc b/odb-tools/src/migrator/odb2oda.cc
new file mode 100755
index 0000000..e12ba46
--- /dev/null
+++ b/odb-tools/src/migrator/odb2oda.cc
@@ -0,0 +1,66 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "eckit/filesystem/PathName.h"
+#include "eckit/io/FileHandle.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/MigratorTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+#include "odb_api/tools/ToolRunnerApplication.h"
+
+
+using namespace std;
+using namespace odb::tool;
+
+// Cannot use just string for str because of a clash with a typedef in ODB header...
+typedef std::string str;
+
+int gdb(int argc, char *argv[]);
+int valgrind(int argc, char *argv[]);
+
+//void test_schemaFile();
+
+int main(int argc, char *argv[])
+{
+    CommandLineParser clp(argc, argv);
+	clp.registerOptionWithArgument("-genreptype");
+    clp.registerOptionWithArgument("-reptypecfg");
+    clp.registerOptionWithArgument("-addcolumns");
+    clp.registerOptionWithArgument("-mdi");
+    clp.parameters();
+
+    cout << clp << std::endl;
+
+	ToolRunnerApplication runner(argc, argv, false, false);
+	//ToolRunnerApplication runner(clp, false, false);
+	MigratorTool migrator(clp);
+	runner.tool(&migrator);
+	return runner.start();
+}
+
+#if 0
+#include <assert.h>
+
+void test_schemaFile() {
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ECMA.tmi") == "/asdfasd/sdfas/ECMA.tmi/ECMA.sch");
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi/") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("ODA.tmi/") == "ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("ODA.tmi") == "ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("dupa/ODA.tmi") == "dupa/ODA.tmi/ODA.sch");
+}
+#endif 
+
+
diff --git a/odb_api/src/odb_api/migrator/odbdump.h b/odb-tools/src/migrator/odbdump.h
similarity index 100%
copy from odb_api/src/odb_api/migrator/odbdump.h
copy to odb-tools/src/migrator/odbdump.h
diff --git a/odb_api/src/odb_api/migrator/pyodbdump.i b/odb-tools/src/migrator/pyodbdump.i
similarity index 100%
copy from odb_api/src/odb_api/migrator/pyodbdump.i
copy to odb-tools/src/migrator/pyodbdump.i
diff --git a/odb_api/src/odb_api/migrator/pyodbdump_example.py b/odb-tools/src/migrator/pyodbdump_example.py
similarity index 100%
copy from odb_api/src/odb_api/migrator/pyodbdump_example.py
copy to odb-tools/src/migrator/pyodbdump_example.py
diff --git a/odb_api/src/odb_api/migrator/solar_elevation.f90 b/odb-tools/src/migrator/solar_elevation.f90
similarity index 100%
copy from odb_api/src/odb_api/migrator/solar_elevation.f90
copy to odb-tools/src/migrator/solar_elevation.f90
diff --git a/odb_api/src/odb_api/migrator/solar_elevation.sc b/odb-tools/src/migrator/solar_elevation.sc
similarity index 100%
copy from odb_api/src/odb_api/migrator/solar_elevation.sc
copy to odb-tools/src/migrator/solar_elevation.sc
diff --git a/odb_api/src/odb_api/migrator/test_migrator.ecml b/odb-tools/src/migrator/test_migrator.ecml
similarity index 100%
copy from odb_api/src/odb_api/migrator/test_migrator.ecml
copy to odb-tools/src/migrator/test_migrator.ecml
diff --git a/odb-tools/src/odb2_to_odb1/CMakeLists.txt b/odb-tools/src/odb2_to_odb1/CMakeLists.txt
new file mode 100644
index 0000000..6d6caad
--- /dev/null
+++ b/odb-tools/src/odb2_to_odb1/CMakeLists.txt
@@ -0,0 +1,27 @@
+ecbuild_add_executable(
+
+    TARGET odb2_to_odb1.x
+
+    INCLUDES
+        ${ODB_INCLUDE_DIRS}
+        ${ODB_INCLUDE_DIRS}/../module
+        ${ECKIT_INCLUDE_DIRS}
+
+    SOURCES
+        Odb2Odb1.cc
+        Odb2Odb1.h
+        Odb2Odb1Main.cc
+        mpi_wrapper.F90
+        mpif.h
+        odb_wrapper.F90
+        odbi.F90
+
+    LIBS
+        Odb_fortran
+        Odb
+        eckit
+        ${ODB_LIBRARIES}
+)
+
+include(odb_link_schemas)
+odb_link_schemas(odb2_to_odb1.x ${ODB_SCHEMAS})
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.cc b/odb-tools/src/odb2_to_odb1/Odb2Odb1.cc
similarity index 100%
copy from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.cc
copy to odb-tools/src/odb2_to_odb1/Odb2Odb1.cc
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.h b/odb-tools/src/odb2_to_odb1/Odb2Odb1.h
similarity index 100%
copy from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.h
copy to odb-tools/src/odb2_to_odb1/Odb2Odb1.h
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1Main.cc b/odb-tools/src/odb2_to_odb1/Odb2Odb1Main.cc
similarity index 100%
copy from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1Main.cc
copy to odb-tools/src/odb2_to_odb1/Odb2Odb1Main.cc
diff --git a/odb_api/src/odb_api/odb2_to_odb1/mpi_wrapper.F90 b/odb-tools/src/odb2_to_odb1/mpi_wrapper.F90
similarity index 100%
copy from odb_api/src/odb_api/odb2_to_odb1/mpi_wrapper.F90
copy to odb-tools/src/odb2_to_odb1/mpi_wrapper.F90
diff --git a/odb_api/src/odb_api/odb2_to_odb1/mpif.h b/odb-tools/src/odb2_to_odb1/mpif.h
similarity index 100%
copy from odb_api/src/odb_api/odb2_to_odb1/mpif.h
copy to odb-tools/src/odb2_to_odb1/mpif.h
diff --git a/odb-tools/src/odb2_to_odb1/odb_wrapper.F90 b/odb-tools/src/odb2_to_odb1/odb_wrapper.F90
new file mode 100644
index 0000000..80afe13
--- /dev/null
+++ b/odb-tools/src/odb2_to_odb1/odb_wrapper.F90
@@ -0,0 +1,753 @@
+!> @file   odb_wrapper.F90
+!> @author Anne Fouilloux
+
+!----------------------------------------------------------------------
+function odb_no_of_local_pools_c(handle) bind(C, name="odb_no_of_local_pools_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                :: handle
+  integer(C_INT)                      :: odb_no_of_local_pools_c
+
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_nmypools
+
+  f90_handle = handle
+
+  f90_nmypools = ODB_poolinfo(f90_handle)
+
+  odb_no_of_local_pools_c = f90_nmypools
+
+end function odb_no_of_local_pools_c
+!----------------------------------------------------------------------
+function odb_get_local_pools_c(handle, local_pools) bind(C, name="odb_get_local_pools_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  integer(C_INT),VALUE                :: handle
+  integer(C_INT)                      :: odb_get_local_pools_c
+  type(c_int_array), intent(out)      :: local_pools
+  integer(C_INT), pointer             :: c_local_pools(:)
+
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_nmypools
+
+  f90_handle = handle
+
+  call C_F_POINTER(local_pools%array, c_local_pools, (/local_pools%len/))
+
+  f90_nmypools = ODB_poolinfo(f90_handle, c_local_pools)
+
+  odb_get_local_pools_c = f90_nmypools
+
+end function odb_get_local_pools_c
+!----------------------------------------------------------------------
+function odb_open_c(dbname, dbname_length, mode, mode_length, npools) bind(C, name="odb_open_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+  use mpl_module
+
+  implicit none
+
+  character(kind=C_CHAR), dimension(*) :: dbname
+  character(kind=C_CHAR), dimension(*) :: mode
+  integer(C_INT)                       :: npools
+  integer(C_INT),VALUE                 :: dbname_length
+  integer(C_INT),VALUE                 :: mode_length
+  integer(C_INT)                       :: odb_open_c
+
+  character(len=64)                    :: f90_dbname
+  character(len=64)                    :: f90_mode
+  integer(kind=JPIM)                   :: f90_npools
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: f90_rc
+  integer(kind=JPIM)                   :: i
+
+
+  f90_npools = npools
+  f90_dbname=""
+  do i=1, dbname_length
+    if (dbname(i) .eq. C_NULL_CHAR) exit
+    f90_dbname(i:i)  = dbname(i)
+  end do
+  f90_mode=""
+  do i=1, mode_length
+    if (mode(i) .eq. C_NULL_CHAR) exit
+    f90_mode(i:i)  = mode(i)
+  end do
+
+  f90_handle = ODB_open(f90_dbname, f90_mode, f90_npools)
+  odb_open_c = f90_handle
+! write flag files
+  call cODB_print_flags_file(f90_dbname, MPL_MYRANK(), f90_rc)
+end function odb_open_c
+!----------------------------------------------------------------------
+function odb_close_c(handle, save) bind(C, name="odb_close_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                :: handle
+  logical(C_BOOL), VALUE              :: save
+  integer(C_INT)                      :: odb_close_c
+
+  logical                             :: f90_save
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_err
+
+  f90_save = save
+  f90_handle = handle
+  write(0,*) 'ODB_close f90_save = ', f90_save, ' f90_handle = ', f90_handle
+  f90_err = ODB_close(f90_handle, f90_save)
+  odb_close_c = f90_err
+end function odb_close_c
+!----------------------------------------------------------------------
+function odb_swapout_c(handle, dtname, dtname_length, poolno, save, repack) bind(C, name="odb_swapout_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                 :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT),VALUE                 :: poolno
+  logical(C_BOOL), VALUE               :: save
+  logical(C_BOOL), VALUE               :: repack
+  integer(C_INT)                       :: odb_swapout_c
+
+  integer(kind=JPIM)                   :: f90_poolno
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  logical                              :: f90_save, f90_repack
+  integer(kind=JPIM)                   :: i
+  integer(kind=JPIM)                   :: rc
+
+  f90_dtname=""
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i:i)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_poolno = poolno
+  f90_save = save
+  f90_repack = repack
+
+  rc = ODB_swapout(f90_handle, f90_dtname, poolno=f90_poolno, save=f90_save, repack=f90_repack)
+
+  odb_swapout_c = rc
+end function odb_swapout_c
+!----------------------------------------------------------------------
+function odb_get_no_of_columns_c(handle, dtname, dtname_length) bind(C, name="odb_get_no_of_columns_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT)                       :: odb_get_no_of_columns_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, at_offset
+
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+  odb_get_no_of_columns_c = f90_ncols
+end function odb_get_no_of_columns_c
+!----------------------------------------------------------------------
+subroutine odb_api_get_colnames(odb_iterator, colnames, c_ncols, idx_seqno, masterKey)
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  TYPE(C_PTR)                               :: odb_iterator
+  character(len=maxvarlen), dimension(*)    :: colnames
+  integer(kind=C_INT)                       :: c_ncols
+  integer(kind=JPIM), intent(out)           :: idx_seqno
+  character(len=maxvarlen)                  :: masterKey
+
+  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
+
+  type(C_PTR)                                   :: ptr_colname
+  integer(kind=C_INT)                           :: cerr, size_name
+  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
+  character(len=256)                            :: colname
+
+    idx_seqno =-1
+
+    do i=1, c_ncols
+      ptr_colname = C_NULL_PTR
+      colname(:) = ""
+      cerr = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
+      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
+      do j=1, size_name
+       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
+       colname(j:j)  = f_ptr_colname(j)
+      end do
+      at_idx = index(colname, '@')
+      if (at_idx > 0) then
+        colnames(i) = colname(:at_idx-1)
+      else
+        colnames(i) = colname
+      endif
+      if (trim(colnames(i)) .eq. masterKey) then
+        idx_seqno = i
+      endif
+    enddo
+end subroutine odb_api_get_colnames
+!----------------------------------------------------------------------
+function odb_create_index_c(handle, dtname, dtname_length, odb_iterator, &
+                            idx_odb, idx_size ) bind(C, name="odb_create_index_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  TYPE(C_PTR)                          :: odb_iterator
+  integer(kind=C_INT), dimension(*)    :: idx_odb
+  integer(C_INT),VALUE                 :: idx_size
+  integer(kind=C_INT)                  :: odb_create_index_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
+
+  INTEGER(kind=C_INT)                  :: c_ncols
+
+  type(C_PTR)                                   :: ptr_colname
+  integer(kind=C_INT)                           :: size_name
+  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
+  character(len=256)                            :: coltable, colname, temp(1)
+  integer(kind=JPIM)                            :: f90_idx(1)
+  integer(kind=JPIM)                            :: rc
+
+
+
+  odb_create_index_c = 0
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+
+  odb_create_index_c = odb_read_get_no_of_columns(odb_iterator, c_ncols)
+
+  if (idx_size == c_ncols) then
+    do i=1, c_ncols
+      odb_create_index_c = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
+      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
+      do j=1, size_name
+       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
+       colname(j:j)  = f_ptr_colname(j)
+      end do
+      at_idx = index(colname, '@')
+      if (at_idx > 0) then
+        temp(1) = colname(:at_idx-1)
+        coltable = colname(at_idx:)
+
+      else
+        temp(1) = colname
+        coltable=""
+      endif
+      f90_idx=-1
+      if (trim(coltable) == trim(f90_dtname)) then
+
+      rc = ODB_varindex(f90_handle, f90_dtname, temp, f90_idx)
+      if (f90_idx(1) > 0) then
+        idx_odb(i)  = f90_idx(1)
+      endif
+      endif
+    enddo
+  endif
+
+end function odb_create_index_c
+!----------------------------------------------------------------------
+function ODB_whatis(colname, flaglist)
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+
+  implicit none
+  character(len=*), intent(in)    :: colname
+  type(C_PTR),        intent(in)  :: flaglist
+  integer(kind=JPIM)              :: ODB_whatis
+  integer(kind=JPIM)              :: idx_l, idx_r, i
+  integer(kind=C_INT)             :: c_whatis, typeOfTable
+  character(kind=C_CHAR),dimension(257)  :: c_colname
+
+  ODB_whatis = ODB_NMDI
+
+  c_colname(:)=' '
+  do i=1,len(trim(colname))
+    c_colname(i) = colname(i:i)
+  enddo
+  c_colname(i+1) = C_NULL_CHAR
+  c_whatis = typeOfTable(c_colname, flaglist)
+  ODB_whatis = c_whatis
+  !write(0,*) 'ODB_whatis = ', trim(colname), ' ' ,  ODB_whatis
+end function ODB_whatis
+!----------------------------------------------------------------------
+subroutine odb_fill_c(handle, filename, odb_hdr_array, odb_body_array, flaglist, c_masterKey, c_len, np) bind(C, name="odb_fill_f90")
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+  use odbi
+
+  implicit none
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  interface
+     function ODB_whatis(colname, flaglist)
+       use, intrinsic :: iso_c_binding
+       use odb_module
+
+       implicit none
+       character(len=*), intent(in)    :: colname
+       type(C_PTR), intent(in)         :: flaglist
+       integer(kind=JPIM)              :: ODB_whatis
+     end function ODB_whatis
+  end interface
+
+
+  integer(C_INT), VALUE                  :: handle
+  character(kind=C_CHAR), dimension(*)   :: filename
+  character(kind=C_CHAR), dimension(*)   :: c_masterKey
+  type(C_PTR), intent(in)                :: flaglist
+  integer(C_INT),VALUE                   :: c_len, np
+
+  type(c_int_array), intent(in)          :: odb_hdr_array
+  type(c_int_array), intent(inout)       :: odb_body_array
+  integer(kind=JPIM)                     :: f90_handle
+  integer(kind=JPIM)                     :: f90_np
+
+  character(len=256), allocatable        :: tablenames(:)
+  type(t_odbtable), allocatable          :: odbtables(:)
+  integer(kind=JPIM)                     :: ntables
+  integer(kind=JPIM)                     :: rc, i, j, f90_nrows, f90_ncols
+  integer(kind=JPIM)                     :: idx_seqno, ihdr, ibody
+  character(len=maxvarlen)               :: masterKey, cltable
+  integer(C_INT), pointer                :: c_odb_hdr_array(:)
+  integer(C_INT), pointer                :: c_odb_body_array(:)
+
+  type(C_PTR)                                            :: odb_handler, odb_it
+  character(kind=C_CHAR, len=64)                         :: config = C_NULL_CHAR
+  integer(kind=C_INT)                                    :: cerr, new_dataset, ncols
+  logical                                                :: LLfirstdataset, LLindexNotdone
+  real(kind=C_DOUBLE), dimension(:), allocatable         :: one_row
+  character(len=maxvarlen), allocatable                  :: colnames_in(:)
+  character(len=64)                                      :: f90_filename
+  integer(kind=JPIM)                                     :: previous_seqno
+
+  f90_filename=""
+  do i=1, maxvarlen
+    if (filename(i) .eq. C_NULL_CHAR) exit
+    f90_filename(i:i)  = filename(i)
+  end do
+
+
+  masterKey=""
+  do i=1, c_len
+    if (c_masterKey(i) .eq. C_NULL_CHAR) exit
+    masterKey(i:i)  = c_masterKey(i)
+  end do
+
+! associate c_odb_hdr_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
+  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
+
+  write(0,*) 'masterKey= ', trim(masterKey)
+  write(0,*) 'number of BODY entries = ', odb_body_array%len
+  write(0,*) 'number of HDR entries = ', odb_hdr_array%len
+  f90_handle = handle
+  f90_np = np
+
+  ntables = ODB_getnames(f90_handle, '*', 'table')
+  allocate(tablenames(ntables))
+  ntables = ODB_getnames(f90_handle, '*', 'table', tablenames)
+  allocate(odbtables(ntables))
+  odbtables(:)%table_kind = -1
+  do j=1,ntables
+    NULLIFY(odbtables(j)%data)
+    NULLIFY(odbtables(j)%index)
+    NULLIFY(odbtables(j)%colnames)
+    odbtables(j)%table_kind = ODB_whatis(trim(tablenames(j)), flaglist)
+    if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .or. odbtables(j)%table_kind  == ODB_BODY_ALIGNED) then
+      odbtables(j)%tablename = trim(tablenames(j))
+      cltable = odbtables(j)%tablename
+      f90_ncols = ODB_getnames(f90_handle,cltable,'name')
+      allocate(odbtables(j)%colnames(f90_ncols))
+      rc = ODB_getnames(f90_handle,cltable,'name', outnames=odbtables(j)%colnames)
+!*AF      write(0,*) trim(cltable), 'f90_ncols = ', f90_ncols
+      if (odbtables(j)%table_kind  == ODB_HDR_ALIGNED) then
+        allocate(odbtables(j)%data(int(odb_hdr_array%len),0:f90_ncols))
+      else
+        allocate(odbtables(j)%data(int(odb_body_array%len),0:f90_ncols))
+      endif
+      odbtables(j)%data(:,:) = 0.0
+    endif
+  enddo
+
+! start to read the input file
+  LLfirstdataset=.true.
+  LLindexNotdone=.true.
+  ihdr=1
+  ibody=1
+!*AF  write(0,*) 'LLfirstdataset=.true. ', LLfirstdataset, ' LLindexNotdone= ', LLindexNotdone
+  odb_handler = odb_read_new(config, cerr)
+  odb_it = odb_read_iterator_new(odb_handler, filename, cerr);
+  cerr = odb_read_get_no_of_columns(odb_it, ncols)
+  if (allocated(one_row)) deallocate(one_row)
+  allocate(one_row(ncols))
+
+  previous_seqno = -1
+  do while (odb_read_get_next_row(odb_it, ncols, one_row, new_dataset) == 0)
+    LLindexNotdone = (new_dataset > 0) .or. LLfirstdataset
+    if (LLindexNotDone) then
+      LLfirstdataset = .false.
+! we must compute the list of index in ODB-1 valid in the current ODB-2 one_row
+      allocate(colnames_in(ncols))
+      colnames_in(:) = ""
+      call odb_api_get_colnames(odb_it, colnames_in, ncols, idx_seqno, masterKey)
+!*AF      do j=1, ncols
+!*AF        write(0,*) 'colnames_in (odb-api) (', j,')= ', trim(colnames_in(j))
+!*AF      enddo
+      do j=1, ntables
+        if (odbtables(j)%table_kind > 0) then
+          allocate(odbtables(j)%index(ncols))
+          rc = ODB_varindex(f90_handle,odbtables(j)%tablename , colnames_in, odbtables(j)%index)
+          !write(0,*) 'table = ', trim(odbtables(j)%tablename), ' ', odbtables(j)%index
+        endif
+      enddo
+
+      deallocate(colnames_in)
+
+!*AF      write(0,*) 'new_dataset'
+    endif
+    do j=1, ntables
+      if (odbtables(j)%table_kind > 0) then
+       do i=1, ncols
+         if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .and. &
+             one_row(idx_seqno) /= previous_seqno &
+             .and. odbtables(j)%index(i) > 0) then
+           !write(0,*) one_row(idx_seqno), c_odb_hdr_array(ihdr), ihdr, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
+           odbtables(j)%data(ihdr, odbtables(j)%index(i)) = one_row(i)
+         else if (odbtables(j)%table_kind == ODB_BODY_ALIGNED .and. &
+             odbtables(j)%index(i) > 0) then
+           !write(0,*) ibody, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
+           odbtables(j)%data(ibody, odbtables(j)%index(i)) = one_row(i)
+         endif
+       enddo
+      endif
+    enddo
+    c_odb_body_array(ibody) = one_row(idx_seqno)
+    ibody = ibody + 1
+    if (one_row(idx_seqno) /= previous_seqno) then
+      previous_seqno = c_odb_hdr_array(ihdr)
+      ihdr = ihdr + 1
+    endif
+  enddo
+  if (allocated(one_row)) deallocate(one_row)
+  cerr = odb_read_iterator_delete(odb_it)
+  cerr = odb_read_delete(odb_handler)
+! deallocation
+ do j=1,ntables
+    if (odbtables(j)%table_kind > 0) then
+     f90_nrows = size(odbtables(j)%data,1)
+     f90_ncols = size(odbtables(j)%data,2)
+!*AF     write(0,*) 'ODB_put ', trim(odbtables(j)%tablename), f90_nrows, f90_ncols, f90_np
+     !do i=1, f90_nrows
+     !  write(*,*) i, 'row ', odbtables(j)%data(i,:)
+     !enddo
+     rc = ODB_put(f90_handle, odbtables(j)%tablename, odbtables(j)%data, &
+        f90_nrows, f90_ncols, poolno = f90_np)
+    endif
+    if (associated(odbtables(j)%data)) deallocate(odbtables(j)%data)
+    if (associated(odbtables(j)%index)) deallocate(odbtables(j)%index)
+    if (associated(odbtables(j)%colnames)) deallocate(odbtables(j)%colnames)
+ enddo
+ deallocate(odbtables)
+ deallocate(tablenames)
+end subroutine odb_fill_c
+!----------------------------------------------------------------------
+function odb_put_one_row_c(handle, dtname, dtname_length, odb_row, idx_odb, ncols, np) bind(C, name="odb_put_one_row_f90")
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  real(kind=C_DOUBLE), dimension(*)    :: odb_row
+  integer(kind=C_INT), dimension(*)    :: idx_odb
+  integer(C_INT),VALUE                 :: ncols
+  integer(C_INT),VALUE                 :: np
+  integer(kind=C_INT)                  :: odb_put_one_row_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: f90_np
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, at_offset
+  integer(kind=JPIM)                   :: nrows
+  real(kind=JPRD), allocatable         :: f90_one_row(:,:)
+
+  odb_put_one_row_c = 0
+  nrows = 1
+
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+
+  f90_np = np
+  allocate(f90_one_row(nrows,0:f90_ncols))
+
+  f90_one_row=0
+  do i=1, ncols
+    f90_one_row(1,idx_odb(i)) = odb_row(i)
+  enddo
+
+  odb_put_one_row_c = ODB_put(f90_handle, f90_dtname, f90_one_row, nrows, f90_ncols, poolno = f90_np)
+  deallocate(f90_one_row)
+
+end function odb_put_one_row_c
+!----------------------------------------------------------------------
+subroutine compute_links(ilink, c_odb_len_array)
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  integer(C_INT), intent(in)         :: c_odb_len_array(:)
+  integer(KIND=JPIM), intent(inout)    :: ilink(:)
+
+  integer(kind=JPIM)          :: i, j
+  integer(kind=JPIM)          :: previous_seqno, bodylen
+
+  !write(0,*) 'Size of ilink = ', size(ilink, dim=1), size(c_odb_len_array, dim=1)
+
+  if (size(ilink, dim=1) == size(c_odb_len_array, dim=1)) then
+    ilink=1
+  else
+    ilink=-1
+    previous_seqno = c_odb_len_array(1)
+    bodylen=0
+    j=1
+    do i=1, size(c_odb_len_array, dim=1)
+!*AF      write(0,*) 'previous_seqno = ', previous_seqno, ' seqno = ', c_odb_len_array(i)
+      if (previous_seqno /= c_odb_len_array(i)) then
+! we have a different seqno so we can set the len of the previous body part
+        ilink(j) = bodylen
+!*AF        write(0,*) 'ilink(', j, ')=', ilink(j)
+        bodylen=0
+        j = j+1
+        previous_seqno = c_odb_len_array(i)
+      endif
+      bodylen = bodylen + 1
+    enddo
+    if (previous_seqno == c_odb_len_array(size(c_odb_len_array, dim=1))) ilink(j) = bodylen
+  endif
+end subroutine compute_links
+!----------------------------------------------------------------------
+function odb_update_links_c(handle, dtname, dtname_length, poolno, odb_hdr_array, odb_body_array, flaglist) bind(C, name="odb_update_links_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  interface
+    subroutine compute_links(ilink, c_odb_len_array)
+      use, intrinsic :: iso_c_binding
+      use            :: odb_module
+      integer(C_INT), intent(in)         :: c_odb_len_array(:)
+      integer(KIND=JPIM), intent(inout)  :: ilink(:)
+     end subroutine compute_links
+
+     function ODB_whatis(colname, flaglist)
+       use, intrinsic :: iso_c_binding
+       use odb_module
+
+       implicit none
+       character(len=*), intent(in)    :: colname
+       type(C_PTR), intent(in)  :: flaglist
+       integer(kind=JPIM)              :: ODB_whatis
+     end function ODB_whatis
+  end interface
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  type(C_PTR), intent(in)              :: flaglist
+  integer(C_INT),VALUE                 :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT),VALUE                 :: poolno
+  type(c_int_array), intent(in)        :: odb_hdr_array
+  type(c_int_array), intent(in)        :: odb_body_array
+  integer(C_INT)                       :: odb_update_links_c
+
+  integer(C_INT), pointer              :: c_odb_hdr_array(:)
+  integer(C_INT), pointer              :: c_odb_body_array(:)
+
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: f90_poolno
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: i, j
+  integer(kind=JPIM)                   :: rc
+  integer(kind=JPIM)                   :: nrows, ncols, nra
+  character(len=256), allocatable      :: colnames(:)
+  integer(kind=JPIM), allocatable      :: col_aligned(:)
+  character(len=256)                   :: colname
+  real(KIND=JPRD), allocatable         :: x(:,:)
+  integer(KIND=JPIM), allocatable      :: ilink_hdr(:)
+  integer(KIND=JPIM), allocatable      :: ilink_body(:)
+  integer(kind=JPIM)                   :: ioffset_hdr
+  integer(kind=JPIM)                   :: ioffset_body
+
+  odb_update_links_c = 0
+
+! associate c_odb_hdr_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
+
+! associate c_odb_body_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
+
+  f90_handle = handle
+  f90_poolno = poolno
+  f90_dtname=""
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i:i)  = dtname(i)
+  end do
+
+
+  rc = ODB_addview(f90_handle, f90_dtname, abort = .false.)
+  write(0,*) 'rc = ', rc, 'odb_update_links_c f90_handle = ', f90_handle, ' f90_poolno = ', f90_poolno, &
+             ' f90_dtname = ', trim(f90_dtname), ' odb_hdr_array.len = ',size(c_odb_hdr_array), &
+             ' odb_body_array.len = ',size(c_odb_body_array)
+
+  if (rc > 0) then
+! this SQL is registered and we can fecth data from ODB
+    rc = ODB_select(f90_handle,f90_dtname,nrows,ncols,nra=nra,poolno=f90_poolno)
+!*AF    write(0,*) 'odb_update_links_c ', trim(f90_dtname), ' nrows = ', nrows, ' ncols = ', ncols
+    if (nrows > 0) then
+      ALLOCATE(x(nra,0:ncols))
+      ALLOCATE(ilink_hdr(nrows))
+      ALLOCATE(ilink_body(nrows))
+      ALLOCATE(colnames(ncols))
+      ALLOCATE(col_aligned(ncols))
+      rc = ODB_get(f90_handle,f90_dtname,x,nrows,ncols,poolno=f90_poolno)
+      call compute_links(ilink_hdr, c_odb_hdr_array)
+      call compute_links(ilink_body, c_odb_body_array)
+      rc = ODB_getnames(f90_handle, f90_dtname, 'name', colnames)
+      col_aligned(:)=ODB_NMDI
+      do j=1, ncols
+        colname = trim(colnames(j))
+        if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
+           col_aligned(j) = ODB_whatis(colname, flaglist) ! offset
+           col_aligned(j+1) = col_aligned(j)              ! len
+        endif
+      enddo
+
+      ioffset_hdr = 0
+      ioffset_body = 0
+       ! write(0,*) 'nrows = ', nrows, ' ncols = ', ncols
+      do i=1, nrows
+        do j=1, ncols
+          colname = trim(colnames(j))
+          if (len(colname) > 7 .and. colname(1:7) == 'LINKLEN') then
+             if (col_aligned(j) == ODB_HDR_ALIGNED) then
+               x(i,j) = ilink_hdr(i)
+             else if (col_aligned(j)  == ODB_BODY_ALIGNED) then
+               x(i,j) = ilink_body(i)
+             else
+               x(i,j) = 0
+             endif
+          else if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
+             if (col_aligned(j)  == ODB_HDR_ALIGNED) then
+               x(i,j) = ioffset_hdr
+             else if (col_aligned(j) == ODB_BODY_ALIGNED) then
+               x(i,j) = ioffset_body
+             else
+               x(i,j) = 0
+             endif
+          endif
+        enddo
+        ioffset_hdr = ioffset_hdr + ilink_hdr(i)
+        ioffset_body = ioffset_body + ilink_body(i)
+      enddo
+      rc = ODB_put(f90_handle,f90_dtname,x, nrows,ncols,poolno=f90_poolno)
+      DEALLOCATE(x)
+      DEALLOCATE(ilink_hdr)
+      DEALLOCATE(ilink_body)
+      DEALLOCATE(colnames)
+      DEALLOCATE(col_aligned)
+    endif
+    rc = ODB_cancel(f90_handle,f90_dtname,poolno=f90_poolno)
+  else
+   write(0,*) '******Warning: retrieval ', trim(f90_dtname), ' is not registered'
+  endif
+
+end function odb_update_links_c
+
+!----------------------------------------------------------------------
diff --git a/odb-tools/src/odb2_to_odb1/odbi.F90 b/odb-tools/src/odb2_to_odb1/odbi.F90
new file mode 100644
index 0000000..510f093
--- /dev/null
+++ b/odb-tools/src/odb2_to_odb1/odbi.F90
@@ -0,0 +1,286 @@
+!> @file   odbi.F90
+!> @author Anne Fouilloux
+
+module odbi
+
+  use iso_c_binding
+  use odb_c_binding
+  use odb_module
+  USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+  implicit none
+  integer, parameter :: MAX_STRING=1024
+  integer, parameter :: ODB_MAX_ENTRYNO = 1000
+  integer, parameter :: ODB_MAX_ROWS = 100000
+
+  type t_odbtable
+    character(len=maxvarlen)                         :: tablename
+    integer(kind=JPIM)                               :: table_kind
+    real(kind=JPRD), pointer                         :: data(:,:)
+    character(len=MAX_STRING), dimension(:), pointer :: colnames
+    integer(kind=JPIM), dimension(:), pointer        :: index
+  end type t_odbtable
+  type t_bufr2odb
+    logical                                          :: LLcreate_odb_header
+    type(C_PTR)                                      :: c_handle
+    type(C_PTR)                                      :: c_odb_it
+    integer(kind=JPIM)                               :: handle
+    integer(kind=C_INT)                              :: c_ncolumns
+    character(len=MAX_STRING), dimension(:), pointer :: ODBcolname
+    integer(kind=JPIM), dimension(:), pointer        :: ODBcoltype
+    integer(kind=JPIM)                               :: nrows
+  end type t_bufr2odb
+
+  type t_odb2odb1
+    character(len=MAX_STRING)              :: tablename
+    logical                                :: aligned_header
+    logical                                :: aligned_body
+    integer(kind=JPIM), pointer            :: ODB1index(:)
+    character(len=MAX_STRING), pointer     :: colnames(:)
+    logical, pointer                       :: col_is_len(:)
+    logical, pointer                       :: child_is_body(:)
+    type(t_odb2odb1), pointer              :: next
+  end type t_odb2odb1
+
+
+  type relative
+     integer(kind=JPIM)                                   :: idx     ! index dans dbinfo%tables
+     type(relative), pointer                              :: next
+  end type relative
+
+  type tableinfo
+     character(len=MAX_STRING)                            :: ODBtablename  ! ODB table name @table i.e. contains "@"
+     integer(JPIM)                                        :: ODBncols      ! number of ODB columns
+     character(len=MAX_STRING), dimension(:), allocatable :: ODBcolname
+     character(len=MAX_STRING), dimension(:), allocatable :: ODBtypename
+     integer(kind=JPIM), dimension(:), allocatable        :: ODB2ODAindex
+     integer(kind=JPIM)                                   :: ODAncols  ! if 0 it means this table is not present in ODA
+     real(kind=JPRD), dimension(:,:), allocatable         :: ODBrow
+     real(kind=JPRD), dimension(:), allocatable           :: ODBonerow
+     integer(kind=JPIM)                                   :: ODBnrows
+     integer(kind=JPIM)                                   :: nchildren
+     logical                                              :: cut ! true if we need to cut
+     logical                                              :: done ! true if already proceeded
+     logical                                              :: ODBwrite ! true if we need to write in ODB
+     integer(kind=JPIM)                                   :: len_idx ! index in ODBcol of LEN
+     integer(kind=JPIM)                                   :: offset_idx ! index in ODBcol of OFFSET
+     type(relative), pointer                              :: child
+     type(relative), pointer                              :: aligned
+     type(relative), pointer                              :: onelooper
+     type(relative), pointer                              :: parent
+  end type tableinfo
+
+  type dbinfo
+     character(len=MAX_STRING)                  :: dbname
+     integer(kind = JPIM)                       :: handle
+     integer(kind = JPIM)                       :: ntables
+     integer(kind = JPIM)                       :: npools
+     integer(kind = JPIM)                       :: current_poolno
+     integer(kind = JPIM)                       :: current_seqno
+     integer(kind = JPIM)                       :: idx_seqno ! idx in ODA
+     integer(kind = JPIM)                       :: ODAncols ! total number of columns in ODA; can be less or greater than the number of column in ODB
+     character(len=MAX_STRING), dimension(:), allocatable :: ODAcolname
+     real(kind=JPRD)                            :: mdi
+     integer(kind=JPIM)                         :: master       ! root table (desc)
+     type(tableinfo), dimension(:), allocatable :: tables
+  end type dbinfo
+
+contains
+function get_coltype(khandle, colnames, types, ftntypes, one_colname, itype) RESULT(idx_col)
+  implicit none
+  INTEGER(KIND=JPIM), intent(in)         :: khandle
+  character(len=*),intent(in)           :: colnames(:)
+  character(len=maxvarlen), intent(in)  :: types(:), ftntypes(:)
+  character(len=*), intent(in)          :: one_colname
+  integer(kind=C_INT), intent(out)      :: itype
+
+  integer(kind=JPIM)                    :: idx_col, jc
+  real(kind=JPRD)                       :: mdi
+
+  REAL(KIND=JPRD)                       :: ZHOOK_HANDLE
+
+  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',0,ZHOOK_HANDLE)
+  mdi = abs(ODB_getval(khandle, '$mdi'))
+
+  idx_col = -1
+  do jc=1, size(colnames)
+    if (trim(colnames(jc)) == trim(one_colname)) then
+      idx_col = jc
+      exit
+    endif
+  end do
+
+  if ( ftntypes(idx_col)(1:7) == 'REAL(8)' .and.&
+  &       types(idx_col)(1:7) == 'string ' ) then
+      itype = ODB_STRING
+  else if ( ftntypes(idx_col)(1:7) == 'CHAR(8)') then ! a future extension
+      itype = ODB_STRING
+  else if (ftntypes(idx_col)(1:5) == 'REAL(') then
+      itype = ODB_REAL
+  else if (ftntypes(idx_col)(1:8) == 'INTEGER(' .and. &
+  &           types(idx_col)(1:8) == 'Bitfield') then
+      itype = ODB_BITFIELD
+  else if (ftntypes(idx_col)(1:8) == 'INTEGER(') then
+      itype = ODB_INTEGER
+  else
+      itype = ODB_INTEGER
+  endif
+  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',1,ZHOOK_HANDLE)
+end function get_coltype
+SUBROUTINE odb_bitfield_definition(khandle, coln, bnames, bsizes)
+implicit none
+INTEGER(KIND=JPIM), intent(in)        :: khandle
+character(len=*), intent(in)          :: coln
+character(len=*), intent(out)         :: bnames, bsizes
+character(len=maxvarlen)              :: tablename
+integer(kind=jpim)                    :: nextnames, rc, jj, jg
+character(len=maxvarlen), allocatable :: extnames(:), exttypes(:)
+
+integer(kind=jpim)                    :: idx_at, idx_at_ext
+REAL(KIND=JPRD)                       :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',0,ZHOOK_HANDLE)
+
+idx_at = index(coln,'@')
+tablename= coln(idx_at:)
+nextnames = ODB_getnames(khandle, trim(tablename),'extname')
+allocate(extnames(nextnames))
+allocate(exttypes(nextnames))
+
+rc = ODB_getnames(khandle, trim(tablename),'extname', extnames(1:nextnames))
+rc = ODB_getnames(khandle, trim(tablename),'exttype', exttypes(1:nextnames))
+
+jj=1
+
+
+do while (extnames(jj)(1:idx_at) /= coln(1:idx_at-1)//'.')
+  jj=jj+1
+enddo
+bnames=""
+bsizes=""
+
+do jg=jj,nextnames
+  if  (extnames(jg)(1:idx_at-1) /= coln(1:idx_at-1)) exit
+
+  idx_at_ext = index(extnames(jg),'@')
+  bnames=trim(bnames)//extnames(jg)(idx_at+1:idx_at_ext-1)//':'
+  bsizes=trim(bsizes)//trim(exttypes(jg)(4:))//':'
+enddo
+
+deallocate(extnames)
+deallocate(exttypes)
+
+IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',1,ZHOOK_HANDLE)
+
+END SUBROUTINE odb_bitfield_definition
+
+subroutine create_header_table(b2o_info, jc, tablename, list_cols)
+ use, intrinsic :: iso_c_binding
+ use odb_c_binding
+!*AF use varindex_module
+
+implicit none
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+ integer(kind=JPIM), intent(inout)           :: jc
+ character(len=maxvarlen), intent(in)        :: tablename
+ character(len=64) , dimension(:),intent(in) :: list_cols
+
+ integer(kind=C_INT)                    :: cerr
+ integer(kind=JPIM)                     :: jj
+ integer(kind=JPIM)                     :: rc
+ integer(kind=JPIM)                     :: idx_col
+ integer(kind=JPIM)                     :: ncolumns
+ integer(kind=C_INT)                    :: itype
+ character(len=maxvarlen)               :: bitfield_names, bitfield_sizes
+ character(len=maxvarlen)               :: full_colname
+ character(len=maxvarlen), allocatable  :: types(:), ftntypes(:)
+ character(len=maxvarlen), allocatable  :: colnames(:)
+ REAL(KIND=JPRD)                        :: ZHOOK_HANDLE
+
+
+  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',0,ZHOOK_HANDLE)
+  ncolumns = ODB_getnames(b2o_info%handle,tablename,'name')
+  allocate(colnames(ncolumns))
+  rc = ODB_getnames(b2o_info%handle,tablename,'name',colnames)
+  allocate(types(ncolumns))
+  allocate(ftntypes(ncolumns))
+  rc = ODB_getnames(b2o_info%handle, tablename,'type', types(1:ncolumns))
+  rc = ODB_getnames(b2o_info%handle, tablename,'ftntype', ftntypes(1:ncolumns))
+  do jj=1, size(list_cols)
+    full_colname = trim(list_cols(jj))//trim(tablename)
+    idx_col = get_coltype(b2o_info%handle, colnames, types, ftntypes, full_colname, itype)
+
+!*AF    write(0,*) 'column = ', trim(list_cols(jj)), itype
+    if (itype /= ODB_BITFIELD) then
+      if (len(list_cols(jj)) > 10 .and. list_cols(jj)(1:10) == 'linkoffset') then
+! change linkoffset by linken because linkoffset will be recomputed
+           full_colname(1:10) = '   linklen'
+      endif
+      full_colname = trim(adjustl(full_colname))
+      b2o_info%ODBcolname(jc+1) = full_colname
+      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
+      b2o_info%ODBcoltype(jc+1) = itype
+      cerr = odb_write_set_column(b2o_info%c_odb_it, jc, itype, full_colname)
+    else
+      full_colname = trim(adjustl(full_colname))
+      b2o_info%ODBcolname(jc+1) = full_colname
+      b2o_info%ODBcoltype(jc+1) = itype
+      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
+      call odb_bitfield_definition(b2o_info%handle,full_colname, bitfield_names, bitfield_sizes)
+      bitfield_names=trim(bitfield_names)//C_NULL_CHAR
+      bitfield_sizes=trim(bitfield_sizes)//C_NULL_CHAR
+      cerr = odb_write_set_bitfield(b2o_info%c_odb_it, jc, itype, full_colname, bitfield_names, bitfield_sizes)
+    endif
+    jc = jc + 1
+  enddo
+  deallocate(colnames)
+  deallocate(types)
+  deallocate(ftntypes)
+  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',1,ZHOOK_HANDLE)
+end subroutine create_header_table
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine init_one_row(b2o_info, one_row)
+implicit none
+
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+ real(kind=C_DOUBLE), intent(inout)          :: one_row(:)
+
+ integer(kind=JPIM)                          :: i
+ character(len=8)                            :: csgn=""
+ REAL(KIND=JPRD)                             :: str_real8
+ real(kind=JPRD)                             :: mdi
+
+
+ mdi = abs(ODB_getval(b2o_info%handle, '$mdi'))
+ do i=1, b2o_info%c_ncolumns
+   select case (b2o_info%ODBcoltype(i))
+      case(ODB_BITFIELD)
+        one_row(i) = 0
+      case(ODB_INTEGER)
+        if (b2o_info%ODBcolname(i)(1:4) == 'link' .or. &
+            b2o_info%ODBcolname(i)(1:4) == 'LINK') then
+
+            one_row(i) = 0
+        else
+          one_row(i) = mdi
+        endif
+      case(ODB_REAL)
+        one_row(i) = -mdi
+      case(ODB_STRING)
+        one_row(i) = transfer(csgn,str_real8)
+    end select
+ enddo
+
+end subroutine init_one_row
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine delete_header_table(b2o_info)
+implicit none
+
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+
+ if (associated(b2o_info%ODBcolname)) deallocate(b2o_info%ODBcolname)
+ if (associated(b2o_info%ODBcoltype)) deallocate(b2o_info%ODBcoltype)
+end subroutine delete_header_table
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+end module odbi
diff --git a/odb-tools/src/tests/CMakeLists.txt b/odb-tools/src/tests/CMakeLists.txt
new file mode 100644
index 0000000..52d08d2
--- /dev/null
+++ b/odb-tools/src/tests/CMakeLists.txt
@@ -0,0 +1,74 @@
+
+get_target_property( odb_bin odb LOCATION )
+
+set( test_environment
+  ODB_API_CODES=${PROJECT_SOURCE_DIR}/etc
+  ODB_API_HOME=${PROJECT_SOURCE_DIR}
+  ODB_API_TEST_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}
+  PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+  ODB_RTABLE_PATH=${PROJECT_SOURCE_DIR}/etc
+
+  TEST_DHSHOME=${CMAKE_CURRENT_SOURCE_DIR}/dhshome/
+  TEST_DATA_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}
+)
+
+### odb2_to_odb1 tests
+
+ecbuild_get_test_multidata( TARGET get_odb2_to_odb1_data NAMES odb2_to_odb1.ECMA.conv.tar.gz NOCHECK )
+
+ecbuild_add_test(
+
+    TARGET test_odb2_to_odb1
+
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_odb2_to_odb1.sh
+
+    ENVIRONMENT
+        ${test_environment}
+        ${ODB_ENVIRONMENT}
+        PATH=${CMAKE_BINARY_DIR}/bin:${odb_BASE_DIR}/bin:$ENV{PATH}
+        ODB_IO_METHOD=4
+        ODB_IO_GRPSIZE=160
+
+    TEST_DEPENDS get_odb2_to_odb1_data
+
+    CONDITION HAVE_FORTRAN AND ODB_FOUND AND ODB_HAVE_ECMA )
+
+
+if ( HAVE_FORTRAN AND ODB_FOUND AND ODB_HAVE_ECMA)
+    set_tests_properties( test_odb2_to_odb1 PROPERTIES LABELS "odb_api;odb_api_migrator" )
+endif()
+
+
+### Migrator tests
+
+if ( HAVE_MIGRATOR )
+
+    list( APPEND test_migrator_data_files 2000010106.old.ECMA.tar.gz )
+
+    ecbuild_get_test_multidata( TARGET get_migrator_test_data
+                                NAMES ${test_migrator_data_files}
+                                NOCHECK )
+
+    list( APPEND migrator_tests
+        import_odb
+        import_odb_dispatching )
+
+    foreach( _test ${migrator_tests} )
+
+        ecbuild_add_test(
+
+            TARGET test_${_test}
+            COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_${_test}.sh
+
+            ENVIRONMENT
+                ${test_environment}
+                ${ODB_ENVIRONMENT}
+
+            TEST_DEPENDS get_migrator_test_data
+        )
+
+        set_tests_properties( test_${_test} PROPERTIES LABELS "odb_api;odb_api_migrator" )
+
+    endforeach()
+
+endif()
diff --git a/odb-tools/src/tests/test_import_odb.sh b/odb-tools/src/tests/test_import_odb.sh
new file mode 100755
index 0000000..c4844b5
--- /dev/null
+++ b/odb-tools/src/tests/test_import_odb.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+set -uex
+
+which odb_migrator
+
+# A unique working directory
+
+wd=$(pwd)
+test_wd=$(pwd)/test_import_odb_wd
+
+if [ -d ${test_wd} ]; then
+    rm -rf ${test_wd}
+fi
+
+mkdir ${test_wd}
+cd ${test_wd}
+
+# Extract the test data
+
+tar xfz ${ODB_API_TEST_DATA_PATH}/2000010106.old.ECMA.tar.gz
+
+export ODB_COMPILER_FLAGS=`pwd`/2000010106/ECMA/ECMA.flags
+
+if [ -z ${ODB_ROOT:=""} ]; then
+
+    echo "ODB_ROOT not set"
+    exit -1
+
+else
+
+    # Runs its own verification step
+    odb_migrator 2000010106/ECMA . 2000010106.odb
+
+fi
+
+# Clean up
+
+cd ${wd}
+rm -rf ${test_wd}
+
diff --git a/odb-tools/src/tests/test_import_odb_dispatching.sh b/odb-tools/src/tests/test_import_odb_dispatching.sh
new file mode 100755
index 0000000..b540d06
--- /dev/null
+++ b/odb-tools/src/tests/test_import_odb_dispatching.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+set -ex
+
+which odb_migrator
+
+# A unique working directory
+
+wd=$(pwd)
+test_wd=$(pwd)/test_import_odb_dispatching_wd
+
+if [ -d ${test_wd} ]; then
+    rm -rf ${test_wd}
+fi
+
+mkdir ${test_wd}
+cd ${test_wd}
+
+# Extract the test data
+
+tar xfz ${ODB_API_TEST_DATA_PATH}/2000010106.old.ECMA.tar.gz
+
+export MALLOC_CHECK_=2
+export ODB_COMPILER_FLAGS=`pwd`/2000010106/ECMA/ECMA.flags
+
+if [ -z ${ODB_ROOT:=""} ]; then
+
+    echo "ODB_ROOT not set"
+    exit -1
+
+else
+
+    odb_migrator 2000010106/ECMA . 2000010106.{obstype}.{sensor}.odb
+
+fi
+
+# Clean up
+
+cd ${wd}
+rm -rf ${test_wd}
diff --git a/odb_api/tests/test_odb2_to_odb1.sh b/odb-tools/src/tests/test_odb2_to_odb1.sh
similarity index 100%
copy from odb_api/tests/test_odb2_to_odb1.sh
copy to odb-tools/src/tests/test_odb2_to_odb1.sh
diff --git a/odb/.gitignore b/odb/.gitignore
new file mode 100644
index 0000000..1b2211d
--- /dev/null
+++ b/odb/.gitignore
@@ -0,0 +1 @@
+build*
diff --git a/odb/CMakeLists.txt b/odb/CMakeLists.txt
new file mode 100644
index 0000000..fbbca75
--- /dev/null
+++ b/odb/CMakeLists.txt
@@ -0,0 +1,152 @@
+cmake_minimum_required(VERSION 2.8.4 FATAL_ERROR)
+
+project(odb C Fortran)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+if(NOT PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME)
+  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake PARENT_SCOPE)
+endif()
+
+include(ecbuild_system)
+include(odb_add_schema)
+include(odb_link_schemas)
+include(odb_set_environment)
+
+ecbuild_requires_macro_version(1.9)
+
+if(PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME)
+  set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/module)
+else()
+  set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/odb/module)
+endif()
+
+ecbuild_add_option(FEATURE ODB_MPI
+  DESCRIPTION "Use system MPI library"
+  REQUIRED_PACKAGES MPI
+  DEFAULT OFF)
+
+ecbuild_add_option(FEATURE ODB_MPI_SERIAL_WRAPPERS
+  DESCRIPTION "Create serial wrappers for MPI programs"
+  CONDITION HAVE_ODB_MPI
+  DEFAULT ON)
+
+ecbuild_add_option(FEATURE ODB_EMOS
+  DESCRIPTION "Use system EMOS library"
+  REQUIRED_PACKAGES libemos
+  DEFAULT OFF)
+
+ecbuild_add_option(FEATURE ODB_SHARED_LIBS
+  DESCRIPTION "Build ODB project with shared libraries (overrides BUILD_SHARED_LIBS)"
+  DEFAULT ${BUILD_SHARED_LIBS}
+  ADVANCED)
+
+if(HAVE_ODB_SHARED_LIBS)
+  set(ODB_LIBS_TYPE SHARED)
+else()
+  set(ODB_LIBS_TYPE STATIC)
+endif()
+
+option(ODB_CLIENT_SERVER "Enable client/server support" OFF)
+
+if(ODB_CLIENT_SERVER AND HAVE_ODB_SHARED_LIBS)
+  message(FATAL_ERROR "Please set BUILD_SHARED_LIBS or ENABLE_ODB_SHARED_LIBS to OFF for client/server support")
+endif()
+
+test_big_endian(BIG_ENDIAN)
+
+if(NOT BIG_ENDIAN)
+  add_definitions(-DLITTLE)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+  add_definitions(-DLINUX)
+endif()
+
+if(CMAKE_C_COMPILER_ID MATCHES "Intel")
+    set(CMAKE_C_FLAGS "-fPIC -DINTEL -traceback")
+endif()
+
+if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
+
+  set(CMAKE_C_FLAGS "-fPIC")
+  set(CMAKE_Fortran_FLAGS "-fPIC -fopenmp -ffree-line-length-none")
+  set(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -fcheck=bounds")
+  set(CMAKE_Fortran_FLAGS_RELEASE "-O2")
+  set(CMAKE_EXE_LINKER_FLAGS "-fopenmp -Wl,--as-needed")
+
+elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
+
+  set(CMAKE_Fortran_FLAGS "-fPIC -openmp -traceback -fpe0 -names lowercase")
+  set(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -check bounds -check pointers")
+  set(CMAKE_EXE_LINKER_FLAGS "-openmp -Wl,--as-needed")
+
+elseif(CMAKE_Fortran_COMPILER_ID MATCHES "PGI")
+
+  set(CMAKE_Fortran_FLAGS "-fPIC -mp -Ktrap=fp -noswitcherror")
+  set(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -Mbounds")
+  set(CMAKE_Fortran_FLAGS_RELEASE "-O2")
+
+elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Cray")
+
+  set(CMAKE_Fortran_FLAGS "-hPIC -emf -homp -M 226,867,7212")
+  set(CMAKE_Fortran_FLAGS_DEBUG "-G0 -O0 -hdevelop")
+  set(CMAKE_Fortran_FLAGS_RELEASE "-G2 -O2")
+  set(CMAKE_C_FLAGS "-fPIC -hnomessage=186:192:223:236:7212:10082")
+  set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+
+endif()
+
+find_package(Dl REQUIRED)
+find_package(PythonInterp REQUIRED)
+
+find_program(ODB_AR NAMES sxar ar)
+find_program(ODB_GZIP NAMES gzip)
+find_program(ODB_GUNZIP NAMES gunzip)
+
+ecbuild_declare_project()
+
+file(GLOB schema_dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src "src/ddl.[A-Z0-9]*")
+string(REGEX REPLACE "ddl.([A-Z0-9]*)" "\\1" schemas "${schema_dirs}")
+set(ODB_SCHEMAS ${schemas} CACHE STRING "List of pre-compiled ODB schemas")
+
+foreach(schema ${ODB_SCHEMAS})
+  set(ODB_HAVE_${schema} 1 CACHE INTERNAL "")
+endforeach()
+
+get_directory_property(ODB_DEFINITIONS COMPILE_DEFINITIONS)
+
+list(APPEND ODB_TPLS Dl)
+
+set(ODB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/include ${CMAKE_Fortran_MODULE_DIRECTORY})
+set(ODB_LIBRARIES odb_lib)
+set(ODB_CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake CACHE INTERNAL "")
+
+odb_set_environment(ODB_ENVIRONMENT ROOT ${CMAKE_BINARY_DIR})
+odb_set_environment(ODB_INSTALL_ENVIRONMENT ROOT ${CMAKE_INSTALL_PREFIX})
+
+ecbuild_find_project_files()
+
+add_subdirectory(cmake)
+add_subdirectory(src)
+add_subdirectory(share)
+add_subdirectory(tests)
+
+odb_set_environment(ODB_PKGCONFIG_ENVIRONMENT ROOT \\\${prefix})
+
+set(_odb_pkgconfig_vars)
+
+foreach(_pair ${ODB_PKGCONFIG_ENVIRONMENT})
+    string(REGEX MATCH "^[^=]+" _name ${_pair})
+    string(REGEX REPLACE "${_name}=" "" _value ${_pair})
+    list(APPEND _odb_pkgconfig_vars ${_name})
+    set(${_name} ${_value})
+endforeach()
+
+ecbuild_pkgconfig(URL "https://software.ecmwf.int/wiki/display/ODB"
+  DESCRIPTION "Observation database software"
+  VARIABLES ${_odb_pkgconfig_vars})
+
+ecbuild_install_project(NAME odb)
+
+ecbuild_print_summary()
diff --git a/odb/README b/odb/README
new file mode 100644
index 0000000..48b8667
--- /dev/null
+++ b/odb/README
@@ -0,0 +1,44 @@
+ODB
+===
+
+A non-relational, distributed, parallel database system designed for handling of large volumes of observational data.
+
+Home page: https://software.ecmwf.int/wiki/display/ODB
+
+Installation
+============
+
+To build ODB software from source, you will need CMake (www.cmake.org).
+
+1. Unpack the source tarball
+
+    $ tar xzf odb-1.0.2-Source.tar.gz
+
+2. Configure your build using CMake
+
+    $ cmake odb-1.0.2-Source
+
+3. Build libraries and tools
+
+    $ make -j<N>
+
+4. Run tests
+
+    $ make check
+
+4. Install
+
+    $ make install
+
+Useful CMake options
+--------------------
+
+-DCMAKE_SHARED_LIBS=OFF # build static libraries
+-DCMAKE_INSTALL_PREFIX=/usr/local/apps/odb # installation directory
+-DODB_SCHEMAS="ECMA;CCMA" # list of schema libraries to build
+
+Setting environment
+===================
+
+    $ export ODB_ROOT=/usr/local/apps/odb
+    $ source $ODB_ROOT/bin/use_odb.sh
diff --git a/odb/VERSION.cmake b/odb/VERSION.cmake
new file mode 100644
index 0000000..7987641
--- /dev/null
+++ b/odb/VERSION.cmake
@@ -0,0 +1 @@
+set(${PROJECT_NAME}_VERSION_STR "1.0.6")
diff --git a/odb/cmake/CMakeLists.txt b/odb/cmake/CMakeLists.txt
new file mode 100644
index 0000000..6f5ee87
--- /dev/null
+++ b/odb/cmake/CMakeLists.txt
@@ -0,0 +1,8 @@
+file(GLOB cmake_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cmake" "*.py")
+
+# Copy files to build tree so they're added to the CMAKE_MODULE_PATH by
+# odb-import.cmake when odb is picked up from a build tree
+file(COPY ${cmake_files} DESTINATION ${PROJECT_BINARY_DIR})
+install(FILES ${cmake_files} DESTINATION ${INSTALL_DATA_DIR}/cmake)
+
+ecbuild_add_resources(TARGET odb_cmake_files SOURCES_PACK ${cmake_files})
diff --git a/odb/cmake/odb_add_schema.cmake b/odb/cmake/odb_add_schema.cmake
new file mode 100644
index 0000000..5e5aca7
--- /dev/null
+++ b/odb/cmake/odb_add_schema.cmake
@@ -0,0 +1,137 @@
+macro(odb_add_schema)
+
+    find_package(PythonInterp REQUIRED)
+
+    set(options NOINSTALL)
+    set(single_value_args TARGET TYPE)
+    set(multi_value_args SOURCES VIEWS DEFINITIONS CONDITION)
+
+    cmake_parse_arguments(_PAR "${options}" "${single_value_args}" "${multi_value_args}" ${ARGN})
+
+    if(NOT _PAR_TARGET)
+        message(FATAL_ERROR "odb_add_schema: TARGET argument not specified")
+    endif()
+
+    if(NOT _PAR_SOURCES)
+        message(FATAL_ERROR "odb_add_schema: SOURCES argument not specified")
+    endif()
+
+    if(_PAR_NOINSTALL)
+        set(_PAR_UNPARSED_ARGUMENTS "NOINSTALL" ${_PAR_UNPARSED_ARGUMENTS})
+    endif()
+
+    if(_PAR_TYPE)
+        set(_PAR_UNPARSED_ARGUMENTS TYPE ${_PAR_TYPE} ${_PAR_UNPARSED_ARGUMENTS})
+    endif()
+
+    set(TARGET ${_PAR_TARGET})
+    set(SOURCES ${_PAR_SOURCES})
+
+    set(VIEWS)
+    foreach(view_sql ${_PAR_VIEWS})
+        if(NOT IS_ABSOLUTE ${view_sql})
+            set(view_sql ${CMAKE_CURRENT_SOURCE_DIR}/${view_sql})
+        endif()
+        list(APPEND VIEWS ${view_sql})
+    endforeach()
+
+    # Declare DDL and SQL files as project files
+
+    ecbuild_declare_project_files(${_PAR_SOURCES} ${_PAR_VIEWS})
+
+    # Allow conditional build
+
+    if(DEFINED _PAR_CONDITION)
+        set(_target_condition_file "${CMAKE_CURRENT_BINARY_DIR}/set_${_PAR_TARGET}_condition.cmake")
+        file(WRITE ${_target_condition_file} "  if( ")
+        foreach(term ${_PAR_CONDITION})
+            file(APPEND ${_target_condition_file} " ${term}")
+        endforeach()
+        file(APPEND ${_target_condition_file} " )\n    set(_${_PAR_TARGET}_condition TRUE)\n  else()\n    set(_${_PAR_TARGET}_condition FALSE)\n  endif()\n")
+        include(${_target_condition_file})
+    else()
+        set(_${_PAR_TARGET}_condition TRUE)
+    endif()
+
+    # Do not continue pass this point if condition is false
+
+    if(NOT _${_PAR_TARGET}_condition)
+        return()
+    endif()
+
+    # Create a list of ODB-SQL compiler flags
+
+    set(_flags "-I.")
+
+    foreach(dir ${ODB_INCLUDE_DIRS})
+        list(APPEND _flags "-I${dir}")
+    endforeach()
+
+    foreach(def ${_PAR_DEFINITIONS})
+        list(APPEND _flags "-D${def}")
+    endforeach()
+
+    # Find target's DDL file (FIXME: assuming it's the first file in the list of sources)
+
+    list(GET _PAR_SOURCES 0 target_ddl)
+
+    # Parse DDL file and generate a list of all table names in the schema
+
+    if(IS_ABSOLUTE ${target_ddl})
+        get_filename_component(work_dir ${target_ddl} DIRECTORY)
+    else()
+        set(work_dir ${CMAKE_CURRENT_SOURCE_DIR})
+        set(target_ddl ${CMAKE_CURRENT_SOURCE_DIR}/${target_ddl})
+    endif()
+
+    execute_process(COMMAND ${PYTHON_EXECUTABLE} ${ODB_CMAKE_DIR}/odb_generate_table_names.py ${_flags} ${target_ddl}
+        WORKING_DIRECTORY ${work_dir}
+        OUTPUT_VARIABLE table_names)
+
+    # Create a list of all table source files that will be generated by ODB-SQL compiler
+
+    set(table_sources)
+    foreach(name ${table_names})
+        list(APPEND table_sources ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_T_${name}.c)
+    endforeach()
+
+    # Use ODB/SQL compiler to generate the actual table sources
+
+    add_custom_command(OUTPUT ${TARGET}.ddl_ ${TARGET}.h ${TARGET}.c ${table_sources}
+        COMMAND odb98.x -C ${_flags} -o ${CMAKE_CURRENT_BINARY_DIR} -l ${TARGET} -c ${target_ddl}
+        DEPENDS ${SOURCES} odb98.x)
+
+    # Generate a static stub file for this schema
+
+    add_custom_command(OUTPUT ${TARGET}_Sstatic.c
+        COMMAND ${CMAKE_COMMAND} -D TARGET=${TARGET} -D VIEWS="${VIEWS}"
+            -P ${ODB_CMAKE_DIR}/odb_create_static_stub.cmake
+        DEPENDS ${TARGET}.h ${VIEWS})
+
+    # Use ODB/SQL compiler to generate the actual view sources
+
+    set(view_sources)
+
+    foreach(view_sql ${VIEWS})
+
+        get_filename_component(view_name ${view_sql} NAME_WE)
+
+        add_custom_command(OUTPUT ${TARGET}_${view_name}.c
+            COMMAND odb98.x -C ${_flags} -c -l ${TARGET} -w -Q ${view_sql}
+            DEPENDS ${view_sql} ${TARGET}.h odb98.x)
+
+        list(APPEND view_sources ${TARGET}_${view_name}.c)
+
+    endforeach()
+
+    # Add the actual schema library
+
+    ecbuild_add_library(TARGET ${TARGET}
+        DEFINITIONS ${_PAR_DEFINITIONS}
+        SOURCES ${TARGET}.c ${TARGET}.h ${TARGET}_Sstatic.c ${table_sources} ${view_sources}
+        PRIVATE_INCLUDES ${CMAKE_CURRENT_BINARY_DIR} ${ODB_INCLUDE_DIRS}
+        LIBS ${ODB_LIBRARIES}
+        CFLAGS -O0
+        ${_PAR_UNPARSED_ARGUMENTS})
+
+endmacro()
diff --git a/odb/cmake/odb_create_glue.cmake b/odb/cmake/odb_create_glue.cmake
new file mode 100644
index 0000000..85d88c1
--- /dev/null
+++ b/odb/cmake/odb_create_glue.cmake
@@ -0,0 +1,57 @@
+# CMake script to create ODB glue file
+
+if(NOT OUTPUT)
+    message(FATAL_ERROR "odb_create_glue: OUTPUT argument not specified")
+endif()
+
+if(NOT SCHEMAS)
+    message(FATAL_ERROR "odb_create_glue: SCHEMAS argument not specified")
+endif()
+
+file(WRITE ${OUTPUT} 
+"/* WARNING: This file is automatically generated by odb_create_glue.cmake. */
+
+#include <stdio.h>
+#include <string.h>
+
+extern void
+codb_procdata_(int *myproc,
+               int *nproc,
+               int *pid,
+               int *it,
+               int *inumt);
+
+extern void 
+ODB_add2funclist(const char *dbname,
+		 void (*func)(),
+                 int funcno);
+
+#define Static_Init(db) \\
+if (strncmp(dbname, #db, dbname_len) == 0) { \\
+  extern void db##_static_init(); \\
+  ODB_add2funclist(#db, db##_static_init, 0); \\
+} \\
+else { /* fprintf(stderr,\"***Warning: Not initializing '%s'\\n\",#db); */ }  
+
+void
+codb_set_entrypoint_(const char *dbname
+	             /* Hidden arguments */
+	             , int dbname_len)
+{
+  int myproc = 0;
+  codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+  if (myproc == 1) {
+    fprintf(stderr,
+            \"codb_set_entrypoint_(dbname='%*s', dbname_len=%d)\\n\",
+            dbname_len, dbname, dbname_len);
+  }
+")
+
+separate_arguments(SCHEMAS)
+list(REMOVE_DUPLICATES SCHEMAS)
+
+foreach(db ${SCHEMAS})
+    file(APPEND ${OUTPUT} "  Static_Init(${db});\n")
+endforeach()
+
+file(APPEND ${OUTPUT} "}\n")
diff --git a/odb/cmake/odb_create_static_stub.cmake b/odb/cmake/odb_create_static_stub.cmake
new file mode 100644
index 0000000..20bed5e
--- /dev/null
+++ b/odb/cmake/odb_create_static_stub.cmake
@@ -0,0 +1,28 @@
+# Script to generate database specific static stub file for given list of SQL views.
+# We assume there is only one view per file, which is the current practise.
+
+file(WRITE ${TARGET}_Sstatic.c 
+"/* Warning: This file is automatically generated by odb_create_static_stub.cmake */
+
+#define ODB_GENCODE 0
+#include \"${TARGET}.h\"
+
+PUBLIC void ${TARGET}_static_init() {
+ODB_ANCHOR(${TARGET});\n"
+)
+
+set(regex_create_view "^[ ]*[Cc][Rr][Ee][Aa][Tt][Ee][ ]+[Vv][Ii][Ee][Ww][ ]+([^ ]+).*$")
+
+separate_arguments(VIEWS)
+
+foreach(view ${VIEWS})
+  file(STRINGS ${view} matched_line REGEX ${regex_create_view})
+  if(NOT matched_line)
+    message(FATAL_ERROR "Could not find SQL view in ${view}")
+  endif()
+  string(REGEX REPLACE ${regex_create_view} "\\1" view_name ${matched_line})
+  string(TOLOWER "${view_name}" view_name)
+  file(APPEND ${TARGET}_Sstatic.c "ODB_ANCHOR_VIEW(${TARGET}, ${view_name});\n")
+endforeach()
+
+file(APPEND ${TARGET}_Sstatic.c "}\n")
diff --git a/odb/cmake/odb_generate_table_names.py b/odb/cmake/odb_generate_table_names.py
new file mode 100755
index 0000000..20d648e
--- /dev/null
+++ b/odb/cmake/odb_generate_table_names.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+import os, re, sys
+import argparse
+
+RE_INCLUDE = re.compile(r'^\s*#include\s+"(.*)"')
+RE_CREATE_TABLE = re.compile(r'^\s*CREATE\s+TABLE\s+(\w+)(|\[1:\$(\w+)\])\s+AS', re.IGNORECASE)
+RE_SET_VAR = re.compile(r'^\s*SET\s+\$(\w+)\s*=\s*(\w+)\s*;', re.IGNORECASE)
+RE_IFDEF = re.compile(r'^\s*#ifdef\s+(\w+)')
+RE_IFNDEF = re.compile(r'^\s*#ifndef\s+(\w+)')
+RE_ENDIF = re.compile(r'^\s*#endif')
+
+def parse(filename, parent_scope, definitions):
+
+    tables = []
+    scope = parent_scope
+    skip = False
+
+    for line in open(filename, "r"):
+
+        match = RE_ENDIF.match(line)
+        if match:
+            skip = False
+            continue
+
+        match = RE_IFDEF.match(line)
+        if match:
+            d = match.group(1)
+            if d not in definitions:
+                skip = True
+            continue
+
+        match = RE_IFNDEF.match(line)
+        if match:
+            d = match.group(1)
+            if d in definitions:
+                skip = True
+            continue
+
+        if skip: # until closing #endif found
+            continue
+
+        match = RE_INCLUDE.match(line)
+        if match:
+            f = match.group(1)
+            t = parse(f, scope, definitions)
+            tables.extend(t)
+
+        match = RE_SET_VAR.match(line)
+        if match:
+            k, v = match.group(1), match.group(2)
+            if not v.isdigit():
+                v = definitions[v]
+            scope[k] = v
+
+        match = RE_CREATE_TABLE.match(line)
+        if match:
+            table = match.group(1).lower()
+            if match.group(3): # multi-table (e.g. enkf[1:$NMXENKF])
+                size = int(scope[match.group(3)])
+                for n in range(1, size + 1):
+                    tables += ["%s_%d" % (table, n)]
+            else: # single table
+                tables += [table]
+
+    return tables
+
+#-----------------
+
+ap = argparse.ArgumentParser()
+ap.add_argument("ddl", nargs=1)
+ap.add_argument("-D", help="definitions", action="append", default=[])
+ap.add_argument("-I", help="includes", action="append", default=[])
+args = vars(ap.parse_args())
+
+definitions = {}
+
+for d in args["D"]:
+    k, v = d.split("=")
+    definitions[k] = v
+
+tables = parse(args["ddl"][0], {}, definitions)
+
+sys.stdout.write(";".join(tables))
diff --git a/odb/cmake/odb_link_schemas.cmake b/odb/cmake/odb_link_schemas.cmake
new file mode 100644
index 0000000..2ef523a
--- /dev/null
+++ b/odb/cmake/odb_link_schemas.cmake
@@ -0,0 +1,72 @@
+# Link a target to given ODB schemas
+#
+# Usage: odb_link_schemas(<target> <schema1> [<schema2> ...])
+#
+# This function generates a special glue code that needs to be linked to a
+# program in order to register the listed schemas with ODB library (see ODB
+# User Guide 2.2.1 for more details).
+#
+# Note that this function must be called from target's source directory.
+#
+# TODO: Add the possibility to invoke this function  multiple times for the
+# same target. This would allow to add new schemas iteratively in a similar
+# fashion target_link_libraries allows to add libraries to the same target.
+# Currently, this function can be invoked only once per target.
+
+function(odb_link_schemas target)
+
+    if(NOT target)
+        message(FATAL_ERROR "odb_link_schemas: <target> not specified")
+    endif()
+
+    set(schemas ${ARGN})
+
+    if(NOT schemas)
+        return()
+    endif()
+
+    list(REMOVE_DUPLICATES schemas)
+
+    # Inspect target's condition file, if present
+
+    set(target_condition_file "${CMAKE_CURRENT_BINARY_DIR}/set_${target}_condition.cmake")
+
+    if(EXISTS ${target_condition_file})
+        include(${target_condition_file})
+        if(NOT _${target}_condition)
+            return()
+        endif()
+    endif()
+
+    # Generate a glue source file
+
+    set(glue_source ${target}_glue.c)
+
+    add_custom_command(OUTPUT ${glue_source}
+        COMMAND ${CMAKE_COMMAND} -D OUTPUT=${glue_source} -D SCHEMAS="${schemas}"
+            -P ${ODB_CMAKE_DIR}/odb_create_glue.cmake)
+
+    # This compiles the glue source without creating an actual library
+
+    add_library(${target}_glue OBJECT ${glue_source})
+
+    # Get hold of the compiled glue object file
+
+    set(glue_object ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}_glue.dir/${glue_source}${CMAKE_C_OUTPUT_EXTENSION})
+
+    # Add glue object to the list of target's link libraries. Note that glue
+    # object must precede ODB libraries in order to override the default
+    # implementation of codb_set_entrypoint_ from odb/lib/static.c.
+
+    get_target_property(libs ${target} LINK_LIBRARIES)
+
+    list(INSERT libs 0 -Wl,-z,muldefs ${glue_object})
+
+    set_property(TARGET ${target} PROPERTY LINK_LIBRARIES ${libs})
+
+    # Finaly, link the schema libraries
+
+    add_dependencies(${target} ${target}_glue)
+    target_link_libraries(${target} ${schemas})
+
+endfunction()
diff --git a/odb/cmake/odb_set_environment.cmake b/odb/cmake/odb_set_environment.cmake
new file mode 100644
index 0000000..df34ad1
--- /dev/null
+++ b/odb/cmake/odb_set_environment.cmake
@@ -0,0 +1,50 @@
+macro(odb_set_environment)
+
+    set(options)
+    set(single_value_args ROOT)
+    set(multi_value_args)
+
+    set(_ARGN ${ARGN}) # convert ARGN into a list
+    list(GET _ARGN 0 _output_variable) # and get the first argument
+
+    cmake_parse_arguments(_PAR "${options}" "${single_value_args}" "${multi_value_args}" ${ARGN})
+
+    if(NOT _PAR_ROOT)
+        message(FATAL_ERROR "odb_set_environment: ROOT argument not specified")
+    endif()
+
+    set(_environment
+
+        ODB_ROOT=${_PAR_ROOT}
+        ODB_SYSPATH=${_PAR_ROOT}/include
+        ODB_BINPATH=${_PAR_ROOT}/bin
+        ODB_BEBINPATH=${_PAR_ROOT}/bin
+        ODB_FEBINPATH=${_PAR_ROOT}/bin
+        ODB_LIBPATH=${_PAR_ROOT}/lib
+        ODB_RTABLE_PATH=${_PAR_ROOT}/share/odb
+        ODB_SYSDBPATH=${_PAR_ROOT}/share/odb
+
+        # Run-time compilation and linking
+
+        ODB_CC=${CMAKE_C_COMPILER}\ ${CMAKE_C_FLAGS}\ -I${_PAR_ROOT}/include
+        ODB_F90=${CMAKE_Fortran_COMPILER}\ ${CMAKE_Fortran_FLAGS}\ -I${_PAR_ROOT}/include\ -I${_PAR_ROOT}/module\ -I${_PAR_ROOT}/odb/module
+        ODB_COMPILER=${_PAR_ROOT}/bin/odb98.x\ -V\ -O3
+        ODB_COMPILER_FLAGS=${_PAR_ROOT}/share/odb/odb98.flags
+
+        ODB_STATIC_LINKING=1
+        ODB_LD_SHARED=none
+        ODB_LD_SHARED_SFX=${CMAKE_SHARED_LIBRARY_SUFFIX}
+
+        ODB_IOASSIGN_MAXPROC=32
+        ODB_IOASSIGN_PARAMS=-r\ 1m\ -w\ 1m
+
+        ODB_AR=${ODB_AR}
+        ODB_GZIP=${ODB_GZIP}
+        ODB_GUNZIP=${ODB_GUNZIP}
+
+        ODB_SETUP_SHELL=/bin/sh
+    )
+
+    set(${_output_variable} ${_environment} CACHE INTERNAL "Environment variables used by ODB at run-time")
+
+endmacro()
diff --git a/odb/odb-import.cmake.in b/odb/odb-import.cmake.in
new file mode 100644
index 0000000..2700aba
--- /dev/null
+++ b/odb/odb-import.cmake.in
@@ -0,0 +1,15 @@
+# Import file for ODB package
+#
+# ODB_ENVIRONMENT - list of run-time environment variables
+# ODB_SCHEMAS     - list of pre-compiled schemas
+
+set(ODB_ENVIRONMENT "@ODB_INSTALL_ENVIRONMENT@")
+set(ODB_SCHEMAS "@ODB_SCHEMAS@")
+
+foreach(schema ${ODB_SCHEMAS})
+    set(ODB_HAVE_${schema} 1)
+endforeach()
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR})
+
+list(APPEND ODB_INCLUDE_DIRS "${ODB_CMAKE_DIR}/../../../module")
diff --git a/odb/share/CMakeLists.txt b/odb/share/CMakeLists.txt
new file mode 100644
index 0000000..3c5d97f
--- /dev/null
+++ b/odb/share/CMakeLists.txt
@@ -0,0 +1,3 @@
+install(DIRECTORY odb DESTINATION ${INSTALL_DATA_DIR}/..)
+file(GLOB_RECURSE odb_support_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "odb/*")
+ecbuild_add_resources(TARGET ${PROJECT_NAME}_odb_support_files SOURCES_PACK ${odb_support_files})
diff --git a/odb/share/odb/DUMMY/DUMMY.IOASSIGN b/odb/share/odb/DUMMY/DUMMY.IOASSIGN
new file mode 100644
index 0000000..a075b68
--- /dev/null
+++ b/odb/share/odb/DUMMY/DUMMY.IOASSIGN
@@ -0,0 +1,5 @@
+DUMMY $ODB_SRCPATH_DUMMY/DUMMY.dd 1 0 0 0 0 0 0 0 0
+DUMMY.sch $ODB_SRCPATH_DUMMY/DUMMY.sch 1 0 0 0 0 0 0 0 0
+DUMMY.flags $ODB_SRCPATH_DUMMY/DUMMY.flags 1 0 0 0 0 0 0 0 0
+DUMMY.dummy.dca $ODB_SRCPATH_DUMMY/dca/dummy.dca 1 0 0 0 0 0 0 0 0
+DUMMY.dummy.%d $ODB_DATAPATH_DUMMY/%d/dummy 1 4194304 4194304 4194304 4194304 0 0 0 1
diff --git a/odb/share/odb/DUMMY/DUMMY.dd b/odb/share/odb/DUMMY/DUMMY.dd
new file mode 100644
index 0000000..503f8ae
--- /dev/null
+++ b/odb/share/odb/DUMMY/DUMMY.dd
@@ -0,0 +1,11 @@
+32 2.034 1
+20070625 143000
+20070625 143100
+20070625 000000
+1
+1
+1 @dummy -1
+ at dummy 1
+  int:dummy at dummy 0
+1
+$mdi 2147483647
diff --git a/odb/share/odb/DUMMY/DUMMY.sch b/odb/share/odb/DUMMY/DUMMY.sch
new file mode 100644
index 0000000..3533248
--- /dev/null
+++ b/odb/share/odb/DUMMY/DUMMY.sch
@@ -0,0 +1,8 @@
+
+// Schema for database '$ODB_SYSPATH/DUMMY'
+
+SET $mdi = 2147483647;
+
+CREATE TABLE dummy AS (
+  dummy int,
+);
diff --git a/odb/share/odb/an_depar.cmap b/odb/share/odb/an_depar.cmap
new file mode 100644
index 0000000..698ca67
--- /dev/null
+++ b/odb/share/odb/an_depar.cmap
@@ -0,0 +1,4 @@
+Obs. minus Analysis
+an_depar at body
+0,-1 ! automatic scaling since min > max
+
diff --git a/odb/share/odb/date.cmap b/odb/share/odb/date.cmap
new file mode 100644
index 0000000..15fdb70
--- /dev/null
+++ b/odb/share/odb/date.cmap
@@ -0,0 +1,5 @@
+Observation day
+date at hdr
+0,-1 ! Automatic
+3,100,0 ! Method=3 --> mod(YYYYMMDD,100) + 0
+
diff --git a/odb/share/odb/dir.cmap b/odb/share/odb/dir.cmap
new file mode 100644
index 0000000..152b468
--- /dev/null
+++ b/odb/share/odb/dir.cmap
@@ -0,0 +1,3 @@
+Wind direction
+aux_2 at body
+-180,180
diff --git a/odb/share/odb/fg_depar.cmap b/odb/share/odb/fg_depar.cmap
new file mode 100644
index 0000000..9c1db44
--- /dev/null
+++ b/odb/share/odb/fg_depar.cmap
@@ -0,0 +1,4 @@
+Obs. minus First Guess
+fg_depar at body
+0,-1 ! automatic scaling since min > max
+
diff --git a/odb/share/odb/modoro.cmap b/odb/share/odb/modoro.cmap
new file mode 100644
index 0000000..cc45935
--- /dev/null
+++ b/odb/share/odb/modoro.cmap
@@ -0,0 +1,4 @@
+Model orography
+modoro at hdr
+0,-1
+
diff --git a/odb/share/odb/obstype.cmap b/odb/share/odb/obstype.cmap
new file mode 100644
index 0000000..bbf1b31
--- /dev/null
+++ b/odb/share/odb/obstype.cmap
@@ -0,0 +1,3 @@
+CMA Observation type
+obstype at hdr
+1,9 ! Gives nice (integer) spectrum for obstypes 1..8
diff --git a/odb/share/odb/oldwind.cmap b/odb/share/odb/oldwind.cmap
new file mode 100644
index 0000000..ccbf999
--- /dev/null
+++ b/odb/share/odb/oldwind.cmap
@@ -0,0 +1,3 @@
+Wind Speed (m/s)
+aux1 at body
+0,-1 ! Automatic
diff --git a/odb/share/odb/press.cmap b/odb/share/odb/press.cmap
new file mode 100644
index 0000000..41207d3
--- /dev/null
+++ b/odb/share/odb/press.cmap
@@ -0,0 +1,3 @@
+Pressure (Pa)
+obsvalue at body
+0,-1 ! Automatic
diff --git a/odb/share/odb/press_hpa.cmap b/odb/share/odb/press_hpa.cmap
new file mode 100644
index 0000000..8713857
--- /dev/null
+++ b/odb/share/odb/press_hpa.cmap
@@ -0,0 +1,5 @@
+Pressure (hPa)
+obsvalue at body
+0,-1 ! Automatic
+1,0.01,0 ! Method=1 --> Scaling: 0.01 * press + 0
+
diff --git a/odb/share/odb/procid.cmap b/odb/share/odb/procid.cmap
new file mode 100644
index 0000000..10eb8bb
--- /dev/null
+++ b/odb/share/odb/procid.cmap
@@ -0,0 +1,3 @@
+ECMA pool number
+procid at index
+0,-1 ! Autoscale
diff --git a/odb/share/odb/ps.cmap b/odb/share/odb/ps.cmap
new file mode 100644
index 0000000..cda9c68
--- /dev/null
+++ b/odb/share/odb/ps.cmap
@@ -0,0 +1,3 @@
+Surface pressure (Pa)
+obsvalue at body
+0,-1 ! Automatic range
diff --git a/odb/share/odb/ps_hpa.cmap b/odb/share/odb/ps_hpa.cmap
new file mode 100644
index 0000000..8ac3457
--- /dev/null
+++ b/odb/share/odb/ps_hpa.cmap
@@ -0,0 +1,4 @@
+Surface pressure (hPa)
+obsvalue at body
+0,-1 ! Automatic range
+1,0.01,0 ! Method=1 --> Scaling: 0.01 * press + 0
diff --git a/odb/share/odb/rtablel_2031 b/odb/share/odb/rtablel_2031
new file mode 100644
index 0000000..b16d38a
--- /dev/null
+++ b/odb/share/odb/rtablel_2031
@@ -0,0 +1,34 @@
+ &NAMRGRI
+  NRGRI(0001)=   20,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   48,
+  NRGRI(0007)=   54,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   64,
+  NRGRI(0010)=   64,
+  NRGRI(0011)=   64,
+  NRGRI(0012)=   64,
+  NRGRI(0013)=   64,
+  NRGRI(0014)=   64,
+  NRGRI(0015)=   64,
+  NRGRI(0016)=   64,
+  NRGRI(0017)=   64,
+  NRGRI(0018)=   64,
+  NRGRI(0019)=   64,
+  NRGRI(0020)=   64,
+  NRGRI(0021)=   64,
+  NRGRI(0022)=   64,
+  NRGRI(0023)=   64,
+  NRGRI(0024)=   64,
+  NRGRI(0025)=   60,
+  NRGRI(0026)=   54,
+  NRGRI(0027)=   48,
+  NRGRI(0028)=   45,
+  NRGRI(0029)=   40,
+  NRGRI(0030)=   32,
+  NRGRI(0031)=   25,
+  NRGRI(0032)=   20,
+ /
diff --git a/odb/share/odb/rtablel_2047 b/odb/share/odb/rtablel_2047
new file mode 100644
index 0000000..b3f5f18
--- /dev/null
+++ b/odb/share/odb/rtablel_2047
@@ -0,0 +1,50 @@
+ &NAMRGRI
+  NRGRI(0001)=   20,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   36,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   48,
+  NRGRI(0007)=   54,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   64,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   80,
+  NRGRI(0012)=   80,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   90,
+  NRGRI(0015)=   96,
+  NRGRI(0016)=   96,
+  NRGRI(0017)=   96,
+  NRGRI(0018)=   96,
+  NRGRI(0019)=   96,
+  NRGRI(0020)=   96,
+  NRGRI(0021)=   96,
+  NRGRI(0022)=   96,
+  NRGRI(0023)=   96,
+  NRGRI(0024)=   96,
+  NRGRI(0025)=   96,
+  NRGRI(0026)=   96,
+  NRGRI(0027)=   96,
+  NRGRI(0028)=   96,
+  NRGRI(0029)=   96,
+  NRGRI(0030)=   96,
+  NRGRI(0031)=   96,
+  NRGRI(0032)=   96,
+  NRGRI(0033)=   96,
+  NRGRI(0034)=   96,
+  NRGRI(0035)=   90,
+  NRGRI(0036)=   90,
+  NRGRI(0037)=   80,
+  NRGRI(0038)=   80,
+  NRGRI(0039)=   72,
+  NRGRI(0040)=   64,
+  NRGRI(0041)=   60,
+  NRGRI(0042)=   54,
+  NRGRI(0043)=   48,
+  NRGRI(0044)=   45,
+  NRGRI(0045)=   40,
+  NRGRI(0046)=   36,
+  NRGRI(0047)=   25,
+  NRGRI(0048)=   20,
+ /
diff --git a/odb/share/odb/rtablel_2063 b/odb/share/odb/rtablel_2063
new file mode 100644
index 0000000..14a85af
--- /dev/null
+++ b/odb/share/odb/rtablel_2063
@@ -0,0 +1,66 @@
+ &NAMRGRI
+  NRGRI(1)= 20,
+  NRGRI(2)= 27,
+  NRGRI(3)= 36,
+  NRGRI(4)= 40,
+  NRGRI(5)= 45,
+  NRGRI(6)= 50,
+  NRGRI(7)= 60,
+  NRGRI(8)= 64,
+  NRGRI(9)= 72,
+  NRGRI(10)= 75,
+  NRGRI(11)= 80,
+  NRGRI(12)= 90,
+  NRGRI(13)= 90,
+  NRGRI(14)= 96,
+  NRGRI(15)= 100,
+  NRGRI(16)= 108,
+  NRGRI(17)= 108,
+  NRGRI(18)= 120,
+  NRGRI(19)= 120,
+  NRGRI(20)= 120,
+  NRGRI(21)= 128,
+  NRGRI(22)= 128,
+  NRGRI(23)= 128,
+  NRGRI(24)= 128,
+  NRGRI(25)= 128,
+  NRGRI(26)= 128,
+  NRGRI(27)= 128,
+  NRGRI(28)= 128,
+  NRGRI(29)= 128,
+  NRGRI(30)= 128,
+  NRGRI(31)= 128,
+  NRGRI(32)= 128,
+  NRGRI(33)= 128,
+  NRGRI(34)= 128,
+  NRGRI(35)= 128,
+  NRGRI(36)= 128,
+  NRGRI(37)= 128,
+  NRGRI(38)= 128,
+  NRGRI(39)= 128,
+  NRGRI(40)= 128,
+  NRGRI(41)= 128,
+  NRGRI(42)= 128,
+  NRGRI(43)= 128,
+  NRGRI(44)= 128,
+  NRGRI(45)= 120,
+  NRGRI(46)= 120,
+  NRGRI(47)= 120,
+  NRGRI(48)= 108,
+  NRGRI(49)= 108,
+  NRGRI(50)= 100,
+  NRGRI(51)= 96,
+  NRGRI(52)= 90,
+  NRGRI(53)= 90,
+  NRGRI(54)= 80,
+  NRGRI(55)= 75,
+  NRGRI(56)= 72,
+  NRGRI(57)= 64,
+  NRGRI(58)= 60,
+  NRGRI(59)= 50,
+  NRGRI(60)= 45,
+  NRGRI(61)= 40,
+  NRGRI(62)= 36,
+  NRGRI(63)= 27,
+  NRGRI(64)= 20,
+ /
diff --git a/odb/share/odb/rtablel_2095 b/odb/share/odb/rtablel_2095
new file mode 100644
index 0000000..f4e4b95
--- /dev/null
+++ b/odb/share/odb/rtablel_2095
@@ -0,0 +1,98 @@
+ &NAMRGRI
+  NRGRI(1)= 20,
+  NRGRI(2)= 25,
+  NRGRI(3)= 36,
+  NRGRI(4)= 40,
+  NRGRI(5)= 45,
+  NRGRI(6)= 50,
+  NRGRI(7)= 60,
+  NRGRI(8)= 60,
+  NRGRI(9)= 72,
+  NRGRI(10)= 75,
+  NRGRI(11)= 80,
+  NRGRI(12)= 90,
+  NRGRI(13)= 96,
+  NRGRI(14)=100,
+  NRGRI(15)=108,
+  NRGRI(16)=120,
+  NRGRI(17)=120,
+  NRGRI(18)=120,
+  NRGRI(19)=128,
+  NRGRI(20)=135,
+  NRGRI(21)=144,
+  NRGRI(22)=144,
+  NRGRI(23)=160,
+  NRGRI(24)=160,
+  NRGRI(25)=160,
+  NRGRI(26)=160,
+  NRGRI(27)=160,
+  NRGRI(28)=180,
+  NRGRI(29)=180,
+  NRGRI(30)=180,
+  NRGRI(31)=180,
+  NRGRI(32)=180,
+  NRGRI(33)=192,
+  NRGRI(34)=192,
+  NRGRI(35)=192,
+  NRGRI(36)=192,
+  NRGRI(37)=192,
+  NRGRI(38)=192,
+  NRGRI(39)=192,
+  NRGRI(40)=192,
+  NRGRI(41)=192,
+  NRGRI(42)=192,
+  NRGRI(43)=192,
+  NRGRI(44)=192,
+  NRGRI(45)=192,
+  NRGRI(46)=192,
+  NRGRI(47)=192,
+  NRGRI(48)=192,
+  NRGRI(49)=192,
+  NRGRI(50)=192,
+  NRGRI(51)=192,
+  NRGRI(52)=192,
+  NRGRI(53)=192,
+  NRGRI(54)=192,
+  NRGRI(55)=192,
+  NRGRI(56)=192,
+  NRGRI(57)=192,
+  NRGRI(58)=192,
+  NRGRI(59)=192,
+  NRGRI(60)=192,
+  NRGRI(61)=192,
+  NRGRI(62)=192,
+  NRGRI(63)=192,
+  NRGRI(64)=192,
+  NRGRI(65)=180,
+  NRGRI(66)=180,
+  NRGRI(67)=180,
+  NRGRI(68)=180,
+  NRGRI(69)=180,
+  NRGRI(70)=160,
+  NRGRI(71)=160,
+  NRGRI(72)=160,
+  NRGRI(73)=160,
+  NRGRI(74)=160,
+  NRGRI(75)=144,
+  NRGRI(76)=144,
+  NRGRI(77)=135,
+  NRGRI(78)=128,
+  NRGRI(79)=120,
+  NRGRI(80)=120,
+  NRGRI(81)=120,
+  NRGRI(82)=108,
+  NRGRI(83)=100,
+  NRGRI(84)= 96,
+  NRGRI(85)= 90,
+  NRGRI(86)= 80,
+  NRGRI(87)= 75,
+  NRGRI(88)= 72,
+  NRGRI(89)= 60,
+  NRGRI(90)= 60,
+  NRGRI(91)= 50,
+  NRGRI(92)= 45,
+  NRGRI(93)= 40,
+  NRGRI(94)= 36,
+  NRGRI(95)= 25,
+  NRGRI(96)= 20,
+ /
diff --git a/odb/share/odb/rtablel_21023 b/odb/share/odb/rtablel_21023
new file mode 100644
index 0000000..493f748
--- /dev/null
+++ b/odb/share/odb/rtablel_21023
@@ -0,0 +1,1026 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   75,
+  NRGRI(0012)=   81,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   96,
+  NRGRI(0015)=   96,
+  NRGRI(0016)=  100,
+  NRGRI(0017)=  108,
+  NRGRI(0018)=  120,
+  NRGRI(0019)=  125,
+  NRGRI(0020)=  128,
+  NRGRI(0021)=  135,
+  NRGRI(0022)=  144,
+  NRGRI(0023)=  150,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  160,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  180,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  192,
+  NRGRI(0031)=  200,
+  NRGRI(0032)=  216,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  225,
+  NRGRI(0035)=  225,
+  NRGRI(0036)=  240,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  243,
+  NRGRI(0039)=  250,
+  NRGRI(0040)=  256,
+  NRGRI(0041)=  270,
+  NRGRI(0042)=  270,
+  NRGRI(0043)=  288,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  288,
+  NRGRI(0046)=  300,
+  NRGRI(0047)=  320,
+  NRGRI(0048)=  320,
+  NRGRI(0049)=  320,
+  NRGRI(0050)=  320,
+  NRGRI(0051)=  360,
+  NRGRI(0052)=  360,
+  NRGRI(0053)=  360,
+  NRGRI(0054)=  360,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  375,
+  NRGRI(0058)=  375,
+  NRGRI(0059)=  384,
+  NRGRI(0060)=  384,
+  NRGRI(0061)=  400,
+  NRGRI(0062)=  400,
+  NRGRI(0063)=  400,
+  NRGRI(0064)=  432,
+  NRGRI(0065)=  432,
+  NRGRI(0066)=  432,
+  NRGRI(0067)=  432,
+  NRGRI(0068)=  450,
+  NRGRI(0069)=  450,
+  NRGRI(0070)=  450,
+  NRGRI(0071)=  480,
+  NRGRI(0072)=  480,
+  NRGRI(0073)=  480,
+  NRGRI(0074)=  480,
+  NRGRI(0075)=  480,
+  NRGRI(0076)=  486,
+  NRGRI(0077)=  500,
+  NRGRI(0078)=  500,
+  NRGRI(0079)=  512,
+  NRGRI(0080)=  512,
+  NRGRI(0081)=  540,
+  NRGRI(0082)=  540,
+  NRGRI(0083)=  540,
+  NRGRI(0084)=  540,
+  NRGRI(0085)=  540,
+  NRGRI(0086)=  576,
+  NRGRI(0087)=  576,
+  NRGRI(0088)=  576,
+  NRGRI(0089)=  576,
+  NRGRI(0090)=  576,
+  NRGRI(0091)=  576,
+  NRGRI(0092)=  600,
+  NRGRI(0093)=  600,
+  NRGRI(0094)=  600,
+  NRGRI(0095)=  640,
+  NRGRI(0096)=  640,
+  NRGRI(0097)=  640,
+  NRGRI(0098)=  640,
+  NRGRI(0099)=  640,
+  NRGRI(0100)=  640,
+  NRGRI(0101)=  640,
+  NRGRI(0102)=  648,
+  NRGRI(0103)=  675,
+  NRGRI(0104)=  675,
+  NRGRI(0105)=  675,
+  NRGRI(0106)=  675,
+  NRGRI(0107)=  675,
+  NRGRI(0108)=  720,
+  NRGRI(0109)=  720,
+  NRGRI(0110)=  720,
+  NRGRI(0111)=  720,
+  NRGRI(0112)=  720,
+  NRGRI(0113)=  720,
+  NRGRI(0114)=  720,
+  NRGRI(0115)=  729,
+  NRGRI(0116)=  729,
+  NRGRI(0117)=  750,
+  NRGRI(0118)=  750,
+  NRGRI(0119)=  750,
+  NRGRI(0120)=  768,
+  NRGRI(0121)=  768,
+  NRGRI(0122)=  768,
+  NRGRI(0123)=  800,
+  NRGRI(0124)=  800,
+  NRGRI(0125)=  800,
+  NRGRI(0126)=  800,
+  NRGRI(0127)=  800,
+  NRGRI(0128)=  800,
+  NRGRI(0129)=  810,
+  NRGRI(0130)=  864,
+  NRGRI(0131)=  864,
+  NRGRI(0132)=  864,
+  NRGRI(0133)=  864,
+  NRGRI(0134)=  864,
+  NRGRI(0135)=  864,
+  NRGRI(0136)=  864,
+  NRGRI(0137)=  864,
+  NRGRI(0138)=  864,
+  NRGRI(0139)=  864,
+  NRGRI(0140)=  900,
+  NRGRI(0141)=  900,
+  NRGRI(0142)=  900,
+  NRGRI(0143)=  900,
+  NRGRI(0144)=  900,
+  NRGRI(0145)=  900,
+  NRGRI(0146)=  960,
+  NRGRI(0147)=  960,
+  NRGRI(0148)=  960,
+  NRGRI(0149)=  960,
+  NRGRI(0150)=  960,
+  NRGRI(0151)=  960,
+  NRGRI(0152)=  960,
+  NRGRI(0153)=  960,
+  NRGRI(0154)=  960,
+  NRGRI(0155)=  960,
+  NRGRI(0156)=  960,
+  NRGRI(0157)=  972,
+  NRGRI(0158)=  972,
+  NRGRI(0159)= 1000,
+  NRGRI(0160)= 1000,
+  NRGRI(0161)= 1000,
+  NRGRI(0162)= 1000,
+  NRGRI(0163)= 1000,
+  NRGRI(0164)= 1024,
+  NRGRI(0165)= 1024,
+  NRGRI(0166)= 1024,
+  NRGRI(0167)= 1024,
+  NRGRI(0168)= 1080,
+  NRGRI(0169)= 1080,
+  NRGRI(0170)= 1080,
+  NRGRI(0171)= 1080,
+  NRGRI(0172)= 1080,
+  NRGRI(0173)= 1080,
+  NRGRI(0174)= 1080,
+  NRGRI(0175)= 1080,
+  NRGRI(0176)= 1080,
+  NRGRI(0177)= 1080,
+  NRGRI(0178)= 1125,
+  NRGRI(0179)= 1125,
+  NRGRI(0180)= 1125,
+  NRGRI(0181)= 1125,
+  NRGRI(0182)= 1125,
+  NRGRI(0183)= 1125,
+  NRGRI(0184)= 1125,
+  NRGRI(0185)= 1125,
+  NRGRI(0186)= 1125,
+  NRGRI(0187)= 1152,
+  NRGRI(0188)= 1152,
+  NRGRI(0189)= 1152,
+  NRGRI(0190)= 1152,
+  NRGRI(0191)= 1152,
+  NRGRI(0192)= 1200,
+  NRGRI(0193)= 1200,
+  NRGRI(0194)= 1200,
+  NRGRI(0195)= 1200,
+  NRGRI(0196)= 1200,
+  NRGRI(0197)= 1200,
+  NRGRI(0198)= 1200,
+  NRGRI(0199)= 1200,
+  NRGRI(0200)= 1200,
+  NRGRI(0201)= 1215,
+  NRGRI(0202)= 1215,
+  NRGRI(0203)= 1215,
+  NRGRI(0204)= 1280,
+  NRGRI(0205)= 1280,
+  NRGRI(0206)= 1280,
+  NRGRI(0207)= 1280,
+  NRGRI(0208)= 1280,
+  NRGRI(0209)= 1280,
+  NRGRI(0210)= 1280,
+  NRGRI(0211)= 1280,
+  NRGRI(0212)= 1280,
+  NRGRI(0213)= 1280,
+  NRGRI(0214)= 1280,
+  NRGRI(0215)= 1280,
+  NRGRI(0216)= 1280,
+  NRGRI(0217)= 1296,
+  NRGRI(0218)= 1296,
+  NRGRI(0219)= 1296,
+  NRGRI(0220)= 1350,
+  NRGRI(0221)= 1350,
+  NRGRI(0222)= 1350,
+  NRGRI(0223)= 1350,
+  NRGRI(0224)= 1350,
+  NRGRI(0225)= 1350,
+  NRGRI(0226)= 1350,
+  NRGRI(0227)= 1350,
+  NRGRI(0228)= 1350,
+  NRGRI(0229)= 1350,
+  NRGRI(0230)= 1350,
+  NRGRI(0231)= 1440,
+  NRGRI(0232)= 1440,
+  NRGRI(0233)= 1440,
+  NRGRI(0234)= 1440,
+  NRGRI(0235)= 1440,
+  NRGRI(0236)= 1440,
+  NRGRI(0237)= 1440,
+  NRGRI(0238)= 1440,
+  NRGRI(0239)= 1440,
+  NRGRI(0240)= 1440,
+  NRGRI(0241)= 1440,
+  NRGRI(0242)= 1440,
+  NRGRI(0243)= 1440,
+  NRGRI(0244)= 1440,
+  NRGRI(0245)= 1440,
+  NRGRI(0246)= 1440,
+  NRGRI(0247)= 1440,
+  NRGRI(0248)= 1440,
+  NRGRI(0249)= 1440,
+  NRGRI(0250)= 1458,
+  NRGRI(0251)= 1458,
+  NRGRI(0252)= 1458,
+  NRGRI(0253)= 1458,
+  NRGRI(0254)= 1500,
+  NRGRI(0255)= 1500,
+  NRGRI(0256)= 1500,
+  NRGRI(0257)= 1500,
+  NRGRI(0258)= 1500,
+  NRGRI(0259)= 1500,
+  NRGRI(0260)= 1500,
+  NRGRI(0261)= 1500,
+  NRGRI(0262)= 1500,
+  NRGRI(0263)= 1500,
+  NRGRI(0264)= 1536,
+  NRGRI(0265)= 1536,
+  NRGRI(0266)= 1536,
+  NRGRI(0267)= 1536,
+  NRGRI(0268)= 1536,
+  NRGRI(0269)= 1536,
+  NRGRI(0270)= 1536,
+  NRGRI(0271)= 1536,
+  NRGRI(0272)= 1600,
+  NRGRI(0273)= 1600,
+  NRGRI(0274)= 1600,
+  NRGRI(0275)= 1600,
+  NRGRI(0276)= 1600,
+  NRGRI(0277)= 1600,
+  NRGRI(0278)= 1600,
+  NRGRI(0279)= 1600,
+  NRGRI(0280)= 1600,
+  NRGRI(0281)= 1600,
+  NRGRI(0282)= 1600,
+  NRGRI(0283)= 1600,
+  NRGRI(0284)= 1600,
+  NRGRI(0285)= 1600,
+  NRGRI(0286)= 1600,
+  NRGRI(0287)= 1600,
+  NRGRI(0288)= 1620,
+  NRGRI(0289)= 1620,
+  NRGRI(0290)= 1620,
+  NRGRI(0291)= 1620,
+  NRGRI(0292)= 1728,
+  NRGRI(0293)= 1728,
+  NRGRI(0294)= 1728,
+  NRGRI(0295)= 1728,
+  NRGRI(0296)= 1728,
+  NRGRI(0297)= 1728,
+  NRGRI(0298)= 1728,
+  NRGRI(0299)= 1728,
+  NRGRI(0300)= 1728,
+  NRGRI(0301)= 1728,
+  NRGRI(0302)= 1728,
+  NRGRI(0303)= 1728,
+  NRGRI(0304)= 1728,
+  NRGRI(0305)= 1728,
+  NRGRI(0306)= 1728,
+  NRGRI(0307)= 1728,
+  NRGRI(0308)= 1728,
+  NRGRI(0309)= 1728,
+  NRGRI(0310)= 1728,
+  NRGRI(0311)= 1728,
+  NRGRI(0312)= 1728,
+  NRGRI(0313)= 1728,
+  NRGRI(0314)= 1728,
+  NRGRI(0315)= 1728,
+  NRGRI(0316)= 1728,
+  NRGRI(0317)= 1728,
+  NRGRI(0318)= 1728,
+  NRGRI(0319)= 1728,
+  NRGRI(0320)= 1728,
+  NRGRI(0321)= 1728,
+  NRGRI(0322)= 1800,
+  NRGRI(0323)= 1800,
+  NRGRI(0324)= 1800,
+  NRGRI(0325)= 1800,
+  NRGRI(0326)= 1800,
+  NRGRI(0327)= 1800,
+  NRGRI(0328)= 1800,
+  NRGRI(0329)= 1800,
+  NRGRI(0330)= 1800,
+  NRGRI(0331)= 1800,
+  NRGRI(0332)= 1800,
+  NRGRI(0333)= 1800,
+  NRGRI(0334)= 1800,
+  NRGRI(0335)= 1800,
+  NRGRI(0336)= 1800,
+  NRGRI(0337)= 1800,
+  NRGRI(0338)= 1800,
+  NRGRI(0339)= 1800,
+  NRGRI(0340)= 1800,
+  NRGRI(0341)= 1800,
+  NRGRI(0342)= 1800,
+  NRGRI(0343)= 1800,
+  NRGRI(0344)= 1875,
+  NRGRI(0345)= 1875,
+  NRGRI(0346)= 1875,
+  NRGRI(0347)= 1875,
+  NRGRI(0348)= 1875,
+  NRGRI(0349)= 1875,
+  NRGRI(0350)= 1875,
+  NRGRI(0351)= 1875,
+  NRGRI(0352)= 1875,
+  NRGRI(0353)= 1875,
+  NRGRI(0354)= 1875,
+  NRGRI(0355)= 1875,
+  NRGRI(0356)= 1875,
+  NRGRI(0357)= 1875,
+  NRGRI(0358)= 1875,
+  NRGRI(0359)= 1875,
+  NRGRI(0360)= 1875,
+  NRGRI(0361)= 1875,
+  NRGRI(0362)= 1875,
+  NRGRI(0363)= 1875,
+  NRGRI(0364)= 1875,
+  NRGRI(0365)= 1875,
+  NRGRI(0366)= 1875,
+  NRGRI(0367)= 1875,
+  NRGRI(0368)= 1875,
+  NRGRI(0369)= 1875,
+  NRGRI(0370)= 1920,
+  NRGRI(0371)= 1920,
+  NRGRI(0372)= 1920,
+  NRGRI(0373)= 1920,
+  NRGRI(0374)= 1920,
+  NRGRI(0375)= 1920,
+  NRGRI(0376)= 1920,
+  NRGRI(0377)= 1920,
+  NRGRI(0378)= 1920,
+  NRGRI(0379)= 1920,
+  NRGRI(0380)= 1920,
+  NRGRI(0381)= 1920,
+  NRGRI(0382)= 1920,
+  NRGRI(0383)= 1920,
+  NRGRI(0384)= 1920,
+  NRGRI(0385)= 1920,
+  NRGRI(0386)= 1920,
+  NRGRI(0387)= 1920,
+  NRGRI(0388)= 1944,
+  NRGRI(0389)= 1944,
+  NRGRI(0390)= 1944,
+  NRGRI(0391)= 1944,
+  NRGRI(0392)= 1944,
+  NRGRI(0393)= 1944,
+  NRGRI(0394)= 1944,
+  NRGRI(0395)= 1944,
+  NRGRI(0396)= 1944,
+  NRGRI(0397)= 1944,
+  NRGRI(0398)= 1944,
+  NRGRI(0399)= 2000,
+  NRGRI(0400)= 2000,
+  NRGRI(0401)= 2000,
+  NRGRI(0402)= 2000,
+  NRGRI(0403)= 2000,
+  NRGRI(0404)= 2000,
+  NRGRI(0405)= 2000,
+  NRGRI(0406)= 2000,
+  NRGRI(0407)= 2000,
+  NRGRI(0408)= 2000,
+  NRGRI(0409)= 2000,
+  NRGRI(0410)= 2000,
+  NRGRI(0411)= 2000,
+  NRGRI(0412)= 2000,
+  NRGRI(0413)= 2000,
+  NRGRI(0414)= 2000,
+  NRGRI(0415)= 2000,
+  NRGRI(0416)= 2000,
+  NRGRI(0417)= 2000,
+  NRGRI(0418)= 2000,
+  NRGRI(0419)= 2000,
+  NRGRI(0420)= 2000,
+  NRGRI(0421)= 2000,
+  NRGRI(0422)= 2000,
+  NRGRI(0423)= 2000,
+  NRGRI(0424)= 2000,
+  NRGRI(0425)= 2000,
+  NRGRI(0426)= 2000,
+  NRGRI(0427)= 2000,
+  NRGRI(0428)= 2000,
+  NRGRI(0429)= 2000,
+  NRGRI(0430)= 2000,
+  NRGRI(0431)= 2025,
+  NRGRI(0432)= 2025,
+  NRGRI(0433)= 2025,
+  NRGRI(0434)= 2025,
+  NRGRI(0435)= 2025,
+  NRGRI(0436)= 2025,
+  NRGRI(0437)= 2025,
+  NRGRI(0438)= 2025,
+  NRGRI(0439)= 2025,
+  NRGRI(0440)= 2025,
+  NRGRI(0441)= 2025,
+  NRGRI(0442)= 2025,
+  NRGRI(0443)= 2025,
+  NRGRI(0444)= 2025,
+  NRGRI(0445)= 2025,
+  NRGRI(0446)= 2025,
+  NRGRI(0447)= 2025,
+  NRGRI(0448)= 2025,
+  NRGRI(0449)= 2048,
+  NRGRI(0450)= 2048,
+  NRGRI(0451)= 2048,
+  NRGRI(0452)= 2048,
+  NRGRI(0453)= 2048,
+  NRGRI(0454)= 2048,
+  NRGRI(0455)= 2048,
+  NRGRI(0456)= 2048,
+  NRGRI(0457)= 2048,
+  NRGRI(0458)= 2048,
+  NRGRI(0459)= 2048,
+  NRGRI(0460)= 2048,
+  NRGRI(0461)= 2048,
+  NRGRI(0462)= 2048,
+  NRGRI(0463)= 2048,
+  NRGRI(0464)= 2048,
+  NRGRI(0465)= 2048,
+  NRGRI(0466)= 2048,
+  NRGRI(0467)= 2048,
+  NRGRI(0468)= 2048,
+  NRGRI(0469)= 2048,
+  NRGRI(0470)= 2048,
+  NRGRI(0471)= 2048,
+  NRGRI(0472)= 2048,
+  NRGRI(0473)= 2048,
+  NRGRI(0474)= 2048,
+  NRGRI(0475)= 2048,
+  NRGRI(0476)= 2048,
+  NRGRI(0477)= 2048,
+  NRGRI(0478)= 2048,
+  NRGRI(0479)= 2048,
+  NRGRI(0480)= 2048,
+  NRGRI(0481)= 2048,
+  NRGRI(0482)= 2048,
+  NRGRI(0483)= 2048,
+  NRGRI(0484)= 2048,
+  NRGRI(0485)= 2048,
+  NRGRI(0486)= 2048,
+  NRGRI(0487)= 2048,
+  NRGRI(0488)= 2048,
+  NRGRI(0489)= 2048,
+  NRGRI(0490)= 2048,
+  NRGRI(0491)= 2048,
+  NRGRI(0492)= 2048,
+  NRGRI(0493)= 2048,
+  NRGRI(0494)= 2048,
+  NRGRI(0495)= 2048,
+  NRGRI(0496)= 2048,
+  NRGRI(0497)= 2048,
+  NRGRI(0498)= 2048,
+  NRGRI(0499)= 2048,
+  NRGRI(0500)= 2048,
+  NRGRI(0501)= 2048,
+  NRGRI(0502)= 2048,
+  NRGRI(0503)= 2048,
+  NRGRI(0504)= 2048,
+  NRGRI(0505)= 2048,
+  NRGRI(0506)= 2048,
+  NRGRI(0507)= 2048,
+  NRGRI(0508)= 2048,
+  NRGRI(0509)= 2048,
+  NRGRI(0510)= 2048,
+  NRGRI(0511)= 2048,
+  NRGRI(0512)= 2048,
+  NRGRI(0513)= 2048,
+  NRGRI(0514)= 2048,
+  NRGRI(0515)= 2048,
+  NRGRI(0516)= 2048,
+  NRGRI(0517)= 2048,
+  NRGRI(0518)= 2048,
+  NRGRI(0519)= 2048,
+  NRGRI(0520)= 2048,
+  NRGRI(0521)= 2048,
+  NRGRI(0522)= 2048,
+  NRGRI(0523)= 2048,
+  NRGRI(0524)= 2048,
+  NRGRI(0525)= 2048,
+  NRGRI(0526)= 2048,
+  NRGRI(0527)= 2048,
+  NRGRI(0528)= 2048,
+  NRGRI(0529)= 2048,
+  NRGRI(0530)= 2048,
+  NRGRI(0531)= 2048,
+  NRGRI(0532)= 2048,
+  NRGRI(0533)= 2048,
+  NRGRI(0534)= 2048,
+  NRGRI(0535)= 2048,
+  NRGRI(0536)= 2048,
+  NRGRI(0537)= 2048,
+  NRGRI(0538)= 2048,
+  NRGRI(0539)= 2048,
+  NRGRI(0540)= 2048,
+  NRGRI(0541)= 2048,
+  NRGRI(0542)= 2048,
+  NRGRI(0543)= 2048,
+  NRGRI(0544)= 2048,
+  NRGRI(0545)= 2048,
+  NRGRI(0546)= 2048,
+  NRGRI(0547)= 2048,
+  NRGRI(0548)= 2048,
+  NRGRI(0549)= 2048,
+  NRGRI(0550)= 2048,
+  NRGRI(0551)= 2048,
+  NRGRI(0552)= 2048,
+  NRGRI(0553)= 2048,
+  NRGRI(0554)= 2048,
+  NRGRI(0555)= 2048,
+  NRGRI(0556)= 2048,
+  NRGRI(0557)= 2048,
+  NRGRI(0558)= 2048,
+  NRGRI(0559)= 2048,
+  NRGRI(0560)= 2048,
+  NRGRI(0561)= 2048,
+  NRGRI(0562)= 2048,
+  NRGRI(0563)= 2048,
+  NRGRI(0564)= 2048,
+  NRGRI(0565)= 2048,
+  NRGRI(0566)= 2048,
+  NRGRI(0567)= 2048,
+  NRGRI(0568)= 2048,
+  NRGRI(0569)= 2048,
+  NRGRI(0570)= 2048,
+  NRGRI(0571)= 2048,
+  NRGRI(0572)= 2048,
+  NRGRI(0573)= 2048,
+  NRGRI(0574)= 2048,
+  NRGRI(0575)= 2048,
+  NRGRI(0576)= 2048,
+  NRGRI(0577)= 2025,
+  NRGRI(0578)= 2025,
+  NRGRI(0579)= 2025,
+  NRGRI(0580)= 2025,
+  NRGRI(0581)= 2025,
+  NRGRI(0582)= 2025,
+  NRGRI(0583)= 2025,
+  NRGRI(0584)= 2025,
+  NRGRI(0585)= 2025,
+  NRGRI(0586)= 2025,
+  NRGRI(0587)= 2025,
+  NRGRI(0588)= 2025,
+  NRGRI(0589)= 2025,
+  NRGRI(0590)= 2025,
+  NRGRI(0591)= 2025,
+  NRGRI(0592)= 2025,
+  NRGRI(0593)= 2025,
+  NRGRI(0594)= 2025,
+  NRGRI(0595)= 2000,
+  NRGRI(0596)= 2000,
+  NRGRI(0597)= 2000,
+  NRGRI(0598)= 2000,
+  NRGRI(0599)= 2000,
+  NRGRI(0600)= 2000,
+  NRGRI(0601)= 2000,
+  NRGRI(0602)= 2000,
+  NRGRI(0603)= 2000,
+  NRGRI(0604)= 2000,
+  NRGRI(0605)= 2000,
+  NRGRI(0606)= 2000,
+  NRGRI(0607)= 2000,
+  NRGRI(0608)= 2000,
+  NRGRI(0609)= 2000,
+  NRGRI(0610)= 2000,
+  NRGRI(0611)= 2000,
+  NRGRI(0612)= 2000,
+  NRGRI(0613)= 2000,
+  NRGRI(0614)= 2000,
+  NRGRI(0615)= 2000,
+  NRGRI(0616)= 2000,
+  NRGRI(0617)= 2000,
+  NRGRI(0618)= 2000,
+  NRGRI(0619)= 2000,
+  NRGRI(0620)= 2000,
+  NRGRI(0621)= 2000,
+  NRGRI(0622)= 2000,
+  NRGRI(0623)= 2000,
+  NRGRI(0624)= 2000,
+  NRGRI(0625)= 2000,
+  NRGRI(0626)= 2000,
+  NRGRI(0627)= 1944,
+  NRGRI(0628)= 1944,
+  NRGRI(0629)= 1944,
+  NRGRI(0630)= 1944,
+  NRGRI(0631)= 1944,
+  NRGRI(0632)= 1944,
+  NRGRI(0633)= 1944,
+  NRGRI(0634)= 1944,
+  NRGRI(0635)= 1944,
+  NRGRI(0636)= 1944,
+  NRGRI(0637)= 1944,
+  NRGRI(0638)= 1920,
+  NRGRI(0639)= 1920,
+  NRGRI(0640)= 1920,
+  NRGRI(0641)= 1920,
+  NRGRI(0642)= 1920,
+  NRGRI(0643)= 1920,
+  NRGRI(0644)= 1920,
+  NRGRI(0645)= 1920,
+  NRGRI(0646)= 1920,
+  NRGRI(0647)= 1920,
+  NRGRI(0648)= 1920,
+  NRGRI(0649)= 1920,
+  NRGRI(0650)= 1920,
+  NRGRI(0651)= 1920,
+  NRGRI(0652)= 1920,
+  NRGRI(0653)= 1920,
+  NRGRI(0654)= 1920,
+  NRGRI(0655)= 1920,
+  NRGRI(0656)= 1875,
+  NRGRI(0657)= 1875,
+  NRGRI(0658)= 1875,
+  NRGRI(0659)= 1875,
+  NRGRI(0660)= 1875,
+  NRGRI(0661)= 1875,
+  NRGRI(0662)= 1875,
+  NRGRI(0663)= 1875,
+  NRGRI(0664)= 1875,
+  NRGRI(0665)= 1875,
+  NRGRI(0666)= 1875,
+  NRGRI(0667)= 1875,
+  NRGRI(0668)= 1875,
+  NRGRI(0669)= 1875,
+  NRGRI(0670)= 1875,
+  NRGRI(0671)= 1875,
+  NRGRI(0672)= 1875,
+  NRGRI(0673)= 1875,
+  NRGRI(0674)= 1875,
+  NRGRI(0675)= 1875,
+  NRGRI(0676)= 1875,
+  NRGRI(0677)= 1875,
+  NRGRI(0678)= 1875,
+  NRGRI(0679)= 1875,
+  NRGRI(0680)= 1875,
+  NRGRI(0681)= 1875,
+  NRGRI(0682)= 1800,
+  NRGRI(0683)= 1800,
+  NRGRI(0684)= 1800,
+  NRGRI(0685)= 1800,
+  NRGRI(0686)= 1800,
+  NRGRI(0687)= 1800,
+  NRGRI(0688)= 1800,
+  NRGRI(0689)= 1800,
+  NRGRI(0690)= 1800,
+  NRGRI(0691)= 1800,
+  NRGRI(0692)= 1800,
+  NRGRI(0693)= 1800,
+  NRGRI(0694)= 1800,
+  NRGRI(0695)= 1800,
+  NRGRI(0696)= 1800,
+  NRGRI(0697)= 1800,
+  NRGRI(0698)= 1800,
+  NRGRI(0699)= 1800,
+  NRGRI(0700)= 1800,
+  NRGRI(0701)= 1800,
+  NRGRI(0702)= 1800,
+  NRGRI(0703)= 1800,
+  NRGRI(0704)= 1728,
+  NRGRI(0705)= 1728,
+  NRGRI(0706)= 1728,
+  NRGRI(0707)= 1728,
+  NRGRI(0708)= 1728,
+  NRGRI(0709)= 1728,
+  NRGRI(0710)= 1728,
+  NRGRI(0711)= 1728,
+  NRGRI(0712)= 1728,
+  NRGRI(0713)= 1728,
+  NRGRI(0714)= 1728,
+  NRGRI(0715)= 1728,
+  NRGRI(0716)= 1728,
+  NRGRI(0717)= 1728,
+  NRGRI(0718)= 1728,
+  NRGRI(0719)= 1728,
+  NRGRI(0720)= 1728,
+  NRGRI(0721)= 1728,
+  NRGRI(0722)= 1728,
+  NRGRI(0723)= 1728,
+  NRGRI(0724)= 1728,
+  NRGRI(0725)= 1728,
+  NRGRI(0726)= 1728,
+  NRGRI(0727)= 1728,
+  NRGRI(0728)= 1728,
+  NRGRI(0729)= 1728,
+  NRGRI(0730)= 1728,
+  NRGRI(0731)= 1728,
+  NRGRI(0732)= 1728,
+  NRGRI(0733)= 1728,
+  NRGRI(0734)= 1620,
+  NRGRI(0735)= 1620,
+  NRGRI(0736)= 1620,
+  NRGRI(0737)= 1620,
+  NRGRI(0738)= 1600,
+  NRGRI(0739)= 1600,
+  NRGRI(0740)= 1600,
+  NRGRI(0741)= 1600,
+  NRGRI(0742)= 1600,
+  NRGRI(0743)= 1600,
+  NRGRI(0744)= 1600,
+  NRGRI(0745)= 1600,
+  NRGRI(0746)= 1600,
+  NRGRI(0747)= 1600,
+  NRGRI(0748)= 1600,
+  NRGRI(0749)= 1600,
+  NRGRI(0750)= 1600,
+  NRGRI(0751)= 1600,
+  NRGRI(0752)= 1600,
+  NRGRI(0753)= 1600,
+  NRGRI(0754)= 1536,
+  NRGRI(0755)= 1536,
+  NRGRI(0756)= 1536,
+  NRGRI(0757)= 1536,
+  NRGRI(0758)= 1536,
+  NRGRI(0759)= 1536,
+  NRGRI(0760)= 1536,
+  NRGRI(0761)= 1536,
+  NRGRI(0762)= 1500,
+  NRGRI(0763)= 1500,
+  NRGRI(0764)= 1500,
+  NRGRI(0765)= 1500,
+  NRGRI(0766)= 1500,
+  NRGRI(0767)= 1500,
+  NRGRI(0768)= 1500,
+  NRGRI(0769)= 1500,
+  NRGRI(0770)= 1500,
+  NRGRI(0771)= 1500,
+  NRGRI(0772)= 1458,
+  NRGRI(0773)= 1458,
+  NRGRI(0774)= 1458,
+  NRGRI(0775)= 1458,
+  NRGRI(0776)= 1440,
+  NRGRI(0777)= 1440,
+  NRGRI(0778)= 1440,
+  NRGRI(0779)= 1440,
+  NRGRI(0780)= 1440,
+  NRGRI(0781)= 1440,
+  NRGRI(0782)= 1440,
+  NRGRI(0783)= 1440,
+  NRGRI(0784)= 1440,
+  NRGRI(0785)= 1440,
+  NRGRI(0786)= 1440,
+  NRGRI(0787)= 1440,
+  NRGRI(0788)= 1440,
+  NRGRI(0789)= 1440,
+  NRGRI(0790)= 1440,
+  NRGRI(0791)= 1440,
+  NRGRI(0792)= 1440,
+  NRGRI(0793)= 1440,
+  NRGRI(0794)= 1440,
+  NRGRI(0795)= 1350,
+  NRGRI(0796)= 1350,
+  NRGRI(0797)= 1350,
+  NRGRI(0798)= 1350,
+  NRGRI(0799)= 1350,
+  NRGRI(0800)= 1350,
+  NRGRI(0801)= 1350,
+  NRGRI(0802)= 1350,
+  NRGRI(0803)= 1350,
+  NRGRI(0804)= 1350,
+  NRGRI(0805)= 1350,
+  NRGRI(0806)= 1296,
+  NRGRI(0807)= 1296,
+  NRGRI(0808)= 1296,
+  NRGRI(0809)= 1280,
+  NRGRI(0810)= 1280,
+  NRGRI(0811)= 1280,
+  NRGRI(0812)= 1280,
+  NRGRI(0813)= 1280,
+  NRGRI(0814)= 1280,
+  NRGRI(0815)= 1280,
+  NRGRI(0816)= 1280,
+  NRGRI(0817)= 1280,
+  NRGRI(0818)= 1280,
+  NRGRI(0819)= 1280,
+  NRGRI(0820)= 1280,
+  NRGRI(0821)= 1280,
+  NRGRI(0822)= 1215,
+  NRGRI(0823)= 1215,
+  NRGRI(0824)= 1215,
+  NRGRI(0825)= 1200,
+  NRGRI(0826)= 1200,
+  NRGRI(0827)= 1200,
+  NRGRI(0828)= 1200,
+  NRGRI(0829)= 1200,
+  NRGRI(0830)= 1200,
+  NRGRI(0831)= 1200,
+  NRGRI(0832)= 1200,
+  NRGRI(0833)= 1200,
+  NRGRI(0834)= 1152,
+  NRGRI(0835)= 1152,
+  NRGRI(0836)= 1152,
+  NRGRI(0837)= 1152,
+  NRGRI(0838)= 1152,
+  NRGRI(0839)= 1125,
+  NRGRI(0840)= 1125,
+  NRGRI(0841)= 1125,
+  NRGRI(0842)= 1125,
+  NRGRI(0843)= 1125,
+  NRGRI(0844)= 1125,
+  NRGRI(0845)= 1125,
+  NRGRI(0846)= 1125,
+  NRGRI(0847)= 1125,
+  NRGRI(0848)= 1080,
+  NRGRI(0849)= 1080,
+  NRGRI(0850)= 1080,
+  NRGRI(0851)= 1080,
+  NRGRI(0852)= 1080,
+  NRGRI(0853)= 1080,
+  NRGRI(0854)= 1080,
+  NRGRI(0855)= 1080,
+  NRGRI(0856)= 1080,
+  NRGRI(0857)= 1080,
+  NRGRI(0858)= 1024,
+  NRGRI(0859)= 1024,
+  NRGRI(0860)= 1024,
+  NRGRI(0861)= 1024,
+  NRGRI(0862)= 1000,
+  NRGRI(0863)= 1000,
+  NRGRI(0864)= 1000,
+  NRGRI(0865)= 1000,
+  NRGRI(0866)= 1000,
+  NRGRI(0867)=  972,
+  NRGRI(0868)=  972,
+  NRGRI(0869)=  960,
+  NRGRI(0870)=  960,
+  NRGRI(0871)=  960,
+  NRGRI(0872)=  960,
+  NRGRI(0873)=  960,
+  NRGRI(0874)=  960,
+  NRGRI(0875)=  960,
+  NRGRI(0876)=  960,
+  NRGRI(0877)=  960,
+  NRGRI(0878)=  960,
+  NRGRI(0879)=  960,
+  NRGRI(0880)=  900,
+  NRGRI(0881)=  900,
+  NRGRI(0882)=  900,
+  NRGRI(0883)=  900,
+  NRGRI(0884)=  900,
+  NRGRI(0885)=  900,
+  NRGRI(0886)=  864,
+  NRGRI(0887)=  864,
+  NRGRI(0888)=  864,
+  NRGRI(0889)=  864,
+  NRGRI(0890)=  864,
+  NRGRI(0891)=  864,
+  NRGRI(0892)=  864,
+  NRGRI(0893)=  864,
+  NRGRI(0894)=  864,
+  NRGRI(0895)=  864,
+  NRGRI(0896)=  810,
+  NRGRI(0897)=  800,
+  NRGRI(0898)=  800,
+  NRGRI(0899)=  800,
+  NRGRI(0900)=  800,
+  NRGRI(0901)=  800,
+  NRGRI(0902)=  800,
+  NRGRI(0903)=  768,
+  NRGRI(0904)=  768,
+  NRGRI(0905)=  768,
+  NRGRI(0906)=  750,
+  NRGRI(0907)=  750,
+  NRGRI(0908)=  750,
+  NRGRI(0909)=  729,
+  NRGRI(0910)=  729,
+  NRGRI(0911)=  720,
+  NRGRI(0912)=  720,
+  NRGRI(0913)=  720,
+  NRGRI(0914)=  720,
+  NRGRI(0915)=  720,
+  NRGRI(0916)=  720,
+  NRGRI(0917)=  720,
+  NRGRI(0918)=  675,
+  NRGRI(0919)=  675,
+  NRGRI(0920)=  675,
+  NRGRI(0921)=  675,
+  NRGRI(0922)=  675,
+  NRGRI(0923)=  648,
+  NRGRI(0924)=  640,
+  NRGRI(0925)=  640,
+  NRGRI(0926)=  640,
+  NRGRI(0927)=  640,
+  NRGRI(0928)=  640,
+  NRGRI(0929)=  640,
+  NRGRI(0930)=  640,
+  NRGRI(0931)=  600,
+  NRGRI(0932)=  600,
+  NRGRI(0933)=  600,
+  NRGRI(0934)=  576,
+  NRGRI(0935)=  576,
+  NRGRI(0936)=  576,
+  NRGRI(0937)=  576,
+  NRGRI(0938)=  576,
+  NRGRI(0939)=  576,
+  NRGRI(0940)=  540,
+  NRGRI(0941)=  540,
+  NRGRI(0942)=  540,
+  NRGRI(0943)=  540,
+  NRGRI(0944)=  540,
+  NRGRI(0945)=  512,
+  NRGRI(0946)=  512,
+  NRGRI(0947)=  500,
+  NRGRI(0948)=  500,
+  NRGRI(0949)=  486,
+  NRGRI(0950)=  480,
+  NRGRI(0951)=  480,
+  NRGRI(0952)=  480,
+  NRGRI(0953)=  480,
+  NRGRI(0954)=  480,
+  NRGRI(0955)=  450,
+  NRGRI(0956)=  450,
+  NRGRI(0957)=  450,
+  NRGRI(0958)=  432,
+  NRGRI(0959)=  432,
+  NRGRI(0960)=  432,
+  NRGRI(0961)=  432,
+  NRGRI(0962)=  400,
+  NRGRI(0963)=  400,
+  NRGRI(0964)=  400,
+  NRGRI(0965)=  384,
+  NRGRI(0966)=  384,
+  NRGRI(0967)=  375,
+  NRGRI(0968)=  375,
+  NRGRI(0969)=  360,
+  NRGRI(0970)=  360,
+  NRGRI(0971)=  360,
+  NRGRI(0972)=  360,
+  NRGRI(0973)=  360,
+  NRGRI(0974)=  360,
+  NRGRI(0975)=  320,
+  NRGRI(0976)=  320,
+  NRGRI(0977)=  320,
+  NRGRI(0978)=  320,
+  NRGRI(0979)=  300,
+  NRGRI(0980)=  288,
+  NRGRI(0981)=  288,
+  NRGRI(0982)=  288,
+  NRGRI(0983)=  270,
+  NRGRI(0984)=  270,
+  NRGRI(0985)=  256,
+  NRGRI(0986)=  250,
+  NRGRI(0987)=  243,
+  NRGRI(0988)=  240,
+  NRGRI(0989)=  240,
+  NRGRI(0990)=  225,
+  NRGRI(0991)=  225,
+  NRGRI(0992)=  216,
+  NRGRI(0993)=  216,
+  NRGRI(0994)=  200,
+  NRGRI(0995)=  192,
+  NRGRI(0996)=  192,
+  NRGRI(0997)=  180,
+  NRGRI(0998)=  180,
+  NRGRI(0999)=  180,
+  NRGRI(1000)=  160,
+  NRGRI(1001)=  160,
+  NRGRI(1002)=  150,
+  NRGRI(1003)=  144,
+  NRGRI(1004)=  135,
+  NRGRI(1005)=  128,
+  NRGRI(1006)=  125,
+  NRGRI(1007)=  120,
+  NRGRI(1008)=  108,
+  NRGRI(1009)=  100,
+  NRGRI(1010)=   96,
+  NRGRI(1011)=   96,
+  NRGRI(1012)=   90,
+  NRGRI(1013)=   81,
+  NRGRI(1014)=   75,
+  NRGRI(1015)=   72,
+  NRGRI(1016)=   72,
+  NRGRI(1017)=   60,
+  NRGRI(1018)=   60,
+  NRGRI(1019)=   50,
+  NRGRI(1020)=   45,
+  NRGRI(1021)=   40,
+  NRGRI(1022)=   32,
+  NRGRI(1023)=   25,
+  NRGRI(1024)=   18,
+ /
diff --git a/odb/share/odb/rtablel_21151 b/odb/share/odb/rtablel_21151
new file mode 100644
index 0000000..dba89ef
--- /dev/null
+++ b/odb/share/odb/rtablel_21151
@@ -0,0 +1,1154 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   75,
+  NRGRI(0012)=   81,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   96,
+  NRGRI(0015)=   96,
+  NRGRI(0016)=  100,
+  NRGRI(0017)=  108,
+  NRGRI(0018)=  120,
+  NRGRI(0019)=  120,
+  NRGRI(0020)=  125,
+  NRGRI(0021)=  135,
+  NRGRI(0022)=  144,
+  NRGRI(0023)=  150,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  160,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  180,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  192,
+  NRGRI(0031)=  200,
+  NRGRI(0032)=  216,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  225,
+  NRGRI(0035)=  225,
+  NRGRI(0036)=  240,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  243,
+  NRGRI(0039)=  250,
+  NRGRI(0040)=  256,
+  NRGRI(0041)=  270,
+  NRGRI(0042)=  270,
+  NRGRI(0043)=  288,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  288,
+  NRGRI(0046)=  300,
+  NRGRI(0047)=  300,
+  NRGRI(0048)=  320,
+  NRGRI(0049)=  320,
+  NRGRI(0050)=  320,
+  NRGRI(0051)=  360,
+  NRGRI(0052)=  360,
+  NRGRI(0053)=  360,
+  NRGRI(0054)=  360,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  375,
+  NRGRI(0058)=  375,
+  NRGRI(0059)=  384,
+  NRGRI(0060)=  384,
+  NRGRI(0061)=  400,
+  NRGRI(0062)=  400,
+  NRGRI(0063)=  400,
+  NRGRI(0064)=  432,
+  NRGRI(0065)=  432,
+  NRGRI(0066)=  432,
+  NRGRI(0067)=  432,
+  NRGRI(0068)=  450,
+  NRGRI(0069)=  450,
+  NRGRI(0070)=  450,
+  NRGRI(0071)=  480,
+  NRGRI(0072)=  480,
+  NRGRI(0073)=  480,
+  NRGRI(0074)=  480,
+  NRGRI(0075)=  480,
+  NRGRI(0076)=  486,
+  NRGRI(0077)=  500,
+  NRGRI(0078)=  500,
+  NRGRI(0079)=  512,
+  NRGRI(0080)=  512,
+  NRGRI(0081)=  540,
+  NRGRI(0082)=  540,
+  NRGRI(0083)=  540,
+  NRGRI(0084)=  540,
+  NRGRI(0085)=  540,
+  NRGRI(0086)=  576,
+  NRGRI(0087)=  576,
+  NRGRI(0088)=  576,
+  NRGRI(0089)=  576,
+  NRGRI(0090)=  576,
+  NRGRI(0091)=  600,
+  NRGRI(0092)=  600,
+  NRGRI(0093)=  600,
+  NRGRI(0094)=  600,
+  NRGRI(0095)=  640,
+  NRGRI(0096)=  640,
+  NRGRI(0097)=  640,
+  NRGRI(0098)=  640,
+  NRGRI(0099)=  640,
+  NRGRI(0100)=  640,
+  NRGRI(0101)=  640,
+  NRGRI(0102)=  648,
+  NRGRI(0103)=  675,
+  NRGRI(0104)=  675,
+  NRGRI(0105)=  675,
+  NRGRI(0106)=  675,
+  NRGRI(0107)=  675,
+  NRGRI(0108)=  720,
+  NRGRI(0109)=  720,
+  NRGRI(0110)=  720,
+  NRGRI(0111)=  720,
+  NRGRI(0112)=  720,
+  NRGRI(0113)=  720,
+  NRGRI(0114)=  720,
+  NRGRI(0115)=  729,
+  NRGRI(0116)=  750,
+  NRGRI(0117)=  750,
+  NRGRI(0118)=  750,
+  NRGRI(0119)=  750,
+  NRGRI(0120)=  768,
+  NRGRI(0121)=  768,
+  NRGRI(0122)=  768,
+  NRGRI(0123)=  800,
+  NRGRI(0124)=  800,
+  NRGRI(0125)=  800,
+  NRGRI(0126)=  800,
+  NRGRI(0127)=  800,
+  NRGRI(0128)=  810,
+  NRGRI(0129)=  810,
+  NRGRI(0130)=  864,
+  NRGRI(0131)=  864,
+  NRGRI(0132)=  864,
+  NRGRI(0133)=  864,
+  NRGRI(0134)=  864,
+  NRGRI(0135)=  864,
+  NRGRI(0136)=  864,
+  NRGRI(0137)=  864,
+  NRGRI(0138)=  864,
+  NRGRI(0139)=  900,
+  NRGRI(0140)=  900,
+  NRGRI(0141)=  900,
+  NRGRI(0142)=  900,
+  NRGRI(0143)=  900,
+  NRGRI(0144)=  900,
+  NRGRI(0145)=  960,
+  NRGRI(0146)=  960,
+  NRGRI(0147)=  960,
+  NRGRI(0148)=  960,
+  NRGRI(0149)=  960,
+  NRGRI(0150)=  960,
+  NRGRI(0151)=  960,
+  NRGRI(0152)=  960,
+  NRGRI(0153)=  960,
+  NRGRI(0154)=  960,
+  NRGRI(0155)=  972,
+  NRGRI(0156)=  972,
+  NRGRI(0157)=  972,
+  NRGRI(0158)= 1000,
+  NRGRI(0159)= 1000,
+  NRGRI(0160)= 1000,
+  NRGRI(0161)= 1000,
+  NRGRI(0162)= 1000,
+  NRGRI(0163)= 1024,
+  NRGRI(0164)= 1024,
+  NRGRI(0165)= 1024,
+  NRGRI(0166)= 1024,
+  NRGRI(0167)= 1080,
+  NRGRI(0168)= 1080,
+  NRGRI(0169)= 1080,
+  NRGRI(0170)= 1080,
+  NRGRI(0171)= 1080,
+  NRGRI(0172)= 1080,
+  NRGRI(0173)= 1080,
+  NRGRI(0174)= 1080,
+  NRGRI(0175)= 1080,
+  NRGRI(0176)= 1125,
+  NRGRI(0177)= 1125,
+  NRGRI(0178)= 1125,
+  NRGRI(0179)= 1125,
+  NRGRI(0180)= 1125,
+  NRGRI(0181)= 1125,
+  NRGRI(0182)= 1125,
+  NRGRI(0183)= 1125,
+  NRGRI(0184)= 1152,
+  NRGRI(0185)= 1152,
+  NRGRI(0186)= 1152,
+  NRGRI(0187)= 1152,
+  NRGRI(0188)= 1152,
+  NRGRI(0189)= 1200,
+  NRGRI(0190)= 1200,
+  NRGRI(0191)= 1200,
+  NRGRI(0192)= 1200,
+  NRGRI(0193)= 1200,
+  NRGRI(0194)= 1200,
+  NRGRI(0195)= 1200,
+  NRGRI(0196)= 1200,
+  NRGRI(0197)= 1200,
+  NRGRI(0198)= 1215,
+  NRGRI(0199)= 1215,
+  NRGRI(0200)= 1215,
+  NRGRI(0201)= 1280,
+  NRGRI(0202)= 1280,
+  NRGRI(0203)= 1280,
+  NRGRI(0204)= 1280,
+  NRGRI(0205)= 1280,
+  NRGRI(0206)= 1280,
+  NRGRI(0207)= 1280,
+  NRGRI(0208)= 1280,
+  NRGRI(0209)= 1280,
+  NRGRI(0210)= 1280,
+  NRGRI(0211)= 1280,
+  NRGRI(0212)= 1280,
+  NRGRI(0213)= 1296,
+  NRGRI(0214)= 1296,
+  NRGRI(0215)= 1296,
+  NRGRI(0216)= 1350,
+  NRGRI(0217)= 1350,
+  NRGRI(0218)= 1350,
+  NRGRI(0219)= 1350,
+  NRGRI(0220)= 1350,
+  NRGRI(0221)= 1350,
+  NRGRI(0222)= 1350,
+  NRGRI(0223)= 1350,
+  NRGRI(0224)= 1350,
+  NRGRI(0225)= 1350,
+  NRGRI(0226)= 1440,
+  NRGRI(0227)= 1440,
+  NRGRI(0228)= 1440,
+  NRGRI(0229)= 1440,
+  NRGRI(0230)= 1440,
+  NRGRI(0231)= 1440,
+  NRGRI(0232)= 1440,
+  NRGRI(0233)= 1440,
+  NRGRI(0234)= 1440,
+  NRGRI(0235)= 1440,
+  NRGRI(0236)= 1440,
+  NRGRI(0237)= 1440,
+  NRGRI(0238)= 1440,
+  NRGRI(0239)= 1440,
+  NRGRI(0240)= 1440,
+  NRGRI(0241)= 1440,
+  NRGRI(0242)= 1440,
+  NRGRI(0243)= 1440,
+  NRGRI(0244)= 1458,
+  NRGRI(0245)= 1458,
+  NRGRI(0246)= 1458,
+  NRGRI(0247)= 1458,
+  NRGRI(0248)= 1500,
+  NRGRI(0249)= 1500,
+  NRGRI(0250)= 1500,
+  NRGRI(0251)= 1500,
+  NRGRI(0252)= 1500,
+  NRGRI(0253)= 1500,
+  NRGRI(0254)= 1500,
+  NRGRI(0255)= 1500,
+  NRGRI(0256)= 1536,
+  NRGRI(0257)= 1536,
+  NRGRI(0258)= 1536,
+  NRGRI(0259)= 1536,
+  NRGRI(0260)= 1536,
+  NRGRI(0261)= 1536,
+  NRGRI(0262)= 1536,
+  NRGRI(0263)= 1536,
+  NRGRI(0264)= 1600,
+  NRGRI(0265)= 1600,
+  NRGRI(0266)= 1600,
+  NRGRI(0267)= 1600,
+  NRGRI(0268)= 1600,
+  NRGRI(0269)= 1600,
+  NRGRI(0270)= 1600,
+  NRGRI(0271)= 1600,
+  NRGRI(0272)= 1600,
+  NRGRI(0273)= 1600,
+  NRGRI(0274)= 1600,
+  NRGRI(0275)= 1600,
+  NRGRI(0276)= 1600,
+  NRGRI(0277)= 1600,
+  NRGRI(0278)= 1620,
+  NRGRI(0279)= 1620,
+  NRGRI(0280)= 1620,
+  NRGRI(0281)= 1620,
+  NRGRI(0282)= 1728,
+  NRGRI(0283)= 1728,
+  NRGRI(0284)= 1728,
+  NRGRI(0285)= 1728,
+  NRGRI(0286)= 1728,
+  NRGRI(0287)= 1728,
+  NRGRI(0288)= 1728,
+  NRGRI(0289)= 1728,
+  NRGRI(0290)= 1728,
+  NRGRI(0291)= 1728,
+  NRGRI(0292)= 1728,
+  NRGRI(0293)= 1728,
+  NRGRI(0294)= 1728,
+  NRGRI(0295)= 1728,
+  NRGRI(0296)= 1728,
+  NRGRI(0297)= 1728,
+  NRGRI(0298)= 1728,
+  NRGRI(0299)= 1728,
+  NRGRI(0300)= 1728,
+  NRGRI(0301)= 1728,
+  NRGRI(0302)= 1728,
+  NRGRI(0303)= 1728,
+  NRGRI(0304)= 1728,
+  NRGRI(0305)= 1728,
+  NRGRI(0306)= 1728,
+  NRGRI(0307)= 1800,
+  NRGRI(0308)= 1800,
+  NRGRI(0309)= 1800,
+  NRGRI(0310)= 1800,
+  NRGRI(0311)= 1800,
+  NRGRI(0312)= 1800,
+  NRGRI(0313)= 1800,
+  NRGRI(0314)= 1800,
+  NRGRI(0315)= 1800,
+  NRGRI(0316)= 1800,
+  NRGRI(0317)= 1800,
+  NRGRI(0318)= 1800,
+  NRGRI(0319)= 1800,
+  NRGRI(0320)= 1800,
+  NRGRI(0321)= 1800,
+  NRGRI(0322)= 1800,
+  NRGRI(0323)= 1800,
+  NRGRI(0324)= 1875,
+  NRGRI(0325)= 1875,
+  NRGRI(0326)= 1875,
+  NRGRI(0327)= 1875,
+  NRGRI(0328)= 1875,
+  NRGRI(0329)= 1875,
+  NRGRI(0330)= 1875,
+  NRGRI(0331)= 1875,
+  NRGRI(0332)= 1875,
+  NRGRI(0333)= 1875,
+  NRGRI(0334)= 1875,
+  NRGRI(0335)= 1875,
+  NRGRI(0336)= 1875,
+  NRGRI(0337)= 1875,
+  NRGRI(0338)= 1875,
+  NRGRI(0339)= 1875,
+  NRGRI(0340)= 1875,
+  NRGRI(0341)= 1875,
+  NRGRI(0342)= 1875,
+  NRGRI(0343)= 1920,
+  NRGRI(0344)= 1920,
+  NRGRI(0345)= 1920,
+  NRGRI(0346)= 1920,
+  NRGRI(0347)= 1920,
+  NRGRI(0348)= 1920,
+  NRGRI(0349)= 1920,
+  NRGRI(0350)= 1920,
+  NRGRI(0351)= 1920,
+  NRGRI(0352)= 1920,
+  NRGRI(0353)= 1920,
+  NRGRI(0354)= 1920,
+  NRGRI(0355)= 1920,
+  NRGRI(0356)= 1944,
+  NRGRI(0357)= 1944,
+  NRGRI(0358)= 1944,
+  NRGRI(0359)= 1944,
+  NRGRI(0360)= 1944,
+  NRGRI(0361)= 1944,
+  NRGRI(0362)= 1944,
+  NRGRI(0363)= 2000,
+  NRGRI(0364)= 2000,
+  NRGRI(0365)= 2000,
+  NRGRI(0366)= 2000,
+  NRGRI(0367)= 2000,
+  NRGRI(0368)= 2000,
+  NRGRI(0369)= 2000,
+  NRGRI(0370)= 2000,
+  NRGRI(0371)= 2000,
+  NRGRI(0372)= 2000,
+  NRGRI(0373)= 2000,
+  NRGRI(0374)= 2000,
+  NRGRI(0375)= 2000,
+  NRGRI(0376)= 2000,
+  NRGRI(0377)= 2000,
+  NRGRI(0378)= 2000,
+  NRGRI(0379)= 2000,
+  NRGRI(0380)= 2025,
+  NRGRI(0381)= 2025,
+  NRGRI(0382)= 2025,
+  NRGRI(0383)= 2025,
+  NRGRI(0384)= 2025,
+  NRGRI(0385)= 2025,
+  NRGRI(0386)= 2025,
+  NRGRI(0387)= 2025,
+  NRGRI(0388)= 2048,
+  NRGRI(0389)= 2048,
+  NRGRI(0390)= 2048,
+  NRGRI(0391)= 2048,
+  NRGRI(0392)= 2048,
+  NRGRI(0393)= 2048,
+  NRGRI(0394)= 2048,
+  NRGRI(0395)= 2160,
+  NRGRI(0396)= 2160,
+  NRGRI(0397)= 2160,
+  NRGRI(0398)= 2160,
+  NRGRI(0399)= 2160,
+  NRGRI(0400)= 2160,
+  NRGRI(0401)= 2160,
+  NRGRI(0402)= 2160,
+  NRGRI(0403)= 2160,
+  NRGRI(0404)= 2160,
+  NRGRI(0405)= 2160,
+  NRGRI(0406)= 2160,
+  NRGRI(0407)= 2160,
+  NRGRI(0408)= 2160,
+  NRGRI(0409)= 2160,
+  NRGRI(0410)= 2160,
+  NRGRI(0411)= 2160,
+  NRGRI(0412)= 2160,
+  NRGRI(0413)= 2160,
+  NRGRI(0414)= 2160,
+  NRGRI(0415)= 2160,
+  NRGRI(0416)= 2160,
+  NRGRI(0417)= 2160,
+  NRGRI(0418)= 2160,
+  NRGRI(0419)= 2160,
+  NRGRI(0420)= 2160,
+  NRGRI(0421)= 2160,
+  NRGRI(0422)= 2160,
+  NRGRI(0423)= 2160,
+  NRGRI(0424)= 2160,
+  NRGRI(0425)= 2160,
+  NRGRI(0426)= 2160,
+  NRGRI(0427)= 2160,
+  NRGRI(0428)= 2160,
+  NRGRI(0429)= 2160,
+  NRGRI(0430)= 2160,
+  NRGRI(0431)= 2160,
+  NRGRI(0432)= 2160,
+  NRGRI(0433)= 2160,
+  NRGRI(0434)= 2160,
+  NRGRI(0435)= 2160,
+  NRGRI(0436)= 2160,
+  NRGRI(0437)= 2160,
+  NRGRI(0438)= 2187,
+  NRGRI(0439)= 2187,
+  NRGRI(0440)= 2187,
+  NRGRI(0441)= 2187,
+  NRGRI(0442)= 2187,
+  NRGRI(0443)= 2187,
+  NRGRI(0444)= 2187,
+  NRGRI(0445)= 2187,
+  NRGRI(0446)= 2187,
+  NRGRI(0447)= 2187,
+  NRGRI(0448)= 2187,
+  NRGRI(0449)= 2187,
+  NRGRI(0450)= 2250,
+  NRGRI(0451)= 2250,
+  NRGRI(0452)= 2250,
+  NRGRI(0453)= 2250,
+  NRGRI(0454)= 2250,
+  NRGRI(0455)= 2250,
+  NRGRI(0456)= 2250,
+  NRGRI(0457)= 2250,
+  NRGRI(0458)= 2250,
+  NRGRI(0459)= 2250,
+  NRGRI(0460)= 2250,
+  NRGRI(0461)= 2250,
+  NRGRI(0462)= 2250,
+  NRGRI(0463)= 2250,
+  NRGRI(0464)= 2250,
+  NRGRI(0465)= 2250,
+  NRGRI(0466)= 2250,
+  NRGRI(0467)= 2250,
+  NRGRI(0468)= 2250,
+  NRGRI(0469)= 2250,
+  NRGRI(0470)= 2250,
+  NRGRI(0471)= 2250,
+  NRGRI(0472)= 2250,
+  NRGRI(0473)= 2250,
+  NRGRI(0474)= 2250,
+  NRGRI(0475)= 2250,
+  NRGRI(0476)= 2250,
+  NRGRI(0477)= 2250,
+  NRGRI(0478)= 2250,
+  NRGRI(0479)= 2250,
+  NRGRI(0480)= 2250,
+  NRGRI(0481)= 2250,
+  NRGRI(0482)= 2250,
+  NRGRI(0483)= 2250,
+  NRGRI(0484)= 2250,
+  NRGRI(0485)= 2250,
+  NRGRI(0486)= 2304,
+  NRGRI(0487)= 2304,
+  NRGRI(0488)= 2304,
+  NRGRI(0489)= 2304,
+  NRGRI(0490)= 2304,
+  NRGRI(0491)= 2304,
+  NRGRI(0492)= 2304,
+  NRGRI(0493)= 2304,
+  NRGRI(0494)= 2304,
+  NRGRI(0495)= 2304,
+  NRGRI(0496)= 2304,
+  NRGRI(0497)= 2304,
+  NRGRI(0498)= 2304,
+  NRGRI(0499)= 2304,
+  NRGRI(0500)= 2304,
+  NRGRI(0501)= 2304,
+  NRGRI(0502)= 2304,
+  NRGRI(0503)= 2304,
+  NRGRI(0504)= 2304,
+  NRGRI(0505)= 2304,
+  NRGRI(0506)= 2304,
+  NRGRI(0507)= 2304,
+  NRGRI(0508)= 2304,
+  NRGRI(0509)= 2304,
+  NRGRI(0510)= 2304,
+  NRGRI(0511)= 2304,
+  NRGRI(0512)= 2304,
+  NRGRI(0513)= 2304,
+  NRGRI(0514)= 2304,
+  NRGRI(0515)= 2304,
+  NRGRI(0516)= 2304,
+  NRGRI(0517)= 2304,
+  NRGRI(0518)= 2304,
+  NRGRI(0519)= 2304,
+  NRGRI(0520)= 2304,
+  NRGRI(0521)= 2304,
+  NRGRI(0522)= 2304,
+  NRGRI(0523)= 2304,
+  NRGRI(0524)= 2304,
+  NRGRI(0525)= 2304,
+  NRGRI(0526)= 2304,
+  NRGRI(0527)= 2304,
+  NRGRI(0528)= 2304,
+  NRGRI(0529)= 2304,
+  NRGRI(0530)= 2304,
+  NRGRI(0531)= 2304,
+  NRGRI(0532)= 2304,
+  NRGRI(0533)= 2304,
+  NRGRI(0534)= 2304,
+  NRGRI(0535)= 2304,
+  NRGRI(0536)= 2304,
+  NRGRI(0537)= 2304,
+  NRGRI(0538)= 2304,
+  NRGRI(0539)= 2304,
+  NRGRI(0540)= 2304,
+  NRGRI(0541)= 2304,
+  NRGRI(0542)= 2304,
+  NRGRI(0543)= 2304,
+  NRGRI(0544)= 2304,
+  NRGRI(0545)= 2304,
+  NRGRI(0546)= 2304,
+  NRGRI(0547)= 2304,
+  NRGRI(0548)= 2304,
+  NRGRI(0549)= 2304,
+  NRGRI(0550)= 2304,
+  NRGRI(0551)= 2304,
+  NRGRI(0552)= 2304,
+  NRGRI(0553)= 2304,
+  NRGRI(0554)= 2304,
+  NRGRI(0555)= 2304,
+  NRGRI(0556)= 2304,
+  NRGRI(0557)= 2304,
+  NRGRI(0558)= 2304,
+  NRGRI(0559)= 2304,
+  NRGRI(0560)= 2304,
+  NRGRI(0561)= 2304,
+  NRGRI(0562)= 2304,
+  NRGRI(0563)= 2304,
+  NRGRI(0564)= 2304,
+  NRGRI(0565)= 2304,
+  NRGRI(0566)= 2304,
+  NRGRI(0567)= 2304,
+  NRGRI(0568)= 2304,
+  NRGRI(0569)= 2304,
+  NRGRI(0570)= 2304,
+  NRGRI(0571)= 2304,
+  NRGRI(0572)= 2304,
+  NRGRI(0573)= 2304,
+  NRGRI(0574)= 2304,
+  NRGRI(0575)= 2304,
+  NRGRI(0576)= 2304,
+  NRGRI(0577)= 2304,
+  NRGRI(0578)= 2304,
+  NRGRI(0579)= 2304,
+  NRGRI(0580)= 2304,
+  NRGRI(0581)= 2304,
+  NRGRI(0582)= 2304,
+  NRGRI(0583)= 2304,
+  NRGRI(0584)= 2304,
+  NRGRI(0585)= 2304,
+  NRGRI(0586)= 2304,
+  NRGRI(0587)= 2304,
+  NRGRI(0588)= 2304,
+  NRGRI(0589)= 2304,
+  NRGRI(0590)= 2304,
+  NRGRI(0591)= 2304,
+  NRGRI(0592)= 2304,
+  NRGRI(0593)= 2304,
+  NRGRI(0594)= 2304,
+  NRGRI(0595)= 2304,
+  NRGRI(0596)= 2304,
+  NRGRI(0597)= 2304,
+  NRGRI(0598)= 2304,
+  NRGRI(0599)= 2304,
+  NRGRI(0600)= 2304,
+  NRGRI(0601)= 2304,
+  NRGRI(0602)= 2304,
+  NRGRI(0603)= 2304,
+  NRGRI(0604)= 2304,
+  NRGRI(0605)= 2304,
+  NRGRI(0606)= 2304,
+  NRGRI(0607)= 2304,
+  NRGRI(0608)= 2304,
+  NRGRI(0609)= 2304,
+  NRGRI(0610)= 2304,
+  NRGRI(0611)= 2304,
+  NRGRI(0612)= 2304,
+  NRGRI(0613)= 2304,
+  NRGRI(0614)= 2304,
+  NRGRI(0615)= 2304,
+  NRGRI(0616)= 2304,
+  NRGRI(0617)= 2304,
+  NRGRI(0618)= 2304,
+  NRGRI(0619)= 2304,
+  NRGRI(0620)= 2304,
+  NRGRI(0621)= 2304,
+  NRGRI(0622)= 2304,
+  NRGRI(0623)= 2304,
+  NRGRI(0624)= 2304,
+  NRGRI(0625)= 2304,
+  NRGRI(0626)= 2304,
+  NRGRI(0627)= 2304,
+  NRGRI(0628)= 2304,
+  NRGRI(0629)= 2304,
+  NRGRI(0630)= 2304,
+  NRGRI(0631)= 2304,
+  NRGRI(0632)= 2304,
+  NRGRI(0633)= 2304,
+  NRGRI(0634)= 2304,
+  NRGRI(0635)= 2304,
+  NRGRI(0636)= 2304,
+  NRGRI(0637)= 2304,
+  NRGRI(0638)= 2304,
+  NRGRI(0639)= 2304,
+  NRGRI(0640)= 2304,
+  NRGRI(0641)= 2304,
+  NRGRI(0642)= 2304,
+  NRGRI(0643)= 2304,
+  NRGRI(0644)= 2304,
+  NRGRI(0645)= 2304,
+  NRGRI(0646)= 2304,
+  NRGRI(0647)= 2304,
+  NRGRI(0648)= 2304,
+  NRGRI(0649)= 2304,
+  NRGRI(0650)= 2304,
+  NRGRI(0651)= 2304,
+  NRGRI(0652)= 2304,
+  NRGRI(0653)= 2304,
+  NRGRI(0654)= 2304,
+  NRGRI(0655)= 2304,
+  NRGRI(0656)= 2304,
+  NRGRI(0657)= 2304,
+  NRGRI(0658)= 2304,
+  NRGRI(0659)= 2304,
+  NRGRI(0660)= 2304,
+  NRGRI(0661)= 2304,
+  NRGRI(0662)= 2304,
+  NRGRI(0663)= 2304,
+  NRGRI(0664)= 2304,
+  NRGRI(0665)= 2304,
+  NRGRI(0666)= 2304,
+  NRGRI(0667)= 2304,
+  NRGRI(0668)= 2250,
+  NRGRI(0669)= 2250,
+  NRGRI(0670)= 2250,
+  NRGRI(0671)= 2250,
+  NRGRI(0672)= 2250,
+  NRGRI(0673)= 2250,
+  NRGRI(0674)= 2250,
+  NRGRI(0675)= 2250,
+  NRGRI(0676)= 2250,
+  NRGRI(0677)= 2250,
+  NRGRI(0678)= 2250,
+  NRGRI(0679)= 2250,
+  NRGRI(0680)= 2250,
+  NRGRI(0681)= 2250,
+  NRGRI(0682)= 2250,
+  NRGRI(0683)= 2250,
+  NRGRI(0684)= 2250,
+  NRGRI(0685)= 2250,
+  NRGRI(0686)= 2250,
+  NRGRI(0687)= 2250,
+  NRGRI(0688)= 2250,
+  NRGRI(0689)= 2250,
+  NRGRI(0690)= 2250,
+  NRGRI(0691)= 2250,
+  NRGRI(0692)= 2250,
+  NRGRI(0693)= 2250,
+  NRGRI(0694)= 2250,
+  NRGRI(0695)= 2250,
+  NRGRI(0696)= 2250,
+  NRGRI(0697)= 2250,
+  NRGRI(0698)= 2250,
+  NRGRI(0699)= 2250,
+  NRGRI(0700)= 2250,
+  NRGRI(0701)= 2250,
+  NRGRI(0702)= 2250,
+  NRGRI(0703)= 2250,
+  NRGRI(0704)= 2187,
+  NRGRI(0705)= 2187,
+  NRGRI(0706)= 2187,
+  NRGRI(0707)= 2187,
+  NRGRI(0708)= 2187,
+  NRGRI(0709)= 2187,
+  NRGRI(0710)= 2187,
+  NRGRI(0711)= 2187,
+  NRGRI(0712)= 2187,
+  NRGRI(0713)= 2187,
+  NRGRI(0714)= 2187,
+  NRGRI(0715)= 2187,
+  NRGRI(0716)= 2160,
+  NRGRI(0717)= 2160,
+  NRGRI(0718)= 2160,
+  NRGRI(0719)= 2160,
+  NRGRI(0720)= 2160,
+  NRGRI(0721)= 2160,
+  NRGRI(0722)= 2160,
+  NRGRI(0723)= 2160,
+  NRGRI(0724)= 2160,
+  NRGRI(0725)= 2160,
+  NRGRI(0726)= 2160,
+  NRGRI(0727)= 2160,
+  NRGRI(0728)= 2160,
+  NRGRI(0729)= 2160,
+  NRGRI(0730)= 2160,
+  NRGRI(0731)= 2160,
+  NRGRI(0732)= 2160,
+  NRGRI(0733)= 2160,
+  NRGRI(0734)= 2160,
+  NRGRI(0735)= 2160,
+  NRGRI(0736)= 2160,
+  NRGRI(0737)= 2160,
+  NRGRI(0738)= 2160,
+  NRGRI(0739)= 2160,
+  NRGRI(0740)= 2160,
+  NRGRI(0741)= 2160,
+  NRGRI(0742)= 2160,
+  NRGRI(0743)= 2160,
+  NRGRI(0744)= 2160,
+  NRGRI(0745)= 2160,
+  NRGRI(0746)= 2160,
+  NRGRI(0747)= 2160,
+  NRGRI(0748)= 2160,
+  NRGRI(0749)= 2160,
+  NRGRI(0750)= 2160,
+  NRGRI(0751)= 2160,
+  NRGRI(0752)= 2160,
+  NRGRI(0753)= 2160,
+  NRGRI(0754)= 2160,
+  NRGRI(0755)= 2160,
+  NRGRI(0756)= 2160,
+  NRGRI(0757)= 2160,
+  NRGRI(0758)= 2160,
+  NRGRI(0759)= 2048,
+  NRGRI(0760)= 2048,
+  NRGRI(0761)= 2048,
+  NRGRI(0762)= 2048,
+  NRGRI(0763)= 2048,
+  NRGRI(0764)= 2048,
+  NRGRI(0765)= 2048,
+  NRGRI(0766)= 2025,
+  NRGRI(0767)= 2025,
+  NRGRI(0768)= 2025,
+  NRGRI(0769)= 2025,
+  NRGRI(0770)= 2025,
+  NRGRI(0771)= 2025,
+  NRGRI(0772)= 2025,
+  NRGRI(0773)= 2025,
+  NRGRI(0774)= 2000,
+  NRGRI(0775)= 2000,
+  NRGRI(0776)= 2000,
+  NRGRI(0777)= 2000,
+  NRGRI(0778)= 2000,
+  NRGRI(0779)= 2000,
+  NRGRI(0780)= 2000,
+  NRGRI(0781)= 2000,
+  NRGRI(0782)= 2000,
+  NRGRI(0783)= 2000,
+  NRGRI(0784)= 2000,
+  NRGRI(0785)= 2000,
+  NRGRI(0786)= 2000,
+  NRGRI(0787)= 2000,
+  NRGRI(0788)= 2000,
+  NRGRI(0789)= 2000,
+  NRGRI(0790)= 2000,
+  NRGRI(0791)= 1944,
+  NRGRI(0792)= 1944,
+  NRGRI(0793)= 1944,
+  NRGRI(0794)= 1944,
+  NRGRI(0795)= 1944,
+  NRGRI(0796)= 1944,
+  NRGRI(0797)= 1944,
+  NRGRI(0798)= 1920,
+  NRGRI(0799)= 1920,
+  NRGRI(0800)= 1920,
+  NRGRI(0801)= 1920,
+  NRGRI(0802)= 1920,
+  NRGRI(0803)= 1920,
+  NRGRI(0804)= 1920,
+  NRGRI(0805)= 1920,
+  NRGRI(0806)= 1920,
+  NRGRI(0807)= 1920,
+  NRGRI(0808)= 1920,
+  NRGRI(0809)= 1920,
+  NRGRI(0810)= 1920,
+  NRGRI(0811)= 1875,
+  NRGRI(0812)= 1875,
+  NRGRI(0813)= 1875,
+  NRGRI(0814)= 1875,
+  NRGRI(0815)= 1875,
+  NRGRI(0816)= 1875,
+  NRGRI(0817)= 1875,
+  NRGRI(0818)= 1875,
+  NRGRI(0819)= 1875,
+  NRGRI(0820)= 1875,
+  NRGRI(0821)= 1875,
+  NRGRI(0822)= 1875,
+  NRGRI(0823)= 1875,
+  NRGRI(0824)= 1875,
+  NRGRI(0825)= 1875,
+  NRGRI(0826)= 1875,
+  NRGRI(0827)= 1875,
+  NRGRI(0828)= 1875,
+  NRGRI(0829)= 1875,
+  NRGRI(0830)= 1800,
+  NRGRI(0831)= 1800,
+  NRGRI(0832)= 1800,
+  NRGRI(0833)= 1800,
+  NRGRI(0834)= 1800,
+  NRGRI(0835)= 1800,
+  NRGRI(0836)= 1800,
+  NRGRI(0837)= 1800,
+  NRGRI(0838)= 1800,
+  NRGRI(0839)= 1800,
+  NRGRI(0840)= 1800,
+  NRGRI(0841)= 1800,
+  NRGRI(0842)= 1800,
+  NRGRI(0843)= 1800,
+  NRGRI(0844)= 1800,
+  NRGRI(0845)= 1800,
+  NRGRI(0846)= 1800,
+  NRGRI(0847)= 1728,
+  NRGRI(0848)= 1728,
+  NRGRI(0849)= 1728,
+  NRGRI(0850)= 1728,
+  NRGRI(0851)= 1728,
+  NRGRI(0852)= 1728,
+  NRGRI(0853)= 1728,
+  NRGRI(0854)= 1728,
+  NRGRI(0855)= 1728,
+  NRGRI(0856)= 1728,
+  NRGRI(0857)= 1728,
+  NRGRI(0858)= 1728,
+  NRGRI(0859)= 1728,
+  NRGRI(0860)= 1728,
+  NRGRI(0861)= 1728,
+  NRGRI(0862)= 1728,
+  NRGRI(0863)= 1728,
+  NRGRI(0864)= 1728,
+  NRGRI(0865)= 1728,
+  NRGRI(0866)= 1728,
+  NRGRI(0867)= 1728,
+  NRGRI(0868)= 1728,
+  NRGRI(0869)= 1728,
+  NRGRI(0870)= 1728,
+  NRGRI(0871)= 1728,
+  NRGRI(0872)= 1620,
+  NRGRI(0873)= 1620,
+  NRGRI(0874)= 1620,
+  NRGRI(0875)= 1620,
+  NRGRI(0876)= 1600,
+  NRGRI(0877)= 1600,
+  NRGRI(0878)= 1600,
+  NRGRI(0879)= 1600,
+  NRGRI(0880)= 1600,
+  NRGRI(0881)= 1600,
+  NRGRI(0882)= 1600,
+  NRGRI(0883)= 1600,
+  NRGRI(0884)= 1600,
+  NRGRI(0885)= 1600,
+  NRGRI(0886)= 1600,
+  NRGRI(0887)= 1600,
+  NRGRI(0888)= 1600,
+  NRGRI(0889)= 1600,
+  NRGRI(0890)= 1536,
+  NRGRI(0891)= 1536,
+  NRGRI(0892)= 1536,
+  NRGRI(0893)= 1536,
+  NRGRI(0894)= 1536,
+  NRGRI(0895)= 1536,
+  NRGRI(0896)= 1536,
+  NRGRI(0897)= 1536,
+  NRGRI(0898)= 1500,
+  NRGRI(0899)= 1500,
+  NRGRI(0900)= 1500,
+  NRGRI(0901)= 1500,
+  NRGRI(0902)= 1500,
+  NRGRI(0903)= 1500,
+  NRGRI(0904)= 1500,
+  NRGRI(0905)= 1500,
+  NRGRI(0906)= 1458,
+  NRGRI(0907)= 1458,
+  NRGRI(0908)= 1458,
+  NRGRI(0909)= 1458,
+  NRGRI(0910)= 1440,
+  NRGRI(0911)= 1440,
+  NRGRI(0912)= 1440,
+  NRGRI(0913)= 1440,
+  NRGRI(0914)= 1440,
+  NRGRI(0915)= 1440,
+  NRGRI(0916)= 1440,
+  NRGRI(0917)= 1440,
+  NRGRI(0918)= 1440,
+  NRGRI(0919)= 1440,
+  NRGRI(0920)= 1440,
+  NRGRI(0921)= 1440,
+  NRGRI(0922)= 1440,
+  NRGRI(0923)= 1440,
+  NRGRI(0924)= 1440,
+  NRGRI(0925)= 1440,
+  NRGRI(0926)= 1440,
+  NRGRI(0927)= 1440,
+  NRGRI(0928)= 1350,
+  NRGRI(0929)= 1350,
+  NRGRI(0930)= 1350,
+  NRGRI(0931)= 1350,
+  NRGRI(0932)= 1350,
+  NRGRI(0933)= 1350,
+  NRGRI(0934)= 1350,
+  NRGRI(0935)= 1350,
+  NRGRI(0936)= 1350,
+  NRGRI(0937)= 1350,
+  NRGRI(0938)= 1296,
+  NRGRI(0939)= 1296,
+  NRGRI(0940)= 1296,
+  NRGRI(0941)= 1280,
+  NRGRI(0942)= 1280,
+  NRGRI(0943)= 1280,
+  NRGRI(0944)= 1280,
+  NRGRI(0945)= 1280,
+  NRGRI(0946)= 1280,
+  NRGRI(0947)= 1280,
+  NRGRI(0948)= 1280,
+  NRGRI(0949)= 1280,
+  NRGRI(0950)= 1280,
+  NRGRI(0951)= 1280,
+  NRGRI(0952)= 1280,
+  NRGRI(0953)= 1215,
+  NRGRI(0954)= 1215,
+  NRGRI(0955)= 1215,
+  NRGRI(0956)= 1200,
+  NRGRI(0957)= 1200,
+  NRGRI(0958)= 1200,
+  NRGRI(0959)= 1200,
+  NRGRI(0960)= 1200,
+  NRGRI(0961)= 1200,
+  NRGRI(0962)= 1200,
+  NRGRI(0963)= 1200,
+  NRGRI(0964)= 1200,
+  NRGRI(0965)= 1152,
+  NRGRI(0966)= 1152,
+  NRGRI(0967)= 1152,
+  NRGRI(0968)= 1152,
+  NRGRI(0969)= 1152,
+  NRGRI(0970)= 1125,
+  NRGRI(0971)= 1125,
+  NRGRI(0972)= 1125,
+  NRGRI(0973)= 1125,
+  NRGRI(0974)= 1125,
+  NRGRI(0975)= 1125,
+  NRGRI(0976)= 1125,
+  NRGRI(0977)= 1125,
+  NRGRI(0978)= 1080,
+  NRGRI(0979)= 1080,
+  NRGRI(0980)= 1080,
+  NRGRI(0981)= 1080,
+  NRGRI(0982)= 1080,
+  NRGRI(0983)= 1080,
+  NRGRI(0984)= 1080,
+  NRGRI(0985)= 1080,
+  NRGRI(0986)= 1080,
+  NRGRI(0987)= 1024,
+  NRGRI(0988)= 1024,
+  NRGRI(0989)= 1024,
+  NRGRI(0990)= 1024,
+  NRGRI(0991)= 1000,
+  NRGRI(0992)= 1000,
+  NRGRI(0993)= 1000,
+  NRGRI(0994)= 1000,
+  NRGRI(0995)= 1000,
+  NRGRI(0996)=  972,
+  NRGRI(0997)=  972,
+  NRGRI(0998)=  972,
+  NRGRI(0999)=  960,
+  NRGRI(1000)=  960,
+  NRGRI(1001)=  960,
+  NRGRI(1002)=  960,
+  NRGRI(1003)=  960,
+  NRGRI(1004)=  960,
+  NRGRI(1005)=  960,
+  NRGRI(1006)=  960,
+  NRGRI(1007)=  960,
+  NRGRI(1008)=  960,
+  NRGRI(1009)=  900,
+  NRGRI(1010)=  900,
+  NRGRI(1011)=  900,
+  NRGRI(1012)=  900,
+  NRGRI(1013)=  900,
+  NRGRI(1014)=  900,
+  NRGRI(1015)=  864,
+  NRGRI(1016)=  864,
+  NRGRI(1017)=  864,
+  NRGRI(1018)=  864,
+  NRGRI(1019)=  864,
+  NRGRI(1020)=  864,
+  NRGRI(1021)=  864,
+  NRGRI(1022)=  864,
+  NRGRI(1023)=  864,
+  NRGRI(1024)=  810,
+  NRGRI(1025)=  810,
+  NRGRI(1026)=  800,
+  NRGRI(1027)=  800,
+  NRGRI(1028)=  800,
+  NRGRI(1029)=  800,
+  NRGRI(1030)=  800,
+  NRGRI(1031)=  768,
+  NRGRI(1032)=  768,
+  NRGRI(1033)=  768,
+  NRGRI(1034)=  750,
+  NRGRI(1035)=  750,
+  NRGRI(1036)=  750,
+  NRGRI(1037)=  750,
+  NRGRI(1038)=  729,
+  NRGRI(1039)=  720,
+  NRGRI(1040)=  720,
+  NRGRI(1041)=  720,
+  NRGRI(1042)=  720,
+  NRGRI(1043)=  720,
+  NRGRI(1044)=  720,
+  NRGRI(1045)=  720,
+  NRGRI(1046)=  675,
+  NRGRI(1047)=  675,
+  NRGRI(1048)=  675,
+  NRGRI(1049)=  675,
+  NRGRI(1050)=  675,
+  NRGRI(1051)=  648,
+  NRGRI(1052)=  640,
+  NRGRI(1053)=  640,
+  NRGRI(1054)=  640,
+  NRGRI(1055)=  640,
+  NRGRI(1056)=  640,
+  NRGRI(1057)=  640,
+  NRGRI(1058)=  640,
+  NRGRI(1059)=  600,
+  NRGRI(1060)=  600,
+  NRGRI(1061)=  600,
+  NRGRI(1062)=  600,
+  NRGRI(1063)=  576,
+  NRGRI(1064)=  576,
+  NRGRI(1065)=  576,
+  NRGRI(1066)=  576,
+  NRGRI(1067)=  576,
+  NRGRI(1068)=  540,
+  NRGRI(1069)=  540,
+  NRGRI(1070)=  540,
+  NRGRI(1071)=  540,
+  NRGRI(1072)=  540,
+  NRGRI(1073)=  512,
+  NRGRI(1074)=  512,
+  NRGRI(1075)=  500,
+  NRGRI(1076)=  500,
+  NRGRI(1077)=  486,
+  NRGRI(1078)=  480,
+  NRGRI(1079)=  480,
+  NRGRI(1080)=  480,
+  NRGRI(1081)=  480,
+  NRGRI(1082)=  480,
+  NRGRI(1083)=  450,
+  NRGRI(1084)=  450,
+  NRGRI(1085)=  450,
+  NRGRI(1086)=  432,
+  NRGRI(1087)=  432,
+  NRGRI(1088)=  432,
+  NRGRI(1089)=  432,
+  NRGRI(1090)=  400,
+  NRGRI(1091)=  400,
+  NRGRI(1092)=  400,
+  NRGRI(1093)=  384,
+  NRGRI(1094)=  384,
+  NRGRI(1095)=  375,
+  NRGRI(1096)=  375,
+  NRGRI(1097)=  360,
+  NRGRI(1098)=  360,
+  NRGRI(1099)=  360,
+  NRGRI(1100)=  360,
+  NRGRI(1101)=  360,
+  NRGRI(1102)=  360,
+  NRGRI(1103)=  320,
+  NRGRI(1104)=  320,
+  NRGRI(1105)=  320,
+  NRGRI(1106)=  300,
+  NRGRI(1107)=  300,
+  NRGRI(1108)=  288,
+  NRGRI(1109)=  288,
+  NRGRI(1110)=  288,
+  NRGRI(1111)=  270,
+  NRGRI(1112)=  270,
+  NRGRI(1113)=  256,
+  NRGRI(1114)=  250,
+  NRGRI(1115)=  243,
+  NRGRI(1116)=  240,
+  NRGRI(1117)=  240,
+  NRGRI(1118)=  225,
+  NRGRI(1119)=  225,
+  NRGRI(1120)=  216,
+  NRGRI(1121)=  216,
+  NRGRI(1122)=  200,
+  NRGRI(1123)=  192,
+  NRGRI(1124)=  192,
+  NRGRI(1125)=  180,
+  NRGRI(1126)=  180,
+  NRGRI(1127)=  180,
+  NRGRI(1128)=  160,
+  NRGRI(1129)=  160,
+  NRGRI(1130)=  150,
+  NRGRI(1131)=  144,
+  NRGRI(1132)=  135,
+  NRGRI(1133)=  125,
+  NRGRI(1134)=  120,
+  NRGRI(1135)=  120,
+  NRGRI(1136)=  108,
+  NRGRI(1137)=  100,
+  NRGRI(1138)=   96,
+  NRGRI(1139)=   96,
+  NRGRI(1140)=   90,
+  NRGRI(1141)=   81,
+  NRGRI(1142)=   75,
+  NRGRI(1143)=   72,
+  NRGRI(1144)=   72,
+  NRGRI(1145)=   60,
+  NRGRI(1146)=   60,
+  NRGRI(1147)=   50,
+  NRGRI(1148)=   45,
+  NRGRI(1149)=   40,
+  NRGRI(1150)=   32,
+  NRGRI(1151)=   25,
+  NRGRI(1152)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2127 b/odb/share/odb/rtablel_2127
new file mode 100644
index 0000000..9a4fb2b
--- /dev/null
+++ b/odb/share/odb/rtablel_2127
@@ -0,0 +1,130 @@
+ &NAMRGRI
+  NRGRI(0001)=   20,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   36,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   54,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   64,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   75,
+  NRGRI(0011)=   80,
+  NRGRI(0012)=   90,
+  NRGRI(0013)=   96,
+  NRGRI(0014)=  100,
+  NRGRI(0015)=  108,
+  NRGRI(0016)=  120,
+  NRGRI(0017)=  120,
+  NRGRI(0018)=  125,
+  NRGRI(0019)=  135,
+  NRGRI(0020)=  135,
+  NRGRI(0021)=  144,
+  NRGRI(0022)=  150,
+  NRGRI(0023)=  160,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  180,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  180,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  192,
+  NRGRI(0031)=  200,
+  NRGRI(0032)=  200,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  216,
+  NRGRI(0035)=  216,
+  NRGRI(0036)=  216,
+  NRGRI(0037)=  225,
+  NRGRI(0038)=  225,
+  NRGRI(0039)=  225,
+  NRGRI(0040)=  240,
+  NRGRI(0041)=  240,
+  NRGRI(0042)=  240,
+  NRGRI(0043)=  240,
+  NRGRI(0044)=  243,
+  NRGRI(0045)=  250,
+  NRGRI(0046)=  250,
+  NRGRI(0047)=  250,
+  NRGRI(0048)=  250,
+  NRGRI(0049)=  256,
+  NRGRI(0050)=  256,
+  NRGRI(0051)=  256,
+  NRGRI(0052)=  256,
+  NRGRI(0053)=  256,
+  NRGRI(0054)=  256,
+  NRGRI(0055)=  256,
+  NRGRI(0056)=  256,
+  NRGRI(0057)=  256,
+  NRGRI(0058)=  256,
+  NRGRI(0059)=  256,
+  NRGRI(0060)=  256,
+  NRGRI(0061)=  256,
+  NRGRI(0062)=  256,
+  NRGRI(0063)=  256,
+  NRGRI(0064)=  256,
+  NRGRI(0065)=  256,
+  NRGRI(0066)=  256,
+  NRGRI(0067)=  256,
+  NRGRI(0068)=  256,
+  NRGRI(0069)=  256,
+  NRGRI(0070)=  256,
+  NRGRI(0071)=  256,
+  NRGRI(0072)=  256,
+  NRGRI(0073)=  256,
+  NRGRI(0074)=  256,
+  NRGRI(0075)=  256,
+  NRGRI(0076)=  256,
+  NRGRI(0077)=  256,
+  NRGRI(0078)=  256,
+  NRGRI(0079)=  256,
+  NRGRI(0080)=  256,
+  NRGRI(0081)=  250,
+  NRGRI(0082)=  250,
+  NRGRI(0083)=  250,
+  NRGRI(0084)=  250,
+  NRGRI(0085)=  243,
+  NRGRI(0086)=  240,
+  NRGRI(0087)=  240,
+  NRGRI(0088)=  240,
+  NRGRI(0089)=  240,
+  NRGRI(0090)=  225,
+  NRGRI(0091)=  225,
+  NRGRI(0092)=  225,
+  NRGRI(0093)=  216,
+  NRGRI(0094)=  216,
+  NRGRI(0095)=  216,
+  NRGRI(0096)=  216,
+  NRGRI(0097)=  200,
+  NRGRI(0098)=  200,
+  NRGRI(0099)=  192,
+  NRGRI(0100)=  192,
+  NRGRI(0101)=  180,
+  NRGRI(0102)=  180,
+  NRGRI(0103)=  180,
+  NRGRI(0104)=  180,
+  NRGRI(0105)=  160,
+  NRGRI(0106)=  160,
+  NRGRI(0107)=  150,
+  NRGRI(0108)=  144,
+  NRGRI(0109)=  135,
+  NRGRI(0110)=  135,
+  NRGRI(0111)=  125,
+  NRGRI(0112)=  120,
+  NRGRI(0113)=  120,
+  NRGRI(0114)=  108,
+  NRGRI(0115)=  100,
+  NRGRI(0116)=   96,
+  NRGRI(0117)=   90,
+  NRGRI(0118)=   80,
+  NRGRI(0119)=   75,
+  NRGRI(0120)=   72,
+  NRGRI(0121)=   64,
+  NRGRI(0122)=   60,
+  NRGRI(0123)=   54,
+  NRGRI(0124)=   45,
+  NRGRI(0125)=   40,
+  NRGRI(0126)=   36,
+  NRGRI(0127)=   25,
+  NRGRI(0128)=   20,
+ /
diff --git a/odb/share/odb/rtablel_21279 b/odb/share/odb/rtablel_21279
new file mode 100644
index 0000000..77dc2f9
--- /dev/null
+++ b/odb/share/odb/rtablel_21279
@@ -0,0 +1,1282 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   75,
+  NRGRI(0012)=   81,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   90,
+  NRGRI(0015)=   96,
+  NRGRI(0016)=  100,
+  NRGRI(0017)=  108,
+  NRGRI(0018)=  120,
+  NRGRI(0019)=  120,
+  NRGRI(0020)=  125,
+  NRGRI(0021)=  135,
+  NRGRI(0022)=  144,
+  NRGRI(0023)=  150,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  160,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  180,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  192,
+  NRGRI(0031)=  200,
+  NRGRI(0032)=  216,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  216,
+  NRGRI(0035)=  225,
+  NRGRI(0036)=  240,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  243,
+  NRGRI(0039)=  250,
+  NRGRI(0040)=  256,
+  NRGRI(0041)=  270,
+  NRGRI(0042)=  270,
+  NRGRI(0043)=  288,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  288,
+  NRGRI(0046)=  300,
+  NRGRI(0047)=  300,
+  NRGRI(0048)=  320,
+  NRGRI(0049)=  320,
+  NRGRI(0050)=  320,
+  NRGRI(0051)=  360,
+  NRGRI(0052)=  360,
+  NRGRI(0053)=  360,
+  NRGRI(0054)=  360,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  375,
+  NRGRI(0058)=  375,
+  NRGRI(0059)=  384,
+  NRGRI(0060)=  384,
+  NRGRI(0061)=  400,
+  NRGRI(0062)=  400,
+  NRGRI(0063)=  400,
+  NRGRI(0064)=  432,
+  NRGRI(0065)=  432,
+  NRGRI(0066)=  432,
+  NRGRI(0067)=  432,
+  NRGRI(0068)=  450,
+  NRGRI(0069)=  450,
+  NRGRI(0070)=  450,
+  NRGRI(0071)=  480,
+  NRGRI(0072)=  480,
+  NRGRI(0073)=  480,
+  NRGRI(0074)=  480,
+  NRGRI(0075)=  480,
+  NRGRI(0076)=  486,
+  NRGRI(0077)=  500,
+  NRGRI(0078)=  500,
+  NRGRI(0079)=  512,
+  NRGRI(0080)=  512,
+  NRGRI(0081)=  540,
+  NRGRI(0082)=  540,
+  NRGRI(0083)=  540,
+  NRGRI(0084)=  540,
+  NRGRI(0085)=  540,
+  NRGRI(0086)=  576,
+  NRGRI(0087)=  576,
+  NRGRI(0088)=  576,
+  NRGRI(0089)=  576,
+  NRGRI(0090)=  576,
+  NRGRI(0091)=  600,
+  NRGRI(0092)=  600,
+  NRGRI(0093)=  600,
+  NRGRI(0094)=  600,
+  NRGRI(0095)=  640,
+  NRGRI(0096)=  640,
+  NRGRI(0097)=  640,
+  NRGRI(0098)=  640,
+  NRGRI(0099)=  640,
+  NRGRI(0100)=  640,
+  NRGRI(0101)=  640,
+  NRGRI(0102)=  648,
+  NRGRI(0103)=  675,
+  NRGRI(0104)=  675,
+  NRGRI(0105)=  675,
+  NRGRI(0106)=  675,
+  NRGRI(0107)=  720,
+  NRGRI(0108)=  720,
+  NRGRI(0109)=  720,
+  NRGRI(0110)=  720,
+  NRGRI(0111)=  720,
+  NRGRI(0112)=  720,
+  NRGRI(0113)=  720,
+  NRGRI(0114)=  720,
+  NRGRI(0115)=  729,
+  NRGRI(0116)=  750,
+  NRGRI(0117)=  750,
+  NRGRI(0118)=  750,
+  NRGRI(0119)=  750,
+  NRGRI(0120)=  768,
+  NRGRI(0121)=  768,
+  NRGRI(0122)=  768,
+  NRGRI(0123)=  800,
+  NRGRI(0124)=  800,
+  NRGRI(0125)=  800,
+  NRGRI(0126)=  800,
+  NRGRI(0127)=  800,
+  NRGRI(0128)=  810,
+  NRGRI(0129)=  810,
+  NRGRI(0130)=  864,
+  NRGRI(0131)=  864,
+  NRGRI(0132)=  864,
+  NRGRI(0133)=  864,
+  NRGRI(0134)=  864,
+  NRGRI(0135)=  864,
+  NRGRI(0136)=  864,
+  NRGRI(0137)=  864,
+  NRGRI(0138)=  900,
+  NRGRI(0139)=  900,
+  NRGRI(0140)=  900,
+  NRGRI(0141)=  900,
+  NRGRI(0142)=  900,
+  NRGRI(0143)=  900,
+  NRGRI(0144)=  960,
+  NRGRI(0145)=  960,
+  NRGRI(0146)=  960,
+  NRGRI(0147)=  960,
+  NRGRI(0148)=  960,
+  NRGRI(0149)=  960,
+  NRGRI(0150)=  960,
+  NRGRI(0151)=  960,
+  NRGRI(0152)=  960,
+  NRGRI(0153)=  960,
+  NRGRI(0154)=  960,
+  NRGRI(0155)=  972,
+  NRGRI(0156)=  972,
+  NRGRI(0157)= 1000,
+  NRGRI(0158)= 1000,
+  NRGRI(0159)= 1000,
+  NRGRI(0160)= 1000,
+  NRGRI(0161)= 1000,
+  NRGRI(0162)= 1024,
+  NRGRI(0163)= 1024,
+  NRGRI(0164)= 1024,
+  NRGRI(0165)= 1024,
+  NRGRI(0166)= 1080,
+  NRGRI(0167)= 1080,
+  NRGRI(0168)= 1080,
+  NRGRI(0169)= 1080,
+  NRGRI(0170)= 1080,
+  NRGRI(0171)= 1080,
+  NRGRI(0172)= 1080,
+  NRGRI(0173)= 1080,
+  NRGRI(0174)= 1080,
+  NRGRI(0175)= 1125,
+  NRGRI(0176)= 1125,
+  NRGRI(0177)= 1125,
+  NRGRI(0178)= 1125,
+  NRGRI(0179)= 1125,
+  NRGRI(0180)= 1125,
+  NRGRI(0181)= 1125,
+  NRGRI(0182)= 1125,
+  NRGRI(0183)= 1152,
+  NRGRI(0184)= 1152,
+  NRGRI(0185)= 1152,
+  NRGRI(0186)= 1152,
+  NRGRI(0187)= 1152,
+  NRGRI(0188)= 1200,
+  NRGRI(0189)= 1200,
+  NRGRI(0190)= 1200,
+  NRGRI(0191)= 1200,
+  NRGRI(0192)= 1200,
+  NRGRI(0193)= 1200,
+  NRGRI(0194)= 1200,
+  NRGRI(0195)= 1200,
+  NRGRI(0196)= 1215,
+  NRGRI(0197)= 1215,
+  NRGRI(0198)= 1215,
+  NRGRI(0199)= 1280,
+  NRGRI(0200)= 1280,
+  NRGRI(0201)= 1280,
+  NRGRI(0202)= 1280,
+  NRGRI(0203)= 1280,
+  NRGRI(0204)= 1280,
+  NRGRI(0205)= 1280,
+  NRGRI(0206)= 1280,
+  NRGRI(0207)= 1280,
+  NRGRI(0208)= 1280,
+  NRGRI(0209)= 1280,
+  NRGRI(0210)= 1280,
+  NRGRI(0211)= 1296,
+  NRGRI(0212)= 1296,
+  NRGRI(0213)= 1350,
+  NRGRI(0214)= 1350,
+  NRGRI(0215)= 1350,
+  NRGRI(0216)= 1350,
+  NRGRI(0217)= 1350,
+  NRGRI(0218)= 1350,
+  NRGRI(0219)= 1350,
+  NRGRI(0220)= 1350,
+  NRGRI(0221)= 1350,
+  NRGRI(0222)= 1350,
+  NRGRI(0223)= 1440,
+  NRGRI(0224)= 1440,
+  NRGRI(0225)= 1440,
+  NRGRI(0226)= 1440,
+  NRGRI(0227)= 1440,
+  NRGRI(0228)= 1440,
+  NRGRI(0229)= 1440,
+  NRGRI(0230)= 1440,
+  NRGRI(0231)= 1440,
+  NRGRI(0232)= 1440,
+  NRGRI(0233)= 1440,
+  NRGRI(0234)= 1440,
+  NRGRI(0235)= 1440,
+  NRGRI(0236)= 1440,
+  NRGRI(0237)= 1440,
+  NRGRI(0238)= 1440,
+  NRGRI(0239)= 1440,
+  NRGRI(0240)= 1458,
+  NRGRI(0241)= 1458,
+  NRGRI(0242)= 1458,
+  NRGRI(0243)= 1458,
+  NRGRI(0244)= 1500,
+  NRGRI(0245)= 1500,
+  NRGRI(0246)= 1500,
+  NRGRI(0247)= 1500,
+  NRGRI(0248)= 1500,
+  NRGRI(0249)= 1500,
+  NRGRI(0250)= 1500,
+  NRGRI(0251)= 1500,
+  NRGRI(0252)= 1536,
+  NRGRI(0253)= 1536,
+  NRGRI(0254)= 1536,
+  NRGRI(0255)= 1536,
+  NRGRI(0256)= 1536,
+  NRGRI(0257)= 1536,
+  NRGRI(0258)= 1536,
+  NRGRI(0259)= 1600,
+  NRGRI(0260)= 1600,
+  NRGRI(0261)= 1600,
+  NRGRI(0262)= 1600,
+  NRGRI(0263)= 1600,
+  NRGRI(0264)= 1600,
+  NRGRI(0265)= 1600,
+  NRGRI(0266)= 1600,
+  NRGRI(0267)= 1600,
+  NRGRI(0268)= 1600,
+  NRGRI(0269)= 1600,
+  NRGRI(0270)= 1600,
+  NRGRI(0271)= 1600,
+  NRGRI(0272)= 1620,
+  NRGRI(0273)= 1620,
+  NRGRI(0274)= 1620,
+  NRGRI(0275)= 1728,
+  NRGRI(0276)= 1728,
+  NRGRI(0277)= 1728,
+  NRGRI(0278)= 1728,
+  NRGRI(0279)= 1728,
+  NRGRI(0280)= 1728,
+  NRGRI(0281)= 1728,
+  NRGRI(0282)= 1728,
+  NRGRI(0283)= 1728,
+  NRGRI(0284)= 1728,
+  NRGRI(0285)= 1728,
+  NRGRI(0286)= 1728,
+  NRGRI(0287)= 1728,
+  NRGRI(0288)= 1728,
+  NRGRI(0289)= 1728,
+  NRGRI(0290)= 1728,
+  NRGRI(0291)= 1728,
+  NRGRI(0292)= 1728,
+  NRGRI(0293)= 1728,
+  NRGRI(0294)= 1728,
+  NRGRI(0295)= 1728,
+  NRGRI(0296)= 1728,
+  NRGRI(0297)= 1728,
+  NRGRI(0298)= 1800,
+  NRGRI(0299)= 1800,
+  NRGRI(0300)= 1800,
+  NRGRI(0301)= 1800,
+  NRGRI(0302)= 1800,
+  NRGRI(0303)= 1800,
+  NRGRI(0304)= 1800,
+  NRGRI(0305)= 1800,
+  NRGRI(0306)= 1800,
+  NRGRI(0307)= 1800,
+  NRGRI(0308)= 1800,
+  NRGRI(0309)= 1800,
+  NRGRI(0310)= 1800,
+  NRGRI(0311)= 1800,
+  NRGRI(0312)= 1800,
+  NRGRI(0313)= 1875,
+  NRGRI(0314)= 1875,
+  NRGRI(0315)= 1875,
+  NRGRI(0316)= 1875,
+  NRGRI(0317)= 1875,
+  NRGRI(0318)= 1875,
+  NRGRI(0319)= 1875,
+  NRGRI(0320)= 1875,
+  NRGRI(0321)= 1875,
+  NRGRI(0322)= 1875,
+  NRGRI(0323)= 1875,
+  NRGRI(0324)= 1875,
+  NRGRI(0325)= 1875,
+  NRGRI(0326)= 1875,
+  NRGRI(0327)= 1875,
+  NRGRI(0328)= 1875,
+  NRGRI(0329)= 1875,
+  NRGRI(0330)= 1920,
+  NRGRI(0331)= 1920,
+  NRGRI(0332)= 1920,
+  NRGRI(0333)= 1920,
+  NRGRI(0334)= 1920,
+  NRGRI(0335)= 1920,
+  NRGRI(0336)= 1920,
+  NRGRI(0337)= 1920,
+  NRGRI(0338)= 1920,
+  NRGRI(0339)= 1920,
+  NRGRI(0340)= 1920,
+  NRGRI(0341)= 1944,
+  NRGRI(0342)= 1944,
+  NRGRI(0343)= 1944,
+  NRGRI(0344)= 1944,
+  NRGRI(0345)= 1944,
+  NRGRI(0346)= 2000,
+  NRGRI(0347)= 2000,
+  NRGRI(0348)= 2000,
+  NRGRI(0349)= 2000,
+  NRGRI(0350)= 2000,
+  NRGRI(0351)= 2000,
+  NRGRI(0352)= 2000,
+  NRGRI(0353)= 2000,
+  NRGRI(0354)= 2000,
+  NRGRI(0355)= 2000,
+  NRGRI(0356)= 2000,
+  NRGRI(0357)= 2000,
+  NRGRI(0358)= 2000,
+  NRGRI(0359)= 2000,
+  NRGRI(0360)= 2025,
+  NRGRI(0361)= 2025,
+  NRGRI(0362)= 2025,
+  NRGRI(0363)= 2025,
+  NRGRI(0364)= 2025,
+  NRGRI(0365)= 2025,
+  NRGRI(0366)= 2048,
+  NRGRI(0367)= 2048,
+  NRGRI(0368)= 2048,
+  NRGRI(0369)= 2048,
+  NRGRI(0370)= 2048,
+  NRGRI(0371)= 2048,
+  NRGRI(0372)= 2048,
+  NRGRI(0373)= 2160,
+  NRGRI(0374)= 2160,
+  NRGRI(0375)= 2160,
+  NRGRI(0376)= 2160,
+  NRGRI(0377)= 2160,
+  NRGRI(0378)= 2160,
+  NRGRI(0379)= 2160,
+  NRGRI(0380)= 2160,
+  NRGRI(0381)= 2160,
+  NRGRI(0382)= 2160,
+  NRGRI(0383)= 2160,
+  NRGRI(0384)= 2160,
+  NRGRI(0385)= 2160,
+  NRGRI(0386)= 2160,
+  NRGRI(0387)= 2160,
+  NRGRI(0388)= 2160,
+  NRGRI(0389)= 2160,
+  NRGRI(0390)= 2160,
+  NRGRI(0391)= 2160,
+  NRGRI(0392)= 2160,
+  NRGRI(0393)= 2160,
+  NRGRI(0394)= 2160,
+  NRGRI(0395)= 2160,
+  NRGRI(0396)= 2160,
+  NRGRI(0397)= 2160,
+  NRGRI(0398)= 2160,
+  NRGRI(0399)= 2160,
+  NRGRI(0400)= 2160,
+  NRGRI(0401)= 2160,
+  NRGRI(0402)= 2160,
+  NRGRI(0403)= 2187,
+  NRGRI(0404)= 2187,
+  NRGRI(0405)= 2187,
+  NRGRI(0406)= 2187,
+  NRGRI(0407)= 2187,
+  NRGRI(0408)= 2187,
+  NRGRI(0409)= 2187,
+  NRGRI(0410)= 2187,
+  NRGRI(0411)= 2250,
+  NRGRI(0412)= 2250,
+  NRGRI(0413)= 2250,
+  NRGRI(0414)= 2250,
+  NRGRI(0415)= 2250,
+  NRGRI(0416)= 2250,
+  NRGRI(0417)= 2250,
+  NRGRI(0418)= 2250,
+  NRGRI(0419)= 2250,
+  NRGRI(0420)= 2250,
+  NRGRI(0421)= 2250,
+  NRGRI(0422)= 2250,
+  NRGRI(0423)= 2250,
+  NRGRI(0424)= 2250,
+  NRGRI(0425)= 2250,
+  NRGRI(0426)= 2250,
+  NRGRI(0427)= 2250,
+  NRGRI(0428)= 2250,
+  NRGRI(0429)= 2250,
+  NRGRI(0430)= 2250,
+  NRGRI(0431)= 2304,
+  NRGRI(0432)= 2304,
+  NRGRI(0433)= 2304,
+  NRGRI(0434)= 2304,
+  NRGRI(0435)= 2304,
+  NRGRI(0436)= 2304,
+  NRGRI(0437)= 2304,
+  NRGRI(0438)= 2304,
+  NRGRI(0439)= 2304,
+  NRGRI(0440)= 2304,
+  NRGRI(0441)= 2304,
+  NRGRI(0442)= 2304,
+  NRGRI(0443)= 2304,
+  NRGRI(0444)= 2304,
+  NRGRI(0445)= 2304,
+  NRGRI(0446)= 2304,
+  NRGRI(0447)= 2304,
+  NRGRI(0448)= 2304,
+  NRGRI(0449)= 2400,
+  NRGRI(0450)= 2400,
+  NRGRI(0451)= 2400,
+  NRGRI(0452)= 2400,
+  NRGRI(0453)= 2400,
+  NRGRI(0454)= 2400,
+  NRGRI(0455)= 2400,
+  NRGRI(0456)= 2400,
+  NRGRI(0457)= 2400,
+  NRGRI(0458)= 2400,
+  NRGRI(0459)= 2400,
+  NRGRI(0460)= 2400,
+  NRGRI(0461)= 2400,
+  NRGRI(0462)= 2400,
+  NRGRI(0463)= 2400,
+  NRGRI(0464)= 2400,
+  NRGRI(0465)= 2400,
+  NRGRI(0466)= 2400,
+  NRGRI(0467)= 2400,
+  NRGRI(0468)= 2400,
+  NRGRI(0469)= 2400,
+  NRGRI(0470)= 2400,
+  NRGRI(0471)= 2400,
+  NRGRI(0472)= 2400,
+  NRGRI(0473)= 2400,
+  NRGRI(0474)= 2400,
+  NRGRI(0475)= 2400,
+  NRGRI(0476)= 2400,
+  NRGRI(0477)= 2400,
+  NRGRI(0478)= 2400,
+  NRGRI(0479)= 2400,
+  NRGRI(0480)= 2400,
+  NRGRI(0481)= 2400,
+  NRGRI(0482)= 2400,
+  NRGRI(0483)= 2400,
+  NRGRI(0484)= 2400,
+  NRGRI(0485)= 2400,
+  NRGRI(0486)= 2430,
+  NRGRI(0487)= 2430,
+  NRGRI(0488)= 2430,
+  NRGRI(0489)= 2430,
+  NRGRI(0490)= 2430,
+  NRGRI(0491)= 2430,
+  NRGRI(0492)= 2430,
+  NRGRI(0493)= 2430,
+  NRGRI(0494)= 2430,
+  NRGRI(0495)= 2430,
+  NRGRI(0496)= 2430,
+  NRGRI(0497)= 2430,
+  NRGRI(0498)= 2430,
+  NRGRI(0499)= 2430,
+  NRGRI(0500)= 2500,
+  NRGRI(0501)= 2500,
+  NRGRI(0502)= 2500,
+  NRGRI(0503)= 2500,
+  NRGRI(0504)= 2500,
+  NRGRI(0505)= 2500,
+  NRGRI(0506)= 2500,
+  NRGRI(0507)= 2500,
+  NRGRI(0508)= 2500,
+  NRGRI(0509)= 2500,
+  NRGRI(0510)= 2500,
+  NRGRI(0511)= 2500,
+  NRGRI(0512)= 2500,
+  NRGRI(0513)= 2500,
+  NRGRI(0514)= 2500,
+  NRGRI(0515)= 2500,
+  NRGRI(0516)= 2500,
+  NRGRI(0517)= 2500,
+  NRGRI(0518)= 2500,
+  NRGRI(0519)= 2500,
+  NRGRI(0520)= 2500,
+  NRGRI(0521)= 2500,
+  NRGRI(0522)= 2500,
+  NRGRI(0523)= 2500,
+  NRGRI(0524)= 2500,
+  NRGRI(0525)= 2500,
+  NRGRI(0526)= 2500,
+  NRGRI(0527)= 2500,
+  NRGRI(0528)= 2500,
+  NRGRI(0529)= 2500,
+  NRGRI(0530)= 2500,
+  NRGRI(0531)= 2500,
+  NRGRI(0532)= 2500,
+  NRGRI(0533)= 2500,
+  NRGRI(0534)= 2500,
+  NRGRI(0535)= 2500,
+  NRGRI(0536)= 2500,
+  NRGRI(0537)= 2500,
+  NRGRI(0538)= 2500,
+  NRGRI(0539)= 2500,
+  NRGRI(0540)= 2500,
+  NRGRI(0541)= 2560,
+  NRGRI(0542)= 2560,
+  NRGRI(0543)= 2560,
+  NRGRI(0544)= 2560,
+  NRGRI(0545)= 2560,
+  NRGRI(0546)= 2560,
+  NRGRI(0547)= 2560,
+  NRGRI(0548)= 2560,
+  NRGRI(0549)= 2560,
+  NRGRI(0550)= 2560,
+  NRGRI(0551)= 2560,
+  NRGRI(0552)= 2560,
+  NRGRI(0553)= 2560,
+  NRGRI(0554)= 2560,
+  NRGRI(0555)= 2560,
+  NRGRI(0556)= 2560,
+  NRGRI(0557)= 2560,
+  NRGRI(0558)= 2560,
+  NRGRI(0559)= 2560,
+  NRGRI(0560)= 2560,
+  NRGRI(0561)= 2560,
+  NRGRI(0562)= 2560,
+  NRGRI(0563)= 2560,
+  NRGRI(0564)= 2560,
+  NRGRI(0565)= 2560,
+  NRGRI(0566)= 2560,
+  NRGRI(0567)= 2560,
+  NRGRI(0568)= 2560,
+  NRGRI(0569)= 2560,
+  NRGRI(0570)= 2560,
+  NRGRI(0571)= 2560,
+  NRGRI(0572)= 2560,
+  NRGRI(0573)= 2560,
+  NRGRI(0574)= 2560,
+  NRGRI(0575)= 2560,
+  NRGRI(0576)= 2560,
+  NRGRI(0577)= 2560,
+  NRGRI(0578)= 2560,
+  NRGRI(0579)= 2560,
+  NRGRI(0580)= 2560,
+  NRGRI(0581)= 2560,
+  NRGRI(0582)= 2560,
+  NRGRI(0583)= 2560,
+  NRGRI(0584)= 2560,
+  NRGRI(0585)= 2560,
+  NRGRI(0586)= 2560,
+  NRGRI(0587)= 2560,
+  NRGRI(0588)= 2560,
+  NRGRI(0589)= 2560,
+  NRGRI(0590)= 2560,
+  NRGRI(0591)= 2560,
+  NRGRI(0592)= 2560,
+  NRGRI(0593)= 2560,
+  NRGRI(0594)= 2560,
+  NRGRI(0595)= 2560,
+  NRGRI(0596)= 2560,
+  NRGRI(0597)= 2560,
+  NRGRI(0598)= 2560,
+  NRGRI(0599)= 2560,
+  NRGRI(0600)= 2560,
+  NRGRI(0601)= 2560,
+  NRGRI(0602)= 2560,
+  NRGRI(0603)= 2560,
+  NRGRI(0604)= 2560,
+  NRGRI(0605)= 2560,
+  NRGRI(0606)= 2560,
+  NRGRI(0607)= 2560,
+  NRGRI(0608)= 2560,
+  NRGRI(0609)= 2560,
+  NRGRI(0610)= 2560,
+  NRGRI(0611)= 2560,
+  NRGRI(0612)= 2560,
+  NRGRI(0613)= 2560,
+  NRGRI(0614)= 2560,
+  NRGRI(0615)= 2560,
+  NRGRI(0616)= 2560,
+  NRGRI(0617)= 2560,
+  NRGRI(0618)= 2560,
+  NRGRI(0619)= 2560,
+  NRGRI(0620)= 2560,
+  NRGRI(0621)= 2560,
+  NRGRI(0622)= 2560,
+  NRGRI(0623)= 2560,
+  NRGRI(0624)= 2560,
+  NRGRI(0625)= 2560,
+  NRGRI(0626)= 2560,
+  NRGRI(0627)= 2560,
+  NRGRI(0628)= 2560,
+  NRGRI(0629)= 2560,
+  NRGRI(0630)= 2560,
+  NRGRI(0631)= 2560,
+  NRGRI(0632)= 2560,
+  NRGRI(0633)= 2560,
+  NRGRI(0634)= 2560,
+  NRGRI(0635)= 2560,
+  NRGRI(0636)= 2560,
+  NRGRI(0637)= 2560,
+  NRGRI(0638)= 2560,
+  NRGRI(0639)= 2560,
+  NRGRI(0640)= 2560,
+  NRGRI(0641)= 2560,
+  NRGRI(0642)= 2560,
+  NRGRI(0643)= 2560,
+  NRGRI(0644)= 2560,
+  NRGRI(0645)= 2560,
+  NRGRI(0646)= 2560,
+  NRGRI(0647)= 2560,
+  NRGRI(0648)= 2560,
+  NRGRI(0649)= 2560,
+  NRGRI(0650)= 2560,
+  NRGRI(0651)= 2560,
+  NRGRI(0652)= 2560,
+  NRGRI(0653)= 2560,
+  NRGRI(0654)= 2560,
+  NRGRI(0655)= 2560,
+  NRGRI(0656)= 2560,
+  NRGRI(0657)= 2560,
+  NRGRI(0658)= 2560,
+  NRGRI(0659)= 2560,
+  NRGRI(0660)= 2560,
+  NRGRI(0661)= 2560,
+  NRGRI(0662)= 2560,
+  NRGRI(0663)= 2560,
+  NRGRI(0664)= 2560,
+  NRGRI(0665)= 2560,
+  NRGRI(0666)= 2560,
+  NRGRI(0667)= 2560,
+  NRGRI(0668)= 2560,
+  NRGRI(0669)= 2560,
+  NRGRI(0670)= 2560,
+  NRGRI(0671)= 2560,
+  NRGRI(0672)= 2560,
+  NRGRI(0673)= 2560,
+  NRGRI(0674)= 2560,
+  NRGRI(0675)= 2560,
+  NRGRI(0676)= 2560,
+  NRGRI(0677)= 2560,
+  NRGRI(0678)= 2560,
+  NRGRI(0679)= 2560,
+  NRGRI(0680)= 2560,
+  NRGRI(0681)= 2560,
+  NRGRI(0682)= 2560,
+  NRGRI(0683)= 2560,
+  NRGRI(0684)= 2560,
+  NRGRI(0685)= 2560,
+  NRGRI(0686)= 2560,
+  NRGRI(0687)= 2560,
+  NRGRI(0688)= 2560,
+  NRGRI(0689)= 2560,
+  NRGRI(0690)= 2560,
+  NRGRI(0691)= 2560,
+  NRGRI(0692)= 2560,
+  NRGRI(0693)= 2560,
+  NRGRI(0694)= 2560,
+  NRGRI(0695)= 2560,
+  NRGRI(0696)= 2560,
+  NRGRI(0697)= 2560,
+  NRGRI(0698)= 2560,
+  NRGRI(0699)= 2560,
+  NRGRI(0700)= 2560,
+  NRGRI(0701)= 2560,
+  NRGRI(0702)= 2560,
+  NRGRI(0703)= 2560,
+  NRGRI(0704)= 2560,
+  NRGRI(0705)= 2560,
+  NRGRI(0706)= 2560,
+  NRGRI(0707)= 2560,
+  NRGRI(0708)= 2560,
+  NRGRI(0709)= 2560,
+  NRGRI(0710)= 2560,
+  NRGRI(0711)= 2560,
+  NRGRI(0712)= 2560,
+  NRGRI(0713)= 2560,
+  NRGRI(0714)= 2560,
+  NRGRI(0715)= 2560,
+  NRGRI(0716)= 2560,
+  NRGRI(0717)= 2560,
+  NRGRI(0718)= 2560,
+  NRGRI(0719)= 2560,
+  NRGRI(0720)= 2560,
+  NRGRI(0721)= 2560,
+  NRGRI(0722)= 2560,
+  NRGRI(0723)= 2560,
+  NRGRI(0724)= 2560,
+  NRGRI(0725)= 2560,
+  NRGRI(0726)= 2560,
+  NRGRI(0727)= 2560,
+  NRGRI(0728)= 2560,
+  NRGRI(0729)= 2560,
+  NRGRI(0730)= 2560,
+  NRGRI(0731)= 2560,
+  NRGRI(0732)= 2560,
+  NRGRI(0733)= 2560,
+  NRGRI(0734)= 2560,
+  NRGRI(0735)= 2560,
+  NRGRI(0736)= 2560,
+  NRGRI(0737)= 2560,
+  NRGRI(0738)= 2560,
+  NRGRI(0739)= 2560,
+  NRGRI(0740)= 2560,
+  NRGRI(0741)= 2500,
+  NRGRI(0742)= 2500,
+  NRGRI(0743)= 2500,
+  NRGRI(0744)= 2500,
+  NRGRI(0745)= 2500,
+  NRGRI(0746)= 2500,
+  NRGRI(0747)= 2500,
+  NRGRI(0748)= 2500,
+  NRGRI(0749)= 2500,
+  NRGRI(0750)= 2500,
+  NRGRI(0751)= 2500,
+  NRGRI(0752)= 2500,
+  NRGRI(0753)= 2500,
+  NRGRI(0754)= 2500,
+  NRGRI(0755)= 2500,
+  NRGRI(0756)= 2500,
+  NRGRI(0757)= 2500,
+  NRGRI(0758)= 2500,
+  NRGRI(0759)= 2500,
+  NRGRI(0760)= 2500,
+  NRGRI(0761)= 2500,
+  NRGRI(0762)= 2500,
+  NRGRI(0763)= 2500,
+  NRGRI(0764)= 2500,
+  NRGRI(0765)= 2500,
+  NRGRI(0766)= 2500,
+  NRGRI(0767)= 2500,
+  NRGRI(0768)= 2500,
+  NRGRI(0769)= 2500,
+  NRGRI(0770)= 2500,
+  NRGRI(0771)= 2500,
+  NRGRI(0772)= 2500,
+  NRGRI(0773)= 2500,
+  NRGRI(0774)= 2500,
+  NRGRI(0775)= 2500,
+  NRGRI(0776)= 2500,
+  NRGRI(0777)= 2500,
+  NRGRI(0778)= 2500,
+  NRGRI(0779)= 2500,
+  NRGRI(0780)= 2500,
+  NRGRI(0781)= 2500,
+  NRGRI(0782)= 2430,
+  NRGRI(0783)= 2430,
+  NRGRI(0784)= 2430,
+  NRGRI(0785)= 2430,
+  NRGRI(0786)= 2430,
+  NRGRI(0787)= 2430,
+  NRGRI(0788)= 2430,
+  NRGRI(0789)= 2430,
+  NRGRI(0790)= 2430,
+  NRGRI(0791)= 2430,
+  NRGRI(0792)= 2430,
+  NRGRI(0793)= 2430,
+  NRGRI(0794)= 2430,
+  NRGRI(0795)= 2430,
+  NRGRI(0796)= 2400,
+  NRGRI(0797)= 2400,
+  NRGRI(0798)= 2400,
+  NRGRI(0799)= 2400,
+  NRGRI(0800)= 2400,
+  NRGRI(0801)= 2400,
+  NRGRI(0802)= 2400,
+  NRGRI(0803)= 2400,
+  NRGRI(0804)= 2400,
+  NRGRI(0805)= 2400,
+  NRGRI(0806)= 2400,
+  NRGRI(0807)= 2400,
+  NRGRI(0808)= 2400,
+  NRGRI(0809)= 2400,
+  NRGRI(0810)= 2400,
+  NRGRI(0811)= 2400,
+  NRGRI(0812)= 2400,
+  NRGRI(0813)= 2400,
+  NRGRI(0814)= 2400,
+  NRGRI(0815)= 2400,
+  NRGRI(0816)= 2400,
+  NRGRI(0817)= 2400,
+  NRGRI(0818)= 2400,
+  NRGRI(0819)= 2400,
+  NRGRI(0820)= 2400,
+  NRGRI(0821)= 2400,
+  NRGRI(0822)= 2400,
+  NRGRI(0823)= 2400,
+  NRGRI(0824)= 2400,
+  NRGRI(0825)= 2400,
+  NRGRI(0826)= 2400,
+  NRGRI(0827)= 2400,
+  NRGRI(0828)= 2400,
+  NRGRI(0829)= 2400,
+  NRGRI(0830)= 2400,
+  NRGRI(0831)= 2400,
+  NRGRI(0832)= 2400,
+  NRGRI(0833)= 2304,
+  NRGRI(0834)= 2304,
+  NRGRI(0835)= 2304,
+  NRGRI(0836)= 2304,
+  NRGRI(0837)= 2304,
+  NRGRI(0838)= 2304,
+  NRGRI(0839)= 2304,
+  NRGRI(0840)= 2304,
+  NRGRI(0841)= 2304,
+  NRGRI(0842)= 2304,
+  NRGRI(0843)= 2304,
+  NRGRI(0844)= 2304,
+  NRGRI(0845)= 2304,
+  NRGRI(0846)= 2304,
+  NRGRI(0847)= 2304,
+  NRGRI(0848)= 2304,
+  NRGRI(0849)= 2304,
+  NRGRI(0850)= 2304,
+  NRGRI(0851)= 2250,
+  NRGRI(0852)= 2250,
+  NRGRI(0853)= 2250,
+  NRGRI(0854)= 2250,
+  NRGRI(0855)= 2250,
+  NRGRI(0856)= 2250,
+  NRGRI(0857)= 2250,
+  NRGRI(0858)= 2250,
+  NRGRI(0859)= 2250,
+  NRGRI(0860)= 2250,
+  NRGRI(0861)= 2250,
+  NRGRI(0862)= 2250,
+  NRGRI(0863)= 2250,
+  NRGRI(0864)= 2250,
+  NRGRI(0865)= 2250,
+  NRGRI(0866)= 2250,
+  NRGRI(0867)= 2250,
+  NRGRI(0868)= 2250,
+  NRGRI(0869)= 2250,
+  NRGRI(0870)= 2250,
+  NRGRI(0871)= 2187,
+  NRGRI(0872)= 2187,
+  NRGRI(0873)= 2187,
+  NRGRI(0874)= 2187,
+  NRGRI(0875)= 2187,
+  NRGRI(0876)= 2187,
+  NRGRI(0877)= 2187,
+  NRGRI(0878)= 2187,
+  NRGRI(0879)= 2160,
+  NRGRI(0880)= 2160,
+  NRGRI(0881)= 2160,
+  NRGRI(0882)= 2160,
+  NRGRI(0883)= 2160,
+  NRGRI(0884)= 2160,
+  NRGRI(0885)= 2160,
+  NRGRI(0886)= 2160,
+  NRGRI(0887)= 2160,
+  NRGRI(0888)= 2160,
+  NRGRI(0889)= 2160,
+  NRGRI(0890)= 2160,
+  NRGRI(0891)= 2160,
+  NRGRI(0892)= 2160,
+  NRGRI(0893)= 2160,
+  NRGRI(0894)= 2160,
+  NRGRI(0895)= 2160,
+  NRGRI(0896)= 2160,
+  NRGRI(0897)= 2160,
+  NRGRI(0898)= 2160,
+  NRGRI(0899)= 2160,
+  NRGRI(0900)= 2160,
+  NRGRI(0901)= 2160,
+  NRGRI(0902)= 2160,
+  NRGRI(0903)= 2160,
+  NRGRI(0904)= 2160,
+  NRGRI(0905)= 2160,
+  NRGRI(0906)= 2160,
+  NRGRI(0907)= 2160,
+  NRGRI(0908)= 2160,
+  NRGRI(0909)= 2048,
+  NRGRI(0910)= 2048,
+  NRGRI(0911)= 2048,
+  NRGRI(0912)= 2048,
+  NRGRI(0913)= 2048,
+  NRGRI(0914)= 2048,
+  NRGRI(0915)= 2048,
+  NRGRI(0916)= 2025,
+  NRGRI(0917)= 2025,
+  NRGRI(0918)= 2025,
+  NRGRI(0919)= 2025,
+  NRGRI(0920)= 2025,
+  NRGRI(0921)= 2025,
+  NRGRI(0922)= 2000,
+  NRGRI(0923)= 2000,
+  NRGRI(0924)= 2000,
+  NRGRI(0925)= 2000,
+  NRGRI(0926)= 2000,
+  NRGRI(0927)= 2000,
+  NRGRI(0928)= 2000,
+  NRGRI(0929)= 2000,
+  NRGRI(0930)= 2000,
+  NRGRI(0931)= 2000,
+  NRGRI(0932)= 2000,
+  NRGRI(0933)= 2000,
+  NRGRI(0934)= 2000,
+  NRGRI(0935)= 2000,
+  NRGRI(0936)= 1944,
+  NRGRI(0937)= 1944,
+  NRGRI(0938)= 1944,
+  NRGRI(0939)= 1944,
+  NRGRI(0940)= 1944,
+  NRGRI(0941)= 1920,
+  NRGRI(0942)= 1920,
+  NRGRI(0943)= 1920,
+  NRGRI(0944)= 1920,
+  NRGRI(0945)= 1920,
+  NRGRI(0946)= 1920,
+  NRGRI(0947)= 1920,
+  NRGRI(0948)= 1920,
+  NRGRI(0949)= 1920,
+  NRGRI(0950)= 1920,
+  NRGRI(0951)= 1920,
+  NRGRI(0952)= 1875,
+  NRGRI(0953)= 1875,
+  NRGRI(0954)= 1875,
+  NRGRI(0955)= 1875,
+  NRGRI(0956)= 1875,
+  NRGRI(0957)= 1875,
+  NRGRI(0958)= 1875,
+  NRGRI(0959)= 1875,
+  NRGRI(0960)= 1875,
+  NRGRI(0961)= 1875,
+  NRGRI(0962)= 1875,
+  NRGRI(0963)= 1875,
+  NRGRI(0964)= 1875,
+  NRGRI(0965)= 1875,
+  NRGRI(0966)= 1875,
+  NRGRI(0967)= 1875,
+  NRGRI(0968)= 1875,
+  NRGRI(0969)= 1800,
+  NRGRI(0970)= 1800,
+  NRGRI(0971)= 1800,
+  NRGRI(0972)= 1800,
+  NRGRI(0973)= 1800,
+  NRGRI(0974)= 1800,
+  NRGRI(0975)= 1800,
+  NRGRI(0976)= 1800,
+  NRGRI(0977)= 1800,
+  NRGRI(0978)= 1800,
+  NRGRI(0979)= 1800,
+  NRGRI(0980)= 1800,
+  NRGRI(0981)= 1800,
+  NRGRI(0982)= 1800,
+  NRGRI(0983)= 1800,
+  NRGRI(0984)= 1728,
+  NRGRI(0985)= 1728,
+  NRGRI(0986)= 1728,
+  NRGRI(0987)= 1728,
+  NRGRI(0988)= 1728,
+  NRGRI(0989)= 1728,
+  NRGRI(0990)= 1728,
+  NRGRI(0991)= 1728,
+  NRGRI(0992)= 1728,
+  NRGRI(0993)= 1728,
+  NRGRI(0994)= 1728,
+  NRGRI(0995)= 1728,
+  NRGRI(0996)= 1728,
+  NRGRI(0997)= 1728,
+  NRGRI(0998)= 1728,
+  NRGRI(0999)= 1728,
+  NRGRI(1000)= 1728,
+  NRGRI(1001)= 1728,
+  NRGRI(1002)= 1728,
+  NRGRI(1003)= 1728,
+  NRGRI(1004)= 1728,
+  NRGRI(1005)= 1728,
+  NRGRI(1006)= 1728,
+  NRGRI(1007)= 1620,
+  NRGRI(1008)= 1620,
+  NRGRI(1009)= 1620,
+  NRGRI(1010)= 1600,
+  NRGRI(1011)= 1600,
+  NRGRI(1012)= 1600,
+  NRGRI(1013)= 1600,
+  NRGRI(1014)= 1600,
+  NRGRI(1015)= 1600,
+  NRGRI(1016)= 1600,
+  NRGRI(1017)= 1600,
+  NRGRI(1018)= 1600,
+  NRGRI(1019)= 1600,
+  NRGRI(1020)= 1600,
+  NRGRI(1021)= 1600,
+  NRGRI(1022)= 1600,
+  NRGRI(1023)= 1536,
+  NRGRI(1024)= 1536,
+  NRGRI(1025)= 1536,
+  NRGRI(1026)= 1536,
+  NRGRI(1027)= 1536,
+  NRGRI(1028)= 1536,
+  NRGRI(1029)= 1536,
+  NRGRI(1030)= 1500,
+  NRGRI(1031)= 1500,
+  NRGRI(1032)= 1500,
+  NRGRI(1033)= 1500,
+  NRGRI(1034)= 1500,
+  NRGRI(1035)= 1500,
+  NRGRI(1036)= 1500,
+  NRGRI(1037)= 1500,
+  NRGRI(1038)= 1458,
+  NRGRI(1039)= 1458,
+  NRGRI(1040)= 1458,
+  NRGRI(1041)= 1458,
+  NRGRI(1042)= 1440,
+  NRGRI(1043)= 1440,
+  NRGRI(1044)= 1440,
+  NRGRI(1045)= 1440,
+  NRGRI(1046)= 1440,
+  NRGRI(1047)= 1440,
+  NRGRI(1048)= 1440,
+  NRGRI(1049)= 1440,
+  NRGRI(1050)= 1440,
+  NRGRI(1051)= 1440,
+  NRGRI(1052)= 1440,
+  NRGRI(1053)= 1440,
+  NRGRI(1054)= 1440,
+  NRGRI(1055)= 1440,
+  NRGRI(1056)= 1440,
+  NRGRI(1057)= 1440,
+  NRGRI(1058)= 1440,
+  NRGRI(1059)= 1350,
+  NRGRI(1060)= 1350,
+  NRGRI(1061)= 1350,
+  NRGRI(1062)= 1350,
+  NRGRI(1063)= 1350,
+  NRGRI(1064)= 1350,
+  NRGRI(1065)= 1350,
+  NRGRI(1066)= 1350,
+  NRGRI(1067)= 1350,
+  NRGRI(1068)= 1350,
+  NRGRI(1069)= 1296,
+  NRGRI(1070)= 1296,
+  NRGRI(1071)= 1280,
+  NRGRI(1072)= 1280,
+  NRGRI(1073)= 1280,
+  NRGRI(1074)= 1280,
+  NRGRI(1075)= 1280,
+  NRGRI(1076)= 1280,
+  NRGRI(1077)= 1280,
+  NRGRI(1078)= 1280,
+  NRGRI(1079)= 1280,
+  NRGRI(1080)= 1280,
+  NRGRI(1081)= 1280,
+  NRGRI(1082)= 1280,
+  NRGRI(1083)= 1215,
+  NRGRI(1084)= 1215,
+  NRGRI(1085)= 1215,
+  NRGRI(1086)= 1200,
+  NRGRI(1087)= 1200,
+  NRGRI(1088)= 1200,
+  NRGRI(1089)= 1200,
+  NRGRI(1090)= 1200,
+  NRGRI(1091)= 1200,
+  NRGRI(1092)= 1200,
+  NRGRI(1093)= 1200,
+  NRGRI(1094)= 1152,
+  NRGRI(1095)= 1152,
+  NRGRI(1096)= 1152,
+  NRGRI(1097)= 1152,
+  NRGRI(1098)= 1152,
+  NRGRI(1099)= 1125,
+  NRGRI(1100)= 1125,
+  NRGRI(1101)= 1125,
+  NRGRI(1102)= 1125,
+  NRGRI(1103)= 1125,
+  NRGRI(1104)= 1125,
+  NRGRI(1105)= 1125,
+  NRGRI(1106)= 1125,
+  NRGRI(1107)= 1080,
+  NRGRI(1108)= 1080,
+  NRGRI(1109)= 1080,
+  NRGRI(1110)= 1080,
+  NRGRI(1111)= 1080,
+  NRGRI(1112)= 1080,
+  NRGRI(1113)= 1080,
+  NRGRI(1114)= 1080,
+  NRGRI(1115)= 1080,
+  NRGRI(1116)= 1024,
+  NRGRI(1117)= 1024,
+  NRGRI(1118)= 1024,
+  NRGRI(1119)= 1024,
+  NRGRI(1120)= 1000,
+  NRGRI(1121)= 1000,
+  NRGRI(1122)= 1000,
+  NRGRI(1123)= 1000,
+  NRGRI(1124)= 1000,
+  NRGRI(1125)=  972,
+  NRGRI(1126)=  972,
+  NRGRI(1127)=  960,
+  NRGRI(1128)=  960,
+  NRGRI(1129)=  960,
+  NRGRI(1130)=  960,
+  NRGRI(1131)=  960,
+  NRGRI(1132)=  960,
+  NRGRI(1133)=  960,
+  NRGRI(1134)=  960,
+  NRGRI(1135)=  960,
+  NRGRI(1136)=  960,
+  NRGRI(1137)=  960,
+  NRGRI(1138)=  900,
+  NRGRI(1139)=  900,
+  NRGRI(1140)=  900,
+  NRGRI(1141)=  900,
+  NRGRI(1142)=  900,
+  NRGRI(1143)=  900,
+  NRGRI(1144)=  864,
+  NRGRI(1145)=  864,
+  NRGRI(1146)=  864,
+  NRGRI(1147)=  864,
+  NRGRI(1148)=  864,
+  NRGRI(1149)=  864,
+  NRGRI(1150)=  864,
+  NRGRI(1151)=  864,
+  NRGRI(1152)=  810,
+  NRGRI(1153)=  810,
+  NRGRI(1154)=  800,
+  NRGRI(1155)=  800,
+  NRGRI(1156)=  800,
+  NRGRI(1157)=  800,
+  NRGRI(1158)=  800,
+  NRGRI(1159)=  768,
+  NRGRI(1160)=  768,
+  NRGRI(1161)=  768,
+  NRGRI(1162)=  750,
+  NRGRI(1163)=  750,
+  NRGRI(1164)=  750,
+  NRGRI(1165)=  750,
+  NRGRI(1166)=  729,
+  NRGRI(1167)=  720,
+  NRGRI(1168)=  720,
+  NRGRI(1169)=  720,
+  NRGRI(1170)=  720,
+  NRGRI(1171)=  720,
+  NRGRI(1172)=  720,
+  NRGRI(1173)=  720,
+  NRGRI(1174)=  720,
+  NRGRI(1175)=  675,
+  NRGRI(1176)=  675,
+  NRGRI(1177)=  675,
+  NRGRI(1178)=  675,
+  NRGRI(1179)=  648,
+  NRGRI(1180)=  640,
+  NRGRI(1181)=  640,
+  NRGRI(1182)=  640,
+  NRGRI(1183)=  640,
+  NRGRI(1184)=  640,
+  NRGRI(1185)=  640,
+  NRGRI(1186)=  640,
+  NRGRI(1187)=  600,
+  NRGRI(1188)=  600,
+  NRGRI(1189)=  600,
+  NRGRI(1190)=  600,
+  NRGRI(1191)=  576,
+  NRGRI(1192)=  576,
+  NRGRI(1193)=  576,
+  NRGRI(1194)=  576,
+  NRGRI(1195)=  576,
+  NRGRI(1196)=  540,
+  NRGRI(1197)=  540,
+  NRGRI(1198)=  540,
+  NRGRI(1199)=  540,
+  NRGRI(1200)=  540,
+  NRGRI(1201)=  512,
+  NRGRI(1202)=  512,
+  NRGRI(1203)=  500,
+  NRGRI(1204)=  500,
+  NRGRI(1205)=  486,
+  NRGRI(1206)=  480,
+  NRGRI(1207)=  480,
+  NRGRI(1208)=  480,
+  NRGRI(1209)=  480,
+  NRGRI(1210)=  480,
+  NRGRI(1211)=  450,
+  NRGRI(1212)=  450,
+  NRGRI(1213)=  450,
+  NRGRI(1214)=  432,
+  NRGRI(1215)=  432,
+  NRGRI(1216)=  432,
+  NRGRI(1217)=  432,
+  NRGRI(1218)=  400,
+  NRGRI(1219)=  400,
+  NRGRI(1220)=  400,
+  NRGRI(1221)=  384,
+  NRGRI(1222)=  384,
+  NRGRI(1223)=  375,
+  NRGRI(1224)=  375,
+  NRGRI(1225)=  360,
+  NRGRI(1226)=  360,
+  NRGRI(1227)=  360,
+  NRGRI(1228)=  360,
+  NRGRI(1229)=  360,
+  NRGRI(1230)=  360,
+  NRGRI(1231)=  320,
+  NRGRI(1232)=  320,
+  NRGRI(1233)=  320,
+  NRGRI(1234)=  300,
+  NRGRI(1235)=  300,
+  NRGRI(1236)=  288,
+  NRGRI(1237)=  288,
+  NRGRI(1238)=  288,
+  NRGRI(1239)=  270,
+  NRGRI(1240)=  270,
+  NRGRI(1241)=  256,
+  NRGRI(1242)=  250,
+  NRGRI(1243)=  243,
+  NRGRI(1244)=  240,
+  NRGRI(1245)=  240,
+  NRGRI(1246)=  225,
+  NRGRI(1247)=  216,
+  NRGRI(1248)=  216,
+  NRGRI(1249)=  216,
+  NRGRI(1250)=  200,
+  NRGRI(1251)=  192,
+  NRGRI(1252)=  192,
+  NRGRI(1253)=  180,
+  NRGRI(1254)=  180,
+  NRGRI(1255)=  180,
+  NRGRI(1256)=  160,
+  NRGRI(1257)=  160,
+  NRGRI(1258)=  150,
+  NRGRI(1259)=  144,
+  NRGRI(1260)=  135,
+  NRGRI(1261)=  125,
+  NRGRI(1262)=  120,
+  NRGRI(1263)=  120,
+  NRGRI(1264)=  108,
+  NRGRI(1265)=  100,
+  NRGRI(1266)=   96,
+  NRGRI(1267)=   90,
+  NRGRI(1268)=   90,
+  NRGRI(1269)=   81,
+  NRGRI(1270)=   75,
+  NRGRI(1271)=   72,
+  NRGRI(1272)=   72,
+  NRGRI(1273)=   60,
+  NRGRI(1274)=   60,
+  NRGRI(1275)=   50,
+  NRGRI(1276)=   45,
+  NRGRI(1277)=   40,
+  NRGRI(1278)=   32,
+  NRGRI(1279)=   25,
+  NRGRI(1280)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2159 b/odb/share/odb/rtablel_2159
new file mode 100644
index 0000000..e13ea68
--- /dev/null
+++ b/odb/share/odb/rtablel_2159
@@ -0,0 +1,162 @@
+&NAMRGRI
+NRGRI(1)=18,
+NRGRI(2)=25,
+NRGRI(3)=36,
+NRGRI(4)=40,
+NRGRI(5)=45,
+NRGRI(6)=54,
+NRGRI(7)=60,
+NRGRI(8)=64,
+NRGRI(9)=72,
+NRGRI(10)=72,
+NRGRI(11)=80,
+NRGRI(12)=90,
+NRGRI(13)=96,
+NRGRI(14)=100,
+NRGRI(15)=108,
+NRGRI(16)=120,
+NRGRI(17)=120,
+NRGRI(18)=128,
+NRGRI(19)=135,
+NRGRI(20)=144,
+NRGRI(21)=144,
+NRGRI(22)=150,
+NRGRI(23)=160,
+NRGRI(24)=160,
+NRGRI(25)=180,
+NRGRI(26)=180,
+NRGRI(27)=180,
+NRGRI(28)=192,
+NRGRI(29)=192,
+NRGRI(30)=200,
+NRGRI(31)=200,
+NRGRI(32)=216,
+NRGRI(33)=216,
+NRGRI(34)=216,
+NRGRI(35)=225,
+NRGRI(36)=225,
+NRGRI(37)=240,
+NRGRI(38)=240,
+NRGRI(39)=240,
+NRGRI(40)=256,
+NRGRI(41)=256,
+NRGRI(42)=256,
+NRGRI(43)=256,
+NRGRI(44)=288,
+NRGRI(45)=288,
+NRGRI(46)=288,
+NRGRI(47)=288,
+NRGRI(48)=288,
+NRGRI(49)=288,
+NRGRI(50)=288,
+NRGRI(51)=288,
+NRGRI(52)=288,
+NRGRI(53)=300,
+NRGRI(54)=300,
+NRGRI(55)=300,
+NRGRI(56)=300,
+NRGRI(57)=320,
+NRGRI(58)=320,
+NRGRI(59)=320,
+NRGRI(60)=320,
+NRGRI(61)=320,
+NRGRI(62)=320,
+NRGRI(63)=320,
+NRGRI(64)=320,
+NRGRI(65)=320,
+NRGRI(66)=320,
+NRGRI(67)=320,
+NRGRI(68)=320,
+NRGRI(69)=320,
+NRGRI(70)=320,
+NRGRI(71)=320,
+NRGRI(72)=320,
+NRGRI(73)=320,
+NRGRI(74)=320,
+NRGRI(75)=320,
+NRGRI(76)=320,
+NRGRI(77)=320,
+NRGRI(78)=320,
+NRGRI(79)=320,
+NRGRI(80)=320,
+NRGRI(81)=320,
+NRGRI(82)=320,
+NRGRI(83)=320,
+NRGRI(84)=320,
+NRGRI(85)=320,
+NRGRI(86)=320,
+NRGRI(87)=320,
+NRGRI(88)=320,
+NRGRI(89)=320,
+NRGRI(90)=320,
+NRGRI(91)=320,
+NRGRI(92)=320,
+NRGRI(93)=320,
+NRGRI(94)=320,
+NRGRI(95)=320,
+NRGRI(96)=320,
+NRGRI(97)=320,
+NRGRI(98)=320,
+NRGRI(99)=320,
+NRGRI(100)=320,
+NRGRI(101)=320,
+NRGRI(102)=320,
+NRGRI(103)=320,
+NRGRI(104)=320,
+NRGRI(105)=300,
+NRGRI(106)=300,
+NRGRI(107)=300,
+NRGRI(108)=300,
+NRGRI(109)=288,
+NRGRI(110)=288,
+NRGRI(111)=288,
+NRGRI(112)=288,
+NRGRI(113)=288,
+NRGRI(114)=288,
+NRGRI(115)=288,
+NRGRI(116)=288,
+NRGRI(117)=288,
+NRGRI(118)=256,
+NRGRI(119)=256,
+NRGRI(120)=256,
+NRGRI(121)=256,
+NRGRI(122)=240,
+NRGRI(123)=240,
+NRGRI(124)=240,
+NRGRI(125)=225,
+NRGRI(126)=225,
+NRGRI(127)=216,
+NRGRI(128)=216,
+NRGRI(129)=216,
+NRGRI(130)=200,
+NRGRI(131)=200,
+NRGRI(132)=192,
+NRGRI(133)=192,
+NRGRI(134)=180,
+NRGRI(135)=180,
+NRGRI(136)=180,
+NRGRI(137)=160,
+NRGRI(138)=160,
+NRGRI(139)=150,
+NRGRI(140)=144,
+NRGRI(141)=144,
+NRGRI(142)=135,
+NRGRI(143)=128,
+NRGRI(144)=120,
+NRGRI(145)=120,
+NRGRI(146)=108,
+NRGRI(147)=100,
+NRGRI(148)=96,
+NRGRI(149)=90,
+NRGRI(150)=80,
+NRGRI(151)=72,
+NRGRI(152)=72,
+NRGRI(153)=64,
+NRGRI(154)=60,
+NRGRI(155)=54,
+NRGRI(156)=45,
+NRGRI(157)=40,
+NRGRI(158)=36,
+NRGRI(159)=25,
+NRGRI(160)=18,
+/
diff --git a/odb/share/odb/rtablel_22047 b/odb/share/odb/rtablel_22047
new file mode 100644
index 0000000..98abc5b
--- /dev/null
+++ b/odb/share/odb/rtablel_22047
@@ -0,0 +1,2050 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   54,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   75,
+  NRGRI(0012)=   80,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   90,
+  NRGRI(0015)=   96,
+  NRGRI(0016)=  100,
+  NRGRI(0017)=  108,
+  NRGRI(0018)=  120,
+  NRGRI(0019)=  120,
+  NRGRI(0020)=  120,
+  NRGRI(0021)=  125,
+  NRGRI(0022)=  135,
+  NRGRI(0023)=  144,
+  NRGRI(0024)=  150,
+  NRGRI(0025)=  160,
+  NRGRI(0026)=  160,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  180,
+  NRGRI(0029)=  180,
+  NRGRI(0030)=  192,
+  NRGRI(0031)=  192,
+  NRGRI(0032)=  200,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  216,
+  NRGRI(0035)=  225,
+  NRGRI(0036)=  225,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  240,
+  NRGRI(0039)=  243,
+  NRGRI(0040)=  250,
+  NRGRI(0041)=  256,
+  NRGRI(0042)=  270,
+  NRGRI(0043)=  270,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  288,
+  NRGRI(0046)=  288,
+  NRGRI(0047)=  300,
+  NRGRI(0048)=  300,
+  NRGRI(0049)=  320,
+  NRGRI(0050)=  320,
+  NRGRI(0051)=  320,
+  NRGRI(0052)=  360,
+  NRGRI(0053)=  360,
+  NRGRI(0054)=  360,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  360,
+  NRGRI(0058)=  375,
+  NRGRI(0059)=  375,
+  NRGRI(0060)=  384,
+  NRGRI(0061)=  384,
+  NRGRI(0062)=  400,
+  NRGRI(0063)=  400,
+  NRGRI(0064)=  405,
+  NRGRI(0065)=  432,
+  NRGRI(0066)=  432,
+  NRGRI(0067)=  432,
+  NRGRI(0068)=  432,
+  NRGRI(0069)=  450,
+  NRGRI(0070)=  450,
+  NRGRI(0071)=  450,
+  NRGRI(0072)=  480,
+  NRGRI(0073)=  480,
+  NRGRI(0074)=  480,
+  NRGRI(0075)=  480,
+  NRGRI(0076)=  480,
+  NRGRI(0077)=  486,
+  NRGRI(0078)=  500,
+  NRGRI(0079)=  500,
+  NRGRI(0080)=  512,
+  NRGRI(0081)=  512,
+  NRGRI(0082)=  540,
+  NRGRI(0083)=  540,
+  NRGRI(0084)=  540,
+  NRGRI(0085)=  540,
+  NRGRI(0086)=  576,
+  NRGRI(0087)=  576,
+  NRGRI(0088)=  576,
+  NRGRI(0089)=  576,
+  NRGRI(0090)=  576,
+  NRGRI(0091)=  576,
+  NRGRI(0092)=  600,
+  NRGRI(0093)=  600,
+  NRGRI(0094)=  600,
+  NRGRI(0095)=  600,
+  NRGRI(0096)=  640,
+  NRGRI(0097)=  640,
+  NRGRI(0098)=  640,
+  NRGRI(0099)=  640,
+  NRGRI(0100)=  640,
+  NRGRI(0101)=  640,
+  NRGRI(0102)=  648,
+  NRGRI(0103)=  675,
+  NRGRI(0104)=  675,
+  NRGRI(0105)=  675,
+  NRGRI(0106)=  675,
+  NRGRI(0107)=  675,
+  NRGRI(0108)=  720,
+  NRGRI(0109)=  720,
+  NRGRI(0110)=  720,
+  NRGRI(0111)=  720,
+  NRGRI(0112)=  720,
+  NRGRI(0113)=  720,
+  NRGRI(0114)=  720,
+  NRGRI(0115)=  729,
+  NRGRI(0116)=  750,
+  NRGRI(0117)=  750,
+  NRGRI(0118)=  750,
+  NRGRI(0119)=  750,
+  NRGRI(0120)=  768,
+  NRGRI(0121)=  768,
+  NRGRI(0122)=  800,
+  NRGRI(0123)=  800,
+  NRGRI(0124)=  800,
+  NRGRI(0125)=  800,
+  NRGRI(0126)=  800,
+  NRGRI(0127)=  800,
+  NRGRI(0128)=  810,
+  NRGRI(0129)=  864,
+  NRGRI(0130)=  864,
+  NRGRI(0131)=  864,
+  NRGRI(0132)=  864,
+  NRGRI(0133)=  864,
+  NRGRI(0134)=  864,
+  NRGRI(0135)=  864,
+  NRGRI(0136)=  864,
+  NRGRI(0137)=  864,
+  NRGRI(0138)=  900,
+  NRGRI(0139)=  900,
+  NRGRI(0140)=  900,
+  NRGRI(0141)=  900,
+  NRGRI(0142)=  900,
+  NRGRI(0143)=  900,
+  NRGRI(0144)=  960,
+  NRGRI(0145)=  960,
+  NRGRI(0146)=  960,
+  NRGRI(0147)=  960,
+  NRGRI(0148)=  960,
+  NRGRI(0149)=  960,
+  NRGRI(0150)=  960,
+  NRGRI(0151)=  960,
+  NRGRI(0152)=  960,
+  NRGRI(0153)=  972,
+  NRGRI(0154)=  972,
+  NRGRI(0155)= 1000,
+  NRGRI(0156)= 1000,
+  NRGRI(0157)= 1000,
+  NRGRI(0158)= 1000,
+  NRGRI(0159)= 1000,
+  NRGRI(0160)= 1024,
+  NRGRI(0161)= 1024,
+  NRGRI(0162)= 1024,
+  NRGRI(0163)= 1024,
+  NRGRI(0164)= 1080,
+  NRGRI(0165)= 1080,
+  NRGRI(0166)= 1080,
+  NRGRI(0167)= 1080,
+  NRGRI(0168)= 1080,
+  NRGRI(0169)= 1080,
+  NRGRI(0170)= 1080,
+  NRGRI(0171)= 1080,
+  NRGRI(0172)= 1080,
+  NRGRI(0173)= 1125,
+  NRGRI(0174)= 1125,
+  NRGRI(0175)= 1125,
+  NRGRI(0176)= 1125,
+  NRGRI(0177)= 1125,
+  NRGRI(0178)= 1125,
+  NRGRI(0179)= 1125,
+  NRGRI(0180)= 1152,
+  NRGRI(0181)= 1152,
+  NRGRI(0182)= 1152,
+  NRGRI(0183)= 1152,
+  NRGRI(0184)= 1152,
+  NRGRI(0185)= 1200,
+  NRGRI(0186)= 1200,
+  NRGRI(0187)= 1200,
+  NRGRI(0188)= 1200,
+  NRGRI(0189)= 1200,
+  NRGRI(0190)= 1200,
+  NRGRI(0191)= 1200,
+  NRGRI(0192)= 1215,
+  NRGRI(0193)= 1215,
+  NRGRI(0194)= 1215,
+  NRGRI(0195)= 1280,
+  NRGRI(0196)= 1280,
+  NRGRI(0197)= 1280,
+  NRGRI(0198)= 1280,
+  NRGRI(0199)= 1280,
+  NRGRI(0200)= 1280,
+  NRGRI(0201)= 1280,
+  NRGRI(0202)= 1280,
+  NRGRI(0203)= 1280,
+  NRGRI(0204)= 1280,
+  NRGRI(0205)= 1280,
+  NRGRI(0206)= 1296,
+  NRGRI(0207)= 1296,
+  NRGRI(0208)= 1350,
+  NRGRI(0209)= 1350,
+  NRGRI(0210)= 1350,
+  NRGRI(0211)= 1350,
+  NRGRI(0212)= 1350,
+  NRGRI(0213)= 1350,
+  NRGRI(0214)= 1350,
+  NRGRI(0215)= 1350,
+  NRGRI(0216)= 1350,
+  NRGRI(0217)= 1440,
+  NRGRI(0218)= 1440,
+  NRGRI(0219)= 1440,
+  NRGRI(0220)= 1440,
+  NRGRI(0221)= 1440,
+  NRGRI(0222)= 1440,
+  NRGRI(0223)= 1440,
+  NRGRI(0224)= 1440,
+  NRGRI(0225)= 1440,
+  NRGRI(0226)= 1440,
+  NRGRI(0227)= 1440,
+  NRGRI(0228)= 1440,
+  NRGRI(0229)= 1440,
+  NRGRI(0230)= 1440,
+  NRGRI(0231)= 1440,
+  NRGRI(0232)= 1458,
+  NRGRI(0233)= 1458,
+  NRGRI(0234)= 1458,
+  NRGRI(0235)= 1500,
+  NRGRI(0236)= 1500,
+  NRGRI(0237)= 1500,
+  NRGRI(0238)= 1500,
+  NRGRI(0239)= 1500,
+  NRGRI(0240)= 1500,
+  NRGRI(0241)= 1500,
+  NRGRI(0242)= 1500,
+  NRGRI(0243)= 1536,
+  NRGRI(0244)= 1536,
+  NRGRI(0245)= 1536,
+  NRGRI(0246)= 1536,
+  NRGRI(0247)= 1536,
+  NRGRI(0248)= 1536,
+  NRGRI(0249)= 1600,
+  NRGRI(0250)= 1600,
+  NRGRI(0251)= 1600,
+  NRGRI(0252)= 1600,
+  NRGRI(0253)= 1600,
+  NRGRI(0254)= 1600,
+  NRGRI(0255)= 1600,
+  NRGRI(0256)= 1600,
+  NRGRI(0257)= 1600,
+  NRGRI(0258)= 1600,
+  NRGRI(0259)= 1600,
+  NRGRI(0260)= 1620,
+  NRGRI(0261)= 1620,
+  NRGRI(0262)= 1620,
+  NRGRI(0263)= 1728,
+  NRGRI(0264)= 1728,
+  NRGRI(0265)= 1728,
+  NRGRI(0266)= 1728,
+  NRGRI(0267)= 1728,
+  NRGRI(0268)= 1728,
+  NRGRI(0269)= 1728,
+  NRGRI(0270)= 1728,
+  NRGRI(0271)= 1728,
+  NRGRI(0272)= 1728,
+  NRGRI(0273)= 1728,
+  NRGRI(0274)= 1728,
+  NRGRI(0275)= 1728,
+  NRGRI(0276)= 1728,
+  NRGRI(0277)= 1728,
+  NRGRI(0278)= 1728,
+  NRGRI(0279)= 1728,
+  NRGRI(0280)= 1728,
+  NRGRI(0281)= 1728,
+  NRGRI(0282)= 1800,
+  NRGRI(0283)= 1800,
+  NRGRI(0284)= 1800,
+  NRGRI(0285)= 1800,
+  NRGRI(0286)= 1800,
+  NRGRI(0287)= 1800,
+  NRGRI(0288)= 1800,
+  NRGRI(0289)= 1800,
+  NRGRI(0290)= 1800,
+  NRGRI(0291)= 1800,
+  NRGRI(0292)= 1800,
+  NRGRI(0293)= 1800,
+  NRGRI(0294)= 1875,
+  NRGRI(0295)= 1875,
+  NRGRI(0296)= 1875,
+  NRGRI(0297)= 1875,
+  NRGRI(0298)= 1875,
+  NRGRI(0299)= 1875,
+  NRGRI(0300)= 1875,
+  NRGRI(0301)= 1875,
+  NRGRI(0302)= 1875,
+  NRGRI(0303)= 1875,
+  NRGRI(0304)= 1875,
+  NRGRI(0305)= 1875,
+  NRGRI(0306)= 1875,
+  NRGRI(0307)= 1920,
+  NRGRI(0308)= 1920,
+  NRGRI(0309)= 1920,
+  NRGRI(0310)= 1920,
+  NRGRI(0311)= 1920,
+  NRGRI(0312)= 1920,
+  NRGRI(0313)= 1920,
+  NRGRI(0314)= 1920,
+  NRGRI(0315)= 1944,
+  NRGRI(0316)= 1944,
+  NRGRI(0317)= 1944,
+  NRGRI(0318)= 1944,
+  NRGRI(0319)= 1944,
+  NRGRI(0320)= 2000,
+  NRGRI(0321)= 2000,
+  NRGRI(0322)= 2000,
+  NRGRI(0323)= 2000,
+  NRGRI(0324)= 2000,
+  NRGRI(0325)= 2000,
+  NRGRI(0326)= 2000,
+  NRGRI(0327)= 2000,
+  NRGRI(0328)= 2000,
+  NRGRI(0329)= 2000,
+  NRGRI(0330)= 2025,
+  NRGRI(0331)= 2025,
+  NRGRI(0332)= 2025,
+  NRGRI(0333)= 2025,
+  NRGRI(0334)= 2048,
+  NRGRI(0335)= 2048,
+  NRGRI(0336)= 2048,
+  NRGRI(0337)= 2048,
+  NRGRI(0338)= 2048,
+  NRGRI(0339)= 2160,
+  NRGRI(0340)= 2160,
+  NRGRI(0341)= 2160,
+  NRGRI(0342)= 2160,
+  NRGRI(0343)= 2160,
+  NRGRI(0344)= 2160,
+  NRGRI(0345)= 2160,
+  NRGRI(0346)= 2160,
+  NRGRI(0347)= 2160,
+  NRGRI(0348)= 2160,
+  NRGRI(0349)= 2160,
+  NRGRI(0350)= 2160,
+  NRGRI(0351)= 2160,
+  NRGRI(0352)= 2160,
+  NRGRI(0353)= 2160,
+  NRGRI(0354)= 2160,
+  NRGRI(0355)= 2160,
+  NRGRI(0356)= 2160,
+  NRGRI(0357)= 2160,
+  NRGRI(0358)= 2160,
+  NRGRI(0359)= 2187,
+  NRGRI(0360)= 2187,
+  NRGRI(0361)= 2187,
+  NRGRI(0362)= 2187,
+  NRGRI(0363)= 2187,
+  NRGRI(0364)= 2250,
+  NRGRI(0365)= 2250,
+  NRGRI(0366)= 2250,
+  NRGRI(0367)= 2250,
+  NRGRI(0368)= 2250,
+  NRGRI(0369)= 2250,
+  NRGRI(0370)= 2250,
+  NRGRI(0371)= 2250,
+  NRGRI(0372)= 2250,
+  NRGRI(0373)= 2250,
+  NRGRI(0374)= 2250,
+  NRGRI(0375)= 2250,
+  NRGRI(0376)= 2304,
+  NRGRI(0377)= 2304,
+  NRGRI(0378)= 2304,
+  NRGRI(0379)= 2304,
+  NRGRI(0380)= 2304,
+  NRGRI(0381)= 2304,
+  NRGRI(0382)= 2304,
+  NRGRI(0383)= 2304,
+  NRGRI(0384)= 2304,
+  NRGRI(0385)= 2304,
+  NRGRI(0386)= 2400,
+  NRGRI(0387)= 2400,
+  NRGRI(0388)= 2400,
+  NRGRI(0389)= 2400,
+  NRGRI(0390)= 2400,
+  NRGRI(0391)= 2400,
+  NRGRI(0392)= 2400,
+  NRGRI(0393)= 2400,
+  NRGRI(0394)= 2400,
+  NRGRI(0395)= 2400,
+  NRGRI(0396)= 2400,
+  NRGRI(0397)= 2400,
+  NRGRI(0398)= 2400,
+  NRGRI(0399)= 2400,
+  NRGRI(0400)= 2400,
+  NRGRI(0401)= 2400,
+  NRGRI(0402)= 2400,
+  NRGRI(0403)= 2400,
+  NRGRI(0404)= 2400,
+  NRGRI(0405)= 2430,
+  NRGRI(0406)= 2430,
+  NRGRI(0407)= 2430,
+  NRGRI(0408)= 2430,
+  NRGRI(0409)= 2430,
+  NRGRI(0410)= 2500,
+  NRGRI(0411)= 2500,
+  NRGRI(0412)= 2500,
+  NRGRI(0413)= 2500,
+  NRGRI(0414)= 2500,
+  NRGRI(0415)= 2500,
+  NRGRI(0416)= 2500,
+  NRGRI(0417)= 2500,
+  NRGRI(0418)= 2500,
+  NRGRI(0419)= 2500,
+  NRGRI(0420)= 2500,
+  NRGRI(0421)= 2500,
+  NRGRI(0422)= 2500,
+  NRGRI(0423)= 2500,
+  NRGRI(0424)= 2500,
+  NRGRI(0425)= 2560,
+  NRGRI(0426)= 2560,
+  NRGRI(0427)= 2560,
+  NRGRI(0428)= 2560,
+  NRGRI(0429)= 2560,
+  NRGRI(0430)= 2560,
+  NRGRI(0431)= 2560,
+  NRGRI(0432)= 2560,
+  NRGRI(0433)= 2560,
+  NRGRI(0434)= 2560,
+  NRGRI(0435)= 2560,
+  NRGRI(0436)= 2560,
+  NRGRI(0437)= 2592,
+  NRGRI(0438)= 2592,
+  NRGRI(0439)= 2592,
+  NRGRI(0440)= 2592,
+  NRGRI(0441)= 2592,
+  NRGRI(0442)= 2592,
+  NRGRI(0443)= 2700,
+  NRGRI(0444)= 2700,
+  NRGRI(0445)= 2700,
+  NRGRI(0446)= 2700,
+  NRGRI(0447)= 2700,
+  NRGRI(0448)= 2700,
+  NRGRI(0449)= 2700,
+  NRGRI(0450)= 2700,
+  NRGRI(0451)= 2700,
+  NRGRI(0452)= 2700,
+  NRGRI(0453)= 2700,
+  NRGRI(0454)= 2700,
+  NRGRI(0455)= 2700,
+  NRGRI(0456)= 2700,
+  NRGRI(0457)= 2700,
+  NRGRI(0458)= 2700,
+  NRGRI(0459)= 2700,
+  NRGRI(0460)= 2700,
+  NRGRI(0461)= 2700,
+  NRGRI(0462)= 2700,
+  NRGRI(0463)= 2700,
+  NRGRI(0464)= 2700,
+  NRGRI(0465)= 2880,
+  NRGRI(0466)= 2880,
+  NRGRI(0467)= 2880,
+  NRGRI(0468)= 2880,
+  NRGRI(0469)= 2880,
+  NRGRI(0470)= 2880,
+  NRGRI(0471)= 2880,
+  NRGRI(0472)= 2880,
+  NRGRI(0473)= 2880,
+  NRGRI(0474)= 2880,
+  NRGRI(0475)= 2880,
+  NRGRI(0476)= 2880,
+  NRGRI(0477)= 2880,
+  NRGRI(0478)= 2880,
+  NRGRI(0479)= 2880,
+  NRGRI(0480)= 2880,
+  NRGRI(0481)= 2880,
+  NRGRI(0482)= 2880,
+  NRGRI(0483)= 2880,
+  NRGRI(0484)= 2880,
+  NRGRI(0485)= 2880,
+  NRGRI(0486)= 2880,
+  NRGRI(0487)= 2880,
+  NRGRI(0488)= 2880,
+  NRGRI(0489)= 2880,
+  NRGRI(0490)= 2880,
+  NRGRI(0491)= 2880,
+  NRGRI(0492)= 2880,
+  NRGRI(0493)= 2880,
+  NRGRI(0494)= 2880,
+  NRGRI(0495)= 2880,
+  NRGRI(0496)= 2880,
+  NRGRI(0497)= 2880,
+  NRGRI(0498)= 2880,
+  NRGRI(0499)= 2880,
+  NRGRI(0500)= 2880,
+  NRGRI(0501)= 2880,
+  NRGRI(0502)= 2880,
+  NRGRI(0503)= 2880,
+  NRGRI(0504)= 2916,
+  NRGRI(0505)= 2916,
+  NRGRI(0506)= 2916,
+  NRGRI(0507)= 2916,
+  NRGRI(0508)= 2916,
+  NRGRI(0509)= 2916,
+  NRGRI(0510)= 2916,
+  NRGRI(0511)= 2916,
+  NRGRI(0512)= 3000,
+  NRGRI(0513)= 3000,
+  NRGRI(0514)= 3000,
+  NRGRI(0515)= 3000,
+  NRGRI(0516)= 3000,
+  NRGRI(0517)= 3000,
+  NRGRI(0518)= 3000,
+  NRGRI(0519)= 3000,
+  NRGRI(0520)= 3000,
+  NRGRI(0521)= 3000,
+  NRGRI(0522)= 3000,
+  NRGRI(0523)= 3000,
+  NRGRI(0524)= 3000,
+  NRGRI(0525)= 3000,
+  NRGRI(0526)= 3000,
+  NRGRI(0527)= 3000,
+  NRGRI(0528)= 3000,
+  NRGRI(0529)= 3000,
+  NRGRI(0530)= 3000,
+  NRGRI(0531)= 3072,
+  NRGRI(0532)= 3072,
+  NRGRI(0533)= 3072,
+  NRGRI(0534)= 3072,
+  NRGRI(0535)= 3072,
+  NRGRI(0536)= 3072,
+  NRGRI(0537)= 3072,
+  NRGRI(0538)= 3072,
+  NRGRI(0539)= 3072,
+  NRGRI(0540)= 3072,
+  NRGRI(0541)= 3072,
+  NRGRI(0542)= 3072,
+  NRGRI(0543)= 3072,
+  NRGRI(0544)= 3072,
+  NRGRI(0545)= 3072,
+  NRGRI(0546)= 3072,
+  NRGRI(0547)= 3072,
+  NRGRI(0548)= 3125,
+  NRGRI(0549)= 3125,
+  NRGRI(0550)= 3125,
+  NRGRI(0551)= 3125,
+  NRGRI(0552)= 3125,
+  NRGRI(0553)= 3125,
+  NRGRI(0554)= 3125,
+  NRGRI(0555)= 3125,
+  NRGRI(0556)= 3125,
+  NRGRI(0557)= 3125,
+  NRGRI(0558)= 3125,
+  NRGRI(0559)= 3125,
+  NRGRI(0560)= 3125,
+  NRGRI(0561)= 3200,
+  NRGRI(0562)= 3200,
+  NRGRI(0563)= 3200,
+  NRGRI(0564)= 3200,
+  NRGRI(0565)= 3200,
+  NRGRI(0566)= 3200,
+  NRGRI(0567)= 3200,
+  NRGRI(0568)= 3200,
+  NRGRI(0569)= 3200,
+  NRGRI(0570)= 3200,
+  NRGRI(0571)= 3200,
+  NRGRI(0572)= 3200,
+  NRGRI(0573)= 3200,
+  NRGRI(0574)= 3200,
+  NRGRI(0575)= 3200,
+  NRGRI(0576)= 3200,
+  NRGRI(0577)= 3200,
+  NRGRI(0578)= 3200,
+  NRGRI(0579)= 3240,
+  NRGRI(0580)= 3240,
+  NRGRI(0581)= 3240,
+  NRGRI(0582)= 3240,
+  NRGRI(0583)= 3240,
+  NRGRI(0584)= 3240,
+  NRGRI(0585)= 3240,
+  NRGRI(0586)= 3240,
+  NRGRI(0587)= 3240,
+  NRGRI(0588)= 3240,
+  NRGRI(0589)= 3375,
+  NRGRI(0590)= 3375,
+  NRGRI(0591)= 3375,
+  NRGRI(0592)= 3375,
+  NRGRI(0593)= 3375,
+  NRGRI(0594)= 3375,
+  NRGRI(0595)= 3375,
+  NRGRI(0596)= 3375,
+  NRGRI(0597)= 3375,
+  NRGRI(0598)= 3375,
+  NRGRI(0599)= 3375,
+  NRGRI(0600)= 3375,
+  NRGRI(0601)= 3375,
+  NRGRI(0602)= 3375,
+  NRGRI(0603)= 3375,
+  NRGRI(0604)= 3375,
+  NRGRI(0605)= 3375,
+  NRGRI(0606)= 3375,
+  NRGRI(0607)= 3375,
+  NRGRI(0608)= 3375,
+  NRGRI(0609)= 3375,
+  NRGRI(0610)= 3375,
+  NRGRI(0611)= 3375,
+  NRGRI(0612)= 3375,
+  NRGRI(0613)= 3375,
+  NRGRI(0614)= 3375,
+  NRGRI(0615)= 3375,
+  NRGRI(0616)= 3375,
+  NRGRI(0617)= 3375,
+  NRGRI(0618)= 3375,
+  NRGRI(0619)= 3375,
+  NRGRI(0620)= 3375,
+  NRGRI(0621)= 3375,
+  NRGRI(0622)= 3375,
+  NRGRI(0623)= 3375,
+  NRGRI(0624)= 3375,
+  NRGRI(0625)= 3456,
+  NRGRI(0626)= 3456,
+  NRGRI(0627)= 3456,
+  NRGRI(0628)= 3456,
+  NRGRI(0629)= 3456,
+  NRGRI(0630)= 3456,
+  NRGRI(0631)= 3456,
+  NRGRI(0632)= 3456,
+  NRGRI(0633)= 3456,
+  NRGRI(0634)= 3456,
+  NRGRI(0635)= 3456,
+  NRGRI(0636)= 3456,
+  NRGRI(0637)= 3456,
+  NRGRI(0638)= 3456,
+  NRGRI(0639)= 3456,
+  NRGRI(0640)= 3456,
+  NRGRI(0641)= 3456,
+  NRGRI(0642)= 3456,
+  NRGRI(0643)= 3456,
+  NRGRI(0644)= 3456,
+  NRGRI(0645)= 3456,
+  NRGRI(0646)= 3456,
+  NRGRI(0647)= 3456,
+  NRGRI(0648)= 3600,
+  NRGRI(0649)= 3600,
+  NRGRI(0650)= 3600,
+  NRGRI(0651)= 3600,
+  NRGRI(0652)= 3600,
+  NRGRI(0653)= 3600,
+  NRGRI(0654)= 3600,
+  NRGRI(0655)= 3600,
+  NRGRI(0656)= 3600,
+  NRGRI(0657)= 3600,
+  NRGRI(0658)= 3600,
+  NRGRI(0659)= 3600,
+  NRGRI(0660)= 3600,
+  NRGRI(0661)= 3600,
+  NRGRI(0662)= 3600,
+  NRGRI(0663)= 3600,
+  NRGRI(0664)= 3600,
+  NRGRI(0665)= 3600,
+  NRGRI(0666)= 3600,
+  NRGRI(0667)= 3600,
+  NRGRI(0668)= 3600,
+  NRGRI(0669)= 3600,
+  NRGRI(0670)= 3600,
+  NRGRI(0671)= 3600,
+  NRGRI(0672)= 3600,
+  NRGRI(0673)= 3600,
+  NRGRI(0674)= 3600,
+  NRGRI(0675)= 3600,
+  NRGRI(0676)= 3600,
+  NRGRI(0677)= 3600,
+  NRGRI(0678)= 3600,
+  NRGRI(0679)= 3600,
+  NRGRI(0680)= 3600,
+  NRGRI(0681)= 3600,
+  NRGRI(0682)= 3600,
+  NRGRI(0683)= 3600,
+  NRGRI(0684)= 3600,
+  NRGRI(0685)= 3600,
+  NRGRI(0686)= 3600,
+  NRGRI(0687)= 3600,
+  NRGRI(0688)= 3600,
+  NRGRI(0689)= 3600,
+  NRGRI(0690)= 3600,
+  NRGRI(0691)= 3600,
+  NRGRI(0692)= 3645,
+  NRGRI(0693)= 3645,
+  NRGRI(0694)= 3645,
+  NRGRI(0695)= 3645,
+  NRGRI(0696)= 3645,
+  NRGRI(0697)= 3645,
+  NRGRI(0698)= 3645,
+  NRGRI(0699)= 3645,
+  NRGRI(0700)= 3645,
+  NRGRI(0701)= 3645,
+  NRGRI(0702)= 3645,
+  NRGRI(0703)= 3645,
+  NRGRI(0704)= 3645,
+  NRGRI(0705)= 3645,
+  NRGRI(0706)= 3645,
+  NRGRI(0707)= 3750,
+  NRGRI(0708)= 3750,
+  NRGRI(0709)= 3750,
+  NRGRI(0710)= 3750,
+  NRGRI(0711)= 3750,
+  NRGRI(0712)= 3750,
+  NRGRI(0713)= 3750,
+  NRGRI(0714)= 3750,
+  NRGRI(0715)= 3750,
+  NRGRI(0716)= 3750,
+  NRGRI(0717)= 3750,
+  NRGRI(0718)= 3750,
+  NRGRI(0719)= 3750,
+  NRGRI(0720)= 3750,
+  NRGRI(0721)= 3750,
+  NRGRI(0722)= 3750,
+  NRGRI(0723)= 3750,
+  NRGRI(0724)= 3750,
+  NRGRI(0725)= 3750,
+  NRGRI(0726)= 3750,
+  NRGRI(0727)= 3750,
+  NRGRI(0728)= 3750,
+  NRGRI(0729)= 3750,
+  NRGRI(0730)= 3750,
+  NRGRI(0731)= 3750,
+  NRGRI(0732)= 3750,
+  NRGRI(0733)= 3750,
+  NRGRI(0734)= 3750,
+  NRGRI(0735)= 3750,
+  NRGRI(0736)= 3750,
+  NRGRI(0737)= 3750,
+  NRGRI(0738)= 3750,
+  NRGRI(0739)= 3750,
+  NRGRI(0740)= 3750,
+  NRGRI(0741)= 3750,
+  NRGRI(0742)= 3750,
+  NRGRI(0743)= 3750,
+  NRGRI(0744)= 3750,
+  NRGRI(0745)= 3750,
+  NRGRI(0746)= 3840,
+  NRGRI(0747)= 3840,
+  NRGRI(0748)= 3840,
+  NRGRI(0749)= 3840,
+  NRGRI(0750)= 3840,
+  NRGRI(0751)= 3840,
+  NRGRI(0752)= 3840,
+  NRGRI(0753)= 3840,
+  NRGRI(0754)= 3840,
+  NRGRI(0755)= 3840,
+  NRGRI(0756)= 3840,
+  NRGRI(0757)= 3840,
+  NRGRI(0758)= 3840,
+  NRGRI(0759)= 3840,
+  NRGRI(0760)= 3840,
+  NRGRI(0761)= 3840,
+  NRGRI(0762)= 3840,
+  NRGRI(0763)= 3840,
+  NRGRI(0764)= 3840,
+  NRGRI(0765)= 3840,
+  NRGRI(0766)= 3840,
+  NRGRI(0767)= 3840,
+  NRGRI(0768)= 3840,
+  NRGRI(0769)= 3840,
+  NRGRI(0770)= 3840,
+  NRGRI(0771)= 3840,
+  NRGRI(0772)= 3840,
+  NRGRI(0773)= 3840,
+  NRGRI(0774)= 3840,
+  NRGRI(0775)= 3840,
+  NRGRI(0776)= 3840,
+  NRGRI(0777)= 3840,
+  NRGRI(0778)= 3840,
+  NRGRI(0779)= 3840,
+  NRGRI(0780)= 3840,
+  NRGRI(0781)= 3840,
+  NRGRI(0782)= 3840,
+  NRGRI(0783)= 3888,
+  NRGRI(0784)= 3888,
+  NRGRI(0785)= 3888,
+  NRGRI(0786)= 3888,
+  NRGRI(0787)= 3888,
+  NRGRI(0788)= 3888,
+  NRGRI(0789)= 3888,
+  NRGRI(0790)= 3888,
+  NRGRI(0791)= 3888,
+  NRGRI(0792)= 3888,
+  NRGRI(0793)= 3888,
+  NRGRI(0794)= 3888,
+  NRGRI(0795)= 3888,
+  NRGRI(0796)= 3888,
+  NRGRI(0797)= 3888,
+  NRGRI(0798)= 3888,
+  NRGRI(0799)= 3888,
+  NRGRI(0800)= 3888,
+  NRGRI(0801)= 3888,
+  NRGRI(0802)= 3888,
+  NRGRI(0803)= 3888,
+  NRGRI(0804)= 3888,
+  NRGRI(0805)= 4000,
+  NRGRI(0806)= 4000,
+  NRGRI(0807)= 4000,
+  NRGRI(0808)= 4000,
+  NRGRI(0809)= 4000,
+  NRGRI(0810)= 4000,
+  NRGRI(0811)= 4000,
+  NRGRI(0812)= 4000,
+  NRGRI(0813)= 4000,
+  NRGRI(0814)= 4000,
+  NRGRI(0815)= 4000,
+  NRGRI(0816)= 4000,
+  NRGRI(0817)= 4000,
+  NRGRI(0818)= 4000,
+  NRGRI(0819)= 4000,
+  NRGRI(0820)= 4000,
+  NRGRI(0821)= 4000,
+  NRGRI(0822)= 4000,
+  NRGRI(0823)= 4000,
+  NRGRI(0824)= 4000,
+  NRGRI(0825)= 4000,
+  NRGRI(0826)= 4000,
+  NRGRI(0827)= 4000,
+  NRGRI(0828)= 4000,
+  NRGRI(0829)= 4000,
+  NRGRI(0830)= 4000,
+  NRGRI(0831)= 4000,
+  NRGRI(0832)= 4000,
+  NRGRI(0833)= 4000,
+  NRGRI(0834)= 4000,
+  NRGRI(0835)= 4000,
+  NRGRI(0836)= 4000,
+  NRGRI(0837)= 4000,
+  NRGRI(0838)= 4000,
+  NRGRI(0839)= 4000,
+  NRGRI(0840)= 4000,
+  NRGRI(0841)= 4000,
+  NRGRI(0842)= 4000,
+  NRGRI(0843)= 4000,
+  NRGRI(0844)= 4000,
+  NRGRI(0845)= 4000,
+  NRGRI(0846)= 4000,
+  NRGRI(0847)= 4000,
+  NRGRI(0848)= 4000,
+  NRGRI(0849)= 4000,
+  NRGRI(0850)= 4000,
+  NRGRI(0851)= 4000,
+  NRGRI(0852)= 4000,
+  NRGRI(0853)= 4000,
+  NRGRI(0854)= 4000,
+  NRGRI(0855)= 4000,
+  NRGRI(0856)= 4000,
+  NRGRI(0857)= 4000,
+  NRGRI(0858)= 4000,
+  NRGRI(0859)= 4000,
+  NRGRI(0860)= 4000,
+  NRGRI(0861)= 4000,
+  NRGRI(0862)= 4000,
+  NRGRI(0863)= 4000,
+  NRGRI(0864)= 4000,
+  NRGRI(0865)= 4000,
+  NRGRI(0866)= 4000,
+  NRGRI(0867)= 4000,
+  NRGRI(0868)= 4000,
+  NRGRI(0869)= 4000,
+  NRGRI(0870)= 4050,
+  NRGRI(0871)= 4050,
+  NRGRI(0872)= 4050,
+  NRGRI(0873)= 4050,
+  NRGRI(0874)= 4050,
+  NRGRI(0875)= 4050,
+  NRGRI(0876)= 4050,
+  NRGRI(0877)= 4050,
+  NRGRI(0878)= 4050,
+  NRGRI(0879)= 4050,
+  NRGRI(0880)= 4050,
+  NRGRI(0881)= 4050,
+  NRGRI(0882)= 4050,
+  NRGRI(0883)= 4050,
+  NRGRI(0884)= 4050,
+  NRGRI(0885)= 4050,
+  NRGRI(0886)= 4050,
+  NRGRI(0887)= 4050,
+  NRGRI(0888)= 4050,
+  NRGRI(0889)= 4050,
+  NRGRI(0890)= 4050,
+  NRGRI(0891)= 4050,
+  NRGRI(0892)= 4050,
+  NRGRI(0893)= 4050,
+  NRGRI(0894)= 4050,
+  NRGRI(0895)= 4050,
+  NRGRI(0896)= 4050,
+  NRGRI(0897)= 4050,
+  NRGRI(0898)= 4050,
+  NRGRI(0899)= 4050,
+  NRGRI(0900)= 4050,
+  NRGRI(0901)= 4050,
+  NRGRI(0902)= 4050,
+  NRGRI(0903)= 4050,
+  NRGRI(0904)= 4050,
+  NRGRI(0905)= 4050,
+  NRGRI(0906)= 4050,
+  NRGRI(0907)= 4050,
+  NRGRI(0908)= 4050,
+  NRGRI(0909)= 4096,
+  NRGRI(0910)= 4096,
+  NRGRI(0911)= 4096,
+  NRGRI(0912)= 4096,
+  NRGRI(0913)= 4096,
+  NRGRI(0914)= 4096,
+  NRGRI(0915)= 4096,
+  NRGRI(0916)= 4096,
+  NRGRI(0917)= 4096,
+  NRGRI(0918)= 4096,
+  NRGRI(0919)= 4096,
+  NRGRI(0920)= 4096,
+  NRGRI(0921)= 4096,
+  NRGRI(0922)= 4096,
+  NRGRI(0923)= 4096,
+  NRGRI(0924)= 4096,
+  NRGRI(0925)= 4096,
+  NRGRI(0926)= 4096,
+  NRGRI(0927)= 4096,
+  NRGRI(0928)= 4096,
+  NRGRI(0929)= 4096,
+  NRGRI(0930)= 4096,
+  NRGRI(0931)= 4096,
+  NRGRI(0932)= 4096,
+  NRGRI(0933)= 4096,
+  NRGRI(0934)= 4096,
+  NRGRI(0935)= 4096,
+  NRGRI(0936)= 4096,
+  NRGRI(0937)= 4096,
+  NRGRI(0938)= 4096,
+  NRGRI(0939)= 4096,
+  NRGRI(0940)= 4096,
+  NRGRI(0941)= 4096,
+  NRGRI(0942)= 4096,
+  NRGRI(0943)= 4096,
+  NRGRI(0944)= 4096,
+  NRGRI(0945)= 4096,
+  NRGRI(0946)= 4096,
+  NRGRI(0947)= 4096,
+  NRGRI(0948)= 4096,
+  NRGRI(0949)= 4096,
+  NRGRI(0950)= 4096,
+  NRGRI(0951)= 4096,
+  NRGRI(0952)= 4096,
+  NRGRI(0953)= 4096,
+  NRGRI(0954)= 4096,
+  NRGRI(0955)= 4096,
+  NRGRI(0956)= 4096,
+  NRGRI(0957)= 4096,
+  NRGRI(0958)= 4096,
+  NRGRI(0959)= 4096,
+  NRGRI(0960)= 4096,
+  NRGRI(0961)= 4096,
+  NRGRI(0962)= 4096,
+  NRGRI(0963)= 4096,
+  NRGRI(0964)= 4096,
+  NRGRI(0965)= 4096,
+  NRGRI(0966)= 4096,
+  NRGRI(0967)= 4096,
+  NRGRI(0968)= 4096,
+  NRGRI(0969)= 4096,
+  NRGRI(0970)= 4096,
+  NRGRI(0971)= 4096,
+  NRGRI(0972)= 4096,
+  NRGRI(0973)= 4096,
+  NRGRI(0974)= 4096,
+  NRGRI(0975)= 4096,
+  NRGRI(0976)= 4096,
+  NRGRI(0977)= 4096,
+  NRGRI(0978)= 4096,
+  NRGRI(0979)= 4096,
+  NRGRI(0980)= 4096,
+  NRGRI(0981)= 4096,
+  NRGRI(0982)= 4096,
+  NRGRI(0983)= 4096,
+  NRGRI(0984)= 4096,
+  NRGRI(0985)= 4096,
+  NRGRI(0986)= 4096,
+  NRGRI(0987)= 4096,
+  NRGRI(0988)= 4096,
+  NRGRI(0989)= 4096,
+  NRGRI(0990)= 4096,
+  NRGRI(0991)= 4096,
+  NRGRI(0992)= 4096,
+  NRGRI(0993)= 4096,
+  NRGRI(0994)= 4096,
+  NRGRI(0995)= 4096,
+  NRGRI(0996)= 4096,
+  NRGRI(0997)= 4096,
+  NRGRI(0998)= 4096,
+  NRGRI(0999)= 4096,
+  NRGRI(1000)= 4096,
+  NRGRI(1001)= 4096,
+  NRGRI(1002)= 4096,
+  NRGRI(1003)= 4096,
+  NRGRI(1004)= 4096,
+  NRGRI(1005)= 4096,
+  NRGRI(1006)= 4096,
+  NRGRI(1007)= 4096,
+  NRGRI(1008)= 4096,
+  NRGRI(1009)= 4096,
+  NRGRI(1010)= 4096,
+  NRGRI(1011)= 4096,
+  NRGRI(1012)= 4096,
+  NRGRI(1013)= 4096,
+  NRGRI(1014)= 4096,
+  NRGRI(1015)= 4096,
+  NRGRI(1016)= 4096,
+  NRGRI(1017)= 4096,
+  NRGRI(1018)= 4096,
+  NRGRI(1019)= 4096,
+  NRGRI(1020)= 4096,
+  NRGRI(1021)= 4096,
+  NRGRI(1022)= 4096,
+  NRGRI(1023)= 4096,
+  NRGRI(1024)= 4096,
+  NRGRI(1025)= 4096,
+  NRGRI(1026)= 4096,
+  NRGRI(1027)= 4096,
+  NRGRI(1028)= 4096,
+  NRGRI(1029)= 4096,
+  NRGRI(1030)= 4096,
+  NRGRI(1031)= 4096,
+  NRGRI(1032)= 4096,
+  NRGRI(1033)= 4096,
+  NRGRI(1034)= 4096,
+  NRGRI(1035)= 4096,
+  NRGRI(1036)= 4096,
+  NRGRI(1037)= 4096,
+  NRGRI(1038)= 4096,
+  NRGRI(1039)= 4096,
+  NRGRI(1040)= 4096,
+  NRGRI(1041)= 4096,
+  NRGRI(1042)= 4096,
+  NRGRI(1043)= 4096,
+  NRGRI(1044)= 4096,
+  NRGRI(1045)= 4096,
+  NRGRI(1046)= 4096,
+  NRGRI(1047)= 4096,
+  NRGRI(1048)= 4096,
+  NRGRI(1049)= 4096,
+  NRGRI(1050)= 4096,
+  NRGRI(1051)= 4096,
+  NRGRI(1052)= 4096,
+  NRGRI(1053)= 4096,
+  NRGRI(1054)= 4096,
+  NRGRI(1055)= 4096,
+  NRGRI(1056)= 4096,
+  NRGRI(1057)= 4096,
+  NRGRI(1058)= 4096,
+  NRGRI(1059)= 4096,
+  NRGRI(1060)= 4096,
+  NRGRI(1061)= 4096,
+  NRGRI(1062)= 4096,
+  NRGRI(1063)= 4096,
+  NRGRI(1064)= 4096,
+  NRGRI(1065)= 4096,
+  NRGRI(1066)= 4096,
+  NRGRI(1067)= 4096,
+  NRGRI(1068)= 4096,
+  NRGRI(1069)= 4096,
+  NRGRI(1070)= 4096,
+  NRGRI(1071)= 4096,
+  NRGRI(1072)= 4096,
+  NRGRI(1073)= 4096,
+  NRGRI(1074)= 4096,
+  NRGRI(1075)= 4096,
+  NRGRI(1076)= 4096,
+  NRGRI(1077)= 4096,
+  NRGRI(1078)= 4096,
+  NRGRI(1079)= 4096,
+  NRGRI(1080)= 4096,
+  NRGRI(1081)= 4096,
+  NRGRI(1082)= 4096,
+  NRGRI(1083)= 4096,
+  NRGRI(1084)= 4096,
+  NRGRI(1085)= 4096,
+  NRGRI(1086)= 4096,
+  NRGRI(1087)= 4096,
+  NRGRI(1088)= 4096,
+  NRGRI(1089)= 4096,
+  NRGRI(1090)= 4096,
+  NRGRI(1091)= 4096,
+  NRGRI(1092)= 4096,
+  NRGRI(1093)= 4096,
+  NRGRI(1094)= 4096,
+  NRGRI(1095)= 4096,
+  NRGRI(1096)= 4096,
+  NRGRI(1097)= 4096,
+  NRGRI(1098)= 4096,
+  NRGRI(1099)= 4096,
+  NRGRI(1100)= 4096,
+  NRGRI(1101)= 4096,
+  NRGRI(1102)= 4096,
+  NRGRI(1103)= 4096,
+  NRGRI(1104)= 4096,
+  NRGRI(1105)= 4096,
+  NRGRI(1106)= 4096,
+  NRGRI(1107)= 4096,
+  NRGRI(1108)= 4096,
+  NRGRI(1109)= 4096,
+  NRGRI(1110)= 4096,
+  NRGRI(1111)= 4096,
+  NRGRI(1112)= 4096,
+  NRGRI(1113)= 4096,
+  NRGRI(1114)= 4096,
+  NRGRI(1115)= 4096,
+  NRGRI(1116)= 4096,
+  NRGRI(1117)= 4096,
+  NRGRI(1118)= 4096,
+  NRGRI(1119)= 4096,
+  NRGRI(1120)= 4096,
+  NRGRI(1121)= 4096,
+  NRGRI(1122)= 4096,
+  NRGRI(1123)= 4096,
+  NRGRI(1124)= 4096,
+  NRGRI(1125)= 4096,
+  NRGRI(1126)= 4096,
+  NRGRI(1127)= 4096,
+  NRGRI(1128)= 4096,
+  NRGRI(1129)= 4096,
+  NRGRI(1130)= 4096,
+  NRGRI(1131)= 4096,
+  NRGRI(1132)= 4096,
+  NRGRI(1133)= 4096,
+  NRGRI(1134)= 4096,
+  NRGRI(1135)= 4096,
+  NRGRI(1136)= 4096,
+  NRGRI(1137)= 4096,
+  NRGRI(1138)= 4096,
+  NRGRI(1139)= 4096,
+  NRGRI(1140)= 4096,
+  NRGRI(1141)= 4050,
+  NRGRI(1142)= 4050,
+  NRGRI(1143)= 4050,
+  NRGRI(1144)= 4050,
+  NRGRI(1145)= 4050,
+  NRGRI(1146)= 4050,
+  NRGRI(1147)= 4050,
+  NRGRI(1148)= 4050,
+  NRGRI(1149)= 4050,
+  NRGRI(1150)= 4050,
+  NRGRI(1151)= 4050,
+  NRGRI(1152)= 4050,
+  NRGRI(1153)= 4050,
+  NRGRI(1154)= 4050,
+  NRGRI(1155)= 4050,
+  NRGRI(1156)= 4050,
+  NRGRI(1157)= 4050,
+  NRGRI(1158)= 4050,
+  NRGRI(1159)= 4050,
+  NRGRI(1160)= 4050,
+  NRGRI(1161)= 4050,
+  NRGRI(1162)= 4050,
+  NRGRI(1163)= 4050,
+  NRGRI(1164)= 4050,
+  NRGRI(1165)= 4050,
+  NRGRI(1166)= 4050,
+  NRGRI(1167)= 4050,
+  NRGRI(1168)= 4050,
+  NRGRI(1169)= 4050,
+  NRGRI(1170)= 4050,
+  NRGRI(1171)= 4050,
+  NRGRI(1172)= 4050,
+  NRGRI(1173)= 4050,
+  NRGRI(1174)= 4050,
+  NRGRI(1175)= 4050,
+  NRGRI(1176)= 4050,
+  NRGRI(1177)= 4050,
+  NRGRI(1178)= 4050,
+  NRGRI(1179)= 4050,
+  NRGRI(1180)= 4000,
+  NRGRI(1181)= 4000,
+  NRGRI(1182)= 4000,
+  NRGRI(1183)= 4000,
+  NRGRI(1184)= 4000,
+  NRGRI(1185)= 4000,
+  NRGRI(1186)= 4000,
+  NRGRI(1187)= 4000,
+  NRGRI(1188)= 4000,
+  NRGRI(1189)= 4000,
+  NRGRI(1190)= 4000,
+  NRGRI(1191)= 4000,
+  NRGRI(1192)= 4000,
+  NRGRI(1193)= 4000,
+  NRGRI(1194)= 4000,
+  NRGRI(1195)= 4000,
+  NRGRI(1196)= 4000,
+  NRGRI(1197)= 4000,
+  NRGRI(1198)= 4000,
+  NRGRI(1199)= 4000,
+  NRGRI(1200)= 4000,
+  NRGRI(1201)= 4000,
+  NRGRI(1202)= 4000,
+  NRGRI(1203)= 4000,
+  NRGRI(1204)= 4000,
+  NRGRI(1205)= 4000,
+  NRGRI(1206)= 4000,
+  NRGRI(1207)= 4000,
+  NRGRI(1208)= 4000,
+  NRGRI(1209)= 4000,
+  NRGRI(1210)= 4000,
+  NRGRI(1211)= 4000,
+  NRGRI(1212)= 4000,
+  NRGRI(1213)= 4000,
+  NRGRI(1214)= 4000,
+  NRGRI(1215)= 4000,
+  NRGRI(1216)= 4000,
+  NRGRI(1217)= 4000,
+  NRGRI(1218)= 4000,
+  NRGRI(1219)= 4000,
+  NRGRI(1220)= 4000,
+  NRGRI(1221)= 4000,
+  NRGRI(1222)= 4000,
+  NRGRI(1223)= 4000,
+  NRGRI(1224)= 4000,
+  NRGRI(1225)= 4000,
+  NRGRI(1226)= 4000,
+  NRGRI(1227)= 4000,
+  NRGRI(1228)= 4000,
+  NRGRI(1229)= 4000,
+  NRGRI(1230)= 4000,
+  NRGRI(1231)= 4000,
+  NRGRI(1232)= 4000,
+  NRGRI(1233)= 4000,
+  NRGRI(1234)= 4000,
+  NRGRI(1235)= 4000,
+  NRGRI(1236)= 4000,
+  NRGRI(1237)= 4000,
+  NRGRI(1238)= 4000,
+  NRGRI(1239)= 4000,
+  NRGRI(1240)= 4000,
+  NRGRI(1241)= 4000,
+  NRGRI(1242)= 4000,
+  NRGRI(1243)= 4000,
+  NRGRI(1244)= 4000,
+  NRGRI(1245)= 3888,
+  NRGRI(1246)= 3888,
+  NRGRI(1247)= 3888,
+  NRGRI(1248)= 3888,
+  NRGRI(1249)= 3888,
+  NRGRI(1250)= 3888,
+  NRGRI(1251)= 3888,
+  NRGRI(1252)= 3888,
+  NRGRI(1253)= 3888,
+  NRGRI(1254)= 3888,
+  NRGRI(1255)= 3888,
+  NRGRI(1256)= 3888,
+  NRGRI(1257)= 3888,
+  NRGRI(1258)= 3888,
+  NRGRI(1259)= 3888,
+  NRGRI(1260)= 3888,
+  NRGRI(1261)= 3888,
+  NRGRI(1262)= 3888,
+  NRGRI(1263)= 3888,
+  NRGRI(1264)= 3888,
+  NRGRI(1265)= 3888,
+  NRGRI(1266)= 3888,
+  NRGRI(1267)= 3840,
+  NRGRI(1268)= 3840,
+  NRGRI(1269)= 3840,
+  NRGRI(1270)= 3840,
+  NRGRI(1271)= 3840,
+  NRGRI(1272)= 3840,
+  NRGRI(1273)= 3840,
+  NRGRI(1274)= 3840,
+  NRGRI(1275)= 3840,
+  NRGRI(1276)= 3840,
+  NRGRI(1277)= 3840,
+  NRGRI(1278)= 3840,
+  NRGRI(1279)= 3840,
+  NRGRI(1280)= 3840,
+  NRGRI(1281)= 3840,
+  NRGRI(1282)= 3840,
+  NRGRI(1283)= 3840,
+  NRGRI(1284)= 3840,
+  NRGRI(1285)= 3840,
+  NRGRI(1286)= 3840,
+  NRGRI(1287)= 3840,
+  NRGRI(1288)= 3840,
+  NRGRI(1289)= 3840,
+  NRGRI(1290)= 3840,
+  NRGRI(1291)= 3840,
+  NRGRI(1292)= 3840,
+  NRGRI(1293)= 3840,
+  NRGRI(1294)= 3840,
+  NRGRI(1295)= 3840,
+  NRGRI(1296)= 3840,
+  NRGRI(1297)= 3840,
+  NRGRI(1298)= 3840,
+  NRGRI(1299)= 3840,
+  NRGRI(1300)= 3840,
+  NRGRI(1301)= 3840,
+  NRGRI(1302)= 3840,
+  NRGRI(1303)= 3840,
+  NRGRI(1304)= 3750,
+  NRGRI(1305)= 3750,
+  NRGRI(1306)= 3750,
+  NRGRI(1307)= 3750,
+  NRGRI(1308)= 3750,
+  NRGRI(1309)= 3750,
+  NRGRI(1310)= 3750,
+  NRGRI(1311)= 3750,
+  NRGRI(1312)= 3750,
+  NRGRI(1313)= 3750,
+  NRGRI(1314)= 3750,
+  NRGRI(1315)= 3750,
+  NRGRI(1316)= 3750,
+  NRGRI(1317)= 3750,
+  NRGRI(1318)= 3750,
+  NRGRI(1319)= 3750,
+  NRGRI(1320)= 3750,
+  NRGRI(1321)= 3750,
+  NRGRI(1322)= 3750,
+  NRGRI(1323)= 3750,
+  NRGRI(1324)= 3750,
+  NRGRI(1325)= 3750,
+  NRGRI(1326)= 3750,
+  NRGRI(1327)= 3750,
+  NRGRI(1328)= 3750,
+  NRGRI(1329)= 3750,
+  NRGRI(1330)= 3750,
+  NRGRI(1331)= 3750,
+  NRGRI(1332)= 3750,
+  NRGRI(1333)= 3750,
+  NRGRI(1334)= 3750,
+  NRGRI(1335)= 3750,
+  NRGRI(1336)= 3750,
+  NRGRI(1337)= 3750,
+  NRGRI(1338)= 3750,
+  NRGRI(1339)= 3750,
+  NRGRI(1340)= 3750,
+  NRGRI(1341)= 3750,
+  NRGRI(1342)= 3750,
+  NRGRI(1343)= 3645,
+  NRGRI(1344)= 3645,
+  NRGRI(1345)= 3645,
+  NRGRI(1346)= 3645,
+  NRGRI(1347)= 3645,
+  NRGRI(1348)= 3645,
+  NRGRI(1349)= 3645,
+  NRGRI(1350)= 3645,
+  NRGRI(1351)= 3645,
+  NRGRI(1352)= 3645,
+  NRGRI(1353)= 3645,
+  NRGRI(1354)= 3645,
+  NRGRI(1355)= 3645,
+  NRGRI(1356)= 3645,
+  NRGRI(1357)= 3645,
+  NRGRI(1358)= 3600,
+  NRGRI(1359)= 3600,
+  NRGRI(1360)= 3600,
+  NRGRI(1361)= 3600,
+  NRGRI(1362)= 3600,
+  NRGRI(1363)= 3600,
+  NRGRI(1364)= 3600,
+  NRGRI(1365)= 3600,
+  NRGRI(1366)= 3600,
+  NRGRI(1367)= 3600,
+  NRGRI(1368)= 3600,
+  NRGRI(1369)= 3600,
+  NRGRI(1370)= 3600,
+  NRGRI(1371)= 3600,
+  NRGRI(1372)= 3600,
+  NRGRI(1373)= 3600,
+  NRGRI(1374)= 3600,
+  NRGRI(1375)= 3600,
+  NRGRI(1376)= 3600,
+  NRGRI(1377)= 3600,
+  NRGRI(1378)= 3600,
+  NRGRI(1379)= 3600,
+  NRGRI(1380)= 3600,
+  NRGRI(1381)= 3600,
+  NRGRI(1382)= 3600,
+  NRGRI(1383)= 3600,
+  NRGRI(1384)= 3600,
+  NRGRI(1385)= 3600,
+  NRGRI(1386)= 3600,
+  NRGRI(1387)= 3600,
+  NRGRI(1388)= 3600,
+  NRGRI(1389)= 3600,
+  NRGRI(1390)= 3600,
+  NRGRI(1391)= 3600,
+  NRGRI(1392)= 3600,
+  NRGRI(1393)= 3600,
+  NRGRI(1394)= 3600,
+  NRGRI(1395)= 3600,
+  NRGRI(1396)= 3600,
+  NRGRI(1397)= 3600,
+  NRGRI(1398)= 3600,
+  NRGRI(1399)= 3600,
+  NRGRI(1400)= 3600,
+  NRGRI(1401)= 3600,
+  NRGRI(1402)= 3456,
+  NRGRI(1403)= 3456,
+  NRGRI(1404)= 3456,
+  NRGRI(1405)= 3456,
+  NRGRI(1406)= 3456,
+  NRGRI(1407)= 3456,
+  NRGRI(1408)= 3456,
+  NRGRI(1409)= 3456,
+  NRGRI(1410)= 3456,
+  NRGRI(1411)= 3456,
+  NRGRI(1412)= 3456,
+  NRGRI(1413)= 3456,
+  NRGRI(1414)= 3456,
+  NRGRI(1415)= 3456,
+  NRGRI(1416)= 3456,
+  NRGRI(1417)= 3456,
+  NRGRI(1418)= 3456,
+  NRGRI(1419)= 3456,
+  NRGRI(1420)= 3456,
+  NRGRI(1421)= 3456,
+  NRGRI(1422)= 3456,
+  NRGRI(1423)= 3456,
+  NRGRI(1424)= 3456,
+  NRGRI(1425)= 3375,
+  NRGRI(1426)= 3375,
+  NRGRI(1427)= 3375,
+  NRGRI(1428)= 3375,
+  NRGRI(1429)= 3375,
+  NRGRI(1430)= 3375,
+  NRGRI(1431)= 3375,
+  NRGRI(1432)= 3375,
+  NRGRI(1433)= 3375,
+  NRGRI(1434)= 3375,
+  NRGRI(1435)= 3375,
+  NRGRI(1436)= 3375,
+  NRGRI(1437)= 3375,
+  NRGRI(1438)= 3375,
+  NRGRI(1439)= 3375,
+  NRGRI(1440)= 3375,
+  NRGRI(1441)= 3375,
+  NRGRI(1442)= 3375,
+  NRGRI(1443)= 3375,
+  NRGRI(1444)= 3375,
+  NRGRI(1445)= 3375,
+  NRGRI(1446)= 3375,
+  NRGRI(1447)= 3375,
+  NRGRI(1448)= 3375,
+  NRGRI(1449)= 3375,
+  NRGRI(1450)= 3375,
+  NRGRI(1451)= 3375,
+  NRGRI(1452)= 3375,
+  NRGRI(1453)= 3375,
+  NRGRI(1454)= 3375,
+  NRGRI(1455)= 3375,
+  NRGRI(1456)= 3375,
+  NRGRI(1457)= 3375,
+  NRGRI(1458)= 3375,
+  NRGRI(1459)= 3375,
+  NRGRI(1460)= 3375,
+  NRGRI(1461)= 3240,
+  NRGRI(1462)= 3240,
+  NRGRI(1463)= 3240,
+  NRGRI(1464)= 3240,
+  NRGRI(1465)= 3240,
+  NRGRI(1466)= 3240,
+  NRGRI(1467)= 3240,
+  NRGRI(1468)= 3240,
+  NRGRI(1469)= 3240,
+  NRGRI(1470)= 3240,
+  NRGRI(1471)= 3200,
+  NRGRI(1472)= 3200,
+  NRGRI(1473)= 3200,
+  NRGRI(1474)= 3200,
+  NRGRI(1475)= 3200,
+  NRGRI(1476)= 3200,
+  NRGRI(1477)= 3200,
+  NRGRI(1478)= 3200,
+  NRGRI(1479)= 3200,
+  NRGRI(1480)= 3200,
+  NRGRI(1481)= 3200,
+  NRGRI(1482)= 3200,
+  NRGRI(1483)= 3200,
+  NRGRI(1484)= 3200,
+  NRGRI(1485)= 3200,
+  NRGRI(1486)= 3200,
+  NRGRI(1487)= 3200,
+  NRGRI(1488)= 3200,
+  NRGRI(1489)= 3125,
+  NRGRI(1490)= 3125,
+  NRGRI(1491)= 3125,
+  NRGRI(1492)= 3125,
+  NRGRI(1493)= 3125,
+  NRGRI(1494)= 3125,
+  NRGRI(1495)= 3125,
+  NRGRI(1496)= 3125,
+  NRGRI(1497)= 3125,
+  NRGRI(1498)= 3125,
+  NRGRI(1499)= 3125,
+  NRGRI(1500)= 3125,
+  NRGRI(1501)= 3125,
+  NRGRI(1502)= 3072,
+  NRGRI(1503)= 3072,
+  NRGRI(1504)= 3072,
+  NRGRI(1505)= 3072,
+  NRGRI(1506)= 3072,
+  NRGRI(1507)= 3072,
+  NRGRI(1508)= 3072,
+  NRGRI(1509)= 3072,
+  NRGRI(1510)= 3072,
+  NRGRI(1511)= 3072,
+  NRGRI(1512)= 3072,
+  NRGRI(1513)= 3072,
+  NRGRI(1514)= 3072,
+  NRGRI(1515)= 3072,
+  NRGRI(1516)= 3072,
+  NRGRI(1517)= 3072,
+  NRGRI(1518)= 3072,
+  NRGRI(1519)= 3000,
+  NRGRI(1520)= 3000,
+  NRGRI(1521)= 3000,
+  NRGRI(1522)= 3000,
+  NRGRI(1523)= 3000,
+  NRGRI(1524)= 3000,
+  NRGRI(1525)= 3000,
+  NRGRI(1526)= 3000,
+  NRGRI(1527)= 3000,
+  NRGRI(1528)= 3000,
+  NRGRI(1529)= 3000,
+  NRGRI(1530)= 3000,
+  NRGRI(1531)= 3000,
+  NRGRI(1532)= 3000,
+  NRGRI(1533)= 3000,
+  NRGRI(1534)= 3000,
+  NRGRI(1535)= 3000,
+  NRGRI(1536)= 3000,
+  NRGRI(1537)= 3000,
+  NRGRI(1538)= 2916,
+  NRGRI(1539)= 2916,
+  NRGRI(1540)= 2916,
+  NRGRI(1541)= 2916,
+  NRGRI(1542)= 2916,
+  NRGRI(1543)= 2916,
+  NRGRI(1544)= 2916,
+  NRGRI(1545)= 2916,
+  NRGRI(1546)= 2880,
+  NRGRI(1547)= 2880,
+  NRGRI(1548)= 2880,
+  NRGRI(1549)= 2880,
+  NRGRI(1550)= 2880,
+  NRGRI(1551)= 2880,
+  NRGRI(1552)= 2880,
+  NRGRI(1553)= 2880,
+  NRGRI(1554)= 2880,
+  NRGRI(1555)= 2880,
+  NRGRI(1556)= 2880,
+  NRGRI(1557)= 2880,
+  NRGRI(1558)= 2880,
+  NRGRI(1559)= 2880,
+  NRGRI(1560)= 2880,
+  NRGRI(1561)= 2880,
+  NRGRI(1562)= 2880,
+  NRGRI(1563)= 2880,
+  NRGRI(1564)= 2880,
+  NRGRI(1565)= 2880,
+  NRGRI(1566)= 2880,
+  NRGRI(1567)= 2880,
+  NRGRI(1568)= 2880,
+  NRGRI(1569)= 2880,
+  NRGRI(1570)= 2880,
+  NRGRI(1571)= 2880,
+  NRGRI(1572)= 2880,
+  NRGRI(1573)= 2880,
+  NRGRI(1574)= 2880,
+  NRGRI(1575)= 2880,
+  NRGRI(1576)= 2880,
+  NRGRI(1577)= 2880,
+  NRGRI(1578)= 2880,
+  NRGRI(1579)= 2880,
+  NRGRI(1580)= 2880,
+  NRGRI(1581)= 2880,
+  NRGRI(1582)= 2880,
+  NRGRI(1583)= 2880,
+  NRGRI(1584)= 2880,
+  NRGRI(1585)= 2700,
+  NRGRI(1586)= 2700,
+  NRGRI(1587)= 2700,
+  NRGRI(1588)= 2700,
+  NRGRI(1589)= 2700,
+  NRGRI(1590)= 2700,
+  NRGRI(1591)= 2700,
+  NRGRI(1592)= 2700,
+  NRGRI(1593)= 2700,
+  NRGRI(1594)= 2700,
+  NRGRI(1595)= 2700,
+  NRGRI(1596)= 2700,
+  NRGRI(1597)= 2700,
+  NRGRI(1598)= 2700,
+  NRGRI(1599)= 2700,
+  NRGRI(1600)= 2700,
+  NRGRI(1601)= 2700,
+  NRGRI(1602)= 2700,
+  NRGRI(1603)= 2700,
+  NRGRI(1604)= 2700,
+  NRGRI(1605)= 2700,
+  NRGRI(1606)= 2700,
+  NRGRI(1607)= 2592,
+  NRGRI(1608)= 2592,
+  NRGRI(1609)= 2592,
+  NRGRI(1610)= 2592,
+  NRGRI(1611)= 2592,
+  NRGRI(1612)= 2592,
+  NRGRI(1613)= 2560,
+  NRGRI(1614)= 2560,
+  NRGRI(1615)= 2560,
+  NRGRI(1616)= 2560,
+  NRGRI(1617)= 2560,
+  NRGRI(1618)= 2560,
+  NRGRI(1619)= 2560,
+  NRGRI(1620)= 2560,
+  NRGRI(1621)= 2560,
+  NRGRI(1622)= 2560,
+  NRGRI(1623)= 2560,
+  NRGRI(1624)= 2560,
+  NRGRI(1625)= 2500,
+  NRGRI(1626)= 2500,
+  NRGRI(1627)= 2500,
+  NRGRI(1628)= 2500,
+  NRGRI(1629)= 2500,
+  NRGRI(1630)= 2500,
+  NRGRI(1631)= 2500,
+  NRGRI(1632)= 2500,
+  NRGRI(1633)= 2500,
+  NRGRI(1634)= 2500,
+  NRGRI(1635)= 2500,
+  NRGRI(1636)= 2500,
+  NRGRI(1637)= 2500,
+  NRGRI(1638)= 2500,
+  NRGRI(1639)= 2500,
+  NRGRI(1640)= 2430,
+  NRGRI(1641)= 2430,
+  NRGRI(1642)= 2430,
+  NRGRI(1643)= 2430,
+  NRGRI(1644)= 2430,
+  NRGRI(1645)= 2400,
+  NRGRI(1646)= 2400,
+  NRGRI(1647)= 2400,
+  NRGRI(1648)= 2400,
+  NRGRI(1649)= 2400,
+  NRGRI(1650)= 2400,
+  NRGRI(1651)= 2400,
+  NRGRI(1652)= 2400,
+  NRGRI(1653)= 2400,
+  NRGRI(1654)= 2400,
+  NRGRI(1655)= 2400,
+  NRGRI(1656)= 2400,
+  NRGRI(1657)= 2400,
+  NRGRI(1658)= 2400,
+  NRGRI(1659)= 2400,
+  NRGRI(1660)= 2400,
+  NRGRI(1661)= 2400,
+  NRGRI(1662)= 2400,
+  NRGRI(1663)= 2400,
+  NRGRI(1664)= 2304,
+  NRGRI(1665)= 2304,
+  NRGRI(1666)= 2304,
+  NRGRI(1667)= 2304,
+  NRGRI(1668)= 2304,
+  NRGRI(1669)= 2304,
+  NRGRI(1670)= 2304,
+  NRGRI(1671)= 2304,
+  NRGRI(1672)= 2304,
+  NRGRI(1673)= 2304,
+  NRGRI(1674)= 2250,
+  NRGRI(1675)= 2250,
+  NRGRI(1676)= 2250,
+  NRGRI(1677)= 2250,
+  NRGRI(1678)= 2250,
+  NRGRI(1679)= 2250,
+  NRGRI(1680)= 2250,
+  NRGRI(1681)= 2250,
+  NRGRI(1682)= 2250,
+  NRGRI(1683)= 2250,
+  NRGRI(1684)= 2250,
+  NRGRI(1685)= 2250,
+  NRGRI(1686)= 2187,
+  NRGRI(1687)= 2187,
+  NRGRI(1688)= 2187,
+  NRGRI(1689)= 2187,
+  NRGRI(1690)= 2187,
+  NRGRI(1691)= 2160,
+  NRGRI(1692)= 2160,
+  NRGRI(1693)= 2160,
+  NRGRI(1694)= 2160,
+  NRGRI(1695)= 2160,
+  NRGRI(1696)= 2160,
+  NRGRI(1697)= 2160,
+  NRGRI(1698)= 2160,
+  NRGRI(1699)= 2160,
+  NRGRI(1700)= 2160,
+  NRGRI(1701)= 2160,
+  NRGRI(1702)= 2160,
+  NRGRI(1703)= 2160,
+  NRGRI(1704)= 2160,
+  NRGRI(1705)= 2160,
+  NRGRI(1706)= 2160,
+  NRGRI(1707)= 2160,
+  NRGRI(1708)= 2160,
+  NRGRI(1709)= 2160,
+  NRGRI(1710)= 2160,
+  NRGRI(1711)= 2048,
+  NRGRI(1712)= 2048,
+  NRGRI(1713)= 2048,
+  NRGRI(1714)= 2048,
+  NRGRI(1715)= 2048,
+  NRGRI(1716)= 2025,
+  NRGRI(1717)= 2025,
+  NRGRI(1718)= 2025,
+  NRGRI(1719)= 2025,
+  NRGRI(1720)= 2000,
+  NRGRI(1721)= 2000,
+  NRGRI(1722)= 2000,
+  NRGRI(1723)= 2000,
+  NRGRI(1724)= 2000,
+  NRGRI(1725)= 2000,
+  NRGRI(1726)= 2000,
+  NRGRI(1727)= 2000,
+  NRGRI(1728)= 2000,
+  NRGRI(1729)= 2000,
+  NRGRI(1730)= 1944,
+  NRGRI(1731)= 1944,
+  NRGRI(1732)= 1944,
+  NRGRI(1733)= 1944,
+  NRGRI(1734)= 1944,
+  NRGRI(1735)= 1920,
+  NRGRI(1736)= 1920,
+  NRGRI(1737)= 1920,
+  NRGRI(1738)= 1920,
+  NRGRI(1739)= 1920,
+  NRGRI(1740)= 1920,
+  NRGRI(1741)= 1920,
+  NRGRI(1742)= 1920,
+  NRGRI(1743)= 1875,
+  NRGRI(1744)= 1875,
+  NRGRI(1745)= 1875,
+  NRGRI(1746)= 1875,
+  NRGRI(1747)= 1875,
+  NRGRI(1748)= 1875,
+  NRGRI(1749)= 1875,
+  NRGRI(1750)= 1875,
+  NRGRI(1751)= 1875,
+  NRGRI(1752)= 1875,
+  NRGRI(1753)= 1875,
+  NRGRI(1754)= 1875,
+  NRGRI(1755)= 1875,
+  NRGRI(1756)= 1800,
+  NRGRI(1757)= 1800,
+  NRGRI(1758)= 1800,
+  NRGRI(1759)= 1800,
+  NRGRI(1760)= 1800,
+  NRGRI(1761)= 1800,
+  NRGRI(1762)= 1800,
+  NRGRI(1763)= 1800,
+  NRGRI(1764)= 1800,
+  NRGRI(1765)= 1800,
+  NRGRI(1766)= 1800,
+  NRGRI(1767)= 1800,
+  NRGRI(1768)= 1728,
+  NRGRI(1769)= 1728,
+  NRGRI(1770)= 1728,
+  NRGRI(1771)= 1728,
+  NRGRI(1772)= 1728,
+  NRGRI(1773)= 1728,
+  NRGRI(1774)= 1728,
+  NRGRI(1775)= 1728,
+  NRGRI(1776)= 1728,
+  NRGRI(1777)= 1728,
+  NRGRI(1778)= 1728,
+  NRGRI(1779)= 1728,
+  NRGRI(1780)= 1728,
+  NRGRI(1781)= 1728,
+  NRGRI(1782)= 1728,
+  NRGRI(1783)= 1728,
+  NRGRI(1784)= 1728,
+  NRGRI(1785)= 1728,
+  NRGRI(1786)= 1728,
+  NRGRI(1787)= 1620,
+  NRGRI(1788)= 1620,
+  NRGRI(1789)= 1620,
+  NRGRI(1790)= 1600,
+  NRGRI(1791)= 1600,
+  NRGRI(1792)= 1600,
+  NRGRI(1793)= 1600,
+  NRGRI(1794)= 1600,
+  NRGRI(1795)= 1600,
+  NRGRI(1796)= 1600,
+  NRGRI(1797)= 1600,
+  NRGRI(1798)= 1600,
+  NRGRI(1799)= 1600,
+  NRGRI(1800)= 1600,
+  NRGRI(1801)= 1536,
+  NRGRI(1802)= 1536,
+  NRGRI(1803)= 1536,
+  NRGRI(1804)= 1536,
+  NRGRI(1805)= 1536,
+  NRGRI(1806)= 1536,
+  NRGRI(1807)= 1500,
+  NRGRI(1808)= 1500,
+  NRGRI(1809)= 1500,
+  NRGRI(1810)= 1500,
+  NRGRI(1811)= 1500,
+  NRGRI(1812)= 1500,
+  NRGRI(1813)= 1500,
+  NRGRI(1814)= 1500,
+  NRGRI(1815)= 1458,
+  NRGRI(1816)= 1458,
+  NRGRI(1817)= 1458,
+  NRGRI(1818)= 1440,
+  NRGRI(1819)= 1440,
+  NRGRI(1820)= 1440,
+  NRGRI(1821)= 1440,
+  NRGRI(1822)= 1440,
+  NRGRI(1823)= 1440,
+  NRGRI(1824)= 1440,
+  NRGRI(1825)= 1440,
+  NRGRI(1826)= 1440,
+  NRGRI(1827)= 1440,
+  NRGRI(1828)= 1440,
+  NRGRI(1829)= 1440,
+  NRGRI(1830)= 1440,
+  NRGRI(1831)= 1440,
+  NRGRI(1832)= 1440,
+  NRGRI(1833)= 1350,
+  NRGRI(1834)= 1350,
+  NRGRI(1835)= 1350,
+  NRGRI(1836)= 1350,
+  NRGRI(1837)= 1350,
+  NRGRI(1838)= 1350,
+  NRGRI(1839)= 1350,
+  NRGRI(1840)= 1350,
+  NRGRI(1841)= 1350,
+  NRGRI(1842)= 1296,
+  NRGRI(1843)= 1296,
+  NRGRI(1844)= 1280,
+  NRGRI(1845)= 1280,
+  NRGRI(1846)= 1280,
+  NRGRI(1847)= 1280,
+  NRGRI(1848)= 1280,
+  NRGRI(1849)= 1280,
+  NRGRI(1850)= 1280,
+  NRGRI(1851)= 1280,
+  NRGRI(1852)= 1280,
+  NRGRI(1853)= 1280,
+  NRGRI(1854)= 1280,
+  NRGRI(1855)= 1215,
+  NRGRI(1856)= 1215,
+  NRGRI(1857)= 1215,
+  NRGRI(1858)= 1200,
+  NRGRI(1859)= 1200,
+  NRGRI(1860)= 1200,
+  NRGRI(1861)= 1200,
+  NRGRI(1862)= 1200,
+  NRGRI(1863)= 1200,
+  NRGRI(1864)= 1200,
+  NRGRI(1865)= 1152,
+  NRGRI(1866)= 1152,
+  NRGRI(1867)= 1152,
+  NRGRI(1868)= 1152,
+  NRGRI(1869)= 1152,
+  NRGRI(1870)= 1125,
+  NRGRI(1871)= 1125,
+  NRGRI(1872)= 1125,
+  NRGRI(1873)= 1125,
+  NRGRI(1874)= 1125,
+  NRGRI(1875)= 1125,
+  NRGRI(1876)= 1125,
+  NRGRI(1877)= 1080,
+  NRGRI(1878)= 1080,
+  NRGRI(1879)= 1080,
+  NRGRI(1880)= 1080,
+  NRGRI(1881)= 1080,
+  NRGRI(1882)= 1080,
+  NRGRI(1883)= 1080,
+  NRGRI(1884)= 1080,
+  NRGRI(1885)= 1080,
+  NRGRI(1886)= 1024,
+  NRGRI(1887)= 1024,
+  NRGRI(1888)= 1024,
+  NRGRI(1889)= 1024,
+  NRGRI(1890)= 1000,
+  NRGRI(1891)= 1000,
+  NRGRI(1892)= 1000,
+  NRGRI(1893)= 1000,
+  NRGRI(1894)= 1000,
+  NRGRI(1895)=  972,
+  NRGRI(1896)=  972,
+  NRGRI(1897)=  960,
+  NRGRI(1898)=  960,
+  NRGRI(1899)=  960,
+  NRGRI(1900)=  960,
+  NRGRI(1901)=  960,
+  NRGRI(1902)=  960,
+  NRGRI(1903)=  960,
+  NRGRI(1904)=  960,
+  NRGRI(1905)=  960,
+  NRGRI(1906)=  900,
+  NRGRI(1907)=  900,
+  NRGRI(1908)=  900,
+  NRGRI(1909)=  900,
+  NRGRI(1910)=  900,
+  NRGRI(1911)=  900,
+  NRGRI(1912)=  864,
+  NRGRI(1913)=  864,
+  NRGRI(1914)=  864,
+  NRGRI(1915)=  864,
+  NRGRI(1916)=  864,
+  NRGRI(1917)=  864,
+  NRGRI(1918)=  864,
+  NRGRI(1919)=  864,
+  NRGRI(1920)=  864,
+  NRGRI(1921)=  810,
+  NRGRI(1922)=  800,
+  NRGRI(1923)=  800,
+  NRGRI(1924)=  800,
+  NRGRI(1925)=  800,
+  NRGRI(1926)=  800,
+  NRGRI(1927)=  800,
+  NRGRI(1928)=  768,
+  NRGRI(1929)=  768,
+  NRGRI(1930)=  750,
+  NRGRI(1931)=  750,
+  NRGRI(1932)=  750,
+  NRGRI(1933)=  750,
+  NRGRI(1934)=  729,
+  NRGRI(1935)=  720,
+  NRGRI(1936)=  720,
+  NRGRI(1937)=  720,
+  NRGRI(1938)=  720,
+  NRGRI(1939)=  720,
+  NRGRI(1940)=  720,
+  NRGRI(1941)=  720,
+  NRGRI(1942)=  675,
+  NRGRI(1943)=  675,
+  NRGRI(1944)=  675,
+  NRGRI(1945)=  675,
+  NRGRI(1946)=  675,
+  NRGRI(1947)=  648,
+  NRGRI(1948)=  640,
+  NRGRI(1949)=  640,
+  NRGRI(1950)=  640,
+  NRGRI(1951)=  640,
+  NRGRI(1952)=  640,
+  NRGRI(1953)=  640,
+  NRGRI(1954)=  600,
+  NRGRI(1955)=  600,
+  NRGRI(1956)=  600,
+  NRGRI(1957)=  600,
+  NRGRI(1958)=  576,
+  NRGRI(1959)=  576,
+  NRGRI(1960)=  576,
+  NRGRI(1961)=  576,
+  NRGRI(1962)=  576,
+  NRGRI(1963)=  576,
+  NRGRI(1964)=  540,
+  NRGRI(1965)=  540,
+  NRGRI(1966)=  540,
+  NRGRI(1967)=  540,
+  NRGRI(1968)=  512,
+  NRGRI(1969)=  512,
+  NRGRI(1970)=  500,
+  NRGRI(1971)=  500,
+  NRGRI(1972)=  486,
+  NRGRI(1973)=  480,
+  NRGRI(1974)=  480,
+  NRGRI(1975)=  480,
+  NRGRI(1976)=  480,
+  NRGRI(1977)=  480,
+  NRGRI(1978)=  450,
+  NRGRI(1979)=  450,
+  NRGRI(1980)=  450,
+  NRGRI(1981)=  432,
+  NRGRI(1982)=  432,
+  NRGRI(1983)=  432,
+  NRGRI(1984)=  432,
+  NRGRI(1985)=  405,
+  NRGRI(1986)=  400,
+  NRGRI(1987)=  400,
+  NRGRI(1988)=  384,
+  NRGRI(1989)=  384,
+  NRGRI(1990)=  375,
+  NRGRI(1991)=  375,
+  NRGRI(1992)=  360,
+  NRGRI(1993)=  360,
+  NRGRI(1994)=  360,
+  NRGRI(1995)=  360,
+  NRGRI(1996)=  360,
+  NRGRI(1997)=  360,
+  NRGRI(1998)=  320,
+  NRGRI(1999)=  320,
+  NRGRI(2000)=  320,
+  NRGRI(2001)=  300,
+  NRGRI(2002)=  300,
+  NRGRI(2003)=  288,
+  NRGRI(2004)=  288,
+  NRGRI(2005)=  288,
+  NRGRI(2006)=  270,
+  NRGRI(2007)=  270,
+  NRGRI(2008)=  256,
+  NRGRI(2009)=  250,
+  NRGRI(2010)=  243,
+  NRGRI(2011)=  240,
+  NRGRI(2012)=  240,
+  NRGRI(2013)=  225,
+  NRGRI(2014)=  225,
+  NRGRI(2015)=  216,
+  NRGRI(2016)=  216,
+  NRGRI(2017)=  200,
+  NRGRI(2018)=  192,
+  NRGRI(2019)=  192,
+  NRGRI(2020)=  180,
+  NRGRI(2021)=  180,
+  NRGRI(2022)=  180,
+  NRGRI(2023)=  160,
+  NRGRI(2024)=  160,
+  NRGRI(2025)=  150,
+  NRGRI(2026)=  144,
+  NRGRI(2027)=  135,
+  NRGRI(2028)=  125,
+  NRGRI(2029)=  120,
+  NRGRI(2030)=  120,
+  NRGRI(2031)=  120,
+  NRGRI(2032)=  108,
+  NRGRI(2033)=  100,
+  NRGRI(2034)=   96,
+  NRGRI(2035)=   90,
+  NRGRI(2036)=   90,
+  NRGRI(2037)=   80,
+  NRGRI(2038)=   75,
+  NRGRI(2039)=   72,
+  NRGRI(2040)=   72,
+  NRGRI(2041)=   60,
+  NRGRI(2042)=   54,
+  NRGRI(2043)=   50,
+  NRGRI(2044)=   45,
+  NRGRI(2045)=   40,
+  NRGRI(2046)=   32,
+  NRGRI(2047)=   25,
+  NRGRI(2048)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2215 b/odb/share/odb/rtablel_2215
new file mode 100644
index 0000000..3319f93
--- /dev/null
+++ b/odb/share/odb/rtablel_2215
@@ -0,0 +1,218 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   36,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   64,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   80,
+  NRGRI(0012)=   90,
+  NRGRI(0013)=   96,
+  NRGRI(0014)=  100,
+  NRGRI(0015)=  108,
+  NRGRI(0016)=  120,
+  NRGRI(0017)=  120,
+  NRGRI(0018)=  125,
+  NRGRI(0019)=  135,
+  NRGRI(0020)=  144,
+  NRGRI(0021)=  144,
+  NRGRI(0022)=  150,
+  NRGRI(0023)=  160,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  180,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  192,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  200,
+  NRGRI(0031)=  216,
+  NRGRI(0032)=  216,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  225,
+  NRGRI(0035)=  240,
+  NRGRI(0036)=  240,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  243,
+  NRGRI(0039)=  250,
+  NRGRI(0040)=  256,
+  NRGRI(0041)=  256,
+  NRGRI(0042)=  270,
+  NRGRI(0043)=  270,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  288,
+  NRGRI(0046)=  288,
+  NRGRI(0047)=  300,
+  NRGRI(0048)=  300,
+  NRGRI(0049)=  300,
+  NRGRI(0050)=  320,
+  NRGRI(0051)=  320,
+  NRGRI(0052)=  320,
+  NRGRI(0053)=  320,
+  NRGRI(0054)=  324,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  360,
+  NRGRI(0058)=  360,
+  NRGRI(0059)=  360,
+  NRGRI(0060)=  360,
+  NRGRI(0061)=  360,
+  NRGRI(0062)=  360,
+  NRGRI(0063)=  360,
+  NRGRI(0064)=  375,
+  NRGRI(0065)=  375,
+  NRGRI(0066)=  375,
+  NRGRI(0067)=  375,
+  NRGRI(0068)=  384,
+  NRGRI(0069)=  384,
+  NRGRI(0070)=  384,
+  NRGRI(0071)=  400,
+  NRGRI(0072)=  400,
+  NRGRI(0073)=  400,
+  NRGRI(0074)=  400,
+  NRGRI(0075)=  400,
+  NRGRI(0076)=  400,
+  NRGRI(0077)=  405,
+  NRGRI(0078)=  432,
+  NRGRI(0079)=  432,
+  NRGRI(0080)=  432,
+  NRGRI(0081)=  432,
+  NRGRI(0082)=  432,
+  NRGRI(0083)=  432,
+  NRGRI(0084)=  432,
+  NRGRI(0085)=  432,
+  NRGRI(0086)=  432,
+  NRGRI(0087)=  432,
+  NRGRI(0088)=  432,
+  NRGRI(0089)=  432,
+  NRGRI(0090)=  432,
+  NRGRI(0091)=  432,
+  NRGRI(0092)=  432,
+  NRGRI(0093)=  432,
+  NRGRI(0094)=  432,
+  NRGRI(0095)=  432,
+  NRGRI(0096)=  432,
+  NRGRI(0097)=  432,
+  NRGRI(0098)=  432,
+  NRGRI(0099)=  432,
+  NRGRI(0100)=  432,
+  NRGRI(0101)=  432,
+  NRGRI(0102)=  432,
+  NRGRI(0103)=  432,
+  NRGRI(0104)=  432,
+  NRGRI(0105)=  432,
+  NRGRI(0106)=  432,
+  NRGRI(0107)=  432,
+  NRGRI(0108)=  432,
+  NRGRI(0109)=  432,
+  NRGRI(0110)=  432,
+  NRGRI(0111)=  432,
+  NRGRI(0112)=  432,
+  NRGRI(0113)=  432,
+  NRGRI(0114)=  432,
+  NRGRI(0115)=  432,
+  NRGRI(0116)=  432,
+  NRGRI(0117)=  432,
+  NRGRI(0118)=  432,
+  NRGRI(0119)=  432,
+  NRGRI(0120)=  432,
+  NRGRI(0121)=  432,
+  NRGRI(0122)=  432,
+  NRGRI(0123)=  432,
+  NRGRI(0124)=  432,
+  NRGRI(0125)=  432,
+  NRGRI(0126)=  432,
+  NRGRI(0127)=  432,
+  NRGRI(0128)=  432,
+  NRGRI(0129)=  432,
+  NRGRI(0130)=  432,
+  NRGRI(0131)=  432,
+  NRGRI(0132)=  432,
+  NRGRI(0133)=  432,
+  NRGRI(0134)=  432,
+  NRGRI(0135)=  432,
+  NRGRI(0136)=  432,
+  NRGRI(0137)=  432,
+  NRGRI(0138)=  432,
+  NRGRI(0139)=  432,
+  NRGRI(0140)=  405,
+  NRGRI(0141)=  400,
+  NRGRI(0142)=  400,
+  NRGRI(0143)=  400,
+  NRGRI(0144)=  400,
+  NRGRI(0145)=  400,
+  NRGRI(0146)=  400,
+  NRGRI(0147)=  384,
+  NRGRI(0148)=  384,
+  NRGRI(0149)=  384,
+  NRGRI(0150)=  375,
+  NRGRI(0151)=  375,
+  NRGRI(0152)=  375,
+  NRGRI(0153)=  375,
+  NRGRI(0154)=  360,
+  NRGRI(0155)=  360,
+  NRGRI(0156)=  360,
+  NRGRI(0157)=  360,
+  NRGRI(0158)=  360,
+  NRGRI(0159)=  360,
+  NRGRI(0160)=  360,
+  NRGRI(0161)=  360,
+  NRGRI(0162)=  360,
+  NRGRI(0163)=  324,
+  NRGRI(0164)=  320,
+  NRGRI(0165)=  320,
+  NRGRI(0166)=  320,
+  NRGRI(0167)=  320,
+  NRGRI(0168)=  300,
+  NRGRI(0169)=  300,
+  NRGRI(0170)=  300,
+  NRGRI(0171)=  288,
+  NRGRI(0172)=  288,
+  NRGRI(0173)=  288,
+  NRGRI(0174)=  270,
+  NRGRI(0175)=  270,
+  NRGRI(0176)=  256,
+  NRGRI(0177)=  256,
+  NRGRI(0178)=  250,
+  NRGRI(0179)=  243,
+  NRGRI(0180)=  240,
+  NRGRI(0181)=  240,
+  NRGRI(0182)=  240,
+  NRGRI(0183)=  225,
+  NRGRI(0184)=  216,
+  NRGRI(0185)=  216,
+  NRGRI(0186)=  216,
+  NRGRI(0187)=  200,
+  NRGRI(0188)=  192,
+  NRGRI(0189)=  192,
+  NRGRI(0190)=  180,
+  NRGRI(0191)=  180,
+  NRGRI(0192)=  180,
+  NRGRI(0193)=  160,
+  NRGRI(0194)=  160,
+  NRGRI(0195)=  150,
+  NRGRI(0196)=  144,
+  NRGRI(0197)=  144,
+  NRGRI(0198)=  135,
+  NRGRI(0199)=  125,
+  NRGRI(0200)=  120,
+  NRGRI(0201)=  120,
+  NRGRI(0202)=  108,
+  NRGRI(0203)=  100,
+  NRGRI(0204)=   96,
+  NRGRI(0205)=   90,
+  NRGRI(0206)=   80,
+  NRGRI(0207)=   72,
+  NRGRI(0208)=   72,
+  NRGRI(0209)=   64,
+  NRGRI(0210)=   60,
+  NRGRI(0211)=   50,
+  NRGRI(0212)=   45,
+  NRGRI(0213)=   40,
+  NRGRI(0214)=   36,
+  NRGRI(0215)=   25,
+  NRGRI(0216)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2255 b/odb/share/odb/rtablel_2255
new file mode 100644
index 0000000..62e9359
--- /dev/null
+++ b/odb/share/odb/rtablel_2255
@@ -0,0 +1,258 @@
+ &NAMRGRI
+  NRGRI(1)=   18,
+  NRGRI(2)=   25,
+  NRGRI(3)=   36,
+  NRGRI(4)=   40,
+  NRGRI(5)=   45,
+  NRGRI(6)=   50,
+  NRGRI(7)=   60,
+  NRGRI(8)=   64,
+  NRGRI(9)=   72,
+  NRGRI(10)=   72,
+  NRGRI(11)=   80,
+  NRGRI(12)=   90,
+  NRGRI(13)=   90,
+  NRGRI(14)=  100,
+  NRGRI(15)=  108,
+  NRGRI(16)=  120,
+  NRGRI(17)=  120,
+  NRGRI(18)=  125,
+  NRGRI(19)=  128,
+  NRGRI(20)=  144,
+  NRGRI(21)=  144,
+  NRGRI(22)=  150,
+  NRGRI(23)=  160,
+  NRGRI(24)=  160,
+  NRGRI(25)=  180,
+  NRGRI(26)=  180,
+  NRGRI(27)=  180,
+  NRGRI(28)=  192,
+  NRGRI(29)=  192,
+  NRGRI(30)=  200,
+  NRGRI(31)=  216,
+  NRGRI(32)=  216,
+  NRGRI(33)=  216,
+  NRGRI(34)=  225,
+  NRGRI(35)=  240,
+  NRGRI(36)=  240,
+  NRGRI(37)=  240,
+  NRGRI(38)=  250,
+  NRGRI(39)=  250,
+  NRGRI(40)=  256,
+  NRGRI(41)=  270,
+  NRGRI(42)=  270,
+  NRGRI(43)=  288,
+  NRGRI(44)=  288,
+  NRGRI(45)=  288,
+  NRGRI(46)=  300,
+  NRGRI(47)=  300,
+  NRGRI(48)=  320,
+  NRGRI(49)=  320,
+  NRGRI(50)=  320,
+  NRGRI(51)=  320,
+  NRGRI(52)=  324,
+  NRGRI(53)=  360,
+  NRGRI(54)=  360,
+  NRGRI(55)=  360,
+  NRGRI(56)=  360,
+  NRGRI(57)=  360,
+  NRGRI(58)=  360,
+  NRGRI(59)=  360,
+  NRGRI(60)=  375,
+  NRGRI(61)=  375,
+  NRGRI(62)=  375,
+  NRGRI(63)=  375,
+  NRGRI(64)=  384,
+  NRGRI(65)=  384,
+  NRGRI(66)=  400,
+  NRGRI(67)=  400,
+  NRGRI(68)=  400,
+  NRGRI(69)=  400,
+  NRGRI(70)=  405,
+  NRGRI(71)=  432,
+  NRGRI(72)=  432,
+  NRGRI(73)=  432,
+  NRGRI(74)=  432,
+  NRGRI(75)=  432,
+  NRGRI(76)=  432,
+  NRGRI(77)=  432,
+  NRGRI(78)=  450,
+  NRGRI(79)=  450,
+  NRGRI(80)=  450,
+  NRGRI(81)=  450,
+  NRGRI(82)=  450,
+  NRGRI(83)=  480,
+  NRGRI(84)=  480,
+  NRGRI(85)=  480,
+  NRGRI(86)=  480,
+  NRGRI(87)=  480,
+  NRGRI(88)=  480,
+  NRGRI(89)=  480,
+  NRGRI(90)=  480,
+  NRGRI(91)=  480,
+  NRGRI(92)=  480,
+  NRGRI(93)=  486,
+  NRGRI(94)=  486,
+  NRGRI(95)=  486,
+  NRGRI(96)=  500,
+  NRGRI(97)=  500,
+  NRGRI(98)=  500,
+  NRGRI(99)=  500,
+  NRGRI(100)=  500,
+  NRGRI(101)=  500,
+  NRGRI(102)=  500,
+  NRGRI(103)=  512,
+  NRGRI(104)=  512,
+  NRGRI(105)=  512,
+  NRGRI(106)=  512,
+  NRGRI(107)=  512,
+  NRGRI(108)=  512,
+  NRGRI(109)=  512,
+  NRGRI(110)=  512,
+  NRGRI(111)=  512,
+  NRGRI(112)=  512,
+  NRGRI(113)=  512,
+  NRGRI(114)=  512,
+  NRGRI(115)=  512,
+  NRGRI(116)=  512,
+  NRGRI(117)=  512,
+  NRGRI(118)=  512,
+  NRGRI(119)=  512,
+  NRGRI(120)=  512,
+  NRGRI(121)=  512,
+  NRGRI(122)=  512,
+  NRGRI(123)=  512,
+  NRGRI(124)=  512,
+  NRGRI(125)=  512,
+  NRGRI(126)=  512,
+  NRGRI(127)=  512,
+  NRGRI(128)=  512,
+  NRGRI(129)=  512,
+  NRGRI(130)=  512,
+  NRGRI(131)=  512,
+  NRGRI(132)=  512,
+  NRGRI(133)=  512,
+  NRGRI(134)=  512,
+  NRGRI(135)=  512,
+  NRGRI(136)=  512,
+  NRGRI(137)=  512,
+  NRGRI(138)=  512,
+  NRGRI(139)=  512,
+  NRGRI(140)=  512,
+  NRGRI(141)=  512,
+  NRGRI(142)=  512,
+  NRGRI(143)=  512,
+  NRGRI(144)=  512,
+  NRGRI(145)=  512,
+  NRGRI(146)=  512,
+  NRGRI(147)=  512,
+  NRGRI(148)=  512,
+  NRGRI(149)=  512,
+  NRGRI(150)=  512,
+  NRGRI(151)=  512,
+  NRGRI(152)=  512,
+  NRGRI(153)=  512,
+  NRGRI(154)=  512,
+  NRGRI(155)=  500,
+  NRGRI(156)=  500,
+  NRGRI(157)=  500,
+  NRGRI(158)=  500,
+  NRGRI(159)=  500,
+  NRGRI(160)=  500,
+  NRGRI(161)=  500,
+  NRGRI(162)=  486,
+  NRGRI(163)=  486,
+  NRGRI(164)=  486,
+  NRGRI(165)=  480,
+  NRGRI(166)=  480,
+  NRGRI(167)=  480,
+  NRGRI(168)=  480,
+  NRGRI(169)=  480,
+  NRGRI(170)=  480,
+  NRGRI(171)=  480,
+  NRGRI(172)=  480,
+  NRGRI(173)=  480,
+  NRGRI(174)=  480,
+  NRGRI(175)=  450,
+  NRGRI(176)=  450,
+  NRGRI(177)=  450,
+  NRGRI(178)=  450,
+  NRGRI(179)=  450,
+  NRGRI(180)=  432,
+  NRGRI(181)=  432,
+  NRGRI(182)=  432,
+  NRGRI(183)=  432,
+  NRGRI(184)=  432,
+  NRGRI(185)=  432,
+  NRGRI(186)=  432,
+  NRGRI(187)=  405,
+  NRGRI(188)=  400,
+  NRGRI(189)=  400,
+  NRGRI(190)=  400,
+  NRGRI(191)=  400,
+  NRGRI(192)=  384,
+  NRGRI(193)=  384,
+  NRGRI(194)=  375,
+  NRGRI(195)=  375,
+  NRGRI(196)=  375,
+  NRGRI(197)=  375,
+  NRGRI(198)=  360,
+  NRGRI(199)=  360,
+  NRGRI(200)=  360,
+  NRGRI(201)=  360,
+  NRGRI(202)=  360,
+  NRGRI(203)=  360,
+  NRGRI(204)=  360,
+  NRGRI(205)=  324,
+  NRGRI(206)=  320,
+  NRGRI(207)=  320,
+  NRGRI(208)=  320,
+  NRGRI(209)=  320,
+  NRGRI(210)=  300,
+  NRGRI(211)=  300,
+  NRGRI(212)=  288,
+  NRGRI(213)=  288,
+  NRGRI(214)=  288,
+  NRGRI(215)=  270,
+  NRGRI(216)=  270,
+  NRGRI(217)=  256,
+  NRGRI(218)=  250,
+  NRGRI(219)=  250,
+  NRGRI(220)=  240,
+  NRGRI(221)=  240,
+  NRGRI(222)=  240,
+  NRGRI(223)=  225,
+  NRGRI(224)=  216,
+  NRGRI(225)=  216,
+  NRGRI(226)=  216,
+  NRGRI(227)=  200,
+  NRGRI(228)=  192,
+  NRGRI(229)=  192,
+  NRGRI(230)=  180,
+  NRGRI(231)=  180,
+  NRGRI(232)=  180,
+  NRGRI(233)=  160,
+  NRGRI(234)=  160,
+  NRGRI(235)=  150,
+  NRGRI(236)=  144,
+  NRGRI(237)=  144,
+  NRGRI(238)=  128,
+  NRGRI(239)=  125,
+  NRGRI(240)=  120,
+  NRGRI(241)=  120,
+  NRGRI(242)=  108,
+  NRGRI(243)=  100,
+  NRGRI(244)=   90,
+  NRGRI(245)=   90,
+  NRGRI(246)=   80,
+  NRGRI(247)=   72,
+  NRGRI(248)=   72,
+  NRGRI(249)=   64,
+  NRGRI(250)=   60,
+  NRGRI(251)=   50,
+  NRGRI(252)=   45,
+  NRGRI(253)=   40,
+  NRGRI(254)=   36,
+  NRGRI(255)=   25,
+  NRGRI(256)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2319 b/odb/share/odb/rtablel_2319
new file mode 100644
index 0000000..bc749e1
--- /dev/null
+++ b/odb/share/odb/rtablel_2319
@@ -0,0 +1,322 @@
+ &NAMRGRI
+  NRGRI(1)= 18,
+  NRGRI(2)= 25,
+  NRGRI(3)= 36,
+  NRGRI(4)= 40,
+  NRGRI(5)= 45,
+  NRGRI(6)= 50,
+  NRGRI(7)= 60,
+  NRGRI(8)= 64,
+  NRGRI(9)= 72,
+  NRGRI(10)= 72,
+  NRGRI(11)= 80,
+  NRGRI(12)= 90,
+  NRGRI(13)= 90,
+  NRGRI(14)= 96,
+  NRGRI(15)=108,
+  NRGRI(16)=120,
+  NRGRI(17)=120,
+  NRGRI(18)=125,
+  NRGRI(19)=128,
+  NRGRI(20)=135,
+  NRGRI(21)=144,
+  NRGRI(22)=150,
+  NRGRI(23)=160,
+  NRGRI(24)=160,
+  NRGRI(25)=180,
+  NRGRI(26)=180,
+  NRGRI(27)=180,
+  NRGRI(28)=192,
+  NRGRI(29)=192,
+  NRGRI(30)=200,
+  NRGRI(31)=216,
+  NRGRI(32)=216,
+  NRGRI(33)=225,
+  NRGRI(34)=225,
+  NRGRI(35)=240,
+  NRGRI(36)=240,
+  NRGRI(37)=243,
+  NRGRI(38)=250,
+  NRGRI(39)=256,
+  NRGRI(40)=270,
+  NRGRI(41)=270,
+  NRGRI(42)=288,
+  NRGRI(43)=288,
+  NRGRI(44)=288,
+  NRGRI(45)=300,
+  NRGRI(46)=300,
+  NRGRI(47)=320,
+  NRGRI(48)=320,
+  NRGRI(49)=320,
+  NRGRI(50)=320,
+  NRGRI(51)=324,
+  NRGRI(52)=360,
+  NRGRI(53)=360,
+  NRGRI(54)=360,
+  NRGRI(55)=360,
+  NRGRI(56)=360,
+  NRGRI(57)=360,
+  NRGRI(58)=375,
+  NRGRI(59)=375,
+  NRGRI(60)=375,
+  NRGRI(61)=384,
+  NRGRI(62)=384,
+  NRGRI(63)=400,
+  NRGRI(64)=400,
+  NRGRI(65)=400,
+  NRGRI(66)=405,
+  NRGRI(67)=432,
+  NRGRI(68)=432,
+  NRGRI(69)=432,
+  NRGRI(70)=432,
+  NRGRI(71)=432,
+  NRGRI(72)=450,
+  NRGRI(73)=450,
+  NRGRI(74)=450,
+  NRGRI(75)=450,
+  NRGRI(76)=480,
+  NRGRI(77)=480,
+  NRGRI(78)=480,
+  NRGRI(79)=480,
+  NRGRI(80)=480,
+  NRGRI(81)=480,
+  NRGRI(82)=480,
+  NRGRI(83)=500,
+  NRGRI(84)=500,
+  NRGRI(85)=500,
+  NRGRI(86)=500,
+  NRGRI(87)=500,
+  NRGRI(88)=512,
+  NRGRI(89)=512,
+  NRGRI(90)=540,
+  NRGRI(91)=540,
+  NRGRI(92)=540,
+  NRGRI(93)=540,
+  NRGRI(94)=540,
+  NRGRI(95)=540,
+  NRGRI(96)=540,
+  NRGRI(97)=540,
+  NRGRI(98)=576,
+  NRGRI(99)=576,
+  NRGRI(100)=576,
+  NRGRI(101)=576,
+  NRGRI(102)=576,
+  NRGRI(103)=576,
+  NRGRI(104)=576,
+  NRGRI(105)=576,
+  NRGRI(106)=576,
+  NRGRI(107)=576,
+  NRGRI(108)=600,
+  NRGRI(109)=600,
+  NRGRI(110)=600,
+  NRGRI(111)=600,
+  NRGRI(112)=600,
+  NRGRI(113)=600,
+  NRGRI(114)=600,
+  NRGRI(115)=600,
+  NRGRI(116)=600,
+  NRGRI(117)=640,
+  NRGRI(118)=640,
+  NRGRI(119)=640,
+  NRGRI(120)=640,
+  NRGRI(121)=640,
+  NRGRI(122)=640,
+  NRGRI(123)=640,
+  NRGRI(124)=640,
+  NRGRI(125)=640,
+  NRGRI(126)=640,
+  NRGRI(127)=640,
+  NRGRI(128)=640,
+  NRGRI(129)=640,
+  NRGRI(130)=640,
+  NRGRI(131)=640,
+  NRGRI(132)=640,
+  NRGRI(133)=640,
+  NRGRI(134)=640,
+  NRGRI(135)=640,
+  NRGRI(136)=640,
+  NRGRI(137)=640,
+  NRGRI(138)=640,
+  NRGRI(139)=640,
+  NRGRI(140)=640,
+  NRGRI(141)=640,
+  NRGRI(142)=640,
+  NRGRI(143)=640,
+  NRGRI(144)=640,
+  NRGRI(145)=640,
+  NRGRI(146)=640,
+  NRGRI(147)=640,
+  NRGRI(148)=640,
+  NRGRI(149)=640,
+  NRGRI(150)=640,
+  NRGRI(151)=640,
+  NRGRI(152)=640,
+  NRGRI(153)=640,
+  NRGRI(154)=640,
+  NRGRI(155)=640,
+  NRGRI(156)=640,
+  NRGRI(157)=640,
+  NRGRI(158)=640,
+  NRGRI(159)=640,
+  NRGRI(160)=640,
+  NRGRI(161)=640,
+  NRGRI(162)=640,
+  NRGRI(163)=640,
+  NRGRI(164)=640,
+  NRGRI(165)=640,
+  NRGRI(166)=640,
+  NRGRI(167)=640,
+  NRGRI(168)=640,
+  NRGRI(169)=640,
+  NRGRI(170)=640,
+  NRGRI(171)=640,
+  NRGRI(172)=640,
+  NRGRI(173)=640,
+  NRGRI(174)=640,
+  NRGRI(175)=640,
+  NRGRI(176)=640,
+  NRGRI(177)=640,
+  NRGRI(178)=640,
+  NRGRI(179)=640,
+  NRGRI(180)=640,
+  NRGRI(181)=640,
+  NRGRI(182)=640,
+  NRGRI(183)=640,
+  NRGRI(184)=640,
+  NRGRI(185)=640,
+  NRGRI(186)=640,
+  NRGRI(187)=640,
+  NRGRI(188)=640,
+  NRGRI(189)=640,
+  NRGRI(190)=640,
+  NRGRI(191)=640,
+  NRGRI(192)=640,
+  NRGRI(193)=640,
+  NRGRI(194)=640,
+  NRGRI(195)=640,
+  NRGRI(196)=640,
+  NRGRI(197)=640,
+  NRGRI(198)=640,
+  NRGRI(199)=640,
+  NRGRI(200)=640,
+  NRGRI(201)=640,
+  NRGRI(202)=640,
+  NRGRI(203)=640,
+  NRGRI(204)=640,
+  NRGRI(205)=600,
+  NRGRI(206)=600,
+  NRGRI(207)=600,
+  NRGRI(208)=600,
+  NRGRI(209)=600,
+  NRGRI(210)=600,
+  NRGRI(211)=600,
+  NRGRI(212)=600,
+  NRGRI(213)=600,
+  NRGRI(214)=576,
+  NRGRI(215)=576,
+  NRGRI(216)=576,
+  NRGRI(217)=576,
+  NRGRI(218)=576,
+  NRGRI(219)=576,
+  NRGRI(220)=576,
+  NRGRI(221)=576,
+  NRGRI(222)=576,
+  NRGRI(223)=576,
+  NRGRI(224)=540,
+  NRGRI(225)=540,
+  NRGRI(226)=540,
+  NRGRI(227)=540,
+  NRGRI(228)=540,
+  NRGRI(229)=540,
+  NRGRI(230)=540,
+  NRGRI(231)=540,
+  NRGRI(232)=512,
+  NRGRI(233)=512,
+  NRGRI(234)=500,
+  NRGRI(235)=500,
+  NRGRI(236)=500,
+  NRGRI(237)=500,
+  NRGRI(238)=500,
+  NRGRI(239)=480,
+  NRGRI(240)=480,
+  NRGRI(241)=480,
+  NRGRI(242)=480,
+  NRGRI(243)=480,
+  NRGRI(244)=480,
+  NRGRI(245)=480,
+  NRGRI(246)=450,
+  NRGRI(247)=450,
+  NRGRI(248)=450,
+  NRGRI(249)=450,
+  NRGRI(250)=432,
+  NRGRI(251)=432,
+  NRGRI(252)=432,
+  NRGRI(253)=432,
+  NRGRI(254)=432,
+  NRGRI(255)=405,
+  NRGRI(256)=400,
+  NRGRI(257)=400,
+  NRGRI(258)=400,
+  NRGRI(259)=384,
+  NRGRI(260)=384,
+  NRGRI(261)=375,
+  NRGRI(262)=375,
+  NRGRI(263)=375,
+  NRGRI(264)=360,
+  NRGRI(265)=360,
+  NRGRI(266)=360,
+  NRGRI(267)=360,
+  NRGRI(268)=360,
+  NRGRI(269)=360,
+  NRGRI(270)=324,
+  NRGRI(271)=320,
+  NRGRI(272)=320,
+  NRGRI(273)=320,
+  NRGRI(274)=320,
+  NRGRI(275)=300,
+  NRGRI(276)=300,
+  NRGRI(277)=288,
+  NRGRI(278)=288,
+  NRGRI(279)=288,
+  NRGRI(280)=270,
+  NRGRI(281)=270,
+  NRGRI(282)=256,
+  NRGRI(283)=250,
+  NRGRI(284)=243,
+  NRGRI(285)=240,
+  NRGRI(286)=240,
+  NRGRI(287)=225,
+  NRGRI(288)=225,
+  NRGRI(289)=216,
+  NRGRI(290)=216,
+  NRGRI(291)=200,
+  NRGRI(292)=192,
+  NRGRI(293)=192,
+  NRGRI(294)=180,
+  NRGRI(295)=180,
+  NRGRI(296)=180,
+  NRGRI(297)=160,
+  NRGRI(298)=160,
+  NRGRI(299)=150,
+  NRGRI(300)=144,
+  NRGRI(301)=135,
+  NRGRI(302)=128,
+  NRGRI(303)=125,
+  NRGRI(304)=120,
+  NRGRI(305)=120,
+  NRGRI(306)=108,
+  NRGRI(307)= 96,
+  NRGRI(308)= 90,
+  NRGRI(309)= 90,
+  NRGRI(310)= 80,
+  NRGRI(311)= 72,
+  NRGRI(312)= 72,
+  NRGRI(313)= 64,
+  NRGRI(314)= 60,
+  NRGRI(315)= 50,
+  NRGRI(316)= 45,
+  NRGRI(317)= 40,
+  NRGRI(318)= 36,
+  NRGRI(319)= 25,
+  NRGRI(320)= 18,
+ /
diff --git a/odb/share/odb/rtablel_2399 b/odb/share/odb/rtablel_2399
new file mode 100644
index 0000000..aac1af6
--- /dev/null
+++ b/odb/share/odb/rtablel_2399
@@ -0,0 +1,402 @@
+ &NAMRGRI
+  NRGRI(1)=   18,
+  NRGRI(2)=   25,
+  NRGRI(3)=   36,
+  NRGRI(4)=   40,
+  NRGRI(5)=   45,
+  NRGRI(6)=   50,
+  NRGRI(7)=   60,
+  NRGRI(8)=   64,
+  NRGRI(9)=   72,
+  NRGRI(10)=   72,
+  NRGRI(11)=   75,
+  NRGRI(12)=   81,
+  NRGRI(13)=   90,
+  NRGRI(14)=   96,
+  NRGRI(15)=  100,
+  NRGRI(16)=  108,
+  NRGRI(17)=  120,
+  NRGRI(18)=  125,
+  NRGRI(19)=  128,
+  NRGRI(20)=  135,
+  NRGRI(21)=  144,
+  NRGRI(22)=  150,
+  NRGRI(23)=  160,
+  NRGRI(24)=  160,
+  NRGRI(25)=  180,
+  NRGRI(26)=  180,
+  NRGRI(27)=  180,
+  NRGRI(28)=  192,
+  NRGRI(29)=  192,
+  NRGRI(30)=  200,
+  NRGRI(31)=  216,
+  NRGRI(32)=  216,
+  NRGRI(33)=  225,
+  NRGRI(34)=  225,
+  NRGRI(35)=  240,
+  NRGRI(36)=  240,
+  NRGRI(37)=  243,
+  NRGRI(38)=  250,
+  NRGRI(39)=  256,
+  NRGRI(40)=  270,
+  NRGRI(41)=  270,
+  NRGRI(42)=  288,
+  NRGRI(43)=  288,
+  NRGRI(44)=  288,
+  NRGRI(45)=  300,
+  NRGRI(46)=  300,
+  NRGRI(47)=  320,
+  NRGRI(48)=  320,
+  NRGRI(49)=  320,
+  NRGRI(50)=  320,
+  NRGRI(51)=  360,
+  NRGRI(52)=  360,
+  NRGRI(53)=  360,
+  NRGRI(54)=  360,
+  NRGRI(55)=  360,
+  NRGRI(56)=  360,
+  NRGRI(57)=  375,
+  NRGRI(58)=  375,
+  NRGRI(59)=  375,
+  NRGRI(60)=  384,
+  NRGRI(61)=  400,
+  NRGRI(62)=  400,
+  NRGRI(63)=  400,
+  NRGRI(64)=  400,
+  NRGRI(65)=  432,
+  NRGRI(66)=  432,
+  NRGRI(67)=  432,
+  NRGRI(68)=  432,
+  NRGRI(69)=  432,
+  NRGRI(70)=  450,
+  NRGRI(71)=  450,
+  NRGRI(72)=  450,
+  NRGRI(73)=  480,
+  NRGRI(74)=  480,
+  NRGRI(75)=  480,
+  NRGRI(76)=  480,
+  NRGRI(77)=  480,
+  NRGRI(78)=  480,
+  NRGRI(79)=  486,
+  NRGRI(80)=  500,
+  NRGRI(81)=  500,
+  NRGRI(82)=  500,
+  NRGRI(83)=  512,
+  NRGRI(84)=  512,
+  NRGRI(85)=  512,
+  NRGRI(86)=  540,
+  NRGRI(87)=  540,
+  NRGRI(88)=  540,
+  NRGRI(89)=  540,
+  NRGRI(90)=  540,
+  NRGRI(91)=  576,
+  NRGRI(92)=  576,
+  NRGRI(93)=  576,
+  NRGRI(94)=  576,
+  NRGRI(95)=  576,
+  NRGRI(96)=  576,
+  NRGRI(97)=  576,
+  NRGRI(98)=  576,
+  NRGRI(99)=  600,
+  NRGRI(100)=  600,
+  NRGRI(101)=  600,
+  NRGRI(102)=  600,
+  NRGRI(103)=  600,
+  NRGRI(104)=  640,
+  NRGRI(105)=  640,
+  NRGRI(106)=  640,
+  NRGRI(107)=  640,
+  NRGRI(108)=  640,
+  NRGRI(109)=  640,
+  NRGRI(110)=  640,
+  NRGRI(111)=  640,
+  NRGRI(112)=  640,
+  NRGRI(113)=  640,
+  NRGRI(114)=  648,
+  NRGRI(115)=  648,
+  NRGRI(116)=  675,
+  NRGRI(117)=  675,
+  NRGRI(118)=  675,
+  NRGRI(119)=  675,
+  NRGRI(120)=  675,
+  NRGRI(121)=  675,
+  NRGRI(122)=  675,
+  NRGRI(123)=  720,
+  NRGRI(124)=  720,
+  NRGRI(125)=  720,
+  NRGRI(126)=  720,
+  NRGRI(127)=  720,
+  NRGRI(128)=  720,
+  NRGRI(129)=  720,
+  NRGRI(130)=  720,
+  NRGRI(131)=  720,
+  NRGRI(132)=  720,
+  NRGRI(133)=  720,
+  NRGRI(134)=  720,
+  NRGRI(135)=  720,
+  NRGRI(136)=  720,
+  NRGRI(137)=  729,
+  NRGRI(138)=  729,
+  NRGRI(139)=  729,
+  NRGRI(140)=  750,
+  NRGRI(141)=  750,
+  NRGRI(142)=  750,
+  NRGRI(143)=  750,
+  NRGRI(144)=  750,
+  NRGRI(145)=  750,
+  NRGRI(146)=  750,
+  NRGRI(147)=  750,
+  NRGRI(148)=  768,
+  NRGRI(149)=  768,
+  NRGRI(150)=  768,
+  NRGRI(151)=  768,
+  NRGRI(152)=  768,
+  NRGRI(153)=  768,
+  NRGRI(154)=  768,
+  NRGRI(155)=  768,
+  NRGRI(156)=  800,
+  NRGRI(157)=  800,
+  NRGRI(158)=  800,
+  NRGRI(159)=  800,
+  NRGRI(160)=  800,
+  NRGRI(161)=  800,
+  NRGRI(162)=  800,
+  NRGRI(163)=  800,
+  NRGRI(164)=  800,
+  NRGRI(165)=  800,
+  NRGRI(166)=  800,
+  NRGRI(167)=  800,
+  NRGRI(168)=  800,
+  NRGRI(169)=  800,
+  NRGRI(170)=  800,
+  NRGRI(171)=  800,
+  NRGRI(172)=  800,
+  NRGRI(173)=  800,
+  NRGRI(174)=  800,
+  NRGRI(175)=  800,
+  NRGRI(176)=  800,
+  NRGRI(177)=  800,
+  NRGRI(178)=  800,
+  NRGRI(179)=  800,
+  NRGRI(180)=  800,
+  NRGRI(181)=  800,
+  NRGRI(182)=  800,
+  NRGRI(183)=  800,
+  NRGRI(184)=  800,
+  NRGRI(185)=  800,
+  NRGRI(186)=  800,
+  NRGRI(187)=  800,
+  NRGRI(188)=  800,
+  NRGRI(189)=  800,
+  NRGRI(190)=  800,
+  NRGRI(191)=  800,
+  NRGRI(192)=  800,
+  NRGRI(193)=  800,
+  NRGRI(194)=  800,
+  NRGRI(195)=  800,
+  NRGRI(196)=  800,
+  NRGRI(197)=  800,
+  NRGRI(198)=  800,
+  NRGRI(199)=  800,
+  NRGRI(200)=  800,
+  NRGRI(201)=  800,
+  NRGRI(202)=  800,
+  NRGRI(203)=  800,
+  NRGRI(204)=  800,
+  NRGRI(205)=  800,
+  NRGRI(206)=  800,
+  NRGRI(207)=  800,
+  NRGRI(208)=  800,
+  NRGRI(209)=  800,
+  NRGRI(210)=  800,
+  NRGRI(211)=  800,
+  NRGRI(212)=  800,
+  NRGRI(213)=  800,
+  NRGRI(214)=  800,
+  NRGRI(215)=  800,
+  NRGRI(216)=  800,
+  NRGRI(217)=  800,
+  NRGRI(218)=  800,
+  NRGRI(219)=  800,
+  NRGRI(220)=  800,
+  NRGRI(221)=  800,
+  NRGRI(222)=  800,
+  NRGRI(223)=  800,
+  NRGRI(224)=  800,
+  NRGRI(225)=  800,
+  NRGRI(226)=  800,
+  NRGRI(227)=  800,
+  NRGRI(228)=  800,
+  NRGRI(229)=  800,
+  NRGRI(230)=  800,
+  NRGRI(231)=  800,
+  NRGRI(232)=  800,
+  NRGRI(233)=  800,
+  NRGRI(234)=  800,
+  NRGRI(235)=  800,
+  NRGRI(236)=  800,
+  NRGRI(237)=  800,
+  NRGRI(238)=  800,
+  NRGRI(239)=  800,
+  NRGRI(240)=  800,
+  NRGRI(241)=  800,
+  NRGRI(242)=  800,
+  NRGRI(243)=  800,
+  NRGRI(244)=  800,
+  NRGRI(245)=  800,
+  NRGRI(246)=  768,
+  NRGRI(247)=  768,
+  NRGRI(248)=  768,
+  NRGRI(249)=  768,
+  NRGRI(250)=  768,
+  NRGRI(251)=  768,
+  NRGRI(252)=  768,
+  NRGRI(253)=  768,
+  NRGRI(254)=  750,
+  NRGRI(255)=  750,
+  NRGRI(256)=  750,
+  NRGRI(257)=  750,
+  NRGRI(258)=  750,
+  NRGRI(259)=  750,
+  NRGRI(260)=  750,
+  NRGRI(261)=  750,
+  NRGRI(262)=  729,
+  NRGRI(263)=  729,
+  NRGRI(264)=  729,
+  NRGRI(265)=  720,
+  NRGRI(266)=  720,
+  NRGRI(267)=  720,
+  NRGRI(268)=  720,
+  NRGRI(269)=  720,
+  NRGRI(270)=  720,
+  NRGRI(271)=  720,
+  NRGRI(272)=  720,
+  NRGRI(273)=  720,
+  NRGRI(274)=  720,
+  NRGRI(275)=  720,
+  NRGRI(276)=  720,
+  NRGRI(277)=  720,
+  NRGRI(278)=  720,
+  NRGRI(279)=  675,
+  NRGRI(280)=  675,
+  NRGRI(281)=  675,
+  NRGRI(282)=  675,
+  NRGRI(283)=  675,
+  NRGRI(284)=  675,
+  NRGRI(285)=  675,
+  NRGRI(286)=  648,
+  NRGRI(287)=  648,
+  NRGRI(288)=  640,
+  NRGRI(289)=  640,
+  NRGRI(290)=  640,
+  NRGRI(291)=  640,
+  NRGRI(292)=  640,
+  NRGRI(293)=  640,
+  NRGRI(294)=  640,
+  NRGRI(295)=  640,
+  NRGRI(296)=  640,
+  NRGRI(297)=  640,
+  NRGRI(298)=  600,
+  NRGRI(299)=  600,
+  NRGRI(300)=  600,
+  NRGRI(301)=  600,
+  NRGRI(302)=  600,
+  NRGRI(303)=  576,
+  NRGRI(304)=  576,
+  NRGRI(305)=  576,
+  NRGRI(306)=  576,
+  NRGRI(307)=  576,
+  NRGRI(308)=  576,
+  NRGRI(309)=  576,
+  NRGRI(310)=  576,
+  NRGRI(311)=  540,
+  NRGRI(312)=  540,
+  NRGRI(313)=  540,
+  NRGRI(314)=  540,
+  NRGRI(315)=  540,
+  NRGRI(316)=  512,
+  NRGRI(317)=  512,
+  NRGRI(318)=  512,
+  NRGRI(319)=  500,
+  NRGRI(320)=  500,
+  NRGRI(321)=  500,
+  NRGRI(322)=  486,
+  NRGRI(323)=  480,
+  NRGRI(324)=  480,
+  NRGRI(325)=  480,
+  NRGRI(326)=  480,
+  NRGRI(327)=  480,
+  NRGRI(328)=  480,
+  NRGRI(329)=  450,
+  NRGRI(330)=  450,
+  NRGRI(331)=  450,
+  NRGRI(332)=  432,
+  NRGRI(333)=  432,
+  NRGRI(334)=  432,
+  NRGRI(335)=  432,
+  NRGRI(336)=  432,
+  NRGRI(337)=  400,
+  NRGRI(338)=  400,
+  NRGRI(339)=  400,
+  NRGRI(340)=  400,
+  NRGRI(341)=  384,
+  NRGRI(342)=  375,
+  NRGRI(343)=  375,
+  NRGRI(344)=  375,
+  NRGRI(345)=  360,
+  NRGRI(346)=  360,
+  NRGRI(347)=  360,
+  NRGRI(348)=  360,
+  NRGRI(349)=  360,
+  NRGRI(350)=  360,
+  NRGRI(351)=  320,
+  NRGRI(352)=  320,
+  NRGRI(353)=  320,
+  NRGRI(354)=  320,
+  NRGRI(355)=  300,
+  NRGRI(356)=  300,
+  NRGRI(357)=  288,
+  NRGRI(358)=  288,
+  NRGRI(359)=  288,
+  NRGRI(360)=  270,
+  NRGRI(361)=  270,
+  NRGRI(362)=  256,
+  NRGRI(363)=  250,
+  NRGRI(364)=  243,
+  NRGRI(365)=  240,
+  NRGRI(366)=  240,
+  NRGRI(367)=  225,
+  NRGRI(368)=  225,
+  NRGRI(369)=  216,
+  NRGRI(370)=  216,
+  NRGRI(371)=  200,
+  NRGRI(372)=  192,
+  NRGRI(373)=  192,
+  NRGRI(374)=  180,
+  NRGRI(375)=  180,
+  NRGRI(376)=  180,
+  NRGRI(377)=  160,
+  NRGRI(378)=  160,
+  NRGRI(379)=  150,
+  NRGRI(380)=  144,
+  NRGRI(381)=  135,
+  NRGRI(382)=  128,
+  NRGRI(383)=  125,
+  NRGRI(384)=  120,
+  NRGRI(385)=  108,
+  NRGRI(386)=  100,
+  NRGRI(387)=   96,
+  NRGRI(388)=   90,
+  NRGRI(389)=   81,
+  NRGRI(390)=   75,
+  NRGRI(391)=   72,
+  NRGRI(392)=   72,
+  NRGRI(393)=   64,
+  NRGRI(394)=   60,
+  NRGRI(395)=   50,
+  NRGRI(396)=   45,
+  NRGRI(397)=   40,
+  NRGRI(398)=   36,
+  NRGRI(399)=   25,
+  NRGRI(400)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2511 b/odb/share/odb/rtablel_2511
new file mode 100644
index 0000000..2d2eb3b
--- /dev/null
+++ b/odb/share/odb/rtablel_2511
@@ -0,0 +1,514 @@
+ &NAMRGRI
+  NRGRI(1)=   18,
+  NRGRI(2)=   25,
+  NRGRI(3)=   32,
+  NRGRI(4)=   40,
+  NRGRI(5)=   45,
+  NRGRI(6)=   50,
+  NRGRI(7)=   60,
+  NRGRI(8)=   64,
+  NRGRI(9)=   72,
+  NRGRI(10)=   72,
+  NRGRI(11)=   75,
+  NRGRI(12)=   81,
+  NRGRI(13)=   90,
+  NRGRI(14)=   96,
+  NRGRI(15)=  100,
+  NRGRI(16)=  108,
+  NRGRI(17)=  120,
+  NRGRI(18)=  120,
+  NRGRI(19)=  125,
+  NRGRI(20)=  135,
+  NRGRI(21)=  144,
+  NRGRI(22)=  150,
+  NRGRI(23)=  160,
+  NRGRI(24)=  160,
+  NRGRI(25)=  180,
+  NRGRI(26)=  180,
+  NRGRI(27)=  180,
+  NRGRI(28)=  192,
+  NRGRI(29)=  192,
+  NRGRI(30)=  200,
+  NRGRI(31)=  216,
+  NRGRI(32)=  216,
+  NRGRI(33)=  216,
+  NRGRI(34)=  225,
+  NRGRI(35)=  240,
+  NRGRI(36)=  240,
+  NRGRI(37)=  243,
+  NRGRI(38)=  250,
+  NRGRI(39)=  256,
+  NRGRI(40)=  270,
+  NRGRI(41)=  270,
+  NRGRI(42)=  288,
+  NRGRI(43)=  288,
+  NRGRI(44)=  288,
+  NRGRI(45)=  300,
+  NRGRI(46)=  300,
+  NRGRI(47)=  320,
+  NRGRI(48)=  320,
+  NRGRI(49)=  320,
+  NRGRI(50)=  324,
+  NRGRI(51)=  360,
+  NRGRI(52)=  360,
+  NRGRI(53)=  360,
+  NRGRI(54)=  360,
+  NRGRI(55)=  360,
+  NRGRI(56)=  360,
+  NRGRI(57)=  375,
+  NRGRI(58)=  375,
+  NRGRI(59)=  384,
+  NRGRI(60)=  384,
+  NRGRI(61)=  400,
+  NRGRI(62)=  400,
+  NRGRI(63)=  400,
+  NRGRI(64)=  432,
+  NRGRI(65)=  432,
+  NRGRI(66)=  432,
+  NRGRI(67)=  432,
+  NRGRI(68)=  432,
+  NRGRI(69)=  450,
+  NRGRI(70)=  450,
+  NRGRI(71)=  450,
+  NRGRI(72)=  480,
+  NRGRI(73)=  480,
+  NRGRI(74)=  480,
+  NRGRI(75)=  480,
+  NRGRI(76)=  480,
+  NRGRI(77)=  486,
+  NRGRI(78)=  500,
+  NRGRI(79)=  500,
+  NRGRI(80)=  500,
+  NRGRI(81)=  512,
+  NRGRI(82)=  512,
+  NRGRI(83)=  540,
+  NRGRI(84)=  540,
+  NRGRI(85)=  540,
+  NRGRI(86)=  540,
+  NRGRI(87)=  540,
+  NRGRI(88)=  576,
+  NRGRI(89)=  576,
+  NRGRI(90)=  576,
+  NRGRI(91)=  576,
+  NRGRI(92)=  576,
+  NRGRI(93)=  576,
+  NRGRI(94)=  600,
+  NRGRI(95)=  600,
+  NRGRI(96)=  600,
+  NRGRI(97)=  600,
+  NRGRI(98)=  600,
+  NRGRI(99)=  640,
+  NRGRI(100)=  640,
+  NRGRI(101)=  640,
+  NRGRI(102)=  640,
+  NRGRI(103)=  640,
+  NRGRI(104)=  640,
+  NRGRI(105)=  640,
+  NRGRI(106)=  640,
+  NRGRI(107)=  648,
+  NRGRI(108)=  675,
+  NRGRI(109)=  675,
+  NRGRI(110)=  675,
+  NRGRI(111)=  675,
+  NRGRI(112)=  675,
+  NRGRI(113)=  675,
+  NRGRI(114)=  720,
+  NRGRI(115)=  720,
+  NRGRI(116)=  720,
+  NRGRI(117)=  720,
+  NRGRI(118)=  720,
+  NRGRI(119)=  720,
+  NRGRI(120)=  720,
+  NRGRI(121)=  720,
+  NRGRI(122)=  720,
+  NRGRI(123)=  729,
+  NRGRI(124)=  729,
+  NRGRI(125)=  750,
+  NRGRI(126)=  750,
+  NRGRI(127)=  750,
+  NRGRI(128)=  750,
+  NRGRI(129)=  750,
+  NRGRI(130)=  768,
+  NRGRI(131)=  768,
+  NRGRI(132)=  768,
+  NRGRI(133)=  768,
+  NRGRI(134)=  800,
+  NRGRI(135)=  800,
+  NRGRI(136)=  800,
+  NRGRI(137)=  800,
+  NRGRI(138)=  800,
+  NRGRI(139)=  800,
+  NRGRI(140)=  800,
+  NRGRI(141)=  800,
+  NRGRI(142)=  810,
+  NRGRI(143)=  810,
+  NRGRI(144)=  864,
+  NRGRI(145)=  864,
+  NRGRI(146)=  864,
+  NRGRI(147)=  864,
+  NRGRI(148)=  864,
+  NRGRI(149)=  864,
+  NRGRI(150)=  864,
+  NRGRI(151)=  864,
+  NRGRI(152)=  864,
+  NRGRI(153)=  864,
+  NRGRI(154)=  864,
+  NRGRI(155)=  864,
+  NRGRI(156)=  864,
+  NRGRI(157)=  864,
+  NRGRI(158)=  900,
+  NRGRI(159)=  900,
+  NRGRI(160)=  900,
+  NRGRI(161)=  900,
+  NRGRI(162)=  900,
+  NRGRI(163)=  900,
+  NRGRI(164)=  900,
+  NRGRI(165)=  900,
+  NRGRI(166)=  900,
+  NRGRI(167)=  900,
+  NRGRI(168)=  900,
+  NRGRI(169)=  960,
+  NRGRI(170)=  960,
+  NRGRI(171)=  960,
+  NRGRI(172)=  960,
+  NRGRI(173)=  960,
+  NRGRI(174)=  960,
+  NRGRI(175)=  960,
+  NRGRI(176)=  960,
+  NRGRI(177)=  960,
+  NRGRI(178)=  960,
+  NRGRI(179)=  960,
+  NRGRI(180)=  960,
+  NRGRI(181)=  960,
+  NRGRI(182)=  960,
+  NRGRI(183)=  960,
+  NRGRI(184)=  960,
+  NRGRI(185)=  960,
+  NRGRI(186)=  960,
+  NRGRI(187)=  960,
+  NRGRI(188)=  960,
+  NRGRI(189)=  960,
+  NRGRI(190)=  960,
+  NRGRI(191)=  972,
+  NRGRI(192)=  972,
+  NRGRI(193)=  972,
+  NRGRI(194)=  972,
+  NRGRI(195)=  972,
+  NRGRI(196)= 1000,
+  NRGRI(197)= 1000,
+  NRGRI(198)= 1000,
+  NRGRI(199)= 1000,
+  NRGRI(200)= 1000,
+  NRGRI(201)= 1000,
+  NRGRI(202)= 1000,
+  NRGRI(203)= 1000,
+  NRGRI(204)= 1000,
+  NRGRI(205)= 1000,
+  NRGRI(206)= 1000,
+  NRGRI(207)= 1000,
+  NRGRI(208)= 1000,
+  NRGRI(209)= 1000,
+  NRGRI(210)= 1000,
+  NRGRI(211)= 1000,
+  NRGRI(212)= 1024,
+  NRGRI(213)= 1024,
+  NRGRI(214)= 1024,
+  NRGRI(215)= 1024,
+  NRGRI(216)= 1024,
+  NRGRI(217)= 1024,
+  NRGRI(218)= 1024,
+  NRGRI(219)= 1024,
+  NRGRI(220)= 1024,
+  NRGRI(221)= 1024,
+  NRGRI(222)= 1024,
+  NRGRI(223)= 1024,
+  NRGRI(224)= 1024,
+  NRGRI(225)= 1024,
+  NRGRI(226)= 1024,
+  NRGRI(227)= 1024,
+  NRGRI(228)= 1024,
+  NRGRI(229)= 1024,
+  NRGRI(230)= 1024,
+  NRGRI(231)= 1024,
+  NRGRI(232)= 1024,
+  NRGRI(233)= 1024,
+  NRGRI(234)= 1024,
+  NRGRI(235)= 1024,
+  NRGRI(236)= 1024,
+  NRGRI(237)= 1024,
+  NRGRI(238)= 1024,
+  NRGRI(239)= 1024,
+  NRGRI(240)= 1024,
+  NRGRI(241)= 1024,
+  NRGRI(242)= 1024,
+  NRGRI(243)= 1024,
+  NRGRI(244)= 1024,
+  NRGRI(245)= 1024,
+  NRGRI(246)= 1024,
+  NRGRI(247)= 1024,
+  NRGRI(248)= 1024,
+  NRGRI(249)= 1024,
+  NRGRI(250)= 1024,
+  NRGRI(251)= 1024,
+  NRGRI(252)= 1024,
+  NRGRI(253)= 1024,
+  NRGRI(254)= 1024,
+  NRGRI(255)= 1024,
+  NRGRI(256)= 1024,
+  NRGRI(257)= 1024,
+  NRGRI(258)= 1024,
+  NRGRI(259)= 1024,
+  NRGRI(260)= 1024,
+  NRGRI(261)= 1024,
+  NRGRI(262)= 1024,
+  NRGRI(263)= 1024,
+  NRGRI(264)= 1024,
+  NRGRI(265)= 1024,
+  NRGRI(266)= 1024,
+  NRGRI(267)= 1024,
+  NRGRI(268)= 1024,
+  NRGRI(269)= 1024,
+  NRGRI(270)= 1024,
+  NRGRI(271)= 1024,
+  NRGRI(272)= 1024,
+  NRGRI(273)= 1024,
+  NRGRI(274)= 1024,
+  NRGRI(275)= 1024,
+  NRGRI(276)= 1024,
+  NRGRI(277)= 1024,
+  NRGRI(278)= 1024,
+  NRGRI(279)= 1024,
+  NRGRI(280)= 1024,
+  NRGRI(281)= 1024,
+  NRGRI(282)= 1024,
+  NRGRI(283)= 1024,
+  NRGRI(284)= 1024,
+  NRGRI(285)= 1024,
+  NRGRI(286)= 1024,
+  NRGRI(287)= 1024,
+  NRGRI(288)= 1024,
+  NRGRI(289)= 1024,
+  NRGRI(290)= 1024,
+  NRGRI(291)= 1024,
+  NRGRI(292)= 1024,
+  NRGRI(293)= 1024,
+  NRGRI(294)= 1024,
+  NRGRI(295)= 1024,
+  NRGRI(296)= 1024,
+  NRGRI(297)= 1024,
+  NRGRI(298)= 1024,
+  NRGRI(299)= 1024,
+  NRGRI(300)= 1024,
+  NRGRI(301)= 1024,
+  NRGRI(302)= 1000,
+  NRGRI(303)= 1000,
+  NRGRI(304)= 1000,
+  NRGRI(305)= 1000,
+  NRGRI(306)= 1000,
+  NRGRI(307)= 1000,
+  NRGRI(308)= 1000,
+  NRGRI(309)= 1000,
+  NRGRI(310)= 1000,
+  NRGRI(311)= 1000,
+  NRGRI(312)= 1000,
+  NRGRI(313)= 1000,
+  NRGRI(314)= 1000,
+  NRGRI(315)= 1000,
+  NRGRI(316)= 1000,
+  NRGRI(317)= 1000,
+  NRGRI(318)=  972,
+  NRGRI(319)=  972,
+  NRGRI(320)=  972,
+  NRGRI(321)=  972,
+  NRGRI(322)=  972,
+  NRGRI(323)=  960,
+  NRGRI(324)=  960,
+  NRGRI(325)=  960,
+  NRGRI(326)=  960,
+  NRGRI(327)=  960,
+  NRGRI(328)=  960,
+  NRGRI(329)=  960,
+  NRGRI(330)=  960,
+  NRGRI(331)=  960,
+  NRGRI(332)=  960,
+  NRGRI(333)=  960,
+  NRGRI(334)=  960,
+  NRGRI(335)=  960,
+  NRGRI(336)=  960,
+  NRGRI(337)=  960,
+  NRGRI(338)=  960,
+  NRGRI(339)=  960,
+  NRGRI(340)=  960,
+  NRGRI(341)=  960,
+  NRGRI(342)=  960,
+  NRGRI(343)=  960,
+  NRGRI(344)=  960,
+  NRGRI(345)=  900,
+  NRGRI(346)=  900,
+  NRGRI(347)=  900,
+  NRGRI(348)=  900,
+  NRGRI(349)=  900,
+  NRGRI(350)=  900,
+  NRGRI(351)=  900,
+  NRGRI(352)=  900,
+  NRGRI(353)=  900,
+  NRGRI(354)=  900,
+  NRGRI(355)=  900,
+  NRGRI(356)=  864,
+  NRGRI(357)=  864,
+  NRGRI(358)=  864,
+  NRGRI(359)=  864,
+  NRGRI(360)=  864,
+  NRGRI(361)=  864,
+  NRGRI(362)=  864,
+  NRGRI(363)=  864,
+  NRGRI(364)=  864,
+  NRGRI(365)=  864,
+  NRGRI(366)=  864,
+  NRGRI(367)=  864,
+  NRGRI(368)=  864,
+  NRGRI(369)=  864,
+  NRGRI(370)=  810,
+  NRGRI(371)=  810,
+  NRGRI(372)=  800,
+  NRGRI(373)=  800,
+  NRGRI(374)=  800,
+  NRGRI(375)=  800,
+  NRGRI(376)=  800,
+  NRGRI(377)=  800,
+  NRGRI(378)=  800,
+  NRGRI(379)=  800,
+  NRGRI(380)=  768,
+  NRGRI(381)=  768,
+  NRGRI(382)=  768,
+  NRGRI(383)=  768,
+  NRGRI(384)=  750,
+  NRGRI(385)=  750,
+  NRGRI(386)=  750,
+  NRGRI(387)=  750,
+  NRGRI(388)=  750,
+  NRGRI(389)=  729,
+  NRGRI(390)=  729,
+  NRGRI(391)=  720,
+  NRGRI(392)=  720,
+  NRGRI(393)=  720,
+  NRGRI(394)=  720,
+  NRGRI(395)=  720,
+  NRGRI(396)=  720,
+  NRGRI(397)=  720,
+  NRGRI(398)=  720,
+  NRGRI(399)=  720,
+  NRGRI(400)=  675,
+  NRGRI(401)=  675,
+  NRGRI(402)=  675,
+  NRGRI(403)=  675,
+  NRGRI(404)=  675,
+  NRGRI(405)=  675,
+  NRGRI(406)=  648,
+  NRGRI(407)=  640,
+  NRGRI(408)=  640,
+  NRGRI(409)=  640,
+  NRGRI(410)=  640,
+  NRGRI(411)=  640,
+  NRGRI(412)=  640,
+  NRGRI(413)=  640,
+  NRGRI(414)=  640,
+  NRGRI(415)=  600,
+  NRGRI(416)=  600,
+  NRGRI(417)=  600,
+  NRGRI(418)=  600,
+  NRGRI(419)=  600,
+  NRGRI(420)=  576,
+  NRGRI(421)=  576,
+  NRGRI(422)=  576,
+  NRGRI(423)=  576,
+  NRGRI(424)=  576,
+  NRGRI(425)=  576,
+  NRGRI(426)=  540,
+  NRGRI(427)=  540,
+  NRGRI(428)=  540,
+  NRGRI(429)=  540,
+  NRGRI(430)=  540,
+  NRGRI(431)=  512,
+  NRGRI(432)=  512,
+  NRGRI(433)=  500,
+  NRGRI(434)=  500,
+  NRGRI(435)=  500,
+  NRGRI(436)=  486,
+  NRGRI(437)=  480,
+  NRGRI(438)=  480,
+  NRGRI(439)=  480,
+  NRGRI(440)=  480,
+  NRGRI(441)=  480,
+  NRGRI(442)=  450,
+  NRGRI(443)=  450,
+  NRGRI(444)=  450,
+  NRGRI(445)=  432,
+  NRGRI(446)=  432,
+  NRGRI(447)=  432,
+  NRGRI(448)=  432,
+  NRGRI(449)=  432,
+  NRGRI(450)=  400,
+  NRGRI(451)=  400,
+  NRGRI(452)=  400,
+  NRGRI(453)=  384,
+  NRGRI(454)=  384,
+  NRGRI(455)=  375,
+  NRGRI(456)=  375,
+  NRGRI(457)=  360,
+  NRGRI(458)=  360,
+  NRGRI(459)=  360,
+  NRGRI(460)=  360,
+  NRGRI(461)=  360,
+  NRGRI(462)=  360,
+  NRGRI(463)=  324,
+  NRGRI(464)=  320,
+  NRGRI(465)=  320,
+  NRGRI(466)=  320,
+  NRGRI(467)=  300,
+  NRGRI(468)=  300,
+  NRGRI(469)=  288,
+  NRGRI(470)=  288,
+  NRGRI(471)=  288,
+  NRGRI(472)=  270,
+  NRGRI(473)=  270,
+  NRGRI(474)=  256,
+  NRGRI(475)=  250,
+  NRGRI(476)=  243,
+  NRGRI(477)=  240,
+  NRGRI(478)=  240,
+  NRGRI(479)=  225,
+  NRGRI(480)=  216,
+  NRGRI(481)=  216,
+  NRGRI(482)=  216,
+  NRGRI(483)=  200,
+  NRGRI(484)=  192,
+  NRGRI(485)=  192,
+  NRGRI(486)=  180,
+  NRGRI(487)=  180,
+  NRGRI(488)=  180,
+  NRGRI(489)=  160,
+  NRGRI(490)=  160,
+  NRGRI(491)=  150,
+  NRGRI(492)=  144,
+  NRGRI(493)=  135,
+  NRGRI(494)=  125,
+  NRGRI(495)=  120,
+  NRGRI(496)=  120,
+  NRGRI(497)=  108,
+  NRGRI(498)=  100,
+  NRGRI(499)=   96,
+  NRGRI(500)=   90,
+  NRGRI(501)=   81,
+  NRGRI(502)=   75,
+  NRGRI(503)=   72,
+  NRGRI(504)=   72,
+  NRGRI(505)=   64,
+  NRGRI(506)=   60,
+  NRGRI(507)=   50,
+  NRGRI(508)=   45,
+  NRGRI(509)=   40,
+  NRGRI(510)=   32,
+  NRGRI(511)=   25,
+  NRGRI(512)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2639 b/odb/share/odb/rtablel_2639
new file mode 100644
index 0000000..3659882
--- /dev/null
+++ b/odb/share/odb/rtablel_2639
@@ -0,0 +1,642 @@
+ &NAMRGRI
+  NRGRI(1)=   18,
+  NRGRI(2)=   25,
+  NRGRI(3)=   36,
+  NRGRI(4)=   40,
+  NRGRI(5)=   45,
+  NRGRI(6)=   50,
+  NRGRI(7)=   60,
+  NRGRI(8)=   64,
+  NRGRI(9)=   72,
+  NRGRI(10)=   72,
+  NRGRI(11)=   75,
+  NRGRI(12)=   81,
+  NRGRI(13)=   90,
+  NRGRI(14)=   96,
+  NRGRI(15)=  100,
+  NRGRI(16)=  108,
+  NRGRI(17)=  120,
+  NRGRI(18)=  120,
+  NRGRI(19)=  125,
+  NRGRI(20)=  135,
+  NRGRI(21)=  144,
+  NRGRI(22)=  144,
+  NRGRI(23)=  150,
+  NRGRI(24)=  160,
+  NRGRI(25)=  180,
+  NRGRI(26)=  180,
+  NRGRI(27)=  180,
+  NRGRI(28)=  192,
+  NRGRI(29)=  192,
+  NRGRI(30)=  200,
+  NRGRI(31)=  216,
+  NRGRI(32)=  216,
+  NRGRI(33)=  216,
+  NRGRI(34)=  225,
+  NRGRI(35)=  240,
+  NRGRI(36)=  240,
+  NRGRI(37)=  240,
+  NRGRI(38)=  250,
+  NRGRI(39)=  256,
+  NRGRI(40)=  270,
+  NRGRI(41)=  270,
+  NRGRI(42)=  288,
+  NRGRI(43)=  288,
+  NRGRI(44)=  288,
+  NRGRI(45)=  300,
+  NRGRI(46)=  300,
+  NRGRI(47)=  320,
+  NRGRI(48)=  320,
+  NRGRI(49)=  320,
+  NRGRI(50)=  324,
+  NRGRI(51)=  360,
+  NRGRI(52)=  360,
+  NRGRI(53)=  360,
+  NRGRI(54)=  360,
+  NRGRI(55)=  360,
+  NRGRI(56)=  360,
+  NRGRI(57)=  375,
+  NRGRI(58)=  375,
+  NRGRI(59)=  384,
+  NRGRI(60)=  384,
+  NRGRI(61)=  400,
+  NRGRI(62)=  400,
+  NRGRI(63)=  405,
+  NRGRI(64)=  432,
+  NRGRI(65)=  432,
+  NRGRI(66)=  432,
+  NRGRI(67)=  432,
+  NRGRI(68)=  450,
+  NRGRI(69)=  450,
+  NRGRI(70)=  450,
+  NRGRI(71)=  480,
+  NRGRI(72)=  480,
+  NRGRI(73)=  480,
+  NRGRI(74)=  480,
+  NRGRI(75)=  480,
+  NRGRI(76)=  486,
+  NRGRI(77)=  500,
+  NRGRI(78)=  500,
+  NRGRI(79)=  500,
+  NRGRI(80)=  512,
+  NRGRI(81)=  512,
+  NRGRI(82)=  540,
+  NRGRI(83)=  540,
+  NRGRI(84)=  540,
+  NRGRI(85)=  540,
+  NRGRI(86)=  540,
+  NRGRI(87)=  576,
+  NRGRI(88)=  576,
+  NRGRI(89)=  576,
+  NRGRI(90)=  576,
+  NRGRI(91)=  576,
+  NRGRI(92)=  576,
+  NRGRI(93)=  600,
+  NRGRI(94)=  600,
+  NRGRI(95)=  600,
+  NRGRI(96)=  600,
+  NRGRI(97)=  640,
+  NRGRI(98)=  640,
+  NRGRI(99)=  640,
+  NRGRI(100)=  640,
+  NRGRI(101)=  640,
+  NRGRI(102)=  640,
+  NRGRI(103)=  640,
+  NRGRI(104)=  648,
+  NRGRI(105)=  648,
+  NRGRI(106)=  675,
+  NRGRI(107)=  675,
+  NRGRI(108)=  675,
+  NRGRI(109)=  675,
+  NRGRI(110)=  720,
+  NRGRI(111)=  720,
+  NRGRI(112)=  720,
+  NRGRI(113)=  720,
+  NRGRI(114)=  720,
+  NRGRI(115)=  720,
+  NRGRI(116)=  720,
+  NRGRI(117)=  720,
+  NRGRI(118)=  720,
+  NRGRI(119)=  729,
+  NRGRI(120)=  750,
+  NRGRI(121)=  750,
+  NRGRI(122)=  750,
+  NRGRI(123)=  750,
+  NRGRI(124)=  768,
+  NRGRI(125)=  768,
+  NRGRI(126)=  768,
+  NRGRI(127)=  768,
+  NRGRI(128)=  800,
+  NRGRI(129)=  800,
+  NRGRI(130)=  800,
+  NRGRI(131)=  800,
+  NRGRI(132)=  800,
+  NRGRI(133)=  800,
+  NRGRI(134)=  810,
+  NRGRI(135)=  810,
+  NRGRI(136)=  864,
+  NRGRI(137)=  864,
+  NRGRI(138)=  864,
+  NRGRI(139)=  864,
+  NRGRI(140)=  864,
+  NRGRI(141)=  864,
+  NRGRI(142)=  864,
+  NRGRI(143)=  864,
+  NRGRI(144)=  864,
+  NRGRI(145)=  864,
+  NRGRI(146)=  864,
+  NRGRI(147)=  900,
+  NRGRI(148)=  900,
+  NRGRI(149)=  900,
+  NRGRI(150)=  900,
+  NRGRI(151)=  900,
+  NRGRI(152)=  900,
+  NRGRI(153)=  900,
+  NRGRI(154)=  900,
+  NRGRI(155)=  960,
+  NRGRI(156)=  960,
+  NRGRI(157)=  960,
+  NRGRI(158)=  960,
+  NRGRI(159)=  960,
+  NRGRI(160)=  960,
+  NRGRI(161)=  960,
+  NRGRI(162)=  960,
+  NRGRI(163)=  960,
+  NRGRI(164)=  960,
+  NRGRI(165)=  960,
+  NRGRI(166)=  960,
+  NRGRI(167)=  960,
+  NRGRI(168)=  960,
+  NRGRI(169)=  972,
+  NRGRI(170)=  972,
+  NRGRI(171)= 1000,
+  NRGRI(172)= 1000,
+  NRGRI(173)= 1000,
+  NRGRI(174)= 1000,
+  NRGRI(175)= 1000,
+  NRGRI(176)= 1000,
+  NRGRI(177)= 1000,
+  NRGRI(178)= 1000,
+  NRGRI(179)= 1024,
+  NRGRI(180)= 1024,
+  NRGRI(181)= 1024,
+  NRGRI(182)= 1024,
+  NRGRI(183)= 1024,
+  NRGRI(184)= 1024,
+  NRGRI(185)= 1080,
+  NRGRI(186)= 1080,
+  NRGRI(187)= 1080,
+  NRGRI(188)= 1080,
+  NRGRI(189)= 1080,
+  NRGRI(190)= 1080,
+  NRGRI(191)= 1080,
+  NRGRI(192)= 1080,
+  NRGRI(193)= 1080,
+  NRGRI(194)= 1080,
+  NRGRI(195)= 1080,
+  NRGRI(196)= 1080,
+  NRGRI(197)= 1080,
+  NRGRI(198)= 1080,
+  NRGRI(199)= 1125,
+  NRGRI(200)= 1125,
+  NRGRI(201)= 1125,
+  NRGRI(202)= 1125,
+  NRGRI(203)= 1125,
+  NRGRI(204)= 1125,
+  NRGRI(205)= 1125,
+  NRGRI(206)= 1125,
+  NRGRI(207)= 1125,
+  NRGRI(208)= 1125,
+  NRGRI(209)= 1125,
+  NRGRI(210)= 1125,
+  NRGRI(211)= 1125,
+  NRGRI(212)= 1125,
+  NRGRI(213)= 1152,
+  NRGRI(214)= 1152,
+  NRGRI(215)= 1152,
+  NRGRI(216)= 1152,
+  NRGRI(217)= 1152,
+  NRGRI(218)= 1152,
+  NRGRI(219)= 1152,
+  NRGRI(220)= 1152,
+  NRGRI(221)= 1152,
+  NRGRI(222)= 1200,
+  NRGRI(223)= 1200,
+  NRGRI(224)= 1200,
+  NRGRI(225)= 1200,
+  NRGRI(226)= 1200,
+  NRGRI(227)= 1200,
+  NRGRI(228)= 1200,
+  NRGRI(229)= 1200,
+  NRGRI(230)= 1200,
+  NRGRI(231)= 1200,
+  NRGRI(232)= 1200,
+  NRGRI(233)= 1200,
+  NRGRI(234)= 1200,
+  NRGRI(235)= 1200,
+  NRGRI(236)= 1200,
+  NRGRI(237)= 1200,
+  NRGRI(238)= 1200,
+  NRGRI(239)= 1200,
+  NRGRI(240)= 1215,
+  NRGRI(241)= 1215,
+  NRGRI(242)= 1215,
+  NRGRI(243)= 1215,
+  NRGRI(244)= 1215,
+  NRGRI(245)= 1215,
+  NRGRI(246)= 1215,
+  NRGRI(247)= 1280,
+  NRGRI(248)= 1280,
+  NRGRI(249)= 1280,
+  NRGRI(250)= 1280,
+  NRGRI(251)= 1280,
+  NRGRI(252)= 1280,
+  NRGRI(253)= 1280,
+  NRGRI(254)= 1280,
+  NRGRI(255)= 1280,
+  NRGRI(256)= 1280,
+  NRGRI(257)= 1280,
+  NRGRI(258)= 1280,
+  NRGRI(259)= 1280,
+  NRGRI(260)= 1280,
+  NRGRI(261)= 1280,
+  NRGRI(262)= 1280,
+  NRGRI(263)= 1280,
+  NRGRI(264)= 1280,
+  NRGRI(265)= 1280,
+  NRGRI(266)= 1280,
+  NRGRI(267)= 1280,
+  NRGRI(268)= 1280,
+  NRGRI(269)= 1280,
+  NRGRI(270)= 1280,
+  NRGRI(271)= 1280,
+  NRGRI(272)= 1280,
+  NRGRI(273)= 1280,
+  NRGRI(274)= 1280,
+  NRGRI(275)= 1280,
+  NRGRI(276)= 1280,
+  NRGRI(277)= 1280,
+  NRGRI(278)= 1280,
+  NRGRI(279)= 1280,
+  NRGRI(280)= 1280,
+  NRGRI(281)= 1280,
+  NRGRI(282)= 1280,
+  NRGRI(283)= 1280,
+  NRGRI(284)= 1280,
+  NRGRI(285)= 1280,
+  NRGRI(286)= 1280,
+  NRGRI(287)= 1280,
+  NRGRI(288)= 1280,
+  NRGRI(289)= 1280,
+  NRGRI(290)= 1280,
+  NRGRI(291)= 1280,
+  NRGRI(292)= 1280,
+  NRGRI(293)= 1280,
+  NRGRI(294)= 1280,
+  NRGRI(295)= 1280,
+  NRGRI(296)= 1280,
+  NRGRI(297)= 1280,
+  NRGRI(298)= 1280,
+  NRGRI(299)= 1280,
+  NRGRI(300)= 1280,
+  NRGRI(301)= 1280,
+  NRGRI(302)= 1280,
+  NRGRI(303)= 1280,
+  NRGRI(304)= 1280,
+  NRGRI(305)= 1280,
+  NRGRI(306)= 1280,
+  NRGRI(307)= 1280,
+  NRGRI(308)= 1280,
+  NRGRI(309)= 1280,
+  NRGRI(310)= 1280,
+  NRGRI(311)= 1280,
+  NRGRI(312)= 1280,
+  NRGRI(313)= 1280,
+  NRGRI(314)= 1280,
+  NRGRI(315)= 1280,
+  NRGRI(316)= 1280,
+  NRGRI(317)= 1280,
+  NRGRI(318)= 1280,
+  NRGRI(319)= 1280,
+  NRGRI(320)= 1280,
+  NRGRI(321)= 1280,
+  NRGRI(322)= 1280,
+  NRGRI(323)= 1280,
+  NRGRI(324)= 1280,
+  NRGRI(325)= 1280,
+  NRGRI(326)= 1280,
+  NRGRI(327)= 1280,
+  NRGRI(328)= 1280,
+  NRGRI(329)= 1280,
+  NRGRI(330)= 1280,
+  NRGRI(331)= 1280,
+  NRGRI(332)= 1280,
+  NRGRI(333)= 1280,
+  NRGRI(334)= 1280,
+  NRGRI(335)= 1280,
+  NRGRI(336)= 1280,
+  NRGRI(337)= 1280,
+  NRGRI(338)= 1280,
+  NRGRI(339)= 1280,
+  NRGRI(340)= 1280,
+  NRGRI(341)= 1280,
+  NRGRI(342)= 1280,
+  NRGRI(343)= 1280,
+  NRGRI(344)= 1280,
+  NRGRI(345)= 1280,
+  NRGRI(346)= 1280,
+  NRGRI(347)= 1280,
+  NRGRI(348)= 1280,
+  NRGRI(349)= 1280,
+  NRGRI(350)= 1280,
+  NRGRI(351)= 1280,
+  NRGRI(352)= 1280,
+  NRGRI(353)= 1280,
+  NRGRI(354)= 1280,
+  NRGRI(355)= 1280,
+  NRGRI(356)= 1280,
+  NRGRI(357)= 1280,
+  NRGRI(358)= 1280,
+  NRGRI(359)= 1280,
+  NRGRI(360)= 1280,
+  NRGRI(361)= 1280,
+  NRGRI(362)= 1280,
+  NRGRI(363)= 1280,
+  NRGRI(364)= 1280,
+  NRGRI(365)= 1280,
+  NRGRI(366)= 1280,
+  NRGRI(367)= 1280,
+  NRGRI(368)= 1280,
+  NRGRI(369)= 1280,
+  NRGRI(370)= 1280,
+  NRGRI(371)= 1280,
+  NRGRI(372)= 1280,
+  NRGRI(373)= 1280,
+  NRGRI(374)= 1280,
+  NRGRI(375)= 1280,
+  NRGRI(376)= 1280,
+  NRGRI(377)= 1280,
+  NRGRI(378)= 1280,
+  NRGRI(379)= 1280,
+  NRGRI(380)= 1280,
+  NRGRI(381)= 1280,
+  NRGRI(382)= 1280,
+  NRGRI(383)= 1280,
+  NRGRI(384)= 1280,
+  NRGRI(385)= 1280,
+  NRGRI(386)= 1280,
+  NRGRI(387)= 1280,
+  NRGRI(388)= 1280,
+  NRGRI(389)= 1280,
+  NRGRI(390)= 1280,
+  NRGRI(391)= 1280,
+  NRGRI(392)= 1280,
+  NRGRI(393)= 1280,
+  NRGRI(394)= 1280,
+  NRGRI(395)= 1215,
+  NRGRI(396)= 1215,
+  NRGRI(397)= 1215,
+  NRGRI(398)= 1215,
+  NRGRI(399)= 1215,
+  NRGRI(400)= 1215,
+  NRGRI(401)= 1215,
+  NRGRI(402)= 1200,
+  NRGRI(403)= 1200,
+  NRGRI(404)= 1200,
+  NRGRI(405)= 1200,
+  NRGRI(406)= 1200,
+  NRGRI(407)= 1200,
+  NRGRI(408)= 1200,
+  NRGRI(409)= 1200,
+  NRGRI(410)= 1200,
+  NRGRI(411)= 1200,
+  NRGRI(412)= 1200,
+  NRGRI(413)= 1200,
+  NRGRI(414)= 1200,
+  NRGRI(415)= 1200,
+  NRGRI(416)= 1200,
+  NRGRI(417)= 1200,
+  NRGRI(418)= 1200,
+  NRGRI(419)= 1200,
+  NRGRI(420)= 1152,
+  NRGRI(421)= 1152,
+  NRGRI(422)= 1152,
+  NRGRI(423)= 1152,
+  NRGRI(424)= 1152,
+  NRGRI(425)= 1152,
+  NRGRI(426)= 1152,
+  NRGRI(427)= 1152,
+  NRGRI(428)= 1152,
+  NRGRI(429)= 1125,
+  NRGRI(430)= 1125,
+  NRGRI(431)= 1125,
+  NRGRI(432)= 1125,
+  NRGRI(433)= 1125,
+  NRGRI(434)= 1125,
+  NRGRI(435)= 1125,
+  NRGRI(436)= 1125,
+  NRGRI(437)= 1125,
+  NRGRI(438)= 1125,
+  NRGRI(439)= 1125,
+  NRGRI(440)= 1125,
+  NRGRI(441)= 1125,
+  NRGRI(442)= 1125,
+  NRGRI(443)= 1080,
+  NRGRI(444)= 1080,
+  NRGRI(445)= 1080,
+  NRGRI(446)= 1080,
+  NRGRI(447)= 1080,
+  NRGRI(448)= 1080,
+  NRGRI(449)= 1080,
+  NRGRI(450)= 1080,
+  NRGRI(451)= 1080,
+  NRGRI(452)= 1080,
+  NRGRI(453)= 1080,
+  NRGRI(454)= 1080,
+  NRGRI(455)= 1080,
+  NRGRI(456)= 1080,
+  NRGRI(457)= 1024,
+  NRGRI(458)= 1024,
+  NRGRI(459)= 1024,
+  NRGRI(460)= 1024,
+  NRGRI(461)= 1024,
+  NRGRI(462)= 1024,
+  NRGRI(463)= 1000,
+  NRGRI(464)= 1000,
+  NRGRI(465)= 1000,
+  NRGRI(466)= 1000,
+  NRGRI(467)= 1000,
+  NRGRI(468)= 1000,
+  NRGRI(469)= 1000,
+  NRGRI(470)= 1000,
+  NRGRI(471)=  972,
+  NRGRI(472)=  972,
+  NRGRI(473)=  960,
+  NRGRI(474)=  960,
+  NRGRI(475)=  960,
+  NRGRI(476)=  960,
+  NRGRI(477)=  960,
+  NRGRI(478)=  960,
+  NRGRI(479)=  960,
+  NRGRI(480)=  960,
+  NRGRI(481)=  960,
+  NRGRI(482)=  960,
+  NRGRI(483)=  960,
+  NRGRI(484)=  960,
+  NRGRI(485)=  960,
+  NRGRI(486)=  960,
+  NRGRI(487)=  900,
+  NRGRI(488)=  900,
+  NRGRI(489)=  900,
+  NRGRI(490)=  900,
+  NRGRI(491)=  900,
+  NRGRI(492)=  900,
+  NRGRI(493)=  900,
+  NRGRI(494)=  900,
+  NRGRI(495)=  864,
+  NRGRI(496)=  864,
+  NRGRI(497)=  864,
+  NRGRI(498)=  864,
+  NRGRI(499)=  864,
+  NRGRI(500)=  864,
+  NRGRI(501)=  864,
+  NRGRI(502)=  864,
+  NRGRI(503)=  864,
+  NRGRI(504)=  864,
+  NRGRI(505)=  864,
+  NRGRI(506)=  810,
+  NRGRI(507)=  810,
+  NRGRI(508)=  800,
+  NRGRI(509)=  800,
+  NRGRI(510)=  800,
+  NRGRI(511)=  800,
+  NRGRI(512)=  800,
+  NRGRI(513)=  800,
+  NRGRI(514)=  768,
+  NRGRI(515)=  768,
+  NRGRI(516)=  768,
+  NRGRI(517)=  768,
+  NRGRI(518)=  750,
+  NRGRI(519)=  750,
+  NRGRI(520)=  750,
+  NRGRI(521)=  750,
+  NRGRI(522)=  729,
+  NRGRI(523)=  720,
+  NRGRI(524)=  720,
+  NRGRI(525)=  720,
+  NRGRI(526)=  720,
+  NRGRI(527)=  720,
+  NRGRI(528)=  720,
+  NRGRI(529)=  720,
+  NRGRI(530)=  720,
+  NRGRI(531)=  720,
+  NRGRI(532)=  675,
+  NRGRI(533)=  675,
+  NRGRI(534)=  675,
+  NRGRI(535)=  675,
+  NRGRI(536)=  648,
+  NRGRI(537)=  648,
+  NRGRI(538)=  640,
+  NRGRI(539)=  640,
+  NRGRI(540)=  640,
+  NRGRI(541)=  640,
+  NRGRI(542)=  640,
+  NRGRI(543)=  640,
+  NRGRI(544)=  640,
+  NRGRI(545)=  600,
+  NRGRI(546)=  600,
+  NRGRI(547)=  600,
+  NRGRI(548)=  600,
+  NRGRI(549)=  576,
+  NRGRI(550)=  576,
+  NRGRI(551)=  576,
+  NRGRI(552)=  576,
+  NRGRI(553)=  576,
+  NRGRI(554)=  576,
+  NRGRI(555)=  540,
+  NRGRI(556)=  540,
+  NRGRI(557)=  540,
+  NRGRI(558)=  540,
+  NRGRI(559)=  540,
+  NRGRI(560)=  512,
+  NRGRI(561)=  512,
+  NRGRI(562)=  500,
+  NRGRI(563)=  500,
+  NRGRI(564)=  500,
+  NRGRI(565)=  486,
+  NRGRI(566)=  480,
+  NRGRI(567)=  480,
+  NRGRI(568)=  480,
+  NRGRI(569)=  480,
+  NRGRI(570)=  480,
+  NRGRI(571)=  450,
+  NRGRI(572)=  450,
+  NRGRI(573)=  450,
+  NRGRI(574)=  432,
+  NRGRI(575)=  432,
+  NRGRI(576)=  432,
+  NRGRI(577)=  432,
+  NRGRI(578)=  405,
+  NRGRI(579)=  400,
+  NRGRI(580)=  400,
+  NRGRI(581)=  384,
+  NRGRI(582)=  384,
+  NRGRI(583)=  375,
+  NRGRI(584)=  375,
+  NRGRI(585)=  360,
+  NRGRI(586)=  360,
+  NRGRI(587)=  360,
+  NRGRI(588)=  360,
+  NRGRI(589)=  360,
+  NRGRI(590)=  360,
+  NRGRI(591)=  324,
+  NRGRI(592)=  320,
+  NRGRI(593)=  320,
+  NRGRI(594)=  320,
+  NRGRI(595)=  300,
+  NRGRI(596)=  300,
+  NRGRI(597)=  288,
+  NRGRI(598)=  288,
+  NRGRI(599)=  288,
+  NRGRI(600)=  270,
+  NRGRI(601)=  270,
+  NRGRI(602)=  256,
+  NRGRI(603)=  250,
+  NRGRI(604)=  240,
+  NRGRI(605)=  240,
+  NRGRI(606)=  240,
+  NRGRI(607)=  225,
+  NRGRI(608)=  216,
+  NRGRI(609)=  216,
+  NRGRI(610)=  216,
+  NRGRI(611)=  200,
+  NRGRI(612)=  192,
+  NRGRI(613)=  192,
+  NRGRI(614)=  180,
+  NRGRI(615)=  180,
+  NRGRI(616)=  180,
+  NRGRI(617)=  160,
+  NRGRI(618)=  150,
+  NRGRI(619)=  144,
+  NRGRI(620)=  144,
+  NRGRI(621)=  135,
+  NRGRI(622)=  125,
+  NRGRI(623)=  120,
+  NRGRI(624)=  120,
+  NRGRI(625)=  108,
+  NRGRI(626)=  100,
+  NRGRI(627)=   96,
+  NRGRI(628)=   90,
+  NRGRI(629)=   81,
+  NRGRI(630)=   75,
+  NRGRI(631)=   72,
+  NRGRI(632)=   72,
+  NRGRI(633)=   64,
+  NRGRI(634)=   60,
+  NRGRI(635)=   50,
+  NRGRI(636)=   45,
+  NRGRI(637)=   40,
+  NRGRI(638)=   36,
+  NRGRI(639)=   25,
+  NRGRI(640)=   18,
+ /
diff --git a/odb/share/odb/rtablel_2799 b/odb/share/odb/rtablel_2799
new file mode 100644
index 0000000..121ce57
--- /dev/null
+++ b/odb/share/odb/rtablel_2799
@@ -0,0 +1,802 @@
+ &NAMRGRI
+  NRGRI(0001)=   18,
+  NRGRI(0002)=   25,
+  NRGRI(0003)=   32,
+  NRGRI(0004)=   40,
+  NRGRI(0005)=   45,
+  NRGRI(0006)=   50,
+  NRGRI(0007)=   60,
+  NRGRI(0008)=   60,
+  NRGRI(0009)=   72,
+  NRGRI(0010)=   72,
+  NRGRI(0011)=   75,
+  NRGRI(0012)=   81,
+  NRGRI(0013)=   90,
+  NRGRI(0014)=   96,
+  NRGRI(0015)=  100,
+  NRGRI(0016)=  108,
+  NRGRI(0017)=  120,
+  NRGRI(0018)=  120,
+  NRGRI(0019)=  125,
+  NRGRI(0020)=  128,
+  NRGRI(0021)=  144,
+  NRGRI(0022)=  144,
+  NRGRI(0023)=  150,
+  NRGRI(0024)=  160,
+  NRGRI(0025)=  160,
+  NRGRI(0026)=  180,
+  NRGRI(0027)=  180,
+  NRGRI(0028)=  192,
+  NRGRI(0029)=  192,
+  NRGRI(0030)=  200,
+  NRGRI(0031)=  200,
+  NRGRI(0032)=  216,
+  NRGRI(0033)=  216,
+  NRGRI(0034)=  225,
+  NRGRI(0035)=  240,
+  NRGRI(0036)=  240,
+  NRGRI(0037)=  240,
+  NRGRI(0038)=  250,
+  NRGRI(0039)=  250,
+  NRGRI(0040)=  256,
+  NRGRI(0041)=  270,
+  NRGRI(0042)=  288,
+  NRGRI(0043)=  288,
+  NRGRI(0044)=  288,
+  NRGRI(0045)=  300,
+  NRGRI(0046)=  300,
+  NRGRI(0047)=  320,
+  NRGRI(0048)=  320,
+  NRGRI(0049)=  320,
+  NRGRI(0050)=  324,
+  NRGRI(0051)=  360,
+  NRGRI(0052)=  360,
+  NRGRI(0053)=  360,
+  NRGRI(0054)=  360,
+  NRGRI(0055)=  360,
+  NRGRI(0056)=  360,
+  NRGRI(0057)=  375,
+  NRGRI(0058)=  375,
+  NRGRI(0059)=  384,
+  NRGRI(0060)=  400,
+  NRGRI(0061)=  400,
+  NRGRI(0062)=  400,
+  NRGRI(0063)=  405,
+  NRGRI(0064)=  432,
+  NRGRI(0065)=  432,
+  NRGRI(0066)=  432,
+  NRGRI(0067)=  432,
+  NRGRI(0068)=  450,
+  NRGRI(0069)=  450,
+  NRGRI(0070)=  450,
+  NRGRI(0071)=  480,
+  NRGRI(0072)=  480,
+  NRGRI(0073)=  480,
+  NRGRI(0074)=  480,
+  NRGRI(0075)=  480,
+  NRGRI(0076)=  486,
+  NRGRI(0077)=  500,
+  NRGRI(0078)=  500,
+  NRGRI(0079)=  512,
+  NRGRI(0080)=  512,
+  NRGRI(0081)=  540,
+  NRGRI(0082)=  540,
+  NRGRI(0083)=  540,
+  NRGRI(0084)=  540,
+  NRGRI(0085)=  540,
+  NRGRI(0086)=  576,
+  NRGRI(0087)=  576,
+  NRGRI(0088)=  576,
+  NRGRI(0089)=  576,
+  NRGRI(0090)=  576,
+  NRGRI(0091)=  576,
+  NRGRI(0092)=  600,
+  NRGRI(0093)=  600,
+  NRGRI(0094)=  600,
+  NRGRI(0095)=  600,
+  NRGRI(0096)=  640,
+  NRGRI(0097)=  640,
+  NRGRI(0098)=  640,
+  NRGRI(0099)=  640,
+  NRGRI(0100)=  640,
+  NRGRI(0101)=  640,
+  NRGRI(0102)=  640,
+  NRGRI(0103)=  648,
+  NRGRI(0104)=  675,
+  NRGRI(0105)=  675,
+  NRGRI(0106)=  675,
+  NRGRI(0107)=  675,
+  NRGRI(0108)=  675,
+  NRGRI(0109)=  720,
+  NRGRI(0110)=  720,
+  NRGRI(0111)=  720,
+  NRGRI(0112)=  720,
+  NRGRI(0113)=  720,
+  NRGRI(0114)=  720,
+  NRGRI(0115)=  720,
+  NRGRI(0116)=  729,
+  NRGRI(0117)=  729,
+  NRGRI(0118)=  750,
+  NRGRI(0119)=  750,
+  NRGRI(0120)=  750,
+  NRGRI(0121)=  750,
+  NRGRI(0122)=  768,
+  NRGRI(0123)=  768,
+  NRGRI(0124)=  768,
+  NRGRI(0125)=  800,
+  NRGRI(0126)=  800,
+  NRGRI(0127)=  800,
+  NRGRI(0128)=  800,
+  NRGRI(0129)=  800,
+  NRGRI(0130)=  800,
+  NRGRI(0131)=  810,
+  NRGRI(0132)=  864,
+  NRGRI(0133)=  864,
+  NRGRI(0134)=  864,
+  NRGRI(0135)=  864,
+  NRGRI(0136)=  864,
+  NRGRI(0137)=  864,
+  NRGRI(0138)=  864,
+  NRGRI(0139)=  864,
+  NRGRI(0140)=  864,
+  NRGRI(0141)=  864,
+  NRGRI(0142)=  900,
+  NRGRI(0143)=  900,
+  NRGRI(0144)=  900,
+  NRGRI(0145)=  900,
+  NRGRI(0146)=  900,
+  NRGRI(0147)=  900,
+  NRGRI(0148)=  900,
+  NRGRI(0149)=  960,
+  NRGRI(0150)=  960,
+  NRGRI(0151)=  960,
+  NRGRI(0152)=  960,
+  NRGRI(0153)=  960,
+  NRGRI(0154)=  960,
+  NRGRI(0155)=  960,
+  NRGRI(0156)=  960,
+  NRGRI(0157)=  960,
+  NRGRI(0158)=  960,
+  NRGRI(0159)=  960,
+  NRGRI(0160)=  960,
+  NRGRI(0161)=  972,
+  NRGRI(0162)=  972,
+  NRGRI(0163)= 1000,
+  NRGRI(0164)= 1000,
+  NRGRI(0165)= 1000,
+  NRGRI(0166)= 1000,
+  NRGRI(0167)= 1000,
+  NRGRI(0168)= 1000,
+  NRGRI(0169)= 1024,
+  NRGRI(0170)= 1024,
+  NRGRI(0171)= 1024,
+  NRGRI(0172)= 1024,
+  NRGRI(0173)= 1024,
+  NRGRI(0174)= 1080,
+  NRGRI(0175)= 1080,
+  NRGRI(0176)= 1080,
+  NRGRI(0177)= 1080,
+  NRGRI(0178)= 1080,
+  NRGRI(0179)= 1080,
+  NRGRI(0180)= 1080,
+  NRGRI(0181)= 1080,
+  NRGRI(0182)= 1080,
+  NRGRI(0183)= 1080,
+  NRGRI(0184)= 1080,
+  NRGRI(0185)= 1125,
+  NRGRI(0186)= 1125,
+  NRGRI(0187)= 1125,
+  NRGRI(0188)= 1125,
+  NRGRI(0189)= 1125,
+  NRGRI(0190)= 1125,
+  NRGRI(0191)= 1125,
+  NRGRI(0192)= 1125,
+  NRGRI(0193)= 1125,
+  NRGRI(0194)= 1152,
+  NRGRI(0195)= 1152,
+  NRGRI(0196)= 1152,
+  NRGRI(0197)= 1152,
+  NRGRI(0198)= 1152,
+  NRGRI(0199)= 1152,
+  NRGRI(0200)= 1200,
+  NRGRI(0201)= 1200,
+  NRGRI(0202)= 1200,
+  NRGRI(0203)= 1200,
+  NRGRI(0204)= 1200,
+  NRGRI(0205)= 1200,
+  NRGRI(0206)= 1200,
+  NRGRI(0207)= 1200,
+  NRGRI(0208)= 1200,
+  NRGRI(0209)= 1200,
+  NRGRI(0210)= 1200,
+  NRGRI(0211)= 1215,
+  NRGRI(0212)= 1215,
+  NRGRI(0213)= 1215,
+  NRGRI(0214)= 1215,
+  NRGRI(0215)= 1280,
+  NRGRI(0216)= 1280,
+  NRGRI(0217)= 1280,
+  NRGRI(0218)= 1280,
+  NRGRI(0219)= 1280,
+  NRGRI(0220)= 1280,
+  NRGRI(0221)= 1280,
+  NRGRI(0222)= 1280,
+  NRGRI(0223)= 1280,
+  NRGRI(0224)= 1280,
+  NRGRI(0225)= 1280,
+  NRGRI(0226)= 1280,
+  NRGRI(0227)= 1280,
+  NRGRI(0228)= 1280,
+  NRGRI(0229)= 1280,
+  NRGRI(0230)= 1280,
+  NRGRI(0231)= 1296,
+  NRGRI(0232)= 1296,
+  NRGRI(0233)= 1296,
+  NRGRI(0234)= 1296,
+  NRGRI(0235)= 1350,
+  NRGRI(0236)= 1350,
+  NRGRI(0237)= 1350,
+  NRGRI(0238)= 1350,
+  NRGRI(0239)= 1350,
+  NRGRI(0240)= 1350,
+  NRGRI(0241)= 1350,
+  NRGRI(0242)= 1350,
+  NRGRI(0243)= 1350,
+  NRGRI(0244)= 1350,
+  NRGRI(0245)= 1350,
+  NRGRI(0246)= 1350,
+  NRGRI(0247)= 1350,
+  NRGRI(0248)= 1350,
+  NRGRI(0249)= 1350,
+  NRGRI(0250)= 1440,
+  NRGRI(0251)= 1440,
+  NRGRI(0252)= 1440,
+  NRGRI(0253)= 1440,
+  NRGRI(0254)= 1440,
+  NRGRI(0255)= 1440,
+  NRGRI(0256)= 1440,
+  NRGRI(0257)= 1440,
+  NRGRI(0258)= 1440,
+  NRGRI(0259)= 1440,
+  NRGRI(0260)= 1440,
+  NRGRI(0261)= 1440,
+  NRGRI(0262)= 1440,
+  NRGRI(0263)= 1440,
+  NRGRI(0264)= 1440,
+  NRGRI(0265)= 1440,
+  NRGRI(0266)= 1440,
+  NRGRI(0267)= 1440,
+  NRGRI(0268)= 1440,
+  NRGRI(0269)= 1440,
+  NRGRI(0270)= 1440,
+  NRGRI(0271)= 1440,
+  NRGRI(0272)= 1440,
+  NRGRI(0273)= 1440,
+  NRGRI(0274)= 1440,
+  NRGRI(0275)= 1440,
+  NRGRI(0276)= 1440,
+  NRGRI(0277)= 1440,
+  NRGRI(0278)= 1458,
+  NRGRI(0279)= 1458,
+  NRGRI(0280)= 1458,
+  NRGRI(0281)= 1458,
+  NRGRI(0282)= 1458,
+  NRGRI(0283)= 1458,
+  NRGRI(0284)= 1458,
+  NRGRI(0285)= 1500,
+  NRGRI(0286)= 1500,
+  NRGRI(0287)= 1500,
+  NRGRI(0288)= 1500,
+  NRGRI(0289)= 1500,
+  NRGRI(0290)= 1500,
+  NRGRI(0291)= 1500,
+  NRGRI(0292)= 1500,
+  NRGRI(0293)= 1500,
+  NRGRI(0294)= 1500,
+  NRGRI(0295)= 1500,
+  NRGRI(0296)= 1500,
+  NRGRI(0297)= 1500,
+  NRGRI(0298)= 1500,
+  NRGRI(0299)= 1500,
+  NRGRI(0300)= 1500,
+  NRGRI(0301)= 1500,
+  NRGRI(0302)= 1536,
+  NRGRI(0303)= 1536,
+  NRGRI(0304)= 1536,
+  NRGRI(0305)= 1536,
+  NRGRI(0306)= 1536,
+  NRGRI(0307)= 1536,
+  NRGRI(0308)= 1536,
+  NRGRI(0309)= 1536,
+  NRGRI(0310)= 1536,
+  NRGRI(0311)= 1536,
+  NRGRI(0312)= 1536,
+  NRGRI(0313)= 1536,
+  NRGRI(0314)= 1536,
+  NRGRI(0315)= 1536,
+  NRGRI(0316)= 1536,
+  NRGRI(0317)= 1536,
+  NRGRI(0318)= 1600,
+  NRGRI(0319)= 1600,
+  NRGRI(0320)= 1600,
+  NRGRI(0321)= 1600,
+  NRGRI(0322)= 1600,
+  NRGRI(0323)= 1600,
+  NRGRI(0324)= 1600,
+  NRGRI(0325)= 1600,
+  NRGRI(0326)= 1600,
+  NRGRI(0327)= 1600,
+  NRGRI(0328)= 1600,
+  NRGRI(0329)= 1600,
+  NRGRI(0330)= 1600,
+  NRGRI(0331)= 1600,
+  NRGRI(0332)= 1600,
+  NRGRI(0333)= 1600,
+  NRGRI(0334)= 1600,
+  NRGRI(0335)= 1600,
+  NRGRI(0336)= 1600,
+  NRGRI(0337)= 1600,
+  NRGRI(0338)= 1600,
+  NRGRI(0339)= 1600,
+  NRGRI(0340)= 1600,
+  NRGRI(0341)= 1600,
+  NRGRI(0342)= 1600,
+  NRGRI(0343)= 1600,
+  NRGRI(0344)= 1600,
+  NRGRI(0345)= 1600,
+  NRGRI(0346)= 1600,
+  NRGRI(0347)= 1600,
+  NRGRI(0348)= 1600,
+  NRGRI(0349)= 1600,
+  NRGRI(0350)= 1600,
+  NRGRI(0351)= 1600,
+  NRGRI(0352)= 1600,
+  NRGRI(0353)= 1600,
+  NRGRI(0354)= 1600,
+  NRGRI(0355)= 1600,
+  NRGRI(0356)= 1600,
+  NRGRI(0357)= 1600,
+  NRGRI(0358)= 1600,
+  NRGRI(0359)= 1600,
+  NRGRI(0360)= 1600,
+  NRGRI(0361)= 1600,
+  NRGRI(0362)= 1600,
+  NRGRI(0363)= 1600,
+  NRGRI(0364)= 1600,
+  NRGRI(0365)= 1600,
+  NRGRI(0366)= 1600,
+  NRGRI(0367)= 1600,
+  NRGRI(0368)= 1600,
+  NRGRI(0369)= 1600,
+  NRGRI(0370)= 1600,
+  NRGRI(0371)= 1600,
+  NRGRI(0372)= 1600,
+  NRGRI(0373)= 1600,
+  NRGRI(0374)= 1600,
+  NRGRI(0375)= 1600,
+  NRGRI(0376)= 1600,
+  NRGRI(0377)= 1600,
+  NRGRI(0378)= 1600,
+  NRGRI(0379)= 1600,
+  NRGRI(0380)= 1600,
+  NRGRI(0381)= 1600,
+  NRGRI(0382)= 1600,
+  NRGRI(0383)= 1600,
+  NRGRI(0384)= 1600,
+  NRGRI(0385)= 1600,
+  NRGRI(0386)= 1600,
+  NRGRI(0387)= 1600,
+  NRGRI(0388)= 1600,
+  NRGRI(0389)= 1600,
+  NRGRI(0390)= 1600,
+  NRGRI(0391)= 1600,
+  NRGRI(0392)= 1600,
+  NRGRI(0393)= 1600,
+  NRGRI(0394)= 1600,
+  NRGRI(0395)= 1600,
+  NRGRI(0396)= 1600,
+  NRGRI(0397)= 1600,
+  NRGRI(0398)= 1600,
+  NRGRI(0399)= 1600,
+  NRGRI(0400)= 1600,
+  NRGRI(0401)= 1600,
+  NRGRI(0402)= 1600,
+  NRGRI(0403)= 1600,
+  NRGRI(0404)= 1600,
+  NRGRI(0405)= 1600,
+  NRGRI(0406)= 1600,
+  NRGRI(0407)= 1600,
+  NRGRI(0408)= 1600,
+  NRGRI(0409)= 1600,
+  NRGRI(0410)= 1600,
+  NRGRI(0411)= 1600,
+  NRGRI(0412)= 1600,
+  NRGRI(0413)= 1600,
+  NRGRI(0414)= 1600,
+  NRGRI(0415)= 1600,
+  NRGRI(0416)= 1600,
+  NRGRI(0417)= 1600,
+  NRGRI(0418)= 1600,
+  NRGRI(0419)= 1600,
+  NRGRI(0420)= 1600,
+  NRGRI(0421)= 1600,
+  NRGRI(0422)= 1600,
+  NRGRI(0423)= 1600,
+  NRGRI(0424)= 1600,
+  NRGRI(0425)= 1600,
+  NRGRI(0426)= 1600,
+  NRGRI(0427)= 1600,
+  NRGRI(0428)= 1600,
+  NRGRI(0429)= 1600,
+  NRGRI(0430)= 1600,
+  NRGRI(0431)= 1600,
+  NRGRI(0432)= 1600,
+  NRGRI(0433)= 1600,
+  NRGRI(0434)= 1600,
+  NRGRI(0435)= 1600,
+  NRGRI(0436)= 1600,
+  NRGRI(0437)= 1600,
+  NRGRI(0438)= 1600,
+  NRGRI(0439)= 1600,
+  NRGRI(0440)= 1600,
+  NRGRI(0441)= 1600,
+  NRGRI(0442)= 1600,
+  NRGRI(0443)= 1600,
+  NRGRI(0444)= 1600,
+  NRGRI(0445)= 1600,
+  NRGRI(0446)= 1600,
+  NRGRI(0447)= 1600,
+  NRGRI(0448)= 1600,
+  NRGRI(0449)= 1600,
+  NRGRI(0450)= 1600,
+  NRGRI(0451)= 1600,
+  NRGRI(0452)= 1600,
+  NRGRI(0453)= 1600,
+  NRGRI(0454)= 1600,
+  NRGRI(0455)= 1600,
+  NRGRI(0456)= 1600,
+  NRGRI(0457)= 1600,
+  NRGRI(0458)= 1600,
+  NRGRI(0459)= 1600,
+  NRGRI(0460)= 1600,
+  NRGRI(0461)= 1600,
+  NRGRI(0462)= 1600,
+  NRGRI(0463)= 1600,
+  NRGRI(0464)= 1600,
+  NRGRI(0465)= 1600,
+  NRGRI(0466)= 1600,
+  NRGRI(0467)= 1600,
+  NRGRI(0468)= 1600,
+  NRGRI(0469)= 1600,
+  NRGRI(0470)= 1600,
+  NRGRI(0471)= 1600,
+  NRGRI(0472)= 1600,
+  NRGRI(0473)= 1600,
+  NRGRI(0474)= 1600,
+  NRGRI(0475)= 1600,
+  NRGRI(0476)= 1600,
+  NRGRI(0477)= 1600,
+  NRGRI(0478)= 1600,
+  NRGRI(0479)= 1600,
+  NRGRI(0480)= 1600,
+  NRGRI(0481)= 1600,
+  NRGRI(0482)= 1600,
+  NRGRI(0483)= 1600,
+  NRGRI(0484)= 1536,
+  NRGRI(0485)= 1536,
+  NRGRI(0486)= 1536,
+  NRGRI(0487)= 1536,
+  NRGRI(0488)= 1536,
+  NRGRI(0489)= 1536,
+  NRGRI(0490)= 1536,
+  NRGRI(0491)= 1536,
+  NRGRI(0492)= 1536,
+  NRGRI(0493)= 1536,
+  NRGRI(0494)= 1536,
+  NRGRI(0495)= 1536,
+  NRGRI(0496)= 1536,
+  NRGRI(0497)= 1536,
+  NRGRI(0498)= 1536,
+  NRGRI(0499)= 1536,
+  NRGRI(0500)= 1500,
+  NRGRI(0501)= 1500,
+  NRGRI(0502)= 1500,
+  NRGRI(0503)= 1500,
+  NRGRI(0504)= 1500,
+  NRGRI(0505)= 1500,
+  NRGRI(0506)= 1500,
+  NRGRI(0507)= 1500,
+  NRGRI(0508)= 1500,
+  NRGRI(0509)= 1500,
+  NRGRI(0510)= 1500,
+  NRGRI(0511)= 1500,
+  NRGRI(0512)= 1500,
+  NRGRI(0513)= 1500,
+  NRGRI(0514)= 1500,
+  NRGRI(0515)= 1500,
+  NRGRI(0516)= 1500,
+  NRGRI(0517)= 1458,
+  NRGRI(0518)= 1458,
+  NRGRI(0519)= 1458,
+  NRGRI(0520)= 1458,
+  NRGRI(0521)= 1458,
+  NRGRI(0522)= 1458,
+  NRGRI(0523)= 1458,
+  NRGRI(0524)= 1440,
+  NRGRI(0525)= 1440,
+  NRGRI(0526)= 1440,
+  NRGRI(0527)= 1440,
+  NRGRI(0528)= 1440,
+  NRGRI(0529)= 1440,
+  NRGRI(0530)= 1440,
+  NRGRI(0531)= 1440,
+  NRGRI(0532)= 1440,
+  NRGRI(0533)= 1440,
+  NRGRI(0534)= 1440,
+  NRGRI(0535)= 1440,
+  NRGRI(0536)= 1440,
+  NRGRI(0537)= 1440,
+  NRGRI(0538)= 1440,
+  NRGRI(0539)= 1440,
+  NRGRI(0540)= 1440,
+  NRGRI(0541)= 1440,
+  NRGRI(0542)= 1440,
+  NRGRI(0543)= 1440,
+  NRGRI(0544)= 1440,
+  NRGRI(0545)= 1440,
+  NRGRI(0546)= 1440,
+  NRGRI(0547)= 1440,
+  NRGRI(0548)= 1440,
+  NRGRI(0549)= 1440,
+  NRGRI(0550)= 1440,
+  NRGRI(0551)= 1440,
+  NRGRI(0552)= 1350,
+  NRGRI(0553)= 1350,
+  NRGRI(0554)= 1350,
+  NRGRI(0555)= 1350,
+  NRGRI(0556)= 1350,
+  NRGRI(0557)= 1350,
+  NRGRI(0558)= 1350,
+  NRGRI(0559)= 1350,
+  NRGRI(0560)= 1350,
+  NRGRI(0561)= 1350,
+  NRGRI(0562)= 1350,
+  NRGRI(0563)= 1350,
+  NRGRI(0564)= 1350,
+  NRGRI(0565)= 1350,
+  NRGRI(0566)= 1350,
+  NRGRI(0567)= 1296,
+  NRGRI(0568)= 1296,
+  NRGRI(0569)= 1296,
+  NRGRI(0570)= 1296,
+  NRGRI(0571)= 1280,
+  NRGRI(0572)= 1280,
+  NRGRI(0573)= 1280,
+  NRGRI(0574)= 1280,
+  NRGRI(0575)= 1280,
+  NRGRI(0576)= 1280,
+  NRGRI(0577)= 1280,
+  NRGRI(0578)= 1280,
+  NRGRI(0579)= 1280,
+  NRGRI(0580)= 1280,
+  NRGRI(0581)= 1280,
+  NRGRI(0582)= 1280,
+  NRGRI(0583)= 1280,
+  NRGRI(0584)= 1280,
+  NRGRI(0585)= 1280,
+  NRGRI(0586)= 1280,
+  NRGRI(0587)= 1215,
+  NRGRI(0588)= 1215,
+  NRGRI(0589)= 1215,
+  NRGRI(0590)= 1215,
+  NRGRI(0591)= 1200,
+  NRGRI(0592)= 1200,
+  NRGRI(0593)= 1200,
+  NRGRI(0594)= 1200,
+  NRGRI(0595)= 1200,
+  NRGRI(0596)= 1200,
+  NRGRI(0597)= 1200,
+  NRGRI(0598)= 1200,
+  NRGRI(0599)= 1200,
+  NRGRI(0600)= 1200,
+  NRGRI(0601)= 1200,
+  NRGRI(0602)= 1152,
+  NRGRI(0603)= 1152,
+  NRGRI(0604)= 1152,
+  NRGRI(0605)= 1152,
+  NRGRI(0606)= 1152,
+  NRGRI(0607)= 1152,
+  NRGRI(0608)= 1125,
+  NRGRI(0609)= 1125,
+  NRGRI(0610)= 1125,
+  NRGRI(0611)= 1125,
+  NRGRI(0612)= 1125,
+  NRGRI(0613)= 1125,
+  NRGRI(0614)= 1125,
+  NRGRI(0615)= 1125,
+  NRGRI(0616)= 1125,
+  NRGRI(0617)= 1080,
+  NRGRI(0618)= 1080,
+  NRGRI(0619)= 1080,
+  NRGRI(0620)= 1080,
+  NRGRI(0621)= 1080,
+  NRGRI(0622)= 1080,
+  NRGRI(0623)= 1080,
+  NRGRI(0624)= 1080,
+  NRGRI(0625)= 1080,
+  NRGRI(0626)= 1080,
+  NRGRI(0627)= 1080,
+  NRGRI(0628)= 1024,
+  NRGRI(0629)= 1024,
+  NRGRI(0630)= 1024,
+  NRGRI(0631)= 1024,
+  NRGRI(0632)= 1024,
+  NRGRI(0633)= 1000,
+  NRGRI(0634)= 1000,
+  NRGRI(0635)= 1000,
+  NRGRI(0636)= 1000,
+  NRGRI(0637)= 1000,
+  NRGRI(0638)= 1000,
+  NRGRI(0639)=  972,
+  NRGRI(0640)=  972,
+  NRGRI(0641)=  960,
+  NRGRI(0642)=  960,
+  NRGRI(0643)=  960,
+  NRGRI(0644)=  960,
+  NRGRI(0645)=  960,
+  NRGRI(0646)=  960,
+  NRGRI(0647)=  960,
+  NRGRI(0648)=  960,
+  NRGRI(0649)=  960,
+  NRGRI(0650)=  960,
+  NRGRI(0651)=  960,
+  NRGRI(0652)=  960,
+  NRGRI(0653)=  900,
+  NRGRI(0654)=  900,
+  NRGRI(0655)=  900,
+  NRGRI(0656)=  900,
+  NRGRI(0657)=  900,
+  NRGRI(0658)=  900,
+  NRGRI(0659)=  900,
+  NRGRI(0660)=  864,
+  NRGRI(0661)=  864,
+  NRGRI(0662)=  864,
+  NRGRI(0663)=  864,
+  NRGRI(0664)=  864,
+  NRGRI(0665)=  864,
+  NRGRI(0666)=  864,
+  NRGRI(0667)=  864,
+  NRGRI(0668)=  864,
+  NRGRI(0669)=  864,
+  NRGRI(0670)=  810,
+  NRGRI(0671)=  800,
+  NRGRI(0672)=  800,
+  NRGRI(0673)=  800,
+  NRGRI(0674)=  800,
+  NRGRI(0675)=  800,
+  NRGRI(0676)=  800,
+  NRGRI(0677)=  768,
+  NRGRI(0678)=  768,
+  NRGRI(0679)=  768,
+  NRGRI(0680)=  750,
+  NRGRI(0681)=  750,
+  NRGRI(0682)=  750,
+  NRGRI(0683)=  750,
+  NRGRI(0684)=  729,
+  NRGRI(0685)=  729,
+  NRGRI(0686)=  720,
+  NRGRI(0687)=  720,
+  NRGRI(0688)=  720,
+  NRGRI(0689)=  720,
+  NRGRI(0690)=  720,
+  NRGRI(0691)=  720,
+  NRGRI(0692)=  720,
+  NRGRI(0693)=  675,
+  NRGRI(0694)=  675,
+  NRGRI(0695)=  675,
+  NRGRI(0696)=  675,
+  NRGRI(0697)=  675,
+  NRGRI(0698)=  648,
+  NRGRI(0699)=  640,
+  NRGRI(0700)=  640,
+  NRGRI(0701)=  640,
+  NRGRI(0702)=  640,
+  NRGRI(0703)=  640,
+  NRGRI(0704)=  640,
+  NRGRI(0705)=  640,
+  NRGRI(0706)=  600,
+  NRGRI(0707)=  600,
+  NRGRI(0708)=  600,
+  NRGRI(0709)=  600,
+  NRGRI(0710)=  576,
+  NRGRI(0711)=  576,
+  NRGRI(0712)=  576,
+  NRGRI(0713)=  576,
+  NRGRI(0714)=  576,
+  NRGRI(0715)=  576,
+  NRGRI(0716)=  540,
+  NRGRI(0717)=  540,
+  NRGRI(0718)=  540,
+  NRGRI(0719)=  540,
+  NRGRI(0720)=  540,
+  NRGRI(0721)=  512,
+  NRGRI(0722)=  512,
+  NRGRI(0723)=  500,
+  NRGRI(0724)=  500,
+  NRGRI(0725)=  486,
+  NRGRI(0726)=  480,
+  NRGRI(0727)=  480,
+  NRGRI(0728)=  480,
+  NRGRI(0729)=  480,
+  NRGRI(0730)=  480,
+  NRGRI(0731)=  450,
+  NRGRI(0732)=  450,
+  NRGRI(0733)=  450,
+  NRGRI(0734)=  432,
+  NRGRI(0735)=  432,
+  NRGRI(0736)=  432,
+  NRGRI(0737)=  432,
+  NRGRI(0738)=  405,
+  NRGRI(0739)=  400,
+  NRGRI(0740)=  400,
+  NRGRI(0741)=  400,
+  NRGRI(0742)=  384,
+  NRGRI(0743)=  375,
+  NRGRI(0744)=  375,
+  NRGRI(0745)=  360,
+  NRGRI(0746)=  360,
+  NRGRI(0747)=  360,
+  NRGRI(0748)=  360,
+  NRGRI(0749)=  360,
+  NRGRI(0750)=  360,
+  NRGRI(0751)=  324,
+  NRGRI(0752)=  320,
+  NRGRI(0753)=  320,
+  NRGRI(0754)=  320,
+  NRGRI(0755)=  300,
+  NRGRI(0756)=  300,
+  NRGRI(0757)=  288,
+  NRGRI(0758)=  288,
+  NRGRI(0759)=  288,
+  NRGRI(0760)=  270,
+  NRGRI(0761)=  256,
+  NRGRI(0762)=  250,
+  NRGRI(0763)=  250,
+  NRGRI(0764)=  240,
+  NRGRI(0765)=  240,
+  NRGRI(0766)=  240,
+  NRGRI(0767)=  225,
+  NRGRI(0768)=  216,
+  NRGRI(0769)=  216,
+  NRGRI(0770)=  200,
+  NRGRI(0771)=  200,
+  NRGRI(0772)=  192,
+  NRGRI(0773)=  192,
+  NRGRI(0774)=  180,
+  NRGRI(0775)=  180,
+  NRGRI(0776)=  160,
+  NRGRI(0777)=  160,
+  NRGRI(0778)=  150,
+  NRGRI(0779)=  144,
+  NRGRI(0780)=  144,
+  NRGRI(0781)=  128,
+  NRGRI(0782)=  125,
+  NRGRI(0783)=  120,
+  NRGRI(0784)=  120,
+  NRGRI(0785)=  108,
+  NRGRI(0786)=  100,
+  NRGRI(0787)=   96,
+  NRGRI(0788)=   90,
+  NRGRI(0789)=   81,
+  NRGRI(0790)=   75,
+  NRGRI(0791)=   72,
+  NRGRI(0792)=   72,
+  NRGRI(0793)=   60,
+  NRGRI(0794)=   60,
+  NRGRI(0795)=   50,
+  NRGRI(0796)=   45,
+  NRGRI(0797)=   40,
+  NRGRI(0798)=   32,
+  NRGRI(0799)=   25,
+  NRGRI(0800)=   18,
+ /
diff --git a/odb/share/odb/stalt.cmap b/odb/share/odb/stalt.cmap
new file mode 100644
index 0000000..2f632aa
--- /dev/null
+++ b/odb/share/odb/stalt.cmap
@@ -0,0 +1,3 @@
+Station altitude
+stalt at hdr
+0,-1
diff --git a/odb/share/odb/status.cmap b/odb/share/odb/status.cmap
new file mode 100644
index 0000000..02839ff
--- /dev/null
+++ b/odb/share/odb/status.cmap
@@ -0,0 +1,4 @@
+First 3 bits of body status word
+status at body
+0,-1
+4,4,0 ! Method=4 --> iand(status,4) + 0
diff --git a/odb/share/odb/t.cmap b/odb/share/odb/t.cmap
new file mode 100644
index 0000000..967c6cd
--- /dev/null
+++ b/odb/share/odb/t.cmap
@@ -0,0 +1,3 @@
+Temperature
+obsvalue at body
+220 320
diff --git a/odb/share/odb/t2m.cmap b/odb/share/odb/t2m.cmap
new file mode 100644
index 0000000..4f6470c
--- /dev/null
+++ b/odb/share/odb/t2m.cmap
@@ -0,0 +1,3 @@
+2 metre Temperature
+obsvalue at body
+220 320
diff --git a/odb/share/odb/target.cmap b/odb/share/odb/target.cmap
new file mode 100644
index 0000000..032b9ca
--- /dev/null
+++ b/odb/share/odb/target.cmap
@@ -0,0 +1,3 @@
+CCMA pool number (MPI-task)
+target at index
+0,-1 ! Automatic
diff --git a/odb/share/odb/tbr.cmap b/odb/share/odb/tbr.cmap
new file mode 100644
index 0000000..1f98a7f
--- /dev/null
+++ b/odb/share/odb/tbr.cmap
@@ -0,0 +1,3 @@
+Brightness temperature
+obsvalue at body
+200 300
diff --git a/odb/share/odb/tcelsius.cmap b/odb/share/odb/tcelsius.cmap
new file mode 100644
index 0000000..7ca23c6
--- /dev/null
+++ b/odb/share/odb/tcelsius.cmap
@@ -0,0 +1,4 @@
+Temperature (in C)
+obsvalue at body
+220 320
+1,1,-273.15 ! Method=1 --> Scaling: 1 * K - 273.15
diff --git a/odb/share/odb/tfahrenheit.cmap b/odb/share/odb/tfahrenheit.cmap
new file mode 100644
index 0000000..9d03664
--- /dev/null
+++ b/odb/share/odb/tfahrenheit.cmap
@@ -0,0 +1,5 @@
+Temperature (in F)
+obsvalue at body
+220 320
+1,1.8,-459.67 ! Method=1 --> Scaling: 1.8 * K - 459.67
+
diff --git a/odb/share/odb/time.cmap b/odb/share/odb/time.cmap
new file mode 100644
index 0000000..db4d399
--- /dev/null
+++ b/odb/share/odb/time.cmap
@@ -0,0 +1,4 @@
+Observed time (hour)
+time at hdr
+0 240000 ! Time range in original units (here: HHMMSS)
+2,0.0001,0 ! Method=2 --> Scaling: int(0.0001 * time) + 0
diff --git a/odb/share/odb/tslot.cmap b/odb/share/odb/tslot.cmap
new file mode 100644
index 0000000..00c08da
--- /dev/null
+++ b/odb/share/odb/tslot.cmap
@@ -0,0 +1,3 @@
+4D-VAR time slot
+tslot at index
+0,-1 ! Automatic scaling
diff --git a/odb/share/odb/wind.cmap b/odb/share/odb/wind.cmap
new file mode 100644
index 0000000..f5a6f8b
--- /dev/null
+++ b/odb/share/odb/wind.cmap
@@ -0,0 +1,3 @@
+Wind Speed (m/s)
+aux_1 at body
+0,-1 ! Automatic
diff --git a/odb/src/CMakeLists.txt b/odb/src/CMakeLists.txt
new file mode 100644
index 0000000..1b30689
--- /dev/null
+++ b/odb/src/CMakeLists.txt
@@ -0,0 +1,39 @@
+
+add_subdirectory(aux)
+add_subdirectory(compiler)
+add_subdirectory(ddl)
+add_subdirectory(ddl.CCMA)
+add_subdirectory(ddl.COUNTRYRSTRHBIAS)
+add_subdirectory(ddl.ECMA)
+add_subdirectory(ddl.ERACOUNTRYTTABLE11)
+add_subdirectory(ddl.ERACOUNTRYTTABLE12)
+add_subdirectory(ddl.MTOCOMP)
+add_subdirectory(ddl.PSBIAS)
+add_subdirectory(ddl.RSTBIAS)
+add_subdirectory(ddl.SONDETYPERSTRHBIAS)
+add_subdirectory(ddl.SONDETYPES)
+add_subdirectory(extras)
+add_subdirectory(include)
+add_subdirectory(lib)
+add_subdirectory(module)
+add_subdirectory(scripts)
+add_subdirectory(tools)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set_property(SOURCE lib/twindow.c PROPERTY COMPILE_DEFINITIONS _ABI64)
+endif()
+
+set_property(SOURCE aux/codb_netcdf.c aux/result.c aux/dtnum.c
+  PROPERTY COMPILE_DEFINITIONS HAS_NETCDF=0) # needed by include/codb_netcdf.h
+
+ecbuild_add_library(TARGET odb_lib OUTPUT_NAME odb
+  TYPE ${ODB_LIBS_TYPE}
+  SOURCES ${odb_aux_files} ${odb_lib_files} ${odb_module_files}
+  PRIVATE_INCLUDES ${ODB_INCLUDE_DIRS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/interface
+    ${CMAKE_CURRENT_SOURCE_DIR}/extras/ifsaux/include
+  LIBS odbifsaux odbec odbdummy ${DL_LIBRARIES})
+
+# Install Fortran modules
+
+install(CODE "EXECUTE_PROCESS (COMMAND \"${CMAKE_COMMAND}\" -E copy_directory \"${CMAKE_Fortran_MODULE_DIRECTORY}/\${CMAKE_CFG_INTDIR}\" \"${CMAKE_INSTALL_PREFIX}/module\")" )
diff --git a/odb/src/aux/CMakeLists.txt b/odb/src/aux/CMakeLists.txt
new file mode 100644
index 0000000..bb23ec0
--- /dev/null
+++ b/odb/src/aux/CMakeLists.txt
@@ -0,0 +1,118 @@
+list(APPEND aux_files
+
+    aux/binio.c
+    aux/bits.c
+    aux/cardinality.c
+    aux/cma_attach.c
+    aux/cma_bin_file.c
+    aux/cma_bin_info.c
+    aux/cma_byteswap.c
+    aux/cma_close.c
+    aux/cma_debug.c
+    aux/cma_detach.c
+    aux/cma_filesize.c
+    aux/cma_flpcheck.c
+    aux/cma_flperr.F90
+    aux/cma_get_concat.c
+    aux/cma_get_concat_byname.c
+    aux/cma_get_ddrs.c
+    aux/cma_get_report.c
+    aux/cma_info.c
+    aux/cma_is_packed.c
+    aux/cma_on_mrfs.c
+    aux/cma_open.c
+    aux/cma_prt_stat.F90
+    aux/cma_read.c
+    aux/cma_readb.c
+    aux/cma_readc.c
+    aux/cma_readf.c
+    aux/cma_readi.c
+    aux/cma_rewind.c
+    aux/cma_seek.c
+    aux/cma_seekb.c
+    aux/cma_seekf.c
+    aux/cma_seeki.c
+    aux/cma_stat.c
+    aux/cma_wrapup.c
+    aux/cma_write.c
+    aux/cma_writeb.c
+    aux/cma_writec.c
+    aux/cma_writef.c
+    aux/cma_writei.c
+    aux/codb2netcdf.F90
+    aux/codb_netcdf.c
+    aux/dca.c
+    aux/ds.c
+    aux/dtnum.c
+    aux/f_odb_layer.F90
+    aux/fileutil.c
+    aux/generic.c
+    aux/history.c
+    aux/idx.c
+    aux/info.c
+    aux/ioassign_hash.c
+    aux/ioassign_read.c
+    aux/ioassign_write.c
+    aux/ioconcat.c
+    aux/iocopy.c
+    aux/iogetattr.c
+    aux/iogetsize.c
+    aux/ioknowncmd.c
+    aux/ioprealloc.c
+    aux/iosetbuf.c
+    aux/iostrdup.c
+    aux/iostuff_init.c
+    aux/iotimes.c
+    aux/lzw.c
+    aux/magicwords.c
+    aux/md5sub.c
+    aux/memmap.c
+    aux/memory.c
+    aux/newio.c
+    aux/odb2mysql.c
+    aux/odbcrc.c
+    aux/odbcs_conf.c
+    aux/odbcs_error.c
+    aux/odbcs_signal.c
+    aux/odbcs_wrappers.c
+    aux/odbdump.c
+    aux/odbsql.c
+    aux/pcma.c
+    aux/pcma_1.c
+    aux/pcma_11to19.c
+    aux/pcma_2.c
+    aux/pcma_21to29.c
+    aux/pcma_255.c
+    aux/pcma_3.c
+    aux/pcma_31to39.c
+    aux/pcma_4.c
+    aux/pcma_5.c
+    aux/pcma_9.c
+    aux/pcma_mdis.c
+    aux/qtar_sub.c
+    aux/result.c
+    aux/runcmd.c
+    aux/simul.c
+    aux/swapbytes.c
+    aux/upcma.c
+    aux/util.c
+    aux/util_ccode.c
+    aux/util_filehandler.c
+    aux/util_iobuf.c
+    aux/util_stat.c
+    aux/vpack_bits.c
+)
+
+if(ODB_CLIENT_SERVER)
+
+  list(APPEND aux_files
+
+    aux/odbi_client.c
+    aux/odbi_common.c
+    aux/odbi_direct.c # uses global symbols from ../tools/odbi_direct_main.c
+    aux/odbi_server.c
+    aux/odbi_shared.c)
+
+endif()
+
+set(odb_aux_files ${aux_files} PARENT_SCOPE)
diff --git a/odb/src/aux/binio.c b/odb/src/aux/binio.c
new file mode 100644
index 0000000..4661038
--- /dev/null
+++ b/odb/src/aux/binio.c
@@ -0,0 +1,174 @@
+#include <stdio.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "alloc.h"
+
+/* Fortran-callable binary I/O utility */
+
+#define BINIO_CLOSED 0
+#define BINIO_FOPEN  1
+#define BINIO_POPEN  2
+
+typedef struct binio_ {
+  FILE *io;
+  char *name;
+  char *mode;
+  int kind;
+} Binio_t;
+
+PRIVATE Binio_t bin[FOPEN_MAX] = { 0 };
+
+void 
+binary_open_(int *channel,
+	     const char *name,
+	     const char *mode,
+	     int *rc
+	     /* Hidden arguments */
+	     ,int name_len
+	     ,int mode_len
+	     )
+{
+  int j;
+  int ret = 0;
+  int kind = BINIO_CLOSED;
+  FILE *io;
+  char *Name = NULL;
+  char *Mode = NULL;
+  char *pName;
+  char *pMode;
+
+  ALLOC(Name, name_len + 1);
+  for (j=0; j<name_len; j++) Name[j] = name[j];
+  for (j=name_len-1; j>=0; j--) {
+    if (!isspace(Name[j])) break;
+    name_len--;
+  }
+  Name[name_len] = '\0';
+  pName = Name;
+  while (isspace(*pName)) pName++;
+
+  ALLOC(Mode, mode_len + 1);
+  for (j=0; j<mode_len; j++) Mode[j] = mode[j];
+  for (j=mode_len-1; j>=0; j--) {
+    if (!isspace(Mode[j])) break;
+    mode_len--;
+  }
+  Mode[mode_len] = '\0';
+  pMode = Mode;
+  while (isspace(*pMode)) pMode++;
+
+  if (pName[0] == '|') {
+    pName++;
+    io = popen(pName, pMode);
+    kind = BINIO_POPEN;
+  }
+  else {
+    io = fopen(pName, pMode);
+    kind = BINIO_FOPEN;
+  }
+
+  if (!io) {
+    perror(pName);
+    ret = -1;
+    goto finish;
+  }
+
+  *channel = fileno(io);
+  bin[*channel].io = io;
+  bin[*channel].name = STRDUP(pName);
+  bin[*channel].mode = STRDUP(pMode);
+  bin[*channel].kind = kind;
+
+ finish:
+  FREE(Name);
+  *rc = ret;
+}
+
+
+void
+binary_flush_(const int *channel,
+	      int *rc)
+{
+  int ret = 0;
+  FILE *io = bin[*channel].io;
+  ret = fflush(io);
+
+  /* finish: */
+  *rc = ret;
+}
+
+
+void
+binary_close_(int *channel,
+	      int *rc)
+{
+  int ret = 0;
+  FILE *io = bin[*channel].io;
+  if (bin[*channel].kind == BINIO_FOPEN) {
+    ret = fclose(io);
+    bin[*channel].io = NULL;
+    FREE(bin[*channel].name);
+  }
+  else if (bin[*channel].kind == BINIO_POPEN) {
+    ret = pclose(io);
+    bin[*channel].io = NULL;
+    FREE(bin[*channel].name);
+  }
+  *channel = -1;
+
+  /* finish: */
+  *rc = ret;
+}
+
+
+void
+binary_put_(const int *channel,
+	    const char bytes[],
+	    const int *nbytes,
+	    int *rc)
+{
+  int ret = 0;
+  FILE *io = bin[*channel].io;
+  int nb;
+
+  nb = fwrite(bytes, sizeof(char), *nbytes, io);
+  if (nb != sizeof(char) * (*nbytes)) {
+    perror("***Error in BINARY_PUT: fwrite");
+    ret = -1;
+    goto finish;
+  }
+
+  ret = nb;
+ finish:
+  *rc = ret;
+}
+
+
+void
+binary_get_(const int *channel,
+	    char bytes[],
+	    const int *nbytes,
+	    int *rc)
+{
+  int ret = 0;
+  FILE *io = bin[*channel].io;
+  int nb;
+
+  nb = fread(bytes, sizeof(char), *nbytes, io);
+  if (nb != sizeof(char) * (*nbytes)) {
+    if (!feof(io)) {
+      perror("***Error in BINARY_GET: fread");
+      ret = -1;
+      goto finish;
+    }
+  }
+
+  ret = nb;
+ finish:
+  *rc = ret;
+}
+
+
diff --git a/odb/src/aux/bits.c b/odb/src/aux/bits.c
new file mode 100644
index 0000000..d806027
--- /dev/null
+++ b/odb/src/aux/bits.c
@@ -0,0 +1,511 @@
+/* bits.c */
+
+#include <stdio.h>
+#include "alloc.h"
+#include "bits.h"
+#include "swapbytes.h"
+
+/* direct bit stream manipulation */
+
+/* 
+   The following array bitcnt[] contains the number of bits set (=1) 
+   for each unsigned char (=byte) in range between 0 and 255.
+   For reference, the following piece of (Fortran90!) code was used to generated this table :
+
+   program bitcnt
+   implicit none
+   integer j
+   integer numbits
+   do j=0,255
+     if (mod(j,16) == 0) print *,' '
+     write(*,'(i2,",")',advance='no') numbits(j)
+   enddo
+   end program bitcnt
+   
+   function numbits(j)
+   implicit none
+   integer i,j,tmp,numbits
+   numbits = 0
+   tmp = j
+   do i=1,8
+     if (iand(tmp,1) == 1) numbits = numbits + 1
+     tmp = tmp/2
+   enddo
+   end function numbits
+
+*/
+
+#if defined(VPP) || defined(NECSX)
+/* Preserve chances for vectorization */
+static const int 
+#else
+static const unsigned char
+#endif
+bitcnt[256] = {
+  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+  4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+#define GETCOUNT(t, Nbw, ptr, offset, Nbits) \
+  const t *ww = ptr; \
+  int Offset = offset; \
+  const t one = 0x1; \
+  int j; \
+  for (j=0; j<Nbits; j++) { \
+    int wordno = (j + Nbw)/Nbw - 1; \
+    int shft  = Nbw - 1 - j%Nbw; \
+    if ((ww[Offset+wordno] >> shft) & one) cnt++; \
+  } /* for (j=0; j<Nbits; j++) */ \
+
+#define GETCOUNT_PRE(t, Nbw, ptr, Nbits) \
+  const t *w = ptr; \
+  const t one = 0x1; \
+  int j; \
+  int modulo = Nbits%Nbw; \
+  for (j=0; j<Nbits-modulo; j+=Nbw) { \
+    int wordno = (j + Nbw)/Nbw - 1; \
+    int shft  = Nbw - 1 - j%Nbw
+
+/* CNT8OPT works *ONLY* with byte-data or big-endian non-byte data */
+#define CNT8OPT cnt += bitcnt[w[wordno]]
+
+#define CNT8 \
+    if ((w[wordno] >> shft--) & one) cnt++; if ((w[wordno] >> shft--) & one) cnt++; \
+    if ((w[wordno] >> shft--) & one) cnt++; if ((w[wordno] >> shft--) & one) cnt++; \
+    if ((w[wordno] >> shft--) & one) cnt++; if ((w[wordno] >> shft--) & one) cnt++; \
+    if ((w[wordno] >> shft--) & one) cnt++; if ((w[wordno] >> shft--) & one) cnt++
+
+#define CNT16 CNT8; CNT8
+#define CNT32 CNT16; CNT16
+#define CNT64 CNT32; CNT32
+
+#define GETCOUNT_POST(t, Nbw, ptr, Nbits) \
+  } /* for (j=0; j<Nbits-modulo; j+=Nbw) */ \
+  if (modulo > 0) { GETCOUNT(t, Nbw, w, (Nbits-modulo)/Nbw, modulo); }
+
+#define GETCOUNT_08(t, Nbw, ptr, Nbits) \
+        GETCOUNT_PRE(t, Nbw, ptr, Nbits); \
+        CNT8OPT; GETCOUNT_POST(t, Nbw, ptr, Nbits)
+
+#define GETCOUNT_16(t, Nbw, ptr, Nbits) \
+        GETCOUNT_PRE(t, Nbw, ptr, Nbits); \
+        CNT16; GETCOUNT_POST(t, Nbw, ptr, Nbits)
+
+#define GETCOUNT_32(t, Nbw, ptr, Nbits) \
+        GETCOUNT_PRE(t, Nbw, ptr, Nbits); \
+        CNT32; GETCOUNT_POST(t, Nbw, ptr, Nbits)
+
+#define GETCOUNT_64(t, Nbw, ptr, Nbits) \
+        GETCOUNT_PRE(t, Nbw, ptr, Nbits); \
+        CNT64; GETCOUNT_POST(t, Nbw, ptr, Nbits)
+
+
+int
+ODBIT_get_count(const void *data, int nbits, int nbw)
+{
+  int cnt = 0;
+  if (nbits > 0) {
+    switch (nbw) {
+    case  8: { GETCOUNT_08(unsigned char         , 8,data,nbits) ; } break;
+    case 16: { GETCOUNT_16(unsigned short int    ,16,data,nbits); } break;
+    case 32: { GETCOUNT_32(unsigned int          ,32,data,nbits); } break;
+    case 64: { GETCOUNT_64(unsigned long long int,64,data,nbits); } break;
+    }
+  }
+  return cnt;
+}
+
+
+void 
+codbit_get_count_(const void *data,
+		  const int *nbits,
+		  const int *nbw,
+		  int *rc)
+{ /* Get the count of number of bits set to 1 */
+  *rc = ODBIT_get_count(data, *nbits, *nbw);
+}
+
+
+#define GETIDX(t, Nbw) \
+case Nbw: { \
+  const t *w = data; \
+  const t one = 0x1; \
+  int j, Nbits = *nbits; \
+  for (j=0; j<Nbits; j++) { \
+    int wordno = (j + Nbw)/Nbw - 1; \
+    int shft  = Nbw - 1 - j%Nbw; \
+    /* No array bound checks in idx[] below; make sure *nidx is sufficient */ \
+    if ((w[wordno] >> shft) & one) idx[cnt++] = j; /* C-indexing : [0 .. *nbits - 1] */ \
+  } /* for (j=0; j<Nbits; j++) */ \
+} break
+
+
+void
+codbit_getidx_(const void *data, 
+	       const int *nbits,
+	       const int *nbw,
+	       unsigned int idx[], /* bit numbers [0 .. *nbits - 1] that are set to 1 */
+	       const int *nidx, /* length of idx[], potentially >= *nbits */
+	       int *rc) /* no. of bits set to 1 */
+{ /* gets indices [0 .. *nbits - 1] of bits that are set to 1 */
+  int cnt = 0;
+  if (idx && *nidx > 0) {
+    switch (*nbw) {
+      GETIDX(unsigned char         ,  8);
+      GETIDX(unsigned short int    , 16);
+      GETIDX(unsigned int          , 32);
+      GETIDX(unsigned long long int, 64);
+    }
+  }
+  else {
+    /* idx[] NULL-pointer or *nidx <= 0 ==> return count, as negative number */
+    cnt = -ODBIT_get_count(data, *nbits, *nbw);
+  }
+  *rc = cnt;
+}
+
+
+unsigned int *
+ODBIT_getidx(const void *data, int nbits, int nbw, int *idxlen)
+{
+  int cnt = ODBIT_get_count(data, nbits, nbw);
+  unsigned int *idx = NULL;
+  ALLOC(idx, cnt);
+  codbit_getidx_(data, &nbits, &nbw, idx, &cnt, idxlen);
+  return idx; /* A potential memory leakage; must be released via ODBIT_free(idx) */
+}
+
+
+void
+ODBIT_free(void *v)
+{
+  FREE(v); /* just to use consistent set of ALLOC & FREE */
+}
+
+
+#define GETBIT(t, Nbw) \
+case Nbw: { \
+  const t *w = data; \
+  int wordno = (bitno + Nbw)/Nbw - 1; \
+  int shft  = Nbw - bitno%Nbw - 1; \
+  rc = (w[wordno] >> shft) & 0x1; \
+} break
+
+
+int
+ODBIT_get(const void *data, int nbits, int nbw, int bitno)
+{
+  int rc = -1;
+  if (nbits > 0 && bitno >= 0 && bitno < nbits) {
+    switch (nbw) {
+      GETBIT(unsigned char         ,  8);
+      GETBIT(unsigned short int    , 16);
+      GETBIT(unsigned int          , 32);
+      GETBIT(unsigned long long int, 64);
+    }
+  }
+  return rc; /* Successful returns are 0 or 1 ; out of bit-range returns -1 */
+}
+
+
+void 
+codbit_get_(const void *data, 
+	    const int *nbits,
+	    const int *nbw,
+	    const int *bitno, /* C-indexing : between [0 .. *nbits - 1] */
+	    int *rc)
+{
+  *rc = ODBIT_get(data, *nbits, *nbw, *bitno);
+}
+
+
+int
+ODBIT_test(const void *data, int nbits, int nbw, int bitno1, int bitno2)
+{ /* 
+     Returns  1, if ALL bits in range [bitno1,bitno2] are set 
+     Returns  0, if ALL bits in range [bitno1,bitno2] are NOT set
+     Returns -1, if when the first bit in the range happens to go out of bounds
+   */
+  int j, rctot = 0, n = bitno2 - bitno1 + 1;
+  int rc = 0;
+  for (j=bitno1; j<=bitno2; j++) {
+    rc = ODBIT_get(data, nbits, nbw, j); /* Can be 1, 0 or -1 */
+    if (rc == 1) {
+      rctot++; 
+    }
+    else {
+      /* Note: rc == -1 counts as out-of-bounds */
+      break;
+    }
+  } 
+  return (n > 0 && rctot == n) ? 1 : rc;
+}
+
+
+char *
+ODBIT_getmap(const void *data, int nbits, int nbw, char *s)
+{ /* 
+     Returns a character-string s[] of length nbits+1 (= its minimum length)
+     containing a stream of 0's and 1's (left-to-right) for printing etc. purposes 
+     '-' means bit tested was out of its range
+  */
+  if (!s) ALLOC(s, nbits+1); /* A potential memory leak; use ODBIT_free(s) to release the space */
+  if (s) {
+    char *p = s;
+    int j;
+    for (j=0; j<nbits; j++) {
+      int test = ODBIT_test(data, nbits, nbw, j, j);
+      *p++ = (test == 1) ? '1' : ((test == 0) ? '0' : '-');
+    }
+    *p = '\0';
+  }
+  return s; 
+}
+
+
+#define SETBIT(t, Nbw, One) \
+case Nbw: { \
+  int j; \
+  t *w = data; \
+  for (j=bitno1; j<=bitno2; j++) { \
+    int wordno = (j + Nbw)/Nbw - 1; \
+    int shft  = Nbw - j%Nbw - 1; \
+    t mask = (One << shft); \
+    w[wordno] |= mask; \
+  } \
+} break
+
+
+void
+ODBIT_set(void *data, int nbits, int nbw, int bitno1, int bitno2)
+{ /* sets bit number(s) in range [bitno1,bitno2] to 1 */
+  if ( nbits >  0 && bitno1 <= bitno2 &&
+      bitno1 >= 0 && bitno1 <  nbits &&
+      bitno2 >= 0 && bitno2 <  nbits) {
+    switch (nbw) {
+      SETBIT(unsigned char         ,  8, 1U);
+      SETBIT(unsigned short int    , 16, 1U);
+      SETBIT(unsigned int          , 32, 1U);
+      SETBIT(unsigned long long int, 64, 1ull);
+    }
+  }
+}
+
+
+void 
+codbit_set_(void *data, 
+	    const int *nbits,
+	    const int *nbw,
+	    const int *bitno1,
+	    const int *bitno2) /* C-indexing : between [0 .. *nbits - 1] */
+{
+  ODBIT_set(data, *nbits, *nbw, *bitno1, *bitno2);
+}
+
+
+void
+codbit_setidx_(void *data, 
+	       const int *nbits,
+	       const int *nbw,
+	       const unsigned int idx[], /* the bit numbers [0 .. *nbits - 1] that will be set to 1 */
+	       const int *nidx) /* length of idx[], potentially >= *nbits */
+{
+  if (idx && *nidx > 0) {
+    int j, Nidx = *nidx;
+    for (j=0; j<Nidx; j++) ODBIT_set(data, *nbits, *nbw, idx[j], idx[j]);
+  }
+}
+
+#define UNSETBIT(t, Nbw, One) \
+case Nbw: { \
+  int j; \
+  t *w = data; \
+  for (j=bitno1; j<=bitno2; j++) { \
+    int wordno = (j + Nbw)/Nbw - 1; \
+    int shft  = Nbw - j%Nbw - 1; \
+    t mask = (One << shft); \
+    w[wordno] &= ~mask; \
+  } \
+} break
+
+
+void
+ODBIT_unset(void *data, int nbits, int nbw, int bitno1, int bitno2)
+{ /* sets bit number(s) in range [bitno1,bitno2] to 0 */
+  if ( nbits >  0 && bitno1 <= bitno2 &&
+      bitno1 >= 0 && bitno1 <  nbits &&
+      bitno2 >= 0 && bitno2 <  nbits) {
+    switch (nbw) {
+      UNSETBIT(unsigned char         ,  8, 1U);
+      UNSETBIT(unsigned short int    , 16, 1U);
+      UNSETBIT(unsigned int          , 32, 1U);
+      UNSETBIT(unsigned long long int, 64, 1ull);
+    }
+  }
+}
+
+
+void 
+codbit_unset_(void *data, 
+	      const int *nbits,
+	      const int *nbw,
+	      const int *bitno1,
+	      const int *bitno2) /* C-indexing : between [0 .. *nbits - 1] */
+{
+  ODBIT_unset(data, *nbits, *nbw, *bitno1, *bitno2);
+}
+
+
+void
+codbit_unsetidx_(void *data, 
+		 const int *nbits,
+		 const int *nbw,
+		 const unsigned int idx[], /* the bit numbers [0 .. *nbits - 1] that will be set to 0 */
+		 const int *nidx) /* length of idx[], potentially >= *nbits */
+{
+  if (idx && *nidx > 0) {
+    int j, Nidx = *nidx;
+    for (j=0; j<Nidx; j++) ODBIT_unset(data, *nbits, *nbw, idx[j], idx[j]);
+  }
+}
+
+
+#define AND_OR(t,Nbw,One,op1,op2) \
+case Nbw: { \
+  t *wout = out_data; \
+  const t *win = in_data; \
+  int nw = (*nbits)/Nbw; \
+  int nrembits = (*nbits)%Nbw; \
+  int j; \
+  /* Full words first */ \
+  for (j=0; j<nw; j++) wout[j] op1 win[j]; /* Nbw-bits at a time */ \
+  if (nrembits > 0) { /* Remainder of the bits */ \
+    t *last_word_out = &wout[nw]; \
+    const t *last_word_in = &win[nw]; \
+    t value = 0; \
+    const t one = 0x1; \
+    for (j=0; j<nrembits; j++) { \
+      int shft = Nbw - 1 - j%Nbw; \
+      if ( (((*last_word_out) >> shft) & 0x1) op2 \
+	   (((*last_word_in ) >> shft) & 0x1) ) { \
+	t mask = (One << shft); \
+	value |= mask; \
+      } \
+    } /* for (j=0; j<nrembits; j++) */ \
+    for (j=nrembits; j<Nbw; j++) { \
+      /* Keep bits between [nrembits .. Nbw-1] unchanged in the last word */ \
+      int shft = Nbw - 1 - j%Nbw; \
+      t mask = (One << shft); \
+      value |= ((*last_word_out) & mask); \
+    } \
+    *last_word_out = value; \
+  } /* if (nrembits > 0) */ \
+} break
+
+
+void 
+codbit_and_(void *out_data, 
+	    const void *in_data,
+	    const int *nbits,
+	    const int *nbw)
+{ /* BITAND of two bit-vectors of *nbits bit-elements */
+  if (*nbits > 0) {
+    switch (*nbw) {
+      AND_OR(unsigned char         , 8,1U  ,&=,&&);      
+      AND_OR(unsigned short int    ,16,1U  ,&=,&&);      
+      AND_OR(unsigned int          ,32,1U  ,&=,&&);      
+      AND_OR(unsigned long long int,64,1ull,&=,&&);      
+    }
+  }
+}
+
+
+void 
+codbit_or_(void *out_data, 
+	   const void *in_data,
+	   const int *nbits,
+	   const int *nbw)
+{ /* BITOR of two bit-vectors of *nbits bit-elements */
+  if (*nbits > 0) {
+    switch (*nbw) {
+      AND_OR(unsigned char         , 8,1U  ,|=,||);      
+      AND_OR(unsigned short int    ,16,1U  ,|=,||);      
+      AND_OR(unsigned int          ,32,1U  ,|=,||);      
+      AND_OR(unsigned long long int,64,1ull,|=,||);      
+    }
+  }
+}
+
+/* Leading zero counts */
+
+/*
+  The following table contains the count of leading 
+  zeros in a 4-bit word
+*/
+
+#if defined(VPP) || defined(NECSX)
+/* Preserve chances for vectorization */
+static const int 
+#else
+static const unsigned char
+#endif
+lzctbl[16] = {
+  4, 3, 2, 2, 1, 1, 1, 1,
+  0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+#define DO_LZC(type, n, byteswap_macro) \
+case n: \
+{ \
+  const type *u = data; \
+  type x = iam_little_endian ? byteswap_macro(*u) : (*u); \
+  int shift = n - 4; \
+  for (; shift >= 0; shift -= 4) { \
+    int cnt = lzctbl[(x>>shift) & 0xF]; \
+    lzc += cnt; \
+    if (cnt != 4) break; \
+  } \
+} break
+
+
+int
+ODBIT_lzc(const void *data, int nbw)
+{ /* Counts the number of leading zero bits in a {8,16,32,64}-bit word*/
+  int lzc = 0;
+  const unsigned int ulbtest = 0x12345678;
+  const unsigned char *clbtest = (const unsigned char *)&ulbtest;
+  int iam_little_endian = (*clbtest == 0x78);
+  switch (nbw) {
+    DO_LZC(unsigned char         ,  8, bswap8bits );
+    DO_LZC(unsigned short int    , 16, bswap16bits);
+    DO_LZC(unsigned int          , 32, bswap32bits);
+    DO_LZC(unsigned long long int, 64, bswap64bits);
+  }
+  return lzc;
+}
+
+void
+codbit_lzc_(const void *data, 
+	    const int *nbw, 
+	    int *lzc)
+{
+  /* Fortran callable lzc */
+  if (lzc) {
+    *lzc = (data && nbw) ? ODBIT_lzc(data, *nbw) : 0;
+  }
+}
diff --git a/odb/src/aux/cardinality.c b/odb/src/aux/cardinality.c
new file mode 100644
index 0000000..1621fe7
--- /dev/null
+++ b/odb/src/aux/cardinality.c
@@ -0,0 +1,270 @@
+/* cardinality.c */
+
+#include "odb.h"
+#include "idx.h"
+
+typedef struct _card_t {
+  /* Binary tree */
+  double *key; /* keys to compare */
+  struct _card_t *left;  /* memcmp() > 0 */
+  struct _card_t *right; /* memcmp() < 0 */
+  Bool alloc_here;
+} card_t;
+
+
+static card_t **begin_card = NULL;
+
+
+PUBLIC void
+InitCard()
+{
+  if (!begin_card) {
+    DEF_INUMT;
+    CALLOC(begin_card, inumt);
+  }
+}
+
+
+PRIVATE card_t *
+GetCard(const double key[], int keylen)
+{
+  DEF_IT;
+  card_t *p = NULL;
+  if (key && keylen > 0) {
+    keylen *= sizeof(*key); /* Now in bytes */
+    p = begin_card[IT];
+    while (p) {
+      int cmp = memcmp(p->key,key,keylen);
+      if (cmp == 0) { /* A match */
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+  }
+  return p;
+}
+
+
+PRIVATE card_t *
+PutCard(const double key[], int keylen, double *mem, 
+	Bool alloc_here, Bool *added)
+{
+  DEF_IT;
+  card_t *p = GetCard(key, keylen);
+  if (added) *added = false;
+  if (keylen > 0 && !p) {
+    int j;
+    CALLOC(p,1);
+    if (!mem) {
+      ALLOC(p->key, keylen);
+      p->alloc_here = true;
+    }
+    else {
+      p->key = mem; /* to avoid memory fragmentation */
+      p->alloc_here = alloc_here;
+    }
+    for (j=0; j<keylen; j++) p->key[j] = key[j];
+    if (begin_card[IT]) {
+      card_t *top = begin_card[IT];
+      keylen *= sizeof(*key); /* Now in bytes */
+      while (top) {
+	int cmp = memcmp(top->key,p->key,keylen);
+        card_t *next = NULL;
+        if (cmp < 0) {
+          if (!top->left) { top->left = p; } else { next = top->left; }
+        }
+        else {
+          if (!top->right) { top->right = p; } else { next = top->right; }
+        }
+        top = next; /* If next == NULL => new position in tree found => get out */
+      }
+    }
+    else {
+      begin_card[IT] = p;
+    }
+    if (added) *added = true;
+  }
+  return p;
+}
+
+
+PRIVATE int
+DelCard(card_t *p)
+{
+  int rc = 0;
+  if (p) {
+    if (p->left) rc += DelCard(p->left);
+    if (p->right) rc += DelCard(p->right);
+    if (p->alloc_here) FREE(p->key);
+    FREE(p);
+    rc++;
+  }
+  return rc;
+}
+
+
+PRIVATE int
+DelAllCard()
+{
+  int rc = 0;
+  if (begin_card) {
+    DEF_IT;
+    card_t *p = begin_card[IT];
+    rc += DelCard(p);
+    begin_card[IT] = NULL;
+  }
+  return rc;
+}
+
+
+PUBLIC void
+codb_cardinality_(const int *ncols, const int *nrows, const int *lda,
+		  const double a[], /* A Fortran matrix A(LDA,1:NCOLS), LDA >= NROWS */
+		  int *rc,          /* cardinality i.e. number of distinct values <= NROWS */
+		  int unique_idx[], /* if not NULL, then Fortran-indices to unique rows of A upon output */
+		  const int *nunique_idx, /* Number of elements allocated for unique_idx[] */
+		  const int *bailout /* Bailout from cardinality study after this many distinct entries found */
+		  )
+{
+  /* 
+     Calculates no. of distinct values on a column or set of columns;
+     Essentially gives the number of rows for 'SELECT DISTINCT col1,col2,..,colN' 
+     Also returns (Fortran) indices to the unique row positions
+  */
+
+  int nunique = nunique_idx ? *nunique_idx : 0;
+  int sign = 1;
+  int klen, kldim, kvals, kvals8;
+  int i, j, keff;
+  double *pd;
+  double *mem = NULL, *pmem;
+  int nmem;
+  int Bailout = bailout ? *bailout : 0;
+  Bool Bailout_reached = false;
+  Bool onekey; /* true if a very common case of one (key) column only */
+  Bool alloc_here = false;
+  card_t *plast = NULL;
+
+  klen = nrows ? *nrows : 0;
+  kldim = lda ? *lda : klen;
+  kvals = ncols ? *ncols : 1;
+  kvals8 = kvals * sizeof(*pd);
+  
+  onekey = (kvals == 1) ? true : false;
+
+  if (Bailout <= 0) Bailout = klen + 1;
+
+  if (!onekey) {
+    ALLOC(pd, kvals);
+  }
+  else {
+    pd = (double *)a; /* a[] is not overwritten, though */
+  }
+
+  if (!begin_card) InitCard(); /* Normally never called here */
+
+  nmem = ((klen+9)/10)*kvals; /* Assume initially that 1:10th of total rows maybe distinct keys */
+  if (nmem > 0) {
+    ALLOC(mem, nmem);
+    alloc_here = true;
+  }
+  pmem = mem;
+
+  keff = 0;
+  for (i=0; i<klen; i++) {
+    Bool is_unique = false;
+    if (!onekey) { /* More than one key */
+      for (j=0; j<kvals; j++) pd[j] = a[kldim*j + i];
+    }
+
+    if (plast && memcmp(plast->key,pd,kvals8) == 0) {
+      /* 
+	 The entries "pd" are the same as (one of) the previously tried entries 
+	 i.e. cannot be unique
+      */
+      is_unique = false;
+    }
+    else {
+      if (pmem) {
+	if (pmem >= mem + nmem) {
+	  /* Need more memory for keys in a less fragmented manner.
+	     Please note that previously allocated "mem" will be freed either in
+	     DelAllCard() or via FREE(mem) after the for-loop "i" */
+	  nmem = ((klen-i+3)/4)*kvals; /* Assume that 1:4th of total rows still available maybe distinct keys */
+	  ALLOC(mem, nmem);
+	  pmem = mem;
+	  alloc_here = true;
+	}
+	else {
+	  alloc_here = false;
+	}
+      } /* if (pmem) */
+      /* 
+	 The "is_unique" will be set to "true" if a new entry will be added to the cardinality binary tree.
+	 The "plast" remembers the latest "found" position. 
+	 The use of "plast" may give some speedup in the next round of "i".
+      */
+      plast = PutCard(pd, kvals, pmem, alloc_here, &is_unique);
+      if (is_unique && pmem) pmem += kvals;
+    }
+
+    if (is_unique) {
+      if (nunique > 0 && unique_idx && keff < nunique) unique_idx[keff] = i+1; /* "+1" due to Fortran-indexing */
+      if (sign == 1 && nunique > 0 && unique_idx && keff >= nunique) sign = -1; /* Not enough space in unique_idx */
+      keff++;
+      if (keff >= Bailout) {
+	/* Too many distinct values ... bailing out */
+	Bailout_reached = true;
+	keff = 0; /* bailed out from (failed) cardinality study */
+	break;
+      }
+    } /* if (is_unique) */
+
+    if (onekey) pd++;
+  } /* for (i=0; i<klen; i++) */
+  if (rc) *rc = sign * keff; /* ABS(*rc) is the space required for unique_idx[] */
+
+  DelAllCard(); 
+  /* Please note that DelAllCard() took care of deallocation of "mem"'s, 
+     unless the condition below is true */
+  if (pmem && pmem == mem) FREE(mem);
+
+  if (!onekey) FREE(pd);
+}
+
+#ifdef STANDALONE_TEST
+int main()
+{
+  int rc = 0;
+  double *d = NULL;
+  FILE *fp = stdin;
+  int n = 0;
+  if (fscanf(fp,"%d", &n) == 1) {
+    int j;
+    ALLOC(d,n);
+    for (j=0; j<n; j++) {
+      if (fscanf(fp,"%lf", &d[j]) != 1) {
+	rc = -(j+1);
+	break;
+      }
+    }
+  }
+  else {
+    rc = 1;
+  }
+  if (rc == 0 && n > 0) {
+    int ncard = 0;
+    int ncols = 1;
+    int nrows = n;
+    int lda = n;
+    int *idx = NULL;
+    CALLOC(idx, n);
+    codb_cardinality_(&ncols, &nrows, &lda,
+		      d, &ncard, idx, &n, NULL);
+    printf("n = %d, ncard = %d\n",n, ncard);
+    FREE(idx);
+  }
+  FREE(d);
+  return rc;
+}
+#endif
diff --git a/odb/src/aux/cma_attach.c b/odb/src/aux/cma_attach.c
new file mode 100644
index 0000000..c16778f
--- /dev/null
+++ b/odb/src/aux/cma_attach.c
@@ -0,0 +1,94 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void 
+cma_attach_(integer4       *unit, 
+	    const char     *filename,
+	    const char     *mode,
+	    integer4       *retcode,
+	    /* Hidden arguments to Fortran-program */
+	    int             len_filename,
+	    int             len_mode)
+{
+  int rc = 0;
+  Boolean found = false;
+  Boolean re_open = false;
+  Boolean read_only = false;
+  int maxcmaio = CMA_get_MAXCMAIO();
+  int i, index = -1;
+  char *sname;    
+  char Mode;
+  int tid = get_thread_id_();
+
+  sname = IOstrdup(filename, &len_filename); /* sname now STRDUP'ed */
+
+  if (iostuff_debug) {
+    fprintf(stderr,"cma_attach('%s') :\n",sname);
+  }
+
+  if (!mode) {
+    /* Error : Invalid open mode */
+    rc = -3;
+    goto finish;
+  }
+
+  Mode = isupper(*mode) ? tolower(*mode) : *mode;
+
+  if (Mode != 'r' && Mode != 'w') {
+    /* Error : Invalid open mode */
+    rc = -3;
+    goto finish;
+  }
+
+  read_only = (Mode == 'r') ? true : false;
+
+  for (i=0; i<maxcmaio; i++) {
+    IOcma *pcmaio = &cmaio[tid][i];
+    if (pcmaio->io.is_inuse && 
+	pcmaio->io.is_detached && 
+	/* The following test prevents from (accidental) attaching to 
+	   a file with conflicting open mode */
+	(pcmaio->io.read_only == read_only)) {
+      if (strequ(pcmaio->io.logical_name, sname)) {
+	found = true;
+	index = i;
+	break;
+      }
+    }
+  }
+
+  FREE(sname);
+
+  if (!found) {
+    re_open = true;
+  }
+  else {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    pcmaio->io.is_detached = false;
+
+    if (iostuff_debug) {
+      fprintf(stderr," : unit=%d; file(s)=('%s' => '%s%s') : numbins=%d",
+	      index, 
+	      pcmaio->io.logical_name, 
+	      pcmaio->io.leading_part,
+	      (pcmaio->io.numbins == 1) ? "\0" : ",*",
+	      pcmaio->io.numbins);
+    }
+    
+    *unit = index;
+    rc = pcmaio->io.numbins;
+  }
+
+  if (re_open) {
+    cma_open_(unit, filename, mode, retcode, len_filename, len_mode);
+    index = *unit;
+    rc = *retcode;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_bin_file.c b/odb/src/aux/cma_bin_file.c
new file mode 100644
index 0000000..513c4be
--- /dev/null
+++ b/odb/src/aux/cma_bin_file.c
@@ -0,0 +1,39 @@
+#include "cmaio.h"
+
+void 
+cma_bin_file_(const integer4 *unit,
+	      char *filename,
+	      integer4 *retcode,
+	      int len_filename)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  int bin   = IOBIN(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (bin >= 0 && bin < pcmaio->io.numbins) {
+      IObin *pbin = &pcmaio->io.bin[bin];
+      int len = MIN(len_filename, strlen(pbin->true_name));
+      int i;
+
+      strncpy(filename, pbin->true_name, len);
+      for (i=len; i<len_filename; i++) 
+	filename[i] = ' ';
+
+      rc = len;
+    }
+    else {
+      /* Error : Attempt to use an invalid bin */
+      rc = -5;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_bin_info.c b/odb/src/aux/cma_bin_info.c
new file mode 100644
index 0000000..2893976
--- /dev/null
+++ b/odb/src/aux/cma_bin_info.c
@@ -0,0 +1,22 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_bin_info_(const integer4 *unit,
+	      integer4       *numbins,
+	      integer4       *binfactor)
+{
+  int index = IOINDEX(*unit);
+
+  if (iostuff_debug) fprintf(stderr,"cma_bin_info(%d)\n", *unit);
+
+  *binfactor = IOBINFACTOR;
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+    *numbins = pcmaio->io.is_inuse ? pcmaio->io.numbins : 0;
+  }
+  else {
+    *numbins = -1;
+  }
+}
diff --git a/odb/src/aux/cma_byteswap.c b/odb/src/aux/cma_byteswap.c
new file mode 100644
index 0000000..a105480
--- /dev/null
+++ b/odb/src/aux/cma_byteswap.c
@@ -0,0 +1,37 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_get_byteswap_(const integer4 *unit, integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+    if (pcmaio->io.is_inuse) {
+      rc = pcmaio->io.req_byteswap;
+    }
+  }
+
+  *retcode = rc;
+}
+
+FORTRAN_CALL void
+cma_set_byteswap_(const integer4 *unit, 
+		  const integer4 *toggle,
+		  integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+    if (pcmaio->io.is_inuse) {
+      pcmaio->io.req_byteswap = *toggle;
+    }
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_close.c b/odb/src/aux/cma_close.c
new file mode 100644
index 0000000..72f8547
--- /dev/null
+++ b/odb/src/aux/cma_close.c
@@ -0,0 +1,127 @@
+#include "cmaio.h"
+#include "cdrhook.h"
+
+FORTRAN_CALL void 
+cma_close_(const integer4 *unit, integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  /* int bin = IOBIN(*unit); */ /* Ignore, since closing ALL bins */
+  DRHOOK_START(cma_close_);
+
+  if (iostuff_debug) fprintf(stderr,"cma_close(%d)\n",index);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      int j, numbins = pcmaio->io.numbins;
+      int (*close_func)(FILE *stream) = 
+	((pcmaio->io.scheme & external) == external) ? pclose : fclose;
+
+      for (j=0; j<numbins; j++) {
+	IObin *pbin = &pcmaio->io.bin[j];
+
+	if (iostuff_stat) IOtimes(NULL);
+	close_func(pbin->fp);
+	if (iostuff_stat) {
+	  IOtimes(&pbin->stat.t);
+	  pbin->stat.num_trans++;
+	}
+
+	if (iostuff_stat && iostuff_stat_ftn_unit >= 0) {
+	  char *p;
+	  char *str_open_time, *str_close_time;
+	  char *logical_name, *true_name;
+	  char *pipecmd, *cmd;
+	  integer4 binno = j;
+	  integer4 read_only = pcmaio->io.read_only ? 1 : 0;
+	  real8 xfer_speed = (pbin->stat.t.walltime > 0) ?
+	    (pbin->stat.bytes/pbin->stat.t.walltime)/MEGABYTE : 0;
+	  integer4 readbuf_is_alloc  = pbin->readbuf.p  ? 1 : 0;
+	  integer4 writebuf_is_alloc = pbin->writebuf.p ? 1 : 0;
+	  integer4 mrfs_flag = (pcmaio->io.on_mrfs == true) ? 1 : 0;
+
+	  time(&pbin->stat.close_time);
+	  
+	  if (!read_only && pbin->true_name) {
+	    (void) IOgetsize(pbin->true_name, &pbin->filesize, &pbin->blksize);
+	  }
+	  
+	  str_open_time  = STRDUP(ctime(&pbin->stat.open_time));
+	  p = strchr(str_open_time,'\n'); if (p) *p = '\0';
+	  str_close_time = STRDUP(ctime(&pbin->stat.close_time));
+	  p = strchr(str_close_time,'\n'); if (p) *p = '\0';
+	  logical_name   = STRDUP(TRIM(pcmaio->io.logical_name));
+	  true_name      = STRDUP(TRIM(pbin->true_name));
+	  pipecmd        = STRDUP(TRIM(pbin->pipecmd));
+	  cmd            = STRDUP(TRIM(pbin->cmd));
+	  
+	  cma_prt_stat_(&iostuff_stat_ftn_unit, &index,
+			&binno, &pcmaio->io.numbins,
+			&pbin->fileno,
+			str_open_time, str_close_time,
+			logical_name, true_name,
+			pipecmd, cmd,
+			&read_only, &pcmaio->io.packmethod, &pcmaio->io.blocksize,
+			&pcmaio->numddrs, &pcmaio->lenddrs,
+			&pcmaio->numobs,  &pcmaio->maxreplen, &pcmaio->cmalen,
+			&pbin->filesize, &pbin->filepos, &pbin->blksize,
+			&pbin->stat.bytes, &pbin->stat.num_trans,
+			&pbin->readbuf.len, &readbuf_is_alloc,
+			&pbin->writebuf.len, &writebuf_is_alloc,
+			&pbin->prealloc, &pbin->extent,
+			&mrfs_flag,
+			&pbin->stat.t.walltime, &xfer_speed,
+			&pbin->stat.t.usercpu, &pbin->stat.t.syscpu,
+			/* Hidden arguments to Fortran-program */
+			strlen(str_open_time), strlen(str_close_time),
+			strlen(logical_name), strlen(true_name),
+			strlen(pipecmd), strlen(cmd)
+			);
+	  
+	  FREE(str_open_time);
+	  FREE(str_close_time);
+	  FREE(logical_name);
+	  FREE(true_name);
+	  FREE(pipecmd);
+	  FREE(cmd);
+	}
+
+	IOstuff_bin_reset(pbin);
+
+      } /* for (j=0; j<numbins; j++) */
+
+      IOstuff_reset(&pcmaio->io);
+
+      FREE(pcmaio->zinfo);
+      pcmaio->zinfolen = 0;
+      FREE(pcmaio->ddrs);
+      pcmaio->numddrs   = 0;
+      pcmaio->lenddrs   = 0;
+      pcmaio->numobs    = 0;
+      pcmaio->maxreplen = 0;
+      pcmaio->cmalen    = 0;
+
+      pcmaio->ddr_read_counter = 0;
+  
+      pcmaio->chunk     = 0;
+
+      if (cmaio_1stfree[tid] > index) cmaio_1stfree[tid] = index;
+    }
+    else {
+      /* Error: File not in use i.e. reference not found */
+      rc = -1;
+    }
+  }
+  else {
+    /* Error: Invalid internal file unit */
+    rc = -2;
+  }
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
diff --git a/odb/src/aux/cma_debug.c b/odb/src/aux/cma_debug.c
new file mode 100644
index 0000000..f1782ab
--- /dev/null
+++ b/odb/src/aux/cma_debug.c
@@ -0,0 +1,10 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void 
+cma_debug_(const integer4 *toggle, 
+	         integer4 *old_value)
+{
+  int cache = *toggle;
+  *old_value = iostuff_debug;
+  iostuff_debug = (cache > 0) ? true : false;
+}
diff --git a/odb/src/aux/cma_detach.c b/odb/src/aux/cma_detach.c
new file mode 100644
index 0000000..9ad88da
--- /dev/null
+++ b/odb/src/aux/cma_detach.c
@@ -0,0 +1,59 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void 
+cma_detach_(const integer4 *unit, integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (iostuff_debug) fprintf(stderr,"cma_detach(%d) ",index);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      if (!pcmaio->io.read_only) {
+	/* If WRITE-ONLY -file, then flush the current contents of the I/O-buf */
+	int numbins = pcmaio->io.numbins;
+	int j;
+
+	for (j=0; j<numbins; j++) {
+	  IObin *pbin = &pcmaio->io.bin[j];
+	  FILE  *fp   =  pbin->fp;
+
+	  /* fflush() */
+	  if (iostuff_stat) IOtimes(NULL);
+	  (void)fflush(fp);
+	  if (iostuff_stat) {
+	    IOtimes(&pbin->stat.t);
+	    pbin->stat.num_trans++;
+	  }
+
+	} /* for (j=0; j<numbins; j++) */
+      }
+
+      pcmaio->io.is_detached = true;
+
+      if (iostuff_debug)
+	fprintf(stderr," file='%s', alias='%s%s', numbins=%d\n",
+		pcmaio->io.logical_name, 
+		pcmaio->io.leading_part,
+		(pcmaio->io.numbins == 1) ? "\0" : ",*",
+		pcmaio->io.numbins);
+      rc = 0;
+    }
+    else {
+      /* Error : File not in use i.e. reference not found */
+      rc = -1;
+    }
+  }
+  else {
+    /* Error: Invalid internal file unit */
+    rc = -2;
+  }
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_filesize.c b/odb/src/aux/cma_filesize.c
new file mode 100644
index 0000000..c7581b3
--- /dev/null
+++ b/odb/src/aux/cma_filesize.c
@@ -0,0 +1,20 @@
+#include "cmaio.h"
+
+void
+cma_filesize_(const char *filename,
+	      integer4 *retcode,
+	      int len_filename)
+{
+  int rc = 0;
+  char *tmp_filename;
+
+  ALLOC(tmp_filename, len_filename+1);
+  strncpy(tmp_filename, filename, len_filename);
+  tmp_filename[len_filename] = '\0';
+
+  (void) IOgetsize(tmp_filename, &rc, NULL);
+
+  FREE(tmp_filename);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_flpcheck.c b/odb/src/aux/cma_flpcheck.c
new file mode 100644
index 0000000..e2c56dc
--- /dev/null
+++ b/odb/src/aux/cma_flpcheck.c
@@ -0,0 +1,398 @@
+#ifdef RS6K
+#pragma options noextchk
+#endif
+
+#include "odb.h"
+#include "cmaio.h"
+#include <math.h>
+
+/* 
+   cma_flpcheck.c: Checks 64-bit IEEE flp validity.
+
+   Mainly for CMA-data checking
+
+   Author: Sami Saarinen, ECMWF, 03-Nov-1998
+             -"-           -"-   13-Mar-2001 : little-endian version squeezed in
+             -"-           -"-   28-May-2002 : ODB-flpcheck wrapper around cma_flpcheck added
+             -"-           -"-   30-May-2002 : Suspected integer overflow & underflow checker on doubles
+             -"-           -"-   12-Jul-2006 : includes also "odb.h" => uses trunc()-fix from "privpub.h"
+
+
+ */
+
+/* Both big and little endian machines supported now */
+
+#define SIGN(x)  ( ((x) & 0x80000000) >> 31 )
+#define EXPO(x)  ( ((x) & 0x7ff00000) >> 20 )
+#define M1(x)    ( ((x) & 0x000fffff) )
+#define M2(x)    (x)
+
+#ifdef LITTLE
+#define WORD_1_OFFSET 1
+#define WORD_2_OFFSET 0 
+#else
+#define WORD_1_OFFSET 0
+#define WORD_2_OFFSET 1
+#endif
+
+typedef unsigned int Uint;
+
+typedef union _Flp_t {
+  double d;
+  Uint   u[2];
+#ifdef LITTLE
+  struct {
+    Uint m2   : 32;
+    Uint m1   : 20;
+    Uint exp  : 11;
+    Uint sign :  1;
+  } s;
+#else
+  struct {
+    Uint sign :  1;
+    Uint exp  : 11;
+    Uint m1   : 20;
+    Uint m2   : 32;
+  } s;
+#endif
+} Flp_t;
+
+PRIVATE void
+any_endian_version(const Uint  u[],
+		          int  flag[],
+		          int  n,
+		          int *rinf,
+		          int *rtiny,
+		          int *rnan)
+{
+  int i, j;
+  Uint expo, m1, m2;
+  int R1 = 0;
+  int R2 = 0;
+  int R3 = 0;
+  static int first_time = 1;
+  static int cmaflp_check_Inf = 1;
+#ifdef VPP5000
+  static int cmaflp_check_Tiny = 0; /* Off for VPP5000 */
+#else
+  static int cmaflp_check_Tiny = 1;
+#endif
+  static int cmaflp_check_NaN = 1;
+
+  if (first_time) {
+    int ienv;
+    char *env;
+    env = getenv("CMAFLP_CHECK_INF");
+    if (env) {
+      ienv = atoi(env);
+      cmaflp_check_Inf = MAX(0,ienv);
+    }
+    env = getenv("CMAFLP_CHECK_TINY");
+    if (env) {
+      ienv = atoi(env);
+      cmaflp_check_Tiny = MAX(0,ienv);
+    }
+    env = getenv("CMAFLP_CHECK_NAN");
+    if (env) {
+      ienv = atoi(env);
+      cmaflp_check_NaN = MAX(0,ienv);
+    }
+    first_time = 0;
+  }
+
+  if (flag) {
+#ifdef VPP
+#pragma loop noalias
+#elif defined(NECSX)
+#pragma cdir nodep
+#endif
+    for (j=0; j<n; j++) {
+      i = 2 * j;
+      expo = EXPO(u[i+WORD_1_OFFSET]);
+      m1   = M1(u[i+WORD_1_OFFSET]);
+      m2   = M2(u[i+WORD_2_OFFSET]);
+	
+      if (cmaflp_check_Inf && expo == 0x7ff && m1 == 0 && m2 == 0)  {
+	/* Infinite */
+	R1++;
+	flag[j] = 1;
+      }
+      else if (cmaflp_check_Tiny && expo == 0 && (m1 > 0 || m2 > 0)) {
+	/* Too tiny */
+	R2++; 
+	flag[j] = 2;
+      }
+      else if (cmaflp_check_NaN && expo == 0x7ff) {
+	/* NaN */
+	R3++; 
+	flag[j] = 3;
+      }
+      else
+	flag[j] = 0;
+    }
+  }
+  else {
+#ifdef VPP
+#pragma loop noalias
+#elif defined(NECSX)
+#pragma cdir nodep
+#endif
+    for (j=0; j<n; j++) {
+      i = 2 * j;
+      expo = EXPO(u[i+WORD_1_OFFSET]);
+      m1   = M1(u[i+WORD_1_OFFSET]);
+      m2   = M2(u[i+WORD_2_OFFSET]);
+	
+      if (cmaflp_check_Inf && expo == 0x7ff && m1 == 0 && m2 == 0)  {
+	/* Infinite */
+	R1++;
+      }
+      else if (cmaflp_check_Tiny && expo == 0 && (m1 > 0 || m2 > 0)) {
+	/* Too tiny */
+	R2++; 
+      }
+      else if (cmaflp_check_NaN && expo == 0x7ff) {
+	/* NaN */
+	R3++; 
+      }
+    }
+  }
+
+  /* Spit out counts of invalid discoveries */
+
+  if (rinf)  *rinf  = cmaflp_check_Inf  ? R1 : 0;
+  if (rtiny) *rtiny = cmaflp_check_Tiny ? R2 : 0;
+  if (rnan)  *rnan  = cmaflp_check_NaN  ? R3 : 0;
+}
+
+void
+cma_flpcheck_(const double d[],
+	      const   int *nd,
+	              int  flag[],
+	      const   int *nf,
+	              int *rinf,
+	              int *rtiny,
+	              int *rnan)
+{
+  int ND = *nd;
+  int NF = *nf;
+  any_endian_version((const Uint *)d,
+		     (flag && (NF >= ND)) ? flag : NULL,
+		     ND,
+		     rinf, rtiny, rnan);
+}
+
+void
+odb_flpcheck_(const double d[],
+	      const   int *nd,
+	              int  flag[],
+	      const   int *nf,
+	              int *rinf,
+	              int *rtiny,
+	              int *rnan)
+{
+  static int first_time = 1;
+  static int do_test = 0;
+
+  if (rinf)  *rinf  = 0;
+  if (rtiny) *rtiny = 0;
+  if (rnan)  *rnan  = 0;
+
+  if (first_time) {
+    char *env = getenv("ODB_FLPCHECK");
+    if (env) {
+      int myproc = 0;
+      int value = atoi(env);
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      do_test = (value == -1 || value == myproc) ? 1 : 0;
+      if (do_test) {
+	fprintf(stderr,
+		"***Warning from odb_flpcheck_(): Floating point checks will be performed on PE#%d\n",
+		myproc);
+      }
+    }
+    first_time = 0;
+  }
+
+  if (do_test) {
+    cma_flpcheck_(d, nd, flag, nf, rinf, rtiny, rnan);
+  }
+}
+
+void
+odb_intcheck_(const double d[],
+	      const   int *nd,
+	      const   int *test_unsigned_only,
+	              int  flag[],
+	      const   int *nf,
+	              int *nlo,
+	              int *nhi)
+{
+  static int first_time = 1;
+  static int do_test = 0;
+  int NLO = 0;
+  int NHI = 0;
+
+  if (first_time) {
+    char *env = getenv("ODB_INTCHECK");
+    if (env) {
+      int myproc = 0;
+      int value = atoi(env);
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      do_test = (value == -1 || value == myproc) ? 1 : 0;
+      if (do_test) {
+	fprintf(stderr,
+		"***Warning from odb_intcheck_(): Integer checks will be performed on PE#%d\n",
+		myproc);
+      }
+    }
+    first_time = 0;
+  }
+
+  if (do_test) {
+    double minimum, maximum;
+    int j;
+    int ND = *nd;
+    int NF = *nf;
+    int UNSIGN = *test_unsigned_only;
+
+    if (UNSIGN) { /* test in unsigned sense only */
+      minimum =           0U;
+      maximum =  4294967295U;
+    }
+    else {
+      minimum = -2147483647;
+      maximum =  2147483647;
+    }
+
+    if (flag && NF >= ND) {
+      for (j=0; j<ND; j++) {
+	double trc = trunc(d[j]);
+	int is_integer = (d[j] == trc);
+	int flg = 0;
+	if (is_integer && trc < minimum) { NLO++; flg = -1; }
+	else if (is_integer && trc > maximum) { NHI++; flg = +1; }
+	else flg = 0;
+	flag[j] = flg;
+      } /* for (j=0; j<ND; j++) */
+    }
+    else { /* no flag vector present or it is too short */
+      for (j=0; j<ND; j++) {
+	double trc = trunc(d[j]);
+	int is_integer = (d[j] == trc);
+	if (is_integer && trc < minimum) NLO++;
+	else if (is_integer && trc > maximum) NHI++;
+      } /* for (j=0; j<ND; j++) */
+    } /* if (flag && NF >= ND) ... else */
+  }
+
+  if (nlo) *nlo = NLO;
+  if (nhi) *nhi = NHI;
+}
+
+#ifndef NFLAGLEN
+#define NFLAGLEN 2048
+#endif
+
+PRIVATE int cmaflp_check = -1;
+PRIVATE int cmaflp_iounit = 0;
+PRIVATE int cmaflp_ignore_error = 0;
+PRIVATE int cmaflp_dump_max = -1;
+PRIVATE int cmaflp_dump_only_invalid = 0;
+
+void
+CMA_flpchecker(const char *name,
+	       int mode, /* 1=read, 2=write */
+	       const char *filename,
+	       const double pbuf[],
+	       int filepos,
+	       int *retcode,
+	       Boolean *check_it)
+{
+  int rc = *retcode;
+
+  if (cmaflp_check == -1) {
+    int ienv;
+    char *env = getenv("CMAFLP_CHECK");
+    if (env) {
+      ienv = atoi(env);
+      cmaflp_check = MAX(0,ienv);
+    }
+    else
+      cmaflp_check = 0;
+    
+    if (cmaflp_check > 0) {
+      env = getenv("CMAFLP_IOUNIT");
+      if (env) {
+	ienv = atoi(env);
+	cmaflp_iounit = MAX(0,ienv);
+      }
+      
+      env = getenv("CMAFLP_IGNORE_ERROR");
+      if (env) {
+	ienv = atoi(env);
+	cmaflp_ignore_error = (ienv != 0);
+      }
+      
+      env = getenv("CMAFLP_DUMP_MAX");
+      if (env) {
+	ienv = atoi(env);
+	cmaflp_dump_max = MAX(-1, ienv);
+      }
+
+      env = getenv("CMAFLP_DUMP_ONLY_INVALID");
+      if (env) {
+	ienv = atoi(env);
+	cmaflp_dump_only_invalid = MAX(0, ienv);
+      }
+    }
+
+    *check_it = (cmaflp_check & mode) > 0 ? true : false;
+  }
+
+  if (rc > 0 && (cmaflp_check & mode) > 0) {
+    int flag[NFLAGLEN];
+    int nd = rc;
+    int nf = (NFLAGLEN >= nd) ? nd : 0;
+    int rinf, rtiny, rnan;
+    int NULOUT  = cmaflp_iounit;
+    int ONLYINV = cmaflp_dump_only_invalid;
+    int MAXDUMP = MIN(cmaflp_dump_max, nd);
+    if (MAXDUMP == -1) MAXDUMP = nd;
+    
+    cma_flpcheck_(pbuf, &nd, 
+		  flag, &nf,
+		  &rinf, &rtiny, &rnan);
+    
+    if (rnan > 0 || rinf > 0 || rtiny > 0) {
+      extern void cma_flperr_(
+	  const int *io, const int *onlyinv, const int *maxdump, const int *mode,
+	  const char *name, const char *filename,
+	  const double d[], const int *nd,
+	  const int flag[], const int *nf,
+	  const int *woff, 
+	  const int *inf, const int *itiny, const int *inan
+	  /* Hidden arguments */
+	  , int name_len, int filename_len);
+
+      int word_offset = 
+	(filepos - nd * sizeof(*pbuf)) / sizeof(*pbuf);
+
+      cma_flperr_(&NULOUT, &ONLYINV, &MAXDUMP, &mode,
+		  name, filename,
+		  pbuf, &nd,
+		  flag, &nf,
+		  &word_offset,
+		  &rinf, &rtiny, &rnan,
+		  /* Hidden arguments to Fortran-program */
+		  strlen(name), strlen(filename));
+
+      if (!cmaflp_ignore_error) {
+	/* Error : Invalid floating point value(s) were detected */
+	rc = -7;
+      }
+    }
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_flperr.F90 b/odb/src/aux/cma_flperr.F90
new file mode 100644
index 0000000..06e690c
--- /dev/null
+++ b/odb/src/aux/cma_flperr.F90
@@ -0,0 +1,111 @@
+SUBROUTINE cma_flperr( &
+ & io, onlyinv, maxdump, mode, &
+ & name, filename, &
+ & d, nd, &
+ & flag, nf, &
+ & woff,  &
+ & inf, itiny, inan) 
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: io, nd, nf, onlyinv, maxdump
+INTEGER(KIND=JPIM), intent(in) :: flag(nf)
+REAL(KIND=JPRB),    intent(in) :: d(nd)
+INTEGER(KIND=JPIM), intent(in) :: woff, inf, itiny, inan, mode
+character(len=*), intent(in) :: name, filename
+character(len=3) ::  star
+character(len=20) ::  cmode
+INTEGER(KIND=JPIM) :: j, jj, iflag
+INTEGER(KIND=JPIM) :: itmp(3)
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CMA_FLPERR',0,ZHOOK_HANDLE)
+cmode = 'processing'
+if (mode == 1) then
+  cmode = 'reading'
+else
+  cmode = 'writing'
+endif
+
+write(io,'(1x,a)') &
+ & 'CMA_FLPERR: Invalid floating point value(s)'// &
+ & ' detected while '//trim(cmode) 
+write(io,'(1x,a)')  &
+ & '            file="'//trim(filename)//'" ;' 
+write(io,'(1x,a)')  &
+ & '            routine="'//trim(name)//'"' 
+write(io,*)'Approximate word offset (unpacked) : ',woff
+
+if (io /= 0) then
+  write( 0,'(1x,a)') &
+   & 'CMA_FLPERR: Invalid floating point value(s)'// &
+   & ' detected while '//trim(cmode) 
+  write( 0,'(1x,a)')  &
+   & '            file="'//trim(filename)//'" ;' 
+  write( 0,'(1x,a)')  &
+   & '            routine="'//trim(name)//'"' 
+  write( 0,*)'Approximate word offset (unpacked) : ',woff
+endif
+
+write(io,*)'There are ',inf,' infinite values (Inf)'
+write(io,*)'          ',itiny,' too tiny numbers'
+write(io,*)'          ',inan,' Not-a-Numbers (NaN)'
+
+if (onlyinv > 0) then
+  if (nf >= nd) then
+    jj = 1
+    j = 1
+    do while (j <= nd .and. jj <= maxdump)
+      if (flag(j) > 0) then
+        write(star,'("<",i1,">")') flag(j)
+        write(io,'(i4,1x,a3,2x,"0x",z16.16,2x,g20.12)') &
+         & j,star,d(j),d(j) 
+        jj = jj + 1
+      endif
+      j = j + 1
+    enddo
+  else
+    jj = 1
+    j = 1
+    do while (j <= nd .and. jj <= maxdump)
+      call cma_flpcheck(d(j),1,iflag,1, &
+       & itmp(1),itmp(2),itmp(3)) 
+      if (iflag > 0) then
+        write(io,'(i4,6x,"0x",z16.16,2x,g20.12)') &
+         & j,d(j),d(j) 
+        jj = jj + 1
+      endif
+      j = j + 1
+    enddo
+  endif
+else
+  if (nf >= nd) then
+    do j=1,maxdump
+      star = ' '
+      if (flag(j) > 0) write(star,'("<",i1,">")') flag(j)
+      write(io,'(i4,1x,a3,2x,"0x",z16.16,2x,g20.12)') &
+       & j,star,d(j),d(j) 
+    enddo
+  else
+    do j=1,maxdump
+      write(io,'(i4,6x,"0x",z16.16,2x,g20.12)') &
+       & j,d(j),d(j) 
+    enddo
+  endif
+endif
+
+write(io,*)'CMA_FLPERR: End of dump.'
+
+#if defined(VPP) || defined(FUJITSU) || defined(SGI) || defined(RS6K)
+call errtra()
+#endif
+
+call flush(io)
+IF (LHOOK) CALL DR_HOOK('CMA_FLPERR',1,ZHOOK_HANDLE)
+END SUBROUTINE cma_flperr
diff --git a/odb/src/aux/cma_get_concat.c b/odb/src/aux/cma_get_concat.c
new file mode 100644
index 0000000..c6b6cfa
--- /dev/null
+++ b/odb/src/aux/cma_get_concat.c
@@ -0,0 +1,28 @@
+#include "cmaio.h"
+
+void 
+cma_get_concat_(const integer4 *unit,
+		integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.read_only) {
+      rc = pcmaio->io.is_mrfs2disk ? pcmaio->io.concat : 0;
+    }
+    else 
+      rc = pcmaio->io.concat;
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+  *retcode = rc;
+}
+
+		    
diff --git a/odb/src/aux/cma_get_concat_byname.c b/odb/src/aux/cma_get_concat_byname.c
new file mode 100644
index 0000000..a6a350f
--- /dev/null
+++ b/odb/src/aux/cma_get_concat_byname.c
@@ -0,0 +1,12 @@
+#include "cmaio.h"
+
+void 
+cma_get_concat_byname_(const char *filename,
+		       integer4 *retcode,
+		       /* Hidden arguments to Fortran-program */
+		       int len_filename)
+{
+  *retcode = IOconcat_byname(filename, len_filename);
+}
+
+		    
diff --git a/odb/src/aux/cma_get_ddrs.c b/odb/src/aux/cma_get_ddrs.c
new file mode 100644
index 0000000..d8ef01a
--- /dev/null
+++ b/odb/src/aux/cma_get_ddrs.c
@@ -0,0 +1,67 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_get_ddrs_(const integer4 *unit,
+	      real8           ddrs[],
+	      const integer4 *lenddrs,
+	      integer4       *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  /* int bin   = IOBIN(*unit); */
+
+  if (iostuff_debug)  fprintf(stderr,"cma_get_ddrs(%d)",*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse && pcmaio->io.read_only) {
+      if (!pcmaio->zinfo) {
+	/* Perform the very first cma_info()-gathering if not done already */
+	/* The following used to be in cma_open() ... */
+	/* bin#0: Get info-vector and DDRs for subsequent use; ignore errors */
+	integer4 *info = NULL;
+	integer4 infolen = 0;
+	integer4 retc;
+	cma_info_(unit, info, &infolen, &retc);
+      }
+      else if (pcmaio->io.is_mrfs2disk && pcmaio->ddr_read_counter > 0) {
+	/* Get the next chunk of DDRs from the concatenated file */ 
+
+	rc = CMA_fetch_ddrs(unit, pcmaio);
+	if (rc < 0) goto finish;
+      }
+      
+      if (iostuff_debug)  
+	fprintf(stderr,": ddr_read_counter=%d ",pcmaio->ddr_read_counter);
+    
+      if (pcmaio->ddrs) {
+	int minlen = MIN(*lenddrs, pcmaio->lenddrs);
+	IOrcopy(ddrs, pcmaio->ddrs, minlen);
+	pcmaio->ddr_read_counter++;
+	rc = minlen;
+      }
+      else
+	rc = 0;
+
+      if (iostuff_debug)  
+	fprintf(stderr,": now=%d ",pcmaio->ddr_read_counter);
+
+    }
+    else {
+      /* Error : File was not in use or was not open for read only */
+      rc = -4;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_get_report.c b/odb/src/aux/cma_get_report.c
new file mode 100644
index 0000000..2cb7b0b
--- /dev/null
+++ b/odb/src/aux/cma_get_report.c
@@ -0,0 +1,58 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_get_report_(const integer4 *unit,
+		real8           pbuf[],
+		const integer4 *kbufsize,
+		integer4       *retcode)
+{
+  int rc = 0;
+  /* int index = IOINDEX(*unit); */
+  integer4 retc;
+  integer4 len;
+  real8 report_len;
+  integer4 bufsize = *kbufsize;
+
+  if (iostuff_debug) fprintf(stderr,"cma_get_report(%d)\n",*unit);
+
+  len = 1;
+  if (len > bufsize) {
+    /* Error : Buffer size provided is too short */
+    rc = -5;
+    goto finish;
+  }
+
+  cma_read_(unit, &report_len, &len, &retc);
+
+  if (retc != len) {
+    /* Error */
+    rc = retc;
+    goto finish;
+  }
+
+  if (iostuff_debug)
+    fprintf(stderr," : replen=%.2f, bufsize=%d\n",
+	    report_len, bufsize);
+
+  len = report_len - 1;
+  if (len > bufsize - 1) {
+    /* Error : Buffer size provided is too short */
+    rc = -len;
+    goto finish;
+  }
+
+  pbuf[0] = report_len;
+  cma_read_(unit, &pbuf[1], &len, &retc);
+  if (retc != len) {
+    /* Error */
+    rc = retc;
+    goto finish;
+  }
+
+  rc = len + 1;
+
+ finish:
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_info.c b/odb/src/aux/cma_info.c
new file mode 100644
index 0000000..fde69e1
--- /dev/null
+++ b/odb/src/aux/cma_info.c
@@ -0,0 +1,286 @@
+#include "cmaio.h"
+
+#ifndef MaxNPES
+#define MaxNPES   256
+#endif
+
+PRIVATE int ZINFOMIN = 8;
+PRIVATE int ZINFOLEN = (32 + 1 + 1 + 2 * MaxNPES);
+
+/* Info-vector :
+
+   1) No. of DDRs
+   2) Total length of DDRs
+   3) No. of CMA-reports
+   4) Total length of report data
+   5) Max. CMA-report length
+   6) Max. obs. type
+   7) =1 if the actual file on memory resident file system
+   8) >0 if internally packed, =0 otherwise
+   9-32) Reserved
+  33) =1 if the file is MR2D-type concatenated file
+  34) No. of chunks (normally equals to no. of PEs) concatenated into the file
+  Followed by no. of chunk -word pairs (35,36), (37,38), ...
+  35) First chunk id (=IFS PE no. that wrote the chunk)
+  36) Size of the first chunk in bytes
+  37) Second chunk id
+  38) Size of the second chunk in bytes
+  ...
+
+*/
+
+/* Borrowed from "/cc/rd/ifs/common/yomcmhdr.h" */
+
+#define NCD1LN    1 /* FIRST DDR LEN. */
+#define NCD1NL    8 /* LEN. OF NEXT DDR */
+#define NCD1ND   18 /* NO. OF DDRS */
+#define NCD1RM   22 /* MAX. LEN. OF ECMA REPORT */
+#define NCD1MOT  26 /* MAX. NO. OF OBS. TYPES */
+#define NCD1TO   27 /* TOTAL NO. OF OBS. */
+#define NCD1AL   51 /* TOTAL LENGTH OF ECMA */
+
+#define NCD2LN    1 /* LEN. OF SECOND DDR */
+#define NCD2LND   8 /* LEN. OF NEXT DDR */
+
+
+int
+CMA_fetch_ddrs(const integer4 *unit,
+	       IOcma *pcmaio)
+{
+  int rc = 0;
+
+  real8 *zinfo = NULL;
+  int zinfolen = 0;
+  int j;
+  int numddrs = 0;
+  int lenddrs = 0;
+  int ddrno = 0;
+  Boolean ddrs_read = false;
+
+  if (iostuff_debug) 
+    fprintf(stderr,"CMA_fetch_ddrs(%d,read_counter=%d)\n",
+	    *unit, pcmaio->ddr_read_counter);
+
+  FREE(pcmaio->zinfo);
+  pcmaio->zinfolen = 0;
+  FREE(pcmaio->ddrs);
+  pcmaio->lenddrs = 0;
+  pcmaio->numddrs = 0;
+  
+  while (!ddrs_read) {
+    integer4 retc;
+    real8 oneword;
+    const integer4 onewordlen = 1;
+    real8 *ddr;
+    integer4 ddrlen;
+    
+    cma_read_(unit, &oneword, &onewordlen, &retc);
+    rc = retc;
+    
+    if (rc != onewordlen) goto finish;
+    
+    ddrlen = oneword;
+    
+    if (iostuff_debug) {
+      fprintf(stderr," ddrlen=%d, oneword=%f\n",ddrlen,oneword);
+    }
+    
+    ALLOC(ddr, ddrlen);
+    ddr[0] = oneword;
+    
+    ddrlen--;
+    cma_read_(unit, ddr+1, &ddrlen, &retc);
+    rc = retc;
+    
+    if (rc != ddrlen) goto finish;
+    ddrlen++;
+    
+    ddrno++;
+	  
+    if (ddrno == 1) {
+      if (pcmaio->io.is_mrfs2disk) {
+	int nchunk = MAX(0,pcmaio->io.concat);
+	zinfolen = MIN(ZINFOLEN, 32 + 1 + 1 + 2 * nchunk);
+      }
+      else {
+	zinfolen = ZINFOMIN;
+      }
+
+      ALLOC(zinfo, zinfolen);
+      for (j=0; j<zinfolen; j++) zinfo[j] = 0;
+
+      numddrs = ddr[NCD1ND-1];     /* No. of DDRs */
+      zinfo[1-1] = numddrs;
+      zinfo[2-1] = 0;
+      zinfo[3-1] = ddr[NCD1TO-1];  /* No. of observations/reports */
+      zinfo[4-1] = ddr[NCD1AL-1];  /* Total length of report data */
+      zinfo[5-1] = ddr[NCD1RM-1];  /* Max. CMA-report length */
+      zinfo[6-1] = ddr[NCD1MOT-1]; /* Max. obs. type */
+      zinfo[7-1] = pcmaio->io.on_mrfs;    /* =1 if file on memory resident file system */
+      zinfo[8-1] = MAX(0,pcmaio->io.packmethod); /* >0 if internally packed, =0 otherwise */
+      
+      pcmaio->numobs    = ddr[NCD1TO-1];
+      pcmaio->cmalen    = ddr[NCD1AL-1];
+      pcmaio->maxreplen = ddr[NCD1RM-1];
+    }
+    
+    lenddrs += ddrlen;
+    
+    REALLOC(pcmaio->ddrs, lenddrs);
+    IOrcopy(&pcmaio->ddrs[pcmaio->lenddrs], ddr, ddrlen);
+    
+    pcmaio->lenddrs = lenddrs;
+    pcmaio->numddrs++;
+    
+    FREE(ddr);
+    
+    ddrs_read = (ddrno == numddrs) ? true : false;
+  } /* while (!ddrs_read) */
+
+  if (zinfo) {
+    zinfo[2-1] = lenddrs; /* Total length of DDRs */
+
+    if (pcmaio->io.is_mrfs2disk) {
+      /* Handle info-words above 32+ */
+      IObin *pbin = &pcmaio->io.bin[0];
+
+      int nchunks = pbin->mr2d_info[0];
+      zinfo[33-1] = pcmaio->io.is_mrfs2disk;
+      
+      IOrucopy(&zinfo[34-1], pbin->mr2d_info, 1 + 2 * nchunks);
+    }
+
+    ALLOC(pcmaio->zinfo, zinfolen);
+    IOrcopy(pcmaio->zinfo, zinfo, zinfolen);
+    
+    pcmaio->zinfolen = zinfolen;
+
+    FREE(zinfo);
+
+    rc = zinfolen;
+  }
+  else {
+    rc = 0;
+  }
+
+ finish:
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n", rc);
+
+  return rc;
+}
+
+
+FORTRAN_CALL void 
+cma_info_(const integer4 *unit, 
+	  integer4        info[],
+	  const integer4 *infolen,
+	  integer4       *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  int bin = IOBIN(*unit);
+
+  if (iostuff_debug) fprintf(stderr,"cma_info(%d)\n",index);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse && pcmaio->io.read_only) {
+      /* Only bin#0 matters currently */
+
+      IObin *pbin = &pcmaio->io.bin[0];
+      int mininfo;
+      
+      if (pbin->filepos == pbin->begin_filepos) {
+	/* int leninfo = 0; */
+
+	/* The very first time */
+	pcmaio->ddr_read_counter = 0;
+	rc = CMA_fetch_ddrs(unit, pcmaio);
+
+	if (rc < 0) goto finish;
+      }
+
+      mininfo = pcmaio->zinfo ?  MIN(*infolen, pcmaio->zinfolen) : 0;
+	
+      if (iostuff_debug && pcmaio->zinfo) {
+	int j;
+	fprintf(stderr," : zinfo[0..%d] =",mininfo-1);
+	for (j=0; j<mininfo; j++) fprintf(stderr," %g",pcmaio->zinfo[j]);
+      }
+
+      if (pcmaio->zinfo) IOircopy(info, pcmaio->zinfo, mininfo);
+
+      if (mininfo < *infolen) {
+	int j, n = *infolen;
+	for (j=mininfo; j<n; j++) info[j] = 0;
+      }
+      
+      rc = *infolen;
+    }
+    else if (pcmaio->io.is_inuse && !pcmaio->io.read_only) {
+      /* Write only files: Use info-words above 32+ to write MR2D-information */
+
+      if (bin >= 0 && bin < pcmaio->io.numbins) {
+	IObin *pbin = &pcmaio->io.bin[bin];
+	/* FILE *fp = pbin->fp; */
+	int mininfo = *infolen;
+	Boolean is_mr2d = false;
+
+	if (mininfo >= 33 && pbin->filepos == pbin->begin_filepos) {
+	  is_mr2d = (info[33-1] == 1) ? true : false;
+
+	  if (is_mr2d) {
+	    /* The file going to be an MR2D concatenated file */
+	    int len;
+	    int retcode;
+	    int nchunks;
+	    int *mr2d_data;
+
+	    nchunks = info[34-1];
+	    len = 1 + 1 + 2 * nchunks;
+
+	    if (mininfo >= 32 + len) {
+	      ALLOC(mr2d_data, len);
+
+	      mr2d_data[0] = MR2D;
+	      mr2d_data[1] = nchunks; /* Note: chunk length in bytes */
+	      IOicopy(&mr2d_data[2], &info[35-1], len - 2);
+
+	      cma_writei_(unit, mr2d_data, &len, &retcode);
+	      
+	      FREE(mr2d_data);
+	    }
+	    else {
+	      retcode = -7; /* Error: Info vector too short */
+	    }
+
+	    rc = retcode; /* May contain a failure code, too */
+
+	  } /* if (is_mr2d) */
+
+	} /* if (mininfo >= 33 && pbin->filepos == 0) */
+      }
+      else {
+	/* Error : Attempt to use an invalid bin */
+	rc = -5;
+      }
+    }
+    else {
+      /* Error: File not in use i.e. reference not found */
+      rc = -1;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  
+}
diff --git a/odb/src/aux/cma_is_packed.c b/odb/src/aux/cma_is_packed.c
new file mode 100644
index 0000000..62962fa
--- /dev/null
+++ b/odb/src/aux/cma_is_packed.c
@@ -0,0 +1,24 @@
+#include "cmaio.h"
+
+void 
+cma_is_packed_(const integer4 *unit,
+	       integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    rc = pcmaio->io.packmethod;
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+  *retcode = rc;
+}
+
+		    
diff --git a/odb/src/aux/cma_on_mrfs.c b/odb/src/aux/cma_on_mrfs.c
new file mode 100644
index 0000000..98b24f8
--- /dev/null
+++ b/odb/src/aux/cma_on_mrfs.c
@@ -0,0 +1,23 @@
+#include "cmaio.h"
+
+void 
+cma_on_mrfs_(const integer4 *unit,
+	     integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    rc = pcmaio->io.on_mrfs;
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+  *retcode = rc;
+}
+
diff --git a/odb/src/aux/cma_open.c b/odb/src/aux/cma_open.c
new file mode 100644
index 0000000..3fb4524
--- /dev/null
+++ b/odb/src/aux/cma_open.c
@@ -0,0 +1,605 @@
+#include "cmaio.h"
+#include "swapbytes.h"
+#include "magicwords.h"
+#include "cdrhook.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * P. Marguinaud : 10-10-2013 : Rename files before overwriting (by using env. ODB_OVERWRITE_METHOD)
+ */
+
+static o_lock_t CMAIO_mylock[MAX_CMAIO_LOCKS] = { 0 } ; /* A specific OMP-lock; initialized only once in
+							   odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+#define MAXCMAIO_DEFAULT 1000
+
+IOcma **cmaio = NULL;
+int *cmaio_1stfree = NULL;
+
+/* flags for thread-safe perror()'ing ; used to be handled via cma_perror() */
+int *cma_perror_flag = NULL; 
+
+void cma_set_lock(int lockno)
+{
+  if (lockno >= 0 && lockno < MAX_CMAIO_LOCKS) coml_set_lockid_(&CMAIO_mylock[lockno]);
+}
+
+void cma_unset_lock(int lockno)
+{
+  if (lockno >= 0 && lockno < MAX_CMAIO_LOCKS) coml_unset_lockid_(&CMAIO_mylock[lockno]);
+}
+
+
+int CMA_get_MAXCMAIO()
+{
+  static int maxcmaio = MAXCMAIO_DEFAULT;
+  if (!cmaio || !cmaio_1stfree || !cma_perror_flag) { /* 1st */
+    cma_set_lock(0);
+    /* We ought to call 1st OpenMP FLUSH here, but we're in C ... */
+    /* 
+       Can't we do something like 
+       int size=sizeof(var);
+       coml_flush_(&var,&size);
+       ??
+    */
+    if (!cmaio || !cmaio_1stfree || !cma_perror_flag) { /* 2nd */
+      int j, inumt = get_max_threads_();
+      if (!cmaio) {
+	char *env = getenv("MAXCMAIO");
+	int value = 0;
+	if (env) value = atoi(env);
+	if (value <= 0) value = maxcmaio;
+	maxcmaio = value;
+	ALLOC(cmaio, 1+inumt); /* "1+" for convenience i.e. no need to do "--tid" */
+	for (j=0; j<=inumt; j++) {
+	  CALLOC(cmaio[j], maxcmaio);
+	}
+      }
+
+      if (!cmaio_1stfree) {
+	CALLOC(cmaio_1stfree, 1+inumt); /* "1+" for convenience; see above */
+      }
+
+      if (!cma_perror_flag) {
+	ALLOC(cma_perror_flag, 1+inumt); /* "1+" for convenience; see above */
+	for (j=0; j<=inumt; j++) cma_perror_flag[j] = 1; /* by default call perror() */
+      }
+
+      /* We ought to call 2nd OpenMP FLUSH here, but we're in C ... */
+    } /* if (!cmaio || !cmaio_1stfree || !cma_perror_flag) 2nd */
+    cma_unset_lock(0);
+  } /* if (!cmaio || !cmaio_1stfree || !cma_perror_flag) 1st */
+  return maxcmaio;
+}
+
+void
+init_CMAIO_lock()
+{
+  int j;
+  for (j=0; j<MAX_CMAIO_LOCKS; j++) {
+    char lockname[80];
+    snprintf(lockname,80,"cma_open.c:CMAIO_mylock[%d]",j);
+    INIT_LOCKID_WITH_NAME(&CMAIO_mylock[j],lockname);
+  }
+  (void) CMA_get_MAXCMAIO(); /* to avoid possible lack-of-OpenMP FLUSH-conditions/problems later */
+  (void) IOgetattr(NULL); /* Read in IOASSIGN unless already done */
+}
+
+FILE *
+CMA_get_fp(const integer4 *unit)
+{
+  /* int rc = 0; */
+  int index = IOINDEX(*unit);
+  int bin = IOBIN(*unit);
+  FILE *fp = NULL;
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      int j, numbins = pcmaio->io.numbins;
+
+      for (j=0; j<numbins; j++) {
+	IObin *pbin = &pcmaio->io.bin[j];
+	if (j == bin) {
+	  fp = pbin->fp;
+	  break;
+	}
+      } /* for (j=0; j<numbins; j++) */
+    } /* if (pcmaio->io.is_inuse) */
+  } /* if (index >= 0 && index < CMA_get_MAXCMAIO()) */
+
+  return fp;
+}
+
+
+static void 
+init_cmaio(IOcma *pcmaio)
+{
+  if (pcmaio) {
+    IOstuff_init(&pcmaio->io);
+    
+    pcmaio->zinfolen  = 0;
+    pcmaio->zinfo     = NULL;
+    pcmaio->numddrs   = 0;
+    pcmaio->lenddrs   = 0;
+    pcmaio->numobs    = 0;
+    pcmaio->maxreplen = 0;
+    pcmaio->cmalen    = 0;
+    pcmaio->ddrs      = NULL;
+    
+    pcmaio->ddr_read_counter = 0;
+    
+    pcmaio->chunk     = 0;
+  }
+}
+
+
+FORTRAN_CALL void 
+cma_open_(integer4       *unit, 
+	  const char     *filename,
+	  const char     *mode,
+	  integer4       *retcode,
+	  /* Hidden arguments to Fortran-program */
+	  int             len_filename,
+	  int             len_mode)
+{
+  int rc = 0;
+  Boolean found = false;
+  int maxcmaio = CMA_get_MAXCMAIO();
+  int i, index = -1;
+  int tid = get_thread_id_();
+  DRHOOK_START(cma_open_);
+
+  *unit = -1;
+
+  i = cmaio_1stfree[tid];
+  if (i < maxcmaio) {
+    IOcma *pcmaio = &cmaio[tid][i];
+    if (pcmaio->io.is_inuse == false) {
+      index = i;
+      found = true;
+    }
+  }
+
+  if (!found) { /* Fallback*/
+    for (i=0; i<maxcmaio; i++) {
+      IOcma *pcmaio = &cmaio[tid][i];
+      if (pcmaio->io.is_inuse == false) {
+	found = true;
+	index = i;
+	break;
+      }
+    }
+  }
+
+  if (iostuff_debug) fprintf(stderr,"cma_open");
+
+  if (found) {
+    IOcma *pcmaio = &cmaio[tid][index];
+    char Mode;
+    int j, numbins;
+    Boolean append_mode = false;
+    int scheme_saved = -1;
+
+    init_cmaio(pcmaio);
+
+    if (!mode) {
+      /* Error : Invalid open mode */
+      rc = -3;
+      goto finish;
+    }
+
+    Mode = isupper(*mode) ? tolower(*mode) : *mode;
+
+    if (Mode != 'r' && Mode != 'w' && Mode != 'a' ) {
+      /* Error : Invalid open mode */
+      rc = -3;
+      goto finish;
+    }
+    
+    pcmaio->io.read_only = (Mode == 'r') ? true : false;
+    append_mode = (Mode == 'a') ? true : false;
+    
+    pcmaio->io.logical_name = IOstrdup(filename, &len_filename);
+
+    if (iostuff_debug) fprintf(stderr,"('%s') :",pcmaio->io.logical_name);
+    
+    (void) IOgetattr(&pcmaio->io);
+
+    numbins = pcmaio->io.numbins;
+
+    if (iostuff_debug) fprintf(stderr," numbins=%d\n",numbins);
+
+    for (j=0; j<numbins; j++) {
+      IObin *pbin = &pcmaio->io.bin[j];
+      FILE *fp = NULL;
+
+      if (scheme_saved >= 0) pcmaio->io.scheme = scheme_saved;
+
+    redo: /* Jump back here (from bottom), if you detected the file needs an external tool */
+      
+      if (j == 0) {
+	if (pbin->pipecmd) {
+	  pcmaio->io.scheme = external;
+	}
+	else {
+	  /* The following is quite useless test for READ-ONLY files,
+	     since an automatic sensing will take place later on */
+	  pcmaio->io.scheme = (pcmaio->io.packmethod == 0) ? none : internal;
+	}
+	if (scheme_saved < 0) scheme_saved = pcmaio->io.scheme;
+      }
+      
+      if (j == 0 && !pcmaio->io.read_only) (void) IOmkdir(pbin->true_name);
+
+      if (!pcmaio->io.read_only && !append_mode && 
+	  ((pcmaio->io.scheme & none) == none)) {
+	/* For write/only ("w", but not "a") files, check the file suffix,
+	   and if it something recognizable, like ".gz", ".Z", ".zip", then use
+	   corresponding external packing hack */
+	const char *scheme_change = Compression_Suffix_Check(pbin->true_name);
+	if (scheme_change) {
+	  if (iostuff_debug) {
+	    fprintf(stderr,
+		    "cma_open(%s,'w'): scheme_change triggered. Now '%s'\n",
+		    pbin->true_name, scheme_change);
+	  }
+	  FREE(pbin->pipecmd);
+	  pbin->pipecmd = STRDUP(scheme_change);
+	  pcmaio->io.scheme = external;
+	}
+      }
+
+      if (((pcmaio->io.scheme & none) == none) || 
+	  ((pcmaio->io.scheme & internal) == internal)) {
+	/* Regular file opening; valid for both none or internal compression */
+	
+	cma_set_lock(0);
+	time(&pbin->stat.open_time);	
+	if (iostuff_stat) IOtimes(NULL);
+#ifdef VPP
+	if (!pcmaio->io.read_only && !pcmaio->io.on_mrfs 
+	    && pbin->prealloc > 0 && !append_mode) {
+	  fp = IOprealloc(pbin->true_name,
+			  pbin->prealloc,
+			  pbin->extent,
+			  NULL,
+			  &pbin->fileno);
+	}
+	else {
+	  char *m = pcmaio->io.read_only ? "r" : "w";
+	  if (append_mode) m = "a";
+	  fp = fopen(pbin->true_name, m);
+	}
+#else
+	{
+	  char *m = pcmaio->io.read_only ? "r" : "w";
+	  if (append_mode) m = "a";
+          if (*m == 'w')
+            {   
+              static int odb_w = -1; 
+              if (odb_w < 0)
+                {   
+                  char * codb_w = getenv ("ODB_OVERWRITE_METHOD");
+                  if (codb_w)
+                    sscanf (codb_w, "%d", &odb_w);
+                  else
+                    odb_w = 0;
+                }   
+              if (odb_w == 1)
+                {   
+                  unlink (pbin->true_name);
+                }   
+              else if (odb_w == 2)
+                {   
+                  char tmp[1024];
+                  char * ext;
+                  int i;
+                  strcpy (tmp, pbin->true_name);
+                  ext = tmp + strlen (pbin->true_name);
+                  for (i = 0; ; i++)
+                    {   
+                      struct stat st; 
+                      sprintf (ext, ".%6.6d", i); 
+                      if (stat (tmp, &st) == -1) 
+                        break;
+                    }   
+                  rename (pbin->true_name, tmp);
+                }   
+            }   
+	  fp = fopen(pbin->true_name, m);
+	}
+#endif
+	if (!fp && cma_perror_flag && cma_perror_flag[tid]) PERROR(pbin->true_name);
+	if (iostuff_stat) IOtimes(&pbin->stat.t);
+	cma_unset_lock(0);
+      }
+      else if ((pcmaio->io.scheme & external) == external) {
+	/* Data to be accessed via Unix-pipe i.e. popen() */
+	int go_ahead = 0;
+
+	if (pcmaio->io.read_only) { 
+	  /* When R/O check existence of the true file */
+	  struct stat buf;
+	  if (stat(pbin->true_name,&buf) == 0) go_ahead = 1;
+	}
+	else {
+	  go_ahead = 1;
+	}
+
+	if (go_ahead) {
+	  char *m = pcmaio->io.read_only ? "r" : "w";
+	  const IObuf *iob = pcmaio->io.read_only ? &pbin->readbuf : &pbin->writebuf;
+	  char *cmd = NULL;
+	  Boolean has_incore = false;
+	  char *pipecmd = IOknowncmd(pbin->pipecmd, pcmaio->io.read_only, &has_incore, NULL, iob);
+	  int len = strlen(pipecmd) + strlen(pbin->true_name) + 20;
+
+	  ALLOC(cmd, len);
+	  sprintf(cmd, pipecmd, pbin->true_name);
+
+	  if (iostuff_debug) {
+	    fprintf(stderr,"cma_open(truename='%s',mode='%s'): pipecmd='%s' --> cmd='%s'\n",
+		    pbin->true_name, m, pipecmd, cmd);
+	  }
+	  
+	  FREE(pipecmd);
+	  
+	  time(&pbin->stat.open_time);	
+	  if (iostuff_stat) IOtimes(NULL);
+	  if (append_mode) m = "a";
+	  fp = popen(cmd, m);
+	  if (!fp && cma_perror_flag && cma_perror_flag[tid]) PERROR(pbin->true_name);
+	  if (iostuff_stat) IOtimes(&pbin->stat.t);
+	  
+	  if (fp) pbin->cmd = STRDUP(cmd);
+	  FREE(cmd);
+	}
+	else
+	  fp = NULL;
+      }
+
+      if (fp) {
+	if (iostuff_stat) {
+	  pbin->stat.num_trans++;
+	}
+	
+	pbin->fp = fp;
+	pbin->fileno = fileno(fp);
+	
+	/* Set I/O-buffering, if applicable */
+
+	(void) IOsetbuf(fp, pbin->true_name, pcmaio->io.read_only,
+			pcmaio->io.read_only ? &pbin->readbuf : &pbin->writebuf,
+			pcmaio->io.read_only ? &pbin->filesize : NULL,
+			pcmaio->io.read_only ? &pbin->blksize : NULL);
+
+	if ((pcmaio->io.scheme & none) == none || (pcmaio->io.scheme & internal) == internal) {
+
+	  if (pcmaio->io.read_only && j == 0 && pbin->filesize > 0) {
+	    Boolean is_mr2d = false;
+	    int offset = 0;
+	    unsigned int first_word = 0;
+	    
+	    int num;
+	    int swp = 0;
+	    const char *scheme_change = NULL;
+
+	    if (iostuff_stat) IOtimes(NULL);
+	    scheme_change = Compression_Magic_Check(fp, &first_word, 0);
+	    if (iostuff_stat) IOtimes(&pbin->stat.t);
+
+	    if (scheme_change) {
+	      if (iostuff_debug) {
+		fprintf(stderr,
+			"cma_open(%s,'r'): scheme_change triggered. Now '%s'\n",
+			pbin->true_name, scheme_change);
+	      }
+	      FREE(pbin->pipecmd);
+	      pbin->pipecmd = STRDUP(scheme_change);
+	      pcmaio->io.scheme = external;
+	      fclose(fp);
+	      FREEIOBUF(pbin->readbuf);
+	      goto redo;
+	    }
+
+	    num = 1;
+	    pbin->stat.bytes += num * sizeof(unsigned int);
+	    pbin->stat.num_trans++;
+
+	    /* Check for concatenated file */
+
+	    if (first_word == MR2D || first_word == D2RM) {
+	      is_mr2d = true;
+	      swp = (first_word == D2RM);
+	    }
+	    else {
+	      is_mr2d = false;
+	      swp = 0;
+	    }
+	    pcmaio->io.is_mrfs2disk = is_mr2d;
+	    pcmaio->io.req_byteswap = swp;
+
+	    if (is_mr2d) {
+	      unsigned int nchunks = 0;
+
+	      if (iostuff_stat) IOtimes(NULL);
+	      fread(&nchunks, sizeof(unsigned int), 1, fp);
+	      if (swp) {
+		int len = 1;
+		swap4bytes_(&nchunks, &len);
+	      }
+	      if (iostuff_stat) IOtimes(&pbin->stat.t);
+
+	      pcmaio->io.concat = nchunks; /* In a normal case remains constant across the bins */
+
+	      pbin->mr2d_infolen = 1 + 2 * nchunks;
+	      ALLOC(pbin->mr2d_info, pbin->mr2d_infolen);
+
+	      pbin->mr2d_info[0] = nchunks;
+
+	      if (iostuff_stat) IOtimes(NULL);
+	      fread(&pbin->mr2d_info[1], sizeof(unsigned int), pbin->mr2d_infolen - 1, fp);
+	      if (swp) {
+		int len = pbin->mr2d_infolen - 1;
+		swap4bytes_(&pbin->mr2d_info[1], &len);
+	      }
+	      if (iostuff_stat) IOtimes(&pbin->stat.t);
+	      
+	      num = 1 + 2 * nchunks;
+
+	      pbin->stat.bytes += num * sizeof(unsigned int);
+	      pbin->stat.num_trans += 2;
+
+	      offset = sizeof(unsigned int) * (1 + num);
+
+	      if (iostuff_stat) IOtimes(NULL);
+	      fread(&first_word, sizeof(unsigned int), 1, fp);
+	      if (iostuff_stat) IOtimes(&pbin->stat.t);
+
+	      num = 1;
+	      pbin->stat.bytes += num * sizeof(unsigned int);
+	      pbin->stat.num_trans++;
+	    }
+
+	    /* Check for internal compression */
+	    if (first_word == PCMA || first_word == AMCP) {
+	      pcmaio->io.scheme = internal;
+	      if (!is_mr2d) swp = (first_word == AMCP);
+	    }
+	    else {
+	      pcmaio->io.scheme = none;
+	      if (!is_mr2d) {
+		swp = (first_word == _BDO || first_word == _23CH);
+	      }
+	    }
+
+	    pcmaio->io.req_byteswap = swp;
+
+	    fseek(fp, offset, SEEK_SET);
+
+	    pbin->filepos = offset;
+	    pbin->begin_filepos = offset;
+	  }
+	}
+
+	if (j == 0 && (pcmaio->io.scheme & internal) == internal) {
+	  if (pcmaio->io.read_only) {
+	    /* Due to an automatic sensing the R/O files do not need this */
+	    pcmaio->io.packmethod = -1; 
+	  }
+	  /* ... and for W/O-files the pcmaio->io.packmethod was
+	     already gathered upon IOgetattr() -phase */
+
+	  pcma_blocksize = MAX(pcma_blocksize, pcmaio->io.blocksize);
+	  pcmaio->io.blocksize = pcma_blocksize;
+	}
+
+	if (iostuff_debug) {
+	  fprintf(stderr," bin=%d : (packing_flag=0x%x; method#%d,blk=%d) %s='%s' ; %s",
+		  j,
+		  pcmaio->io.scheme,
+		  ((pcmaio->io.scheme & none) == none)     ? 0 : pcmaio->io.packmethod,
+		  ((pcmaio->io.scheme & none) == none)     ? 0 : pcmaio->io.blocksize,
+		  ((pcmaio->io.scheme & external) == external) ? "pipe" : "file",
+		  ((pcmaio->io.scheme & external) == external) ? pbin->cmd : pbin->true_name,
+		  pcmaio->io.read_only ? "READ-ONLY" : "WRITE-ONLY");
+	}
+	
+      }
+      else {
+	/* Error : Couldn't open the file */
+	rc = -1;
+	goto finish;
+      }
+
+      if (iostuff_debug) fprintf(stderr,"\n");
+    } /* for (j=0; j<numbins; j++) */
+    
+    /* Everything ok */
+	
+    pcmaio->io.is_inuse = true;
+    pcmaio->io.is_detached = false;
+    
+    *unit = index;
+    if (cmaio_1stfree[tid] <= index) cmaio_1stfree[tid] = index+1;
+    
+    rc = pcmaio->io.numbins;
+  }
+  else {
+    /* Error : Invalid internal file unit */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  /* Upon successful completion now returns no. of bins allocated */
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+void
+cma_set_perror_(const integer4 *onoff, integer4 *retcode)
+{
+  int rc = -1;
+  int tid = get_thread_id_();
+
+  if (cma_perror_flag && onoff) {
+    rc = cma_perror_flag[tid]; /* old value */
+    cma_perror_flag[tid] = (*onoff) ? 1 : 0;
+  }
+
+  *retcode = rc;
+}
+
+
+void
+cma_get_perror_(integer4 *retcode)
+{
+  int tid = get_thread_id_();
+  *retcode = cma_perror_flag ? cma_perror_flag[tid] : 1; /* old value */
+}
+
+
+void
+cma_is_externally_compressed_(const char *filename,
+			      const char *mode,
+			      integer4 *retcode,
+			      /* Hidden argument to Fortran-program */
+			      int len_filename,
+			      int len_mode)
+{ /* Called at least from lib/msgpass_loaddata.F90 and lib/msgpass_storedata.F90 */
+  int rc = 0;
+  char *sname = IOtruename(filename, &len_filename);
+
+  if (sname) {
+    Boolean readonly = (mode && *mode == 'r') ? 1 : 0;
+    if (readonly) {
+      cma_set_lock(0);
+      {
+	FILE *fp = fopen(sname, "r");
+	if (fp) {
+	  unsigned int first_word;
+	  const char *scheme_change = Compression_Magic_Check(fp, &first_word, 1); /* magicwords.c */
+	  rc = (scheme_change != NULL);
+	}
+      }
+      cma_unset_lock(0);
+    }
+    else { /* write only files */
+      const char *scheme_change = Compression_Suffix_Check(sname);
+    }
+    FREE(sname);
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_prt_stat.F90 b/odb/src/aux/cma_prt_stat.F90
new file mode 100644
index 0000000..f7caa15
--- /dev/null
+++ b/odb/src/aux/cma_prt_stat.F90
@@ -0,0 +1,126 @@
+SUBROUTINE cma_prt_stat( &
+ & ftn_unit, cma_unit, &
+ & binno, numbins, &
+ & fileno, &
+ & str_open_time,  str_close_time, &
+ & logical_name,   true_name, &
+ & pipecmd,        cmd, &
+ & read_only, packmethod, blocksize, &
+ & numddrs,   lenddrs, &
+ & numobs,    maxreplen,  cmalen, &
+ & filesize,  filepos, blksize,  &
+ & bytes,     num_trans, &
+ & readbuf_len, readbuf_is_alloc, &
+ & writebuf_len, writebuf_is_alloc, &
+ & prealloc, extent,   &
+ & mrfs_flag, &
+ & walltime,  xfer_speed, &
+ & usercpu,   syscpu) 
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+
+implicit none
+INTEGER(KIND=JPIM), intent(in)       :: ftn_unit, cma_unit, binno, fileno
+CHARACTER (LEN = *), intent(in) :: str_open_time,  str_close_time 
+CHARACTER (LEN = *), intent(in) :: logical_name,   true_name
+CHARACTER (LEN = *), intent(in) :: pipecmd,        cmd
+INTEGER(KIND=JPIM), intent(in)       :: read_only, numbins, packmethod
+INTEGER(KIND=JPIM), intent(in)       :: blocksize
+INTEGER(KIND=JPIM), intent(in)       :: numddrs,   lenddrs
+INTEGER(KIND=JPIM), intent(in)       :: numobs,    maxreplen,  cmalen
+INTEGER(KIND=JPIM), intent(in)       :: filesize,  filepos, blksize
+INTEGER(KIND=JPIM), intent(in)       :: bytes,     num_trans
+INTEGER(KIND=JPIM), intent(in)       :: readbuf_len,  writebuf_len
+INTEGER(KIND=JPIM), intent(in)       :: readbuf_is_alloc, writebuf_is_alloc
+INTEGER(KIND=JPIM), intent(in)       :: prealloc, extent, mrfs_flag
+REAL(KIND=JPRB), intent(in)          :: walltime,  xfer_speed
+REAL(KIND=JPRB), intent(in)          :: usercpu,   syscpu
+! === END OF INTERFACE BLOCK ===
+
+!-----------------------------------------------------------------------
+!234567890c234567890c234567890c234567890c234567890c234567890c234567890--
+
+INTEGER(KIND=JPIM) :: io
+REAL(KIND=JPRB) :: saving
+character(len=20), save :: alloc_msg(0:1)
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+data alloc_msg/'  (NOT allocated)', '  (allocated)'/
+
+IF (LHOOK) CALL DR_HOOK('CMA_PRT_STAT',0,ZHOOK_HANDLE)
+io = ftn_unit
+
+if (io >= 0) then
+  if (binno == 0) then
+    write(io,*) "*** STATISTICS for CMA-file '"// &
+     & logical_name//"'" 
+  else
+    write(io,*)
+  endif
+
+  write(io,*) "Physical filename     : '"//true_name//"'"
+  if (read_only == 1) then
+    write(io,*) "Open mode             :  READ-ONLY"
+  else
+    write(io,*) "Open mode             :  WRITE-ONLY"
+  endif
+  write(io,*) "CMA-index no.         : ",cma_unit
+  write(io,*) "  --- bin no.         : ",binno
+  write(io,*) "No. of bins           : ",numbins
+  write(io,*) "UNIX-file no.         : ",fileno
+  write(io,*) "Disk blocksize        : ",blksize
+  if (mrfs_flag == 1) &
+   & write(io,*) "Assigned to the memory resident file system" 
+  write(io,*) "Opened at "//str_open_time
+  write(io,*) "Closed at "//str_close_time
+         
+  if (read_only == 1 .and. binno == 0) then
+    write(io,*) "No. of DDRs           : ",numddrs
+    write(io,*) "Total DDR length      : ",lenddrs
+    write(io,*) "No. of reports        : ",numobs
+    write(io,*) "Longest report (words): ",maxreplen
+    write(io,*) "Report data length    : ",cmalen
+  endif
+         
+  write(io,*) "Pipe cmd (unfiltered) : "//pipecmd
+  write(io,*) "Pipe cmd (filtered)   : "//cmd
+  write(io,*) "Packing method        : ",packmethod
+  write(io,*) "Blocksize             : ",blocksize
+  write(io,*) "File size (in bytes)  : ",filesize
+  write(io,*) "File position         : ",filepos
+  if ( filesize >  0 .and.  &
+     & filepos  >  0 .and.  &
+     & filepos  >= filesize ) then 
+    saving = 100.0D0*(1.0D0 - dble(filesize)/dble(filepos))
+    write(io,1) "Space saving          : ",saving
+    1          format(1x,a,f12.2,'%')
+  endif
+  write(io,*) "Bytes processed       : ",bytes
+  write(io,*) "No. of transactions   : ",num_trans
+  write(io,*) "I/O-buffer size: read : ",readbuf_len, &
+   & alloc_msg(readbuf_is_alloc) 
+  write(io,*) "            --- write : ",writebuf_len, &
+   & alloc_msg(writebuf_is_alloc) 
+  write(io,*) "Preallocation & extent: ",prealloc,extent
+  write(io,1000) "I/O-times: Wall clock : ", &
+   & walltime," sec", &
+   & xfer_speed," MB/s" 
+  write(io,1000) "        --- CPU-times : ", &
+   & usercpu," sec (user)", &
+   & syscpu," sec (sys)" 
+  1000    format(1x,a,f10.3,a,f10.3,a)
+
+  if (binno == numbins-1) then
+    write(io,*) "*** END OF STATISTICS ***"
+!--   Make sure it comes to the logfile (... before an abort ... ;-)
+    call flush(io)
+  endif
+
+endif
+IF (LHOOK) CALL DR_HOOK('CMA_PRT_STAT',1,ZHOOK_HANDLE)
+
+END SUBROUTINE cma_prt_stat
diff --git a/odb/src/aux/cma_read.c b/odb/src/aux/cma_read.c
new file mode 100644
index 0000000..ac862a0
--- /dev/null
+++ b/odb/src/aux/cma_read.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_read_
+#define FUNC_STR  "cma_read"
+#define DATA_TYPE real8
+#define DATA_STR  "D64-bit"
+#define TYPE_ID   real_8
+
+#include "cma_read.h"
diff --git a/odb/src/aux/cma_readb.c b/odb/src/aux/cma_readb.c
new file mode 100644
index 0000000..9f54f7c
--- /dev/null
+++ b/odb/src/aux/cma_readb.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_readb_
+#define FUNC_STR  "cma_readb"
+#define DATA_TYPE byte1
+#define DATA_STR  "B8-bit"
+#define TYPE_ID   byte_1
+
+#include "cma_read.h"
diff --git a/odb/src/aux/cma_readc.c b/odb/src/aux/cma_readc.c
new file mode 100644
index 0000000..e50be10
--- /dev/null
+++ b/odb/src/aux/cma_readc.c
@@ -0,0 +1,12 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_readc_(const integer4 *unit,
+	   byte1           s[],
+	   integer4       *retcode
+	   /* Hidden arguments */
+	   , int slen)
+{
+  memset(s, ' ', slen);
+  cma_readb_(unit, s, &slen, retcode);
+}
diff --git a/odb/src/aux/cma_readf.c b/odb/src/aux/cma_readf.c
new file mode 100644
index 0000000..9c6693e
--- /dev/null
+++ b/odb/src/aux/cma_readf.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_readf_
+#define FUNC_STR  "cma_readf"
+#define DATA_TYPE real4
+#define DATA_STR  "F32-bit"
+#define TYPE_ID   real_4
+
+#include "cma_read.h"
diff --git a/odb/src/aux/cma_readi.c b/odb/src/aux/cma_readi.c
new file mode 100644
index 0000000..165afa6
--- /dev/null
+++ b/odb/src/aux/cma_readi.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_readi_
+#define FUNC_STR  "cma_readi"
+#define DATA_TYPE integer4
+#define DATA_STR  "I32-bit"
+#define TYPE_ID   integer_4
+
+#include "cma_read.h"
diff --git a/odb/src/aux/cma_rewind.c b/odb/src/aux/cma_rewind.c
new file mode 100644
index 0000000..734d413
--- /dev/null
+++ b/odb/src/aux/cma_rewind.c
@@ -0,0 +1,80 @@
+#include "cmaio.h"
+#include "cdrhook.h"
+
+FORTRAN_CALL void 
+cma_rewind_(integer4 *unit,
+	    integer4 *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  /* int bin = IOBIN(*unit); */ /* Ignored, since ALL will be rewound */
+  DRHOOK_START(cma_rewind_);
+
+  if (iostuff_debug) fprintf(stderr,"cma_rewind(%d) ",*unit);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      int j, numbins = pcmaio->io.numbins;
+
+      for (j=0; j<numbins; j++) {
+	IObin *pbin = &pcmaio->io.bin[j];
+	
+	if ( ((pcmaio->io.scheme & none) == none) || 
+	     ((pcmaio->io.scheme & internal) == internal) ) {
+	  FILE *fp = pbin->fp;
+	  
+	  /* Safe to seek at the beginning since regular, non-piped I/O */
+	  rewind(fp);
+	  
+	  pbin->filepos = 0;
+	  rc = 0;
+	}
+	else {
+	  integer4 retc;
+	  char *file = IOstrdup(pcmaio->io.logical_name, NULL);
+	  char mode = pcmaio->io.read_only ? 'r' : 'w';
+	  int swp = pcmaio->io.req_byteswap;
+	  
+#if 0
+	  fprintf(stderr,"< cma_rewind(): pcmaio->io.req_byteswap = %d [before cma_close_]\n",
+		  pcmaio->io.req_byteswap);
+#endif
+
+	  cma_close_(unit, &retc);
+	  rc = retc;
+	  
+	  if (rc == 0) {
+	    cma_open_(unit, file, &mode, &retc, strlen(file), 1);
+	    rc = retc;
+	    if (rc == 0) {
+	      FREE(file);
+	      break; /* for (j=0; j<numbins; j++) */
+	    }
+	  }
+	  FREE(file);
+	  pcmaio->io.req_byteswap = swp; /* Restored */
+#if 0
+	  fprintf(stderr,"> cma_rewind(): pcmaio->io.req_byteswap = %d\n",
+		  pcmaio->io.req_byteswap);
+#endif
+	}
+      } /* for (j=0; j<numbins; j++) */
+    }
+    else {   
+      /* Error : File was not in use */
+      rc = -4;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
diff --git a/odb/src/aux/cma_seek.c b/odb/src/aux/cma_seek.c
new file mode 100644
index 0000000..be936f1
--- /dev/null
+++ b/odb/src/aux/cma_seek.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_seek_
+#define FUNC_STR  "cma_seek"
+#define DATA_TYPE real8
+#define DATA_STR  "D64-bit"
+#define TYPE_ID   real_8
+
+#include "cma_seek.h"
diff --git a/odb/src/aux/cma_seekb.c b/odb/src/aux/cma_seekb.c
new file mode 100644
index 0000000..b494701
--- /dev/null
+++ b/odb/src/aux/cma_seekb.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_seekb_
+#define FUNC_STR  "cma_seekb"
+#define DATA_TYPE byte1
+#define DATA_STR  "B8-bit"
+#define TYPE_ID   byte_1
+
+#include "cma_seek.h"
diff --git a/odb/src/aux/cma_seekf.c b/odb/src/aux/cma_seekf.c
new file mode 100644
index 0000000..639e668
--- /dev/null
+++ b/odb/src/aux/cma_seekf.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_seekf_
+#define FUNC_STR  "cma_seekf"
+#define DATA_TYPE real4
+#define DATA_STR  "F32-bit"
+#define TYPE_ID   real_4
+
+#include "cma_seek.h"
diff --git a/odb/src/aux/cma_seeki.c b/odb/src/aux/cma_seeki.c
new file mode 100644
index 0000000..5272f4f
--- /dev/null
+++ b/odb/src/aux/cma_seeki.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_seeki_
+#define FUNC_STR  "cma_seeki"
+#define DATA_TYPE integer4
+#define DATA_STR  "I32-bit"
+#define TYPE_ID   integer_4
+
+#include "cma_seek.h"
diff --git a/odb/src/aux/cma_stat.c b/odb/src/aux/cma_stat.c
new file mode 100644
index 0000000..e670033
--- /dev/null
+++ b/odb/src/aux/cma_stat.c
@@ -0,0 +1,12 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void 
+cma_stat_(const integer4 *ftn_unit,
+	  const integer4 *toggle, 
+	        integer4 *old_value)
+{
+  int cache = *toggle;
+  *old_value = iostuff_stat;
+  iostuff_stat = (cache > 0) ? true : false;
+  iostuff_stat_ftn_unit = *ftn_unit;
+}
diff --git a/odb/src/aux/cma_wrapup.c b/odb/src/aux/cma_wrapup.c
new file mode 100644
index 0000000..d3c0863
--- /dev/null
+++ b/odb/src/aux/cma_wrapup.c
@@ -0,0 +1,27 @@
+#include "cmaio.h"
+
+/* Close any files that have been opened via CMA-lib */
+
+FORTRAN_CALL void
+cma_wrapup_(integer4  *retcode)
+{
+  int rc = 0;
+  int i, maxcmaio = CMA_get_MAXCMAIO();
+  int tid = get_thread_id_();
+
+  if (iostuff_debug) fprintf(stderr,"cma_wrapup\n");
+
+  for (i=0; i<maxcmaio; i++) {
+    IOcma *pcmaio = &cmaio[tid][i];
+    if (pcmaio->io.is_inuse) {
+      integer4 unit = i;
+      integer4 retc;
+      cma_close_(&unit, &retc);
+      rc++;
+    }
+  }
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/cma_write.c b/odb/src/aux/cma_write.c
new file mode 100644
index 0000000..e1ffc56
--- /dev/null
+++ b/odb/src/aux/cma_write.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_write_
+#define FUNC_STR  "cma_write"
+#define DATA_TYPE real8
+#define DATA_STR  "D64-bit"
+#define TYPE_ID   real_8
+
+#include "cma_write.h"
diff --git a/odb/src/aux/cma_writeb.c b/odb/src/aux/cma_writeb.c
new file mode 100644
index 0000000..92dff2f
--- /dev/null
+++ b/odb/src/aux/cma_writeb.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_writeb_
+#define FUNC_STR  "cma_writeb"
+#define DATA_TYPE byte1
+#define DATA_STR  "B8-bit"
+#define TYPE_ID   byte_1
+
+#include "cma_write.h"
diff --git a/odb/src/aux/cma_writec.c b/odb/src/aux/cma_writec.c
new file mode 100644
index 0000000..6744541
--- /dev/null
+++ b/odb/src/aux/cma_writec.c
@@ -0,0 +1,11 @@
+#include "cmaio.h"
+
+FORTRAN_CALL void
+cma_writec_(const integer4 *unit,
+	    const byte1     s[],
+	    integer4       *retcode
+	    /* Hidden arguments */
+	    , int slen)
+{
+  cma_writeb_(unit, s, &slen, retcode);
+}
diff --git a/odb/src/aux/cma_writef.c b/odb/src/aux/cma_writef.c
new file mode 100644
index 0000000..9b2d348
--- /dev/null
+++ b/odb/src/aux/cma_writef.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_writef_
+#define FUNC_STR  "cma_writef"
+#define DATA_TYPE real4
+#define DATA_STR  "F32-bit"
+#define TYPE_ID   real_4
+
+#include "cma_write.h"
diff --git a/odb/src/aux/cma_writei.c b/odb/src/aux/cma_writei.c
new file mode 100644
index 0000000..ce1f7bb
--- /dev/null
+++ b/odb/src/aux/cma_writei.c
@@ -0,0 +1,9 @@
+#include "cmaio.h"
+
+#define FUNC_NAME cma_writei_
+#define FUNC_STR  "cma_writei"
+#define DATA_TYPE integer4
+#define DATA_STR  "I32-bit"
+#define TYPE_ID   integer_4
+
+#include "cma_write.h"
diff --git a/odb/src/aux/codb2netcdf.F90 b/odb/src/aux/codb2netcdf.F90
new file mode 100644
index 0000000..67f3a0f
--- /dev/null
+++ b/odb/src/aux/codb2netcdf.F90
@@ -0,0 +1,67 @@
+SUBROUTINE codb2netcdf(title, ncfile, namecfg, sql_query, &
+     & d, nra, nrows, ncols, &
+     & idtnum, ipoolno, &
+     & odb_type_tag, odb_name_tag, odb_nickname_tag)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE ODBNETCDF, ONLY : to_netcdf, init_cdf 
+
+implicit none
+character(len=*), intent(in) :: title, ncfile, namecfg, sql_query
+INTEGER(KIND=JPIM), intent(in) :: nra, nrows, ncols
+REAL(KIND=JPRB), intent(in) :: d(nra, ncols)
+INTEGER(KIND=JPIM), intent(in) :: idtnum(ncols), ipoolno
+character(len=*), intent(in) :: odb_type_tag, odb_name_tag, odb_nickname_tag
+
+INTEGER(KIND=JPIM) :: itype(ncols)
+character(len=4096) types(ncols), names(ncols), nicknames(ncols)
+REAL(KIND=JPRB) :: nmdi, rmdi, mdi
+INTEGER(KIND=JPIM) :: istart, iend, j
+character(len=1) ODB_tag_delim, env
+logical LLnopacking, LLdebug_mode
+
+CALL codb_getenv('ODB_NETCDF_NOPACKING', env) ! set ODB_NETCDF_NOPACKING=1 to see all in double or string
+LLnopacking = (env == '1')
+
+CALL codb_getenv('ODB_NETCDF_DEBUG', env)
+LLdebug_mode = (env == '1')
+
+call pcma_get_mdis(nmdi, rmdi)
+mdi = abs(nmdi)
+
+call cODB_tag_delim(ODB_tag_delim)
+
+call init_cdf()
+
+do j=1,ncols
+  CALL dtnum_to_netcdf_type(idtnum(j), itype(j))
+enddo
+
+iend = 1
+do j=1,ncols
+  istart = iend + 1
+  iend = iend + index(odb_type_tag(istart:),ODB_tag_delim)
+  types(j) = odb_type_tag(istart:iend-1)
+enddo
+
+iend = 1
+do j=1,ncols
+  istart = iend + 1
+  iend = iend + index(odb_name_tag(istart:),ODB_tag_delim)
+  names(j) = odb_name_tag(istart:iend-1)
+enddo
+
+iend = 1
+do j=1,ncols
+  istart = iend + 1
+  iend = iend + index(odb_nickname_tag(istart:),ODB_tag_delim)
+  nicknames(j) = odb_nickname_tag(istart:iend-1)
+enddo
+
+CALL to_netcdf(trim(title), trim(ncfile), trim(namecfg), trim(sql_query), &
+     & d(1:nrows, 1:ncols), &
+     & itype(1:ncols), &
+     & types(1:ncols), names(1:ncols), nicknames(1:ncols), &
+     & mdi, ipoolno, LLnopacking, LLdebug_mode)
+
+END SUBROUTINE codb2netcdf
diff --git a/odb/src/aux/codb_netcdf.c b/odb/src/aux/codb_netcdf.c
new file mode 100644
index 0000000..d2920e1
--- /dev/null
+++ b/odb/src/aux/codb_netcdf.c
@@ -0,0 +1,774 @@
+/* 
+   ODB to NETCDF -interface (SS/7-Jul-2003)
+
+   Only applicable if you compile with -DHAS_NETCDF=1 or -DHAS_NETCDF
+   To disable use of NetCDF, compile with -DHAS_NETCDF=0
+
+*/
+
+#include "odb.h"
+#include "cmaio.h"
+#include "codb_netcdf.h"
+
+#ifdef HAS_NETCDF /* NETCDF is available */
+
+#include "netcdf.h"
+
+/* Define some macros */
+
+#define CHKERR(do_abort) check_err(do_abort, stat, __LINE__, __FILE__)
+
+#define ASSIGN_FV_MDI(type, functype, nct, value) { \
+  type fillvalue = ((*colpack) == 1) ? (*mdi) : value; \
+  stat = nc_put_att_##functype(*ncid, colid, _FillValue, nct, 1, &fillvalue); \
+  CHKERR(1); \
+  stat = nc_put_att_double(*ncid, colid, "missing_value", NC_DOUBLE, 1, mdi); \
+  CHKERR(1); \
+}
+
+#define VIACOPY_TO_NETCDF(type,functype,x) { \
+  int j; \
+  type fillvalue; \
+  type *array = NULL; \
+  stat = nc_get_att_##functype(*ncid, *colid, _FillValue, &fillvalue); \
+  CHKERR(1); \
+  if (debug_mode) fprintf(stderr,"\t%s = %.13g\n", _FillValue, (double)fillvalue); \
+  ALLOC(array, count); \
+  for (j=0; j<count; j++) { \
+    array[j] = (ABS(x[j]) == ABS(mdi)) ? fillvalue : x[j]; \
+  } \
+  stat = nc_put_vara_##functype(*ncid, *colid, &start, &count, array); \
+  CHKERR(1); \
+  FREE(array); \
+}  
+
+#define RAW_TO_NETCDF(type,functype,x) { \
+  stat = nc_put_vara_##functype(*ncid, *colid, &start, &count, (const type *)x); \
+  CHKERR(1); \
+}
+
+#define RAW_TO_NETCDF_VAR(type,functype,x) { \
+  stat = nc_put_var_##functype(*ncid, *colid, (const type *)x); \
+  CHKERR(1); \
+}
+
+static int debug_mode = 0;
+
+static int check_debug_mode()
+{
+  static int first_time = 1;
+  if (first_time) {
+    char *env = getenv("ODB_NETCDF_DEBUG");
+    if (env) debug_mode = atoi(env);
+    debug_mode = (debug_mode > 0) ? 1 : 0;
+    first_time = 0;
+  }
+  return debug_mode;
+}
+
+static void
+check_err(const int   do_abort,
+	  const int   stat, 
+	  const int   line, 
+	  const char *file)
+{
+  if (stat != NC_NOERR) {
+    fprintf(stderr,
+	    "***NetCDF-%s detected in line=%d, file=%s: %s\n",
+	    do_abort ? "error" : "warning",
+	    line, file, nc_strerror(stat));
+    if (do_abort) RAISE(SIGABRT);
+  }
+}
+
+static char *make_printable(const char s[], int slen)
+{
+  int j;
+  char *p = NULL;
+  ALLOC(p, slen + 1);
+  for (j=0; j<slen; j++) {
+    int c = s[j];
+    if (!isprint(c)) c = ' ';
+    p[j] = c;
+  }
+  p[slen] = '\0';
+  return p;
+}
+
+void
+codb_has_netcdf_(int *retcode) 
+{ 
+  *retcode = 1; 
+}
+
+void codb_gettype_netcdf_(const char *typename,
+			  int *retcode
+			  /* Hidden arguments */
+			  ,int typename_len)
+{
+  int rc;
+  char *p;
+  DECL_FTN_CHAR(typename);
+
+  ALLOC_FTN_CHAR(typename);
+  p = p_typename;
+  while (*p) {
+    if (isupper(*p)) *p = tolower(*p);
+    p++;
+  }
+
+  if      (strequ(p_typename,"char"))   rc = NC_CHAR;
+  else if (strequ(p_typename,"byte"))   rc = NC_BYTE;
+  else if (strequ(p_typename,"short"))  rc = NC_SHORT;
+  else if (strequ(p_typename,"int"))    rc = NC_INT;
+  else if (strequ(p_typename,"float"))  rc = NC_FLOAT;
+  else if (strequ(p_typename,"double")) rc = NC_DOUBLE;
+  else rc = NC_EBADTYPE;
+
+  FREE_FTN_CHAR(typename);
+  *retcode = rc;
+}
+
+void codb_open_netcdf_(int *ncid,
+		       const char *filename,
+		       const char *mode,
+		       int *retcode
+		       /* Hidden arguments */
+		       ,int filename_len
+		       ,int mode_len)
+{
+  int stat = NC_NOERR;
+  int write_mode;
+  char *truename = NULL;
+  DECL_FTN_CHAR(mode);
+
+  (void) check_debug_mode();
+
+  ALLOC_FTN_CHAR(mode);
+
+  truename = IOtruename(filename,&filename_len);
+  write_mode = (*p_mode == 'w' || *p_mode == 'W');
+
+  if (write_mode) {
+    if (debug_mode) fprintf(stderr,"Creating NetCDF-file '%s' ...\n",truename);
+    stat = nc_create(truename, NC_CLOBBER, ncid);
+  }
+  else {
+    if (debug_mode) fprintf(stderr,"Opening NetCDF-file '%s' ...\n",truename);
+    stat = nc_open(truename, NC_NOWRITE, ncid); /* read/only */
+  }
+  CHKERR(1);
+
+  *retcode = stat;
+
+  FREE(truename);
+
+  FREE_FTN_CHAR(mode);
+}
+
+void codb_begindef_netcdf_(const int *ncid,
+			   const char *title,
+			   const char *sql_query,
+			   const int *nrows, 
+			   const int *ncols,
+			   const double *mdi,
+			   const int *poolno,
+			   int *retcode
+			   /* Hidden arguments */
+			   , int title_len
+			   , int sql_query_len)
+{
+  int rc = 0;
+  int stat, dimid_rows, dimid_cols, dimid_str;
+
+  /* nrows = number of data rows (elements in every column) */
+  /* stat = nc_def_dim(*ncid, "nrows", *nrows, &dimid); */
+  stat = nc_def_dim(*ncid, "nrows", NC_UNLIMITED, &dimid_rows);
+  CHKERR(1);
+  rc = dimid_rows;
+
+  /* ncols = number of variables/columns */
+  stat = nc_def_dim(*ncid, "ncols", *ncols, &dimid_cols);
+  CHKERR(1);
+
+  /* nstr = number of bytes per in character strings (fixed to 8 bytes) */
+  stat = nc_def_dim(*ncid, "nstr", sizeof(string), &dimid_str);
+  CHKERR(1);
+
+  /* global metadata */
+
+  {
+    const char Conventions[] = "ODB";
+    stat = nc_put_att_text(*ncid, NC_GLOBAL, "Conventions", STRLEN(Conventions), Conventions);
+    CHKERR(1);
+  }
+
+  {
+    DECL_FTN_CHAR(title);
+    ALLOC_FTN_CHAR(title);
+    stat = nc_put_att_text(*ncid, NC_GLOBAL, "title", STRLEN(p_title), p_title);
+    CHKERR(1);
+    FREE_FTN_CHAR(title);
+  }
+
+  {
+    DECL_FTN_CHAR(sql_query);
+    ALLOC_FTN_CHAR(sql_query);
+    if (STRLEN(p_sql_query) > 0) {
+      /* Change all unprintable as well as \t's & \n's into blanks ' ' */
+      char *p = p_sql_query;
+      while (*p) {
+	int c = *p;
+	if (!isprint(c) || c == '\n' || c == '\n') c = ' ';
+	*p++ = c;
+      }
+      stat = nc_put_att_text(*ncid, NC_GLOBAL, "sql_query", STRLEN(p_sql_query), p_sql_query);
+      CHKERR(1);
+    }
+    FREE_FTN_CHAR(sql_query);
+  }
+
+  {
+    const char institution[] = "ECMWF, Reading, U.K.";
+    stat = nc_put_att_text(*ncid, NC_GLOBAL, "institution", STRLEN(institution), institution);
+    CHKERR(1);
+  }
+
+  {
+    char *version = STRDUP(nc_inq_libvers());
+    const char *odbvers = codb_versions_(NULL, NULL, NULL, NULL);
+    const char *dtbuf = odb_datetime_(NULL, NULL);
+    char *source;
+    int len;
+    len = STRLEN(version) + STRLEN(odbvers) + STRLEN(dtbuf) + 50;
+    ALLOC(source,len);
+    snprintf(source, len,
+	    "ODB2NETCDF (%s) on %s ; NetCDF %s",
+	    odbvers, dtbuf, version);
+    stat = nc_put_att_text(*ncid, NC_GLOBAL, "source", STRLEN(source), source);
+    CHKERR(1);
+    FREE(version);
+    FREE(source);
+  }
+
+  { /* Missing data indicator ; 
+       don't use "missing_value", since ncview emits this as the 
+       only true missing value, which is wrong for packed data */
+    stat = nc_put_att_double(*ncid, NC_GLOBAL, "mdi", NC_DOUBLE, 1, mdi);
+    CHKERR(1);
+  }
+
+  { /* Pool number */
+    stat = nc_put_att_int(*ncid, NC_GLOBAL, "poolno", NC_INT, 1, poolno);
+    CHKERR(1);
+  }
+
+  { /* Analysis date & time, if available ;
+       If not present, sets to 19700101 at 000000 */
+    int yyyymmdd_loc, hhmmss_loc;
+    codb_analysis_datetime_(&yyyymmdd_loc, &hhmmss_loc);
+    stat = nc_put_att_int(*ncid, NC_GLOBAL, "analysis_date", NC_INT, 1, &yyyymmdd_loc);
+    CHKERR(1);
+    stat = nc_put_att_int(*ncid, NC_GLOBAL, "analysis_time", NC_INT, 1, &hhmmss_loc);
+    CHKERR(1);
+  }
+
+  { /* Creation date & time */
+    /* NEC_LG: with PGI 10.9, yyyymmdd and hhmmss conflict with
+     * yyyymmdd/hhmmss defined types in privpub.h
+     */
+    int yyyymmdd_loc, hhmmss_loc;
+    codb_datetime_(&yyyymmdd_loc, &hhmmss_loc);
+    stat = nc_put_att_int(*ncid, NC_GLOBAL, "creation_date", NC_INT, 1, &yyyymmdd_loc);
+    CHKERR(1);
+    stat = nc_put_att_int(*ncid, NC_GLOBAL, "creation_time", NC_INT, 1, &hhmmss_loc);
+    CHKERR(1);
+  }
+
+  { /* Jobid, experiment version & owner & user, if available */
+    char chpid[100];
+    char *env;
+    env = getenv("ODB_NETCDF_JOBID");
+    if (!env) {
+      snprintf(chpid,sizeof(chpid),"%d",(int)getpid());
+      env = chpid;
+    }
+    if (env) {
+      char *jobid = STRDUP(env);
+      stat = nc_put_att_text(*ncid, NC_GLOBAL, "jobid", STRLEN(jobid), jobid);
+      CHKERR(1);
+      FREE(jobid);
+    }
+    env = getenv("EXPVER");
+    if (env) {
+      char *expver = STRDUP(env);
+      stat = nc_put_att_text(*ncid, NC_GLOBAL, "expver", STRLEN(expver), expver);
+      CHKERR(1);
+      FREE(expver);
+    }
+    env = getenv("OWNER");
+    if (env) {
+      char *owner = STRDUP(env);
+      stat = nc_put_att_text(*ncid, NC_GLOBAL, "owner", STRLEN(owner), owner);
+      CHKERR(1);
+      FREE(owner);
+    }
+    env = getenv("USER");
+    if (env) {
+      char *user = STRDUP(env);
+      stat = nc_put_att_text(*ncid, NC_GLOBAL, "user", STRLEN(user), user);
+      CHKERR(1);
+      FREE(user);
+    }
+    else {
+      env = getenv("LOGNAME");
+      if (env) {
+	char *logname = STRDUP(env);
+	stat = nc_put_att_text(*ncid, NC_GLOBAL, "user", STRLEN(logname), logname);
+	CHKERR(1);
+	FREE(logname);
+      }
+    }
+  }
+
+  *retcode = rc; /* Dimension id of "nrows" */
+}
+
+void codb_enddef_netcdf_(const int *ncid, 
+			 int *retcode)
+{
+  int stat = nc_enddef(*ncid);
+  CHKERR(1);
+  *retcode = stat;
+}
+
+void codb_putheader_netcdf_(const int *ncid,
+			    const int *colnum,
+
+			    const char *odb_type,
+			    const char *odb_name,
+			    const char *odb_nickname,
+			    const char *mapname,
+			    const char *long_name,
+			    const char *units,
+			    
+			    const double *mdi,
+			    const int *coltype,
+			    const int *colpack,
+			    const double *scale_factor,
+			    const double *add_offset,
+			    
+			    int *retcode
+			    /* Hidden arguments */
+			    ,int odb_type_len
+			    ,int odb_name_len
+			    ,int odb_nickname_len
+			    ,int mapname_len
+			    ,int units_len
+			    ,int long_name_len)
+{
+  DECL_FTN_CHAR(odb_type);
+  DECL_FTN_CHAR(odb_name);
+  DECL_FTN_CHAR(odb_nickname);
+  DECL_FTN_CHAR(mapname);
+  DECL_FTN_CHAR(long_name);
+  DECL_FTN_CHAR(units);
+  int ndims = (*coltype == NC_CHAR) ? 2 : 1;
+  int dimid[2];
+  int colid;
+  int stat;
+  int has_ll = 0;
+  static char *odb_lat = NULL;
+  static char *odb_lon = NULL;
+
+  if (!odb_lat) {
+    char *env = getenv("ODB_LAT");
+    odb_lat = env ? STRDUP(env) : STRDUP("lat at hdr");
+  }
+  if (!odb_lon) {
+    char *env = getenv("ODB_LON");
+    odb_lon = env ? STRDUP(env) : STRDUP("lon at hdr");
+  }
+
+  stat = nc_inq_dimid(*ncid, "nrows", &dimid[0]);
+  CHKERR(1);
+
+  if (ndims == 2) {
+    stat = nc_inq_dimid(*ncid, "nstr", &dimid[1]);
+    CHKERR(1);
+  }
+
+  ALLOC_FTN_CHAR(odb_type);
+  ALLOC_FTN_CHAR(odb_name);
+  ALLOC_FTN_CHAR(odb_nickname);
+  ALLOC_FTN_CHAR(mapname);
+  ALLOC_FTN_CHAR(long_name);
+  ALLOC_FTN_CHAR(units);
+
+  {
+    {
+      char p[30];
+      snprintf(p, sizeof(p), "col_%d", *colnum);
+      stat = nc_def_var(*ncid, p, *coltype, ndims, dimid, &colid);
+      CHKERR(1);
+    }
+
+    if (STRLEN(p_long_name) > 0 && !strequ(p_long_name,"-")) {
+      stat = nc_put_att_text(*ncid, colid, "long_name", STRLEN(p_long_name), p_long_name);
+      CHKERR(1);
+    }
+
+    stat = nc_put_att_text(*ncid, colid, "odb_name", STRLEN(p_odb_name), p_odb_name);
+    CHKERR(1);
+
+    if (STRLEN(p_odb_nickname) > 0 && !strequ(p_odb_name,p_odb_nickname)) {
+      has_ll = (strequ(p_odb_nickname, odb_lat) || strequ(p_odb_nickname, odb_lon)) ? 1 : 0;
+      stat = nc_put_att_text(*ncid, colid, "odb_nickname", STRLEN(p_odb_nickname), p_odb_nickname);
+    }
+    else {
+     has_ll = (strequ(p_odb_name, odb_lat) || strequ(p_odb_name, odb_lon)) ? 1 : 0;
+     stat = nc_put_att_text(*ncid, colid, "odb_nickname", STRLEN(p_odb_name), p_odb_name);
+    }
+    CHKERR(0); /* bail out on error */
+
+    stat = nc_put_att_text(*ncid, colid, "odb_type", STRLEN(p_odb_type), p_odb_type);
+    CHKERR(1);
+
+    if (*colpack == 1 || *coltype != NC_CHAR) {
+      switch (*coltype) {
+      case NC_CHAR: /* Comes here only with *colpack == 1 */
+	{
+	  char *s = NULL;
+	  const char fillvalue[] = " ";
+	  stat = nc_put_att_text(*ncid, colid, _FillValue, STRLEN(fillvalue), fillvalue);
+	  CHKERR(1);
+	  s = make_printable((const char *)mdi, sizeof(*mdi));
+	  stat = nc_put_att_text(*ncid, colid, "missing_value", STRLEN(s), s);
+	  CHKERR(1);
+	  FREE(s);
+	}
+	break;
+      case NC_BYTE:
+	ASSIGN_FV_MDI(signed char, schar, NC_BYTE, -127-1);
+	break;
+      case NC_SHORT:
+	ASSIGN_FV_MDI(short, short, NC_SHORT, -32767-1);
+	break;
+      case NC_INT:
+	ASSIGN_FV_MDI(int, int, NC_INT, -2147483647-1);
+	break;
+      case NC_FLOAT:
+	ASSIGN_FV_MDI(float, float, NC_FLOAT, 1.7e+38);
+	break;
+      case NC_DOUBLE:
+	ASSIGN_FV_MDI(double, double, NC_DOUBLE, *mdi);
+	break;
+      }
+    }
+
+    if (*colpack == 2 || *colpack == 3) {
+      stat = nc_put_att_double(*ncid, colid, "scale_factor", NC_DOUBLE, 1, scale_factor);
+      CHKERR(1);
+      stat = nc_put_att_double(*ncid, colid, "add_offset", NC_DOUBLE, 1, add_offset);
+      CHKERR(1);
+      stat = nc_put_att_int(*ncid, colid, "colpack", NC_INT, 1, colpack);
+      CHKERR(1);
+    }
+
+    if (STRLEN(p_units) > 0 && !strequ(p_units,"-")) {
+      stat = nc_put_att_text(*ncid, colid, "units", STRLEN(p_units), p_units);
+      CHKERR(1);
+    }
+    else if (has_ll) {
+      const char Units[] = "degrees";
+      stat = nc_put_att_text(*ncid, colid, "units", STRLEN(Units), Units);
+      CHKERR(1);
+    }
+  }
+
+  /* finish: */
+  FREE_FTN_CHAR(odb_type);
+  FREE_FTN_CHAR(odb_name);
+  FREE_FTN_CHAR(odb_nickname);
+  FREE_FTN_CHAR(mapname);
+  FREE_FTN_CHAR(long_name);
+  FREE_FTN_CHAR(units);
+
+  *retcode = colid;
+}
+
+/* put to NetCDF */ 
+
+static void pack4cdf_short(const int *ncid,
+			   const int *colid,
+			   size_t start,
+			   const double d[],
+			   size_t count,
+			   double mdi)
+{
+  int j;
+  short *pk = NULL;
+  double scale_factor, add_offset;
+  short fillvalue;
+  int stat;
+
+  stat = nc_get_att_short(*ncid, *colid, _FillValue, &fillvalue);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\t%s = %.13g\n", _FillValue, (double)fillvalue);
+
+  stat = nc_get_att_double(*ncid, *colid, "scale_factor", &scale_factor);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\tscale_factor = %.14g\n", scale_factor);
+
+  stat = nc_get_att_double(*ncid, *colid, "add_offset", &add_offset);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\tadd_offset = %.14g\n", add_offset);
+
+  ALLOC(pk, count);
+  for (j=0; j<count; j++) {
+    double tmp = d[j];
+    if (ABS(tmp) == ABS(mdi)) {
+      tmp = fillvalue;
+    }
+    else {
+      tmp = tmp - add_offset;
+      tmp /= scale_factor;
+    }
+    pk[j] = tmp;
+  }
+
+  RAW_TO_NETCDF(short,short,pk);
+
+  FREE(pk);
+}
+
+static void pack4cdf_byte(const int *ncid,
+			  const int *colid,
+			  size_t start,
+			  const double d[],
+			  size_t count,
+			  double mdi)
+{
+  int j;
+  signed char *pk = NULL;
+  double scale_factor, add_offset;
+  signed char fillvalue;
+  int stat;
+
+  stat = nc_get_att_schar(*ncid, *colid, _FillValue, &fillvalue);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\t%s = %.13g\n", _FillValue, (double)fillvalue);
+
+  stat = nc_get_att_double(*ncid, *colid, "scale_factor", &scale_factor);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\tscale_factor = %.14g\n", scale_factor);
+
+  stat = nc_get_att_double(*ncid, *colid, "add_offset", &add_offset);
+  CHKERR(1);
+  if (debug_mode) fprintf(stderr,"\tadd_offset = %.14g\n", add_offset);
+
+  ALLOC(pk, count);
+  for (j=0; j<count; j++) {
+    double tmp = d[j];
+    if (ABS(tmp) == ABS(mdi)) {
+      tmp = fillvalue;
+    }
+    else {
+      tmp = tmp - add_offset;
+      tmp /= scale_factor;
+    }
+    pk[j] = tmp;
+  }
+
+  RAW_TO_NETCDF(signed char,schar,pk);
+
+  FREE(pk);
+}
+
+void codb_putdata_netcdf_(const int *ncid,
+			  const int *colid,
+			  const int *colpack,
+			  const double d[],
+			  const int *f90_addr,
+			  const int *nd,
+			  int *retcode)
+{
+  size_t start = (*f90_addr) - 1;
+  size_t count = *nd;
+  int id;
+  double mdi;
+  nc_type coltype;
+  int stat;
+
+  if (debug_mode) fprintf(stderr,"Processing colid %d ...\n", *colid);
+
+  stat = nc_inq_vartype(*ncid, *colid, &coltype);
+  CHKERR(1);
+
+  if (debug_mode) fprintf(stderr,"\tcolpack = %d\n", *colpack);
+
+  if (coltype != NC_CHAR) {
+    stat = nc_get_att_double(*ncid, *colid, "missing_value", &mdi);
+    CHKERR(1);
+    if (debug_mode) fprintf(stderr,"\tmdi = %.14g\n", mdi);
+  }
+
+  if (*colpack == 2) {
+    pack4cdf_short(ncid,colid,start,d,count,mdi);
+  }
+  else if (*colpack == 3) {
+    pack4cdf_byte(ncid,colid,start,d,count,mdi);
+  }
+  else if (*colpack == 0) {
+    switch (coltype) {
+    case NC_CHAR:
+      {
+	char *s = NULL;
+	count *= sizeof(string);
+	s = make_printable((const char *)d,count);
+	RAW_TO_NETCDF_VAR(char,text,s);
+	FREE(s);
+	count /= sizeof(string);
+      }
+      break;
+    case NC_BYTE:
+      VIACOPY_TO_NETCDF(signed char,schar,d);
+      break;
+    case NC_SHORT:
+      VIACOPY_TO_NETCDF(short,short,d);
+      break;
+    case NC_INT:
+      VIACOPY_TO_NETCDF(int,int,d);
+      break;
+    case NC_FLOAT:
+      VIACOPY_TO_NETCDF(float,float,d);
+      break;
+    case NC_DOUBLE:
+      RAW_TO_NETCDF(double,double,d);
+      break;
+    default:
+      fprintf(stderr,
+	      "***Warning: Unknown type = %d for NetCDF variable id = %d\n",
+	      coltype, *colid);
+      stat = NC_EBADTYPE;
+      CHKERR(0); /* bail out on error */
+      count = 0;
+      break;
+    }
+  }
+  else { /* *colpack == 1 --> do nothing */
+    fprintf(stderr,
+	    "***Warning: Unsupported packing = %d for NetCDF variable id = %d, type = %d\n",
+	    *colpack, *colid, coltype);
+    count = 0;
+  }
+
+ finish:
+  *retcode = count;
+}
+
+void codb_close_netcdf_(int *ncid, 
+			int *retcode)
+{
+  int stat = nc_close(*ncid);
+  CHKERR(1);
+  *ncid = -1;
+  *retcode = stat;
+}
+
+#else /* NETCDF is NOT available */
+
+void
+codb_has_netcdf_(int *retcode) 
+{ 
+  *retcode = 0; 
+}
+
+void codb_gettype_netcdf_(const char *typename,
+			  int *retcode
+			  /* Hidden arguments */
+			  ,int typename_len)
+{
+  *retcode = -1;
+}
+
+void codb_open_netcdf_(int *ncid,
+		       const char *filename,
+		       const char *mode,
+		       int *retcode
+		       /* Hidden arguments */
+		       ,int filename_len
+		       ,int mode_len)
+{
+  *ncid = -1;
+  *retcode = -1;
+}
+
+void codb_begindef_netcdf_(const int *ncid,
+			   const char *title,
+			   const char *sql_query,
+			   const int *nrows, 
+			   const int *ncols,
+			   const double *mdi,
+			   const int *poolno,
+			   int *retcode
+			   /* Hidden arguments */
+			   , int title_len
+			   , int sql_query_len)
+{
+  *retcode = -1;
+}
+
+void codb_enddef_netcdf_(const int *ncid, 
+			 int *retcode)
+{
+  *retcode = -1;
+}
+
+void codb_putheader_netcdf_(const int *ncid,
+			    const int *colnum,
+
+			    const char *odb_type,
+			    const char *odb_name,
+			    const char *odb_nickname,
+			    const char *mapname,
+			    const char *long_name,
+			    const char *units,
+			    
+			    const double *mdi,
+			    const int *coltype,
+			    const int *colpack,
+			    const double *scale_factor,
+			    const double *add_offset,
+			    
+			    int *retcode
+			    /* Hidden arguments */
+			    ,int odb_type_len
+			    ,int odb_name_len
+			    ,int odb_nickname_len
+			    ,int mapname_len
+			    ,int units_len
+			    ,int long_name_len)
+{
+  *retcode = -1;
+}
+
+void codb_putdata_netcdf_(const int *ncid,
+			  const int *colid,
+			  const int *colpack,
+			  const double d[],
+			  const int *f90_addr,
+			  const int *nd,
+			  int *retcode)
+{
+  *retcode = -1;
+}
+
+void codb_close_netcdf_(int *ncid, 
+			int *retcode)
+{
+  *ncid = -1;
+  *retcode = -1;
+}
+
+#endif
diff --git a/odb/src/aux/dca.c b/odb/src/aux/dca.c
new file mode 100644
index 0000000..50c6869
--- /dev/null
+++ b/odb/src/aux/dca.c
@@ -0,0 +1,1574 @@
+
+/* dca.c */
+
+#include "odb.h"
+#include "odb_macros.h"
+#include "dca.h"
+#include "alloc.h"
+#include "cmaio.h"
+#include "magicwords.h"
+#include "swapbytes.h"
+#include "pcma_extern.h"
+#include "cdrhook.h"
+
+#define NIBUF 14  /* Do not change and keep consistent with tools/dcagen.c's value */
+#define NDBUF_MAX 50
+
+PRIVATE int dca_debug = -1;
+
+#define DCA_DEBUG(hex) ((dca_debug > 0) && ((dca_debug & (hex)) == hex))
+
+PRIVATE dca_chain_t *dca_chain = NULL;
+PRIVATE dca_chain_t *dca_chain_last = NULL;
+  
+#define fast_physproc(poolno,nproc) (((poolno)-1)%nproc + 1)
+
+extern void ODB_monitor_memory_addr(const void *p, const char *pwhat, const char *file, int linenum);
+#define SETMEMOWR(p,pwhat) ODB_monitor_memory_addr(p,pwhat,__FILE__,__LINE__)
+
+extern void ODB_check_memory_overwrite(const char *file, int linenum);
+#define CHKMEMOWR() ODB_check_memory_overwrite(__FILE__, __LINE__)
+
+PRIVATE o_lock_t DCA_mylock = 0; /* A specific OMP-lock; initialized only once in
+				    odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+PUBLIC void
+init_DCA_lock()
+{
+  INIT_LOCKID_WITH_NAME(&DCA_mylock,"dca.c:DCA_mylock");
+}
+
+
+PRIVATE uint 
+HashIs(const char *s)
+{
+  const uint hashsize = 1031U;
+  uint hashval = 0;
+  for (; s && *s ; s++) {
+    hashval = (*s) + 31U * hashval;
+  }
+  hashval = hashval % hashsize;
+  return hashval;
+}
+
+
+PRIVATE void
+DCA_Trace(int mode,
+	  const char *name,
+	  const dca_t *pdca,
+	  const dca_chain_t *pchain,
+	  int misc)
+{
+  if (pdca && pchain) {
+    FILE *do_trace = ODB_trace_fp();
+    coml_set_lockid_(&DCA_mylock);
+    if (do_trace) {
+      char msg[65536]; /* Enough ? */
+      ODB_Trace TracE;
+      TracE.handle = pchain->handle;
+      TracE.msglen = sizeof(msg);
+      TracE.msg = msg;
+      TracE.args[0] = pdca->poolno;
+      TracE.args[1] = pdca->colnum;
+      TracE.args[2] = pdca->nrows;
+      TracE.args[3] = pdca->nmdis;
+      TracE.args[4] = pdca->offset;
+      TracE.args[5] = pdca->length;
+      TracE.args[6] = pdca->dtnum;
+      TracE.args[7] = pdca->pmethod;
+      TracE.args[8] = pdca->pmethod_actual;
+      TracE.args[9] = pdca->is_little;
+      TracE.args[10] = pdca->hash;
+      TracE.args[11] = misc;
+      TracE.numargs = 12; 
+      TracE.mode = mode;
+      sprintf(TracE.msg,
+	      "%s(%s)[it#%d]: %s:%s@%s, (min,max,avg,card)=(%.14g,%.14g,%.14g,%d)",
+	      name, pdca->filename, pchain->it,
+	      pdca->dtname, pdca->colname, pchain->tblname,
+	      pdca->min,pdca->max,pdca->avg,pdca->ncard);
+      codb_trace_(&TracE.handle, &TracE.mode,
+		  TracE.msg, TracE.args, 
+		  &TracE.numargs, TracE.msglen);
+    } /* if (do_trace) */
+    coml_unset_lockid_(&DCA_mylock);
+  }
+}
+  
+
+PRIVATE void
+IODCA_close(iodca_t *iodca)
+{
+  DRHOOK_START(IODCA_close);
+  if (iodca) {
+    if (iodca->unit != -1) {
+      int iret;
+      cma_close_(&iodca->unit, &iret);
+      if (DCA_DEBUG(0x1)) {
+	fprintf(stderr,
+		"IODCA_close[file='%s', unit=%d, rewind=%d, offset=%d : iret=%d]\n",
+		iodca->file, iodca->unit, iodca->can_rewind, iodca->offset, iret);
+      }
+    }
+    iodca->unit = -1;
+    iodca->offset = 0;
+    iodca->can_rewind = 0;
+    FREE(iodca->file);
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE int
+IODCA_open(const char *file,
+	   iodca_t *iodca)
+{
+  int rc = 0;
+  DRHOOK_START(IODCA_open);
+  IODCA_close(iodca);
+  if (file) {
+    int unit,iret;
+    cma_open_(&unit, file, "r", &iret, strlen(file), 1);
+    if (iret != 1) {
+      fprintf(stderr,"***Error in IODCA_open: Unable to open file '%s'\n",file);
+      unit = -1;
+      rc = -1;
+    }
+    else {
+      rc = iret;
+      if (iodca) {
+	int index = IOINDEX(unit);
+	int tid = get_thread_id_();
+	IOcma *pcmaio = &cmaio[tid][index];
+	if (pcmaio && pcmaio->io.is_inuse) {
+	  iodca->can_rewind = ((pcmaio->io.scheme & external) == external) ? 0 : 1;
+	}
+	else {
+	  iodca->can_rewind = 0;
+	}
+	iodca->unit = unit;
+	iodca->offset = 0;
+	iodca->file = STRDUP(file);
+      }
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PRIVATE int 
+IODCA_getpos(const char *file,
+	     int offset,
+	     int length,
+	     iodca_t *iodca,
+	     const char *colname,
+	     const char *tblname,
+	     int poolno,
+	     dca_chain_t *pchain)
+{
+  int rc = 0;
+  if (file && iodca) {
+    if (iodca->unit == -1 || 
+	(!iodca->can_rewind && offset < iodca->offset) ||
+	!strequ(iodca->file,file)) {
+      int thesame = strequ(iodca->file,file);
+      if (DCA_DEBUG(0x1)) {
+	fprintf(stderr,
+		"IODCA_getpos[file='%s' for %s@%s, pool#%d, cur.off=%d, off:len=%d:%d, chain=%p]\n",
+		file,
+		colname,tblname,poolno,iodca->offset,
+		offset,length,pchain);
+      }
+      rc = IODCA_open(file,iodca);
+      if (DCA_DEBUG(0x4)) {
+	fprintf(stderr,
+		">IODCA_getpos[Just %sopened='%s', unit=%d, rewindable=%d : rc=%d]\n",
+		thesame ? "re-" : "",
+		iodca->file, iodca->unit, iodca->can_rewind, rc);
+      }
+    }
+  }
+  return rc;
+}
+
+
+PRIVATE dca_chain_t *
+Next_Free()
+{
+  dca_chain_t *pchain = NULL;
+  coml_set_lockid_(&DCA_mylock);
+  {
+    pchain = dca_chain;
+    while (pchain) {
+      if (pchain->handle < 1) {
+	break; /* Found an unused slot */
+      }
+      pchain = pchain->next;
+    } /* while (pchain) */
+    if (!pchain) {
+      CALLOC(pchain,1);
+      if (!dca_chain) {
+	dca_chain = dca_chain_last = pchain;
+      }
+      else {
+	dca_chain_last->next = pchain;
+	dca_chain_last = dca_chain_last->next;
+      }
+      pchain->next = NULL;
+    }
+  }
+  coml_unset_lockid_(&DCA_mylock);
+  return pchain;
+}
+
+
+PUBLIC dca_chain_t *
+DCA_alloc(int handle,
+	  const char *dbname,
+	  const char *tblname,
+	  int *retcode)
+     /* Read & allocate a DCA-file into internal data structures */
+{
+  int rc = 0;
+  dca_chain_t *pchain = NULL;
+  char *dcafile = NULL;
+  DRHOOK_START(DCA_alloc);
+  if (tblname && *tblname == '@') tblname++;
+  if (handle > 0 && dbname && tblname) {
+    int dcafile_len = strlen(dbname) + 1 + strlen(tblname) + 1 + 3 + 1;
+    if (dca_debug < 0) {
+      char *env = getenv("ODB_DCA_DEBUG");
+      if (env) dca_debug = atoi(env);
+      if (dca_debug < 0) dca_debug = 0;
+    }
+    pchain = Next_Free();
+    ALLOC(pchain->iodca,1);
+    pchain->iodca->unit = -1;
+    pchain->iodca->offset = 0;
+    pchain->iodca->can_rewind = 0;
+    pchain->iodca->file = NULL;
+    pchain->handle = 0; /* Not yet allocated (but ok'ayed) */
+    pchain->it = get_thread_id_();
+    pchain->dbname = NULL;
+    pchain->tblname = NULL;
+    ALLOC(dcafile,dcafile_len);
+    sprintf(dcafile,"%s.%s.dca",dbname,tblname);
+    pchain->dcafile = NULL;
+    pchain->dca = NULL;
+    pchain->dcalen = 0;
+    pchain->ncols = 0;
+    pchain->min_poolno = 2147483647;
+    pchain->max_poolno = 0;
+    pchain->min_hash = 2147483647U;
+    pchain->max_hash = 0;
+  } /* if (handle > 0 && dbname && tblname) */
+
+  if (DCA_DEBUG(0x1)) {
+    fprintf(stderr, 
+	    "DCA_alloc(pchain=%p, handle=%d, dbname='%s', tblname='%s' : dcafile='%s')\n",
+	    pchain, handle, 
+	    dbname ? dbname : NIL,
+	    tblname ? tblname : NIL,
+	    dcafile ? dcafile : NIL);
+  }
+
+  if (pchain) {
+    int unit, iret;
+    FILE *fp = NULL;
+
+    cma_open_(&unit, dcafile, "r", &iret,
+	      strlen(dcafile), 1);
+    fp = (iret == 1) ? CMA_get_fp(&unit) : NULL;
+
+    if (fp) {
+      dca_t this_dca;
+      char colname[MAXLINE+1];
+      char dtname[MAXLINE+1];
+      char filename[MAXLINE+1];
+      char line[MAXLINE+1];
+      int iter = 1;
+      int is_binary = 0;
+      unsigned int magic_word;
+      const int magic_word_len = sizeof(magic_word);
+      int swap_dca = 0;
+      short int nbuf[2];
+      const int nbuf_len = sizeof(nbuf);
+      int ibuf[NIBUF];  /* fixed for life, but ... */
+      double dbuf[NDBUF_MAX]; /* ... this permits any future expansions up to NDBUF_MAX cells */
+      int ilen, nibuf, ndbuf;
+      int j = 0;
+      int myproc = 1, nproc = 1;
+      int errflg = 0;
+      codb_procdata_(&myproc, &nproc, NULL, NULL, NULL);
+
+      cma_readb_(&unit, (byte1 *)&magic_word, &magic_word_len, &iret);
+      if (iret == magic_word_len) {
+	is_binary = (magic_word == DCA2 || magic_word == _2ACD);
+	if (is_binary) {
+	  swap_dca = (magic_word == _2ACD);
+	  cma_readb_(&unit, (byte1 *)&nbuf, &nbuf_len, &iret);
+	  if (iret == nbuf_len) {
+	    ilen = 2;
+	    if (swap_dca) swap2bytes_(&nbuf, &ilen);
+	    nibuf = nbuf[0]; ndbuf = nbuf[1];
+	    if (nibuf != NIBUF) {
+	      fprintf(stderr,
+		      "***Error: Invalid value for nibuf = %d in presumably binary DCA-file '%s'."
+		      " Must always be equal to %d\n",
+		      nibuf,dcafile,NIBUF);
+	      errflg++;
+	    }
+	    if (ndbuf < 0 || ndbuf > NDBUF_MAX) {
+	      fprintf(stderr,
+		      "***Error: Invalid value for ndbuf = %d in presumably binary DCA-file '%s'."
+		      " Must be between 0 and %d\n",
+		      ndbuf,dcafile,NDBUF_MAX);
+	      errflg++;
+	    }
+	  }
+	  else {
+	    fprintf(stderr,
+		    "***Error: Unable to read 'nbuf'-infos from presumably binary DCA-file '%s'\n",
+		    dcafile);
+	    errflg++;
+	  }
+	}
+	if (!is_binary) {
+	  cma_rewind_(&unit, &iret);
+	  fp = CMA_get_fp(&unit); /* need this, if file io_scheme was external */
+	}
+      }
+      else if (iret != -1) { /* Exclude EOF from errors, though */
+	fprintf(stderr,
+		"***Error: The DCA-file '%s' has illegal text/binary format\n",
+		dcafile);
+	errflg++;
+      }
+
+      if (errflg) RAISE(SIGABRT);
+
+      do {
+	if (iter == 2) {
+	  cma_rewind_(&unit, &iret);
+	  fp = CMA_get_fp(&unit); /* need this, if file io_scheme was external */
+	  pchain->dcalen = rc;
+	  CALLOC(pchain->dca,rc);
+	  j = 0;
+	}
+
+	if (is_binary) {
+	  int poolno, *lens;
+	  const int binwhence = 1; /* SEEK_CUR (= seek from the current pos) */
+	  int binoff = magic_word_len + nbuf_len;
+	  if (iter == 2) cma_seekb_(&unit, &binoff, &binwhence, &iret);
+	  for (;;) {
+	    dca_t *pdca = NULL;
+	    ilen = nibuf * sizeof(*ibuf);
+	    cma_readb_(&unit, (byte1 *)ibuf, &ilen, &iret);
+	    if (iret != ilen) {
+	      if (iret == -1) break; /* EOF */
+	      fprintf(stderr,
+		      "***Error: Unable to read the first %d ibuf-words from DCA-file"
+		      " '%s' (iter=%d) : iret=%d\n", 
+		      nibuf, dcafile, iter, iret);
+	      RAISE(SIGABRT);
+	    }
+	    if (swap_dca) swap4bytes_(ibuf, &nibuf);
+	    poolno = ibuf[0];
+	    lens = &ibuf[1];
+	    if (poolno > 0 &&
+		fast_physproc(poolno,nproc) == myproc &&
+		ODB_in_permanent_poolmask(handle,poolno)) {
+	      if (iter == 1) rc++; else pdca = &pchain->dca[j];
+	    }
+
+	    binoff = ndbuf * sizeof(*dbuf) + lens[0] + lens[1] + lens[2];
+
+	    if (pdca) {
+	      binoff = 0; /* We do not want to skip anything over */
+	      ilen = ndbuf * sizeof(*dbuf);
+	      cma_readb_(&unit, (byte1 *)dbuf, &ilen, &iret);
+	      if (iret != ilen) {
+		fprintf(stderr,
+			"***Error: Unable to read the last %d dbuf-words from DCA-file"
+			" '%s' (iter=%d) : iret=%d\n", 
+			ndbuf, dcafile, iter, iret);
+		RAISE(SIGABRT);
+	      }
+	      if (swap_dca) swap8bytes_(&dbuf, &ndbuf);
+
+	      pdca->poolno = poolno;
+
+	      if (nibuf >  4) pdca->dtnum = ibuf[4];
+	      if (nibuf >  5) pdca->colnum = ibuf[5];
+	      if (nibuf >  6) pdca->length = ibuf[6];
+	      if (nibuf >  7) pdca->pmethod = ibuf[7];
+	      if (nibuf >  8) pdca->pmethod_actual = ibuf[8];
+	      if (nibuf >  9) pdca->nrows = ibuf[9];
+	      if (nibuf > 10) pdca->nmdis = ibuf[10];
+	      if (nibuf > 11) pdca->cr = ibuf[11];
+	      if (nibuf > 12) pdca->ncard = ibuf[12];
+	      if (nibuf > 13) pdca->is_little = ibuf[13];
+	      
+	      if (ndbuf >  0) pdca->offset = dbuf[0];
+	      if (ndbuf >  1) pdca->avg = dbuf[1];
+	      if (ndbuf >  2) pdca->min = dbuf[2];
+	      if (ndbuf >  3) pdca->max = dbuf[3];
+
+	      ALLOC(pdca->colname, lens[0] + 1);
+	      cma_readb_(&unit, (byte1 *)pdca->colname, &lens[0],  &iret);
+	      if (iret != lens[0]) {
+		fprintf(stderr,
+			"***Error: Unable to read column name (%d bytes) from DCA-file"
+			" '%s' (iter=%d) : iret=%d\n", lens[0], dcafile, iter, iret);
+		RAISE(SIGABRT);
+	      }
+	      pdca->colname[lens[0]] = '\0';
+	      {
+		char *at = strchr(pdca->colname,'@');
+		if (at) *at = '\0';
+	      }
+	      pdca->hash = HashIs(pdca->colname);
+
+	      ALLOC(pdca->dtname, lens[1] + 1);
+	      cma_readb_(&unit, (byte1 *)pdca->dtname, &lens[1],  &iret);
+	      if (iret != lens[1]) {
+		fprintf(stderr,
+			"***Error: Unable to read column data type (%d bytes) from DCA-file"
+			" '%s' (iter=%d) : iret=%d\n", lens[1], dcafile, iter, iret);
+		RAISE(SIGABRT);
+	      }
+	      pdca->dtname[lens[1]] = '\0';
+	      
+	      ALLOC(pdca->filename, lens[2] + 1);
+	      cma_readb_(&unit, (byte1 *)pdca->filename, &lens[2],  &iret);
+	      if (iret != lens[2]) {
+		fprintf(stderr,
+			"***Error: Unable to read column data file name (%d bytes) from DCA-file"
+			" '%s' (iter=%d) : iret=%d\n", lens[2], dcafile, iter, iret);
+		RAISE(SIGABRT);
+	      }
+	      pdca->filename[lens[2]] = '\0';
+	      
+	      if (pdca->colnum + 1 > pchain->ncols) pchain->ncols = pdca->colnum + 1;
+	      if (pdca->poolno < pchain->min_poolno) pchain->min_poolno = pdca->poolno;
+	      if (pdca->poolno > pchain->max_poolno) pchain->max_poolno = pdca->poolno;
+	      if (pdca->hash < pchain->min_hash) pchain->min_hash = pdca->hash;
+	      if (pdca->hash > pchain->max_hash) pchain->max_hash = pdca->hash;
+	      if (++j >= pchain->dcalen) break; /* for (;;) */
+	    } /* if (pdca) */
+
+	    if (binoff > 0) {
+	      cma_seekb_(&unit, &binoff, &binwhence, &iret);
+	    }
+	  } /* for (;;) */
+	}
+	else {
+	  while (!feof(fp) && fgets(line, MAXLINE, fp)) {
+	    const char *p = line;
+	    if (*p != '#') {
+	      dca_t *pdca = (iter == 1) ? &this_dca : &pchain->dca[j];
+	      int nelem = sscanf(line, 
+				 "%d %s %s %u %s %d %llu %d %d %d %d %d %lf %lf %lf %lf %d %d",
+				 &pdca->colnum, colname, dtname, &pdca->dtnum,
+				 filename, &pdca->poolno, &pdca->offset, &pdca->length,
+				 &pdca->pmethod, &pdca->pmethod_actual,
+				 &pdca->nrows, &pdca->nmdis,
+				 &pdca->avg, &pdca->min, &pdca->max,
+				 &pdca->cr, &pdca->ncard, &pdca->is_little);
+	      if (iter == 1) {
+		if (nelem == 18 && 
+		    pdca->poolno > 0 &&
+		    fast_physproc(pdca->poolno,nproc) == myproc &&
+		    ODB_in_permanent_poolmask(handle,pdca->poolno)) rc++;
+	      }
+	      else { /* iter == 2 */
+		if (nelem == 18 && 
+		    pdca->poolno > 0 &&
+		    fast_physproc(pdca->poolno,nproc) == myproc &&
+		    ODB_in_permanent_poolmask(handle,pdca->poolno)) {
+		  char *at = strchr(colname,'@');
+		  if (at) *at = '\0';
+		  pdca->hash     = HashIs(colname);
+		  pdca->colname  = STRDUP(colname);
+		  pdca->dtname   = STRDUP(dtname);
+		  pdca->filename = STRDUP(filename);
+		  if (pdca->colnum + 1 > pchain->ncols) pchain->ncols = pdca->colnum + 1;
+		  if (pdca->poolno < pchain->min_poolno) pchain->min_poolno = pdca->poolno;
+		  if (pdca->poolno > pchain->max_poolno) pchain->max_poolno = pdca->poolno;
+		  if (pdca->hash < pchain->min_hash) pchain->min_hash = pdca->hash;
+		  if (pdca->hash > pchain->max_hash) pchain->max_hash = pdca->hash;
+		  if (++j >= pchain->dcalen) break; /* while (!feof(fp) && fgets(line, MAXLINE, fp)) */
+		}
+	      }
+	    } /* if (*p != '#') */
+	  } /* while (!feof(fp) && fgets(line, MAXLINE, fp)) */
+	} /* if (is_binary) ... else ... */
+
+	iter++;
+	clearerr(fp);
+      } while (rc > 0 && iter <= 2);
+
+      cma_close_(&unit, &iret);
+
+      if (rc > 0 && j == rc) { /* now all ok */
+	dca_t *pdca = pchain->dca;
+	pchain->handle = handle;
+	pchain->it = get_thread_id_();
+	pchain->dbname = STRDUP(dbname);
+	pchain->tblname = STRDUP(tblname);
+	pchain->dcafile = STRDUP(dcafile);
+	if (DCA_DEBUG(0x16)) {
+	  int poolno = -1;
+	  char *env = getenv("ODB_DCA_DEBUG_POOLNO");
+	  if (env) poolno = atoi(env);
+	  DCA_debugprt(stderr, handle, dbname, tblname, NULL, poolno);
+	}
+      }
+      else if (pchain->dcalen > 0) { /* not ok, but try to reclaim some space anyway */
+	dca_t *pdca = pchain->dca;
+	for (j=0; j<pchain->dcalen; j++) {
+	  FREE(pdca->colname);
+	  FREE(pdca->dtname);
+	  FREE(pdca->filename);
+	  pdca++;
+	}
+      }
+    } /* if (fp) */
+  } /* if (pchain) */
+  FREE(dcafile);
+
+  if (pchain && rc == 0) { /* still nothing found ; 
+			      perhaps DCA-file not there or 
+			      no data available for this tblname ? */
+    /* Find at least number of column -- in a hard way then 
+       (the info is indeed buried in each table's data struc) */
+    int Ncols = 0;
+    int poolno = -1;
+    int len;
+    char *at_tblname;
+    if (*tblname == '@') tblname++;
+    len = strlen(tblname) + 1;
+    ALLOCX(at_tblname,len+1);
+    sprintf(at_tblname,"@%s",tblname);
+    codb_getsize_(&handle,
+		  &poolno,
+		  at_tblname,
+		  NULL,
+		  &Ncols,
+		  NULL,
+		  NULL,
+		  NULL,
+		  /* Hidden arguments */
+		  len);
+    FREEX(at_tblname);
+    if (DCA_DEBUG(0x1)) {
+      fprintf(stderr, ">DCA_alloc(pchain=%p : Ncols=%d)\n", pchain, Ncols);
+    }
+    if (Ncols > 0) {
+      pchain->handle = handle;
+      pchain->it = get_thread_id_();
+      pchain->dbname = STRDUP(dbname);
+      pchain->tblname = STRDUP(tblname);
+      pchain->dcafile = STRDUP(dcafile);
+      pchain->ncols = Ncols;
+      rc = 1;
+    }
+  }
+  if (retcode) *retcode = rc;
+  if (DCA_DEBUG(0x1)) {
+    fprintf(stderr, ">DCA_alloc(pchain=%p : rc=%d)\n", pchain, rc);
+  }
+  DRHOOK_END(0);
+  return (rc > 0) ? pchain : NULL;
+}
+
+
+PUBLIC int
+DCA_free(int handle)
+{
+  int num_freed = 0;
+  DRHOOK_START(DCA_free);
+  coml_set_lockid_(&DCA_mylock);
+  if (dca_chain) {
+    if (DCA_DEBUG(0x8)) {
+      fprintf(stderr,"DCA_free: handle=%d\n",handle);
+    }
+    if (handle > 0) {
+      dca_chain_t *pchain = dca_chain;
+      while (pchain) {
+	if (pchain->handle == handle) {
+	  if (DCA_DEBUG(0x8)) {
+	    fprintf(stderr,"DCA_free: Freeing handle=%d, chain=%p\n",handle,pchain);
+	  }
+	  IODCA_close(pchain->iodca);
+	  FREE(pchain->iodca);
+	  pchain->handle = -handle; /* Free'd handle */
+	  FREE(pchain->dbname);
+	  FREE(pchain->tblname);
+	  FREE(pchain->dcafile);
+	  if (pchain->dca && pchain->dcalen > 0) {
+	    dca_t *pdca = pchain->dca;
+	    int j;
+	    for (j=0; j<pchain->dcalen; j++) {
+	      FREE(pdca->colname);
+	      FREE(pdca->dtname);
+	      FREE(pdca->filename);
+	      pdca++;
+	    }
+	  }
+	  FREE(pchain->dca);
+	  pchain->dcalen = 0;
+	  num_freed++;
+	} /* if (pchain->handle == handle && pchain->it == it) */
+	pchain = pchain->next;
+      } /* while (pchain) */
+    } /* if (handle > 0) */
+  }
+  coml_unset_lockid_(&DCA_mylock);
+  DRHOOK_END(0);
+  return num_freed;
+}
+
+
+PUBLIC int
+DCA_getsize(int handle,
+	    const char *dbname,
+	    const char *tblname,
+	    int poolno,
+	    int *nrows,
+	    int *ncols)
+{
+  int found = 0;
+  int Nrows = 0;
+  int Ncols = 0;
+  DRHOOK_START(DCA_getsize);
+  if ((nrows || ncols) && handle > 0 && dbname && tblname) {
+    int it = get_thread_id_();
+    dca_chain_t *pchain = NULL;
+    if (*tblname == '@') tblname++;
+    coml_set_lockid_(&DCA_mylock);
+    pchain = dca_chain;
+    while (pchain) {
+      if (pchain->handle == handle &&
+	  pchain->it == it &&
+	  strequ(pchain->dbname, dbname) &&
+	  strequ(pchain->tblname, tblname)) {
+	break;
+      }
+      pchain = pchain->next;
+    }
+    if (DCA_DEBUG(0x64)) {
+      fprintf(stderr, 
+	      "DCA_getsize(handle=%d,dbname='%s',tblname='%s',poolno=%d) : pchain=%p\n",
+	      handle, dbname?dbname:NIL, tblname?tblname:NIL,
+	      poolno, pchain);
+    }
+    coml_unset_lockid_(&DCA_mylock);
+    if (pchain && 
+	poolno >= pchain->min_poolno && poolno <= pchain->max_poolno) { /* found */
+      dca_t *pdca = pchain->dca;
+      int j;
+      for (j=0; j<pchain->dcalen; j++) {
+	if (pdca->poolno == poolno) { /* The first match is already sufficient */
+	  Nrows  = pdca->nrows;
+	  found = 1;
+	  break;
+	}
+	pdca++;
+      } /* for (j=0; j<pchain->dcalen; j++) */
+    }
+    if (pchain) {
+      Ncols = pchain->ncols; /* Note: given independently of the pool range */
+      if (!found) found = 2;
+    }
+    if (DCA_DEBUG(0x64)) {
+      fprintf(stderr, 
+	      ">DCA_getsize : Nrows=%d, Ncols=%d, found=%d\n",
+	      Nrows, Ncols, found);
+    }
+  }
+  if (nrows) *nrows = Nrows;
+  if (ncols) *ncols = Ncols;
+  DRHOOK_END(0);
+  return found;
+}
+
+
+PRIVATE int
+Fetch_Raw_Data(const char *dbname,
+	       void *ptr,
+	       dca_t *pdca,
+	       dca_chain_t *pchain)
+{
+  int rc = 0;
+  DRHOOK_START(Fetch_Raw_Data);
+  if (dbname && ptr && pchain && pdca &&
+      pdca->filename && pdca->length > 0) {
+    char *filename = NULL;
+    int allocated_filename;
+
+    if (*pdca->filename == '$' || 
+	*pdca->filename == '.' ||
+	*pdca->filename == '/') {
+      filename = pdca->filename;
+      allocated_filename = 0;
+    }
+    else {
+      char *env;
+      char *s = NULL;
+      int slen = strlen("ODB_DATAPATH_") + strlen(dbname) + 1;
+      ALLOC(s,slen);
+      sprintf(s,"%s%s","ODB_DATAPATH_",dbname);
+      env = getenv(s);
+      FREE(s);
+      if (env) {
+	int len = strlen("$ODB_DATAPATH_") + strlen(dbname) + 1 + strlen(pdca->filename) + 1;
+	ALLOC(filename,len);
+	sprintf(filename,"%s%s/%s","$ODB_DATAPATH_",dbname,pdca->filename);
+      }
+      else {
+	env = getenv("ODB_DATAPATH");
+	if (env) {
+	  int len = strlen("$ODB_DATAPATH") + 1 + strlen(pdca->filename) + 1;
+	  ALLOC(filename,len);
+	  sprintf(filename,"%s/%s","$ODB_DATAPATH",pdca->filename);
+	}
+	else {
+	  int len = 2 + strlen(pdca->filename) + 1;
+	  ALLOC(filename,len);
+	  sprintf(filename,"./%s",pdca->filename);
+	}
+      }
+      allocated_filename = 1;
+    }
+
+    if (pchain->iodca && filename) {
+      int errflg = 0;
+      int iret;
+      u_ll_t offset = pdca->offset;
+
+      if (DCA_DEBUG(0x2)) {
+	fprintf(stderr,
+		"Fetch_Raw_Data[db=%s, var=%s:%s%s%s, pool#%d, file=%s, "
+		"off=%llu, len=%d, nrows=%d]\n",
+		dbname,
+		pdca->dtname, pdca->colname,
+		(pchain && pchain->tblname) ? "@" : "",
+		(pchain && pchain->tblname) ? pchain->tblname : "",
+		pdca->poolno, filename, pdca->offset, pdca->length, pdca->nrows);
+      }
+
+      iret = IODCA_getpos(filename, offset, pdca->length, pchain->iodca, 
+			  pdca->colname, pchain->tblname, pdca->poolno, pchain);
+      if (iret >= 0) {
+	const int whence = 1; /* SEEK_CUR */
+	int ioff = offset - pchain->iodca->offset;
+
+	cma_seekb_(&pchain->iodca->unit, &ioff, &whence, &iret);
+	if (iret < 0) {
+	  errflg = -3;
+	  goto error_processing;
+	}
+
+	cma_readb_(&pchain->iodca->unit, ptr, &pdca->length, &iret);
+	if (iret != pdca->length) {
+	  errflg = -4;
+	  goto error_processing;
+	}
+
+	pchain->iodca->offset = offset + pdca->length; /* current data position */
+	rc = pdca->length;
+      } 
+      else {
+	errflg = -1;
+	goto error_processing;
+      }
+
+    error_processing:
+      if (errflg) {
+	fprintf(stderr,
+		"***Error: Unable to fetch data column='%s%s%s'"
+		" of pool#%d from file='%s' : last iret=%d, errflg=%d\n",
+		pdca->colname, 
+		(pchain && pchain->tblname) ? "@" : "",
+		(pchain && pchain->tblname) ? pchain->tblname : "",
+		pdca->poolno, filename, iret, errflg);
+	rc = errflg;
+	goto finish;
+      }
+    }
+    if (allocated_filename) { /* for the next time */
+      char *refname = STRDUP(pdca->filename);
+      /*
+      fprintf(stderr,"Fetch_Raw_Data(pchain=%p,pdca=%p):",pchain,pdca);
+      fprintf(stderr," filename (truename) ='%s', refname='%s'\n",filename,refname);
+      */
+      /* do the favor for every file that has the same char. string in pdca->filename */
+      if (pchain) {
+	dca_t *Pdca = pchain->dca;
+	int j;
+	for (j=0; j<pchain->dcalen; j++) {
+	  if (strequ(Pdca->filename,refname)) {
+	    FREE(Pdca->filename);
+	    Pdca->filename = STRDUP(filename);
+	  }
+	  Pdca++;
+	}
+      }
+      FREE(refname);
+      FREE(filename);
+    } /* if (allocated_filename) */
+  }
+ finish:
+  DRHOOK_END(0);
+  return rc;
+}
+
+PRIVATE void
+swap_nothing(void *v, const int *vlen) { }
+
+#define SWAPIT(type, nonfpe_type, swapfunc) \
+{ \
+  if (idx && idxlen > 0) { \
+    int j; \
+    /* Using types that do not trigger SIGFPEs when doing d[j] = vdata[idx[j]] */ \
+    /* SIGFPEs are possible especially when getting data from different endian */ \
+    /* Please note that sizeof(type) must be the the same as sizeof(nonfpe_type) !! */ \
+    const nonfpe_type *vdata = data; \
+    nonfpe_type *d = NULL; \
+    if (sizeof(type) != sizeof(nonfpe_type)) { \
+      fprintf(stderr,"***Programming error: sizeof(%s) = %d not equal to sizeof(%s) = %d\n", \
+	      #type, (int)sizeof(type), #nonfpe_type, (int)sizeof(nonfpe_type)); \
+      RAISE(SIGABRT); \
+    } \
+    ALLOC(d,idxlen); \
+    for (j=0; j<idxlen; j++) { \
+      d[j] = vdata[idx[j]]; \
+    } \
+    data = d; \
+    nrows = idxlen; \
+  } \
+  if (swp) swapfunc(data, &nrows); \
+}
+
+PRIVATE void *
+Byte_Swap(void *data, 
+	  int nrows, 
+	  uint dtnum,
+	  int swp,
+	  const int idx[],
+	  int idxlen,
+	  const char *dtname,
+	  const char *colname,
+	  const char *tblname)
+{
+  if (nrows > 0) {
+    if (dtnum == DATATYPE_REAL8) {
+      SWAPIT(double, u_ll_t, swap8bytes_);
+    }
+    else if (dtnum == DATATYPE_INT4) {
+      SWAPIT(int, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_LINKOFFSET) {
+      SWAPIT(linkoffset_t, linkoffset_t, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_LINKLEN) {
+      SWAPIT(linklen_t, linklen_t, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_YYYYMMDD) {
+      SWAPIT(yyyymmdd, yyyymmdd, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_HHMMSS) {
+      SWAPIT(hhmmss, hhmmss, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_BITFIELD) {
+      SWAPIT(int, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_STRING) {
+      SWAPIT(string, u_ll_t, swap8bytes_);
+    }
+    else if (dtnum == DATATYPE_BUFR) {
+      SWAPIT(bufr, bufr, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_GRIB) {
+      SWAPIT(grib, grib, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_UINT4) {
+      SWAPIT(unsigned int, unsigned int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_REAL4) {
+      SWAPIT(float, unsigned int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_INT2) {
+      SWAPIT(short int, short int, swap2bytes_);
+    }
+    else if (dtnum == DATATYPE_UINT2) {
+      SWAPIT(unsigned short int, unsigned short int, swap2bytes_);
+    }
+    else if (dtnum == DATATYPE_INT1) {
+      SWAPIT(char, char, swap_nothing);
+    }
+    else if (dtnum == DATATYPE_UINT1) {
+      SWAPIT(unsigned char, unsigned char, swap_nothing);
+    }
+    else {
+      fprintf(stderr,
+	      "***Fatal error in Byte_Swap[%s:%d]: Unsupported type; dtnum=0x%x for %s:%s@%s\n",
+	      __FILE__,__LINE__,dtnum,
+	      dtname,colname,tblname);
+      RAISE(SIGABRT);
+    }
+  }
+  return data;
+}
+
+#define CONVIT(type) \
+{ \
+  type *d; \
+  if (idx && idxlen > 0) { \
+    ALLOC(d,idxlen); \
+    if (const_value) { \
+      type c = *const_value; \
+      for (j=0; j<idxlen; j++) d[j] = c; \
+    } \
+    else { \
+      for (j=0; j<idxlen; j++) d[j] = data[idx[j]]; \
+    } \
+    nrows = idxlen; \
+  } \
+  else { \
+    if (const_value) { \
+      type c = *const_value; \
+      ALLOC(d,nrows); \
+      for (j=0; j<nrows; j++) d[j] = c; \
+    } \
+    else { \
+      if (!fill_zeroth_cma && \
+          (dtnum == DATATYPE_REAL8  || dtnum == DATATYPE_STRING)) { \
+        d = (type *)data; \
+      } \
+      else { \
+        ALLOC(d,nrows); \
+        for (j=0; j<nrows; j++) d[j] = data[j]; \
+      } \
+    } \
+  } \
+  out_ptr = d; \
+}
+
+PRIVATE void *
+Data_Conv(int fill_zeroth_cma,
+	  double *Data, 
+	  int nrows,
+	  uint dtnum,
+	  const double *const_value,
+	  const int idx[],
+	  int idxlen,
+	  const char *dtname,
+	  const char *colname,
+	  const char *tblname)
+{
+  void *out_ptr = NULL;
+  DRHOOK_START(Data_Conv);
+  if (nrows > 0) {
+    double *data = Data ? &Data[fill_zeroth_cma] : NULL;
+    int j;
+    if (dtnum == DATATYPE_REAL8) {
+      CONVIT(double);
+    }
+    else if (dtnum == DATATYPE_INT4) {
+      CONVIT(int);
+    }
+    else if (dtnum == DATATYPE_LINKOFFSET) {
+      CONVIT(linkoffset_t);
+    }
+    else if (dtnum == DATATYPE_LINKLEN) {
+      CONVIT(linklen_t);
+    }
+    else if (dtnum == DATATYPE_YYYYMMDD) {
+      CONVIT(int);
+    }
+    else if (dtnum == DATATYPE_HHMMSS) {
+      CONVIT(int);
+    }
+    else if (dtnum == DATATYPE_BITFIELD) {
+      CONVIT(int);
+    }
+    else if (dtnum == DATATYPE_STRING) {
+      CONVIT(string);
+    }
+    else if (dtnum == DATATYPE_BUFR) {
+      CONVIT(bufr);
+    }
+    else if (dtnum == DATATYPE_GRIB) {
+      CONVIT(grib);
+    }
+    else if (dtnum == DATATYPE_UINT4) {
+      CONVIT(unsigned int);
+    }
+    else if (dtnum == DATATYPE_REAL4) {
+      CONVIT(float);
+    }
+    else if (dtnum == DATATYPE_INT2) {
+      CONVIT(short int);
+    }
+    else if (dtnum == DATATYPE_UINT2) {
+      CONVIT(unsigned short int);
+    }
+    else if (dtnum == DATATYPE_INT1) {
+      CONVIT(char);
+    }
+    else if (dtnum == DATATYPE_UINT1) {
+      CONVIT(unsigned char);
+    }
+    else {
+      fprintf(stderr,
+	      "***Fatal error in Data_Conv[%s:%d]: Unsupported"
+	      " datatype; dtnum=0x%x for %s:%s@%s\n",
+	      __FILE__,__LINE__,dtnum,
+	      dtname,colname,tblname);
+      RAISE(SIGABRT);
+    }
+  }
+  DRHOOK_END(nrows);
+  return out_ptr;
+}
+
+
+PRIVATE int
+IsConst(const dca_t *pdca,
+	const dca_chain_t *pchain,
+	double *value)
+{
+  int rc = 0;
+  double Value = 0;
+  DRHOOK_START(IsConst);
+  if (pdca && pchain) {
+    if (pdca->nrows > 0) {
+      FILE *do_trace = ODB_trace_fp();
+      if (pdca->nrows == pdca->nmdis) { 
+	/* all values are (some sort of) missing data */
+	int basetype = EXTRACT_BASETYPE(pdca->dtnum);
+	if (basetype == 1) { /* an integer of some kind ==> NMDI */
+	  pcma_get_mdis_(&Value, NULL); /* NMDI */
+	  rc = 1;
+	  if (do_trace) DCA_Trace(-1,"IsConst: all NMDI",pdca,pchain,rc);
+	}
+	else if (basetype == 2) { /* a real of some kind ==> RMDI */
+	  pcma_get_mdis_(NULL, &Value); /* RMDI */
+	  rc = 2;
+	  if (do_trace) DCA_Trace(-1,"IsConst: all RMDI",pdca,pchain,rc);
+	}
+      }
+      else if (pdca->min == pdca->max && pdca->ncard == 1) { 
+	/* all values are the same */
+	Value = pdca->min;
+	rc = 3;
+	if (do_trace) DCA_Trace(-1,"IsConst: min == max and cardinality == 1",pdca,pchain,rc);
+      }
+    } /* if (pdca->nrows > 0) */
+  }
+  if (value) *value = Value;
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC void *
+DCA_fetch(int handle,
+	  const char *dbname,
+	  const char *tblname,
+	  const char *colname,
+	  int poolno,
+	  int unpack,
+	  const int idx[],
+	  int idxlen,
+	  int *nrows,
+	  int *nbytes,
+	  uint *datatype,
+	  int *offset)
+{
+  void *ptr = NULL;
+  int Nrows = 0;
+  int Nbytes = 0;
+  uint Datatype = 0;
+  int ioffset = 0;
+  DRHOOK_START(DCA_fetch);
+  if (!tblname && colname) tblname = strchr(colname, '@');
+  if (handle > 0 && dbname && tblname && colname) {
+    int it = get_thread_id_();
+    dca_chain_t *pchain = NULL;
+    char *p_colname = STRDUP(colname);
+    char *p_at = strchr(p_colname, '@');
+    char *poffset = GET_OFFSET(p_colname);
+    if (p_at) *p_at = '\0';
+    if (poffset) {
+      int sign = 1;
+      int inc = 0;
+      *poffset++ = '\0';
+      if (*poffset == '_' || *poffset == '-') { sign = -1; inc = 1; }
+      else if (*poffset == '+') { sign = 1; inc = 1; }
+      ioffset = sign * atoi(poffset+inc);
+    }
+    if (*tblname == '@') tblname++;
+    coml_set_lockid_(&DCA_mylock);
+    pchain = dca_chain;
+    while (pchain) {
+      if (pchain->handle == handle &&
+	  pchain->it == it &&
+	  strequ(pchain->dbname, dbname) &&
+	  strequ(pchain->tblname, tblname)) {
+	break;
+      }
+      pchain = pchain->next;
+    }
+    coml_unset_lockid_(&DCA_mylock);
+    if (pchain && 
+	poolno >= pchain->min_poolno && 
+	poolno <= pchain->max_poolno) { /* poolno range found */
+      uint hash = HashIs(p_colname);
+      if (pchain->dca && pchain->dcalen > 0 &&
+	  hash >= pchain->min_hash && hash <= pchain->max_hash) { /* even better! */
+	FILE *do_trace = ODB_trace_fp();
+	int errflg = 0;
+	dca_t *pdca = pchain->dca;
+	int j;
+	for (j=0; j<pchain->dcalen; j++) {
+	  if (pdca->poolno == poolno &&
+	      pdca->hash == hash &&
+	      strequ(pdca->colname, p_colname)) { /* ... and this is the exact match */
+	    double value = 0;
+	    int is_const = IsConst(pdca, pchain, &value);
+	    Nrows = pdca->nrows;
+	    Datatype = pdca->dtnum;
+	    if (is_const) {
+	      /* Constant data is found based on DCA-record */
+	      Nbytes = 0; /* indicates that no I/O was performed */
+	      ptr = Data_Conv(0,NULL,Nrows,pdca->dtnum,&value,idx,idxlen,
+			      pdca->dtname,pdca->colname,pchain->tblname);
+	      if (idx && idxlen > 0) Nrows = idxlen;
+	      if (DCA_DEBUG(0x2)) {
+		fprintf(stderr,
+			"IsConst[db=%s, var=%s:%s%s%s, pool#%d, value=%.14g, "
+			"nrows=%d, idx=%p, idxlen=%d] : ptr=%p (dtnum=0x%x)\n",
+			dbname,
+			pdca->dtname, pdca->colname,
+			(pchain && pchain->tblname) ? "@" : "",
+			(pchain && pchain->tblname) ? pchain->tblname : "",
+			pdca->poolno, value, pdca->nrows,
+			idx, idxlen,
+			ptr, pdca->dtnum);
+	      }
+	    }
+	    else {
+	      char *chptr = NULL;
+	      ALLOC(chptr,pdca->length);
+	      if (do_trace) DCA_Trace(1,"Fetch_Raw_Data",pdca,pchain,pdca->length);
+	      Nbytes = Fetch_Raw_Data(dbname,chptr,pdca,pchain);
+	      if (do_trace) DCA_Trace(0,"Fetch_Raw_Data",pdca,pchain,Nbytes);
+	      if (Nbytes != pdca->length) {
+		/* error */
+		Nbytes = -pdca->length;
+		FREE(chptr);
+		errflg = -1;
+		goto error_processing;
+	      }
+	      if (chptr && Nrows > 0) {
+		extern int ec_is_little_endian();
+		int i_am_little = ec_is_little_endian();
+		if (unpack) { /* unpack data into type-specific array */
+		  /* the "logic" borrowed from ../tools/dcagen.c */
+		  void *vptr = NULL;
+		  uint pmethod = pdca->pmethod_actual;
+		  uint dtnum = pdca->dtnum;
+		  uint word = pmethod + 256U * dtnum;
+		  int can_swp_data = EXTRACT_SWAPPABLE(word);
+		  int column_is_big_endian = (pdca->is_little == 0) ? 1 : 0;
+		  int column_is_little_endian = (pdca->is_little == 1) ? 1 : 0;
+		  int byteswap_needed = ((i_am_little && column_is_big_endian) || 
+					 (!i_am_little && column_is_little_endian));
+		  int swp = byteswap_needed;
+		  if (swp) swp = can_swp_data;
+		  if (pmethod == 0) { /* data is not packed */
+		    if (swp || (idx && idxlen > 0)) {
+		      if (do_trace) DCA_Trace(1,"Byte_Swap",pdca,pchain,idxlen);
+		      vptr = Byte_Swap(chptr,Nrows,dtnum,swp,idx,idxlen,
+				       pdca->dtname,pdca->colname,pchain->tblname);
+		      if (idx && idxlen > 0) {
+			Nrows = idxlen;
+			FREE(chptr);
+		      }
+		      if (do_trace) DCA_Trace(0,"Byte_Swap",pdca,pchain,swp);
+		    }
+		    else {
+		      vptr = chptr;
+		    }
+		  }
+		  else { /* data is indeed packed */
+		    int iret, packed_count;
+		    double *cma = NULL;
+		    int lencma = Nrows + 1;
+		    const int fill_zeroth_cma = 0;
+		    ALLOC(cma,lencma);
+		    if (do_trace) DCA_Trace(1,"pcma2cma_",pdca,pchain,lencma);
+		    {
+		      DRHOOK_START(DCA_fetch:pcma2cma_);
+		      coml_set_lockid_(&DCA_mylock);
+		      pcma2cma_(&can_swp_data,
+				(const unsigned int *)chptr,
+				&Nbytes,
+				idx, &idxlen, &fill_zeroth_cma,
+				cma,
+				&lencma,
+				&packed_count,
+				&iret);
+		      coml_unset_lockid_(&DCA_mylock);
+		      DRHOOK_END(Nbytes);
+		    }
+		    if (do_trace) DCA_Trace(0,"pcma2cma_",pdca,pchain,packed_count);
+		    FREE(chptr);
+		    if (iret < 0) {
+		      /* error */
+		      fprintf(stderr,
+			      "***Error: Cannot unpack column='%s%s%s' : iret=%d, errflg=%d\n",
+			      pdca->colname,
+			      pchain->tblname ? "@" : "",
+			      pchain->tblname ? pchain->tblname : "",
+			      iret, errflg);
+		      errflg = -2;
+		      FREE(cma);
+		      goto error_processing;
+		    }
+		    swp = 0; /* All byteswapping already done */
+		    if (DCA_DEBUG(0x32)) {
+		      int jj, jjmax = MIN(3,Nrows);
+		      fprintf(stderr,
+			      "Start of cma[] follows for %s:%s@%s at pool#%d "
+			      "(dtnum=0x%x): nrows=%d, lencma=%d\n\tcma[jj]/swap=",
+			      pdca->dtname,pdca->colname,pchain->tblname,pdca->poolno,
+			      pdca->dtnum,Nrows,lencma);
+		      for (jj=0; jj<=jjmax; jj++) {
+			const int one = 1;
+			double cmaswap = cma[jj];
+			swap8bytes_(&cmaswap, &one);
+			fprintf(stderr," [jj=%d:%.20g/%.20g]",jj,cma[jj],cmaswap);
+		      }
+		      fprintf(stderr,"\n");
+		    } /* if (DCA_DEBUG(0x32)) */
+		    if (do_trace) DCA_Trace(1,"Data_Conv",pdca,pchain,idxlen);
+		    vptr = Data_Conv(fill_zeroth_cma,cma,Nrows,dtnum,NULL,idx,idxlen,
+				     pdca->dtname,pdca->colname,pchain->tblname);
+		    if (idx && idxlen > 0) Nrows = idxlen;
+		    if (do_trace) DCA_Trace(0,"Data_Conv",pdca,pchain,can_swp_data);
+		    if (DCA_DEBUG(0x32)) {
+		      if (pdca->dtnum == DATATYPE_REAL8) {
+			double *dptr = vptr;
+			int jj, jjmax = MIN(3,Nrows);
+			fprintf(stderr,
+				"Start of vptr[]@%p (cma@%p) follows for %s:%s@%s at pool#%d "
+				"(REAL8:dtnum=0x%x): nrows=%d, idxlen=%d\n\tvptr[jj]/swap=",
+				vptr, cma,
+				pdca->dtname,pdca->colname,pchain->tblname,pdca->poolno,
+				pdca->dtnum,Nrows,idxlen);
+			for (jj=0; jj<jjmax; jj++) {
+			  const int one = 1;
+			  double dswap = dptr[jj];
+			  swap8bytes_(&dswap, &one);
+			  fprintf(stderr," [jj=%d:%.20g/%.20g]",jj,dptr[jj],dswap);
+			}
+			fprintf(stderr,"\n");
+		      }
+		      else if (pdca->dtnum == DATATYPE_INT4) {
+			int *dptr = vptr;
+			int jj, jjmax = MIN(3,Nrows);
+			fprintf(stderr,
+				"Start of vptr[]@%p (cma@%p) follows for %s:%s@%s at pool#%d "
+				"(INT4:dtnum=0x%x): nrows=%d, idxlen=%d\n\tvptr[jj]/swap=",
+				vptr, cma,
+				pdca->dtname,pdca->colname,pchain->tblname,pdca->poolno,
+				pdca->dtnum,Nrows,idxlen);
+			for (jj=0; jj<jjmax; jj++) {
+			  const int one = 1;
+			  int dswap = dptr[jj];
+			  swap4bytes_(&dswap, &one);
+			  fprintf(stderr," [jj=%d:%d/%d]",jj,dptr[jj],dswap);
+			}
+			fprintf(stderr,"\n");
+		      }
+		    } /* if (DCA_DEBUG(0x32)) */
+		    if (cma != vptr) FREE(cma);
+		  }
+		  ptr = vptr;
+		}
+		else {
+		  ptr = chptr;
+		}
+	      }
+	      else {
+		ptr = chptr;
+	      } /* if (chptr && Nrows > 0) ... else ... */
+	    }
+	    break; /* for (j=0; j<pchain->dcalen; j++) */
+	  } /* if (pdca->poolno == poolno && ... */
+	  pdca++;
+	} /* for (j=0; j<pchain->dcalen; j++) */
+      error_processing:
+	if (errflg) {
+	  fprintf(stderr,"***Error in DCA_fetch: errflg = %d\n",errflg);
+	  RAISE(SIGABRT);
+	}
+      } /* if (pchain->dca && pchain->dcalen > 0) */
+    } /* if (pchain) */
+    FREE(p_colname);
+  } /* if (handle > 0 && dbname && tblname && colname) */
+  if (nrows)  *nrows  = Nrows;
+  if (nbytes) *nbytes = Nbytes;
+  if (datatype) *datatype = Datatype;
+  if (offset) *offset = ioffset;
+  DRHOOK_END(Nbytes);
+  return ptr;
+}
+
+
+PUBLIC double *
+DCA_fetch_double(int handle,
+		 const char *dbname,
+		 const char *tblname,
+		 const char *colname,
+		 int poolno,
+		 const int idx[],
+		 int idxlen,
+		 int *nrows)
+{
+  double *d = NULL;
+  int Nrows = 0;
+  DRHOOK_START(DCA_fetch_double);
+  {
+    const int unpack = 1;
+    uint datatype = 0;
+    int ioffset = 0;
+    void *ptr = DCA_fetch(handle,
+			  dbname,
+			  tblname,
+			  colname,
+			  poolno,
+			  unpack,
+			  idx,
+			  idxlen,
+			  &Nrows,
+			  NULL,
+			  &datatype,
+			  &ioffset);
+    if (ptr && Nrows > 0) {
+      const int flag = 1; /* i.e. FLAG_FETCH(flag) will be true */
+      const int row_offset = 0; /* Not parameterized -- not at least for now */
+      ALLOC(d, Nrows);
+      /* Convert "any" datatype to real*8 i.e. double */
+      Nrows = ODBCopyGetTable(flag, Nrows, d, ptr, datatype, row_offset);
+      FREE(ptr);
+      if (ioffset != 0) {
+	/* Need to "shift" data to left (ioffset < 0) or right (ioffset > 0)
+	   by ioffset positions. Underflow/overflow areas omitted
+	   and areas not filled, are set to "mdi" */
+	const double mdi = ABS(RMDI);
+	int j;
+	double *dcopy = NULL;
+	ALLOC(dcopy, Nrows);
+	if (ABS(ioffset) < Nrows) {
+	  /* Underflow/overflow less than Nrows */
+	  int len = Nrows - ABS(ioffset);
+	  if (ioffset > 0) {
+	    for (j=0; j<len; j++) dcopy[j] = d[j+ioffset];
+	    for (j=len; j<Nrows; j++) dcopy[j] = mdi;
+	  }
+	  else { /* ioffset < 0 */
+	    ioffset = -ioffset;
+	    for (j=0; j<len; j++) dcopy[j+ioffset] = d[j];
+	    for (j=0; j<ioffset; j++) dcopy[j] = mdi;
+	  }
+	}
+	else {
+	  for (j=0; j<Nrows; j++) dcopy[j] = mdi;
+	}
+	FREE(d);
+	d = dcopy;
+      } /* if (ioffset != 0) */
+    }
+    else {
+      Nrows = 0;
+    }
+  }
+  if (nrows) *nrows = Nrows;
+  DRHOOK_END(Nrows);
+  return d;
+}
+
+
+PUBLIC int *
+DCA_fetch_int(int handle,
+	      const char *dbname,
+	      const char *tblname,
+	      const char *colname,
+	      int poolno,
+	      const int idx[],
+	      int idxlen,
+	      int *nrows)
+{
+  int *i = NULL;
+  int Nrows = 0;
+  DRHOOK_START(DCA_fetch_int);
+  {
+    double *d = DCA_fetch_double(handle,
+				 dbname,
+				 tblname,
+				 colname,
+				 poolno,
+				 idx,
+				 idxlen,
+				 &Nrows);
+    if (Nrows > 0) {
+      int j;
+      ALLOC(i, Nrows);
+      /* No flp. or integer overflow checking below ;-( */
+      for (j=0; j<Nrows; j++) i[j] = (int)d[j];
+    }
+    if (nrows) *nrows = Nrows;
+    FREE(d);
+  }
+  DRHOOK_END(Nrows);
+  return i;
+}
+
+
+PUBLIC void
+DCA_debugprt(FILE *fp,
+	     int handle,
+	     const char *dbname,
+	     const char *tblname,
+	     const char *colname,
+	     int poolno)
+{
+  if (fp && handle > 0 && dbname && tblname) {
+    int it = get_thread_id_();
+    dca_chain_t *pchain = NULL;
+    if (*tblname == '@') tblname++;
+    coml_set_lockid_(&DCA_mylock);
+    pchain = dca_chain;
+    while (pchain) {
+      if (pchain->handle == handle &&
+	  pchain->it == it &&
+	  strequ(pchain->dbname, dbname) &&
+	  strequ(pchain->tblname, tblname)) {
+	break;
+      }
+      pchain = pchain->next;
+    }
+    coml_unset_lockid_(&DCA_mylock);
+    if (pchain) { /* found it !! */
+      int j;
+      dca_t *pdca = pchain->dca;
+      fprintf(fp,
+	      "DCA_debugprt(handle=%d, dbname=%s, tblname=%s, poolno=%d, colname=%s)\n",
+	      handle, dbname, tblname, poolno, colname ? colname : "<any>");
+      for (j=0; j<pchain->dcalen; j++) {
+	if ((poolno == -1 || pdca->poolno == poolno) &&
+	    (!colname || strequ(pdca->colname,colname))) {
+	  fprintf(fp,
+		  "col#%d, hash=%u, name='%s', type='%s', typenum=(0x%x;%u), file='%s', pool#%d\n",
+		  pdca->colnum, pdca->hash, pdca->colname, pdca->dtname, pdca->dtnum, pdca->dtnum,
+		  pdca->filename, pdca->poolno);
+	  fprintf(fp,
+		  "\t(offset,length)=(%llu,%d), pmethods=(%d,%d), nrows=%d, nMDIs=%d\n",
+		  pdca->offset, pdca->length,
+		  pdca->pmethod, pdca->pmethod_actual,
+		  pdca->nrows, pdca->nmdis);
+	  fprintf(fp,
+		  "\t(avg,min,max,card)=(%.14g,%.14g,%.14g,%d), is little-endian ? %s\n",
+		  pdca->avg, pdca->min, pdca->max, pdca->ncard, 
+		  pdca->is_little ? "yes" : "no");
+	}
+	pdca++;
+      } /* for (j=0; j<pchain->dcalen; j++) */
+    } /* if (pchain) */
+  }
+}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+PUBLIC void
+codb_detect_dcadir_(const char *dbname, 
+		    int *io_method_env
+		    /* Hidden arguments */
+		    , int dbname_len)
+{
+  int iom = *io_method_env;
+  if (iom > 0) {
+    /* by setting ODB_IO_METHOD (or ODB_IO_METHOD_<dbname>) <= 0
+       you avoid using dcadir-check altogether */
+    const char base[] = "ODB_SRCPATH";
+    int i, baselen = strlen(base);
+    int found = 0;
+    DECL_FTN_CHAR(dbname);
+    ALLOC_FTN_CHAR(dbname);
+    
+    for (i=1; i<=3 && !found; i++) {
+      int len;
+      char *env, *path;
+
+      if (i == 1) {
+	/* (1) Try with "$ODB_SRCPATH_<dbname>/dca" */
+	len = baselen + 1 + strlen(p_dbname) + 1;
+	ALLOC(env,len);
+	snprintf(env,len,"%s_%s",base,p_dbname);
+	path = getenv(env);
+	FREE(env); 
+      }
+      else if (i == 2) {
+	/* (2) Try with "$ODB_SRCPATH/dca" */
+	path = getenv(base);
+      }
+      else if (i == 3) {
+	/* (3) Try with "./dca" */
+	path = ".";
+      }
+
+      if (path) {
+	struct stat buf;
+	char *dcadir;
+	len = strlen(path) + 4 + 1;
+	ALLOC(dcadir, len);
+	snprintf(dcadir,len,"%s/dca",path);
+	/*
+	fprintf(stderr,
+		"codb_detect_dcadir_(%s,%d): Checking dcadir='%s'\n",
+		p_dbname, *io_method_env, dcadir);
+	*/
+	if (stat(dcadir,&buf) == 0 && S_ISDIR(buf.st_mode)) {
+	  /* Matched !!
+	     We have a reason to believe that the
+	     I/O-method = 5 can be used ;
+	     In doubt --> set I/O-method for this database to 0 !! */
+	  iom = 5;
+	  found = 1;
+	}
+	FREE(dcadir);
+      }
+
+    } /* for (i=1; i<=3 && !found; i++) */
+
+    if (iom == 5 && !found) iom = -5; /* Using I/O-method#5 in this case would be wrong */
+    *io_method_env = iom;
+
+    /*
+    fprintf(stderr,
+	    "codb_detect_dcadir_(%s,%d) finished.\n",
+	    p_dbname, *io_method_env);
+    */
+
+    FREE_FTN_CHAR(dbname);
+  }
+}
diff --git a/odb/src/aux/ds.c b/odb/src/aux/ds.c
new file mode 100644
index 0000000..ce59de2
--- /dev/null
+++ b/odb/src/aux/ds.c
@@ -0,0 +1,489 @@
+
+/* ds.c */
+
+#include "odb.h"
+#include "odb_macros.h"
+#include "cdrhook.h"
+
+DefineDS(void);
+
+PUBLIC int
+Read_DS(void *Pvar,
+	int Handle, int PoolNo, int Nrows, int Byteswap, int IO_method,
+	const char *Dbase, int fp_idx, const char *filename,
+	uint datatype)
+{
+  int Nbytes = 0;
+  uint N[2];
+  DeclareDS(void, *Var);
+  int packing_method;
+  int savelist;
+  DRHOOK_START(Read_DS);
+
+  Var = Pvar;
+  packing_method = Var->pmethod_from_datatype; /* Remember the preset value */
+  Var->pmethod = (ODB_packing(NULL) == 0) ? 0 : ODB_packing(&packing_method);
+  savelist = Var->savelist; /* Remember the preset value */
+  FREE_alldata(*Var);
+  Var->savelist = savelist; /* Restore the preset value */
+
+  if (Nrows > 0) { /* Read nothing unless Nrows > 0 */
+    uint dt;
+    const int two = 2;
+    Nbytes += newio_Read32(&fp_idx, filename, "No of bytes & Pmethod",
+                           Var->name, Handle, PoolNo,
+			   N, sizeof(*N), two);
+    if (Byteswap) swap4bytes_(N, &two);
+    dt = EXTRACT_DATATYPE(N[1]);
+    /* if (dt > 0) datatype = dt; */
+    N[1] = EXTRACT_PMETHOD(N[1]);
+  }
+  else { /* No data */
+    N[0] = 0; 
+    N[1] = Var->pmethod_from_datatype;
+  }
+
+  Var->datatype = datatype;
+
+  if (Var->savelist == 0) {
+    Var->saved_data_N[0] = N[0];
+    Var->saved_data_N[1] = N[1];
+  }
+
+  if (N[0] > 0 && N[1] > 0) { /* Packed data, that is greater than zero-length */
+    int nw = N[0]/sizeof(*Var->pd);
+    ALLOC(Var->pd, nw);
+    Var->pdlen = nw;
+    Nbytes += newio_Read32(&fp_idx, filename, "Packed data",
+                           Var->name, Handle, PoolNo,
+			   Var->pd, sizeof(*Var->pd), Var->pdlen);
+    if (Var->savelist == 0) {
+      /* Create a backup for ODB_SAVELIST-purposes (keep packed; retain byte swapping in packed data) */
+      char *bck;
+      int bcklen = sizeof(*Var->pd) * Var->pdlen;
+      ALLOC(bck,bcklen);
+      memcpy(bck, Var->pd, bcklen);
+      if (Var->saved_data) FREE(Var->saved_data);
+      Var->saved_data = bck;
+      Var->saved_data_nbytes = bcklen;
+    }
+    Var->is_packed = 1;
+  }
+  else { /* Data is in unpacked form */
+    int nw = N[0]/Var->elemsize;
+    ALLOC3(Var->d, nw, Var->elemsize);
+    Var->nalloc = Var->dlen = nw;
+    Nbytes += newio_Read32(&fp_idx, filename, "Unpacked data",
+                           Var->name, Handle, PoolNo,
+			   Var->d, Var->elemsize, Var->dlen);
+    if (Byteswap) {
+      swapANYbytes(Var->d, Var->elemsize, Var->dlen,
+                   Var->datatype, Var->type, Var->name);
+    }
+    if (Var->savelist == 0) {
+      /* Create a backup for ODB_SAVELIST-purposes (keep unpacked & *with* byte swapping)*/
+      char *bck;
+      int bcklen = Var->elemsize * Var->dlen;
+      ALLOC(bck,bcklen);
+      memcpy(bck, Var->d, bcklen); /* now byte swapped (if applicable) */
+      if (Var->saved_data) FREE(Var->saved_data);
+      Var->saved_data = bck;
+      Var->saved_data_nbytes = bcklen;
+    }
+    Var->is_packed = 0;
+  }
+
+  DRHOOK_END(Nbytes);
+  return Nbytes;
+}
+
+PUBLIC int
+Write_DS(void *Pvar,
+	 int Handle, int PoolNo, int Nrows, int Byteswap, int IO_method,
+	 const char *Dbase, int fp_idx, const char *filename,
+	 uint datatype,
+	 Packed_DS *(*DoPackDS)(void *))
+{
+  int Nbytes = 0;
+  DRHOOK_START(Write_DS);
+
+  if (Nrows > 0) { /* Write nothing unless Nrows > 0 */
+    Packed_DS *Packed = NULL;
+    int pmethod = 0;
+    uint N[2];
+    DeclareDS(void, *Var);
+    int packing_method;
+    
+    Var = Pvar;
+    packing_method = Var->pmethod_from_datatype; /* Remember the preset value */
+    
+    Var->pmethod = (ODB_packing(NULL) == 0) ? 0 : ODB_packing(&packing_method);
+    /* Packed = PackDS(P, Dbase, Type, Var); */
+    Packed = ( (IO_method == 5 && !Var->d && !Var->pd) ?
+	       Var->d = DCA_fetch(Handle, Dbase, Var->table, Var->name, PoolNo, 1,
+				  NULL, 0, &Var->dlen, NULL, NULL, NULL) : NULL,
+	       DoPackDS(Var) );
+    FREE(Packed);
+
+    if (Var->savelist == 0) {
+      N[0] = Var->saved_data_N[0];
+      N[1] = Var->saved_data_N[1];
+    }
+    else {
+      N[0] = (Var->is_packed) ? BYTESIZE(Var->pd) : BYTESIZE2(Var->d,Var->elemsize);
+      N[1] = (Var->is_packed) ? Var->pmethod : 0;
+      pmethod = N[1];
+      Var->datatype = datatype;
+      N[1] |= (datatype << 8);
+    }
+
+    /*
+    fprintf(stderr,
+	    "Write_DS(%s@%s): PoolNo=%d, savelist=%d, N[0:1]=(%d:%d)\n",
+	    Var->name, Var->table, PoolNo, Var->savelist, N[0], N[1]);
+    */
+    
+    Nbytes += newio_Write32(&fp_idx, filename, "No of bytes & Pmethod",
+			    Var->name, Handle, PoolNo,
+			    N, sizeof(*N), 2);
+
+    if (Var->savelist == 0) {
+      Nbytes += newio_Write32(&fp_idx, filename, "Data from savelist-backup",
+			      Var->name, Handle, PoolNo,
+			      Var->saved_data, 1, Var->saved_data_nbytes);
+    }
+    else {
+      if (pmethod > 0) {
+	Nbytes += newio_Write32(&fp_idx, filename, "Packed data",
+				Var->name, Handle, PoolNo,
+				Var->pd, sizeof(*Var->pd), Var->pdlen);
+      }
+      else {
+	Nbytes += newio_Write32(&fp_idx, filename, "Unpacked data",
+				Var->name, Handle, PoolNo,
+				Var->d, Var->elemsize, Var->dlen);
+      }
+    }
+  }
+
+  DRHOOK_END(Nbytes);
+  return Nbytes;
+}
+
+
+PUBLIC int
+ODBSQL_PrintGet(const char *Sql[],
+		FILE *fp, int mode, const char *prefix, const char *postfix, char **sqlout)
+{
+  int rc = 0;
+  if (Sql && fp) {
+    int j=0;
+    const char *s;
+    while ((s = Sql[j]) != NULL) {
+      fprintf(fp,"%s%s%s",
+          prefix ? prefix : "", s,
+          postfix ? postfix : "\n"); j++;
+    } /* while ... */
+    rc = j;
+  }
+  if (sqlout) *sqlout = NULL; /* Not implemented */
+  return rc;
+}
+
+#define THEGETLOOP(Type) \
+  { const Type *pVar = Var; for (k=0; k<Count; k++) D[k] = pVar[k+row_offset]; rc = Count; } break
+
+PUBLIC int
+ODBCopyGetTable(int Flag, int Count, double D[], const void *Var, uint datatype, int row_offset)
+{ 
+  int rc = 0;
+  if (FLAG_FETCH(Flag)) {
+    int k;
+    DRHOOK_START(ODBCopyGetTable);
+    switch (datatype) {
+      /* Most common */
+    case DATATYPE_REAL8 : THEGETLOOP(double);
+    case DATATYPE_INT4 : THEGETLOOP(int);
+    case DATATYPE_BITFIELD : THEGETLOOP(Bitfield);
+    case DATATYPE_STRING : THEGETLOOP(string);
+    case DATATYPE_YYYYMMDD : THEGETLOOP(yyyymmdd);
+    case DATATYPE_HHMMSS : THEGETLOOP(hhmmss);
+    case DATATYPE_LINKOFFSET : THEGETLOOP(linkoffset_t);
+    case DATATYPE_LINKLEN : THEGETLOOP(linklen_t);
+    case DATATYPE_BUFR : THEGETLOOP(bufr);
+      /* Less common */
+    case DATATYPE_INT1 : THEGETLOOP(char);
+    case DATATYPE_INT2 : THEGETLOOP(short);
+    case DATATYPE_INT8 : THEGETLOOP(longlong);
+    case DATATYPE_UINT1 : THEGETLOOP(uchar);
+    case DATATYPE_UINT2 : THEGETLOOP(ushort);
+    case DATATYPE_UINT4 : THEGETLOOP(uint);
+    case DATATYPE_UINT8 : THEGETLOOP(ulonglong);
+    case DATATYPE_REAL4 : THEGETLOOP(float);
+    case DATATYPE_GRIB : THEGETLOOP(grib);
+      /* Unsupported */
+    default:
+      fprintf(stderr,"***Error in CopyGetTable(): Unsupported datatype"
+	      " 0x%x (see odb/include/privpub.h)\n",datatype);
+      RAISE(SIGABRT);
+      rc = -1;
+      break;
+    } /* switch (datatype) */
+    DRHOOK_END(Count);
+  }
+  return rc;
+}
+
+#define THEPUTLOOP(Type) \
+  { Type *pVar = Var; for (k=0; k<Count; k++) pVar[k] = D[k]; rc = Count; } break
+
+PUBLIC int
+ODBCopyPutTable(int Flag, int Count, void *Var, const double D[], uint datatype)
+{ 
+  int rc = 0;
+  if (FLAG_UPDATE(Flag)) {
+    int k;
+    DRHOOK_START(ODBCopyPutTable);
+    switch (datatype) {
+      /* Most common */
+    case DATATYPE_REAL8 : THEPUTLOOP(double);
+    case DATATYPE_INT4 : THEPUTLOOP(int);
+    case DATATYPE_BITFIELD : THEPUTLOOP(Bitfield);
+    case DATATYPE_STRING : THEPUTLOOP(string);
+    case DATATYPE_YYYYMMDD : THEPUTLOOP(yyyymmdd);
+    case DATATYPE_HHMMSS : THEPUTLOOP(hhmmss);
+    case DATATYPE_LINKOFFSET : THEPUTLOOP(linkoffset_t);
+    case DATATYPE_LINKLEN : THEPUTLOOP(linklen_t);
+    case DATATYPE_BUFR : THEPUTLOOP(bufr);
+      /* Less common */
+    case DATATYPE_INT1 : THEPUTLOOP(char);
+    case DATATYPE_INT2 : THEPUTLOOP(short);
+    case DATATYPE_INT8 : THEPUTLOOP(longlong);
+    case DATATYPE_UINT1 : THEPUTLOOP(uchar);
+    case DATATYPE_UINT2 : THEPUTLOOP(ushort);
+    case DATATYPE_UINT4 : THEPUTLOOP(uint);
+    case DATATYPE_UINT8 : THEPUTLOOP(ulonglong);
+    case DATATYPE_REAL4 : THEPUTLOOP(float);
+    case DATATYPE_GRIB : THEPUTLOOP(grib);
+      /* Unsupported */
+    default:
+      fprintf(stderr,
+	      "***Error in CopyPutTable(): Unsupported datatype"
+	      " 0x%x (see odb/include/privpub.h)\n",datatype);
+      RAISE(SIGABRT);
+      rc = -1;
+      break;
+    } /* switch (datatype) */
+    DRHOOK_END(Count);
+  }
+  return rc;
+}
+
+
+/* GatherGet */
+
+#ifdef MASK
+#undef MASK
+#endif
+
+static const unsigned int 
+mask[1+32] = {
+          0U,  /*                                 0 */
+          1U,  /*                                 1 */
+          3U,  /*                                11 */
+          7U,  /*                               111 */
+         15U,  /*                              1111 */
+         31U,  /*                             11111 */
+         63U,  /*                            111111 */
+        127U,  /*                           1111111 */
+        255U,  /*                          11111111 */
+        511U,  /*                         111111111 */
+       1023U,  /*                        1111111111 */
+       2047U,  /*                       11111111111 */
+       4095U,  /*                      111111111111 */
+       8191U,  /*                     1111111111111 */
+      16383U,  /*                    11111111111111 */
+      32767U,  /*                   111111111111111 */
+      65535U,  /*                  1111111111111111 */
+     131071U,  /*                 11111111111111111 */
+     262143U,  /*                111111111111111111 */
+     524287U,  /*               1111111111111111111 */
+    1048575U,  /*              11111111111111111111 */
+    2097151U,  /*             111111111111111111111 */
+    4194303U,  /*            1111111111111111111111 */
+    8388607U,  /*           11111111111111111111111 */
+   16777215U,  /*          111111111111111111111111 */
+   33554431U,  /*         1111111111111111111111111 */
+   67108863U,  /*        11111111111111111111111111 */
+  134217727U,  /*       111111111111111111111111111 */
+  268435455U,  /*      1111111111111111111111111111 */
+  536870911U,  /*     11111111111111111111111111111 */
+ 1073741823U,  /*    111111111111111111111111111111 */
+ 2147483647U,  /*   1111111111111111111111111111111 */
+ 4294967295U   /*  11111111111111111111111111111111 */
+};
+
+#define MASK(n) mask[n]
+
+#define THEGATHERGETLOOP(Type) \
+{ \
+  const Type *pVar = Var; \
+  if (Index) { for (k=k1; k<k2; k++) d[k-k1] = pVar[Index[k+row_offset]]; } \
+  else       { for (k=k1; k<k2; k++) d[k-k1] = pVar[k-k1+row_offset]; } \
+} break
+
+PRIVATE void /* Note: a PRIVATE-routine; called only via ODBGatherGetBits() */
+GatherGet(int k1, int k2, const int *Index, double d[], const void *Var, uint datatype, 
+	  int row_offset)
+{
+  int k;
+  DRHOOK_START(GatherGet);
+  switch (datatype) {
+    /* Most common */
+  case DATATYPE_REAL8 : THEGATHERGETLOOP(double);
+  case DATATYPE_INT4 : THEGATHERGETLOOP(int);
+  case DATATYPE_BITFIELD : THEGATHERGETLOOP(Bitfield);
+  case DATATYPE_STRING : THEGATHERGETLOOP(string);
+  case DATATYPE_YYYYMMDD : THEGATHERGETLOOP(yyyymmdd);
+  case DATATYPE_HHMMSS : THEGATHERGETLOOP(hhmmss);
+  case DATATYPE_LINKOFFSET : THEGATHERGETLOOP(linkoffset_t);
+  case DATATYPE_LINKLEN : THEGATHERGETLOOP(linklen_t);
+  case DATATYPE_BUFR : THEGATHERGETLOOP(bufr);
+    /* Less common */
+  case DATATYPE_INT1 : THEGATHERGETLOOP(char);
+  case DATATYPE_INT2 : THEGATHERGETLOOP(short);
+  case DATATYPE_INT8 : THEGATHERGETLOOP(longlong);
+  case DATATYPE_UINT1 : THEGATHERGETLOOP(uchar);
+  case DATATYPE_UINT2 : THEGATHERGETLOOP(ushort);
+  case DATATYPE_UINT4 : THEGATHERGETLOOP(uint);
+  case DATATYPE_UINT8 : THEGATHERGETLOOP(ulonglong);
+  case DATATYPE_REAL4 : THEGATHERGETLOOP(float);
+  case DATATYPE_GRIB : THEGATHERGETLOOP(grib);
+    /* Unsupported */
+  default:
+    fprintf(stderr,
+	    "***Error in GatherGet(): Unsupported datatype"
+	    " 0x%x (see odb/include/privpub.h)\n",datatype);
+    RAISE(SIGABRT);
+    break;
+  } /* switch (datatype) */
+  DRHOOK_END(k2-k1);
+}
+
+
+#define THEGATHERGETBITSLOOP(Type) \
+{ \
+  const Type *pVar = Var; \
+  if (Index) { for (k=k1; k<k2; k++) d[k-k1] = GET_BITS(pVar[Index[k+row_offset]], pos, len); } \
+  else       { for (k=k1; k<k2; k++) d[k-k1] = GET_BITS(pVar[k-k1+row_offset], pos, len); } \
+} break
+
+PUBLIC void
+ODBGatherGetBits(int k1, int k2, const int *Index, double d[], const void *Var, uint datatype,
+		 int pos, int len, int row_offset)
+{
+  int k;
+  if (len <= 0) {
+    GatherGet(k1, k2, Index, d, Var, datatype, row_offset);
+    return;
+  }
+  else {
+    DRHOOK_START(ODBGatherGetBits);
+    switch (datatype) {
+      /* The only applicable */
+    case DATATYPE_BITFIELD : THEGATHERGETBITSLOOP(Bitfield);
+      /* Unsupported */
+    default:
+      fprintf(stderr,
+	      "***Error in ODBGatherGetBits(): Unsupported datatype 0x%x"
+	      " (see odb/include/privpub.h)\n",datatype);
+      RAISE(SIGABRT);
+      break;
+    } /* switch (datatype) */
+    DRHOOK_END(k2-k1);
+  }
+}
+
+
+/* ScatterPut */
+
+
+#define THESCATTERPUTLOOP(Type) \
+{ \
+  Type *pVar = Var; \
+  for (k=k1; k<k2; k++) pVar[Index[k]] = d[k-k1]; \
+} break
+
+PRIVATE void /* Note: a PRIVATE-routine; called only via ODBScatterPutBits() */
+ScatterPut(int k1, int k2, const int *Index, void *Var, const double d[], uint datatype)
+{
+  int k;
+  DRHOOK_START(ScatterPut);
+  switch (datatype) {
+    /* Most common */
+  case DATATYPE_REAL8 : THESCATTERPUTLOOP(double);
+  case DATATYPE_INT4 : THESCATTERPUTLOOP(int);
+  case DATATYPE_BITFIELD : THESCATTERPUTLOOP(Bitfield);
+  case DATATYPE_STRING : THESCATTERPUTLOOP(string);
+  case DATATYPE_YYYYMMDD : THESCATTERPUTLOOP(yyyymmdd);
+  case DATATYPE_HHMMSS : THESCATTERPUTLOOP(hhmmss);
+  case DATATYPE_LINKOFFSET : THESCATTERPUTLOOP(linkoffset_t);
+  case DATATYPE_LINKLEN : THESCATTERPUTLOOP(linklen_t);
+  case DATATYPE_BUFR : THESCATTERPUTLOOP(bufr);
+    /* Less common */
+  case DATATYPE_INT1 : THESCATTERPUTLOOP(char);
+  case DATATYPE_INT2 : THESCATTERPUTLOOP(short);
+  case DATATYPE_INT8 : THESCATTERPUTLOOP(longlong);
+  case DATATYPE_UINT1 : THESCATTERPUTLOOP(uchar);
+  case DATATYPE_UINT2 : THESCATTERPUTLOOP(ushort);
+  case DATATYPE_UINT4 : THESCATTERPUTLOOP(uint);
+  case DATATYPE_UINT8 : THESCATTERPUTLOOP(ulonglong);
+  case DATATYPE_REAL4 : THESCATTERPUTLOOP(float);
+  case DATATYPE_GRIB : THESCATTERPUTLOOP(grib);
+    /* Unsupported */
+  default:
+    fprintf(stderr,
+	    "***Error in ScatterPut(): Unsupported datatype"
+	    " 0x%x (see odb/include/privpub.h)\n",datatype);
+    RAISE(SIGABRT);
+    break;
+  } /* switch (datatype) */
+  DRHOOK_END(k2-k1);
+}
+
+
+#define THESCATTERPUTBITSLOOP(Type) \
+{ \
+  Type *pVar = Var; \
+  for (k=k1; k<k2; k++) PUT_BITS(pVar[Index[k]], d[k-k1], pos, len); \
+} break
+
+PUBLIC void
+ODBScatterPutBits(int k1, int k2, const int *Index, void *Var, const double d[], uint datatype,
+		 int pos, int len)
+{
+  int k;
+  if (!Index) {
+    /* Not applicable */
+    return;
+  }
+  else if (len <= 0) {
+    ScatterPut(k1, k2, Index, Var, d, datatype);
+    return;
+  }
+  else {
+    DRHOOK_START(ODBScatterPutBits);
+    switch (datatype) {
+      /* The only applicable */
+    case DATATYPE_BITFIELD : THESCATTERPUTBITSLOOP(Bitfield);
+      /* Unsupported */
+    default:
+      fprintf(stderr,
+	      "***Error in ODBScatterPutBits(): Unsupported datatype"
+	      " 0x%x (see odb/include/privpub.h)\n",datatype);
+      RAISE(SIGABRT);
+      break;
+    } /* switch (datatype) */
+    DRHOOK_END(k2-k1);
+  }
+}
diff --git a/odb/src/aux/dtnum.c b/odb/src/aux/dtnum.c
new file mode 100644
index 0000000..f0eafc8
--- /dev/null
+++ b/odb/src/aux/dtnum.c
@@ -0,0 +1,100 @@
+#include "alloc.h"
+
+#include "codb_netcdf.h"
+
+#ifdef HAS_NETCDF /* NETCDF is available */
+#include "netcdf.h"
+#endif
+
+void
+dtnum_to_netcdf_type_(const uint *Dtnum, int *retcode)
+{
+  int rc = -1;
+#ifdef HAS_NETCDF /* NETCDF is available */
+  if (Dtnum && retcode) {
+    uint dtnum = *Dtnum;
+    if      (dtnum == DATATYPE_REAL8)      rc = NC_DOUBLE;
+    else if (dtnum == DATATYPE_INT4)       rc = NC_INT;
+    else if (dtnum == DATATYPE_STRING)     rc = NC_CHAR;
+    else if (dtnum == DATATYPE_YYYYMMDD)   rc = NC_INT;
+    else if (dtnum == DATATYPE_HHMMSS)     rc = NC_INT;
+    else if (dtnum == DATATYPE_BITFIELD)   rc = NC_INT;
+    else if (dtnum == DATATYPE_LINKOFFSET) rc = NC_INT;
+    else if (dtnum == DATATYPE_LINKLEN)    rc = NC_INT;
+    else if (dtnum == DATATYPE_BUFR)       rc = NC_INT;
+    else if (dtnum == DATATYPE_GRIB)       rc = NC_INT;
+    else if (dtnum == DATATYPE_INT1)       rc = NC_BYTE;
+    else if (dtnum == DATATYPE_INT2)       rc = NC_SHORT;
+    else if (dtnum == DATATYPE_REAL4)      rc = NC_FLOAT;
+    else if (dtnum == DATATYPE_UINT1)      rc = NC_BYTE;
+    else if (dtnum == DATATYPE_UINT2)      rc = NC_SHORT;
+    else if (dtnum == DATATYPE_UINT4)      rc = NC_INT;
+    else rc = NC_EBADTYPE;
+  }
+#endif
+  if (retcode) *retcode = rc;
+}
+
+uint
+get_dtnum(const char *dt)
+{
+  if (dt) {
+    int len = strlen(dt);
+    if (len >= 6 && strnequ(dt,"pk",2) && strstr(dt,"int")) return DATATYPE_INT4;
+    else if (len >= 7 && strnequ(dt,"pk",2) && strstr(dt,"real")) return DATATYPE_REAL8;
+    else if (strequ(dt,"Formula")) return DATATYPE_REAL8;
+    else if (strequ(dt,"yyyymmdd")) return DATATYPE_YYYYMMDD;
+    else if (strequ(dt,"hhmmss")) return DATATYPE_HHMMSS;
+    else if (strequ(dt,"Bitfield")) return DATATYPE_BITFIELD;
+    else if (strequ(dt,"linkoffset_t")) return DATATYPE_LINKOFFSET;
+    else if (strequ(dt,"linklen_t")) return DATATYPE_LINKLEN;
+    else if (strequ(dt,"string")) return DATATYPE_STRING;
+    else if (strequ(dt,"int")) return DATATYPE_INT4;
+    else if (strequ(dt,"float")) return DATATYPE_REAL4;
+    else if (strequ(dt,"real4")) return DATATYPE_REAL4;
+    else if (strequ(dt,"double")) return DATATYPE_REAL8;
+    else if (strequ(dt,"real")) return DATATYPE_REAL8;
+    else if (strequ(dt,"real8")) return DATATYPE_REAL8;
+    else if (strequ(dt,"bufr")) return DATATYPE_BUFR;
+    else if (strequ(dt,"grib")) return DATATYPE_GRIB;
+    else if (strequ(dt,"uint")) return DATATYPE_UINT4;
+    else if (strequ(dt,"char")) return DATATYPE_INT1;
+    else if (strequ(dt,"uchar")) return DATATYPE_UINT1;
+    else if (strequ(dt,"short")) return DATATYPE_INT2;
+    else if (strequ(dt,"ushort")) return DATATYPE_UINT2;
+    /* else if (strequ(dt,"")) return DATATYPE_; */
+  } /* if (dt) */
+  return DATATYPE_UNDEF;
+}
+
+int
+get_dtsize(const char *dt)
+{ /* Returns data type specific length in bytes */
+  if (dt) {
+    int len = strlen(dt);
+    if (len >= 6 && strnequ(dt,"pk",2) && strstr(dt,"int")) return sizeof(int);
+    else if (len >= 7 && strnequ(dt,"pk",2) && strstr(dt,"real")) return sizeof(double);
+    else if (strequ(dt,"Formula")) return sizeof(Formula);
+    else if (strequ(dt,"yyyymmdd")) return sizeof(yyyymmdd);
+    else if (strequ(dt,"hhmmss")) return sizeof(hhmmss);
+    else if (strequ(dt,"Bitfield")) return sizeof(Bitfield);
+    else if (strequ(dt,"linkoffset_t")) return sizeof(linkoffset_t);
+    else if (strequ(dt,"linklen_t")) return sizeof(linklen_t);
+    else if (strequ(dt,"string")) return sizeof(string);
+    else if (strequ(dt,"int")) return sizeof(int);
+    else if (strequ(dt,"float")) return sizeof(float);
+    else if (strequ(dt,"real4")) return sizeof(real4);
+    else if (strequ(dt,"double")) return sizeof(double);
+    else if (strequ(dt,"real")) return sizeof(real);
+    else if (strequ(dt,"real8")) return sizeof(real8);
+    else if (strequ(dt,"bufr")) return sizeof(bufr);
+    else if (strequ(dt,"grib")) return sizeof(grib);
+    else if (strequ(dt,"uint")) return sizeof(uint);
+    else if (strequ(dt,"char")) return sizeof(char);
+    else if (strequ(dt,"uchar")) return sizeof(uchar);
+    else if (strequ(dt,"short")) return sizeof(short);
+    else if (strequ(dt,"ushort")) return sizeof(ushort);
+    /* else if (strequ(dt,"")) return sizeof(...); */
+  } /* if (dt) */
+  return 0;
+}
diff --git a/odb/src/aux/f_odb_layer.F90 b/odb/src/aux/f_odb_layer.F90
new file mode 100644
index 0000000..121b363
--- /dev/null
+++ b/odb/src/aux/f_odb_layer.F90
@@ -0,0 +1,248 @@
+SUBROUTINE F_ODB_ADDVIEW(HANDLE, NAME, VHANDLE)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_ADDVIEW
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE
+CHARACTER(LEN=*), INTENT(IN)    :: NAME
+INTEGER(KIND=JPIM), INTENT(OUT) :: VHANDLE
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_ADDVIEW',0,ZHOOK_HANDLE)
+VHANDLE = ODB_ADDVIEW(HANDLE, NAME, ABORT=.FALSE.)
+IF (LHOOK) CALL DR_HOOK('F_ODB_ADDVIEW',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_ADDVIEW
+
+SUBROUTINE F_ODB_CANCEL(HANDLE, NAME, POOLNO, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_CANCEL
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, POOLNO
+CHARACTER(LEN=*), INTENT(IN)    :: NAME
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_CANCEL',0,ZHOOK_HANDLE)
+RC = ODB_CANCEL(HANDLE, NAME, POOLNO=POOLNO)
+IF (LHOOK) CALL DR_HOOK('F_ODB_CANCEL',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_CANCEL
+
+SUBROUTINE F_ODB_COPYDATA(TO, NCHUNK, NOFFSET, FROM, NROWS, NCOLS, NRA, SWAPBYTES, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: NCHUNK, NOFFSET, NROWS, NCOLS, NRA, SWAPBYTES
+REAL(KIND=JPRB), INTENT(OUT)    :: TO(NCOLS, NCHUNK)
+REAL(KIND=JPRB), INTENT(IN)     :: FROM(NRA,0:NCOLS)
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+INTEGER :: JROW, JCOL
+LOGICAL :: LLSWAPBYTES 
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_COPYDATA',0,ZHOOK_HANDLE)
+LLSWAPBYTES = (SWAPBYTES == 1)
+DO JCOL=1,NCOLS
+  DO JROW=NOFFSET+1,NOFFSET+NCHUNK
+    TO(JCOL,JROW-NOFFSET) = FROM(JROW,JCOL)
+  ENDDO
+ENDDO
+IF (LLSWAPBYTES) CALL SWAP8BYTES(TO, NCOLS * NCHUNK)
+RC = NCHUNK
+IF (LHOOK) CALL DR_HOOK('F_ODB_COPYDATA',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_COPYDATA
+
+SUBROUTINE F_ODB_CLOSE(HANDLE, SAVE, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_CLOSE
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, SAVE
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+LOGICAL :: LLSAVE
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_CLOSE',0,ZHOOK_HANDLE)
+LLSAVE = (SAVE == 1)
+RC = ODB_CLOSE(HANDLE, SAVE=LLSAVE)
+IF (LHOOK) CALL DR_HOOK('F_ODB_CLOSE',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_CLOSE
+
+SUBROUTINE F_ODB_GET(HANDLE, NAME, A, NROWS, NCOLS, NRA, POOLNO, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_GET
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)    :: HANDLE, POOLNO, NRA
+CHARACTER(LEN=*), INTENT(IN)      :: NAME
+INTEGER(KIND=JPIM), INTENT(INOUT) :: NROWS, NCOLS
+REAL(KIND=JPRB), INTENT(OUT)      :: A(NRA,0:NCOLS)
+INTEGER(KIND=JPIM), INTENT(OUT)   :: RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET',0,ZHOOK_HANDLE)
+RC = ODB_GET(HANDLE, NAME, A, NROWS, NCOLS=NCOLS, POOLNO=POOLNO)
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_GET
+
+SUBROUTINE F_ODB_OPEN(DBNAME, MODE, NPOOLS, HANDLE)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_OPEN
+IMPLICIT NONE
+CHARACTER(LEN=*), INTENT(IN)      :: DBNAME, MODE
+INTEGER(KIND=JPIM), INTENT(INOUT) :: NPOOLS
+INTEGER(KIND=JPIM), INTENT(OUT)   :: HANDLE
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_OPEN',0,ZHOOK_HANDLE)
+HANDLE = ODB_OPEN(DBNAME,MODE,NPOOLS)
+IF (LHOOK) CALL DR_HOOK('F_ODB_OPEN',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_OPEN
+
+SUBROUTINE F_ODB_RELEASE(HANDLE, POOLNO, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_RELEASE
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, POOLNO
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_RELEASE',0,ZHOOK_HANDLE)
+RC = ODB_RELEASE(HANDLE, POOLNO=POOLNO)
+IF (LHOOK) CALL DR_HOOK('F_ODB_RELEASE',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_RELEASE
+
+SUBROUTINE F_ODB_SELECT(HANDLE, NAME, NROWS, NCOLS, NRA, POOLNO, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_SELECT
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, POOLNO
+CHARACTER(LEN=*)  , INTENT(IN)  :: NAME
+INTEGER(KIND=JPIM), INTENT(OUT) :: NROWS, NCOLS, NRA, RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_SELECT',0,ZHOOK_HANDLE)
+RC = ODB_SELECT(HANDLE, NAME, NROWS, NCOLS, NRA=NRA, POOLNO=POOLNO)
+IF (LHOOK) CALL DR_HOOK('F_ODB_SELECT',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_SELECT
+
+SUBROUTINE F_ODB_GET_TABLENAMES(HANDLE, CHTBL, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE
+CHARACTER(LEN=*), INTENT(OUT)   :: CHTBL
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+INTEGER(KIND=JPIM), PARAMETER   :: JPWHAT = 3
+INTEGER(KIND=JPIM)              :: ILOC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_TABLENAMES',0,ZHOOK_HANDLE)
+CHTBL = ' '
+CALL cODB_getnames(HANDLE, '*', JPWHAT, CHTBL, ILOC, RC)
+!ILOC = SCAN(CHTBL,'/',back=.TRUE.)
+IF (ILOC > 0 .AND. ILOC < LEN(CHTBL)) THEN
+!  CHTBL(ILOC+1:) = ' '
+  CHTBL(ILOC+1:ILOC+1) = char(0)
+ENDIF
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_TABLENAMES',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_GET_TABLENAMES
+
+SUBROUTINE F_ODB_GET_COLNAMES(HANDLE, NAME, CHTBL, EXTNAME, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, EXTNAME
+CHARACTER(LEN=*), INTENT(IN)    :: NAME
+CHARACTER(LEN=*), INTENT(OUT)   :: CHTBL
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+INTEGER(KIND=JPIM), PARAMETER   :: JPWHAT = 2
+INTEGER(KIND=JPIM)              :: ILOC, IWHAT
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_COLNAMES',0,ZHOOK_HANDLE)
+CHTBL = ' '
+IWHAT = JPWHAT
+IF (EXTNAME == 1) IWHAT = IWHAT + 100
+CALL cODB_getnames(HANDLE, NAME, IWHAT, CHTBL, ILOC, RC)
+!ILOC = SCAN(CHTBL,'/',back=.TRUE.)
+IF (ILOC > 0 .AND. ILOC < LEN(CHTBL)) THEN
+!  CHTBL(ILOC+1:) = ' '
+  CHTBL(ILOC+1:ILOC+1) = char(0)
+ENDIF
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_COLNAMES',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_GET_COLNAMES
+
+SUBROUTINE F_ODB_GET_TYPENAMES(HANDLE, NAME, CHTBL, EXTNAME, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, EXTNAME
+CHARACTER(LEN=*), INTENT(IN)    :: NAME
+CHARACTER(LEN=*), INTENT(OUT)   :: CHTBL
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+INTEGER(KIND=JPIM), PARAMETER   :: JPWHAT = 1
+INTEGER(KIND=JPIM)              :: ILOC, IWHAT
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_TYPENAMES',0,ZHOOK_HANDLE)
+CHTBL = ' '
+IWHAT = JPWHAT
+IF (EXTNAME == 1) IWHAT = IWHAT + 100
+CALL cODB_getnames(HANDLE, NAME, IWHAT, CHTBL, ILOC, RC)
+!ILOC = SCAN(CHTBL,'/',back=.TRUE.)
+IF (ILOC > 0 .AND. ILOC < LEN(CHTBL)) THEN
+!  CHTBL(ILOC+1:) = ' '
+  CHTBL(ILOC+1:ILOC+1) = char(0)
+ENDIF
+IF (LHOOK) CALL DR_HOOK('F_ODB_GET_TYPENAMES',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_GET_TYPENAMES
+
+SUBROUTINE F_ODB_SETVAL(HANDLE, NAME, VARNAME, NEWVALUE, OLDVALUE)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_SETVAL
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE
+CHARACTER(LEN=*), INTENT(IN)    :: NAME, VARNAME
+REAL(KIND=JPRB), INTENT(IN)     :: NEWVALUE
+REAL(KIND=JPRB), INTENT(OUT)    :: OLDVALUE
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_SETVAL',0,ZHOOK_HANDLE)
+OLDVALUE = 0
+IF (LEN(VARNAME) > 0) THEN
+  IF (VARNAME(1:1) == '$') THEN
+    IF (NAME == ' ') THEN
+      OLDVALUE = ODB_SETVAL(HANDLE, VARNAME, NEWVALUE)
+    ELSE
+      OLDVALUE = ODB_SETVAL(HANDLE, VARNAME, NEWVALUE, VIEWNAME=NAME)
+    ENDIF
+  ELSE
+    IF (NAME == ' ') THEN
+      OLDVALUE = ODB_SETVAL(HANDLE, '$'//VARNAME, NEWVALUE)
+    ELSE
+      OLDVALUE = ODB_SETVAL(HANDLE, '$'//VARNAME, NEWVALUE, VIEWNAME=NAME)
+    ENDIF
+  ENDIF
+ENDIF
+IF (LHOOK) CALL DR_HOOK('F_ODB_SETVAL',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_SETVAL
+
+SUBROUTINE F_ODB_IO_METHOD(HANDLE, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_IO_METHOD
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE
+INTEGER(KIND=JPIM), INTENT(OUT) :: RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_IO_METHOD',0,ZHOOK_HANDLE)
+RC = ODB_IO_METHOD(HANDLE)
+IF (LHOOK) CALL DR_HOOK('F_ODB_IO_METHOD',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_IO_METHOD
+
+SUBROUTINE F_ODB_GETSIZE(HANDLE, NAME, NROWS, NCOLS, NRA, POOLNO, RC)
+USE PARKIND1  ,ONLY  : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY  : LHOOK,   DR_HOOK
+USE ODB_MODULE, ONLY : ODB_GETSIZE
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: HANDLE, POOLNO
+CHARACTER(LEN=*), INTENT(IN)    :: NAME
+INTEGER(KIND=JPIM), INTENT(OUT) :: NROWS, NCOLS, NRA, RC
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('F_ODB_GETSIZE',0,ZHOOK_HANDLE)
+RC = ODB_GETSIZE(HANDLE, NAME, NROWS, NCOLS, NRA=NRA, POOLNO=POOLNO)
+IF (LHOOK) CALL DR_HOOK('F_ODB_GETSIZE',1,ZHOOK_HANDLE)
+END SUBROUTINE F_ODB_GETSIZE
diff --git a/odb/src/aux/fileutil.c b/odb/src/aux/fileutil.c
new file mode 100644
index 0000000..e7256f9
--- /dev/null
+++ b/odb/src/aux/fileutil.c
@@ -0,0 +1,101 @@
+
+#include "alloc.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern char *IOtruename(const char *name, const int *len_str);
+
+int
+file_exist_(const char *s)
+{
+  int exist = 0;
+  if (s) {
+    struct stat buf;
+    int len = strlen(s);
+    char *file = IOtruename(s,&len);
+    exist = (stat(file, &buf) == -1) ? 0 : 1;
+    FREE(file);
+  } /* if (s) */
+  return exist;
+}
+
+int
+is_regular_file_(const char *s)
+{
+  int exist = 0;
+  if (s) {
+    struct stat buf;
+    int len = strlen(s);
+    char *file = IOtruename(s,&len);
+    exist = (stat(file, &buf) == -1) ? 0 : 1;
+    if (exist) exist = S_ISREG(buf.st_mode);
+    FREE(file);
+  } /* if (s) */
+  return exist;
+}
+
+int
+is_directory_(const char *s)
+{
+  int exist = 0;
+  if (s) {
+    struct stat buf;
+    int len = strlen(s);
+    char *file = IOtruename(s,&len);
+    exist = (stat(file, &buf) == -1) ? 0 : 1;
+    if (exist) exist = S_ISDIR(buf.st_mode);
+    FREE(file);
+  } /* if (s) */
+  return exist;
+}
+
+int
+rename_file_(const char *in, const char *out)
+{
+  int rc = 0;
+  if (in && out) {
+    int exist_infile = file_exist_(in);
+    if (exist_infile) {
+      int exist_outfile = file_exist_(out);
+      int lenin = strlen(in);
+      char *in_resolved = IOtruename(in,&lenin);
+      int stalin = strlen(out);
+      char *out_resolved = IOtruename(out,&stalin);
+      if (exist_outfile) {
+	if (remove(out_resolved) != 0) {
+	  /* PERROR(out_resolved); */
+	  rc = 2;
+	}
+      } /* if (exist_outfile) */
+      if (rc == 0 && rename(in_resolved, out_resolved) != 0) {
+	/*
+	PERROR("rename_file: rename()");
+	fprintf(stderr,"***Warning: Unable to rename '%s' to '%s'\n",
+		in_resolved, out_resolved);
+	*/
+	rc = 3;
+      } /* if (rename(in_resolved, out_resolved) != 0) */
+      FREE(in_resolved);
+      FREE(out_resolved);
+    }
+    else {
+      /* fprintf(stderr,"***Warning: Unable to locate (in)file '%s'\n",in); */
+      rc = 1;
+    } /* if (exist_infile) */
+  }
+  return rc;
+}
+
+int
+remove_file_(const char *filename)
+{
+  int rc = 0;
+  if (filename) {
+    int len = strlen(filename);
+    char *p = IOtruename(filename,&len); 
+    rc = remove(p);
+    FREE(p);
+  }
+  return rc;
+}
diff --git a/odb/src/aux/generic.c b/odb/src/aux/generic.c
new file mode 100644
index 0000000..76f34a6
--- /dev/null
+++ b/odb/src/aux/generic.c
@@ -0,0 +1,1616 @@
+
+/* generic.c */
+
+#include "odb.h"
+#include "odb_macros.h"
+#include "dca.h"
+#include "evaluate.h"
+#include "info.h"
+#include "iostuff.h"
+#include "cdrhook.h"
+#include "magicwords.h"
+#include "bits.h"
+#include "idx.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static const int def_maxhandle = 10; /* As in module/odbshared.F90 */
+static int maxhandle = 0;     /* Actual max no. of handles; increase/decrease via export ODB_MAXHANDLE */
+
+static DB_t *free_handles = NULL;
+
+PUBLIC void *
+ODBc_get_free_handles(int *Maxhandle)
+{
+  if (Maxhandle) *Maxhandle = maxhandle;
+  return (void *)free_handles;
+}
+
+
+#define SET_PATH(x,X,subdir) \
+{ \
+  char *add_subdir_if_not_defined = subdir; \
+  char *x = getenv("ODB_" #X); \
+  int len; \
+  char *xdb = NULL; \
+  len = strlen("ODB_" #X) + 1 + strlen(p_dbname) + 1; \
+  ALLOC(xdb, len); \
+  snprintf(xdb,len,"ODB_" #X "_%s",p_dbname); \
+  env = getenv(xdb); \
+  FREE(xdb); \
+  if (!env) env = x; \
+  if (env) { \
+    xdb = STRDUP(env); \
+    add_subdir_if_not_defined = NULL; \
+  } \
+  else if (!x##_dbname) { \
+    char curpath[4096]; \
+    xdb = STRDUP(getcwd(curpath, sizeof(curpath))); \
+  } \
+  if (xdb) { FREE(x##_dbname); x##_dbname = STRDUP(xdb); } \
+  FREE(xdb); \
+  len = strlen("ODB_" #X) + 1 + strlen(p_dbname) + 1 + strlen(x##_dbname) + 1; \
+  if (add_subdir_if_not_defined) len += strlen(add_subdir_if_not_defined); \
+  if (add_subdir_if_not_defined) len += strlen(add_subdir_if_not_defined); \
+  ALLOC(env, len); /* Remains allocated ; cannot be free'd */ \
+  snprintf(env,len,"ODB_" #X "_%s=%s%s",p_dbname,x##_dbname,\
+           add_subdir_if_not_defined?add_subdir_if_not_defined:""); \
+  putenv(env); \
+  { \
+    char *penv = STRDUP(env); \
+    char *eq = strchr(penv,'='); \
+    if (eq) { \
+      *eq = '\0'; \
+      env = getenv(penv); \
+      fprintf(stderr,"%s=%s\n",penv,env?env:NIL); \
+      if (env) { FREE(x##_dbname); x##_dbname = STRDUP(env); } \
+    } \
+    FREE(penv); \
+  } \
+}
+
+
+PUBLIC int 
+ODBc_open(const char *dbname, const char *mode, int *npools, int *ntables, const char *poolmask)
+{
+  Bool on_error = false;
+  int handle = -1;
+  DRHOOK_START(ODBc_open);
+  if (dbname) {
+    int j;
+    int Npools = 0;
+    int Ntables = 0;
+    DB_t *ph = NULL;
+    char *p_dbname = NULL;
+    char *srcpath_dbname = NULL;
+    char *datapath_dbname = NULL;
+    char *idxpath_dbname = NULL;
+    char *env;
+    Bool first_time = false;
+    
+    if (!free_handles) {
+      env = getenv("ODB_MAXHANDLE");
+      if (env) maxhandle = atoi(env);
+      if (maxhandle <= 0) maxhandle = def_maxhandle;
+      CALLOC(free_handles, maxhandle);
+      
+      /* Other first time setups */
+      {
+	extern Boolean iostuff_debug;
+	iostuff_debug = false;
+      }
+
+      env = STRDUP("ODB_IO_METHOD=5"); /* Remains allocated ; cannot be free'd due to putenv() below */
+      putenv(env);
+      first_time = true;
+    }
+    
+    for (j=0; j<maxhandle; j++) {
+      if (free_handles[j].h == 0) {
+	handle = j+1;
+	ph = &free_handles[j];
+	break;
+      }
+    }
+
+    if (!ph) {
+      fprintf(stderr,
+	      "***Error: Unable to open ODB-database '%s' : too many opened databases\n",
+	      dbname);
+      fprintf(stderr,
+	      "\tMax. no. of open databases currently = %d. Increase via export ODB_MAXHANDLE\n",
+	      maxhandle);
+      handle = -1;
+      goto finish;
+    }
+
+    { /* Check if database name contains an '/' */
+      char *pdot = NULL;
+      char *slash = NULL;
+      char *p = STRDUP(dbname);
+      char *pdollar = strchr(p, '$');
+
+      if (pdollar) {
+	/* Resolve possible environment variable(s) in the "dbname" i.e. "p" */
+	char *tmp = IOresolve_env(p);
+	FREE(p);
+	p = tmp;
+      }
+
+      if (strequ(p,".")) {
+	/* "dbname" points to the current directory ? */
+	char curpath[4096];
+	FREE(p);
+	p = STRDUP(getcwd(curpath, sizeof(curpath)));
+      }
+
+      {
+	/* If last char(s) is/are '/', remove it/them from "dbname" i.e. "p" */
+	int len = STRLEN(p);
+	while (len >= 0 && p[len-1] == '/') {
+	  p[len-1] = '\0';
+	  --len;
+	}
+      }
+
+      {
+	/* Is "dbname" i.e. "p" a (schema-)file or a directory ? */
+	struct stat buf;
+	int exist = (stat(p, &buf) == -1) ? 0 : 1;
+	Bool is_dir = (exist && S_ISDIR(buf.st_mode)) ? true : false;
+	if (is_dir) {
+	  /* Directory --> Append <db>.sch to "p" */
+	  int len;
+	  char *tmp = STRDUP(p);
+	  char *db = NULL;
+	  const char suffix[] = ".sch";
+	  slash = strrchr(tmp, '/');
+	  if (slash) {
+	    db = STRDUP(slash+1);
+	  }
+	  else {
+	    db = STRDUP(tmp);
+	  }
+	  pdot = strchr(db, '.');
+	  if (pdot) *pdot = '\0';
+	  len = STRLEN(tmp) + 1 + STRLEN(db) + STRLEN(suffix) + 1;
+	  FREE(p);
+	  ALLOC(p, len);
+	  snprintf(p, len, "%s/%s%s", tmp, db, suffix);
+	  FREE(tmp);
+	} /* if (is_dir) */
+      }
+
+      slash = strrchr(p, '/');
+      if (slash) {
+	*slash = '\0';
+	p_dbname = STRDUP(slash+1);
+	pdot = strchr(p_dbname, '.');
+	if (pdot) *pdot = '\0';
+	srcpath_dbname = STRDUP(p); 
+	datapath_dbname = STRDUP(p); 
+	idxpath_dbname = STRDUP(p);
+      }
+      else {
+	pdot = strchr(p, '.');
+	if (pdot) *pdot = '\0';
+	p_dbname = STRDUP(p);
+      }
+      FREE(p);
+    }
+
+    ph->h = handle;
+    ph->dbname = p_dbname;
+
+    SET_PATH(srcpath, SRCPATH, NULL);
+    SET_PATH(datapath, DATAPATH, NULL);
+    SET_PATH(idxpath, IDXPATH, "/idx");
+
+    ph->srcpath = srcpath_dbname;
+    ph->datapath = datapath_dbname;
+    ph->idxpath = idxpath_dbname;
+
+    if (first_time) { 
+      /* The following is done once only, since currently IOASSIGN is upon the first cma_open() */
+
+      /* Check existence of IOASSIGN and if not defined, then define it */
+      env = getenv("IOASSIGN");
+      if (!env) {
+	int len = 2*strlen("IOASSIGN=") + strlen(srcpath_dbname) + 1 + strlen(p_dbname) + 1;
+	ALLOC(env, len);
+	snprintf(env, len, "IOASSIGN=%s/%s.IOASSIGN", srcpath_dbname, p_dbname);
+	putenv(env); /* Remains allocated ; cannot be free'd */
+      }
+      env = getenv("IOASSIGN");
+
+      codb_init_(NULL, NULL); /* lib/errtarp.c : the same as myproc=1, nproc=1 */
+      codb_init_omp_locks_(); /* lib/codb.c    */
+      codb_trace_init_(NULL); /* lib/tracing.g */
+
+      /* Let poolmasking know what's the maxhandle */
+      codb_alloc_poolmask_(&maxhandle);
+    } /* if (first_time) */
+
+    if (poolmask) { /* Set poolmask explicitly for this database */
+      char *env = NULL;
+      const char str[] = "ODB_PERMANENT_POOLMASK";
+      int len = STRLEN(str) + 1 + STRLEN(p_dbname) + 1 + STRLEN(poolmask) + 1;
+      ALLOC(env,len);
+      snprintf(env, len, "%s_%s=%s", str, p_dbname, poolmask);
+      putenv(env);
+      /* FREE(env); (cannot be freed due to putenv()) */ 
+    } /* if (poolmask) */
+
+    ph->tblname = NULL;
+
+    { /* Read primary metadata (i.e. usually the $ODB_SRCPATH_<dbname>/<dbname>.dd -file) */
+      int iret = 0;
+      int iounit = -1;
+      cma_open_(&iounit, p_dbname, "r", &iret, strlen(p_dbname), 1);
+      if (iret >= 1) {
+	FILE *fp = CMA_get_fp(&iounit);
+	codb_read_metadata_(&handle,
+			    &iounit,
+			    &Npools,
+			    NULL,
+			    NULL,
+			    NULL,
+			    NULL,
+			    NULL,
+			    &Ntables);
+	if (fp && Ntables > 0) {
+	  int i;
+	  char tname[4096];
+	  CALLOC(ph->tblname, Ntables);
+	  for (i=0; i<Ntables; i++) {
+	    int id, fsize;
+	    Bool found = false;
+	    if (fscanf(fp,"%d %s %d",&id,tname,&fsize) == 3) {
+	      char *ptbl = tname;
+	      /* if (*ptbl == '@') ptbl++; */
+	      if (id >= 1 && id <= Ntables) {
+		ph->tblname[id-1] = STRDUP(ptbl);
+		found = true;
+	      }
+	    }
+	    if (!found) ph->tblname[i] = STRDUP("???unknown_table???");
+	  } /* for (i=0; i<Ntables; i++) */
+	}
+      }
+      cma_close_(&iounit, &iret);
+    }
+
+    { /* Check whether $ODB_SRCPATH_<dbname>/dca -directory exists;
+	 if not, try to run "dcagen"-tool from within this code ;
+         Note: the srcpath must be writable by you !! */
+      if (access(ph->srcpath, W_OK | R_OK | X_OK) == 0) {
+	struct stat buf;
+	int exist;
+	Bool is_dir;
+	char *dcadir = NULL;
+	int len = STRLEN(ph->srcpath) + STRLEN("/dca") + 1;
+	ALLOCX(dcadir, len);
+	snprintf(dcadir, len, "%s/dca", ph->srcpath);
+	exist = (stat(dcadir, &buf) == -1) ? 0 : 1;
+	is_dir = (exist && S_ISDIR(buf.st_mode)) ? true : false;
+	if (!is_dir) {
+	  char *binpath = getenv("ODB_FEBINPATH");
+	  if (binpath) {
+	    const char dcagen[] = "dcagen";
+	    char *dcagen_cmd = NULL;
+	    len = STRLEN(binpath) + 1 + STRLEN(dcagen) + 1;
+	    ALLOCX(dcagen_cmd, len);
+	    snprintf(dcagen_cmd, len, "%s/%s", binpath, dcagen);
+	    if (access(dcagen_cmd, X_OK | R_OK) == 0) {
+	      int iret = 0;
+	      extern Bool odbdump_on;
+	      const char *dcagen_fmt = 
+		odbdump_on ? "%s -i %s -F -n -q -N 1 -z -E odbdump.stderr" : "%s -i %s -F -n -q -N 1 -z";
+	      char *cmd = NULL;
+	      len = STRLEN(dcagen_fmt) + STRLEN(dcagen_cmd) + STRLEN(ph->srcpath) + 1;
+	      ALLOCX(cmd, len);
+	      snprintf(cmd, len, dcagen_fmt, dcagen_cmd, ph->srcpath);
+	      fprintf(stderr,"***Warning: Generating dca-indices into directory '%s' ...\n", dcadir);
+	      fprintf(stderr,"***Warning: The command used is : %s\n", cmd);
+	      if (odbdump_on) fflush(stderr);
+	      iret = system(cmd);
+	      if (iret != 0) {
+		fprintf(stderr,
+			"***Error [iret=%d]: Unable to create dca-indices !!\n",
+			iret);
+		on_error = true;
+	      }
+	      FREEX(cmd);
+	    }
+	    FREEX(dcagen_cmd);
+	  } /* if (binpath) */
+	} /* if (!is_dir) */
+	FREEX(dcadir);
+      } /* if (access(ph->srcpath, ... ) */
+    }
+
+    /* Initialize poolmask for this database */
+    
+    codb_init_poolmask_(&handle, p_dbname, &Npools, strlen(p_dbname));
+
+    ph->npools = Npools;
+    ph->ntables = Ntables;
+
+    if (npools) *npools = Npools;
+    if (ntables) *ntables = Ntables;
+  }
+ finish:
+  if (on_error && handle >= 1) handle = ODBc_close(handle);
+  DRHOOK_END(0);
+  return handle;
+}
+
+
+PUBLIC int
+ODBc_get_handle(const char *db)
+{
+  int handle = -1;
+  DRHOOK_START(ODBc_get_handle);
+  if (free_handles) {
+    int j;
+    for (j=0; j<maxhandle; j++) {
+      DB_t *ph = &free_handles[j];
+      if (ph->h > 0 && (!db || strequ(db,ph->dbname))) {
+	handle = ph->h;
+	break; /* for (j=0; j<maxhandle; j++) */
+      }
+    }
+  }
+  DRHOOK_END(0);
+  return handle;
+}
+
+
+PUBLIC int
+ODBc_close(int handle)
+{
+  int rc = -1;
+  DRHOOK_START(ODBc_close);
+  if (free_handles && handle >= 1 && handle <= maxhandle) {
+    DB_t *ph = &free_handles[handle-1];
+    if (ph->h == handle) {
+      DCA_free(handle);
+      codb_end_poolmask_(&handle);
+      ph->h = 0;
+      FREE(ph->dbname);
+      FREE(ph->srcpath);
+      FREE(ph->datapath);
+      if (ph->tblname && ph->ntables > 0) {
+	int i;
+	for (i=0; i<ph->ntables; i++) FREE(ph->tblname[i]);
+	FREE(ph->tblname);
+      }
+      ph->tblname = NULL;
+      rc = 0; /* ok */
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC const char **
+ODBc_get_tablenames(int handle, int *ntables)
+{
+  const char **rc = NULL;
+  DRHOOK_START(ODBc_get_tablenames);
+  if (ntables) *ntables = 0;
+  if (free_handles && handle >= 1 && handle <= maxhandle) {
+    DB_t *ph = &free_handles[handle-1];
+    if (ph->h == handle) {
+      if (ntables) *ntables = ph->ntables;
+      if (ph->tblname) rc = (const char **)ph->tblname;
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC void *
+ODBc_sql_prepare_via_sqlfile(int handle, const char *sql_query_file, const set_t *setvar, int nsetvar)
+{
+  void *Info = NULL;
+  DRHOOK_START(ODBc_sql_prepare_via_sqlfile);
+  if (sql_query_file) {
+    if (free_handles && handle >= 1 && handle <= maxhandle) {
+      DB_t *ph = &free_handles[handle-1];
+      if (ph->h == handle) {
+	char *dbname = ph->dbname;
+	if (dbname) {
+	  info_t *info = NULL;
+	  char *odb98_info = getenv("ODB98_INFO");
+#ifdef NECSX
+	  char *binpath = getenv("ODB_BINPATH");
+	  const char odb98x[] = "odb98be.x";
+#else
+	  char *binpath = getenv("ODB_FEBINPATH");
+	  const char odb98x[] = "odb98.x";
+#endif
+	  char *cmd = NULL;
+
+	  if (odb98_info && STRLEN(odb98_info) > 0) {
+	    /* Info was extracted in advance and put into file $ODB98_INFO */
+	    cmd = STRDUP(odb98_info);
+	    putenv("ODB98_INFO="); /* Discard after it was used once */
+	  }
+	  else {
+	    char *srcpath = ph->srcpath;
+	    char *exe = NULL;
+	    int len, lenexe;
+	    if (!binpath) binpath = ".";
+	    if (!srcpath) srcpath = ".";
+	    lenexe = STRLEN(binpath) + STRLEN(odb98x) + 2;
+	    ALLOC(exe, lenexe);
+	    snprintf(exe, lenexe, "%s/%s", binpath, odb98x);
+	    if (access(exe, X_OK) != 0) {
+	      fprintf(stderr,"***Error: Unable to execute '%s'\n",exe);
+	      FREE(exe);
+	      Info = NULL;
+	      goto finish;
+	    }
+	    len = 2*STRLEN(srcpath) + STRLEN(exe) + STRLEN(dbname) + STRLEN(sql_query_file) + 256;
+	    ALLOC(cmd, len);
+	    snprintf(cmd,len,
+		     "| %s -F2 -Q %s %s/%s.sch"
+		     "; \\echo '/dir=%s'"
+		     "; \\echo '/host='`\\hostname`"
+		     "; \\echo '/tstamp='`\\date`"
+		     ,exe, sql_query_file, srcpath, dbname
+		     ,srcpath);
+	    FREE(exe);
+	  }
+	  Info = info = ODBc_get_info(cmd, setvar, nsetvar);
+	  FREE(cmd);
+
+	  /* Patch up */
+	  {
+	    while (info) {
+	      info->npools = ph->npools;
+	      info->ph = ph;
+	      if (info->use_indices) {
+		/* Fetch stored indices for each (table,wherecond)-pair */
+		table_t *t = info->t;
+		while (t) {
+		  t->stored_idx_count = ODBc_fetch_indices(t, info);
+		  t = t->next;
+		} /* while (t) */
+	      }
+	      info = info->next;
+	    }
+	  }
+
+	} /* if (dbname) */
+      }
+    }
+  } 
+  else { /* if (sql_query_file) ... else ... */
+    fprintf(stderr,
+	    "***Error in ODBc_sql_prepare_via_sqlfile(): The ODB/SQL-query file is not given !!\n");
+    RAISE(SIGABRT);
+  }
+ finish:
+  DRHOOK_END(0);
+  return Info;
+}
+
+
+PUBLIC void *
+ODBc_sql_prepare(int handle, const char *sql_query, const set_t *setvar, int nsetvar)
+{
+  void *Info = NULL;
+  DRHOOK_START(ODBc_sql_prepare);
+  if (sql_query) {
+    FILE *fp;
+    int pid = (int)getpid();
+    int len = 80;
+    char *tmpfile;
+    char *tmpdir = getenv("TMPDIR");
+    if (!tmpdir) tmpdir = "/tmp";
+    len += STRLEN(tmpdir);
+    ALLOCX(tmpfile,len);
+    snprintf(tmpfile,len,"%s/myview_%d.sql",tmpdir,pid);
+    (void) remove_file_(tmpfile);
+    fp = fopen(tmpfile,"w");
+    if (fp) {
+      fprintf(fp,"%s\n;\n",sql_query);
+      fclose(fp);
+      Info = ODBc_sql_prepare_via_sqlfile(handle, tmpfile, setvar, nsetvar);
+      (void) remove_file_(tmpfile);
+    }
+    else {
+      fprintf(stderr,
+	      "***Error in ODBc_sql_prepare(): Unable to create temporary ODB/SQL-file '%s'\n",
+	      tmpfile);
+      RAISE(SIGABRT);
+    }
+  } 
+  else { /* if (sql_query) ... else ... */
+    fprintf(stderr,
+	    "***Error in ODBc_sql_prepare(): The query string is missing !!\n");
+    RAISE(SIGABRT);
+  }
+ finish:
+  DRHOOK_END(0);
+  return Info;
+}
+
+
+PUBLIC char *
+S2D_fix(const void *Info, const char *s)
+{
+  char *rc = NULL;
+  if (Info && s) {
+    const info_t *info = Info;
+    char *pwherecond = STRDUP(s);
+    if (info->ns2d > 0 && strstr(pwherecond, S2D)) {
+      /* Strings involved in f.ex. WHERE-stmt */
+      int j, ns2d = info->ns2d;
+      for (j=ns2d-1; j>=0; j--) {
+	/* Must go reverse to avoid problems with S2D_1 and S2D_10 for example */
+	char *new = NULL;
+	const str_t *s2d = &info->s2d[j];
+	char *s2dname = STRDUP(s2d->name); /* Now still "s2d_<number>" */
+	char *ps = s2dname;
+	char *s2dvalue = NULL;
+	int len_s2dvalue = 1 + STRLEN(s2d->value) + 2;
+	ALLOC(s2dvalue,len_s2dvalue);
+	snprintf(s2dvalue,len_s2dvalue,"\"%s\"",s2d->value);
+	while (*ps) { *ps = ToUpper(*ps); ++ps; } /* "s2d_<number>" --> "S2D_<number>" */
+	new = ReplaceSubStrings(pwherecond,          /* 'haystack' */
+				s2dname,             /* 'needle' */
+				s2dvalue,            /* 'repl_with' */
+				true,                /* 'all_occurences' */
+				false,               /* 'remove_white_space' */
+				false);              /* 'ignore_case' */
+	FREE(pwherecond);
+	pwherecond = new;
+	FREE(s2dvalue);
+	FREE(s2dname);
+      } /* for (j=ns2d-1; j>=0; j--) */
+    }
+    rc = pwherecond;
+  }
+  return rc; /* Watch for memory leakages here */
+}
+
+
+PUBLIC double
+ODB_maxrows()
+{
+  double *testvalue = getsymaddr(_ROWNUM); /* current thread's "info->idxlen" */
+  return testvalue ? *testvalue : (double)0;
+}
+
+
+PUBLIC double
+ODB_maxcount(double x)
+{
+  return (ODB_maxrows() < x) ? (double)1 : (double)0;
+}
+
+
+#define CASE_GET_BITS(x, pos, len) \
+  case len: for (j=0; j<nx; j++) x[j] = GET_BITS(x[j], pos, len); break
+
+PUBLIC void
+ODBc_vget_bits(double x[], int nx, int pos, int len)
+{
+  int j;
+  DRHOOK_START(ODBc_vget_bits);
+  switch (len) {
+    CASE_GET_BITS(x, pos, 1);
+    CASE_GET_BITS(x, pos, 2);
+    CASE_GET_BITS(x, pos, 3);
+    CASE_GET_BITS(x, pos, 4);
+    CASE_GET_BITS(x, pos, 5);
+    CASE_GET_BITS(x, pos, 6);
+    CASE_GET_BITS(x, pos, 7);
+    CASE_GET_BITS(x, pos, 8);
+    CASE_GET_BITS(x, pos, 9);
+    CASE_GET_BITS(x, pos,10);
+    CASE_GET_BITS(x, pos,11);
+    CASE_GET_BITS(x, pos,12);
+    CASE_GET_BITS(x, pos,13);
+    CASE_GET_BITS(x, pos,14);
+    CASE_GET_BITS(x, pos,15);
+    CASE_GET_BITS(x, pos,16);
+    CASE_GET_BITS(x, pos,17);
+    CASE_GET_BITS(x, pos,18);
+    CASE_GET_BITS(x, pos,19);
+    CASE_GET_BITS(x, pos,20);
+    CASE_GET_BITS(x, pos,21);
+    CASE_GET_BITS(x, pos,22);
+    CASE_GET_BITS(x, pos,23);
+    CASE_GET_BITS(x, pos,24);
+    CASE_GET_BITS(x, pos,25);
+    CASE_GET_BITS(x, pos,26);
+    CASE_GET_BITS(x, pos,27);
+    CASE_GET_BITS(x, pos,28);
+    CASE_GET_BITS(x, pos,29);
+    CASE_GET_BITS(x, pos,30);
+    CASE_GET_BITS(x, pos,31);
+    CASE_GET_BITS(x, pos,32);
+  default:
+    for (j=0; j<nx; j++) x[j] = 0;
+    break;
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+InitNrowsNcols(const DB_t *ph, info_t *info, table_t *t, int poolno)
+{
+  DRHOOK_START(InitNrowsNcols);
+  if (ph && info && t && t->ncols == 0) {
+    DCA_getsize(ph->h, ph->dbname, t->name, poolno, &t->nrows, &t->ncols);
+    ODB_fprintf(ODBc_get_debug_fp(),"InitNrowsNcols[poolno#%d]: table='%s', nrows=%d, ncols=%d\n",
+		poolno, t->name, t->nrows, t->ncols);
+  }
+  DRHOOK_END(0);
+}
+
+
+#define DEPTH_TABS(fp,num) ODB_fprintf(fp,"%*.*s[%d]",2*(num),2*(num),"  ",num)
+
+#define LINK_FETCH_ERROR(what) \
+fprintf(stderr, \
+	"***Error in %s:%d: Unable to fetch %s '%s' for pool#%d. " \
+	"Expecting %d (= # of rows in table '%s'), but got %d rows. Link-case = %d.\n", \
+	__FILE__, __LINE__, #what, \
+	t->what, poolno, tp_off->nrows, tp_off->name, Nrows, t->linkcase)
+
+
+#define COLUMN_FETCH_ERROR() \
+fprintf(stderr, \
+	"***Error: Unable to fetch column '%s' (fetch_name='%s') for pool#%d. " \
+	"Expecting %d (= # of rows in table '%s'), but got %d rows.\n", \
+	s, sf ? sf : NIL, poolno, tc->nrows, tc->name, Nrows)
+
+#define COLUMN_FETCH_WARNING() \
+fprintf(stderr, \
+	"***Warning: Unable to fetch column '%s' (fetch_name='%s') for pool#%d. " \
+	"Expecting %d (= # of rows in table '%s'), but got %d rows.\n", \
+	s, sf ? sf : NIL, poolno, tc->nrows, tc->name, Nrows)
+
+
+PRIVATE int
+PrefetchData(const DB_t *ph, col_t *colthis, int poolno, const int depth)
+{
+  int errflg = 0;
+  DRHOOK_START(PrefetchData);
+  if (colthis) {
+    const char *s = colthis->name;
+    table_t *tc = colthis->t;
+    const char *tblname = tc->name;
+    
+    if (!colthis->dsym) {
+      /* 
+	 For the moment accept (and expect) only ordinary columns 'colname at table'
+	 and '#table' -variables
+         (See also info.c, routine HasSimpleWHEREcond(): 
+	 "For the moment ignore all kind of '$...#'-variables and '#table'
+	 variables that are not referring to the current table")
+      */
+      if (IS_HASH(s)) {
+	/* '#table_name' == ROW-number [1..Nrows] */
+	if (strequ(s+1, tblname)) {
+	  colthis->dsym = putsym(s, mdi);
+	}
+	else {
+	  errflg++;
+	}
+      }
+      else {
+	const char *sf = colthis->fetch_name;
+	int Nrows;
+	colthis->dinp = DCA_fetch_double(ph->h, ph->dbname, tc->name, sf,
+					 poolno, NULL, 0, &Nrows);
+	if (Nrows != tc->nrows) {
+	  /* Don't abort */
+	  COLUMN_FETCH_WARNING();
+	  colthis->dsym = putsym(s, mdi);
+	  errflg++;
+	}
+	else {
+	  Bool thesame = strequ(s,sf) ? true : false;
+	  FILE *fp_echo = ODBc_get_debug_fp();
+	  DEPTH_TABS(fp_echo, depth);
+	  ODB_fprintf(fp_echo,
+		      "%s:%d: Successfully fetched (double) %s%s%s (Nrows=%d/%d) : poolno#%d\n",
+		      __FILE__, __LINE__,
+		      thesame ? s : sf,
+		      thesame ? "" : " alias ",
+		      thesame ? (const char *)"" : s,
+		      Nrows, tc->nrows, poolno);
+	  colthis->dinp_len = Nrows;
+	  colthis->dinp_alloc = true;
+	  if (colthis->dtnum == DATATYPE_INT4 && 
+	      colthis->bitpos >= 0 && colthis->bitpos <  MAXBITS &&
+	      colthis->bitlen >= 1 && colthis->bitlen <= MAXBITS) {
+	    ODBc_vget_bits(colthis->dinp, colthis->dinp_len, colthis->bitpos, colthis->bitlen);
+	  }
+	  colthis->dsym = putsymvec(s, mdi, colthis->dinp, Nrows);
+	}
+      }
+    }
+    else {
+      *colthis->dsym = mdi;
+    } /* if (!colthis->dsym) ... else ... */
+  } /* if (colthis) */
+  DRHOOK_END(0);
+  return errflg;
+}
+
+#define INIT_SKIPROW(x) if (t->skiprow) memset(t->skiprow, (x), Nrows * sizeof(*t->skiprow))
+#define FILL_SKIPROW(OP) for (j=0; j<Nrows; j++) t->skiprow[j] = (lhs[j] OP rhs) ? 0 : 1
+#define FILL_SKIPROW_USING_ROWID(OP) for (j=0; j<Nrows; j++) t->skiprow[j] = ((j+1) OP rhs) ? 0 : 1
+
+#define FETCH_ME(what) \
+{ \
+  int Nrows = 0; \
+  t->what = DCA_fetch_int(ph->h, ph->dbname, tp_off->name, t->link##what, \
+			  poolno, NULL, 0, &Nrows); \
+  if (Nrows != tp_off->nrows) { \
+    LINK_FETCH_ERROR(link##what); \
+    RAISE(SIGABRT); \
+  } \
+  else if (fp_echo) { \
+    if (!done) { ODB_fprintf(fp_echo,"\n"); done++; } \
+    DEPTH_TABS(fp_echo, depth); \
+    ODB_fprintf(fp_echo, \
+		"%s:%d: Successfully fetched (int) %s (Nrows=%d/%d) [linkcase=%d, '%s'] : poolno#%d\n", \
+		__FILE__, __LINE__, \
+		t->link##what, Nrows, tp_off->nrows, t->linkcase, \
+		(t->linkcase >= 1 && t->linkcase <= NLINKCASES) ? linkcase_name[t->linkcase] : NIL, \
+		poolno); \
+  } \
+}
+
+PRIVATE int /* Recursive */
+HSL(const DB_t *ph, info_t *info, table_t *t, int poolno, Bool *immed_return, const int depth)
+{ /* HSL = HierarchicalSearchLoop */
+  int rc = 0;
+  if (t && ph && info) {
+    FILE *fp_echo = ODBc_get_debug_fp();
+    table_t *tp_link = t->linkparent;
+    table_t *tp_off = t->offset_parent;
+    int jr, lo=0, hi=0;
+    int done = 0;
+    if (fp_echo) {
+      DEPTH_TABS(fp_echo, depth);
+      ODB_fprintf(fp_echo, "%s:%d: HSL-depth#%d :",__FILE__, __LINE__, depth);
+      if (t->name) {
+	ODB_fprintf(fp_echo, " t=['%s' #%d lo=%d ob=%d jr=%d]",
+		    t->name,t->nrows,t->lo,t->ob,t->jr);
+      }
+      if (tp_link && tp_link->name) {
+	ODB_fprintf(fp_echo, " tp_link=['%s' #%d lo=%d ob=%d jr=%d]",
+		    tp_link->name,tp_link->nrows,tp_link->lo,tp_link->ob,tp_link->jr);
+      }
+      if (tp_off && tp_off->name) {
+	ODB_fprintf(fp_echo, " tp_off=['%s' #%d lo=%d ob=%d jr=%d]",
+		    tp_off->name,tp_off->nrows,tp_off->lo,tp_off->ob,tp_off->jr);
+      }
+      fflush(fp_echo);
+    }
+
+    if (t->linkcase == 1 || t->linkcase == 4 || t->linkcase == 2) {
+      if (!t->offset) FETCH_ME(offset);
+      if (!t->len) FETCH_ME(len);
+    }
+
+    switch (t->linkcase) {
+    case 1: /* ONELOOPER - link */
+    case 4: /* A regular link */
+      if (tp_off->jr >= 0 && tp_off->jr < tp_off->nrows) {
+	/* Extra safeguard : Make sure we stay within the array bounds */
+	if (tp_off->jr != t->ob) {
+	  t->ob = tp_off->jr;
+	  t->lo = t->offset[tp_off->jr];
+	}
+	lo = t->offset[tp_off->jr];
+	if (t->linkcase == 1) {
+	  /* Remember safeguarding */
+	  hi = lo + ((t->len[tp_off->jr] == 1) ? 1 : 0);
+	}
+	else {
+	  hi = lo + t->len[tp_off->jr];
+	}
+	if (lo < 0 || lo >= t->nrows || hi < 0 || hi > t->nrows) {
+	  /* Disallow insane values */
+	  lo = hi = 0;
+	}
+      }
+      else {
+	lo = hi = 0;
+      }
+      break;
+
+    case 2: /* ALIGNed table */
+      {
+	Bool range_ok = false;
+
+	if (tp_off->jr >= 0 && tp_off->jr < tp_off->nrows) {
+	  /* Extra safeguard : Make sure we stay within the array bounds */
+	  if (tp_off->jr != t->ob) {
+	    t->ob = tp_off->jr;
+	    t->lo = t->offset[tp_off->jr];
+	  }
+	  lo = t->offset[tp_off->jr] + (tp_link->jr - tp_link->lo);
+	  range_ok = true;
+	}
+	else {
+	  lo = -1; /* Out of bounds */
+	}
+
+	if (lo < 0 || lo >= t->nrows) {
+	  /* Disallow insane values straight away */
+	  lo = hi = 0;
+	  break;
+	}
+	
+	if (range_ok) {
+	  /* Extra safeguard : Make sure we stay within the array bounds */
+	  /* Remember safeguarding */
+	  int add = ((t->len[tp_off->jr] > 0) ? 1 : 0); /* One-by-one */
+	  hi = lo + add;
+	}
+	else {
+	  /* Disallow insane values */
+	  lo = hi = 0;
+	}
+
+	if (lo < 0 || lo >= t->nrows || hi < 0 || hi > t->nrows) {
+	  /* Disallow insane values */
+	  lo = hi = 0;
+	}
+      }
+      break;
+
+    case 3: /* ALIGNed, but orphaned table (i.e. no link-parent available/specified) */
+      lo = tp_link ? tp_link->jr : 0;
+      hi = lo + 1;
+      if (lo < 0 || lo >= t->nrows || hi < 0 || hi > t->nrows) {
+	/* Disallow insane values */
+	lo = hi = 0;
+      }
+      break;
+
+    case 5: /* The very first table in FROM-stmt */
+    case 6: /* A completely disconnected/isolated table w.r.t. other tables in FROM-stmt */
+      lo = 0;
+      hi = t->nrows;
+      break;
+
+    default:
+      fprintf(stderr,
+	      "***Error: Fatal programming error : Invalid linkcase #%d."
+	      " Must be one between %d and %d, inclusive\n",t->linkcase,1,NLINKCASES);
+      RAISE(SIGABRT);
+      break;
+    } /* switch (t->linkcase) */
+
+    if (fp_echo) {
+      if (!done) { ODB_fprintf(fp_echo,"\n"); done++; }
+      DEPTH_TABS(fp_echo, depth);
+      ODB_fprintf(fp_echo, "%s:%d:",__FILE__,__LINE__);
+      ODB_fprintf(fp_echo, " ==> tbl='%s' @ jr=%d; lo=%d; ob=%d [lo=%d, hi=%d)", 
+		  t->name, t->jr, t->lo, t->ob, lo, hi);
+      if (tp_link) ODB_fprintf(fp_echo, ", linkparent '%s' @ jr=%d", 
+			  tp_link->name, tp_link->jr);
+      if (tp_off) ODB_fprintf(fp_echo, ", offset_parent '%s' @ jr=%d", 
+			      tp_off->name, tp_off->jr);
+      ODB_fprintf(fp_echo, "\n");
+    }
+
+    if (info && info == t->info && lo >= 0 && hi > lo) {
+      int maxfrom = t->table_id; /* The same meaning as in compiler/genc.c */
+
+      if (t->simple_wherecond && !t->skiprow) {
+	/*   
+	     WHERE-condition for this table t was simple enough and thus
+	   we generate exclusion vector skiprow[] in order to skip those
+	   rows that will definitely be ruled out.
+	     This optimization should speed-up satellite data search, when
+	   (say) particular channel numbers (press at body) are to be filtered 
+	*/
+
+	int i;
+	int errflg = 0;
+	int nwl = t->nwl;
+	int nwl_index = 0; /* Number of "wl"'s with stored_idx ... used later ... */
+	simple_where_t *wl = t->wl;
+	int Nrows = t->nrows;
+
+	for (i=0; i<nwl && errflg == 0; i++) {
+	  odbidx_pp_t *pp = NULL;
+
+	  if (wl->stored_idx) {
+	    pp = codb_IDXF_unpack(wl->stored_idx, poolno, 0);
+
+	    if (!pp || (pp && (pp->nrows != Nrows))) {
+	      /* Table no. of rows & the nrows seen by the Index
+		 disagree ==> the index [for this poolno] is probably useless */
+	      pp = NULL;
+	    }
+	  }
+
+	  if (!pp) {
+	    errflg = PrefetchData(ph, wl->wcol, poolno, depth);
+	  }
+	  else {
+	    nwl_index++;
+	  }
+
+	  wl++;
+	} /* for (i=0; i<nwl && errflg == 0; i++) */
+
+	if (errflg == 0) {
+	  int j;
+	  ALLOC(t->skiprow, Nrows);
+	  wl = t->wl;
+
+	  if (wl->stored_idx && nwl == nwl_index) {
+	    /* IDXF available : nwl can be > 1 i.e. more than one AND'ies possible */
+	    unsigned char *lc_picked = NULL;
+	    unsigned char *picked = NULL;
+	    int min_picked = INT_MAX;
+	    int max_picked = -1;
+
+	    CALLOC(picked, Nrows);
+
+	    INIT_SKIPROW(1); /* By default skip all rows */
+
+	    for (i=0; i<nwl; i++) {
+	      odbidx_pp_t *pp = codb_IDXF_locate_pp(wl->stored_idx, poolno, 0);
+	      int js, nsets = pp->nsets;
+	      odbidx_set_t *pidxset = pp->idxset;
+	      if (i == 0) {
+		for (js=0; js<nsets; js++) {
+		  /* Please note that these "idxsets" are considered to be mutually exclusive */
+		  int jr, ndata = pidxset->ndata;
+		  for (jr=0; jr<ndata; jr++) {
+		    int curidx = (int)pidxset->idxdata[jr];
+		    picked[curidx] = 1;
+		    min_picked = MIN(min_picked, curidx);
+		    max_picked = MAX(max_picked, curidx);
+		  } /* for (jr=0; jr<ndata; jr++) */
+		  ++pidxset;
+		} /* for (js=0; js<nsets; js++) */
+	      }
+	      else { /* i > 0 */
+		/* Here we choose only those which are still in "picked[]"-list ;
+		   This is due to the AND'ing of the WHERE-stmts */
+		int lc_min_picked = INT_MAX;
+		int lc_max_picked = -1;
+		Bool found_any = false;
+
+		if (!lc_picked) ALLOC(lc_picked, Nrows);
+		memset(lc_picked, 0, Nrows * sizeof(*lc_picked));
+
+		for (js=0; js<nsets; js++) {
+		  int jr, ndata = pidxset->ndata;
+		  for (jr=0; jr<ndata; jr++) {
+		    int curidx = (int)pidxset->idxdata[jr];
+		    if (curidx >= min_picked && 
+			curidx <= max_picked &&
+			picked[curidx] == 1) {
+		      lc_picked[curidx] = 1;
+		      lc_min_picked = MIN(lc_min_picked, curidx);
+		      lc_max_picked = MAX(lc_max_picked, curidx);
+		      found_any = true;
+		    }
+		  } /* for (jr=0; jr<ndata; jr++) */
+		  ++pidxset;
+		} /* for (js=0; js<nsets; js++) */
+
+		if (found_any) {
+		  min_picked = MAX(min_picked, lc_min_picked);
+		  max_picked = MIN(max_picked, lc_max_picked);
+		}
+		else {
+		  min_picked = Nrows;
+		  max_picked = -1;
+		  goto stop_search_now;
+		}
+
+		/* for (j=0; j<min_picked; j++) picked[j] = 0; */
+		for (j=min_picked; j<=max_picked; j++) picked[j] = lc_picked[j];
+		/* for (j=max_picked+1; j<Nrows; j++) picked[j] = 0; */
+	      }
+	      wl++;
+	    } /* for (i=0; i<nwl; i++) */
+
+	  stop_search_now:
+	    FREE(lc_picked);
+
+	    if (min_picked <= max_picked) {
+	      for (j=min_picked; j<=max_picked; j++) {
+		if (picked[j]) t->skiprow[j] = 2; /* 2 == do *NOT* skip this row, found via IDXF */
+	      }
+	    }
+	    
+	    FREE(picked);
+	  }
+	  else if (nwl == 1) {
+	    /* Just one simple WHERE-condition ; no IDXF */
+	    double rhs = wl->rhs;
+	    if (IS_HASH(wl->lhs)) {
+	      switch (wl->oper) {
+	      case EQ: FILL_SKIPROW_USING_ROWID(==); break;
+	      case NE: FILL_SKIPROW_USING_ROWID(!=); break;
+	      case GT: FILL_SKIPROW_USING_ROWID(> ); break;
+	      case GE: FILL_SKIPROW_USING_ROWID(>=); break;
+	      case LT: FILL_SKIPROW_USING_ROWID(< ); break;
+	      case LE: FILL_SKIPROW_USING_ROWID(<=); break;
+	      default: INIT_SKIPROW(1); break;
+	      } /* switch (wl->oper) */
+	    }
+	    else {
+	      double *lhs = wl->wcol->dinp;
+	      switch (wl->oper) {
+	      case EQ: FILL_SKIPROW(==); break;
+	      case NE: FILL_SKIPROW(!=); break;
+	      case GT: FILL_SKIPROW(> ); break;
+	      case GE: FILL_SKIPROW(>=); break;
+	      case LT: FILL_SKIPROW(< ); break;
+	      case LE: FILL_SKIPROW(<=); break;
+	      default: INIT_SKIPROW(1); break;
+	      } /* switch (wl->oper) */
+	    }
+	  }
+	  else {
+	    /* More than one AND'ed WHERE-conditions ; no IDXF */
+	    for (j=0; j<Nrows; j++) {
+	      Bool and_cond = true;
+	      wl = t->wl;
+	      for (i=0; i<nwl && and_cond; i++) {
+		double lhs = IS_HASH(wl->lhs) ? (double)(j+1) : wl->wcol->dinp[j];
+		double rhs = wl->rhs;
+		switch (wl->oper) {
+		case EQ: and_cond = (lhs == rhs) ? true : false; break;
+		case NE: and_cond = (lhs != rhs) ? true : false; break;
+		case GT: and_cond = (lhs >  rhs) ? true : false; break;
+		case GE: and_cond = (lhs >= rhs) ? true : false; break;
+		case LT: and_cond = (lhs <  rhs) ? true : false; break;
+		case LE: and_cond = (lhs <= rhs) ? true : false; break;
+		default: and_cond = false; break;
+		} /* switch (wl->oper) */
+		wl++;
+	      } /* for (i=0; i<nwl && and_cond; i++) */
+	      t->skiprow[j] = and_cond ? 0 : 1;
+	    } /* for (j=0; j<Nrows; j++) */
+	  } /* if (wl->stored_idx) ... else if (nwl == 1) ... else ... */
+	}
+	else {
+	  /* Switch off the simple WHERE-cond tracking */
+	  t->simple_wherecond = false;
+	} /* if (errlfg == 0) ... else ... */
+      }
+
+      for (jr=lo; jr<hi; jr++) {
+	double val = 1; /* The same as if WHERE was empty i.e. "true" all the time */
+	t->jr = jr;
+
+	if (t->skiprow) {
+	  if (t->skiprow[jr] == 1) {
+	    /* Reject this row */
+	    val = 0;
+	    continue; /* for (jr=lo; jr<hi; jr++) */
+	  }
+	  else if (t->skiprow[jr] == 2) {
+	    /* This row selected due to IDXF-data */
+	    val = 1;
+	    goto go_deeper;
+	  }
+	}
+	else if (t->wherecond_and_ptree) {
+	  int j, iret = 0;
+	  int nwhere = info->nwhere;
+	  for (j=0; j<nwhere; j++) {
+	    col_t *colthis = &info->w[j];
+	    const char *s = colthis->name;
+	    table_t *tc = colthis->t;
+	    if (!tc) continue;
+	    if (tc->table_id > maxfrom) continue;
+	    if (!colthis->dsym) {
+	      if (IS_HASH(s)) {
+		/* '#table_name' == ROW-number [1..Nrows] */
+		colthis->dsym = putsym(s, tc->jr + 1);
+	      }
+	      else {
+		/* Ordinary columns 'colname at table' */
+		const char *sf = colthis->fetch_name;
+		int Nrows;
+		colthis->dinp = DCA_fetch_double(ph->h, ph->dbname, tc->name, sf,
+						 poolno, NULL, 0, &Nrows);
+		if (Nrows != tc->nrows) {
+		  COLUMN_FETCH_ERROR();
+		  RAISE(SIGABRT);
+		}
+		else {
+		  Bool thesame = strequ(s,sf) ? true : false;
+		  DEPTH_TABS(fp_echo, depth);
+		  ODB_fprintf(fp_echo,
+			      "%s:%d: Successfully fetched (double) %s%s%s (Nrows=%d/%d) : poolno#%d\n",
+			      __FILE__, __LINE__,
+			      thesame ? s : sf,
+			      thesame ? "" : " alias ",
+			      thesame ? (const char *)"" : s,
+			      Nrows, tc->nrows, poolno);
+		  colthis->dinp_len = Nrows;
+		  colthis->dinp_alloc = true;
+		  if (colthis->dtnum == DATATYPE_INT4 && 
+		      colthis->bitpos >= 0 && colthis->bitpos <  MAXBITS &&
+		      colthis->bitlen >= 1 && colthis->bitlen <= MAXBITS) {
+		    ODBc_vget_bits(colthis->dinp, colthis->dinp_len, colthis->bitpos, colthis->bitlen);
+		  }
+		}
+		if (colthis->dinp && tc->jr >= 0 && tc->jr < tc->nrows) {
+		  /* Extra safeguarding */
+		  colthis->dsym = putsymvec(s, colthis->dinp[tc->jr], colthis->dinp, Nrows);
+		}
+		else {
+		  colthis->dsym = putsym(s, mdi);
+		}
+	      }
+	    }
+	    else {
+	      if (IS_HASH(s)) {
+		*colthis->dsym = tc->jr + 1;
+	      }
+	      else {
+		if (colthis->dinp && tc->jr >= 0 && tc->jr < tc->nrows) {
+		  /* Extra safeguarding */
+		  *colthis->dsym = colthis->dinp[tc->jr];
+		}
+		else {
+		  *colthis->dsym = mdi;
+		}
+	      }
+	    }
+	    
+	  } /* for (j=0; j<nwhere; j++) */
+
+	  if (!t->skiprow) {
+	    val = RunTree(t->wherecond_and_ptree, NULL, &iret);
+	    if (iret != 0) {
+	      fprintf(stderr,
+		      "***Error: Unable to evaluate the WHERE-conditions AND-part '%s'\n",
+		      t->wherecond_and);
+	      RAISE(SIGABRT);
+	    }
+	  }
+	  /* otherwise val = 1, since t->skiprow && t->skiprow[jr] == 0 or 2 */
+	} /* if (t->wherecond_and_ptree) */
+	
+      go_deeper:
+	if (val != 0) {
+	  /* Go deeper ... */
+	  DEPTH_TABS(fp_echo, depth);
+	  ODB_fprintf(fp_echo, 
+		      "%s:%d: val=%.14g, tbl=[%s #%d lo=%d ob=%d jr=%d]\n",
+		      __FILE__, __LINE__,
+		      val, t->name, t->nrows, t->lo, t->ob, t->jr);
+	  rc += HSL(ph, info, t->next, poolno, immed_return, depth+1);
+	}
+	if (immed_return && *immed_return) break; /* Stop searching now !! */
+      } /* for (jr=lo; jr<hi; jr++) */
+    }
+    else {
+      rc = 0; /* Don't go for this at all ; probably "insane" */
+    }
+  }
+  /* if (t && ph && info) ... */
+  else {
+    /* (usually) take this row & update all indices */
+    if (info) {
+      const int ichunk = 65536; /* A fixed idx[] (re-)alloc chunk increment for now */
+      t = info->t;
+      if (t) {
+	FILE *fp_echo = ODBc_get_debug_fp();
+	int icnt = 0;
+	int idxlen = info->idxlen;
+	int idxalloc = info->idxalloc;
+	while (t) {
+	  if (t->in_select_clause) {
+	    if (idxalloc <= idxlen) REALLOC(t->idx, idxalloc + ichunk);
+	    t->idx[idxlen] = t->jr;
+	  }
+	  if (fp_echo) {
+	    DEPTH_TABS(fp_echo, depth);
+	    ODB_fprintf(fp_echo, 
+			"%s:%d: #<%d> tbl(idx=%d)=[%s #%d lo=%d ob=%d jr=%d]\n",
+			__FILE__, __LINE__, icnt,
+			t->in_select_clause ? idxlen : -1,
+			t->name, t->nrows, t->lo, t->ob, t->jr);
+	  }
+	  t = t->next;
+	  if (fp_echo) ++icnt;
+	} /* while (t) */
+	if (idxalloc <= idxlen) info->idxalloc += ichunk;
+	rc = 1;
+      }
+      else if (info->wherecond) { /* No tables, but may still have a WHERE-condition */
+	int iret = 0;
+	double val = RunTree(info->wherecond_ptree, NULL, &iret);
+	if (iret != 0) {
+	  fprintf(stderr,
+		  "***Error: Unable to evaluate the WHERE-condition '%s'\n",
+		  info->wherecond);
+	  RAISE(SIGABRT);
+	}
+	rc = (val != 0) ? 1 : 0;
+      }
+      else { /* No tables, no WHERE-condition (implies "true") */
+	rc = 1; /* Take this -- unconditionally */
+      }
+      if (rc == 1) {
+	*info->idxlen_dsym = ++(info->idxlen); /* For use by ODB_maxrows/ODB_maxcount */
+      }
+    }
+    else {
+      rc = 0; /* Do *NOT* take this */
+    }
+  }
+  if (immed_return && info && info->__maxcount__) {
+    /* This will effectively stop searching right now and there !! */
+    if (info->idxlen >= *info->__maxcount__) *immed_return = true;
+  }
+  return rc;
+}
+
+
+PRIVATE void
+InitCols(col_t *c)
+{
+  DRHOOK_START(InitCols);
+  if (c) {
+    DEF_IT;
+    (void) delsym(c->name, it);
+    if (c->dinp_alloc) FREE(c->dinp);
+    c->dinp = NULL;
+    c->dinp_len = 0;
+    c->dinp_alloc = false;
+    c->dsym = NULL;
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+InitTables(table_t *t)
+{
+  DRHOOK_START(InitTables);
+  while (t) {
+    t->jr = -1;
+    t->lo =  0;
+    t->ob = -1;
+    t->nrows = 0;
+    t->ncols = 0;
+    FREE(t->offset);
+    FREE(t->len);
+    FREE(t->idx);
+    FREE(t->skiprow);
+    t = t->next;
+  } /* while (t) */
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void *
+ODBc_reset_info(void *Info)
+{
+  DRHOOK_START(ODBc_reset_info);
+  if (Info) {
+    info_t *info = Info;
+    int j;
+    for (j=0; j<info->ncols; j++) {
+      col_t *colthis = &info->c[j];
+      InitCols(colthis);
+    }
+    for (j=0; j<info->nwhere; j++) {
+      col_t *colthis = &info->w[j];
+      InitCols(colthis);
+    }
+    InitTables(info->t);
+    info->idxalloc = 0;
+    info->idxlen = 0;
+    info->idxlen_dsym = putsym(_ROWNUM, info->idxlen);
+    if (info->dyn && info->ndyn > 0) {
+      dyn_t *dyn = info->dyn;
+      int j, ndyn = info->ndyn;
+      for (j=0; j<ndyn; j++) {
+	FREE(dyn->data);
+	dyn->ndata = 0;
+	putsym(dyn->name, 0);
+	dyn++;
+      } /* for (j=0; j<ndyn; j++) */
+    }
+  }
+  DRHOOK_END(0);
+  return Info;
+}
+
+
+PRIVATE void
+GetMinMax(const double d[], int n, double *Min, double *Max)
+{
+  DRHOOK_START(GetMinMax);
+  if (Min && Max) {
+    *Min = mdi; /* Note: from info.h ==> const double mdi = ABS(RMDI); */
+    *Max = 0;
+    if (d && n > 0) {
+      int j;
+      *Min = d[0];
+      *Max = d[0];
+      for (j=1; j<n; j++) {
+	if (ABS(d[j]) != mdi) {
+	  if (*Min > d[j]) *Min = d[j];
+	  if (*Max < d[j]) *Max = d[j];
+	}
+      } /* for (j=1; j<n; j++) */
+    }
+  }
+  DRHOOK_END(0);
+}
+
+
+PUBLIC int
+ODBc_sql_exec(int handle, void *Info, int poolno, int *Begin_row, int *End_row)
+{
+  int nrows = -1;
+  info_t *info = Info;
+  DRHOOK_START(ODBc_sql_exec);
+  if (info) {
+    FILE *fp_echo = ODBc_get_debug_fp();
+    if (free_handles && handle >= 1 && handle <= maxhandle) {
+      DB_t *ph = &free_handles[handle-1];
+      if (ph->h == handle) {
+	int ntables = ph->ntables;
+	int begin_row = Begin_row ? *Begin_row : 0;
+	int end_row = End_row ? *End_row : -1;
+	Bool immed_return = false;
+	Bool poolno_okay;
+	int npools = ph->npools;
+	if (poolno <= 0 || poolno > npools) {
+	  ODB_fprintf(stderr, 
+		      "***Error in ODBc_sql_exec() of %s : poolno (%d) must be between"
+		      " %d and %d\n",
+		      info->view, poolno, 1, npools);
+	  nrows = -2;
+	  goto finish;
+	}
+
+	poolno_okay = ODB_in_permanent_poolmask(handle, poolno) ? true : false;
+	if (!poolno_okay) {
+	  ODB_fprintf(fp_echo,
+		      "***Warning in ODBc_sql_exec() of %s : Pool number %d not in poolmask\n",
+		      info->view, poolno);
+	  nrows = 0; /* Not an error */
+	  goto finish;
+	}
+
+	if (!info->dca_alloc) {
+	  const table_t *t = info->t;
+	  while (t) {
+	    int iret = 0;
+	    (void) DCA_alloc(handle, ph->dbname, t->name, &iret);
+	    t = t->next;
+	  }
+	  info->dca_alloc = true;
+
+	  {
+	    DEF_IT; /* see privpub.h; defines "it" as current (my) YOMOML thread id >= 1 && <= inumt */
+	    delallsym(&it); /* Clean-up symbol table for this thread only */
+	  }
+
+	  info->__maxcount__ = putsym("$__maxcount__", mdi);  /* ODBTk's $__maxcount__ */
+	  if (info->s && info->nset > 0) {
+	    /* Set values of $-variables */
+	    int j;
+	    for (j=0; j<info->nset; j++) {
+	      /* One of these may override "$__maxcount__" as well */
+	      (void) putsym(info->s[j].name, info->s[j].value);
+	    }
+	  }
+
+	  if (info->s2d && info->ns2d > 0) {
+	    /* Install Hollerith-strings */
+	    int j;
+	    for (j=0; j<info->ns2d; j++) {
+	      (void) putsym(info->s2d[j].name, info->s2d[j].u.dval);
+	    }
+	  }
+
+	  if (!info->has_ll && info->odb_lat->t && info->odb_lon->t) {
+	    info->has_ll = true;
+	  }
+
+	  if (info->has_ll /* && (info->latlon_rad == -1 || !getenv("ODB_LATLON_RAD")) */) {
+	    /* Handle setup for use of lldegrees()/llradians() */
+	    if (info->odb_lat->t && info->odb_lon->t) {
+	      /* References to $ODB_LAT & $ODB_LON indeed exists;
+		 Now poll their raw value range (for this poolno only) and (reset) latlon_rad */
+	      int j, errflg = 0;
+	      const double abs_range[2] = { half_pi, pi }; /* [0] for lat & [1] for lon, respectively */
+	      const double eps = (double)0.01e0;
+	      int rad_score = 0;
+	      int deg_score = 0;
+	      col_t *cc[2];
+	      cc[0] = info->odb_lat;
+	      cc[1] = info->odb_lon;
+
+	      for (j=0; j<2; j++) {
+		int Nrows;
+		col_t *colthis = cc[j];
+		const char *s = colthis->name;
+		const char *sf = colthis->fetch_name ? colthis->fetch_name : s;
+		table_t *tc = colthis->t;
+		InitNrowsNcols(ph, info, tc, poolno);
+		colthis->dinp = DCA_fetch_double(ph->h, ph->dbname, tc->name, sf,
+						 poolno, NULL, 0, &Nrows);
+		if (Nrows != tc->nrows) {
+		  /* Don't abort */
+		  COLUMN_FETCH_WARNING();
+		  errflg++;
+		  break; /* for (j=0; j<2; j++) */
+		}
+		else {
+		  double Min, Max;
+		  Bool thesame = strequ(s,sf) ? true : false;
+		  ODB_fprintf(fp_echo,
+			      "%s:%d: Successfully fetched (double) %s%s%s (Nrows=%d/%d) : poolno#%d\n",
+			      __FILE__, __LINE__,
+			      thesame ? s : sf,
+			      thesame ? "" : " alias ",
+			      thesame ? (const char *)"" : s,
+			      Nrows, tc->nrows, poolno);
+		  colthis->dinp_len = Nrows;
+		  colthis->dinp_alloc = true;
+		  colthis->dsym = putsymvec(s, colthis->dinp ? *colthis->dinp : mdi, colthis->dinp, Nrows);
+		  if (Nrows > 0) {
+		    GetMinMax(colthis->dinp, Nrows, &Min, &Max);
+		    if (Min > Max) {
+		      /* Values do not make sense */
+		      errflg++;
+		      break; /* for (j=0; j<2; j++) */
+		    }
+		    if (ABS(Min) < abs_range[j] && ABS(Max) < abs_range[j]) {
+		      /* We have radians */
+		      rad_score++;
+		    }
+		    else {
+		      deg_score++;
+		    }
+		  } /* if (Nrows > 0) */
+		}
+	      } /* for (j=0; j<2; j++) */
+
+	      if (!errflg) {
+		if (rad_score == 2) {
+		  info->latlon_rad = 1;
+		}
+		else if (deg_score == 2) {
+		  info->latlon_rad = 0;
+		}
+		else {
+		  info->latlon_rad = -1;
+		}
+		codb_change_latlon_rad_(&info->latlon_rad);
+	      }
+	      else {
+		fprintf(stderr,
+			"***Warning: Unable to determine whether"
+			" latitudes/longitudes were in degrees or radians\n");
+	      }
+	    } /* if (info->odb_lat->t && info->odb_lon->t) */
+	  } /* if (info->has_ll && !getenv("ODB_LATLON_RAD")) */
+	  if (info->has_ll) {
+	    ODB_fprintf(fp_echo,"ODBc_sql_exec() : info->latlon_rad = %d\n",info->latlon_rad);
+	  }
+	} /* if (!info->dca_alloc) */
+
+	info = ODBc_reset_info(info);
+
+	if (begin_row >= 1) {
+	  (void) putsym(BEGIN_ROW, begin_row);
+	}
+
+	if (info->__maxcount__ && *info->__maxcount__ >= 0 && end_row < 0) {
+	  end_row = *info->__maxcount__;
+	  if (End_row) *End_row = end_row;
+	}
+
+	if (end_row >= 0) {
+	  /* Override the current value of $__maxcount__ */
+	  info->__maxcount__ = putsym("$__maxcount__", end_row);
+	  (void) putsym(END_ROW, end_row);
+	}
+
+	ODB_fprintf(fp_echo, 
+		    "ODBc_sql_exec() : Poolno#%d : info->__maxcount__ = %p, "
+		    "*info->__maxcount__ = %.14g, end_row = %d, *End_row = %.14g\n",
+		    poolno, info->__maxcount__, 
+		    info->__maxcount__ ? *info->__maxcount__ : mdi,
+		    end_row, End_row ? (double) *End_row : mdi);
+
+	(void) putsym("$#", poolno); /* POOLNO */
+	(void) putsym(_POOLNO, poolno); /* POOLNO as well (an alias) */
+
+	(void) putsym(_NPOOLS, npools); /* NPOOLS */
+	(void) putsym(_NTABLES, ntables); /* NTABLES */
+
+	(void) putsym(_UNIQNUM, 0);
+
+	/*
+	(void) putsym(_ROWNUM, 0);
+	(void) putsym(_COLNUM, 0);
+	(void) putsym(_NROWS, 0);
+	*/
+
+	(void) putsym(_NCOLS, info->ncols_true);
+
+	{
+	  table_t *t = info->t;
+	  while (t) {
+	    InitNrowsNcols(ph, info, t, poolno);
+	    t = t->next;
+	  }
+	}
+
+	if ((info->optflags & 0x1) == 0x1) {
+	  /* A special case : SELECT count(*) FROM table */
+	  nrows = 1;
+	}
+	else if (info->t) {
+	  table_t *t = info->t;
+	  while (t) {
+	    /* 
+	       Look for the first table in FROM-hierarchy which has nrows > 0.
+	       This becomes the starting table for this "poolno".
+	       Note: The generated C-code -approach currently differs and it bases
+	       its search from full FROM-hierarchy i.e. also for tables nrows == 0
+	    */
+	    if (t->nrows > 0) break;
+	    /* Since t->nrows == 0 ... */
+	    t->jr = 0;
+	    t->lo = 0;
+	    t = t->next;
+	  }
+	  immed_return = false;
+	  nrows = t ? HSL(ph, info, t, poolno, &immed_return, 0) : 0;
+	}
+	else {
+	  /* TABLE-less query */
+	  immed_return = false;
+	  nrows = HSL(ph, info, NULL, poolno, &immed_return, 0);
+	}
+
+	ODB_fprintf(fp_echo,
+		    "ODBc_sql_exec() : Poolno#%d : nrows = %d : immed_return = %s\n",
+		    poolno,nrows,immed_return ? "true" : "false");
+      }
+      else {
+	/* Handle not in use */
+	ODB_fprintf(stderr, "***Error in ODBc_sql_exec() : Handle %d not in use\n",handle); 
+	nrows = -4;
+      }
+    }
+    else {
+      /* Invalid handle */
+      ODB_fprintf(stderr, "***Error in ODBc_sql_exec() : Invalid handle %d\n",handle); 
+      nrows = -3;
+    }
+  }
+ finish:
+  DRHOOK_END(nrows);
+  return nrows;
+}
diff --git a/odb/src/aux/history.c b/odb/src/aux/history.c
new file mode 100644
index 0000000..27658c6
--- /dev/null
+++ b/odb/src/aux/history.c
@@ -0,0 +1,209 @@
+
+/* history.c */
+
+#include "history.h"
+
+
+typedef struct _hist_tt {
+  char *cmd;
+  int Date;
+  int Time;
+  struct _hist_tt *prev;
+  struct _hist_tt *next;
+} hist_tt;
+
+
+static hist_tt History = { "", 0, 0, NULL, NULL };
+static hist_tt *curHistory = &History;
+static hist_tt *lastHistory = &History;
+
+
+PUBLIC void
+ResetHistory()
+{
+  curHistory = lastHistory;
+}
+
+
+PUBLIC const char *
+AddHistory(const char *cmd, const int *Date, const int *Time)
+{
+  if (cmd && STRLEN(cmd) > 0) {
+    char *p;
+    char *hcmd = STRDUP(cmd);
+    hist_tt *h = NULL;
+    CALLOC(h, 1);
+
+    /* Change non-printable chars into blanks */
+    p = hcmd;
+    while (*p) {
+      if (!isprint(*p)) *p = ' ';
+      p++;
+    }
+
+    /* Strip leading blanks */
+    p = hcmd;
+    while (isspace(*p)) {
+      p++;
+    }
+
+    h->cmd = STRDUP(p);
+    FREE(hcmd);
+
+    if (Date && Time) {
+      h->Date = *Date;
+      h->Time = *Time;
+    }
+    else {
+      char buf[80];
+      time_t tp;
+      time(&tp);
+      strftime(buf, sizeof(buf), "%Y%m%d %H%M%S", localtime(&tp));
+      sscanf(buf,"%d %d", &h->Date, &h->Time);
+    }
+    h->prev = lastHistory;
+    lastHistory->next = h;
+    lastHistory = h;
+    ResetHistory();
+    return h->cmd;
+  }
+  else
+    return NULL;
+}
+
+
+PUBLIC const char *
+GetHistory(int next)
+{
+  hist_tt *h = NULL;
+  if (next > 0) {
+    h = curHistory->next;
+    if (h) curHistory = h;
+  }
+  else {
+    h = curHistory;
+    if (curHistory->prev) curHistory = curHistory->prev;
+  }
+  return h ? h->cmd : NULL;
+}
+
+
+PUBLIC void
+PrintHistory(FILE *fp)
+{
+  const hist_tt *h = &History;
+  if (h && fp) {
+    h = h->next; /* Skip the first one (from static memory) */
+    while (h) {
+      if (STRLEN(h->cmd) > 0) {
+	fprintf(fp, "%8.8d %6.6d %s\n", h->Date, h->Time, h->cmd);
+      }
+      h = h->next;
+    }
+    fflush(fp);
+  }
+}
+
+
+#define SET_FILENAME(name) \
+  FILE *fp; \
+  char *filename; \
+  char *env = getenv("HOME"); \
+  if (!env) env = "."; \
+  ALLOC(filename, STRLEN(env) + STRLEN(name) + 2); \
+  sprintf(filename,"%s/%s",env,name)
+
+
+PUBLIC char *
+LoadHistory(const char *name)
+{
+  SET_FILENAME(name);
+  fp = fopen(filename,"r");
+  if (fp) {
+    int nlines = 0;
+    char buf[4096];
+    while (fgets(buf, sizeof(buf), fp)) {
+      int Date, Time;
+      char *p = strchr(buf,'\n');
+      if (p) *p = 0;
+      if (sscanf(buf,"%d %d", &Date, &Time) == 2) {
+	p = buf + 16;
+	if (AddHistory(p,&Date,&Time)) nlines++;
+      }
+    }
+    fclose(fp);
+  }
+  return filename;
+}
+
+
+PUBLIC char *
+SaveHistory(const char *name, int nlastlines)
+{
+  SET_FILENAME(name);
+  fp = fopen(filename,"w");
+  if (fp) {
+    const hist_tt *h = NULL;
+    int *num = NULL;
+    int maxcnt;
+    int cnt = 0;
+    h = &History;
+    if (h) {
+      h = h->next; /* Skip the first one (from static memory) */
+      while (h) {
+	if (STRLEN(h->cmd) > 0) {
+	  cnt++;
+	}
+	h = h->next;
+      } /* while (h) */
+    } /* if (h) */
+    maxcnt = cnt;
+    ALLOC(num, maxcnt);
+    cnt = 0;
+    h = &History;
+    if (h) {
+      h = h->next; /* Skip the first one (from static memory) */
+      while (h) {
+	if (STRLEN(h->cmd) > 0) {
+	  num[cnt] = maxcnt - cnt;
+	  cnt++;
+	}
+	h = h->next;
+      } /* while (h) */
+    } /* if (h) */
+    h = &History;
+    cnt = 0;
+    if (h) {
+      h = h->next; /* Skip the first one (from static memory) */
+      while (h) {
+	if (STRLEN(h->cmd) > 0) {
+	  if (num[cnt] <= nlastlines) {
+	    fprintf(fp, "%d %d %s\n", h->Date, h->Time, h->cmd);
+	  }
+	  cnt++;
+	}
+	h = h->next;
+      } /* while (h) */
+    } /* if (h) */
+    FREE(num);
+    fclose(fp);
+  }
+  return filename;
+}
+
+
+PUBLIC void
+DelHistory()
+{
+  hist_tt *h = &History;
+  if (h) {
+    h = h->next; /* Skip the first one (from static memory) */
+    while (h) {
+      hist_tt *save_h = h;
+      FREE(h->cmd);
+      FREE(h);
+      h = save_h->next;
+    } /* while (h) */
+    lastHistory = curHistory = &History;
+  } /* if (h) */
+}
diff --git a/odb/src/aux/idx.c b/odb/src/aux/idx.c
new file mode 100644
index 0000000..f7e1bd6
--- /dev/null
+++ b/odb/src/aux/idx.c
@@ -0,0 +1,2031 @@
+
+/* idx.c */
+
+/* Under development as of 1-Jan-2006 */
+/* Lots of new meat under the skin as of 8-Jun-2007 ;-) */
+
+#include "odb.h"
+#include "odbmd5.h"
+#include "idx.h"
+#include "info.h"
+#include "cmaio.h"
+#include "result.h"
+#include "magicwords.h"
+#include "swapbytes.h"
+#include "pcma_extern.h"
+#include "bits.h"
+#include "evaluate.h"
+#include "cdrhook.h"
+
+/* 
+   CREATE [UNIQUE|DISTINCT|BITMAP] INDEX idxname 
+   ON tblname 
+   [( colname(s) )] 
+   [WHERE condition] 
+   ; 
+*/
+
+
+PRIVATE char *MergeStr(const char *a, const char *delim, const char *b)
+{
+  char *s = NULL;
+  DRHOOK_START(MergeStr);
+  {
+    int len = STRLEN(a) + STRLEN(delim) + STRLEN(b) + 1;
+    ALLOC(s, len);
+    snprintf(s, len, "%s%s%s",
+	     a ? a : "",
+	     delim ? delim : "",
+	     b ? b : "");
+  }
+  DRHOOK_END(0);
+  return s;
+}
+
+
+PUBLIC int codb_IDXF_drop(void *Info)
+{
+  int rc = 0;
+  info_t *info = Info;
+  DRHOOK_START(codb_IDXF_drop);
+  if (info && info->ph) {
+    const char *idxpath = info->ph->idxpath ? info->ph->idxpath : "idx";
+    const char *idxname = info->use_index_name ? info->use_index_name : "*";
+    int nfrom = info->nfrom;
+    table_t *t = info->t;
+    do {
+      int iret = 0;
+      const char *tblname = t ? t->name : "*";
+      char *cmd = NULL;
+      int len = STRLEN(idxpath) + STRLEN(tblname) + STRLEN(idxname) + 30;
+      ALLOC(cmd, len);
+      snprintf(cmd, len, "rm -f %s/%s/%s.* < /dev/null", idxpath, tblname, idxname);
+      iret = system(cmd);
+      FREE(cmd);
+      if (t) t = t->next;
+      if (iret == 0) ++rc;
+    } while (t);
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PRIVATE char *
+RemoveWhiteSpace(const char *in)
+{
+  char *s = NULL;
+  int slen = STRLEN(in);
+  if (slen > 0) {
+    const char *p = in;
+    char *ps;
+    int quote_char = 0;
+    Bool in_quote = false;
+    ALLOC(s, slen+1);
+    ps = s;
+    while (*p) {
+      if (in_quote || !isspace(*p)) {
+	*ps++ = *p;
+      }
+      if (!in_quote && (*p == '"' || *p == '\'')) {
+	in_quote = true;
+	quote_char = *p;
+      }
+      else if (in_quote && *p == quote_char) {
+	in_quote = false;
+	quote_char = 0;
+      }
+      ++p;
+    }
+    *ps = '\0';
+  }
+  else
+    s = STRDUP(in);
+  return s;
+}
+
+
+PUBLIC char *
+codb_IDXF_filename(Bool create_name,
+		   const char *idxpath,
+		   const char *tblname, 
+		   const char *idxname,
+		   int ncols,
+		   const char *colnames,
+		   const char *wherecond,
+		   const char *filesuffix)
+{
+  char *name = NULL;
+  DRHOOK_START(codb_IDXF_filename);
+  {
+    const char *any = create_name ? "ANY" : "*";
+
+    const char *m1 = colnames;
+    char *md5sum_m1 = NULL;
+
+    const char *m2 = wherecond;
+    char *md5sum_m2 = NULL;
+
+    char *merge = NULL;
+
+    unsigned char sign[16];
+
+    /* Handle column names */
+
+    if (ncols <= 0 || strequ(colnames,"*")) m1 = NULL;
+    if (m1) {
+      char *mpp = RemoveWhiteSpace(m1);
+      if (MD5_str2sign(mpp, sign) == 0) {
+	md5sum_m1 = MD5_sign2hex(sign, 0); /* STRDUP'ped, no lowercase hex */
+      }
+      else {
+	fprintf(stderr,
+		"***Error in codb_IDXF_filename(): Unable to obtain md5sum on colnames '%s'\n",m1);
+	RAISE(SIGABRT);
+      }
+      FREE(mpp);
+    }
+    else {
+      md5sum_m1 = STRDUP(any); /* Any set of columns */
+    }
+
+    /* Handle WHERE-condition */
+
+    if (!wherecond && create_name) m2 = "1";
+    if (m2) {
+      char *mpp = RemoveWhiteSpace(m2);
+      if (MD5_str2sign(mpp, sign) == 0) {
+	md5sum_m2 = MD5_sign2hex(sign, 0); /* STRDUP'ped, no lowercase hex */
+      }
+      else {
+	fprintf(stderr,
+		"***Error in codb_IDXF_filename(): Unable to obtain md5sum on wherecond '%s'\n",m2);
+	RAISE(SIGABRT);
+      }
+      FREE(mpp);
+    }
+    else {
+      md5sum_m2 = STRDUP(any); /* Any WHERE-statement */
+    }
+
+    merge = MergeStr(md5sum_m1, ".", md5sum_m2);
+
+    FREE(md5sum_m1);
+    FREE(md5sum_m2);
+
+    if (tblname && *tblname == '@') ++tblname;
+
+    if (!idxpath && !tblname && !idxname && merge) {
+      name = STRDUP(merge);
+    }
+    else {
+      char numstr[40];
+      int len = 1;
+      len += STRLEN(idxpath) + 1;
+      len += STRLEN(tblname) + 1;
+      len += STRLEN(idxname ? idxname : any) + 1;
+      if (ncols >= 0) {
+	snprintf(numstr,sizeof(numstr),"%d",ncols);
+      }
+      else {
+	strcpy(numstr,any);
+      }
+      len += STRLEN(numstr) + 1;
+      len += STRLEN(merge) + 1;
+      len += STRLEN(filesuffix);
+      ALLOC(name, len);
+      /* 
+	 Create index-file name ==> It becomes usually :
+	 $ODB_IDXPATH_<dbname>/<tablename>/<indexname>.<ncols>.<md5sum_of_colnames>.<md5sum_of_wherecond>.gz
+	 The $ODB_IDXPATH_<dbname> is by default $ODB_SRCPATH_<dbname>/idx 
+
+	 The "merge"-string below is <md5sum_of_colnames>.<md5sum_of_wherecond>
+
+	 If colnames is empty, then <md5sum_of_colnames> is set to variable "any"
+	 If wherecond is empty or 1, then <md5sum_of_wherecond> is set to variable "any"
+      */
+      snprintf(name, len, "%s%s%s%s%s.%s.%s%s",
+	       idxpath ? idxpath : "", idxpath ? "/" : "",
+	       tblname ? tblname : "", tblname ? "/" : "",
+	       idxname ? idxname : any,
+	       numstr,
+	       merge,
+	       filesuffix ? filesuffix : "");
+    }
+
+    FREE(merge);
+  }
+  DRHOOK_END(0);
+  return name;
+}
+
+
+PUBLIC char *
+codb_IDXF_open(int *Io_idx, const char *filename, const char *mode)
+{
+  int rc = 0;
+  int io_idx = -1;
+  char *filename_out = NULL;
+  DRHOOK_START(codb_IDXF_open);
+  if (Io_idx) {
+    if (mode && *mode == 'r' && strchr(filename,'*')) {
+      /* Wildcard found --> search for the most up to date filename */
+      FILE *fp;
+      char *cmd;
+      int len = STRLEN(filename) + 80;
+      ALLOC(cmd, len);
+      snprintf(cmd, len, "ls -C1t %s 2>/dev/null | head -1", filename);
+      fp = popen(cmd, "r");
+      if (fp) {
+	char *fullname;
+	len = STRLEN(filename) + 4096;
+	ALLOC(fullname, len);
+	if (fscanf(fp,"%s",fullname) == 1) {
+	  cma_open_(&io_idx, fullname, mode, &rc, STRLEN(fullname), STRLEN(mode));
+	  if (io_idx >= 0) filename_out = STRDUP(fullname);
+	}
+	FREE(fullname);
+	pclose(fp);
+      }
+      FREE(cmd);
+    }
+    else {
+      cma_open_(&io_idx, filename, mode, &rc, STRLEN(filename), STRLEN(mode));
+      if (io_idx >= 0) filename_out = STRDUP(filename);
+    }
+    *Io_idx = io_idx;
+  }
+  DRHOOK_END(0);
+  return filename_out; /* Watch for memory leakage */
+}
+
+
+PRIVATE int
+FreeIdxSets(odbidx_set_t *idxset, int nsets, int ncols)
+{
+  int rc = 0;
+  DRHOOK_START(FreeIdxSets);
+  if (idxset && nsets > 0) {
+    int j;
+    for (j=0; j<nsets; j++) {
+      FREE(idxset->value);
+      FREE(idxset->idxdata);
+      ++idxset;
+      ++rc;
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC void *
+codb_IDXF_freeidx(odbidx_t *idx, int recur)
+{
+  DRHOOK_START_RECUR(codb_IDXF_freeidx, recur);
+  if (idx) {
+    int ncols = idx->ncols;
+    int j, npools = idx->npools;
+    odbidx_pp_t *pp = idx->pp;
+    if (pp) {
+      for (j=0; j<npools; j++) {
+	(void) FreeIdxSets(pp->idxset, pp->nsets, ncols);
+	FREE(pp->idxset);
+	++pp;
+      }
+      FREE(idx->pp);
+    }
+    FREE(idx->filename);
+    FREE(idx->tblname);
+    FREE(idx->idxname);
+    FREE(idx->colnames);
+    FREE(idx->wherecond);
+    FREE(idx->dcard);
+    if (idx->next) idx->next = codb_IDXF_freeidx(idx->next, recur + 1);
+    FREE(idx);
+  }
+  DRHOOK_END_RECUR(0, recur);
+  return idx;
+}
+
+
+PUBLIC int
+codb_IDXF_close(int io_idx, odbidx_t *idx)
+{
+  int rc = 0;
+  DRHOOK_START(codb_IDXF_close);
+  cma_close_(&io_idx, &rc);
+  if (rc == 0 && idx) idx = codb_IDXF_freeidx(idx, 0);
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PRIVATE odbidx_t *
+IdxAllocAndFetch(odbidx_t *Idx,
+		 const char *filename,
+		 int handle,
+		 int *poolno_offset,
+		 int *retcode,
+		 int recur,
+		 int oper,
+		 const double *rhs)
+{
+  int rc = 0;
+  odbidx_t *idx = NULL;
+  DRHOOK_START_RECUR(IdxAllocAndFetch, recur);
+  if (filename && handle >= 0) {
+    int io_idx = -1;
+    char *true_filename = codb_IDXF_open(&io_idx, filename, "r");
+    if (true_filename && io_idx >= 0) {
+      if (Idx) idx = Idx; else ALLOC(idx, 1);
+      memset(idx, 0, sizeof(*idx));
+      idx->filename = STRDUP(true_filename);
+      rc = codb_IDXF_read(io_idx, idx, handle, poolno_offset, recur, oper, rhs);
+      (void) codb_IDXF_close(io_idx, NULL);
+    }
+    FREE(true_filename);
+  }
+  if (retcode) *retcode = rc;
+  DRHOOK_END_RECUR(0, recur);
+  return idx;
+}
+
+
+#define CMARD(x, n) \
+  opaque = x; nbytes = sizeof(*(x)) * (n); \
+  cma_readb_(&io_idx, opaque, &nbytes, &iret); \
+  if (byteswap) { \
+    int sz = sizeof(*(x)), nelem = n; \
+    void (*byteswap_func)(void *v, const int *vlen) = \
+      (sz == 4) ? swap4bytes_ : swap8bytes_; \
+    byteswap_func(opaque, &nelem); \
+  }
+
+#define CMARD_TFLAQUE(x, n) \
+  opaque = x; nbytes = sizeof(*(x)) * (n); \
+  cma_readb_(&io_idx, opaque, &nbytes, &iret); \
+  if (byteswap) { \
+    const int one_elem = 1; \
+    int je, sz = sizeof(*(x)), nelem = n; \
+    void (*byteswap_func)(void *v, const int *vlen) = \
+      (sz == 4) ? swap4bytes_ : swap8bytes_; \
+    for (je=0; je<nelem; je++) { \
+      if (tflaque[je] != 1) byteswap_func((x)+je, &one_elem); \
+    } \
+  }
+
+#define EAT_FF() \
+{ \
+  int c; \
+  while ((c = fgetc(fp)) != EOF) { \
+   if (c != '\f') { ungetc(c, fp); break; } \
+  } \
+}
+
+#define EAT_NL() \
+{ \
+  int c; \
+  while ((c = fgetc(fp)) != EOF) { \
+   if (c != '\n') { ungetc(c, fp); break; } \
+  } \
+}
+
+#define EAT_MONKEY(array, str, skip_1st) \
+ FREE(array); EAT_NL(); \
+ if (fgets(line, sizeof(line), fp)) { \
+   char *sl = line; \
+   while (isspace(*sl)) ++sl; \
+   { \
+     char *s = strchr(sl,'\n'); \
+     if (s) *s = '\0'; \
+     if (str) { s = strstr(sl, str); if (s) *s = '\0'; } \
+     if (skip_1st) { \
+       s = strchr(sl,' '); \
+      (array) = s ? STRDUP(s+1) : NULL; \
+     } else { (array) = STRDUP(sl); } \
+   } \
+ }
+
+#define EAT_GORILLA(array) EAT_MONKEY(array, NULL, 0)
+
+#define TAKESET(OP) takeset = (Lhs OP Rhs) ? true : false
+
+#define TAKESET_EVAL() { \
+  double Lhs = *pvalue; \
+  double Rhs = *rhs; \
+  switch (oper) { \
+  case EQ: TAKESET(==); break; \
+  case NE: TAKESET(!=); break; \
+  case GT: TAKESET(> ); break; \
+  case GE: TAKESET(>=); break; \
+  case LT: TAKESET(< ); break; \
+  case LE: TAKESET(<=); break; \
+  default: takeset = false; break; \
+ } /* switch (oper) */ \
+}
+
+#define MAKE_TFLAQUE() \
+if (ncols > 0 && ncols <= MAXBITS) { \
+  if (typeflag == 0) { \
+    memset(tflaque, 0, ncols * sizeof(*tflaque)); \
+  } \
+  else { \
+    int ii; \
+    for (ii=0; ii<ncols; ii++) { \
+      int is_string = (typeflag == 0) ? 0 : \
+	ODBIT_test(&typeflag, MAXBITS, MAXBITS, ii, ii); \
+      tflaque[ii] = is_string; \
+    } /* for (ii=0; ii<ncols; ii++) */ \
+  } \
+}
+
+
+PUBLIC int
+codb_IDXF_read(int io_idx, odbidx_t *idx,
+	       int handle, int *poolno_offset, int recur,
+	       int oper,
+	       const double *rhs)
+{
+  int rc = 0;
+  DRHOOK_START_RECUR(codb_IDXF_read, recur);
+  if (idx && io_idx >= 0) {
+    FILE *fp = CMA_get_fp(&io_idx);
+    if (fp) {
+      Bool last_pool_hit = false;
+      unsigned int idxf;
+      int binary;
+      Bool byteswap = false;
+      int info[8];
+      void *opaque;
+      int nbytes, iret;
+      int this_version;
+      int filekind;
+      char line[65536];
+      char *tmpline = NULL;
+      int j, poolno, npools;
+      unsigned int typeflag;
+      int ncols, npp, ncard;
+      int tflaque[MAXBITS];
+      
+      CMARD(&idxf, 1);
+
+      if (idxf == IDXB || idxf == BXDI) {
+	binary = 1;
+	byteswap = (idxf == BXDI) ? true : false;
+      }
+      else if (idxf == IDXT || idxf == TXDI) {
+	binary = 0;
+	byteswap = (idxf == TXDI) ? true : false;
+      }
+      else {
+	binary = -1;
+	fprintf(stderr,
+		"***Error: Invalid index file (%s) magic number %u\n",
+		idx->filename, idxf);
+	RAISE(SIGABRT);
+      }
+
+      EAT_GORILLA(tmpline);
+      sscanf(tmpline, "%d", &this_version);
+      EAT_GORILLA(tmpline);
+      sscanf(tmpline, "%d", &filekind);
+      FREE(tmpline);
+
+      if (filekind == 2) {
+	/* Create a chain odbidx_t's */
+	odbidx_t *start_idx = idx;
+	odbidx_t *cur_idx = start_idx;
+
+	while (!feof(fp)) {
+	  int iret = 0;
+	  odbidx_t *new_idx = NULL;
+	  char *filename = NULL;
+	  
+	  EAT_MONKEY(filename, NULL, 1);
+	  if (!filename) break; /* No more input --> most likely an EOF reached */
+
+	  new_idx = IdxAllocAndFetch(cur_idx, filename, 
+				     handle, poolno_offset, &iret, recur + 1, 
+				     oper, rhs);
+
+	  if (new_idx && new_idx->npools > 0 && iret > 0) {
+	    cur_idx->next = new_idx;
+	    cur_idx = new_idx;
+	    cur_idx->next = NULL;
+	    rc += iret;
+	  }
+
+	  FREE(filename);
+	} /* while (!feof(fp)) */
+	goto finish;
+      }
+
+      EAT_MONKEY(tmpline, NULL, 1); /* Original index-filename as it was written */
+      FREE(tmpline);
+
+      EAT_MONKEY(idx->tblname, NULL, 1);
+      EAT_MONKEY(idx->idxname, NULL, 1);
+      EAT_MONKEY(idx->colnames, NULL, 1);
+      EAT_MONKEY(idx->wherecond, NULL, 1);
+
+      EAT_NL();
+      EAT_FF();
+
+      if (binary) {
+	CMARD(info, 8);
+	idx->creation_date     = (yyyymmdd)info[0];
+	idx->creation_time     = (hhmmss)info[1];
+	idx->modification_date = (yyyymmdd)info[2];
+	idx->modification_time = (hhmmss)info[3];
+	ncols                  = info[4];
+	npp                    = info[5];
+	typeflag               = (unsigned int)info[6];
+	ncard                  = info[7];
+	MAKE_TFLAQUE();
+	if (ncols > 0) {
+	  double *dcard;
+	  int ntot = ncols * ncard;
+	  ALLOC(dcard, ntot);
+	  if (typeflag == 0 || !byteswap) {
+	    /* No strings or no byteswap'ping needed */
+	    CMARD(dcard, ntot);
+	  }
+	  else {
+	    /* At least one column is a string */
+	    double *pcard = dcard;
+	    for (j=0; j<ncard; j++) {
+	      CMARD_TFLAQUE(pcard, ncols);
+	      pcard += ncols;
+	    }
+	  }
+	  idx->ncard = ncard;
+	  idx->dcard = dcard;
+	}
+	else {
+	  idx->ncard = 0;
+	  idx->dcard = NULL;
+	}
+      }
+      else {
+	EAT_GORILLA(tmpline);
+	sscanf(tmpline, "%d %d", &idx->creation_date, &idx->creation_time);
+	EAT_GORILLA(tmpline);
+	sscanf(tmpline, "%d %d", &idx->modification_date, &idx->modification_time);
+	EAT_GORILLA(tmpline);
+	sscanf(tmpline, "%d %d", &ncols, &npp);
+	EAT_GORILLA(tmpline);
+	sscanf(tmpline, "%u", &typeflag);
+	MAKE_TFLAQUE();
+	if (ncols > 0) {
+	  int k = 0;
+	  int ntot;
+	  double *dcard;
+	  EAT_GORILLA(tmpline);
+	  sscanf(tmpline, "%d", &ncard);
+	  ntot = ncols * ncard;
+	  ALLOC(dcard, ntot);
+	  for (j=0; j<ncard; j++) {
+	    int ii;
+	    char *ptr = NULL;
+	    EAT_GORILLA(tmpline); 
+	    ptr = tmpline;
+	    while (isspace(*ptr)) ++ptr;
+	    for (ii=0; ii<ncols; ii++) {
+	      int is_string = tflaque[ii];
+	      if (is_string == 1) {
+		S2D_Union u;
+		ptr = strstr(ptr, "'"); /* Opening quote */
+		strncpy(u.str,ptr+1,sizeof(double));
+		dcard[k] = u.dval;
+		ptr += sizeof(double) + 1; /* Now at the closing quote */
+	      }
+	      else {
+		sscanf(ptr, "%lf", &dcard[k]);
+		ptr = strchr(ptr,' ');
+	      }
+	      ++k;
+	      ++ptr;
+	    } /* for (ii=0; ii<ncols; ii++) */
+	    FREE(tmpline);
+	  } /* for (j=0; j<ncard; j++) */
+	  idx->ncard = ncard;
+	  idx->dcard = dcard;
+	}
+	else {
+	  idx->ncard = 0;
+	  idx->dcard = NULL;
+	}
+	FREE(tmpline);
+      }
+
+      idx->ncols = ncols;
+      idx->npools = npools = npp;
+      idx->typeflag = typeflag;
+      CALLOC(idx->pp, npools);
+
+      if (npp > 0) {
+	npp = 0;
+	for (j=0; j<npools; j++) {
+	  odbidx_pp_t *pp = &idx->pp[npp];
+	  int nsets, idxtype, nrows;
+	  Bool poolno_okay = false;
+
+	  pp->nsets = 0;
+	  
+	  if (binary) {
+	    CMARD(info, 1);
+	    poolno  = info[0];
+
+	    if (poolno <= 0) {
+	      last_pool_hit = true;
+	      break; /* for (j=0; j<npools; j++) */
+	    }
+
+	    {
+	      ll_t ward[2];
+	      CMARD(ward, 2);
+	      pp->backwd = ward[0];
+	      pp->fwd = ward[1];
+	    }
+
+	    /* The following is essential for timeseries 
+	       (chained/odbmerge/odbdup'ped) databases */
+	    if (poolno_offset && *poolno_offset > 0) poolno += *poolno_offset;
+	    poolno_okay = ODB_in_permanent_poolmask(handle, poolno) ? true : false;
+
+	    if (!poolno_okay) {
+	      int iret;
+	      const int binwhence = 1; /* SEEK_CUR (= seek from the current pos) */
+	      int binoff = pp->fwd;
+	      cma_seekb_(&io_idx, &binoff, &binwhence, &iret);
+	      goto end_pool_loop;
+	    }
+
+	    CMARD(info, 3);
+	    idxtype = info[0];
+	    nrows   = info[1];
+	    nsets   = info[2];
+
+	  }
+	  else {
+	    EAT_GORILLA(tmpline);
+	    sscanf(tmpline, "%d", &poolno);
+	    FREE(tmpline);
+
+	    if (poolno <= 0) {
+	      last_pool_hit = true;
+	      break; /* for (j=0; j<npools; j++) */
+	    }
+
+	    /* The following is essential for timeseries 
+	       (chained/odbmerge/odbdup'ped) databases */
+	    if (poolno_offset && *poolno_offset > 0) poolno += *poolno_offset;
+	    poolno_okay = ODB_in_permanent_poolmask(handle, poolno) ? true : false;
+	    
+	    EAT_GORILLA(tmpline);
+	    sscanf(tmpline, "%d %d %d", &idxtype, &nrows, &nsets);
+
+	    FREE(tmpline);
+	  }
+
+	  { /* Start examine and store contents of this index */
+	    int i;
+	    int ksets = 0;
+
+	    /* Note: 
+	       When "poolno_okay" is false, all data is still read in
+	       but not processed, nor stored anywhere 
+	    */
+
+	    pp->poolno = poolno;
+	    pp->idxtype = idxtype;
+	    pp->nrows = nrows;
+	    pp->nsets = 0;
+
+	    CALLOC(pp->idxset, nsets);
+	    
+	    for (i=0; i<nsets; i++) {
+	      double *pvalue = NULL;
+	      Bool takeset = poolno_okay;
+	      odbidx_set_t *idxset = &pp->idxset[ksets];
+	      int ndata, idxlen, nclusters;
+	      unsigned int *idxdata = NULL;
+	      
+	      if (ncols > 0) {
+		ALLOC(idxset->value, ncols);
+		pvalue = idxset->value;
+	      }
+	      else {
+		idxset->value = NULL;
+	      }
+
+	      if (binary) {
+		if (ncols > 0) {
+		  if (typeflag == 0 || !byteswap) {
+		    /* No strings or no byteswap'ping needed */
+		    CMARD(pvalue, ncols);
+		  }
+		  else {
+		    /* At least one column is a string */
+		    CMARD_TFLAQUE(pvalue, ncols);
+		  }
+		  if (poolno_okay && rhs && ncols == 1) TAKESET_EVAL();
+		}
+		CMARD(info, 2);
+		ndata = info[0];
+		idxlen = info[1];
+		idxset->ndata = ndata;
+		idxset->idxlen = idxlen;
+		idxset->nclusters = 0;
+		ndata = ABS(ndata);
+		ALLOC(idxdata, ndata);
+		CMARD(idxdata, ndata);
+		if (!takeset) FREE(idxdata);
+	      }
+	      else /* text */ {
+		int ii;
+		int set_number;
+
+		EAT_GORILLA(tmpline);
+		sscanf(tmpline,"%d",&set_number);
+		FREE(tmpline);
+
+		if (ncols > 0) {
+		  char *ptr = NULL;
+		  EAT_GORILLA(tmpline); 
+		  ptr = tmpline;
+		  while (isspace(*ptr)) ++ptr;
+		  for (ii=0; ii<ncols; ii++) {
+		    int is_string = tflaque[ii];
+		    if (is_string == 1) {
+		      S2D_Union u;
+		      ptr = strstr(ptr, "'"); /* Opening quote */
+		      strncpy(u.str,ptr+1,sizeof(double));
+		      if (poolno_okay) pvalue[ii] = u.dval;
+		      ptr += sizeof(double) + 1; /* Now at the closing quote */
+		    }
+		    else {
+		      if (poolno_okay) sscanf(ptr, "%lf", &pvalue[ii]);
+		      ptr = strchr(ptr,' ');
+		    }
+		    ++ptr;
+		  } /* for (ii=0; ii<ncols; ii++) */
+		  FREE(tmpline);
+		  if (poolno_okay && rhs && ncols == 1) TAKESET_EVAL();
+		}
+
+		EAT_GORILLA(tmpline);
+		sscanf(tmpline, "%d %d %d", &ndata, &idxlen, &nclusters);
+		idxset->ndata = ndata;
+		idxset->idxlen = idxlen;
+		idxset->nclusters = nclusters;
+		FREE(tmpline);
+
+		if (ndata < 0 || idxtype == 2) {
+		  if (ndata < 0) {
+		    /* PCMA-packed */
+		    ndata = ABS(ndata);
+		    if (takeset) {
+		      ALLOC(idxdata, ndata);
+		      for (ii=0; ii<ndata; ii++) fscanf(fp, "%u", &idxdata[ii]);
+		    }
+		    else {
+		      unsigned int idxdummy;
+		      for (ii=0; ii<ndata; ii++) fscanf(fp, "%u", &idxdummy);
+		    }
+		  }
+		  else {
+		    int k;
+		    char pcl[80];
+		    if (takeset) ALLOC(idxdata, ndata);
+		    ii = 0;
+		    for (k=0; k<nclusters; k++) {
+		      fscanf(fp,"%s",pcl);
+		      if (takeset) {
+			int cnt;
+			unsigned int v;
+			char *star = strchr(pcl,'*');
+			if (star) {
+			  int z;
+			  *star = ' ';
+			  sscanf(pcl,"%d %u",&cnt,&v);
+			  for (z=0; z<cnt; z++) {
+			    idxdata[ii++] = v;
+			  }
+			}
+			else {
+			  sscanf(pcl,"%u",&v);
+			  idxdata[ii++] = v;
+			}
+		      } /* if (takeset) */
+		    } /* for (k=0; k<nclusters; k++) */
+		  }
+		}
+		else if (ndata == 0) {
+		  if (takeset) ALLOC(idxdata, 0);
+		}
+		else { /* ndata > 0 */
+		  int k;
+		  char pcl[80];
+		  if (takeset) ALLOC(idxdata, ndata);
+		  ii = 0;
+		  for (k=0; k<nclusters; k++) {
+		    fscanf(fp,"%s",pcl);
+		    if (takeset) {
+		      unsigned int z,s,e,inc;
+		      char *col1;
+		      col1 = strchr(pcl,':');
+		      if (col1) {
+			char *col2 = strchr(col1+1,':');
+			*col1 = ' ';
+			if (col2) {
+			  *col2 = ' ';
+			  sscanf(pcl,"%u %u %u",&s,&e,&inc);
+			}
+			else {
+			  sscanf(pcl,"%u %u",&s,&e);
+			  inc = 1;
+			}
+			for (z=s; z<=e; z+=inc) {
+			  idxdata[ii++] = z;
+			}
+		      }
+		      else {
+			sscanf(pcl,"%u",&s);
+			idxdata[ii++] = s;
+		      }
+		    } /* if (takeset) */
+		  } /* for (k=0; k<nclusters; k++) */
+		} /* if (ndata < 0) ... else if (ndata == 0) ... else */
+		
+	      } /* if (binary) ... else ... */
+	      
+	      idxset->idxdata = idxdata;
+
+	      if (takeset) 
+		ksets++; 
+	      else {
+		FREE(idxset->value);
+		FREE(idxset->idxdata);
+	      }
+	    } /* for (i=0; i<nsets; i++) */
+	    
+	    pp->nsets = ksets;
+
+	  end_pool_loop:
+	    if (poolno_okay) {
+	      if (pp->nsets > 0) npp++;
+	    }
+	    else { /* This pool wasn't in the poolmask */
+	      FREE(pp->idxset);
+	    }
+
+	  } /* End examine and store contents of this index */
+	} /* for (j=0; j<npools; j++) */
+
+	idx->npools = npp; /* The true number of pools, taking poolmask into account */
+
+	if (poolno_offset) *poolno_offset += npp;
+      } /* if (npp > 0) */
+
+      if (!last_pool_hit) {
+	if (binary) {
+	  CMARD(&poolno, 1);
+	}
+	else {
+	  EAT_GORILLA(tmpline);
+	  sscanf(tmpline, "%d", &poolno);
+	  FREE(tmpline);
+	}
+      }
+
+      ++rc;
+    }
+  }
+
+ finish:
+  DRHOOK_END_RECUR(0, recur);
+  return rc;
+}
+
+
+PUBLIC odbidx_t *
+codb_IDXF_fetch(int handle,
+		const char *idxpath,
+		const char *tblname,
+		const char *idxname,
+		int ncols,
+		const char *colnames,
+		const char *wherecond,
+		int oper,
+		const double *rhs)
+{
+  odbidx_t *idx = NULL;
+  DRHOOK_START(codb_IDXF_fetch);
+  {
+    const char *filesuffix = "*";
+    char *filename = codb_IDXF_filename(false, 
+					idxpath, 
+					tblname, 
+					idxname, 
+					ncols,
+					colnames, 
+					wherecond, 
+					filesuffix);
+    int poolno_offset = 0;
+    int rc = 0;
+    idx = IdxAllocAndFetch(NULL, filename, 
+			   handle, &poolno_offset, &rc, 0, 
+			   oper, rhs);
+    if (idx && idx->npools == 0 && rc == 0) idx = codb_IDXF_freeidx(idx, 0);
+    FREE(filename);
+  }
+  DRHOOK_END(0);
+  return idx;
+}
+
+
+PUBLIC odbidx_pp_t *
+codb_IDXF_pack(odbidx_t *idx, int poolno, int pmethod, int idxtype, int recur)
+{
+  /* Not implemented yet */
+  return NULL;
+}
+
+
+PUBLIC odbidx_pp_t *
+codb_IDXF_locate_pp(odbidx_t *idx, int poolno, int recur)
+{
+  odbidx_pp_t *PP = NULL;
+  DRHOOK_START_RECUR(codb_IDXF_locate_pp, recur);
+  if (idx && poolno > 0) {
+    int j, npp = idx->npools;
+    for (j=0; j<npp; j++) {
+      odbidx_pp_t *pp = &idx->pp[j];
+      if (pp->poolno == poolno) {
+	PP = pp;
+	break;
+      }
+    } /* for (j=0; j<npp; j++) */
+    /* Not found ? Check the chain */
+    if (!PP && idx->next) PP = codb_IDXF_locate_pp(idx->next, poolno, recur + 1);
+  }
+  DRHOOK_END_RECUR(0, recur);
+  return PP;
+}
+
+PUBLIC odbidx_pp_t *
+codb_IDXF_unpack(odbidx_t *idx, int poolno, int recur)
+{
+  /* 
+     Make sure that the idxdata[] in corresponding idxsets is 
+     (a) unpacked in upcma() sense, where applicable
+     (b) idxtype is set 1 i.e. idxdata[] is direct rowid's ready for use
+  */
+
+  odbidx_pp_t *PP = NULL;
+  DRHOOK_START_RECUR(codb_IDXF_unpack, recur);
+  if (idx) {
+    int j;
+    if (poolno == -1) {
+      /* All available pools */
+      for (j=0; j<idx->npools; j++) {
+	odbidx_pp_t *pp = &idx->pp[j];
+	poolno = pp->poolno;
+	if (poolno > 0) (void) codb_IDXF_unpack(idx, poolno, recur + 1);
+      }
+    }
+    else if (poolno > 0) {
+      /* A particular pool only */
+      odbidx_pp_t *pp = codb_IDXF_locate_pp(idx, poolno, 0);
+      if (pp) {
+	int idxtype = pp->idxtype;
+	int nrows = pp->nrows; /* Gives the valid idx-range [0..nrows-1], C-indexing */
+	int js, nsets = pp->nsets;
+	odbidx_set_t *pidxset = pp->idxset;
+	
+	for (js=0; js<nsets; js++) {
+	  int ndata = pidxset->ndata;
+	  
+	  if (ndata < 0) {
+	    /* Firstly, dismantle possible pcma()-packing */
+	    /* Not implemented yet */
+	    ndata = ABS(ndata); /* for now */
+	  }
+	  
+	  if (idxtype == 2) {
+	    /* Secondly, go from idxtype = 2 to idxtype = 1 */
+	    unsigned int *bitmap = pidxset->idxdata;
+	    pidxset->idxdata = ODBIT_getidx(bitmap, nrows, MAXBITS, &ndata);
+	    FREE(bitmap); /* The same as ODBIT_free(bitmap); */
+	  }
+	  
+	  pidxset->ndata = ndata;
+	  ++pidxset;
+	} /* for (js=0; js<nsets; js++) */
+
+	pp->idxtype = 1;
+	PP = pp;
+      } /* if (pp) */
+    }
+  }
+  DRHOOK_END_RECUR(0, recur);
+  return PP;
+}
+
+
+PRIVATE int
+Sequence(const unsigned int idxdata[], int istart, int iend, int *tryInc)
+{
+  int j, last = istart;
+  int inc = (last < iend) ? idxdata[istart+1] - idxdata[last] : 1;
+  int cnt = 0;
+  DRHOOK_START(Sequence);
+  for (j=istart+1; j<iend; j++) {
+    if (idxdata[j] == idxdata[j-1] + inc) {
+      last = j;
+      ++cnt;
+    }
+    else
+      break;
+  }
+  if (tryInc) *tryInc = (cnt > 0) ? inc : 0;
+  DRHOOK_END(0);
+  return last;
+}
+
+#define CMAWR(x, n) \
+  opaque = x; nbytes = sizeof(*(x)) * (n); \
+  cma_writeb_(&io_idx, opaque, &nbytes, &iret)
+
+PUBLIC int
+codb_IDXF_write(int io_idx, odbidx_t *idx, int binary, int pmethod, int use_idxtype)
+{
+  int rc = 0;
+  DRHOOK_START(codb_IDXF_write);
+  if (idx && io_idx >= 0) {
+    FILE *fp = CMA_get_fp(&io_idx);
+    if (fp) {
+      char bitstream[MAXBITS+1];
+      const int this_version = 1;
+      const int filekind = 1;
+      int j, poolno, npools = idx->npools;
+      unsigned int typeflag = idx->typeflag;
+      int ncols = idx->ncols;
+      unsigned int idxf = binary ? IDXB : IDXT;
+      int info[8];
+      const void *opaque;
+      int nbytes, iret, npp;
+      int nsets_tot, ncard = idx->ncard;
+      double *dcard = NULL;
+      
+      codb_datetime_(&idx->modification_date, &idx->modification_time);
+
+      CMAWR(&idxf, 1);
+
+      fprintf(fp,"\n%d ! Index-file format version", this_version);
+      fprintf(fp,"\n%d ! Index-file kind", filekind);
+
+      fprintf(fp, "\n%d %s", STRLEN(idx->filename), idx->filename);
+      fprintf(fp, "\n%d %s", STRLEN(idx->tblname), idx->tblname);
+      fprintf(fp, "\n%d %s", STRLEN(idx->idxname), idx->idxname);
+      {
+	char *s = RemoveWhiteSpace(idx->colnames);
+	fprintf(fp, "\n%d %s", STRLEN(s), s);
+      }
+      {
+	char *s = RemoveWhiteSpace(idx->wherecond);
+	fprintf(fp, "\n%d %s", STRLEN(s), s);
+	FREE(s);
+      }
+      fprintf(fp, "\n\f");
+
+      {
+	ll_t backwd = 0;
+	nsets_tot = 0;
+	npp = 0;
+	for (j=0; j<npools; j++) {
+	  odbidx_pp_t *pp = &idx->pp[j];
+	  poolno = pp->poolno;
+	  if (poolno > 0) {
+	    ll_t sz = 0; /* size of the current pool when in binary index-file */
+	    int i, nsets = pp->nsets;
+	    int idxtype = pp->idxtype;
+	    int poolno_sz = 1 * sizeof(int); /* poolno */
+	    int ward_sz = 2 * sizeof(ll_t); /* backwd, fwd */
+	    int hdr_sz = 3 * sizeof(int);  /* idxtype, nrows, nsets */
+	    int delta = poolno_sz + ward_sz;
+	    nsets_tot += nsets;
+	    sz += poolno_sz;
+	    sz += ward_sz;
+	    sz += hdr_sz;
+	    for (i=0; i<nsets; i++) {
+	      const odbidx_set_t *idxset = &pp->idxset[i];
+	      const double *value = idxset->value;
+	      int ndata = ABS(idxset->ndata);
+	      int idxlen = idxset->idxlen;
+	      const unsigned int *idxdata = idxset->idxdata;
+	      if (ncols > 0) sz += ncols * sizeof(*value); /* value[0..ncols-1] */
+	      sz += sizeof(ndata); /* ndata */
+	      sz += sizeof(idxlen); /* idxlen */
+	      /* "nclusters" is not written for binary file */
+	      sz += ndata * sizeof(*idxdata); /* idxdata[] */
+	    } /* for (i=0; i<nsets; i++) */
+	    /* How many bytes to jump backward to reach the beginning of the
+	       previous poolno-word ? */
+	    pp->backwd = -backwd;
+	    /* How many bytes to jump forward to reach the beginning of the
+	       next poolno-word ? */
+	    pp->fwd = sz - delta;
+	    backwd = sz + delta; /* Remember for the next pool */
+	    npp++;
+	  } /* if (poolno > 0) */
+	} /* for (j=0; j<npools; j++) */
+      }
+
+      if (ncols > 0) {
+	/* 
+	   Create global SELECT DISTINCT -set (over all available [npp] pools).
+
+	   Basically we would like to execute over all pools the following query:
+
+	     SELECT DISTINCT cols FROM table WHERE cond
+
+	   But since all cols-information has already been collected, we just need
+	   to pick up the distinct set (total ncard-rows) and fill dcard[].
+	*/
+
+	int jc, jr, nr = nsets_tot;
+	Bool row_wise = false; /* We need Fortran column-major for codb_cardinality_() */
+	result_t *res = ODBc_new_res("codb_IDXF_write() for dcard[]",
+				     __FILE__, __LINE__,
+				     nr, ncols, NULL, row_wise, -1);
+	result_t *sortres = NULL;
+	int ntot;
+	int *unique_idx = NULL;
+	int *keys = NULL;
+
+	res->typeflag = typeflag;
+
+	jr = 0;
+	for (j=0; j<npools; j++) {
+	  const odbidx_pp_t *pp = &idx->pp[j];
+	  poolno = pp->poolno;
+	  if (poolno > 0) {
+	    int i, nsets = pp->nsets;
+	    for (i=0; i<nsets; i++) {
+	      const odbidx_set_t *idxset = &pp->idxset[i];
+	      const double *value = idxset->value;
+	      for (jc=0; jc<ncols; jc++) {
+		/* Note below : Using d[jc][jr], not d[jr][jc], since row_wise = false !! */
+		res->d[jc][jr] = value[jc];
+	      } /* for (jc=0; jc<ncols; jc++) */
+	      ++jr;
+	    } /* for (i=0; i<nsets; i++) */
+	  } /* if (poolno > 0) */
+	} /* for (j=0; j<npools; j++) */
+
+	/* Note : Returned unique_idx[] is using Fortran-indexing 1..N, not 0..N-1 !! */
+	CALLOC(unique_idx, nr);
+	codb_cardinality_(&res->ncols_in, &res->nrows_in, &res->nra,
+			  res->mem,
+			  &ncard,
+			  unique_idx,
+			  &nr,
+			  NULL);
+
+	/* Values picked for uniqueness may be unordered --> sort them */
+	sortres = ODBc_new_res("codb_IDXF_write() for sorted dcard[]",
+			       __FILE__, __LINE__,
+			       ncard, ncols, NULL, row_wise, -1);
+
+	for (jr=0; jr<ncard; jr++) {
+	  int ir = unique_idx[jr] - 1;
+	  for (jc=0; jc<ncols; jc++) {
+	    sortres->d[jc][jr] = res->d[jc][ir];
+	  } /* for (jc=0; jc<ncols; jc++) */
+	} /* for (jr=0; jr<ncard; jr++) */
+	
+	FREE(unique_idx);
+	(void) ODBc_unget_data(res);
+
+	ALLOC(keys, ncols);
+	for (jc=0; jc<ncols; jc++) {
+	  /* Note : Fortran indexing for keys */
+	  keys[jc] = jc+1;
+	}
+
+	sortres = ODBc_sort(sortres, keys, ncols);
+
+	FREE(keys);
+
+	ntot = ncols * ncard;
+	CALLOC(dcard, ntot);
+
+	row_wise = sortres->row_wise;
+	j = 0;
+	for (jr=0; jr<ncard; jr++) {
+	  for (jc=0; jc<ncols; jc++) {
+	    /* Note again : after ODBc_sort() row_wise may have changed */
+	    dcard[j++] = row_wise ? sortres->d[jr][jc] : sortres->d[jc][jr];
+	  } /* for (jc=0; jc<ncols; jc++) */
+	} /* for (jr=0; jr<ncard; jr++) */
+
+	(void) ODBc_unget_data(sortres);
+      }
+      else {
+	ncard = 0;
+	dcard = NULL;
+      }
+
+      idx->ncard = ncard;
+      idx->dcard = dcard;
+
+      if (binary) {
+	info[0] = (int)idx->creation_date;
+	info[1] = (int)idx->creation_time;
+	info[2] = (int)idx->modification_date;
+	info[3] = (int)idx->modification_time;
+	info[4] = ncols;
+	info[5] = npp;
+	info[6] = (int)typeflag;
+	info[7] = ncard;
+	CMAWR(info, 8);
+	if (ncols > 0) {
+	  int ntot = ncols * ncard;
+	  CMAWR(dcard, ntot);
+	}
+      }
+      else {
+	int nbits = ncols;
+	(void) ODBIT_getmap(&typeflag, nbits, MAXBITS, bitstream);
+	if (nbits < MAXBITS) {
+	  memset(bitstream + nbits, '-', (MAXBITS - nbits) * sizeof(*bitstream));
+	  bitstream[MAXBITS] = '\0';
+	}
+
+	fprintf(fp, "\n%8.8d %6.6d ! Index creation date & time",
+		(int)idx->creation_date, (int)idx->creation_time);
+	fprintf(fp, "\n%8.8d %6.6d ! Last modification date & time",
+		(int)idx->modification_date, (int)idx->modification_time);
+	fprintf(fp, "\n");
+
+	fprintf(fp, "\n%d %d ! ncols npools", ncols, npp);
+	fprintf(fp, "\n%u ! typeflag = %s", typeflag, bitstream);
+	if (ncols > 0) {
+	  int k=0;
+	  fprintf(fp, "\n\n%d ! ncard", ncard);
+	  for (j=0; j<ncard; j++) {
+	    int ii;
+	    fprintf(fp, "\n");
+	    for (ii=0; ii<ncols; ii++) {
+	      int is_string = (typeflag == 0) ? 0 : 
+		ODBIT_test(&typeflag, MAXBITS, MAXBITS, ii, ii);
+	      if (is_string == 1) {
+		register char *c;
+		S2D_Union u;
+		u.dval = dcard[k];
+		if (u.llu == S2D_all_blanks) {
+		  c = &u.str[sizeof(double)];
+		}
+		else {
+		  int k;
+		  c = u.str;
+		  for (k=0; k<sizeof(double); k++) {
+		    if (!isprint(*c)) *c = '?';
+		    c++;
+		  }
+		}
+		*c = 0;
+		fprintf(fp, " '%s'", u.str);
+	      }
+	      else {
+		fprintf(fp, " %.14g", dcard[k]);
+	      }
+	      ++k;
+	    } /* for (ii=0; ii<ncols; ii++) */
+	  } /* for (j=0; j<ncard; j++) */
+	}
+      }
+
+      if (npp > 0) {
+	for (j=0; j<npools; j++) {
+	  odbidx_pp_t *pp = &idx->pp[j];
+	  poolno = pp->poolno;
+	  if (poolno > 0) {
+	    int i, nsets = pp->nsets;
+	    int idxtype = pp->idxtype;
+	    int nrows = pp->nrows;
+	    
+	    if (binary) {
+	      info[0] = poolno;
+	      CMAWR(info, 1);
+
+	      {
+		ll_t ward[2];
+		ward[0] = pp->backwd;
+		ward[1] = pp->fwd;
+		CMAWR(ward, 2);
+	      }
+
+	      info[0] = idxtype;
+	      info[1] = nrows;
+	      info[2] = nsets;
+	      CMAWR(info, 3);
+	    }
+	    else {
+	      fprintf(fp, "\n\n%d ! poolno", poolno);
+	      fprintf(fp, "\n%d %d %d ! idxtype, nrows, nsets", idxtype, nrows, nsets);
+	    }
+	    
+	    for (i=0; i<nsets; i++) {
+	      odbidx_set_t *idxset = &pp->idxset[i];
+	      const double *value = idxset->value;
+	      int ndata = idxset->ndata;
+	      int idxlen = ABS(ndata); /* for now ... */
+	      const unsigned int *idxdata = idxset->idxdata;
+	      
+	      if (binary) {
+		if (ncols > 0) {
+		  CMAWR(value, ncols);
+		}
+		info[0] = ndata;
+		info[1] = idxlen;
+		CMAWR(info, 2);
+		ndata = ABS(ndata);
+		CMAWR(idxdata, ndata);
+	      }
+	      else /* text */ {
+		int ii;
+		int set_number = i + 1;
+		fprintf(fp,"\n%d ! set#",set_number);
+		if (ncols > 0) {
+		  fprintf(fp, "\n");
+		  for (ii=0; ii<ncols; ii++) {
+		    int is_string = (typeflag == 0) ? 0 : 
+		      ODBIT_test(&typeflag, MAXBITS, MAXBITS, ii, ii);
+		    if (is_string == 1) {
+		      register char *c;
+		      S2D_Union u;
+		      u.dval = value[ii];
+		      if (u.llu == S2D_all_blanks) {
+			c = &u.str[sizeof(double)];
+		      }
+		      else {
+			int k;
+			c = u.str;
+			for (k=0; k<sizeof(double); k++) {
+			  if (!isprint(*c)) *c = '?';
+			  c++;
+			}
+		      }
+		      *c = 0;
+		      fprintf(fp, " '%s'", u.str);
+		    }
+		    else {
+		      fprintf(fp, " %.14g", value[ii]);
+		    }
+		  } /* for (ii=0; ii<ncols; ii++) */
+		}
+
+		idxset->nclusters = 0;
+
+		if (ndata < 0 || idxtype == 2) {
+		  if (ndata < 0) {
+		    /* PCMA-packed */
+		    fprintf(fp, "\n%d %d %d ! ndata, idxlen, nclusters",ndata,idxlen,-ndata);
+		    ndata = ABS(ndata);
+		    for (ii=0; ii<ndata; ii++) {
+		      if (ii%5 == 0) fprintf(fp, "\n");
+		      fprintf(fp, " %u", idxdata[ii]);
+		    }
+		  }
+		  else {
+		    /* Not PCMA-packed */
+#if 0
+		    int bit_start = 0, bit_end;
+		    fprintf(fp, "\n%d %d %d ! ndata, idxlen, nclusters",ndata,idxlen,ndata);
+		    for (ii=0; ii<ndata; ii++) {
+		      int nbits;
+		      bit_end = bit_start + MAXBITS - 1;
+		      bit_end = MIN(bit_end, nrows-1);
+		      nbits = bit_end - bit_start + 1;
+		      (void) ODBIT_getmap(&idxdata[ii], nbits, MAXBITS, bitstream);
+		      if (nbits < MAXBITS) {
+			memset(bitstream + nbits, '-', (MAXBITS - nbits) * sizeof(*bitstream));
+			bitstream[MAXBITS] = '\0';
+		      }
+		      fprintf(fp, "\n %10u ! %s : %d - %d", 
+			      idxdata[ii], bitstream,
+			      bit_start, bit_end);
+		      bit_start = bit_end + 1;
+		    }
+#else
+		    int k = 0;
+		    int iprev = 0;
+		    for (ii=0; ii<ndata; ii++) {
+		      if (idxdata[ii] != idxdata[iprev]) {
+			iprev = ii;
+			k++;
+		      }
+		    } /* for (ii=1; ii<ndata; ii++) */
+		    k++;
+		    fprintf(fp, "\n%d %d %d ! ndata, idxlen, nclusters",ndata,idxlen,k);
+		    idxset->nclusters = k;
+		    k = 0;
+		    iprev = 0;
+		    for (ii=0; ii<ndata; ii++) {
+		      if (idxdata[ii] != idxdata[iprev]) {
+			int cnt = ii - iprev;
+			if (k++%5 == 0) fprintf(fp, "\n");
+			if (cnt > 1) {
+			  fprintf(fp, " %d*%u", cnt, idxdata[iprev]);
+			}
+			else {
+			  fprintf(fp, " %u", idxdata[iprev]);
+			}
+			iprev = ii;
+			k++;
+		      }
+		    } /* for (ii=1; ii<ndata; ii++) */
+		    { /* Trailing part */
+		      int cnt = ndata - iprev;
+		      if (k++%5 == 0) fprintf(fp, "\n");
+		      if (cnt > 1) {
+			fprintf(fp, " %d*%u", cnt, idxdata[iprev]);
+		      }
+		      else {
+			fprintf(fp, " %u", idxdata[iprev]);
+		      }
+		    }
+#endif
+		  }
+		}
+		else if (ndata == 0) {
+		  fprintf(fp, "\n0 0 0 ! ndata, idxlen, nclusters");
+		}
+		else { /* ndata > 0 */
+		  int k = 0;
+
+		  for (ii=0; ii<ndata; ) {
+		    int tryinc = 1;
+		    int last = Sequence(idxdata, ii, ndata, &tryinc);
+		    ii = last + 1;
+		    k++;
+		  } /* for (ii=0; ii<ndata; ) */
+
+		  idxset->nclusters = k;
+		  fprintf(fp, "\n%d %d %d ! ndata, idxlen, nclusters",ndata,idxlen,k);
+
+		  k = 0;
+		  for (ii=0; ii<ndata; ) {
+		    int tryinc = 1;
+		    int last = Sequence(idxdata, ii, ndata, &tryinc);
+		    if (k%5 == 0) fprintf(fp, "\n");
+		    if (tryinc == 0) {
+		      fprintf(fp, " %u", idxdata[ii]);
+		    }
+		    else if (tryinc == 1) {
+		      fprintf(fp, " %u:%u", idxdata[ii], idxdata[last]);
+		    }
+		    else { /* tryinc > 1 */
+		      fprintf(fp, " %u:%u:%d", idxdata[ii], idxdata[last], tryinc);
+		    }
+		    ii = last + 1;
+		    k++;
+		  } /* for (ii=0; ii<ndata; ) */
+
+		} /* if (ndata < 0) ... else if (ndata == 0) ... else */
+
+	      } /* if (binary) ... else *text* ... */
+	    } /* for (i=0; i<nsets; i++) */
+	  }
+	} /* for (j=0; j<npools; j++) */
+      } /* if (npp > 0) */
+
+      poolno = -1;
+      if (binary) {
+	CMAWR(&poolno, 1);
+      }
+      else {
+	fprintf(fp, "\n\n%d ! poolno (end-of-pools)\n",poolno);
+      }
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC void *
+ODBc_create_index_prepare(int handle, const void *Info, const void *Infoaux)
+{
+  void *retval = NULL;
+  const info_t *info = Info;
+  const info_t *infoaux = Infoaux;
+  DRHOOK_START(ODBc_create_index_prepare);
+  if (info && !infoaux) {
+    info_t *retinfo = NULL;
+    if (info && info->create_index > 0 && info->nfrom == 1 && info->t) {
+      char *sql_query = NULL;
+      int j, ncols = info->ncols_true;
+      const char *tblname = info->t->name;
+      int lentbl = STRLEN(tblname);
+      char *setvars = NULL;
+      int nsetvars = info->nset;
+      int lensetvars = 1;
+      char *cols = NULL;
+      int lencols = 1;
+      const char *wherecond = info->wherecond ? info->wherecond : "1";
+      char *pwherecond = S2D_fix(info, wherecond);
+      int lenwhere = STRLEN(pwherecond);
+
+      for (j=0; j<nsetvars; j++) {
+	const set_t *sv = &info->s[j];
+	const char *name = sv->name;
+	if (!strequ(name,"$__maxcount__")) {
+	  lensetvars += 4 + STRLEN(name) + 3 + 50;
+	}
+      }
+
+      ALLOC(setvars, lensetvars);
+      *setvars = 0;
+      for (j=0; j<nsetvars; j++) {
+	const set_t *sv = &info->s[j];
+	const char *name = sv->name;
+	if (!strequ(name,"$__maxcount__")) {
+	  double value = sv->value;
+	  int len = STRLEN(setvars);
+	  char *p = setvars + len;
+	  snprintf(p, lensetvars-len, "SET %s = %.14g;",
+		   name, value);
+	}
+      }
+      lensetvars = STRLEN(setvars);
+
+      for (j=0; j<ncols; j++) {
+	const col_t *colthis = &info->c[j];
+	lencols += STRLEN(colthis->name) + 1;
+      }
+
+      ALLOC(cols, lencols);
+      *cols = 0;
+      for (j=0; j<ncols; j++) {
+	const col_t *colthis = &info->c[j];
+	if (j>0) strcat(cols, ",");
+	strcat(cols, colthis->name);
+      }
+      lencols = STRLEN(cols);
+
+      /* Create an info-chain of 3 auxiliary queries */
+
+      if (ncols > 1) {
+	const char fmt[] = 
+	  "CREATE VIEW _1_%s AS SELECT count(*) FROM %s;" /* nrows */
+	  "%s"
+	  "CREATE VIEW _2_%s AS SELECT DISTINCT %s,cksum(%s) FROM %s WHERE %s ORDERBY %s;" /* nsets */
+	  "CREATE VIEW _3_%s AS SELECT %s,cksum(%s),#%s FROM %s WHERE %s;";  /* nsets * (ncols - 2) */
+      
+	int lenq = STRLEN(fmt) + 3 * STRLEN(info->view) +
+	  lentbl +
+	  lensetvars +
+	  3 * lencols + lentbl + lenwhere +
+	  2 * lentbl + 2 * lencols + lenwhere;
+      
+	ALLOC(sql_query, lenq);
+
+	snprintf(sql_query, lenq, fmt,
+		 info->view, tblname,
+		 setvars,
+		 info->view, cols, cols, tblname, pwherecond, cols,
+		 info->view, cols, cols, tblname, tblname, pwherecond);
+      }
+      else if (ncols == 1) { /* we do not need to call cksum() since just one column */
+	const char fmt[] = 
+	  "CREATE VIEW _1_%s AS SELECT count(*) FROM %s;" /* nrows */
+	  "%s"
+	  "CREATE VIEW _2_%s AS SELECT DISTINCT %s FROM %s WHERE %s ORDERBY %s;" /* nsets */
+	  "CREATE VIEW _3_%s AS SELECT %s,#%s FROM %s WHERE %s;";  /* nsets * (ncols - 1) */
+      
+	int lenq = STRLEN(fmt) + 3 * STRLEN(info->view) +
+	  lentbl +
+	  lensetvars +
+	  2 * lencols + lentbl + lenwhere +
+	  2 * lentbl + lencols + lenwhere;
+      
+	ALLOC(sql_query, lenq);
+
+	snprintf(sql_query, lenq, fmt,
+		 info->view, tblname,
+		 setvars,
+		 info->view, cols, tblname, pwherecond, cols,
+		 info->view, cols, tblname, tblname, pwherecond);
+      }
+      else { /* ncols == 0 */
+	const char fmt[] = 
+	  "CREATE VIEW _1_%s AS SELECT count(*) FROM %s;" /* nrows */
+	  "CREATE VIEW _2_%s AS SELECT #%s FROM %s WHERE #%s = 1 AND maxcount(1);" /* nsets == 1 */
+	  "%s"
+	  "CREATE VIEW _3_%s AS SELECT #%s FROM %s WHERE %s;"; /* ndata for the only set */
+      
+	int lenq = STRLEN(fmt) + 3 * STRLEN(info->view) +
+	  lentbl +
+	  lentbl + 3 * lentbl +
+	  lensetvars +
+	  2 * lentbl + lenwhere;
+	
+	ALLOC(sql_query, lenq);
+
+	snprintf(sql_query, lenq, fmt,
+		 info->view, tblname,
+		 info->view, tblname, tblname, tblname,
+		 setvars,
+		 info->view, tblname, tblname, pwherecond);
+      }
+
+      FREE(pwherecond);
+      FREE(cols);
+      FREE(setvars);
+
+      if (sql_query) {
+	retinfo = ODBc_sql_prepare(handle, sql_query, NULL, 0);
+	FREE(sql_query);
+      }
+    }
+    retval = retinfo;
+  }
+  else if (info && infoaux) {
+    int j, ncols = info->ncols_true;
+    char *cols = NULL;
+    int lencols = 1;
+    odbidx_t *stored_idx;
+    CALLOC(stored_idx, 1);
+    stored_idx->tblname = STRDUP(info->t->name);
+    stored_idx->idxname = STRDUP(info->view);
+    stored_idx->wherecond = info->wherecond ? STRDUP(info->wherecond) : STRDUP("1");
+
+    codb_datetime_(&stored_idx->creation_date, &stored_idx->creation_time);
+    stored_idx->modification_date = stored_idx->creation_date;
+    stored_idx->modification_time = stored_idx->creation_time;
+
+    stored_idx->typeflag = 0;
+
+    if (ncols > 0) {
+      int string_count = 0;
+      unsigned int stridx[MAXBITS]; /* Note : ncols >= 0 && <= MAXBITS enforced by odb98.x compiler */
+      memset(stridx, 0, sizeof(stridx));
+      string_count = 0;
+      for (j=0; j<ncols; j++) {
+	const col_t *colthis = &info->c[j];
+	lencols += STRLEN(colthis->name) + 1;
+	if (colthis->dtnum == DATATYPE_STRING) {
+	  stridx[string_count++] = j;
+	}
+      }
+      if (string_count > 0) {
+	unsigned int typeflag = 0;
+	const int nbits = MAXBITS;
+	const int nbw = MAXBITS;
+	const int nstridx = MAXBITS;
+	codbit_setidx_(&typeflag, &nbits, &nbw, stridx, &string_count);
+	stored_idx->typeflag = typeflag;
+      }
+      ALLOC(cols, lencols);
+      *cols = 0;
+      for (j=0; j<ncols; j++) {
+	const col_t *colthis = &info->c[j];
+	if (j>0) strcat(cols, ",");
+	strcat(cols, colthis->name);
+      }
+      stored_idx->colnames = cols;
+    }
+    else { /* ncols == 0 */
+      stored_idx->colnames = STRDUP("*");
+    }
+
+    stored_idx->npools = 0;
+    stored_idx->pp = NULL;
+    stored_idx->ncols = ncols;
+
+    retval = stored_idx;
+  }
+  DRHOOK_END(0);
+  return retval;
+}
+
+
+typedef struct _btree_t {
+  double cksum;
+  int keylen; /* in bytes */
+  void *keys;
+  unsigned int *idxdata;
+  int ndata;
+  int nalloc;
+} btree_t;
+
+
+PRIVATE int
+cmp_bt(const void *A, const void *B)
+{
+  const btree_t *a = A;
+  const btree_t *b = B;
+  if (a->cksum == b->cksum) {
+    return memcmp(a->keys, b->keys, a->keylen);
+  }
+  else return (a->cksum > b->cksum) ? 1 : -1;
+}
+
+
+PUBLIC odbidx_t *
+codb_IDXF_create_index(int handle,
+		       void *Idx, int poolno, 
+		       int idxtype, 
+		       void *Info, int *Nrows)
+{
+  int nrows_out = 0;
+  odbidx_t *idx = Idx;
+  info_t *info = Info;
+  DRHOOK_START(codb_IDXF_create_index);
+  if (idx && info && poolno > 0 && idxtype > 0) {
+    info_t *info1 = info; /* SELECT count(*) FROM table */
+    info_t *info2 = info1->next; /* Usually SELECT DISTINCT cols,cksum(cols) FROM table WHERE ... ORDERBY cols */
+    info_t *info3 = info2 ? info2->next : NULL; /* Usually SELECT cols,cksum(cols),#table FROM table WHERE ... */
+    if (info1 && info2 && info3) {
+      FILE *fp_echo = ODBc_get_debug_fp();
+      int nrows, ncols = idx->ncols;
+      int jloc = -1, npp = idx->npools;
+      int nsets;
+      odbidx_pp_t *pp = NULL;
+      Bool do_alloc = false;
+      Bool poolno_okay = ODB_in_permanent_poolmask(handle, poolno) ? true : false;
+
+      if (!poolno_okay) {
+	ODB_fprintf(fp_echo,
+		    "***Warning in codb_IDXF_create_index() of %s : Pool number %d not in poolmask\n",
+		    info->view, poolno);
+	nrows = 0; /* Not an error */
+	goto finish;
+      }
+
+      /* Running#1 : SELECT count(*) FROM table */
+      nrows = ODBc_sql_exec(handle, info1, poolno, NULL, NULL);
+      if (nrows <= 0) goto finish;
+
+      if (npp <= 0 || !idx->pp) {
+	FREE(idx->pp);
+	npp = 1;
+	do_alloc = true;
+      }
+      else {
+	int j;
+	Bool found = false;
+	pp = idx->pp;
+	for (j=0; j<npp; j++) {
+	  if (pp->poolno == poolno) {
+	    jloc = j;
+	    found = true;
+	    FreeIdxSets(pp->idxset, pp->nsets, ncols);
+	    FREE(pp->idxset);
+	    pp->nsets = 0;
+	    break;
+	  }
+	  ++pp;
+	}
+	if (!found) {
+	  ++npp;
+	  do_alloc = true;
+	}
+      }
+      if (do_alloc) {
+	REALLOC(idx->pp, npp);
+	jloc = npp - 1;
+      }
+
+      idx->npools = npp;
+
+      pp = &idx->pp[jloc];
+
+      pp->backwd = pp->fwd = 0;
+
+      pp->poolno = poolno;
+      pp->idxtype = idxtype;
+
+      if (nrows == 1) {
+	result_t *res = ODBc_get_data(handle, NULL, info1, poolno, 1, nrows, false, NULL);
+	nrows = res->d[0][0];
+	res = ODBc_unget_data(res);
+      }
+      pp->nrows = nrows;
+	    
+      /* Running#2 : 
+	 if (ncols > 1)
+	   SELECT DISTINCT cols,cksum(cols) FROM table WHERE ... ORDERBY cols 
+	 else if (ncols == 1)
+	   SELECT DISTINCT cols FROM table WHERE ... ORDERBY cols
+	 else
+	   SELECT #table FROM table WHERE #table = 1 AND maxcount(1);
+      */
+
+      if (info2->has_select_distinct) {
+	codb_hash_set_lock_();
+	codb_hash_init_();
+      }
+
+      nsets = pp->nsets = ODBc_sql_exec(handle, info2, poolno, NULL, NULL);
+
+      if (info2->has_select_distinct) {
+	codb_hash_init_();
+	codb_hash_unset_lock_();
+      }
+
+      if (nsets > 0) {
+	odbidx_set_t *idxset;
+	CALLOC(idxset, nsets);
+
+	if (ncols > 0) {
+	  result_t *uniq = ODBc_get_data(handle, NULL, info2, poolno, 1, nsets, true, NULL);
+	  if (uniq) {
+	    /* Running#3 : 
+	       if (ncols > 1)
+  	         SELECT cols,cksum(cols),#table FROM table WHERE cond
+	       else if (ncols == 1)
+  	         SELECT cols,#table FROM table WHERE cond
+	    */
+	    int nres = ODBc_sql_exec(handle, info3, poolno, NULL, NULL);
+	    result_t *res = ODBc_get_data(handle, NULL, info3, poolno, 1, nres, false, NULL);
+	    if (res) {
+	      int jcksum = (ncols == 1) ? 0 : ncols;
+	      int jrowid = jcksum + 1;
+	      int js, ntot = ncols * nsets;
+	      double *value = NULL;
+	      int keylen = ncols * sizeof(*value);
+	      btree_t *bt = NULL;
+	      
+	      ALLOC(value, ntot);
+	      
+	      { /* Create binary tree, where each branch (set) has 
+		   cksum(cols) and values (keys) */
+		double *pvalue = value;
+		btree_t *p;
+		DRHOOK_START(codb_IDXF_create_index at qsort);
+
+		CALLOC(bt, nsets); p = bt;
+
+		for (js=0; js<nsets; js++) {
+		  int jcol;
+		  double cksum;
+		  for (jcol=0; jcol<ncols; jcol++) {
+		    pvalue[jcol] = uniq->row_wise ? uniq->d[js][jcol] : uniq->d[jcol][js];
+		  }
+		  cksum = pvalue[jcksum];
+		  
+		  p->cksum = cksum;
+		  p->keylen = keylen;
+		  p->keys = pvalue;
+		  ++p;
+
+		  pvalue += ncols;
+		} /* for (js=0; js<nsets; js++) */
+
+		qsort(bt, nsets, sizeof(btree_t), cmp_bt);
+		DRHOOK_END(nsets);
+	      }
+
+	      { /* Perform binary searches for each row in the res-set */
+		int j;
+		int ichunk = nres/nsets + 1; /* alloc increment ; can't be too large */
+		double *tmp = NULL;
+		btree_t *find = NULL;
+		DRHOOK_START(codb_IDXF_create_index at bsearch);
+		
+		CALLOC(find, 1); find->keylen = keylen;
+
+		if (ncols > 1) ALLOC(tmp, ncols);
+		
+		for (j=0; j<nres; j++) {
+		  int jcol;
+		  btree_t *match = NULL;
+		  
+		  find->cksum = res->row_wise ? res->d[j][jcksum] : res->d[jcksum][j];
+		  if (ncols > 1) {
+		    for (jcol=0; jcol<ncols; jcol++) {
+		      tmp[jcol] = res->row_wise ? res->d[j][jcol] : res->d[jcol][j];
+		    }
+		  }
+		  else
+		    tmp = res->row_wise ? &res->d[j][0] : &res->d[0][j];
+
+		  find->keys = tmp;
+
+		  match = bsearch(find, bt, nsets, sizeof(btree_t), cmp_bt);
+		  if (match) {
+		    int rowid = res->row_wise ? res->d[j][jrowid] : res->d[jrowid][j];
+		    int nalloc = match->nalloc;
+		    int ndata = match->ndata;
+		    if (nalloc <= ndata) {
+		      nalloc += MIN(ichunk,nres-j);
+		      REALLOC(match->idxdata, nalloc);
+		      match->nalloc = nalloc;
+		    }
+		    match->idxdata[ndata++] = rowid - 1;
+		    match->ndata = ndata;
+		  }
+		  else { /* Should not happen */
+		    fprintf(stderr,
+			    "***Error in codb_IDXF_create_index() (ncols=%d): Unable to match record#%d, poolno=%d\n",
+			    ncols, j, poolno);
+		    RAISE(SIGABRT);
+		  }
+		} /* for (j=0; j<nres; j++) */
+
+		if (ncols > 1) FREE(tmp);
+		FREE(find);
+		
+		nrows_out = res->nrows_out;
+		res = ODBc_unget_data(res);
+
+		DRHOOK_END(nres);
+	      }
+
+	      { /* The final fiddle : fill in odbidx_set_t's */
+		odbidx_set_t *pidxset = idxset;
+		btree_t *p = bt;
+		for (js=0; js<nsets; js++) {
+		  int ndata = p->ndata;
+		  unsigned int *idxdata = p->idxdata;
+
+		  ALLOC(pidxset->value, ncols);
+		  memcpy(pidxset->value, p->keys, keylen);
+
+		  if (idxtype == 2) {
+		    int nr = ndata;
+		    unsigned int *bitmap;
+		    const int maxbits = MAXBITS;
+		    ndata = RNDUP_DIV(nrows, maxbits);
+		    CALLOC(bitmap, ndata);
+		    codbit_setidx_(bitmap,&nrows,&maxbits,idxdata,&nr);
+		    FREE(idxdata);
+		    idxdata = bitmap;
+		  }
+		  pidxset->nclusters = 0;
+		  pidxset->ndata = ndata;
+		  pidxset->idxlen = ndata;
+		  pidxset->idxdata = idxdata;
+		  
+		  ++pidxset;
+		  ++p;
+		} /* for (js=0; js<nsets; js++) */
+	      }
+
+	      FREE(bt);
+	      FREE(value);
+	    } /* if (res) */
+	    uniq = ODBc_unget_data(uniq);
+	  } /* if (uniq) */
+	} /* if (ncols > 0) */
+	else { /* ncols == 0 --> just one idxset */
+	  /* Running#3 : SELECT #table FROM table WHERE cond */
+	  int ndata = ODBc_sql_exec(handle, info3, poolno, NULL, NULL);
+	  result_t *res = ODBc_get_data(handle, NULL, info3, poolno, 1, ndata, false, NULL);
+	  if (res) {
+	    int j, nr = res->nrows_out;
+	    unsigned int *idxdata;
+	    ALLOC(idxdata, nr);
+	    for (j=0; j<nr; j++) {
+	      int rowid = res->row_wise ? res->d[j][0] : res->d[0][j];
+	      idxdata[j] = rowid - 1;
+	    }
+	    nrows_out = nr;
+	    res = ODBc_unget_data(res);
+	    if (idxtype == 1) {
+	      ndata = nr;
+	    }
+	    else if (idxtype == 2) {
+	      unsigned int *bitmap;
+	      const int maxbits = MAXBITS;
+	      ndata = RNDUP_DIV(nrows, maxbits);
+	      CALLOC(bitmap, ndata);
+	      codbit_setidx_(bitmap,&nrows,&maxbits,idxdata,&nr);
+	      FREE(idxdata);
+	      idxdata = bitmap;
+	    }
+	    idxset->value = NULL;
+	    idxset->ndata = ndata;
+	    idxset->idxlen = ndata;
+	    idxset->idxdata = idxdata;
+	  } /* if (res) */
+	} /* if (ncols > 0) ... else ... */
+	pp->idxset = idxset;
+      }
+      else {
+	pp->idxset = NULL;
+	pp->nsets = 0;
+      }
+    }
+  }
+ finish:
+  if (Nrows) *Nrows = nrows_out;
+  DRHOOK_END(0);
+  return idx;
+}
diff --git a/odb/src/aux/info.c b/odb/src/aux/info.c
new file mode 100644
index 0000000..043cbf4
--- /dev/null
+++ b/odb/src/aux/info.c
@@ -0,0 +1,2474 @@
+
+/* info.c */
+
+/* Reads ODB INFO-file and returns query parameters
+   back in a more digested form */
+
+#include "odb.h"
+#include "info.h"
+#include "result.h"
+#include "evaluate.h"
+#include "magicwords.h"
+#include "idx.h"
+#include "cdrhook.h"
+
+#define IN_DATABASE              0x00000001ull
+#define IN_VIEWNAME              0x00000002ull
+#define IN_FROM                  0x00000004ull
+#define IN_SELECT                0x00000008ull
+#define IN_WHERESYM              0x00000010ull
+#define IN_ORDERBY               0x00000020ull
+#define IN_UNIQUEBY              0x00000040ull
+#define IN_WHERECOND             0x00000080ull
+#define IN_PREFETCH              0x00000100ull
+#define IN_LINKS                 0x00000200ull
+#define IN_SET                   0x00000400ull
+#define IN_WHERECOND_AND         0x00000800ull
+#define IN_HAS_SELECT_DISTINCT   0x00001000ull
+#define IN_HAS_AGGRFUNCS         0x00002000ull
+#define IN_NICKNAME              0x00004000ull
+#define IN_ERROR_CODE            0x00008000ull
+#define IN_MAXCOLS               0x00010000ull
+#define IN_STRINGS               0x00020000ull
+#define IN_COLAUX                0x00040000ull
+#define IN_HAS_COUNT_STAR        0x00080000ull
+#define IN_SQL_QUERY             0x00100000ull
+#define IN_HAS_THIN              0x00200000ull
+#define IN_CREATE_INDEX          0x00400000ull
+#define IN_USE_INDICES           0x00800000ull
+#define IN_USE_INDEX_NAME        0x01000000ull
+#define IN_BINARY_INDEX          0x02000000ull
+#define IN_SRCPATH               0x04000000ull
+#define IN_DATAPATH              0x08000000ull
+#define IN_IDXPATH               0x10000000ull
+#define IN_POOLMASK              0x20000000ull
+
+PRIVATE FILE *fp_echo = NULL; /* Not thread-safe yet */
+
+PUBLIC FILE *
+ODBc_debug_fp(FILE *fp_debug)
+{ /* Not thread-safe yet */
+  FILE *old_fp = fp_echo;
+  fp_echo = fp_debug;
+  return old_fp;
+}
+
+PUBLIC FILE *
+ODBc_get_debug_fp()
+{ /* Not thread-safe yet */
+  return fp_echo;
+}
+
+PRIVATE int CountChars(const char *s, char ch)
+{
+  int cnt = 0;
+  if (s && ch) {
+    while (*s) {
+      if (*s == ch) ++cnt;
+      ++s;
+    }
+  }
+  return cnt;
+}
+
+PRIVATE char *
+MassageLinkName(const char *s, Bool linklen)
+{
+  char *name = STRDUP(s);
+  char *p = name;
+  char *child = NULL;
+  char *parent = NULL;
+  DRHOOK_START(MassageLinkName);
+  p = name;
+  while (*p) {
+    char ch = *p;
+    if (ch == '(' && !child) {
+      child = ++p;
+    }
+    else if (ch == ')' && child) {
+      *p++ = '\0';
+    }
+    else if (ch == '@' && child && !parent) {
+      parent = ++p;
+    }
+    else {
+      ch = ToLower(ch);
+      *p++ = ch;
+    }
+  }
+  if (child && parent) {
+    int len = STRLEN(child) + STRLEN(parent) + 3;
+    len += (linklen ? STRLEN("len") : STRLEN("offset"));
+    ALLOC(p, len);
+    snprintf(p, len, "%s.%s@%s", child, linklen ? "len" : "offset", parent);
+    FREE(name);
+    name = STRDUP(p);
+  }
+  else { /* No luck */
+    FREE(name);
+    name = STRDUP(s);
+  }
+  DRHOOK_END(0);
+  return name;
+}
+
+PRIVATE Bool
+has_ll(const char *s)
+{
+  Bool haz = (s && strstr(s, "degrees(")) ? true : false;
+  if (!haz && s) haz = (strstr(s, "radians(")) ? true : false;
+  if (!haz && s) haz = (strstr(s, "Inside(")) ? true : false;
+  if (!haz && s) haz = (strstr(s, "InPolygon(")) ? true : false;
+  if (!haz && s) haz = (strstr(s, "Near(")) ? true : false;
+  return haz;
+}
+
+PRIVATE Bool
+has_links(const char *s)
+{
+  Bool haz = (s && strstr(s, "LINKLEN(")) ? true : false;
+  if (!haz && s) haz = (strstr(s, "LINKOFFSET(")) ? true : false;
+  return haz;
+}
+
+PRIVATE char *
+CheckAgainstLinks(char *s, const info_t *info)
+{
+  DRHOOK_START(CheckAgainstLinks);
+  if (s && info) {
+    if (has_links(s)) {
+      char *name = STRDUP(s); /* Note, that the length of 's' does never INCREASE in the process */
+      int j, n;
+
+      /* Check against prefetched links first */
+      n = info->nprefetch;
+      for (j=0; j<n; j++) {
+	if (has_links(name)) { /* still has links */
+	  col_t *colthis = &info->p[j];
+	  /* Using function 'ReplaceSubStrings' from lib/evaluate.c */
+	  char *new = ReplaceSubStrings(name,                /* 'haystack' */
+					colthis->fetch_name, /* 'needle' */
+					colthis->name,       /* 'repl_with' */
+					true,                /* 'all_occurences' */
+					false,               /* 'remove_white_space' */
+					false);              /* 'ignore_case' */
+	  FREE(name);
+	  name = new;
+	}
+	else
+	  goto done;
+      } /* for (j=0; j<n; j++) */
+
+      /* Check against links in select-symbols */
+      n = info->ncols;
+      for (j=0; j<n; j++) {
+	if (has_links(name)) { /* still has links */
+	  col_t *colthis = &info->c[j];
+	  if (colthis->dtnum == DATATYPE_LINKOFFSET || 
+	      colthis->dtnum == DATATYPE_LINKLEN) {
+	    /* Using function 'ReplaceSubStrings' from lib/evaluate.c */
+	    char *new = ReplaceSubStrings(name,                /* 'haystack' */
+					  colthis->fetch_name, /* 'needle' */
+					  colthis->name,       /* 'repl_with' */
+					  true,                /* 'all_occurences' */
+					  false,               /* 'remove_white_space' */
+					  false);              /* 'ignore_case' */
+	    FREE(name);
+	    name = new;
+	  }
+	}
+	else
+	  goto done;
+      } /* for (j=0; j<n; j++) */
+
+      /* Check against links in where-symbols */
+      n = info->nwhere;
+      for (j=0; j<n; j++) {
+	if (has_links(name)) { /* still has links */
+	  col_t *colthis = &info->w[j];
+	  if (colthis->dtnum == DATATYPE_LINKOFFSET || colthis->dtnum == DATATYPE_LINKLEN) {
+	    /* Using function 'ReplaceSubStrings' from lib/evaluate.c */
+	    char *new = ReplaceSubStrings(name,                /* 'haystack' */
+					  colthis->fetch_name, /* 'needle' */
+					  colthis->name,       /* 'repl_with' */
+					  true,                /* 'all_occurences' */
+					  false,               /* 'remove_white_space' */
+	                                  false);              /* 'ignore_case' */
+	    FREE(name);
+	    name = new;
+	  }
+	}
+	else
+	  goto done;
+      } /* for (j=0; j<n; j++) */
+
+    done:
+      strcpy(s, name);
+    }
+  }
+  DRHOOK_END(0);
+  return s;
+}
+
+#define CHECK_SIZE(ds, x, num, cnt) \
+if (ds->num < cnt) { \
+  REALLOC(ds->x, cnt); \
+  ds->num = cnt; \
+}
+
+#define INVALID_INPUT(p, nelem, got) { \
+  fprintf(stderr,"***Error in %s:%d: Invalid input line = '%s'\n",__FILE__,__LINE__,p); \
+  fprintf(stderr,"                   Expecting %d elements, but got %d.\n",nelem,got); \
+  RAISE(SIGABRT); \
+}
+
+#define GET_THESE(x, num) \
+CHECK_SIZE(info, x, num, cnt); \
+{ \
+  /* nelem = sscanf(p,"%d %s\t%d %d %d",&flag,s,&bitpos,&bitlen,&ioffset); */ \
+  char *p_space = NULL; \
+  char *p_tab = NULL; \
+  nelem = 0; \
+  p_space = strchr(p,' '); \
+  p_tab = strchr(p,'\t'); \
+  nelem = sscanf(p,"%d",&flag); \
+  if (nelem == 1 && p_space && p_tab) { \
+    while(p_space < p_tab && isspace(*p_space)) p_space++; \
+    if (p_space < p_tab) { \
+      *p_tab++ = '\0'; \
+      strcpy(s,p_space); nelem++; \
+      nelem += sscanf(p_tab,"%d %d %d",&bitpos,&bitlen,&ioffset); \
+    } \
+  } \
+}\
+if (nelem == 5) { \
+  uint dtnum; \
+  col_t *colthis = &info->x[j]; \
+  char *dtype = s; \
+  p = strchr(s,':'); \
+  if (p) { *p++ = '\0'; } else { p = s; dtype = "Formula"; } \
+  colthis->dtype = STRDUP(dtype); \
+  dtnum = get_dtnum(dtype); \
+  if (dtnum == DATATYPE_BITFIELD && bitlen > 0) { \
+    /* remove the member part, since all we need is in (bitpos,bitlen) */ \
+    char *tmp = STRDUP(p); \
+    char *ptmp = tmp; \
+    char *pp = p; \
+    Bool take = true; \
+    while (*pp) { \
+      if (*pp == '.') take = false; \
+      else if (*pp == '@') take = true; \
+      if (take) *ptmp++ = *pp; \
+      pp++; \
+    } \
+    *ptmp = '\0'; \
+    colthis->fetch_name = STRDUP(tmp); \
+    FREE(tmp); \
+    dtnum = DATATYPE_INT4; \
+    colthis->name = STRDUP(p); \
+  } \
+  else if (dtnum == DATATYPE_LINKOFFSET || dtnum == DATATYPE_LINKLEN) { \
+    colthis->fetch_name = STRDUP(p); \
+    colthis->name = MassageLinkName(p, (dtnum == DATATYPE_LINKLEN) ? true : false); \
+  } \
+  else { \
+    colthis->fetch_name = STRDUP(p); \
+    colthis->name = STRDUP(p); \
+    if (IS_(UNIQNUM,colthis->name)) dtnum = DATATYPE_UINT8; \
+  } \
+  colthis->dtnum = dtnum; \
+  colthis->nickname = NULL; \
+  colthis->kind = flag; \
+  colthis->bitpos = bitpos; \
+  colthis->bitlen = bitlen; \
+  colthis->ioffset = ioffset; \
+  colthis->table_id = -1; \
+  colthis->t = NULL; \
+  colthis->dsym = NULL; \
+  colthis->dinp = NULL; \
+  colthis->dinp_len = 0; \
+  colthis->dinp_alloc = false; \
+  colthis->formula_ptree = NULL; \
+  colthis->formula_ptree_owner = false; \
+} \
+else { \
+  INVALID_INPUT(p, 5, nelem); \
+}
+
+#define COPY_THESE(x,j,cin) \
+{ \
+  col_t *c = &info->x[j]; \
+  c->name = STRDUP(cin->name); \
+  c->fetch_name = cin->fetch_name ? STRDUP(cin->fetch_name) : STRDUP(cin->name); \
+  c->nickname = cin->nickname ? STRDUP(cin->nickname) : NULL; \
+  c->dtnum = (cin->dtnum != DATATYPE_UNDEF) ? cin->dtnum : get_dtnum("double"); \
+  c->dtype = STRDUP(cin->dtype); \
+  c->kind = 1; \
+  c->bitpos = 0; \
+  c->bitlen = 0; \
+  c->ioffset = 0; \
+  c->table_id = cin->table_id; \
+  c->t = cin->t; \
+  c->dsym = NULL; \
+  c->dinp = NULL; \
+  c->dinp_len = 0; \
+  c->dinp_alloc = false; \
+  c->formula_ptree = NULL; \
+  c->formula_ptree_owner = false; \
+}
+
+#define HARDCOPY_THESE(x,j,Cin) \
+{ \
+  col_t *c = &info->x[j]; \
+  col_t *cin = Cin; \
+  memcpy(c, cin, sizeof(*c)); \
+  cin->name = NULL; \
+  cin->fetch_name = NULL; \
+  cin->nickname = NULL; \
+  cin->dtype = NULL; \
+  cin->dsym = NULL; \
+  cin->dinp = NULL; \
+  cin->dinp_len = 0; \
+  cin->dinp_alloc = false; \
+  cin->formula_ptree = NULL; \
+  cin->formula_ptree_owner = false; \
+}
+
+#define FILL_TABLE_ID(x, num, do_test, is_select) \
+{ \
+  int j; \
+  for (j=0; j<num; j++) { \
+    int i; \
+    col_t *colthis = &info->x[j]; \
+    const char *hash = IS_HASH(colthis->name) ? colthis->name : NULL; \
+    const char *at = colthis->name ? strchr(colthis->name,'@') : NULL; \
+    colthis->table_id = -1; /* Initialization */ \
+    colthis->t = NULL; /* Initialization */ \
+    if ((!at && !hash) || (do_test && (colthis->kind == 2 || colthis->kind == 4))) { \
+      continue; \
+    } \
+    else if (at++) { \
+      const char *poffset = GET_OFFSET(at); \
+      int len = poffset ? (int)(poffset - at) : STRLEN(at); \
+      for (i=0; i<info->nfrom; i++) { \
+	if (strnequ(info->t[i].name,at,len)) { \
+	  colthis->table_id = i; \
+	  colthis->t = &info->t[i]; \
+          if (is_select) colthis->t->in_select_clause = true; \
+	  break; \
+	} \
+      } /* for (i=0; i<info->nfrom; i++) */ \
+    } \
+    else if (hash) { \
+      ++hash; \
+      for (i=0; i<info->nfrom; i++) { \
+	if (strequ(info->t[i].name,hash)) { \
+	  colthis->table_id = i; \
+	  colthis->t = &info->t[i]; \
+          if (is_select) colthis->t->in_select_clause = true; \
+	  break; \
+	} \
+      } /* for (i=0; i<info->nfrom; i++) */ \
+    } \
+  } /* for (j=0; j<num; j++) */ \
+}
+
+
+typedef struct _RunOnce_t {
+  char *cmd;
+  uresult_t u;
+  int refcount;
+  struct _RunOnce_t *next;
+} RunOnce_t;
+
+
+PRIVATE RunOnce_t *
+Init_RunOnceCheck()
+{
+  RunOnce_t *ro;
+  CALLOC(ro, 1);
+  return ro;
+}
+
+PRIVATE RunOnce_t *
+Destroy_RunOnceCheck(RunOnce_t *ro)
+{
+  while (ro) {
+    RunOnce_t *ro_next = ro->next;
+    FREE(ro->cmd);
+    FREE(ro);
+    ro = ro_next;
+  }
+  return NULL;
+}
+
+PRIVATE RunOnce_t *
+Find_RunOnceCheck(RunOnce_t *ro, const char *cmd)
+{
+  while (ro) {
+    if (strequ(ro->cmd, cmd)) return ro;
+    ro = ro->next;
+  }
+  return NULL;
+}
+
+PRIVATE char *
+Do_RunOnceCheck(RunOnce_t *ro, 
+		char *w /* note: must be FREE'able !! */,
+		Bool EvalMe)
+{
+  if (ro && w) {
+    const char *key = EvalMe ? "EvalMe(" : "RunOnceQuery(";
+    int keylen = STRLEN(key);
+    for (;;) {
+      const char *p = w;
+      const char *str = strstr(p, key);
+      if (str) {
+	const char *pstart = str;
+	const char *pend = NULL;
+	int paren = 1;
+	p = str + keylen;
+	while (*p && paren > 0) {
+	  if (*p == '(') paren++;
+	  else if (*p == ')') paren--;
+	  if (paren == 0) pend = p;
+	  p++;
+	}
+	if (pend) {
+	  int iret = 0;
+	  double value = 0;
+	  void *parse_tree = NULL;
+	  char valstr[100];
+	  char *cmd = NULL;
+	  int cmdlen = pend - pstart + 1;
+	  RunOnce_t *found = NULL;
+	  ALLOCX(cmd, cmdlen + 1);
+	  snprintf(cmd,cmdlen+1,"%*.*s",cmdlen,cmdlen,pstart);
+	  found = Find_RunOnceCheck(ro, cmd);
+
+	  if (found) {
+	    /* Already ran once !! */
+	    if (EvalMe) {
+	      parse_tree = found->u.parse_tree;
+	    }
+	    else {
+	      value = found->u.alias;
+	    }
+	    found->refcount++;
+	  }
+	  else {
+	    RunOnce_t *ro_save = ro;
+	    if (EvalMe) {
+	      /* Evalme(<expr>) --> only <expr> will be passed to the ParseTree */
+	      char *expr = STRDUP(cmd + keylen);
+	      char *closing_paren = strrchr(expr, ')');
+	      if (closing_paren) *closing_paren = '\0';
+	      parse_tree = ParseTree(expr, &iret);
+	      ODB_fprintf(fp_echo,
+			  "Do_RunOnceCheck for Evalme of '%s' [iret = %d] : parse_tree = %p\n",
+			  expr, iret, parse_tree);
+	      FREE(expr);
+	    }
+	    else {
+	      value = Run(cmd, &iret, NULL, NULL, NULL, true);
+	    }
+	    if (iret != 0) {
+	      /* Should not happen with */
+	      fprintf(stderr, 
+		      "***Error in Do_RunOnceCheck() [iret = %d] : Could not %s '%s'\n",
+		      iret,
+		      EvalMe ? "create parse-tree on" : "evaluate",
+		      cmd);
+	      RAISE(SIGABRT);
+	    }
+	    while (ro) {
+	      if (!ro->cmd) {
+		ro->cmd = STRDUP(cmd);
+		if (EvalMe) {
+		  ro->u.parse_tree = parse_tree;
+		}
+		else {
+		  ro->u.alias = value;
+		}
+		ro->refcount = 1;
+		found = ro;
+		break;
+	      }
+	      else if (!ro->next) {
+		ro->next = Init_RunOnceCheck();
+	      }
+	      ro = ro->next;
+	    } /* while (ro) */
+	  }
+
+	  if (found->u.i[0] == 0 && found->u.i[1] == 0) {
+	    strcpy(valstr,"0");
+	  }
+	  else {
+	    snprintf(valstr, sizeof(valstr), 
+		     "Conv_llu2double(%d, %d)",
+		     found->u.i[0], found->u.i[1]);
+	  }
+	  
+	  {
+	    /* Replace {RunOnceQuery(...)|EvalMe(...)} with Conv_llu2double(...) */
+	    char *new = ReplaceSubStrings(w,                /* 'haystack' */
+					  cmd,              /* 'needle' */
+					  valstr,           /* 'repl_with' */
+					  true,             /* 'all_occurences' */
+					  false,            /* 'remove_white_space' */
+					  false);           /* 'ignore_case' */
+	    FREE(w);
+	    w = new;
+	  }
+
+	  FREEX(cmd);
+	} /* if (pend) */
+      }
+      else
+	break; /* for (;;) */
+    } /* for (;;) */
+  } /* if (ro && w) */
+  return w;
+}
+
+
+PUBLIC void *
+ODBc_make_setvars(const char *varvalue, int *nsetvar)
+{
+  int n = 0;
+  set_t *setvar = NULL;
+  DRHOOK_START(ODBc_make_setvars);
+
+  if (varvalue && !strequ(varvalue,"-") && strchr(varvalue,'=')) {
+    const char *delim = ",";
+    char *var = STRDUP(varvalue);
+    char *token = strtok(var,delim);
+    while (token) {
+      char *ss = STRDUP(token);
+      char *t = strchr(ss,'=');
+      if (t) {
+	int j = n++;
+	char *lhs = ss;
+	char *rhs = t + 1;
+	char *comma = strchr(rhs,',');
+	int len_lhs, len_rhs;
+	*t = '\0';
+	if (comma) *comma = '\0';
+	if (*lhs == '$') ++lhs;
+	len_lhs = STRLEN(lhs);
+	len_rhs = STRLEN(rhs);
+	REALLOC(setvar, n);
+	ALLOC(setvar[j].name, len_lhs + 2);
+	snprintf(setvar[j].name, len_lhs + 2, "$%s", lhs);
+	setvar[j].value = STRLEN(rhs) > 0 ? atof(rhs) : 0;
+      } /* if (t) */
+      FREE(ss);
+      token = strtok(NULL,delim);
+    } /* while (token) */
+    FREE(var);
+  }
+
+  if (nsetvar) *nsetvar = n;
+  DRHOOK_END(0);
+  return setvar;
+}
+
+
+#if defined(MAXLINE)
+#undef MAXLINE
+#endif
+#define MAXLINE    65536
+
+static Bool MakePlotColumns(info_t *info_inout, Bool warrow,
+			    int latcol, int loncol, int colorcol, int ucol, int vcol);
+
+static Bool HasSimpleWHEREcond(const info_t *info, table_t *t, col_t *w, int nwhere, const set_t *set, int nset);
+
+PUBLIC void *
+ODBc_get_info(const char *info_file_or_pipe, const set_t *setvar, int nsetvar)
+{
+  info_t *info_chain = NULL;
+  DRHOOK_START(ODBc_get_info);
+  {
+    Bool is_stdin = strequ(info_file_or_pipe,"stdin") ? true : false;
+    Bool is_pipe = (info_file_or_pipe && (info_file_or_pipe[0] == '|')) ? true : false;
+    FILE *fp = NULL;
+    if (is_stdin) {
+      fp = stdin;
+    }
+    else if (is_pipe) {
+      fp = popen(++info_file_or_pipe,"r");
+    }
+    else {
+      fp = fopen(info_file_or_pipe,"r");
+    }
+    if (fp) {
+      Bool is_plotobs = ODBc_test_format_1("plotobs");
+      Bool warrow = ODBc_test_format_1("wplotobs");
+      info_t *info = NULL;
+      char *dir = NULL;
+      char *host = NULL;
+      char *tstamp = NULL;
+      u_ll_t in = 0;
+      int cnt = 0;
+      table_t *twa = NULL;
+      Bool first_and = false;
+      int errflg = 0;
+      char buf[MAXLINE];
+      while ( fgets(buf,sizeof(buf),fp) ) {
+	char *nl = strchr(buf,'\n');
+	if (nl) *nl = '\0';
+	ODB_fprintf(fp_echo,"%s\n",buf);
+	
+	if (!in && strnequ(buf,"INFO",4)) {
+	  char *env = NULL;
+	  if (info) {
+	    CALLOC(info->next, 1);
+	    info = info->next;
+	  }
+	  else {
+	    CALLOC(info,1);
+	    info_chain = info;
+	  }
+	  info->has_ll = false;
+	  info->latlon_rad = -1; /* undefined */
+	  env = getenv("ODB_LATLON_RAD");
+	  if (env) {
+	    info->latlon_rad = atoi(env);
+	    codb_change_latlon_rad_(&info->latlon_rad);
+	  }
+
+	  env = getenv("ODB_LAT");
+	  CALLOC(info->odb_lat, 1);
+	  info->odb_lat->name = env ? STRDUP(env) : STRDUP("lat at hdr");
+
+	  env = getenv("ODB_LON");
+	  CALLOC(info->odb_lon, 1);
+	  info->odb_lon->name = env ? STRDUP(env) : STRDUP("lon at hdr");
+
+	  env = getenv("ODB_DATE");
+	  CALLOC(info->odb_date, 1);
+	  info->odb_date->name = env ? STRDUP(env) : STRDUP("date at hdr");
+
+	  env = getenv("ODB_TIME");
+	  CALLOC(info->odb_time, 1);
+	  info->odb_time->name = env ? STRDUP(env) : STRDUP("time at hdr");
+
+	  env = getenv("ODB_COLOR");
+	  CALLOC(info->odb_color, 1);
+	  if (warrow) {
+	    info->odb_color->name = env ? STRDUP(env) : STRDUP("speed");
+	  }
+	  else {
+	    info->odb_color->name = env ? STRDUP(env) : STRDUP("obsvalue at body");
+	  }
+
+	  env = getenv("ODB_U");
+	  CALLOC(info->odb_u, 1);
+	  info->odb_u->name = env ? STRDUP(env) : STRDUP("obsvalue at body");
+
+	  env = getenv("ODB_V");
+	  CALLOC(info->odb_v, 1);
+	  info->odb_v->name = env ? STRDUP(env) : STRDUP("obsvalue at body#1"); /* offset(obsvalue at body,1) */
+
+	  in = 0;
+	  cnt = 0;
+	  twa = NULL;
+	  first_and = false;
+	}
+	else if (!in && buf[0] != '/') {
+	  continue;
+	}
+	else if (strnequ(buf,"/end ",5)) {
+	  in = 0;
+	  cnt = 0;
+	  twa = NULL;
+	  first_and = false;
+	}
+	else if (!in && buf[0] == '/') {
+	  char *eq = strchr(buf,'=');
+	  if (eq) { /* /xxx=yyy */
+	    char *key = buf;
+	    *eq++ = '\0';
+	    while (isspace(*eq)) eq++;
+	    if (strequ(key,"/dir")) {
+	      if (dir) FREE(dir);
+	      dir = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/host")) {
+	      if (host) FREE(host);
+	      host = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/tstamp")) {
+	      if (tstamp) FREE(tstamp);
+	      tstamp = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/database")) {
+	      info->dbcred.dbname = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/srcpath")) {
+	      info->dbcred.srcpath = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/datapath")) {
+	      info->dbcred.datapath = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/idxpath")) {
+	      info->dbcred.idxpath = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/poolmask")) {
+	      info->dbcred.poolmask = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/viewname")) {
+	      info->view = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/use_index_name")) {
+	      info->use_index_name = STRDUP(eq);
+	    }
+	    else if (strequ(key,"/has_select_distinct")) {
+	      info->has_select_distinct = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/has_count_star")) {
+	      info->has_count_star = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/has_aggrfuncs")) {
+	      info->has_aggrfuncs = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/has_thin")) {
+	      info->has_thin = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/use_indices")) {
+	      info->use_indices = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/binary_index")) {
+	      info->binary_index = strequ(eq,"1") ? true : false;
+	    }
+	    else if (strequ(key,"/maxcols")) {
+	      int maxcols = atoi(eq);
+	      if (maxcols <= 0) maxcols = ODB_maxcols(); /* Shouldn't happen */
+	      info->maxcols = maxcols;
+	    }
+	    else if (strequ(key,"/create_index")) {
+	      int ci = atoi(eq);
+	      info->create_index = ci;
+	    }
+	    else if (strequ(key,"/error_code")) {
+	      int error_code = atoi(eq);
+	      if (info) {
+		info->error_code = error_code;
+	      }
+	      if (error_code != 0) errflg++;
+	    }
+	    in = 0;
+	    cnt = 0;
+	    twa = NULL;
+	    first_and = false;
+	  }
+	  else { /* /xxx number */
+	    char key[20];
+	    int num;
+	    int nelem = sscanf(buf,"%s %d",key,&num);
+	    if (nelem == 2) {
+	      int nalloc = (num > 0) ? num : 1;
+	      cnt = 0;
+	      if (strequ(key,"/from")) {
+		/* Here "num" must be >= 0 , with "0" meaning a table-less query */
+		if (num < 0) num = 0;
+		info->nfrom = num;
+		if (num > 0) {
+		  CALLOC(info->t, nalloc);
+		}
+		in = IN_FROM;
+	      }
+	      else if (strequ(key,"/select")) {
+		if (num < 0) num = 0;
+		info->ncols = num;
+		info->ncols_true = 0;
+		CALLOC(info->c, nalloc);
+		in = IN_SELECT;
+	      }
+	      else if (strequ(key,"/wheresym")) {
+		/* Column variables referenced in the WHERE-condition */
+		if (num < 0) num = 0;
+		info->nwhere = num;
+		CALLOC(info->w, nalloc);
+		in = IN_WHERESYM;
+	      }
+	      else if (strequ(key,"/wherecond")) {
+		/* WHERE-condition */
+		if (num < 0) num = 0;
+		CALLOC(info->wherecond, nalloc);
+		in = IN_WHERECOND;
+	      }
+	      else if (strequ(key,"/wherecond_and")) {
+		/* WHERE AND-condition : one or more per table */
+		/* num is now table id reference [0..nfrom-1] */
+		int idx = num;
+		twa = (info->t && idx >= 0 && idx < info->nfrom) ? &info->t[idx] : NULL;
+		if (twa) {
+		  in = IN_WHERECOND_AND;
+		  first_and = true;
+		}
+	      }
+	      else if (strequ(key,"/orderby")) {
+		if (num < 0) num = 0;
+		info->norderby = num;
+		CALLOC(info->o, nalloc);
+		in = IN_ORDERBY;
+	      }
+	      else if (strequ(key,"/uniqueby")) {
+		if (num < 0) num = 0;
+		info->nuniqueby = num;
+		CALLOC(info->u, nalloc);
+		in = IN_UNIQUEBY;
+	      }
+	      else if (strequ(key,"/strings")) {
+		if (num < 0) num = 0;
+		info->ns2d = num;
+		CALLOC(info->s2d, nalloc);
+		in = IN_STRINGS;
+	      }
+	      else if (strequ(key,"/prefetch")) {
+		if (num < 0) num = 0;
+		info->nprefetch = num;
+		CALLOC(info->p, nalloc);
+		in = IN_PREFETCH;
+	      }
+	      else if (strequ(key,"/links")) {
+		in = IN_LINKS;
+	      }
+	      else if (strequ(key,"/colaux")) {
+		if (num < 0) num = 0;
+		info->ncolaux = num;
+		CALLOC(info->colaux, nalloc);
+		in = IN_COLAUX;
+	      }
+	      else if (strequ(key,"/set")) {
+		if (num < 0) num = 0;
+		info->nset = num;
+		CALLOC(info->s, nalloc);
+		in = IN_SET;
+	      }
+	      else if (strequ(key,"/nickname")) {
+		/* Assume that this comes always LATER than "/select" */
+		in = IN_NICKNAME;
+	      }
+	      else if (strequ(key,"/sql_query")) {
+		/* SQL-query string */
+		if (num < 0) num = 0;
+		CALLOC(info->sql_query, nalloc);
+		in = IN_SQL_QUERY;
+	      }
+	    }
+	    else {
+	      INVALID_INPUT(buf, 2, nelem);
+	    } /* if (nelem == 2) ... else ... */
+	  } /* if (eq) ... else ... */
+	}
+	else if (in) {
+	  int j;
+	  char *p = buf;
+	  int len, nelem, flag, idx;
+	  int bitpos, bitlen, ioffset;
+	  char *s = NULL;
+	  while (isspace(*p)) p++;
+	  len = strlen(p);
+	  j = cnt++;
+	  ALLOC(s, len+1);
+	  switch (in) {
+	  case IN_FROM:
+	    CHECK_SIZE(info, t, nfrom, cnt);
+	    nelem = sscanf(p,"%d %s",&idx,s);
+	    if (nelem == 2 && idx >= 0 && idx < info->nfrom) {
+	      table_t *t = &info->t[idx];
+	      t->name = STRDUP(s);
+	      t->table_id = idx;
+	      t->linkparent_id = -1;
+	      t->offset_parent_id = -1;
+	      t->b = NULL;
+	      t->e = NULL;
+	      t->prev = NULL;
+	      t->next = NULL;
+	      t->linkparent = NULL;
+	      t->offset_parent = NULL;
+	      t->linkoffset = NULL;
+	      t->linklen = NULL;
+	      t->jr = -1;
+	      t->lo =  0;
+	      t->ob = -1;
+	      t->linkcase = -1;
+	      t->offset = NULL;
+	      t->len = NULL;
+	      t->info = NULL;
+	      t->nrows = 0;
+	      t->ncols = 0;
+	      t->idx = NULL;
+	      t->wherecond_and = NULL;
+	      t->wherecond_and_ptree = NULL;
+	      t->in_select_clause = false;
+	      t->simple_wherecond = false;
+	      t->skiprow = NULL;
+	      t->nwl = 0;
+	      t->wl = NULL;
+	      t->stored_idx_count = 0;
+	    }
+	    else {
+	      INVALID_INPUT(p, 2, nelem);
+	    }  /* if (nelem == 2) ... else ... */
+	    break;
+	  case IN_SELECT:
+	    GET_THESE(c, ncols);
+	    info->ncols_pure += (info->c[j].kind == 1);
+	    info->ncols_formula += (info->c[j].kind == 2);
+	    info->ncols_aggr_formula += (info->c[j].kind == 4);
+	    info->ncols_aux += (info->c[j].kind == 8);
+	    info->ncols_nonassoc += (info->c[j].kind == 0);
+	    break;
+	  case IN_NICKNAME:
+	    {
+	      const char *nickname = strchr(p, ' ');
+	      nelem = sscanf(p,"%d ",&idx);
+	      if (nelem == 1 && nickname && idx >= 0 && idx < info->ncols) {
+		col_t *colthis = &info->c[idx];
+		nickname++;
+		FREE(colthis->nickname);
+		colthis->nickname = STRDUP(nickname);
+	      }
+	      else {
+		INVALID_INPUT(p, 1, nelem);
+	      }
+	    }
+	    break;
+	  case IN_WHERESYM:
+	    GET_THESE(w, nwhere);
+	    break;
+	  case IN_PREFETCH:
+	    GET_THESE(p, nprefetch);
+	    break;
+	  case IN_ORDERBY:
+	    GET_THESE(o, norderby);
+	    break;
+	  case IN_UNIQUEBY:
+	    GET_THESE(u, nuniqueby);
+	    break;
+	  case IN_STRINGS:
+	    CHECK_SIZE(info, s2d, ns2d, cnt);
+	    {
+	      int lenstr = 0;
+	      nelem = sscanf(p, "%d,%d ", &idx, &lenstr);
+	      if (nelem == 2 && idx >= 0 && idx < info->ns2d && lenstr >= 0) {
+		const char *s2d_value = strchr(p, ' ');
+		str_t *s2d = &info->s2d[idx];
+		int len = S2DlcLEN + 30;
+		ALLOC(s2d->name, len);
+		snprintf(s2d->name,len,"%s%d",S2Dlc,idx); /* symbol name "s2d_<number>" */
+		s2d_value++;
+		s2d->value = STRDUP(s2d_value);
+		s2d->u.saddr = s2d->value; /* ==> "s2d->u.dval" is aliased address to the value-char */
+		putsym(s2d->name, s2d->u.dval);
+	      }
+	      else {
+		INVALID_INPUT(p, 2, nelem);
+	      }
+	    }
+	    break;
+	  case IN_LINKS:
+	    CHECK_SIZE(info, t, nfrom, cnt);
+	    {
+	      int linkparent_id = -1;
+	      int offset_parent_id = -1;
+	      char *b, *e, *off;
+	      ALLOCX(b, len+1);
+	      ALLOCX(e, len+1);
+	      ALLOCX(off, len+1);
+	      nelem = sscanf(p,"%d %s %d %s %s %d %s",
+			     &idx,s,&linkparent_id,b,e,
+			     &offset_parent_id, off);
+	      if (nelem == 7 && idx >= 0 && idx < info->nfrom) {
+		table_t *t = &info->t[idx];
+		/* t->name = STRDUP(s); */
+		t->linkparent_id = linkparent_id;
+		t->offset_parent_id = offset_parent_id;
+		t->b = STRDUP(b);
+		t->e = STRDUP(e);
+	      }
+	      else {
+		INVALID_INPUT(p, 7, nelem);
+	      }  /* if (nelem == 7) ... else ... */
+	      FREEX(b);
+	      FREEX(e);
+	      FREEX(off);
+	    }
+	    break;
+	  case IN_COLAUX:
+	    CHECK_SIZE(info, colaux, ncolaux, cnt);
+	    {
+	      int col_aux;
+	      nelem = sscanf(p, "%d %d", &idx, &col_aux);
+	      if (nelem == 2 && idx >= 0 && idx < info->ncolaux) {
+		info->colaux[idx] = col_aux; /* if > 0, Fortran index to a sibling column in multi-arg aggr */
+	      }
+	      else {
+		INVALID_INPUT(p, 2, nelem);
+	      }
+	    }
+	  case IN_SET:
+	    CHECK_SIZE(info, s, nset, cnt);
+	    {
+	      double value = 0;
+	      nelem = sscanf(p,"%s %lf", s, &value);
+	      if (nelem == 2) {
+		info->s[j].name = STRDUP(s);
+		info->s[j].value = value;
+	      }
+	      else {
+		INVALID_INPUT(p, 2, nelem);
+	      } /* if (nelem == 2) ... else ... */
+	    }
+	    break;
+	  case IN_WHERECOND:
+	    {
+	      int curlen = STRLEN(info->wherecond);
+	      int newlen = curlen + len + 1; /* "+1" for extra blank */
+	      REALLOC(info->wherecond, newlen + 1);
+	      info->wherecond[curlen] = '\0';
+	      strncat(info->wherecond, p, len);
+	      info->wherecond[newlen] = '\0';
+	    }
+	    break;
+	  case IN_SQL_QUERY:
+	    {
+	      int curlen = STRLEN(info->sql_query);
+	      int newlen = curlen + len + 1; /* "+1" for extra newline */
+	      REALLOC(info->sql_query, newlen + 1);
+	      info->sql_query[curlen] = '\0';
+	      strncat(info->sql_query, p, len);
+	      strcat(info->sql_query, "\n");
+	      info->sql_query[newlen] = '\0';
+	    }
+	    break;
+	  case IN_WHERECOND_AND:
+	    if (twa && !strequ(p,"1")) {
+	      int jj = twa->nwl;
+	      const char andies[] = " && ";
+	      const int n_andies = 4;
+	      Bool add_andies = false;
+	      int curlen = STRLEN(twa->wherecond_and);
+	      int newlen = curlen + len;
+	      if (first_and && curlen > 0) {
+		/* we already have previous WHERE-condition here */
+		newlen += n_andies;
+		add_andies = true;
+	      }
+	      CHECK_SIZE(twa, wl, nwl, jj+1);
+	      {
+		simple_where_t *wl = &twa->wl[jj];
+		wl->condstr = STRDUP(p);
+		wl->wcol = NULL; /* WHERE-variable of "lhs" */
+		wl->lhs = NULL;
+		wl->oper = UNKNOWN; /* == Kind_t UNKNOWN as in include/evaluate.h */
+		wl->rhs = 0;
+		wl->stored_idx = NULL;
+	      }
+	      REALLOC(twa->wherecond_and, newlen + 1);
+	      twa->wherecond_and[curlen] = '\0';
+	      if (add_andies) strncat(twa->wherecond_and, andies, n_andies);
+	      strncat(twa->wherecond_and, p, len);
+	      twa->wherecond_and[newlen] = '\0';
+	      first_and = false;
+	    }
+	    break;
+	  } /* switch (in) */
+	  FREE(s);
+	}
+      } /* while ( fgets(buf,sizeof(buf),fp) ) */
+
+      if (is_pipe) {
+	int iret = pclose(fp);
+	if (iret == -1) {
+	  fprintf(stderr,
+		  "***Error: Couldn't close the pipe. Maybe compilation has failed ?\n");
+	  exit(SIGABRT);
+	}
+      }
+      else if (!is_stdin) fclose(fp);
+
+      if (!errflg && info_chain) {
+	int j;
+	info = info_chain;
+	while (info) {
+	  int nfrom = info->nfrom;
+
+	  /* Make sure dir, hots & tstamp are filled in */
+
+	  info->dir = STRDUP(dir);
+	  info->host = STRDUP(host);
+	  info->tstamp = STRDUP(tstamp);
+
+	  info->ncols_true = info->ncols_pure + info->ncols_formula + info->ncols_aggr_formula;
+	  
+	  /* Fill in table ids */
+	  FILL_TABLE_ID(c, info->ncols, 1, true);
+	  FILL_TABLE_ID(o, info->norderby, 0, false);
+	  FILL_TABLE_ID(p, info->nprefetch, 1, false);
+
+	  FILL_TABLE_ID(odb_lat, 1, 0, false);
+	  FILL_TABLE_ID(odb_lon, 1, 0, false);
+	  FILL_TABLE_ID(odb_color, 1, 0, false);
+	  FILL_TABLE_ID(odb_u, 1, 0, false);
+	  FILL_TABLE_ID(odb_v, 1, 0, false);
+
+	  FILL_TABLE_ID(u, info->nuniqueby, 1, false);
+	  FILL_TABLE_ID(w, info->nwhere, 1, false);
+
+	  /* Update SET-variables (IN_SET) */
+
+	  if (setvar && nsetvar > 0) {
+	    int js;
+	    if (!info->s) {
+	      /* Copy all */
+	      ALLOC(info->s, nsetvar);
+	      for (js=0; js<nsetvar; js++) {
+		info->s[js].name = STRDUP(setvar[js].name);
+		info->s[js].value = setvar[js].value;
+	      } /* for (js=0; js<nsetvar; js++) */
+	      info->nset = nsetvar;
+	    }
+	    else {
+	      /* Update selectively & add completely new ones */
+	      int jj, njj = info->nset;
+	      int updcnt = 0;
+	      int *is_updated = NULL;
+	      CALLOC(is_updated, nsetvar);
+	      for (js=0; js<nsetvar; js++) {
+		const char *svname = setvar[js].name;
+		double value = setvar[js].value;
+		for (jj=0; jj<njj; jj++) {
+		  if (strequ(info->s[jj].name, svname)) {
+		    info->s[jj].value = value;
+		    is_updated[js] = 1;
+		    ++updcnt;
+		    break;
+		  }
+		} /* for (jj=0; jj<njj; jj++) */
+	      } /* for (js=0; js<nsetvar; js++) */
+	      if (updcnt > 0) {
+		updcnt += njj;
+		CHECK_SIZE(info, s, nset, updcnt);
+		for (js=0; js<nsetvar; js++) {
+		  if (!is_updated[js]) {
+		    const char *svname = setvar[js].name;
+		    double value = setvar[js].value;
+		    info->s[njj].name = STRDUP(svname);
+		    info->s[njj].value = value;
+		    ++njj;
+		  }
+		} /* for (js=0; js<nsetvar; js++) */
+	      } /* if (updcnt > 0) */
+	      FREE(is_updated);
+	    }
+	  }
+
+	  if (is_plotobs || warrow) {
+	    /* When plotting is concerned, then only the following SELECT-columns are needed
+	       $ODB_LAT, $ODB_LON and (possibly) $ODB_COLOR 
+	       and if warrow == true, check also that BOTH $ODB_U & $ODB_V are there
+	       otherwise reset warrow to false
+	    */
+	    int ncols = info->ncols_true;
+	    int latcol = -1, loncol = -1, colorcol = -1;
+	    int ucol = -1, vcol = -1;
+
+	    for (j=0; j<ncols; j++) {
+	      col_t *colthis = &info->c[j];
+	      if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+		const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+		if (strequ(s, info->odb_lat->name)) latcol = j;
+		else if (strequ(s, info->odb_lon->name)) loncol = j;
+		else if (strequ(s, info->odb_color->name)) colorcol = j;
+		else if (strequ(s, info->odb_u->name)) ucol = j;
+		else if (strequ(s, info->odb_v->name)) vcol = j;
+	      }
+	    }
+	    warrow = MakePlotColumns(info, warrow,
+				     latcol, loncol, colorcol, ucol, vcol);
+	    if (!warrow) {
+	      FREE(info->odb_u->name); info->odb_u->name = STRDUP("\t<N/A>");
+	      FREE(info->odb_v->name); info->odb_v->name = STRDUP("\t<N/A>");
+	    }
+	  } /* if (is_plotobs || warrow) */
+
+	  /* Create ParseTree for SELECT-column entries that are formulas;
+	     Remember to replace occurences of LINKLEN(child)@parent & LINKOFFSET(child)@parent
+	     since the parser in evaluate.c cannot currently stand this syntax !! */
+	  
+	  for (j=0; j<info->ncols; j++) {
+	    col_t *colthis = &info->c[j];
+	    int flag = colthis->kind;
+	    if (flag == 2 || flag == 4) {
+	      int iret = 0;
+	      colthis->name = CheckAgainstLinks(colthis->name, info);
+	      colthis->formula_ptree = ParseTree(colthis->name, &iret);
+	      if (iret != 0 || !colthis->formula_ptree) {
+		fprintf(stderr,
+			"***Error: Could not parse formula '%s' : iret = %d\n",
+			colthis->name, iret);
+		RAISE(SIGABRT);
+	      }
+	      colthis->formula_ptree_owner = true;
+	      if (flag == 4 && info->colaux && j < info->ncolaux) {
+		/* Adjust multi-arg. aggregate function's 2nd (or more) argument */
+		int jj = info->colaux[j];
+		if (jj > info->ncols_true) {
+		  col_t *cs = &info->c[--jj]; /* column of a sibling */
+		  if (cs->kind == 8) {
+		    FREE(cs->name);
+		    cs->name = STRDUP(colthis->name);
+		    cs->formula_ptree = colthis->formula_ptree;
+		    cs->formula_ptree_owner = false;
+		  }
+		}
+	      }
+	      if (!info->has_ll && has_ll(colthis->name)) info->has_ll = true;
+	    }
+	  } /* for (j=0; j<info->ncols; j++) */
+
+	  {
+	    /* Handle EvalMe(S2D_<n>)'s first 
+	       Note: We share the RunOnce_t data structure due to similarities */
+	     RunOnce_t *ro = Init_RunOnceCheck();
+	     char *w = info->wherecond = Do_RunOnceCheck(ro, info->wherecond, true);
+	     if (nfrom > 0) {
+	       /* Also kill all table-specific WHERE-stmts that equal to "1" */
+	       for (j=0; j<nfrom; j++) {
+		 table_t *this = &info->t[j];
+		 char *w = this->wherecond_and = Do_RunOnceCheck(ro, this->wherecond_and, true);
+	       }
+	     }
+	     ro = Destroy_RunOnceCheck(ro);
+	  }
+
+	  {
+	    RunOnce_t *ro = Init_RunOnceCheck();
+
+	    if (info->wherecond) {
+	      /* If the master WHERE-cond equals to "1" i.e. default, kill it */
+	      char *w = info->wherecond = Do_RunOnceCheck(ro, info->wherecond, false);
+	      while (isspace(*w)) w++;
+	      if (strequ(w,"1")) { FREE(info->wherecond); w = NULL; }
+	      if (w && info->nuniqueby == 0
+		  && !strchr(w, '$')
+		  && !strstr(w, "maxrows(")
+		  && !strstr(w, "maxcount(")
+		  && !strstr(w, "Inside(")
+		  && !strstr(w, "InPolygon(")
+		  && !strstr(w, "Near(")
+		  && !strstr(w, "Query(")
+		  ) {
+		/* Check for trivial WHERE, which can be evaluated into a constant value */
+		int iret = 0;
+		double value = Run(w, &iret, NULL, NULL, NULL, true);
+		if (iret == 0) { /* Yes, indeed !! */
+		  FREE(info->wherecond); /* After this always true */
+		  if (value == 0) info->wherecond = STRDUP("0"); /* i.e. never true */
+		}
+	      } /* if (w && info->nuniqueby == 0 & ...) */
+	    }
+	  
+	    if (nfrom > 0) {
+	      /* Also kill all table-specific WHERE-stmts that equal to "1" */
+	      for (j=0; j<nfrom; j++) {
+		table_t *this = &info->t[j];
+		char *w = this->wherecond_and = Do_RunOnceCheck(ro, this->wherecond_and, false);
+		if (w) {
+		  while (isspace(*w)) w++;
+		  if (strequ(w,"1")) { FREE(this->wherecond_and); w = NULL; }
+		  if (w && !strchr(w, '$')
+ 		      && !strstr(w, "Unique(")
+		      && !strstr(w, "maxrows(")
+		      && !strstr(w, "maxcount(")
+		      && !strstr(w, "Inside(")
+		      && !strstr(w, "InPolygon(")
+		      && !strstr(w, "Near(")
+		      && !strstr(w, "Query(")
+		      ) {
+		    /* Check for trivial WHERE, which can be evaluated into a constant value */
+		    int iret = 0;
+		    double value = Run(w, &iret, NULL, NULL, NULL, true);
+		    if (iret == 0) { /* Yes, indeed !! */
+		      FREE(this->wherecond_and); /* After this always true */
+		      if (value == 0) this->wherecond_and = STRDUP("0"); /* i.e. never true */
+		    }
+		  } /* if (w && !strchr(w, '$') && ...) */
+		} /* if (w) */
+	      } /* for (j=0; j<nfrom; j++) */
+	    } /* if (nfrom > 0) */
+
+	    ro = Destroy_RunOnceCheck(ro);
+	  }
+
+	  if (nfrom == 0 && info->wherecond) {
+	    /* Needed for table-less SELECT/WHERE only */
+	    int iret = 0;
+	    info->wherecond = CheckAgainstLinks(info->wherecond, info);
+	    info->wherecond_ptree = ParseTree(info->wherecond, &iret);
+	    if (iret != 0 || !info->wherecond_ptree) {
+	      fprintf(stderr,
+		      "***Error: Could not parse (table-less) WHERE-condition '%s' : iret = %d\n",
+		      info->wherecond, iret);
+	      RAISE(SIGABRT);
+	    }
+	  }
+	  else {
+	    info->wherecond_ptree = NULL;
+	  }
+
+	  for (j=0; j<nfrom; j++) {
+	    int len = 0;
+	    table_t *this = &info->t[j];
+	    int linkparent_id = this->linkparent_id;
+	    int offset_parent_id = this->offset_parent_id;
+	    table_t *tp, *tp_off;
+
+	    if (this->wherecond_and) {
+	      int iret = 0;
+	      this->wherecond_and = CheckAgainstLinks(this->wherecond_and, info);
+	      this->wherecond_and_ptree = ParseTree(this->wherecond_and, &iret);
+	      if (iret != 0 || !this->wherecond_and_ptree) {
+		fprintf(stderr,
+			"***Error: Could not parse WHERE-condition '%s' of table '%s' : iret = %d\n",
+			this->wherecond_and, this->name, iret);
+		RAISE(SIGABRT);
+	      }
+	      if (!info->has_ll && has_ll(this->wherecond_and)) info->has_ll = true;
+	    }
+	    else {
+	      this->wherecond_and_ptree = NULL;
+	    }
+
+	    if (linkparent_id >= 0) {
+	      tp = this->linkparent = &info->t[linkparent_id];
+	    }
+	    else {
+	      tp = this->linkparent = NULL;
+	    }
+
+	    if (offset_parent_id >= 0) {
+	      tp_off = this->offset_parent = &info->t[offset_parent_id];
+	    }
+	    else {
+	      tp_off = this->offset_parent = NULL;
+	    }
+
+	    if (tp_off) {
+	      /* Note: No MassageLinkName here, since linkoffset/linklen below are used as "fetch_name" 
+	               and these will never endup in symbol table */
+	      len = strlen("LINKOFFSET()@") + strlen(this->name) + strlen(tp_off->name) + 1;
+	      ALLOC(this->linkoffset, len);
+	      ALLOC(this->linklen, len);
+	      snprintf(this->linkoffset, len, "LINKOFFSET(%s)@%s", this->name, tp_off->name);
+	      snprintf(this->linklen, len, "LINKLEN(%s)@%s", this->name, tp_off->name);
+	    }
+	    else {
+	      this->linkoffset = NULL;
+	      this->linklen = NULL;
+	    }
+
+	    if (*this->e == '1') { 
+	      /* ONELOOPER i.e. one-to-one relationship between parent & child */
+	      this->linkcase = 1;
+	    }
+	    else if (*this->e == 'A') { 
+	      /* ALIGNed tables child1 & child2 : the same number of rows;
+		 may have different parent-tables though */
+	      this->linkcase = 2;
+	    }
+	    else if (*this->e == '=') { 
+	      /* ALIGNed as in 'A', but orphaned from parent; 
+		 child2 shares common row# with the aligned child1 */
+	      this->linkcase = 3;
+	    }
+	    else if (*this->b != '0' && *this->e == 'N') {
+	      /* A regular link between parent & child ; no ONELOOPERs or ALIGNments */
+	      this->linkcase = 4;
+	    }
+	    else { 
+	      /* The very first table in FROM-statement or 
+		 a completely disconnected/isolated table w.r.t. other tables in FROM-stmt */
+	      /* *this->b == '0' && *this->e == 'N' */
+	      this->linkcase = (j == 0) ? 5 : 6;
+	    }
+
+	    this->offset = NULL;
+	    this->len = NULL;
+	    this->nrows = 0;
+	    this->ncols = 0;
+	    this->idx = NULL;
+	    this->prev = (j   >     0) ? &info->t[j-1] : NULL;
+	    this->next = (j+1 < nfrom) ? &info->t[j+1] : NULL;
+	    this->info = info;
+	  } /* for (j=0; j<nfrom; j++) */
+
+	  /* Fill optimization flags */
+
+	  info->optflags = 0;
+	  if (info->has_count_star && !info->wherecond &&
+	      info->nfrom == 1 && info->ncols == 1 &&
+	      info->has_aggrfuncs) {
+	    info->optflags |= 0x1;
+	    info->has_aggrfuncs = false;
+	  }
+
+	  /* Index lengths */
+
+	  info->idxalloc = 0;
+	  info->idxlen = 0;
+	  info->idxlen_dsym = putsym(_ROWNUM, info->idxlen);
+	  info->__maxcount__ = NULL; /* Address for ODBTk's $__maxcount__ */
+
+    	  /* In case of "$<parent_tblname>.<child_tblname>#" -variables exist ... */
+
+	  info->dyn = NULL;
+	  info->ndyn = 0;
+	  if (info->t && info->ncols_nonassoc > 0) {
+	    int jj = 0;
+	    int nalloc = 1; /* just to get the logic in CHECK_SIZE() working */
+	    CALLOC(info->dyn, nalloc); /* but keep info->ndyn still = 0 */
+	    for (j=0; j<info->ncols; j++) {
+	      col_t *colthis = &info->c[j];
+	      char *name = colthis->name;
+	      if (colthis->kind == 0 && IS_USDDOTHASH(name)) {
+		table_t *t = info->t;
+		char *s = STRDUP(name);
+		char *parent = s+1;
+		char *child = strchr(s,'.');
+		char *hash = strchr(s,'#');
+		dyn_t *dyn;
+		*child++ = '\0';
+		*hash = '\0';
+		info->ndyn = jj + 1;
+		CHECK_SIZE(info, dyn, ndyn, cnt);
+		dyn = &info->dyn[jj];
+		dyn->parent = NULL;
+		dyn->child = NULL;
+		while (t) {
+		  if (strequ(t->name, parent)) dyn->parent = t;
+		  else if (strequ(t->name, child)) dyn->child = t;
+		  t = t->next;
+		}
+		putsym(name, 0); /* Regardless whether parent & child were present or not */
+		if (dyn->parent && dyn->child) {
+		  dyn->name = STRDUP(name);
+		  dyn->data = NULL;
+		  dyn->ndata = 0;
+		  dyn->colid = j;
+		  dyn->parent->in_select_clause = true;
+		  dyn->child->in_select_clause = true;
+		  jj = info->ndyn;
+		}
+		else {
+		  info->ndyn--;
+		}
+		FREE(s);
+	      } /* if (colthis->kind == 0 && IS_USDDOTHASH(name)) */
+	    } /* for (j=0; j<info->ncols; j++) */
+	  } /* if (info->ncols_nonassoc > 0) */
+
+	  /* Check for simple WHERE-conditions for each table */
+	  {
+	    table_t *t = info->t;
+	    while (t) {
+	      t->simple_wherecond = HasSimpleWHEREcond(info, t, info->w, info->nwhere, info->s, info->nset);
+	      t = t->next;
+	    } /* while (t) */
+	  }
+
+	  if (info->create_index < 0) {
+	    /* A backstitch that perhaps should have done at odb98.x -stage ... */
+	    FREE(info->use_index_name);
+	    info->use_index_name = STRDUP(info->view);
+	  }
+
+	  /* Redo the SQL-query */
+
+	  {
+	    char *q = NULL;
+	    const char Exit[] = ";\nEXIT; // The original query follows\n\n";
+	    int len = STRLEN(Exit) + STRLEN(info->sql_query) + 1;
+
+	    if (info->create_index < 0) {
+	      /* 'DROP INDEX name' or 'DROP INDEX *' etc. */
+	      len += STRLEN("DROP INDEX ") + STRLEN(info->view);
+	      if (info->nfrom > 0) {
+		table_t *t = info->t;
+		len += STRLEN(" ON ");
+		while (t) {
+		  len += STRLEN(t->name) + 1;
+		  t = t->next;
+		}
+	      }
+	      ALLOC(q, len);
+	      snprintf(q, len, "DROP INDEX %s", info->view);
+	      if (info->nfrom > 0) {
+		table_t *t = info->t;
+		strcat(q, " ON ");
+		while (t) {
+		  strcat(q, t->name);
+		  t = t->next;
+		  if (t) strcat(q, ",");
+		}
+	      }
+	    }
+	    else if (info->create_index == 1 || info->create_index == 2) {
+	      /* 
+		 CREATE UNIQUE INDEX name ON table ... 
+		   or
+		 CREATE BITMAP INDEX name ON table ...
+	       */
+	      int ncols = info->ncols_true;
+	      int lencols = 0;
+	      len += STRLEN("USING BINARY INDEX") + 2;
+	      len += STRLEN("CREATE UNIQUE INDEX ") + STRLEN(info->view);
+	      len += STRLEN(" ON ") + STRLEN(info->t->name);
+	      if (ncols > 0) {
+		lencols = 1;
+		for (j=0; j<ncols; j++) {
+		  col_t *colthis = &info->c[j];
+		  int inclen = STRLEN(colthis->name) + 1;
+		  len += inclen;
+		  lencols += inclen;
+		}
+		len += 6; /* " (  ) " */
+	      }
+	      len += STRLEN(" WHERE ") + (info->wherecond ? STRLEN(info->wherecond) : 1);
+	      ALLOC(q, len);
+	      if (ncols > 0) {
+		char *cols;
+		ALLOC(cols, lencols);
+		*cols = 0;
+		for (j=0; j<ncols; j++) {
+		  col_t *colthis = &info->c[j];
+		  if (j>0) strcat(cols,",");
+		  strcat(cols, colthis->name);
+		}
+		snprintf(q, len, "USING %sINDEX;\nCREATE %s INDEX %s\nON %s\n( %s )\nWHERE %s",
+			 info->binary_index ? "BINARY " : "",
+			 (info->create_index == 1) ? "UNIQUE" : "BITMAP",
+			 info->view,
+			 info->t->name,
+			 cols,
+			 info->wherecond ? info->wherecond : "1");
+		FREE(cols);
+	      }
+	      else {
+		snprintf(q, len, "USING %sINDEX;\nCREATE %s INDEX %s\nON %s\nWHERE %s",
+			 info->binary_index ? "BINARY " : "",
+			 (info->create_index == 1) ? "UNIQUE" : "BITMAP",
+			 info->view,
+			 info->t->name,
+			 info->wherecond ? info->wherecond : "1");
+	      }
+	    }
+	    else { /* if (info->create_index > 0) */
+	      /*
+		SELECT [DISTINCT] columns
+		[UNIQUEBY columns]
+		[FROM tables]
+		[WHERE cond]
+		[ORDERBY columns]
+	      */
+	      table_t *t = info->t;
+	      int ncols = info->ncols_true;
+	      int lencols = 0;
+	      int uniq_ncols = (info->nuniqueby > 0 && !info->has_select_distinct) ?
+		info->nuniqueby : 0;
+	      int uniq_lencols = 0;
+	      int sort_ncols = info->norderby;
+	      int sort_lencols = 0;
+	      char *where = info->wherecond ? STRDUP(info->wherecond) : STRDUP("1");
+	      char *punique = strstr(where,"Unique(");
+	      const char no_indices[] = "NO INDICES;\n";
+
+	      if (punique) {
+		int cnt_lb = CountChars(punique,'('); /* Count of left brackets '(' */
+		int cnt_rb = CountChars(punique,')'); /* Count of right brackets ')' */
+		if (cnt_lb == cnt_rb) {
+		  strcpy(punique,"1");
+		}
+		else if (cnt_lb < cnt_rb) {
+		  strcpy(punique,"1)");
+		}
+		else {
+		  fprintf(stderr,
+			  "***Error: Impossible to have more '(':s than ')':s ; in %s\n",
+			  punique);
+		  RAISE(SIGABRT);
+		}
+	      }
+
+	      if (!info->use_indices) len += STRLEN(no_indices);
+
+	      len += 
+		STRLEN("CREATE VIEW ") + STRLEN(info->view) +
+		STRLEN(" AS SELECT ") +
+		(info->has_select_distinct ? STRLEN("DISTINCT ") : 0);
+
+	      if (ncols > 0) {
+		lencols = 1;
+		for (j=0; j<ncols; j++) {
+		  col_t *colthis = &info->c[j];
+		  char *name = colthis->nickname ? colthis->nickname : colthis->name;
+		  int inclen = STRLEN(name) + 1;
+		  len += inclen;
+		  lencols += inclen;
+		}
+	      }
+
+	      if (uniq_ncols > 0) {
+		uniq_lencols = 1;
+		len += STRLEN(" UNIQUEBY ");
+		for (j=0; j<uniq_ncols; j++) {
+		  col_t *colthis = &info->u[j];
+		  int inclen = STRLEN(colthis->name) + 1;
+		  len += inclen;
+		  uniq_lencols += inclen;
+		}
+	      }
+
+	      t = info->t;
+	      if (t) {
+		len += STRLEN(" FROM ");
+		while (t) {
+		  len += STRLEN(t->name) + 1;
+		  t = t->next;
+		}
+	      }
+
+	      len += STRLEN(" WHERE ") + STRLEN(where);
+
+	      if (sort_ncols > 0) {
+		int maxcols = info->maxcols + 1;
+		sort_lencols = 1;
+		len += STRLEN(" ORDERBY ");
+		for (j=0; j<sort_ncols; j++) {
+		  col_t *colthis = &info->o[j];
+		  int inclen = STRLEN(colthis->name) + 1;
+		  if (colthis->kind < 0) inclen += STRLEN(" DESC");
+		  if (ABS(colthis->kind) > maxcols) inclen += STRLEN("ABS()");
+		  len += inclen;
+		  sort_lencols += inclen;
+		}
+	      }
+
+	      ALLOC(q, len);
+	      snprintf(q, len, "%sCREATE VIEW %s AS\nSELECT %s",
+		       (!info->use_indices) ? no_indices : "",
+		       info->view, 
+		       info->has_select_distinct ? "DISTINCT " : "");
+
+	      if (ncols > 0) {
+		for (j=0; j<ncols; j++) {
+		  col_t *colthis = &info->c[j];
+		  char *name = colthis->nickname ? colthis->nickname : colthis->name;
+		  if (j>0) strcat(q, ",");
+		  strcat(q, name);
+		}
+	      }
+
+	      if (uniq_ncols > 0) {
+		strcat(q,"\nUNIQUEBY ");
+		for (j=0; j<uniq_ncols; j++) {
+		  col_t *colthis = &info->u[j];
+		  char *name = colthis->name;
+		  if (j>0) strcat(q, ",");
+		  strcat(q, name);
+		}
+	      }
+
+	      t = info->t;
+	      if (t) {
+		strcat(q, "\nFROM ");
+		while (t) {
+		  if (t != info->t) strcat(q, ",");
+		  strcat(q, t->name);
+		  t = t->next;
+		}
+	      }
+	      
+	      strcat(q, "\nWHERE ");
+	      strcat(q, where);
+	      FREE(where);
+
+	      if (sort_ncols > 0) {
+		int maxcols = info->maxcols + 1;
+		strcat(q,"\nORDERBY ");
+		for (j=0; j<sort_ncols; j++) {
+		  col_t *colthis = &info->o[j];
+		  char *name = colthis->name;
+		  if (j>0) strcat(q, ",");
+		  if (ABS(colthis->kind) > maxcols) {
+		    strcat(q,"ABS(");
+		    strcat(q, name);
+		    strcat(q,")");
+		  }
+		  else {
+		    strcat(q, name);
+		  }
+		  if (colthis->kind < 0) strcat(q," DESC");
+		}
+	      }
+	    }
+
+	    strcat(q, Exit);
+	    strcat(q, info->sql_query);
+
+	    FREE(info->sql_query);
+	    info->sql_query = q;
+	  }
+
+	  if ((info->u && info->nuniqueby > 0) || 
+	      info->has_select_distinct ||
+	      info->has_aggrfuncs || 
+	      (info->o && info->norderby > 0) ||
+	      ((info->optflags & 0x1) == 0x1) ||
+	      info->create_index > 0) {
+	    info->need_global_view = true;
+	  }
+	  else {
+	    info->need_global_view = false;
+	  }
+
+	  if ((info->u && info->nuniqueby > 0) || info->has_select_distinct) {
+	    /* UNIQUEBY-clause present (or has SELECT DISTINCT) */
+	    info->need_hash_lock = true;
+	  }
+	  else {
+	    info->need_hash_lock = false;
+	  }
+
+	  if (info->has_select_distinct &&
+	      !info->has_aggrfuncs &&
+	      !(info->o && info->norderby > 0) &&
+	      (info->create_index == 0) &&
+	      (info->ncols == info->ncols_true) &&
+	      (info->nwhere == 0) &&
+	      (info->wherecond && strnequ(info->wherecond,"Unique(",7))) {
+	    /* This must be a basic calculator (bc) mode !! */
+	    info->is_bc = true; /* Implies also that just one result line is expected */
+	  }
+	  else {
+	    info->is_bc = false;
+	  }
+
+	  info = info->next;
+	} /* while (info) */
+
+      } /* if (info_chain) */
+      else {
+	fprintf(stderr,
+		"***Error: Cannot extract all compilation metadata. Has compilation failed ?\n");
+	exit(SIGABRT);
+      }
+
+      FREE(dir);
+      FREE(host);
+      FREE(tstamp);
+    } /* if (fp) */
+  }
+  DRHOOK_END(0);
+  return info_chain;
+}
+
+
+PUBLIC void *
+ODBc_next(void *Info)
+{
+  info_t *info = Info;
+  return info ? info->next : NULL;
+}
+
+
+PUBLIC void
+ODBc_print_info(FILE *fp, void *Info)
+{
+  info_t *info = Info;
+  DRHOOK_START(ODBc_print_info);
+  if (info && fp) { /* Print contents of the info */    
+    int j;
+    const char colfmt[] = "  [%d] = '%s' : fetch_name = '%s' : "
+      "kind = %d : (pos,len) = (%d,%d) : ioffset = %d : table_id = %d @ %p\n";
+    const char nickcolfmt[] = "  [%d] = '%s'%s%s%s: fetch_name = '%s' : "
+      "kind = %d : (pos,len) = (%d,%d) : ioffset = %d : table_id = %d @ %p\n";
+    fprintf(fp,"Directory = '%s'\n",info->dir ? info->dir : NIL);
+    fprintf(fp,"Host = '%s'\n",info->host ? info->host : NIL);
+    fprintf(fp,"Timestamp = '%s'\n",info->tstamp ? info->tstamp : NIL);
+    fprintf(fp,"Database = '%s'\n",info->dbcred.dbname ? info->dbcred.dbname : NIL);
+    fprintf(fp,"Npools = %d\n",info->npools);
+    fprintf(fp,"Viewname = '%s'\n",info->view ? info->view : NIL);
+    fprintf(fp,"The SQL-query in concern:\n%s\n",info->sql_query ? info->sql_query : NIL);
+    fprintf(fp,"use_indices = %d\n",info->use_indices);
+    fprintf(fp,"create_index = %d\n",info->create_index);
+    if (info->create_index == 1) {
+      fprintf(fp,"The query serves the CREATE UNIQUE INDEX %s\n",
+	      info->view ? info->view : NIL);
+    }
+    else if (info->create_index == 2) {
+      fprintf(fp,"The query serves the CREATE BITMAP INDEX %s\n",
+	      info->view ? info->view : NIL);
+    }
+    else if (info->create_index < 0) {
+      fprintf(fp,"The query serves the DROP INDEX %s\n",
+	      info->view ? info->view : NIL);
+    }
+    fprintf(fp,"Has SELECT DISTINCT = %s\n", info->has_select_distinct ? "true" : "false");
+    fprintf(fp,"Has SELECT COUNT(*) = %s\n", info->has_count_star ? "true" : "false");
+    fprintf(fp,"Has aggregate functions = %s\n", info->has_aggrfuncs ? "true" : "false");
+    fprintf(fp,"Calls thin()-function = %s\n", info->has_thin ? "true" : "false");
+    fprintf(fp,"Optflags = 0x%x\n",info->optflags);
+    fprintf(fp,"Maxcols = %d\n",info->maxcols);
+    fprintf(fp,"No. of relevant $-variables : %d\n",info->nset);
+    for (j=0; j<info->nset; j++) {
+      fprintf(fp,"\t[%d] : '%s' = %.14g\n", j, info->s[j].name, info->s[j].value);
+    }
+    fprintf(fp,"No. of 'Hollerith'-strings : %d\n",info->ns2d);
+    for (j=0; j<info->ns2d; j++) {
+      fprintf(fp,"\t[%d] : '%s' = '%s' (saddr=%p)\n", 
+	      j, info->s2d[j].name, info->s2d[j].value, info->s2d[j].u.saddr);
+    }
+    fprintf(fp,"No. of tables in FROM-statement : %d\n", info->nfrom);
+    for (j=0; j<info->nfrom; j++) {
+      table_t *t = &info->t[j];
+      fprintf(fp,
+	      "\n"
+	      "\ttable_id = %d (%d) @ %p : '%s' : linkcase=%d ('%s') >\n"
+	      "\t  prev=%p, next=%p, linkparent=%p, offset_parent=%p\n"
+	      "\t  linkparent_id=%d ('%s'), offset_parent_id=%d ('%s')  %s\n"
+	      "\t  [b,offset]=['%s','%s'],\n"
+	      "\t  [e,len]=['%s','%s'] :\n"
+	      "\t  wherecond_and [unless '%s'] =%s%s\n"
+	      "\t  referenced in SELECT-clause ? %s\n"
+	      "\t  has simple WHERE-condition ? %s\n",
+	      t->table_id, j, t,
+	      t->name ? t->name : NIL, t->linkcase,
+	      (t->linkcase >= 1 && t->linkcase <= NLINKCASES) ? linkcase_name[t->linkcase] : NIL,
+	      t->prev, t->next, t->linkparent, t->offset_parent,
+	      t->linkparent_id, 
+	      (t->linkparent && t->linkparent->name) ? t->linkparent->name : NIL,
+	      t->offset_parent_id, 
+	      (t->offset_parent && t->offset_parent->name) ? t->offset_parent->name : NIL,
+	      (t->linkparent_id < 0) ? "" :
+	      ((t->linkparent_id == t->offset_parent_id) ? "--> THE SAME" : "--> DIFFER"),
+	      t->b ? t->b : NIL,
+	      t->linkoffset ? t->linkoffset : NIL,
+	      t->e ? t->e : NIL,
+	      t->linklen ? t->linklen : NIL,
+	      NIL, 
+	      t->wherecond_and ? "\n" : "",
+	      t->wherecond_and ? t->wherecond_and : NIL,
+	      t->in_select_clause ? "yes" : "no",
+	      t->simple_wherecond ? "yes" : "no"
+	      );
+
+      if (t->simple_wherecond && t->wl && t->nwl > 0) {
+	int i, nwl = t->nwl;
+	simple_where_t *wl = t->wl;
+	fprintf(fp,"  %d simple WHERE-condition%s %sfollow for table '%s':\n", 
+		nwl, 
+		(nwl > 1) ? "s" : "",
+		(nwl > 1) ? "(separated by ANDs) " : "",
+		t->name);
+	for (i=0; i<nwl; i++) {
+	  fprintf(fp,"\t%s --> %s %s %.14g\n", 
+		  wl->condstr,
+		  wl->lhs, KindStr((Kind_t)wl->oper), wl->rhs);
+	  wl++;
+	}
+      }
+
+      if (t->stored_idx_count > 0) {
+	int i, nwl = t->nwl;
+	int cnt = 0;
+	simple_where_t *wl = t->wl;
+	fprintf(fp,"  %d stored indices were found for the following WHERE-stmts:\n",
+		t->stored_idx_count);
+	for (i=0; i<nwl; i++) {
+	  if (wl->stored_idx) {
+	    fprintf(fp,"\t(%d) : %s : index-file=\n  %s\n",
+		    ++cnt,wl->condstr,
+		    wl->stored_idx->filename);
+	  }
+	  wl++;
+	}
+      }
+      else {
+	fprintf(fp,"  0 stored indices were found for table '%s'\n",t->name);
+      }
+    }
+    fprintf(fp,"No. of select columns : %d (total), %d (true), %d (pure)",
+	    info->ncols, info->ncols_true, info->ncols_pure);
+    fprintf(fp,", %d (aggr), %d (aux), %d (nonassoc)\n",
+	    info->ncols_aggr_formula, info->ncols_aux, info->ncols_nonassoc);
+    
+    for (j=0; j<info->ncols; j++) {
+      col_t *colthis = &info->c[j];
+      fprintf(fp, nickcolfmt,
+	      j, colthis->name, 
+	      colthis->nickname ? " (as '" : "",
+	      colthis->nickname ? colthis->nickname : "", 
+	      colthis->nickname ? "') " : "",
+	      colthis->fetch_name, colthis->kind, 
+	      colthis->bitpos, colthis->bitlen, colthis->ioffset,
+	      colthis->table_id, colthis->t);
+    }
+
+    fprintf(fp,"Assuming export ODB_LAT=%s\n",info->odb_lat->name);
+    fprintf(fp,"         export ODB_LON=%s\n",info->odb_lon->name);
+    fprintf(fp,"         export ODB_COLOR=%s\n",info->odb_color->name);
+    fprintf(fp,"         export ODB_U=%s\n",info->odb_u->name);
+    fprintf(fp,"         export ODB_V=%s\n",info->odb_v->name);
+
+    fprintf(fp,"No. of UNIQUEBY columns : %d\n", info->nuniqueby);
+    for (j=0; j<info->nuniqueby; j++) {
+      col_t *colthis = &info->u[j];
+      fprintf(fp, colfmt,
+	      j, colthis->name,
+	      colthis->fetch_name, colthis->kind, 
+	      colthis->bitpos, colthis->bitlen, colthis->ioffset,
+	      colthis->table_id, colthis->t);
+    }
+    if (info->wherecond) {
+      fprintf(fp,"WHERE-statement follows:\n");
+      fprintf(fp,"%s\n",info->wherecond);
+    }
+    fprintf(fp,"No. of WHERE-columns to be prefetched : %d\n",info->nwhere);
+    for (j=0; j<info->nwhere; j++) {
+      col_t *colthis = &info->w[j];
+      fprintf(fp, colfmt,
+	      j, colthis->name,
+	      colthis->fetch_name, colthis->kind, 
+	      colthis->bitpos, colthis->bitlen, colthis->ioffset,
+	      colthis->table_id, colthis->t);
+    }
+    fprintf(fp,"No. of ORDERBY columns : %d\n", info->norderby);
+    for (j=0; j<info->norderby; j++) {
+      col_t *colthis = &info->o[j];
+      fprintf(fp, colfmt,
+	      j, colthis->name,
+	      colthis->fetch_name, colthis->kind, 
+	      colthis->bitpos, colthis->bitlen, colthis->ioffset,
+	      colthis->table_id, colthis->t);
+    }
+    fprintf(fp,"No. of columns to be prefetched due to LINKs : %d\n",info->nprefetch);
+    for (j=0; j<info->nprefetch; j++) {
+      col_t *colthis = &info->p[j];
+      fprintf(fp, colfmt,
+	      j, colthis->name,
+	      colthis->fetch_name, colthis->kind, 
+	      colthis->bitpos, colthis->bitlen, colthis->ioffset,
+	      colthis->table_id, colthis->t);
+    }
+    fprintf(fp,"No. of dynamic @LINK-lengths : %d\n", info->ndyn);
+    for (j=0; j<info->ndyn; j++) {
+      dyn_t *dyn = &info->dyn[j];
+      fprintf(fp,"\t%s : parent = '%s' (table_id = %d), child = '%s' (table_id = %d)\n",
+	      dyn->name, 
+	      dyn->parent->name, dyn->parent->table_id, 
+	      dyn->child->name, dyn->child->table_id);
+    }
+  } /* if (info && fp) */
+  DRHOOK_END(0);
+}
+
+
+#define FREE_THIS_SET() { \
+  int j; \
+  for (j=0; j<info->nset; j++) { \
+    set_t *s = &info->s[j]; \
+    (void) delsym(s->name, it); \
+    FREE(s->name); \
+  } \
+  FREE(info->s); \
+}
+
+#define FREE_THIS_S2D() { \
+  int j; \
+  for (j=0; j<info->ns2d; j++) { \
+    str_t *s2d = &info->s2d[j]; \
+    (void) delsym(s2d->name, it); \
+    FREE(s2d->name); \
+    FREE(s2d->value); \
+  } \
+  FREE(info->s2d); \
+}
+
+#define FREE_THIS_COL(x,num) { \
+  int j; \
+  if (info->x) { \
+    int nx = num; \
+    for (j=0; j<nx; j++) { \
+      col_t *colthis = &info->x[j]; \
+      (void) delsym(colthis->name, it); \
+      FREE(colthis->name); \
+      (void) delsym(colthis->fetch_name, it); \
+      FREE(colthis->fetch_name); \
+      FREE(colthis->nickname); \
+      FREE(colthis->dtype); \
+      if (colthis->dinp_alloc) FREE(colthis->dinp); \
+      colthis->dinp = NULL; \
+      colthis->dinp_len = 0; \
+      colthis->dinp_alloc = false; \
+      if (colthis->formula_ptree && colthis->formula_ptree_owner) DelParseTree(colthis->formula_ptree); \
+      colthis->formula_ptree = NULL; \
+    } \
+  } \
+  FREE(info->x); \
+}
+
+#define FREE_HER_TABLES(x,num) { \
+  int j, nx=info->num; \
+  for (j=0; j<nx; j++) { \
+    table_t *this = &info->x[j]; \
+    FREE(this->name); \
+    FREE(this->b); \
+    FREE(this->e); \
+    FREE(this->linkoffset); \
+    FREE(this->linklen); \
+    FREE(this->offset); \
+    FREE(this->len); \
+    FREE(this->idx); \
+    DelParseTree(this->wherecond_and_ptree); \
+    this->wherecond_and_ptree = NULL; \
+    FREE(this->wherecond_and); \
+    if (this->wl) { \
+      int i, nwl = this->nwl; \
+      for (i=0; i<nwl; i++) { \
+        simple_where_t *wl = &this->wl[i]; \
+	FREE(wl->condstr); \
+	FREE(wl->lhs); \
+        wl->stored_idx = codb_IDXF_freeidx(wl->stored_idx, 0); \
+      } \
+      FREE(this->wl); \
+    } \
+  } \
+  FREE(info->x); \
+}
+
+#define FREE_DYN() \
+{ \
+  int j, ndyn = info->ndyn; \
+  for (j=0; j<ndyn; j++) { \
+    dyn_t *dyn = &info->dyn[j]; \
+    (void) delsym(dyn->name, it); \
+    FREE(dyn->name); \
+    FREE(dyn->data); \
+  } \
+  FREE(info->dyn); \
+}
+
+PUBLIC void *
+ODBc_sql_cancel(void *Info)
+{
+  DRHOOK_START(ODBc_sql_cancel);
+  if (Info) {
+    DEF_IT;
+    info_t *info = Info;
+    FREE(info->dir);
+    FREE(info->host);
+    FREE(info->tstamp);
+    FREE(info->dbcred.dbname);
+    FREE(info->dbcred.srcpath);
+    FREE(info->dbcred.datapath);
+    FREE(info->dbcred.idxpath);
+    FREE(info->dbcred.poolmask);
+    FREE(info->view);
+    FREE(info->sql_query);
+    FREE(info->wherecond);
+    DelParseTree(info->wherecond_ptree);
+    info->wherecond_ptree = NULL;
+    FREE_THIS_SET();
+    FREE_THIS_S2D();
+    FREE_THIS_COL(c,info->ncols);
+    FREE_THIS_COL(u,info->nuniqueby);
+    FREE_THIS_COL(w,info->nwhere);
+    FREE_THIS_COL(o,ABS(info->norderby));
+    FREE_THIS_COL(p,info->nprefetch);
+    FREE_THIS_COL(odb_lat,1);
+    FREE_THIS_COL(odb_lon,1);
+    FREE_THIS_COL(odb_color,1);
+    FREE_THIS_COL(odb_u,1);
+    FREE_THIS_COL(odb_v,1);
+    FREE_HER_TABLES(t,nfrom);
+    FREE_DYN();
+    FREE(info->colaux);
+    FREE(info);
+  }
+  DRHOOK_END(0);
+  return NULL;
+}
+
+#define SWAPINFO(n, old, new) tmp = old->n; old->n = new->n; new->n = tmp
+
+PRIVATE Bool
+MakePlotColumns(info_t *info_inout, Bool warrow,
+		int latcol, int loncol, int colorcol, int ucol, int vcol)
+{
+  DRHOOK_START(MakePlotColumns);
+  if (info_inout) {
+    int nc = info_inout->ncols_true;
+    ODB_fprintf(fp_echo,
+		"MakePlotColumns(warrow=%s)< nc = %d, latcol = %d, loncol = %d, colorcol = %d"
+		", ucol = %d, vcol = %d\n",
+		warrow ? "true" : "false", nc, latcol, loncol, colorcol, ucol, vcol);
+    if (latcol >= 0 && latcol < nc && loncol >= 0 && loncol < nc) {
+      info_t *info = NULL;
+      int j, k, cnt = 2; /* 2 == at least two columns i.e. latcol & loncol present */
+      
+      if (warrow) {
+	if (ucol >= 0 && ucol < nc &&
+	    vcol >= 0 && vcol < nc) cnt += 2; /* Both 3rd & 4th present */
+	else {
+	  ODB_fprintf(fp_echo,"MakePlotColumns: No (u,v)-available --> abandoning wind-arrow plot\n");
+	  ucol = vcol = -1;
+	  warrow = false;
+	  ODBc_set_format("plotobs"); /* Reset back to "just" plotobs */
+	}
+      }
+      else {
+	ucol = vcol = -1;
+      }
+
+      if (colorcol >= 0 && colorcol < nc) cnt++; /* 3rd (5th for warrow) column present */
+
+      ODB_fprintf(fp_echo,
+		  "MakePlotColumns(warrow=%s)> nc = %d, latcol = %d, loncol = %d, colorcol = %d"
+		  ", ucol = %d, vcol = %d\n",
+		  warrow ? "true" : "false", nc, latcol, loncol, colorcol, ucol, vcol);
+
+      CALLOC(info, 1); /* All zeroed, too */
+
+      k = cnt; /* "cnt" saved in "k" for future use */
+      for (j=0; j<info_inout->ncols; j++) {
+	info->ncols_pure += (info_inout->c[j].kind == 1);
+	info->ncols_formula += (info_inout->c[j].kind == 2);
+	info->ncols_aggr_formula += (info_inout->c[j].kind == 4);
+	info->ncols_aux += (info_inout->c[j].kind == 8);
+	info->ncols_nonassoc += (info_inout->c[j].kind == 0);
+	if (warrow) {
+	  if (j != latcol && j != loncol && j != colorcol && j != ucol && j != vcol) cnt++;
+	}
+	else {
+	  if (j != latcol && j != loncol && j != colorcol) cnt++;
+	}
+      }
+      info->ncols_true = info->ncols_pure + info->ncols_formula + info->ncols_aggr_formula;
+
+      CHECK_SIZE(info, c, ncols, cnt); /* no. of columns == cnt */
+
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols = %d\n",info->ncols);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_true = %d\n",info->ncols_true);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_pure = %d\n",info->ncols_pure);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_formula = %d\n",info->ncols_formula);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_aggr_formula = %d\n",info->ncols_aggr_formula);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_aux = %d\n",info->ncols_aux);
+      ODB_fprintf(fp_echo,"MakePlotColumns: info->ncols_nonassoc = %d\n",info->ncols_nonassoc);
+
+      /* 
+	 Remap/copy columns so that 
+
+	   $ODB_LAT becomes column#1
+	   $ODB_LON becomes column#2
+
+	   if warrow == true, then
+
+	   $ODB_U becomes column#3
+	   $ODB_V becomes column#4
+	   $ODB_COLOR becomes column#5 (if available)
+
+	   else
+
+	   $ODB_COLOR becomes column#3 (if available)
+	   
+       */
+
+      {
+	int jj = 0;
+	HARDCOPY_THESE(c,0,&info_inout->c[latcol]); ++jj;
+	HARDCOPY_THESE(c,1,&info_inout->c[loncol]); ++jj;
+	if (warrow) {
+	  HARDCOPY_THESE(c,jj,&info_inout->c[ucol]); ++jj;
+	  HARDCOPY_THESE(c,jj,&info_inout->c[vcol]); ++jj;
+	}
+	if (colorcol >= 0 && colorcol < nc) {
+	  HARDCOPY_THESE(c,jj,&info_inout->c[colorcol]); ++jj;
+	}
+      }
+
+      for (j=0; j<info_inout->ncols; j++) {
+	if (j != latcol && j != loncol && j != colorcol &&
+	    j != ucol && j != vcol) {
+	  HARDCOPY_THESE(c,k,&info_inout->c[j]);
+	  k++;
+	}
+      } /* for (j=0; j<info_inout->ncols; j++) */
+
+      /* "k" should now be == "cnt" */
+
+      if (k != cnt) {
+	fprintf(stderr,
+		"***Error: Programming fatality in MakePlotColumns : k != cnt (k=%d, cnt=%d)\n",
+		k, cnt);
+	RAISE(SIGABRT);
+      }
+      
+      /* Swap info->c with info_inout->c */
+      {
+	col_t *tmp;
+	SWAPINFO(c, info, info_inout);
+      }
+
+      /* redo c's dimensions and pass them to info_inout */
+      {
+	int tmp;
+	SWAPINFO(ncols, info, info_inout);
+	SWAPINFO(ncols_true, info, info_inout);
+	SWAPINFO(ncols_pure, info, info_inout);
+	SWAPINFO(ncols_formula, info, info_inout);
+	SWAPINFO(ncols_aggr_formula, info, info_inout);
+	SWAPINFO(ncols_aux, info, info_inout);
+	SWAPINFO(ncols_nonassoc, info, info_inout);
+      }
+
+      /* Get rid of (temporary) info */
+      (void) ODBc_sql_cancel(info);
+    } /* f (latcol >= 0 && latcol < nc && loncol >= 0 && loncol < nc) */
+  }
+  DRHOOK_END(0);
+  return warrow;
+}
+
+
+PRIVATE Bool
+HasSimpleWHEREcond(const info_t *info, table_t *t, col_t *w, int nwhere, const set_t *set, int nset)
+{
+  Bool is_simple = false;
+  simple_where_t *wl = t ? t->wl : NULL;
+  int nwl = t ? t->nwl : 0;
+  int table_id = t ? t->table_id : -1;
+  char *env = getenv("ODB_SIMPLE_WHERECOND_LIMIT");
+  int limit = env ? atoi(env) : (int)ABS(mdi);
+  DRHOOK_START(HasSimpleWHEREcond);
+
+  if (t && wl && nwl >= 1 && nwl <= limit &&
+      w && nwhere > 0 && table_id >= 0) {
+    int i, j, nhits = 0;
+    const char *tblname = t->name;
+    for (i=0; i<nwl; i++) {
+      wl->condstr = CheckAgainstLinks(wl->condstr, info);
+      {
+	const char *s = wl->condstr;
+	char *lhs = GetLHSwhenSimpleExpr(s, &wl->oper, &wl->rhs, set, nset); /* STRDUP'ped lhs */
+	if (lhs) {
+	  /* For the moment ignore all kind of '$...#'-variables and such
+	     '#table'-variables that are not referring to the current table */
+	  if (IS_USDHASH(lhs) || (IS_HASH(lhs) && !strequ(lhs+1, tblname))) FREE(lhs);
+	  if (lhs) {
+	    nhits++;
+	    wl->lhs = lhs;
+	  }
+	}
+      }
+      wl++;
+    } /* for (i=0; i<nwl; i++) */
+
+    if (nhits == nwl) {
+      /* Indeed a simple WHERE-condition ;
+	 Now associate "lhs" with a WHERE-variable */
+      nhits = 0;
+      wl = t->wl;
+      for (i=0; i<nwl; i++) {
+	for (j=0; j<nwhere; j++) {
+	  col_t *colthis = &w[j];
+	  const char *s = colthis->name;
+	  table_t *tc = colthis->t;
+	  if (tc && tc->table_id == table_id && strequ(s, wl->lhs)) {
+	    wl->wcol = colthis;
+	    nhits++;
+	    break; /* for (j=0; j<nwhere; j++) */
+	  }
+	} /* for (j=0; j<nwhere; j++) */
+	wl++;
+      } /* for (i=0; i<nwl; i++) */
+    }
+
+    if (nhits == nwl) is_simple = true;
+  } /* if (t && wl && nwl > 0 && w && nwhere > 0 && table_id >= 0) */
+
+  DRHOOK_END(0);
+  return is_simple;
+}
+
+
+PUBLIC int
+ODBc_fetch_indices(table_t *t, info_t *info)
+{
+  int cnt = 0;
+  DRHOOK_START(ODBc_fetch_indices);
+
+  if (t && info) {
+    int use = (int)info->use_indices;
+    char *env = getenv("ODB_USE_INDICES");
+
+    /* 
+       Normally by default use indices if ODB_USE_INDICES=1 
+       Could have been overridden by info->use_indices = false,
+       coming from odb98.x
+     */
+    
+    if (use && env) use = atoi(env);
+    
+    if (info->create_index != 0) use = 0;
+
+    if (use) {
+      simple_where_t *wl = t ? t->wl : NULL;
+      int nwl = t ? t->nwl : 0;
+      
+      if (wl && nwl >= 1) {
+	int i;
+	int handle = info->ph ? info->ph->h : -1; 
+	const char *idxpath = info->ph->idxpath;
+	const char *tblname = t->name;
+	const char *idxname = info->use_index_name;
+
+	/* The strategy : 
+	   ============
+	   For each simple WHERE-condition "wl", try to find the best 
+	   possible match from among the various index-files
+	   that may lie around. The match is found using the following
+	   precedence (the highest first, and when matched, ignore the rest):
+
+	   (#1) Search for indices that directly satisfy the wl-triplet 
+	        by looking at the WHERE-statement itself.
+
+	   Assuming the previous example : "press at body < 10", we look
+	   for any index-files that satisfy criterias :
+
+	   CREATE INDEX name ON body WHERE press at body < 10;
+
+	   or
+
+	   CREATE INDEX name on body ( some_other_column_names ) WHERE press at body < 10;
+
+	   i.e. "ncols" is irrelevant, as is "colnames"
+
+
+	   (#2) If the (#1) didn't match any index-files (indices), then
+	        we can try the next candidate. 
+		Look for such indices, which have wl->lhs as column name
+	        and WHERE-condition "WHERE 1". Then search for those
+	        index-sets only, which satisfy the wl-triplet (lhs,oper,rhs).
+
+	   E.g. you have created an index like the following:
+	     CREATE INDEX name ON body ( press );
+	   which translates into :
+	     CREATE INDEX name ON body ( press at body ) WHERE 1;
+
+	   And your simple WHERE-condition is "press at body < 10", thus
+	   the wl-triplet is (press at body, '<', 10).
+
+	   So we will search for each index-set that has an occurence of
+	   "press at body" that satisfies "less than ten" condition.
+
+	   ---
+	   
+	   If neither of the two found any match, we abandon use of indices for
+	   this wl-triplet.
+	   
+	   NB: It is assumed that an empty wherecond'ition is the same as 
+	   always true i.e. "WHERE 1"
+	*/
+	   
+	   
+	for (i=0; i<nwl; i++) {
+	  int ncols;
+	  char *wherecond;
+	  const char *lhs =  wl->wcol ? wl->wcol->name : NULL;
+	  int oper = wl->oper;
+	  double rhs = wl->rhs;
+	  /* For the moment ignore all kind of '$...#'-variables and such
+	     '#table'-variables that are not referring to the current table */
+	  const char *colnames = NULL;
+
+	  wl->stored_idx = NULL;
+
+	  {
+	    /* The (#1) */
+	    ncols = -1;
+	    wherecond = S2D_fix(info, wl->condstr);
+	    colnames = NULL;
+	    wl->stored_idx = codb_IDXF_fetch(handle,
+					     idxpath,
+					     tblname,
+					     idxname,
+					     ncols,
+					     colnames,
+					     wherecond,
+					     oper,
+					     NULL);
+	    FREE(wherecond);
+	  }
+
+	  if (!wl->stored_idx) {
+	    /* The (#2) */
+	    ncols = 1;
+	    wherecond = NULL;
+	    if (lhs) {
+	      if (IS_USDHASH(lhs) || (IS_HASH(lhs) && !strequ(lhs+1, tblname)))
+		colnames = NULL;
+	      else
+		colnames = lhs;
+	    }
+	    if (colnames) {
+	      wl->stored_idx = codb_IDXF_fetch(handle,
+					       idxpath,
+					       tblname,
+					       idxname,
+					       ncols,
+					       colnames,
+					       wherecond,
+					       oper,
+					       &rhs);
+	    }
+	  }
+	  if (wl->stored_idx) cnt++;
+	  wl++;
+	} /* for (i=0; i<nwl; i++) */
+      }
+    }
+  }
+  DRHOOK_END(0);
+  return cnt;
+}
+
+
+
+PUBLIC const char *
+ODBc_get_sql_query(const void *Info)
+{
+  const info_t *info = Info;
+  return info ? info->sql_query : NULL;
+}
+
+
+#ifdef STANDALONE_TEST
+int main(int argc, char *argv[])
+{
+  int j;
+  (void) ODBc_debug_fp(stdout);
+  for (j=1; j<argc; j++) {
+    info_t *info = ODBc_get_info(argv[j]);
+    ODBc_print_info(Info, stdout);
+    ODBc_unget_info(info);
+  }
+  return 0;
+}
+#endif
diff --git a/odb/src/aux/ioassign_hash.c b/odb/src/aux/ioassign_hash.c
new file mode 100644
index 0000000..1f0e5ea
--- /dev/null
+++ b/odb/src/aux/ioassign_hash.c
@@ -0,0 +1,48 @@
+#include "iostuff.h"
+#include "ioassign.h"
+
+static const int IOASSIGN_hashsize = 123457U; /* hardcoded for now */
+
+PRIVATE uint
+IOASSIGN_Hash(const char *s)
+{ 
+  uint hashval = 0;
+  for (; *s ; s++) {
+    hashval = (*s) + 31U * hashval;
+  }
+  hashval = hashval % IOASSIGN_hashsize;
+  return hashval;
+}
+
+PUBLIC uint
+IOassign_hash(const char *s)
+{
+  uint hash;
+  int hps = has_percent_sign(s);
+  char *x = hps ? STRDUP(s) : (char *)s;
+  if (hps) {
+    char *p = strchr(x,'%');
+    if (p) *p = '\0'; /* Truncate "x" at '%'-sign */
+  }
+  hash = IOASSIGN_Hash(x);
+  if (hps) FREE(x);
+  return hash;
+}
+
+PUBLIC Ioassign *
+IOassign_lookup(const char *s, Ioassign *pstart)
+{
+  int found = 0;
+  Ioassign *p = pstart;
+  uint hash = p ? IOassign_hash(s) : 0;
+  while (p) {
+    if (p->hash == hash) {
+      char *env = IOresolve_env(p->filename);
+      found = IOstrequ(env,s,NULL,NULL,p->fromproc, p->toproc);
+      FREE(env);
+      if (found) break; /* A match found */
+    }
+    p = p->next;
+  }
+  return found ? p : NULL;
+}
diff --git a/odb/src/aux/ioassign_read.c b/odb/src/aux/ioassign_read.c
new file mode 100644
index 0000000..a78657c
--- /dev/null
+++ b/odb/src/aux/ioassign_read.c
@@ -0,0 +1,421 @@
+#include "iostuff.h"
+#include "ioassign.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "memmap.h"
+
+static int  /* Borrowed from filesize.c */
+filesize_by_fp(FILE *fp, const char *path)
+{
+  int rc;
+  struct stat buf;
+  int file_size = 0;
+
+  rc = fstat(fileno(fp),&buf);
+  if (rc != 0) {
+    file_size = -1;
+    PERROR(path);
+  }
+  else {
+    file_size = buf.st_size;
+  }
+
+  return file_size;
+}
+
+static char *preferred_DBNAME = NULL;
+
+void 
+preferred_dbname_ioassign_(const char *dbname
+			   /* Hidden arguments */
+			   , int dbname_len)
+{
+  if (dbname && dbname_len > 0) {
+    DECL_FTN_CHAR(dbname);
+    ALLOC_FTN_CHAR(dbname);
+    if (preferred_DBNAME) FREE(preferred_DBNAME);
+    preferred_DBNAME = STRDUP(p_dbname);
+    FREE_FTN_CHAR(dbname);
+  }
+}
+
+static char *incore_data = NULL;
+static int   len_incore_data = 0;
+
+void
+get_incore_ioassign_(char         data[],
+		     const int  *ndata, /* in bytes */
+		     int *rc)
+{
+  static int first_time = 1;
+  if (first_time) {
+    FILE *fp = NULL;
+    char *IOASSIGN = getenv("IOASSIGN");
+    int allok = 0;
+    if (!IOASSIGN) IOASSIGN = "IOASSIGN";
+    fp = fopen(IOASSIGN, "r");
+    if (!fp && preferred_DBNAME) {
+      /* Try to find suitable IOASSIGN under preferred database directory */
+      /* When found, use that as IOASSIGN-file */
+      char *path, *env;
+      const char base[] = "ODB_SRCPATH";
+      int baselen = strlen(base);
+      int len = baselen + 1 + strlen(preferred_DBNAME) + 1;
+      ALLOC(env,len);
+      snprintf(env,len,"%s_%s",base,preferred_DBNAME);
+      path = getenv(env);
+      FREE(env);
+      if (!path) path = getenv(base);
+      if (path) {
+	/* path is now either $ODB_SRCPATH_<dbname> or $ODB_SRCPATH */
+	const char also[] = "IOASSIGN";
+	int alsolen = strlen(also);
+	char *file;
+	len = strlen(path) + 1 + strlen(preferred_DBNAME) + 1 + alsolen + 1;
+	ALLOC(file,len);
+	/* Check for <path>/<dbname>.IOASSIGN */
+	snprintf(file,len,"%s/%s.%s",path,preferred_DBNAME,also);
+	fp = fopen(file, "r");
+	if (!fp) {
+	  /* Check for <path>/IOASSIGN */
+	  snprintf(file,len,"%s/%s",path,also);
+	  fp = fopen(file, "r");
+	  if (!fp) {
+	    /* Check for <path>/IOASSIGN.<dbname> */
+	    snprintf(file,len,"%s/%s.%s",path,also,preferred_DBNAME);
+	    fp = fopen(file, "r");
+	  } /* if (!fp) */
+	} /* if (!fp) */
+	if (fp) {
+	  IOASSIGN = file;
+	  allok = 1;
+	}
+	else {
+	  FREE(file);
+	}
+      } /* if (path) */
+    } /* if (!fp && preferred_DBNAME) */
+
+    if (fp) {
+      int nread = 0;
+      int fd = fileno(fp);
+      memmap_t *m = memmap_open_read(fd, NULL, NULL); /* see ifsaux/support/memmap.c */
+      FREE(incore_data);
+      if (m) { /* memory mapped I/O : uses mmap() */
+	len_incore_data = (int)m->len;
+	ALLOC(incore_data,len_incore_data+1);
+	memcpy(incore_data, m->buf, len_incore_data * sizeof(*incore_data));
+	(void) memmap_close(m);
+      }
+      else {
+	len_incore_data = filesize_by_fp(fp, IOASSIGN);
+	ALLOC(incore_data,len_incore_data+1);
+	nread = fread(incore_data, sizeof(*incore_data), len_incore_data, fp);
+	/* An overkill ? if (nread != len_incore_data) then abort ? */
+      }
+      incore_data[len_incore_data] = '\0';
+      fclose(fp);
+      if (allok) FREE(IOASSIGN);
+    }
+    first_time = 0;
+  }
+  if (incore_data && len_incore_data > 0) {
+    if (data && ndata && *ndata >= len_incore_data) {
+      memcpy(data,incore_data,len_incore_data);
+    }
+  }
+  *rc = len_incore_data;
+}
+
+void
+put_incore_ioassign_(const char   data[],
+		     const int  *ndata, /* in bytes */
+		     int *rc)
+{
+  if (data && ndata && *ndata > 0) {
+    FREE(incore_data);
+    len_incore_data = *ndata;
+    ALLOC(incore_data,len_incore_data+1);
+    memcpy(incore_data,data,len_incore_data);
+    incore_data[len_incore_data] = '\0';
+  }
+  *rc = len_incore_data;
+}
+
+int 
+IOassign_read(const char  *IOASSIGN, 
+	             int  *pbcount_out, 
+	        Ioassign **ioassign_start_out, 
+	        Ioassign **ioassign_out)
+{
+  int rc = 0;
+  Ioassign *ioassign = NULL;
+  Ioassign *ioassign_start = NULL;
+  int pbcount = 0;
+  
+  /* Open IOASSIGN datafile for input */
+
+  FILE *fp = IOASSIGN ? fopen(IOASSIGN, "r") : NULL;
+  
+  if (!IOASSIGN) {
+    /* stream output (-s) i.e. do not check existing IOASSIGN-file at all */
+    goto finish;
+  }
+  else if (!fp) {
+    /* Error : IOASSIGN-file could not be located */
+    pbcount = -1;
+    rc = -2;
+  }
+  else {
+    /* Read IOASSIGN data */
+    char oneline[MAXLINE+1];
+    char file[MAXFILELEN];
+    char alias[MAXFILELEN];
+    
+    while ( !feof(fp) && fgets(oneline, sizeof(oneline), fp) ) {
+      char *s;
+      Ioassign *tmp;
+      int nitems;
+      
+      ALLOC(tmp, 1);
+      
+      s = strchr(oneline,'\n');
+      if (s) *s = '\0';
+      if (iostuff_debug) fprintf(stderr,"\n'%s'",oneline);
+      
+      if (ioassign) {
+	ioassign->next = tmp;
+	ioassign       = tmp;
+	ioassign->next = NULL;
+      }
+      else {
+	ioassign = ioassign_start = tmp;
+	ioassign->next = NULL;
+      }
+      
+      ioassign->filename  = NULL;
+      ioassign->aliasname = NULL;
+      ioassign->numbins  = 0;
+      ioassign->readbufsize  = 0;
+      ioassign->writebufsize = 0;
+      ioassign->prealloc  = 0;
+      ioassign->extent    = 0;
+      ioassign->compression = 0;
+      ioassign->blocksize = 0;
+      ioassign->concat    = 0;
+      ioassign->maxproc   = 0;
+      ioassign->fromproc   = 0;
+      ioassign->toproc   = 0;
+      ioassign->pipecmd   = NULL;
+      
+      nitems = sscanf(oneline,"%s %s %d %d %d %d %d %d %d %d %d %d %d",
+		      file, alias,
+		      &ioassign->numbins,
+		      &ioassign->readbufsize, &ioassign->writebufsize,
+		      &ioassign->prealloc, &ioassign->extent,
+		      &ioassign->compression, &ioassign->blocksize,
+		      &ioassign->concat, &ioassign->maxproc,
+            &ioassign->fromproc, &ioassign->toproc);
+      
+      if ((nitems != 11)&&(nitems != 13)) {
+	/* Error : Possibly an invalid IOASSIGN-file format encountered */
+	pbcount = -abs(pbcount);
+	fprintf(stderr,"*** Warning: Invalid IOASSIGN-record encountered; Check format!\n");
+	fprintf(stderr,"             '%s'\n",oneline);
+	rc = -3;
+	goto finish;
+      }
+
+      ioassign->hash = IOassign_hash(file);
+      ioassign->filename  = IOstrdup(file, NULL);
+      ioassign->aliasname = IOstrdup(alias, NULL);
+      
+      s = strchr(oneline,'|');
+      if (s) ioassign->pipecmd = STRDUP(s+1);
+      
+      if (iostuff_debug) {
+	fprintf(stderr,
+		"\n==> hash=%u, file='%s', alias='%s', bins=%d, bufsizes=(%d,%d), prealloc=(%d,%d), compr=(%d,%d), concat=%d, maxproc=%d",
+		ioassign->hash,
+		ioassign->filename, ioassign->aliasname, ioassign->numbins,
+		ioassign->readbufsize, ioassign->writebufsize,
+		ioassign->prealloc, ioassign->extent,
+		ioassign->compression, ioassign->blocksize,
+		ioassign->concat, ioassign->maxproc);
+	fprintf(stderr,
+		"\n    pipe='%s'",TRIM(ioassign->pipecmd));
+      }
+
+      pbcount++;
+    }
+
+    fclose(fp);
+    if (iostuff_debug) fprintf(stderr,"\n");
+  }
+
+ finish:
+
+  *pbcount_out        = pbcount;
+  *ioassign_start_out = ioassign_start;
+  *ioassign_out       = ioassign;
+
+  return rc;
+}
+
+
+typedef struct _incore_t {
+  char *p;
+  int lenp;
+} incore_t;
+
+
+incore_t *
+Use_Incore()
+{
+  incore_t *px = NULL;
+  static incore_t x;
+  if (incore_data && len_incore_data > 0) {
+    px = &x;
+    px->p = incore_data;
+    px->lenp = len_incore_data;
+  }
+  return px;
+}
+
+int
+Next_Incore(char s[], int slen, incore_t *px)
+{
+  int rc = 0;
+  if (px && px->p && px->lenp > 0) {
+    char *next_nl = memchr(px->p,'\n',px->lenp);
+    if (next_nl) {
+      int ilen;
+      rc = next_nl - px->p + 1;
+      ilen = MIN(slen,rc);
+      memcpy(s,px->p,ilen);
+      px->p += rc;
+      px->lenp -= rc;
+      rc = ilen;
+    }
+  }
+  return rc;
+}
+
+int 
+IOassign_read_incore(const char  *IOASSIGN, 
+	             int  *pbcount_out, 
+		     Ioassign **ioassign_start_out, 
+		     Ioassign **ioassign_out)
+{
+  int rc = 0;
+  Ioassign *ioassign = NULL;
+  Ioassign *ioassign_start = NULL;
+  int pbcount = 0;
+
+  /* Open IOASSIGN datafile for input */
+
+  incore_t *fp = IOASSIGN ? Use_Incore() : NULL;
+  
+  if (!IOASSIGN) {
+    /* stream output (-s) i.e. do not check existing IOASSIGN-file at all */
+    goto finish;
+  }
+  else if (!fp) {
+    /* Error : IOASSIGN-file could not be located */
+    pbcount = -1;
+    rc = -2;
+  }
+  else {
+    /* Read IOASSIGN data */
+    char oneline[MAXLINE];
+    char file[MAXFILELEN];
+    char alias[MAXFILELEN];
+    
+    while ( Next_Incore(oneline, sizeof(oneline), fp) ) {
+      char *s;
+      Ioassign *tmp;
+      int nitems;
+      
+      ALLOC(tmp, 1);
+      
+      s = strchr(oneline,'\n');
+      if (s) *s = '\0';
+      if (iostuff_debug) fprintf(stderr,"\n'%s'",oneline);
+      
+      if (ioassign) {
+	ioassign->next = tmp;
+	ioassign       = tmp;
+	ioassign->next = NULL;
+      }
+      else {
+	ioassign = ioassign_start = tmp;
+	ioassign->next = NULL;
+      }
+      
+      ioassign->filename  = NULL;
+      ioassign->aliasname = NULL;
+      ioassign->numbins  = 0;
+      ioassign->readbufsize  = 0;
+      ioassign->writebufsize = 0;
+      ioassign->prealloc  = 0;
+      ioassign->extent    = 0;
+      ioassign->compression = 0;
+      ioassign->blocksize = 0;
+      ioassign->concat    = 0;
+      ioassign->maxproc   = 0;
+      ioassign->fromproc   = 0;
+      ioassign->toproc   = 0;
+      ioassign->pipecmd   = NULL;
+      
+      nitems = sscanf(oneline,"%s %s %d %d %d %d %d %d %d %d %d %d %d",
+		      file, alias,
+		      &ioassign->numbins,
+		      &ioassign->readbufsize, &ioassign->writebufsize,
+		      &ioassign->prealloc, &ioassign->extent,
+		      &ioassign->compression, &ioassign->blocksize,
+		      &ioassign->concat, &ioassign->maxproc,
+            &ioassign->fromproc, &ioassign->toproc);
+      
+      if ((nitems != 11)&&(nitems != 13)) {
+	/* Error : Possibly an invalid IOASSIGN-file format encountered */
+	pbcount = -abs(pbcount);
+	fprintf(stderr,"*** Warning: Invalid IOASSIGN-record encountered; Check format!\n");
+	fprintf(stderr,"             '%s'\n",oneline);
+	rc = -3;
+	goto finish;
+      }
+
+      ioassign->hash = IOassign_hash(file);
+      ioassign->filename  = IOstrdup(file, NULL);
+      ioassign->aliasname = IOstrdup(alias, NULL);
+      
+      s = strchr(oneline,'|');
+      if (s) ioassign->pipecmd = STRDUP(s+1);
+      
+      if (iostuff_debug) {
+	fprintf(stderr,
+		"\n==> hash=%u, file='%s', alias='%s', bins=%d, bufsizes=(%d,%d), prealloc=(%d,%d), compr=(%d,%d), concat=%d, maxproc=%d",
+		ioassign->hash,
+		ioassign->filename, ioassign->aliasname, ioassign->numbins,
+		ioassign->readbufsize, ioassign->writebufsize,
+		ioassign->prealloc, ioassign->extent,
+		ioassign->compression, ioassign->blocksize,
+		ioassign->concat, ioassign->maxproc);
+	fprintf(stderr,
+		"\n    pipe='%s'",TRIM(ioassign->pipecmd));
+      }
+
+      pbcount++;
+    }
+
+    if (iostuff_debug) fprintf(stderr,"\n");
+  }
+
+ finish:
+
+  *pbcount_out        = pbcount;
+  *ioassign_start_out = ioassign_start;
+  *ioassign_out       = ioassign;
+
+  return rc;
+}
diff --git a/odb/src/aux/ioassign_write.c b/odb/src/aux/ioassign_write.c
new file mode 100644
index 0000000..3e377fb
--- /dev/null
+++ b/odb/src/aux/ioassign_write.c
@@ -0,0 +1,50 @@
+#include "iostuff.h"
+#include "ioassign.h"
+
+int 
+IOassign_write(const char *IOASSIGN, 
+                      int  pbcount,
+	        Ioassign  *ioassign_start)
+{
+  int rc = 0;
+
+  /* Open IOASSIGN datafile for output */
+
+  FILE *fp = IOASSIGN ? fopen(IOASSIGN, "w") : stdout;
+  
+  if (!fp) {
+    /* Error : Couldn't open IOASSIGN-file for write */
+    perror(IOASSIGN ? IOASSIGN : "<stdout>");
+    rc = -1;
+  }
+  else {
+    /* Write IOASSIGN data */
+    Ioassign *p = ioassign_start;
+
+    while ( p && pbcount > 0 ) {
+
+      if (p->filename) {
+	
+	fprintf(fp,"%s %s %d %d %d %d %d %d %d %d %d %d %d",
+		p->filename, p->aliasname,
+		p->numbins,
+		p->readbufsize, p->writebufsize,
+		p->prealloc, p->extent,
+		p->compression, p->blocksize,
+		p->concat, p->maxproc,
+      p->fromproc, p->toproc);
+
+	fprintf(fp,"%s%s\n",
+		p->pipecmd ? "|" : "\0",
+		p->pipecmd ? p->pipecmd : "\0");
+      }
+
+      p = p->next;
+      pbcount--;
+    }
+
+    if (IOASSIGN) fclose(fp);
+  }
+
+  return rc;
+}
diff --git a/odb/src/aux/ioconcat.c b/odb/src/aux/ioconcat.c
new file mode 100644
index 0000000..227f186
--- /dev/null
+++ b/odb/src/aux/ioconcat.c
@@ -0,0 +1,31 @@
+#include "iostuff.h"
+
+int
+IOconcat_byname(const char *filename,
+		int len_filename)
+{
+  int rc = 0;
+  IOstuff ios;
+
+  IOstuff_init(&ios);
+  ios.logical_name = IOstrdup(filename, &len_filename);
+
+  rc = IOgetattr(&ios);
+
+  if (rc >= 0) {
+    rc = ios.concat;
+  }
+  else {
+    rc = 0;
+  }
+
+  { /* Clean up code */
+    int j, numbins = ios.numbins;
+    for (j=0; j<numbins; j++) {
+      IOstuff_bin_reset(&ios.bin[j]);
+    }
+    IOstuff_reset(&ios);
+  }
+
+  return rc;
+}
diff --git a/odb/src/aux/iocopy.c b/odb/src/aux/iocopy.c
new file mode 100644
index 0000000..cbbdb35
--- /dev/null
+++ b/odb/src/aux/iocopy.c
@@ -0,0 +1,48 @@
+#include "iostuff.h"
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+void
+IOrcopy(real8 out[], const real8 in[], int len)
+{
+  int j;
+  /* Vectorizable */
+  for (j=0; j<len; j++) out[j] = in[j];
+}
+
+void
+IOircopy(integer4 out[], const real8 in[], int len)
+{
+  int j;
+  /* Vectorizable */
+  for (j=0; j<len; j++) out[j] = in[j];
+}
+
+void
+IOricopy(real8 out[], const integer4 in[], int len)
+{
+  int j;
+  /* Vectorizable */
+  for (j=0; j<len; j++) out[j] = in[j];
+}
+
+void
+IOrucopy(real8 out[], const unsigned int in[], int len)
+{
+  int j;
+  /* Vectorizable */
+  for (j=0; j<len; j++) out[j] = in[j];
+}
+
+void
+IOicopy(integer4 out[], const integer4 in[], int len)
+{
+  int j;
+  /* Vectorizable */
+  for (j=0; j<len; j++) out[j] = in[j];
+}
diff --git a/odb/src/aux/iogetattr.c b/odb/src/aux/iogetattr.c
new file mode 100644
index 0000000..41b9171
--- /dev/null
+++ b/odb/src/aux/iogetattr.c
@@ -0,0 +1,220 @@
+#include "iostuff.h"
+#include "ioassign.h"
+
+PRIVATE Ioassign *ioassign = NULL;
+PRIVATE Ioassign *ioassign_start = NULL;
+PRIVATE int pbcount = 0;
+PRIVATE char *mrfs = NULL;
+
+int 
+IOgetattr(IOstuff *iostuff)
+{
+  int rc = 0;
+
+  if (iostuff_debug) fprintf(stderr,"iogetattr");
+
+  if (pbcount < 0) {
+    /* Error : IOASSIGN-file didn't exist or is incorrect; do not retry */
+    rc = -1;
+  }
+  else if (pbcount == 0) {
+    /* One-off */
+    {
+      /* Get MRFSDIR, if defined */
+      char *MRFSDIR = getenv("MRFSDIR");
+      if (MRFSDIR) {
+	mrfs = STRDUP(MRFSDIR);
+      }
+    }
+
+    {
+      /* Read IOASSIGN data */
+
+      /* Check whether IOASSIGN-file is already stored incore ? */
+      char *env = getenv("IOASSIGN_INCORE");
+      int incore_value = env ? atoi(env) : 0;
+      char *IOASSIGN = getenv("IOASSIGN");
+      
+      if (!IOASSIGN) IOASSIGN = "IOASSIGN";
+      if (iostuff_debug) fprintf(stderr," : IOASSIGN='%s'\n",IOASSIGN);
+
+      if (iostuff_debug) fprintf(stderr," : IOASSIGN_INCORE=%d\n",incore_value);
+      
+      rc = -9999;
+      if (incore_value > 0) {
+	rc = IOassign_read_incore(IOASSIGN, &pbcount, &ioassign_start, &ioassign);
+      }
+      if (rc < 0) { /* The original scheme */
+	rc = IOassign_read(IOASSIGN, &pbcount, &ioassign_start, &ioassign);
+      }
+    }
+  }
+
+  if (!iostuff) goto finish;
+
+  if (rc == 0) {
+    rc = -4;
+
+    if (ioassign_start) {
+      int i = 0;
+      Ioassign *p = ioassign_start;
+      char *env = NULL;
+
+      /* Scan first with respect to internal hash */
+      p = IOassign_lookup(iostuff->logical_name, p);
+      if (!p) p = ioassign_start;
+      
+      while ( p ) {
+	int nproc = 0;
+   char table_name[100];
+   table_name[0]=0;
+   
+	env = IOresolve_env(p->filename);
+
+	if (IOstrequ(env,iostuff->logical_name,&nproc,table_name,p->fromproc,p->toproc)) {
+
+	  int j;
+     int table_name_set = (strlen(table_name)!=0) ? 1 : 0;
+	  FREE(env);
+     if (nproc > 0) {
+      if (table_name_set) {
+        env = IOstrdup_fmt2(p->aliasname, nproc, table_name);
+      }
+      else {
+        env = IOstrdup_fmt(p->aliasname, nproc);
+      }
+     } // nproc > 0
+     else { // nproc not set
+      if (table_name_set) {
+        env = IOstrdup_fmt3(p->aliasname, table_name);
+      }
+      else {
+        env = STRDUP(p->aliasname);
+      } 
+     }
+	  iostuff->leading_part = IOresolve_env(env);
+	  FREE(env);
+	  
+	  if (mrfs) {
+	    char *lp = iostuff->leading_part;
+	    int mrfs_len = strlen(mrfs);
+
+	    iostuff->on_mrfs = 
+	      (strncmp(lp,mrfs,mrfs_len) == 0) ?  true : false;
+	  }
+	  else {
+	    iostuff->on_mrfs = false;
+	  }
+	  
+	  iostuff->packmethod = MAX(0,p->compression);
+	  iostuff->blocksize = MAX(0,p->blocksize);
+
+	  if (iostuff_debug) {
+	    fprintf(stderr,
+		    " : assign '%s' to '%s%s' : attr=(%d,%d,%d,%d,%d,%d,%d,%d,%d)\n : on MRFSDIR[%s]=%s",
+		    p->filename, p->aliasname,
+		    (p->numbins == 1) ? "\0" : ",*",
+		    p->numbins,
+		    p->readbufsize, p->writebufsize,
+		    p->prealloc, p->extent,
+		    p->compression, p->blocksize,
+		    p->concat, p->maxproc,
+		    mrfs ? mrfs : "<not defined>",
+		    iostuff->on_mrfs ? "YES" : "NO");
+	    if (p->pipecmd) fprintf(stderr,"\n : pipe='%s'",p->pipecmd);
+	  }
+
+	  iostuff->numbins = MAX(1,p->numbins);
+	  ALLOC(iostuff->bin, iostuff->numbins);
+
+	  iostuff->concat = p->concat;
+
+	  for (j=0; j<iostuff->numbins; j++) {
+	    IObin *pbin = &iostuff->bin[j];
+
+	    IOstuff_bin_init(pbin);
+
+	    if (iostuff->numbins == 1) {
+	      pbin->true_name = STRDUP(iostuff->leading_part);
+	    }
+	    else {
+	      pbin->true_name = IOstrdup_int(iostuff->leading_part, j);
+	    }
+	    pbin->readbuf.len  = p->readbufsize;
+	    pbin->writebuf.len = p->writebufsize;
+	    pbin->prealloc = p->prealloc;
+	    pbin->extent   = p->extent;
+	    /* pbin->pipecmd = p->pipecmd ? STRDUP(p->pipecmd) : NULL; */
+	    pbin->pipecmd = p->pipecmd ? IOresolve_env(p->pipecmd) : NULL;
+	    /* A safety measure to disallow simultaneous internal & external packing */
+	    if (pbin->pipecmd) iostuff->packmethod = 0; 
+	  }
+
+	  rc = i;
+	  break;
+	} /* if (IOstrequ(p->filename,iostuff->logical_name,&nproc) */
+
+	FREE(env);
+
+	p = p->next;
+	i++;
+      } /* while ( p ) */
+
+      FREE(env);
+    } /* if (ioassign_start) */
+
+  } /* if (rc == 0) */
+
+  if (rc < 0) {
+    /* Error : Nothing found ; initialize with defaults */      
+    int numbins = 1;
+    IObin *pbin = NULL;
+    
+    ALLOC(iostuff->bin, numbins);
+    iostuff->numbins = numbins;
+    iostuff->leading_part = IOresolve_env(iostuff->logical_name);
+    
+    pbin = iostuff->bin;
+    IOstuff_bin_init(pbin);
+    pbin->true_name = STRDUP(iostuff->leading_part);
+  }
+
+ finish:
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  return rc;
+}
+
+
+char *
+IOtruename(const char *name, const int *len_str)
+{
+  char *truename = NULL;
+
+  if (name) {
+    IOstuff ios;
+    
+    IOstuff_init(&ios);
+    ios.logical_name = IOstrdup(name,len_str);
+    
+    (void) IOgetattr(&ios);
+    
+    if (ios.leading_part) {
+      truename = STRDUP(ios.leading_part);
+    }
+    else {
+      truename = STRDUP(name);
+    }
+
+    { /* Clean up code */
+      int j, numbins = ios.numbins;
+      for (j=0; j<numbins; j++) {
+	IOstuff_bin_reset(&ios.bin[j]);
+      }
+      IOstuff_reset(&ios);
+    }
+  }
+
+  return truename;
+}
+
diff --git a/odb/src/aux/iogetsize.c b/odb/src/aux/iogetsize.c
new file mode 100644
index 0000000..828724b
--- /dev/null
+++ b/odb/src/aux/iogetsize.c
@@ -0,0 +1,91 @@
+#include "iostuff.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int
+IOgetsize(const char *path, 
+	  int *filesize,
+	  int *blksize)
+{
+  int rc = 0;
+  struct stat buf;
+  int file_size = 0;
+  int blk_size = 0;
+
+  rc = stat(path,&buf);
+  if (rc != 0) {
+    file_size = -1;
+    blk_size  = -1;
+  }
+  else {
+    file_size = buf.st_size;
+    blk_size  = buf.st_blksize;
+  }
+
+  if (filesize) *filesize = file_size;
+  if (blksize)  *blksize  = blk_size;
+
+  return rc;
+}
+
+static int
+recur_mkdir(const char *dir)
+{
+  struct stat buf;
+  int rc = stat(dir, &buf);
+
+  if (rc != 0 && errno == ENOENT) {
+    char *prevdir = STRDUP(dir);
+    char *last = strrchr(prevdir,'/');
+    if (last) {
+      *last = '\0';
+      rc = recur_mkdir(prevdir);
+    }
+    FREE(prevdir);
+    rc = mkdir(dir,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+  }
+
+  return rc;
+}
+
+int
+IOmkdir(const char *pathname)
+{
+  int created = 0;
+
+  if (strchr(pathname,'/')) {
+    int rc;
+#ifndef NECSX
+    extern int errno;
+#endif
+    struct stat buf;
+    char *dir = STRDUP(pathname);
+    char *last = strrchr(dir,'/');
+    if (last) *last = '\0';
+
+    /* === Obsolete code ===
+    rc = stat(dir, &buf);
+    if (rc != 0 && errno == ENOENT) {
+      char *cmd;
+      int len = strlen(BIN_MKDIR) + strlen(dir) + 2;
+      ALLOC(cmd,len);
+      sprintf(cmd,"%s %s",BIN_MKDIR,dir);
+      (void)system(cmd);
+      FREE(cmd);
+      rc = stat(dir, &buf);
+    }
+      === end of Obsolete code === */
+
+    rc = recur_mkdir(dir);
+    rc = stat(dir, &buf);
+    if (rc == 0) created = S_ISDIR(buf.st_mode);
+
+    FREE(dir);
+  }
+
+  return created;
+}
+
diff --git a/odb/src/aux/ioknowncmd.c b/odb/src/aux/ioknowncmd.c
new file mode 100644
index 0000000..4945f8b
--- /dev/null
+++ b/odb/src/aux/ioknowncmd.c
@@ -0,0 +1,162 @@
+#include "iostuff.h"
+
+typedef struct known_cmd_t {
+  /* Only "char *suffix" can be set to NULL */
+  char *label;
+  char *packcmd;
+  char *pack_to;
+  char *unpackcmd;
+  char *unpack_from;
+  char *suffix;
+  Boolean has_incore; /* true if in-memory rather than unix-command is available */
+} Known_CMD;
+
+
+char *
+IOknowncmd(const char *label, Boolean read_only, Boolean *has_incore, char **suffix, const IObuf *iobuf)
+{
+  static const Known_CMD kcmd[] = {
+    /* 
+       Note the double '%%' in %%s is needed, if %d is also present in the same line.
+       This is due to double filtering; after the first filtering/internal write (snprintf)
+       we want to obviously retain the final '%s' for filename
+    */
+    { "#ddgzip",
+      "gzip -c "                                , " | dd of=%%s bs=%d 2>/dev/null", /* note %%s */
+      "dd if=%%s bs=%d 2>/dev/null | gunzip -c ", " ",                              /* note %%s */
+      ".gz", true }, /* "true" meant to be used with zlib */
+    { "#gzip",
+      "gzip -c "  , " > %s", 
+      "gunzip -c ", " < %s" , 
+      ".gz", true }, /* "true" meant to be used with zlib */
+    { "#bzip2",
+      "bzip2 -c "  , " > %s", 
+      "bunzip2 -c ", " < %s", 
+      ".bz2", false },
+    { "#compress",
+      "compress -c -f "  , " > %s", 
+      "uncompress -c ", " < %s", 
+      ".Z", false },
+    { "#pack",
+      "pack -f "  , " %s", 
+      "unpack ", " %s" , 
+      ".z", false },
+    { "#zip",
+      "zip -c "  , " %s", 
+      "unzip -c ", " %s" , 
+      ".zip", false },
+    { "#pcma",
+      "pcma  -w %d ", " -o %%s", /* note %%s */
+      "upcma -r %d ", " -i %%s", /* note %%s */
+      NULL, false },
+    { "#tfecfs",
+      "to_ecfs "  , " %s", 
+      "from_ecfs ", " %s", 
+      NULL, false },
+    { "#user",
+      "$ODB_USER_PACK "  , " %%s %d", /* note %%s */
+      "$ODB_USER_UNPACK ", " %%s %d", /* note %%s */
+      NULL, false },
+    NULL
+  };
+
+  char *cmd = NULL;
+
+  if (has_incore) *has_incore = false;
+  if (suffix) *suffix = NULL;
+
+  if (label && *label == '#') {
+    int j = 0;
+    char *plabel = STRDUP(label);
+    char *p = strchr(plabel,' ');
+    char *flags = NULL;
+
+    if (p) { /* " for example, from IOASSIGN : ...|#gzip -1v */
+      int flags_offset = (p - plabel);
+      flags = STRDUP(plabel+flags_offset);
+      *p = '\0';
+    }
+    
+    for (;;) {
+      const Known_CMD *pcmd = &kcmd[j];
+      
+      if (!pcmd->label) break; /* Last */
+      
+      if (strequ(plabel, pcmd->label)) { /* Matched !! */
+	int cmdlen = 0;
+	int buflen = IO_BUFSIZE_DEFAULT;
+	const char *cmdpre = NULL;
+	const char *cmdpost = NULL;
+
+	if (iobuf) {
+	  buflen = iobuf->len;
+	  if (buflen < 512 || buflen > 1000000000) buflen = IO_BUFSIZE_DEFAULT;
+	}
+
+	if (read_only) {
+	  if (pcmd->unpackcmd[0] == '$') {
+	    char *env = getenv(&pcmd->unpackcmd[1]);
+	    if (!env) {
+	      fprintf(stderr,
+		      "IOknowncmd(): Unable to unpack '%s': Variable '%s' is not defined\n",
+		      label, pcmd->unpackcmd);
+	      break; /* for (;;) */
+	    }
+	  }
+	  cmdpre = pcmd->unpackcmd;
+	  cmdpost = pcmd->unpack_from;
+	}
+	else {
+	  if (pcmd->packcmd[0] == '$') {
+	    char *env = getenv(&pcmd->packcmd[1]);
+	    if (!env) {
+	      fprintf(stderr,
+		      "IOknowncmd(): Unable to pack '%s': Variable '%s' is not defined\n",
+		      label, pcmd->packcmd);
+	      break; /* for (;;) */
+	    }
+	  }
+	  cmdpre = pcmd->packcmd;
+	  cmdpost = pcmd->pack_to;
+	}
+
+	cmdlen = strlen(cmdpre) + strlen(cmdpost);
+	if (flags) cmdlen += strlen(flags);
+	cmdlen++;
+
+	ALLOC(cmd,cmdlen);
+
+	strcpy(cmd,cmdpre);
+	if (flags) strcat(cmd,flags);
+	strcat(cmd,cmdpost);
+
+	if (strstr(cmd,"%d")) {
+	  char *tmp = NULL;
+	  int tmplen = strlen(cmd) + 30; /* Accomodate value for "%d" */
+	  ALLOC(tmp,tmplen);
+	  snprintf(tmp,tmplen,cmd,buflen);
+	  FREE(cmd);
+	  cmd = tmp;
+	}
+
+	if (has_incore) *has_incore = pcmd->has_incore;
+	if (suffix && pcmd->suffix) *suffix = STRDUP(pcmd->suffix);
+
+	break; /* for (;;) */
+      }
+
+      j++;
+    } /* for (;;) */
+    
+    FREE(plabel);
+    if (flags) FREE(flags);
+  } /* if (label && *label == '#') */
+
+  if (!cmd) cmd = STRDUP(label); /* STRDUP will return blank string if label points to nothing */
+
+#if 0
+  if (label && cmd) fprintf(stderr,"IOknowncmd(%s, etc.) --> '%s'\n",label,cmd);
+#endif
+
+  return cmd;
+}
diff --git a/odb/src/aux/ioprealloc.c b/odb/src/aux/ioprealloc.c
new file mode 100644
index 0000000..71d4673
--- /dev/null
+++ b/odb/src/aux/ioprealloc.c
@@ -0,0 +1,108 @@
+#include "iostuff.h"
+
+#ifdef __uxppx__
+#include <sys/fs/vfl.h>
+#endif
+
+#ifdef CRAYXT
+
+#include <sys/stat.h>
+#define STATVFS stat
+#define STAT_FS(p,pb) stat(p,pb)
+#define STAT_BSIZE st_blksize
+
+#elif defined(CRAY) || defined(NECSX)
+
+#include <sys/statfs.h>
+#define STATVFS statfs
+#define STAT_FS(p,pb) statfs(p,pb,sizeof(struct statfs),0)
+#define STAT_BSIZE f_bsize
+
+#else
+
+#include <sys/statvfs.h>
+#define STATVFS statvfs
+#define STAT_FS(p,pb) statvfs(p,pb)
+#define STAT_BSIZE f_bsize
+
+#endif
+
+
+static int
+IOget_path_blocksize(const char *filename)
+{
+  int blk_size = 0;
+  struct STATVFS buf;
+  char *path = STRDUP(filename);
+  char *s = strrchr(path,'/');
+
+  if (s) {
+    *s = '\0';
+  }
+  else {
+    FREE(path);
+    path = STRDUP(".");
+  }
+  
+  if (STAT_FS(path,&buf) != -1) {
+    blk_size = buf.STAT_BSIZE;
+  }
+
+  FREE(path);
+
+  return blk_size;
+}
+
+
+FILE *
+IOprealloc(const char *filename,
+	   int         prealloc,
+	   int         extent,
+	   int        *blksize,
+	   int        *retcode)
+{
+  int fd = -1;
+  int blk_size = 0;
+  FILE *fp = NULL;
+  const char *write_mode = "w";
+  Boolean allocated = false;
+
+  if (prealloc > 0) {
+    blk_size = IOget_path_blocksize(filename);
+
+#ifdef __uxppx__
+    if (blk_size > 0) {
+      const int vfl_mode = 0664;
+      prealloc = RNDUP(prealloc,blk_size)/blk_size;
+      if (extent <= 0) extent = blk_size;
+      extent = RNDUP(extent,blk_size)/blk_size;
+
+      (void) remove(filename);
+
+      fd = vfl_create(filename, prealloc, extent,
+		      VFL_ZERO, vfl_mode,
+		      VFL_REPLACE);
+
+      if (fd == -1) {
+	PERROR(filename);
+      }
+      else{
+	allocated = true;
+      }
+    }
+#endif
+  }
+
+  if (!allocated) {
+    fp = fopen(filename, write_mode);
+    if (fp) fd = fileno(fp);
+  }
+  else {
+    fp = fdopen(fd, write_mode);
+  }
+
+  if (retcode)                 *retcode  = fd;
+  if (blksize && blk_size > 0) *blksize = blk_size;
+
+  return fp;
+}
diff --git a/odb/src/aux/iosetbuf.c b/odb/src/aux/iosetbuf.c
new file mode 100644
index 0000000..b76aa4b
--- /dev/null
+++ b/odb/src/aux/iosetbuf.c
@@ -0,0 +1,65 @@
+#include "iostuff.h"
+
+const int min_io_bufsize = IO_BUFSIZE_DEFAULT;
+
+int
+IOsetbuf(      FILE *fp,
+	 const char *filename,
+	    Boolean  read_only,
+	      IObuf *iobuf,
+	        int *filesize,
+	        int *blksize)
+{
+  int rc = 0;
+  int file_size = 0;
+  int blk_size = 0;
+  
+  if (read_only) {
+    /* READ-ONLY files */
+
+    rc = IOgetsize(filename, &file_size, &blk_size);
+    
+    if (iostuff_debug) fprintf(stderr," : filesize=%d, blksize=%d",
+			       file_size, blk_size);
+    
+    if (iobuf->len > 0 || iobuf->len == -1) {
+      /* Adjust buflen to prevent buffer becoming too excessive in size 
+	 Note: This is a file size prior to opening any pipe */
+      if (iobuf->len == -1) iobuf->len = file_size;
+      if (file_size >= 0) {
+	iobuf->len = MIN(iobuf->len, file_size);
+      }
+    }
+
+    /* Do not allow too small buffers */
+    iobuf->len = MAX(iobuf->len, min_io_bufsize);
+
+    if (iobuf->len > 0) {
+      SETBUF(iobuf);
+      if (iostuff_debug) {
+	fprintf(stderr," : readIObuf=(%p,%d)",
+		iobuf->p, iobuf->len);
+      }
+    }
+  }
+  else {
+    /* WRITE-ONLY files */
+
+    /* Do not allow too small buffers */
+    iobuf->len = MAX(iobuf->len, min_io_bufsize);
+
+    if (iobuf->len > 0) {
+      SETBUF(iobuf);
+      if (iostuff_debug) {
+	fprintf(stderr," : writeIObuf=(%p,%d)",
+		iobuf->p, iobuf->len);
+      }
+    }
+  }
+
+  if (filesize) *filesize = file_size;
+  if (blksize)  *blksize  = blk_size;
+
+  return rc;
+}
+
diff --git a/odb/src/aux/iostrdup.c b/odb/src/aux/iostrdup.c
new file mode 100644
index 0000000..73a1d2c
--- /dev/null
+++ b/odb/src/aux/iostrdup.c
@@ -0,0 +1,405 @@
+#include "iostuff.h"
+#include "cmaio.h"
+#include <stdbool.h>
+
+char *
+IOstrdup(const char *str, const int *len_str)
+{
+  char *salloc, *s;
+  char *p = NULL;
+  const char *invalid_filename = ":invalid_filename:";
+
+  if (len_str) {
+    int len = *len_str;
+    ALLOC(salloc, len + 1);
+    strncpy(salloc,str,len);
+    salloc[len] = '\0';
+  }
+  else {
+    salloc = STRDUP(str);
+  }
+
+  s = salloc;
+  while (*s) { /* Strip off any leading blanks */
+    if (*s != ' ') break;
+    s++;
+  }
+
+  /* Strip off any trailing blanks */
+  p = strchr(s,' ');
+  if (p) *p = '\0';
+  
+  if (*s) {
+    p = (strlen(s) > 0) ? STRDUP(s) : STRDUP(invalid_filename);
+  }
+  else {
+    p = STRDUP(invalid_filename);
+  }
+
+  FREE(salloc);
+
+  return p;
+}
+
+char *
+IOstrdup_int(const char *str, int binno)
+{
+  char *p = NULL;
+  char *salloc = IOstrdup(str,NULL);
+  int len = strlen(salloc) + 20;
+
+  ALLOC(p, len);
+  snprintf(p,len,"%s,%d",salloc,binno);
+  FREE(salloc);
+
+  return p;
+}
+
+char *
+IOstrdup_fmt(const char *fmt, int nproc)
+{
+  char *p = NULL;
+  size_t len = strlen(fmt) + 20;
+
+  ALLOC(p, len);
+  snprintf(p, len, fmt, nproc);
+
+  return p;
+}
+
+char *
+IOstrdup_fmt2(const char *fmt, int nproc, char *table_name)
+{
+  // TODO: deal with case where table_name comes before nproc in format string
+  char *p = NULL;
+  size_t len = strlen(fmt) + 100; // table names can be large
+
+  ALLOC(p, len);
+  snprintf(p, len, fmt, nproc, table_name);
+
+  return p;
+}
+
+
+char *
+IOstrdup_fmt3(const char *fmt, char *table_name)
+{
+  // TODO: deal with case where table_name comes before nproc in format string
+  char *p = NULL;
+  size_t len = strlen(fmt) + 100; // table names can be large
+
+  ALLOC(p, len);
+  snprintf(p, len, fmt, table_name);
+
+  return p;
+}
+
+
+int count_format_specifiers_in_string(char *mystring){
+   // count how many format specifiers
+    int count=0;
+    char *p = strchr(mystring,'%'); /* location of first '%' */
+    while (p != NULL) {
+       count += 1;
+       p = strchr(p+1,'%'); /* location of next '%' */
+    }
+    return count;
+}
+
+
+/* return a new string with every instance of orig replaced by new_char */
+char *replace_char_with(const char *s, char *orig_char, char *new_char) {
+    size_t len = strlen(s)+1;
+    char *new_string = malloc(len);
+    memcpy(new_string, s,len);
+    int i;
+    for (i=0;i<len;i++){
+        if(s[i] == *orig_char) new_string[i]=*new_char;
+    }
+    return new_string;
+}
+
+
+int calc_local_pool_number(int extracted_nproc, int fromproc, int toproc, int *nproc) {
+     int match = 0;
+     if((fromproc != 0)&&(toproc != 0)){ // if filled in then use them to check valid range
+       if (extracted_nproc>=fromproc && extracted_nproc<=toproc){
+            if (nproc) *nproc = extracted_nproc - (fromproc-1);
+            match = 1;
+       }
+     }
+     else {
+          match = 1;
+          if (nproc) *nproc = extracted_nproc;
+     }
+    return match;
+}
+
+
+int IOstrequ(const char *fmt,
+             const char *str,
+             int *nproc,
+             char *table_name,
+             int fromproc,
+             int toproc)
+{
+    // Initialize
+    bool is_percent_d = false;
+    bool is_percent_s = false;
+    bool contains_dot = false;
+    int match = 0;
+    int i,j,j2;
+    int extracted_nproc;
+    int index_in_char;
+    int index_of_start_of_fmt;
+    int nelem;
+    char *p;
+    
+    if (nproc) *nproc = 0;
+
+    if ((p = strchr(fmt,'%')) != NULL) {
+
+        // Remove all delimiter '.' from the strings
+        char* a = replace_char_with(fmt,"."," ");
+        char* b = replace_char_with(str,"."," ");
+        // Does everything up to the first format specifier match?
+        p = strchr(a,'%'); /* location of first '%' */
+        int len = p-a;
+        bool possible_match = (p && (len == 0 || (len > 0 && strnequ(fmt,str,len))));
+        bool s_first = false;
+        bool d_first = false;
+
+
+        if (possible_match) {
+           
+            size_t lena = strlen(a);
+            size_t lenb = strlen(b);
+
+            // Count how many format specifiers
+            int n_fmt = count_format_specifiers_in_string(a);
+
+            // How long is the string?
+            len = strlen(a);
+
+            is_percent_d = false;
+            is_percent_s = false;
+
+            // Loop over all format specifiers 
+            for (i=1;i<=n_fmt;i++){
+                j=1;
+
+                // Loop over characters after the '%' until either a 'd' or an 's' is reached
+                contains_dot = false;
+                index_of_start_of_fmt = p-a;
+                while (j<(len-(p-a))) {
+                   index_in_char = p+j-a;
+
+                   // do not allow spaces inside format specifiers
+                   if (a[index_in_char] == ' ') {
+                        a[index_in_char] = '.';
+                   }
+
+                   if (a[index_in_char] == '.') {
+                        contains_dot = true;
+                   }
+
+                   // If %..d
+                   if (a[index_in_char] == 'd') { /* is next character a 'd'  */
+                        is_percent_d = true; 
+                        if (!s_first) d_first = true;
+                        
+                        // Special case for %X.Yd format specifiers: %3.3d -> %d
+                        if (contains_dot) {
+                            a[index_of_start_of_fmt+1]='d';
+                            for (j2=2;j2<index_in_char-index_of_start_of_fmt;j2++) {
+                                a[index_of_start_of_fmt+j2] = ' ';
+                            }
+                        }
+                        break;
+                   }
+
+                   // If %s
+                   if( a[index_in_char] == 's') { /* is next character an 's' */
+                        is_percent_s = true;
+                        if (!d_first) s_first = true;
+
+                        break;
+                   }
+                   j++;
+                }
+                p = strchr(p+1,'%'); /* move on to next '%' */
+            }
+
+            if (is_percent_d && is_percent_s && s_first) {
+                // Extract table name and pool number
+                nelem = sscanf(b,a,table_name,&extracted_nproc);
+                if (nelem == 2) match = calc_local_pool_number(extracted_nproc, fromproc, toproc, nproc);
+            }       
+            else if (is_percent_d && is_percent_s && d_first) {
+                // Extract table name and pool number
+                nelem = sscanf(b,a,&extracted_nproc,table_name);
+                if (nelem == 2) match = calc_local_pool_number(extracted_nproc, fromproc, toproc, nproc);
+            }       
+            else if (is_percent_d && !is_percent_s) {
+                // Extract table name and pool number
+                nelem = sscanf(b,a,&extracted_nproc);
+                if (nelem == 1) match = calc_local_pool_number(extracted_nproc, fromproc, toproc, nproc);
+            }
+            else if (is_percent_s && !is_percent_d) {
+                nelem = sscanf(b,a,table_name);
+                if (nelem ==1) match = 1;
+            }
+        }   // if probable match
+        FREE(a);
+        FREE(b);
+  }
+  else {
+        match = strequ(fmt, str);
+  }
+  return match;
+}
+
+/* Crack enviroment variables from a given string */
+
+static int 
+getit(const char *p, int *step, char **out, const char *target)
+{
+  char *salloc = STRDUP(p);
+  char *s      = salloc;
+  int count = 0;
+  int Step = 0;
+  int finish = 0;
+  int curl = ( *s == '{' );
+  char *e;
+  char *env;
+
+  if (curl) {
+    Step++;
+    s++;
+  }
+
+  if (out) *out = NULL;
+
+  e = s;
+
+  while ( *s && !finish ) {
+    if (curl) {
+      if (*s == '}') {
+   Step++;
+   finish = 1;
+      }
+    }
+    else {
+      int c = *s;
+      if (!isalnum(c) && !(c == '_')) finish = 1;
+    }
+    if (!finish) {
+      Step++;
+      s++;
+    }
+  }
+
+  *s = '\0';
+
+  env = getenv(e);
+  if (env) {
+    count = strlen(env);
+    if (out) *out = STRDUP(env);
+  }
+  else if (target) {
+    int rc = 1;
+    cma_get_perror_(&rc);
+    if (rc) {
+      fprintf(stderr,
+         "*** Warning: Cannot resolve the environment variable '%s' in '%s'\n",
+         e, target);
+    }
+  }
+
+  FREE(salloc);
+
+  if (step) *step = Step;
+
+  return count;
+}
+
+static char *
+crack(const char *s)
+{
+  char *r = NULL;
+
+  if (strchr(s,'$')) {
+    int count = 0;
+    char *palloc = STRDUP(s);
+    char *p = palloc;
+    char *pr;
+
+    /* fprintf(stderr,"(1) s='%s'\n",s); */
+
+    while ( *p ) {
+      /* fprintf(stderr,"\t at current *p = '%s'\n",p); */
+      if ( *p != '$' ) {
+   count++;
+   p++;
+      }
+      else {
+   int step;
+   count += getit(++p,&step,NULL,s);
+   p += step;
+      }
+    }
+
+    p = palloc;
+    ALLOC(r, count + 1);
+
+    pr = r;
+
+    /* fprintf(stderr,"(2) s='%s'\n",s); */
+    while ( *p ) {
+      /* fprintf(stderr,"\t at current *p = '%s'\n",p); */
+      if ( *p != '$' ) {
+   *pr++ = *p++;
+      }
+      else {
+   int step;
+   char *out;
+   count = getit(++p,&step,&out,NULL);
+   if (out) {
+     strcpy(pr,out);
+     pr += count;
+     FREE(out);
+   }
+   p += step;
+      }
+    }
+
+    *pr = '\0';
+
+    FREE(palloc);
+  }
+  else {
+    r = STRDUP(s);
+  }
+
+  return r;
+}
+
+
+char *
+IOresolve_env(const char *str)
+{
+  char *p = NULL;
+    
+  if (str) {
+    if (!strchr(str,'$')) {
+      p = STRDUP(str);
+    }
+    else {
+      /* Scan for $'s and resolve (getenv()) them, if possible */
+      
+      p = crack(str);
+    }
+  }
+    
+  return p;
+}
diff --git a/odb/src/aux/iostuff_init.c b/odb/src/aux/iostuff_init.c
new file mode 100644
index 0000000..315d313
--- /dev/null
+++ b/odb/src/aux/iostuff_init.c
@@ -0,0 +1,135 @@
+#include "iostuff.h"
+
+Boolean  iostuff_debug = false;
+Boolean  iostuff_stat  = false;
+integer4 iostuff_stat_ftn_unit = -1;
+
+void 
+IOstuff_init(IOstuff *p)
+{
+  p->logical_name = NULL;
+  p->leading_part = NULL;
+
+  p->is_inuse     = false;
+  p->read_only    = true;
+  p->is_detached  = false;
+  p->on_mrfs      = false;
+  p->is_mrfs2disk = false;
+  p->req_byteswap = false;
+
+  p->scheme       = none;
+
+  p->packmethod   = 0;
+  p->blocksize    = 0;
+
+  p->concat       = 0;
+
+  p->numbins      = 0;
+  p->bin          = NULL;
+}
+
+
+void 
+IOstuff_bin_init(IObin *pbin)
+{
+  pbin->true_name    = NULL;
+
+  pbin->fp           = NULL;
+  pbin->fileno       = -1;
+  pbin->begin_filepos = 0;
+  pbin->filepos      = 0;
+  pbin->filesize     = 0;
+
+  pbin->blksize      = 0;
+
+  pbin->readbuf.p    = NULL;
+  pbin->readbuf.len  = 0;
+  
+  pbin->writebuf.p   = NULL;
+  pbin->writebuf.len = 0;
+
+  pbin->prealloc     = 0;
+  pbin->extent       = 0;
+
+  pbin->pipecmd      = NULL;
+  pbin->cmd          = NULL;
+
+  pbin->stat.open_time  = 0;
+  pbin->stat.close_time = 0;
+  pbin->stat.bytes      = 0;
+  pbin->stat.num_trans  = 0;
+  pbin->stat.t.walltime = 0;
+  pbin->stat.t.usercpu  = 0;
+  pbin->stat.t.syscpu   = 0;
+
+  pbin->mr2d_infolen = 0;
+  pbin->mr2d_info    = NULL;
+}
+
+Boolean
+IOstuff_byteswap(IOstuff *p, Boolean value)
+{
+  Boolean oldvalue = p->req_byteswap;
+  p->req_byteswap = value;
+  return oldvalue;
+}
+
+void 
+IOstuff_reset(IOstuff *p)
+{
+  p->is_inuse     = false;
+  /* p->read_only  = true; */
+  p->is_detached  = false;
+  p->on_mrfs      = false;
+  p->is_mrfs2disk = false;
+  /* p->req_byteswap = false; */
+
+  p->scheme = none;
+	
+  p->packmethod = 0;
+  p->blocksize = 0;
+	
+  p->concat = 0;
+
+  FREE(p->bin);
+  p->numbins = 0;
+  
+  FREE(p->logical_name);
+  FREE(p->leading_part);
+}
+
+
+void 
+IOstuff_bin_reset(IObin *pbin)
+{
+  FREE(pbin->true_name);
+	
+  pbin->fp = NULL;
+  pbin->fileno = -1;
+  pbin->begin_filepos = 0;
+  pbin->filepos = 0;
+  pbin->filesize = 0;
+	
+  pbin->blksize = 0;
+
+  FREEIOBUF(pbin->readbuf);
+
+  FREEIOBUF(pbin->writebuf);
+	
+  pbin->prealloc = 0;
+  pbin->extent   = 0;
+	
+  FREE(pbin->pipecmd);
+  FREE(pbin->cmd);
+	
+  pbin->stat.open_time  = 0;
+  pbin->stat.close_time = 0;
+  pbin->stat.bytes      = 0;
+  pbin->stat.num_trans  = 0;
+  pbin->stat.t.walltime = 0;
+  pbin->stat.t.usercpu  = 0;
+  pbin->stat.t.syscpu   = 0;
+
+  pbin->mr2d_infolen = 0;
+  FREE(pbin->mr2d_info);
+}
diff --git a/odb/src/aux/iotimes.c b/odb/src/aux/iotimes.c
new file mode 100644
index 0000000..791f072
--- /dev/null
+++ b/odb/src/aux/iotimes.c
@@ -0,0 +1,79 @@
+#include "iostuff.h"
+
+#include <sys/types.h>
+#include <sys/times.h>
+#include <time.h>
+#include <sys/time.h>
+
+static real8 
+walltime()
+{
+  static real8 time_init = 0;
+  real8 time_in_secs;
+  struct timeval tbuf;
+  if (gettimeofday(&tbuf,NULL) == -1) PERROR("walltime()");
+
+  if (time_init == 0) time_init = 
+    (real8) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0);
+
+  time_in_secs = 
+  (real8) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0) - time_init;
+
+  return time_in_secs;
+}
+
+
+#if defined(CRAYXT)
+/* Cray XT3/XT4 with catamount microkernel */
+
+static real8 
+cputime(real8 *user, real8 *sys)
+{
+  real8 w = walltime(); /* In absence of anything better */
+  if (user) *user = w;
+  if (sys)  *sys = 0;
+  return w;
+}
+
+#else
+extern clock_t times (struct tms *buffer);
+#define clock_ticks ( (real8) sysconf(_SC_CLK_TCK) )
+
+
+static real8 
+cputime(real8 *user, real8 *sys)
+{
+  struct tms tbuf;
+  (void) times(&tbuf);
+  
+  if (user) *user = (tbuf.tms_utime + tbuf.tms_cutime) / clock_ticks;
+  if (sys)  *sys  = (tbuf.tms_stime + tbuf.tms_cstime) / clock_ticks;
+  
+  return (tbuf.tms_utime + tbuf.tms_stime +
+          tbuf.tms_cutime + tbuf.tms_cstime) / clock_ticks; 
+}
+#endif
+
+void 
+IOtimes(IOtime *p)
+{
+  static real8 w1=0, u1=0, s1=0;
+
+  if (p) {
+    real8 w2, u2, s2;
+
+    cputime(&u2, &s2);
+    w2 = walltime();
+
+    p->usercpu  += (u2 - u1);
+    p->syscpu   += (s2 - s1);
+    p->walltime += (w2 - w1);
+  }
+  else {
+    cputime(&u1, &s1);
+    w1 = walltime();
+  }
+}
+
+
+
diff --git a/odb/src/aux/lzw.c b/odb/src/aux/lzw.c
new file mode 100644
index 0000000..6b04164
--- /dev/null
+++ b/odb/src/aux/lzw.c
@@ -0,0 +1,391 @@
+
+/* Lempel-Ziv-Welch -style of packing (non-vectorizable; some routines are ... now!) */
+
+#include "pcma.h"
+#include <signal.h>
+
+/*
+   ECMWF's LZW packing bugfixed by Sami Saarinen 1-Dec-2000
+   Added OpenMP safety & some vectorization 30-Nov-2004
+ */
+
+#define MAXCODE(n)      ((1 << (n)) - 1)
+#define CHECK_GAP       10000           /* enc_ratio check interval */
+
+#define BITS_MIN        9               /* start with 9 bits */
+#define BITS_MAX        12              /* max of 12 bit strings */
+#define CODE_CLEAR      256             /* code to clear string table */
+#define CODE_EOI        257             /* end-of-information code */
+#define CODE_FIRST      258             /* first free code entry */
+#define CODE_MAX        MAXCODE(BITS_MAX)
+#if 1
+#define HSIZE           9001            /* 91% occupancy */
+#define HSHIFT          (8-(16-13))
+#else
+#define HSIZE           5003            /* 80% occupancy */
+#define HSHIFT          (8-(16-12))
+#endif
+
+PRIVATE const unsigned char masks[] =  {
+  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,
+};
+
+/*====================================================================*/
+
+#define OUT(x,str,fail) \
+{unsigned char _c = x; \
+ if (++outcount>outlen) {errflg++; if (fail) Rabort(str,__FILE__,__LINE__);} \
+ else *outbuffer++ = _c; }
+
+#define PTROUT(x,str,fail) \
+{unsigned char _c = x; \
+ if (++(*outcount)>(*outlen)) {(*errflg)++; if (fail) Rabort(str,__FILE__,__LINE__);} \
+ else *outbuffer++ = _c; }
+
+#define NEXTBYTE(c,buf,str) \
+{ if (++incount>inlen) {errflg++; Rabort(str,__FILE__,__LINE__);} \
+  else c = *buf++; }
+
+
+#define CODE(str) (code < CODE_MAX) ? code : Rabort(str,__FILE__,__LINE__)
+
+/*====================================================================*/
+
+PRIVATE int
+Rabort(const char *str, const char *file, int line)
+{
+  fprintf(stderr,"***Error: LZW packing/unpacking failed at %s:%s, line#%d\n",file,str,line);
+  RAISE(SIGABRT);
+  exit(1);
+  return 0;
+}
+
+PRIVATE unsigned char *
+write_code(unsigned int code,
+           int nbits,
+	   int           *errflg,
+	   unsigned char *outbuffer,
+	   int           *outlen,
+           int           *bitio_used,
+	   unsigned int  *bitio_buffer,
+	   int           *outcount,
+	   const char *str)
+{
+  if (nbits + (*bitio_used) > sizeof(*bitio_buffer)*8) {
+    while (*bitio_used >= 8) {
+      unsigned char c = ((*bitio_buffer) >> (8*sizeof(*bitio_buffer) - 8));
+      PTROUT(c,str,0);
+      *bitio_buffer <<= 8;
+      *bitio_used    -= 8;
+    }
+  }
+  code <<= (sizeof(code)*8 - nbits - (*bitio_used));
+  *bitio_buffer += code;
+  *bitio_used   += nbits;
+  return outbuffer;
+}
+
+#define \
+flush_code() \
+{ \
+  while (bitio_used > 0) { \
+    unsigned char c = (bitio_buffer >> (8*sizeof(bitio_buffer) - 8)); \
+    OUT(c,"flush_code",0); \
+    bitio_buffer <<= 8; \
+    bitio_used    -= 8; \
+  } \
+}
+
+#define \
+init_table(table, \
+	   size) \
+{ \
+  int j; \
+  /* The following routine is now inlined & vectorized (size == HSIZE) */ \
+  /* while (size--) *table++ = -1; */ \
+  for (j=0; j<size; j++) table[j] = -1; \
+}
+
+
+PRIVATE unsigned int 
+read_code(const unsigned char *p,
+	  int *bitp,
+	  int nbits,
+	  int inlen)
+{
+  int    len  = nbits;
+  int    skip = *bitp;
+  int         s = skip%8;
+  int         n = 8-s;
+  unsigned int  ret = 0;
+  const unsigned char *p_orig = p;
+
+  skip = (skip >> 3);
+  if (skip >= inlen) { ret=CODE_EOI; goto finish; }
+
+  p += skip; /* skip the bytes */
+  
+  if (s) {
+    if (p - p_orig + 1 == inlen) { ret=CODE_EOI; goto finish; }
+    ret = masks[n] & *p++;
+    len -= n;
+  }
+  
+  while (len >= 8) {
+    if (p - p_orig + 1 == inlen) { ret=CODE_EOI; goto finish; }
+    ret = (ret<<8) + *p++;
+    len -= 8;
+  }
+
+  ret = (ret << len) + (*p >> (8-len));
+  
+  *bitp += nbits;
+
+  if (p - p_orig >= inlen) {
+    fprintf(stderr,"read_code: out of bounds by %lld bytes\n",
+	    (long long int)(p - p_orig - inlen + 1));
+    Rabort("read_code",__FILE__,__LINE__);
+  }
+
+ finish:  
+  return ret;
+}
+
+
+void
+lzw_unpack_(const unsigned char ibuf[],
+	    const int *Ilen,
+	    unsigned char obuf[], 
+	    const int *Olen,
+	    int *retcode)
+{
+  int ilen = *Ilen;
+  int olen = *Olen;
+  int prefix[HSIZE];
+  unsigned char suffix[CODE_MAX+1];
+  unsigned char stack [HSIZE];
+  
+  unsigned char *stackp = stack;
+  int code,firstchar, oldcode, incode;
+  int i;
+  int bitp = 0;
+  int maxcode;
+  int first_free;
+  int nbits;
+
+  /* "globals" that used to be non-threadsafe */
+  int            errflg       = 0;
+  unsigned char *outbuffer    = obuf;
+  int            outlen       = olen;
+  int            inlen        = ilen;
+  int            bitio_used   = 0;
+  unsigned int   bitio_buffer = 0;
+  int            outcount     = 0;
+  int            incount      = 0;
+
+  for (i=0; i<256; i++) suffix[i] = (unsigned char)i;
+  
+  maxcode    = MAXCODE(BITS_MIN) - 1;
+  nbits      = BITS_MIN;
+  first_free = CODE_FIRST;
+
+  while ((code = read_code(ibuf,&bitp,nbits,inlen)) != CODE_EOI) {
+    if (code == CODE_CLEAR) {
+      bzero(prefix, sizeof(prefix));
+      
+      nbits      = BITS_MIN;
+      maxcode    = MAXCODE(BITS_MIN) - 1;
+      first_free = CODE_FIRST;
+      
+      if ((code = read_code(ibuf,&bitp,nbits,inlen)) == CODE_EOI) break;
+      
+      OUT(code,"lzw_unpack_[code]",1);
+      
+      oldcode = firstchar = code;
+      continue;
+    }
+
+    incode = code;
+
+    if (code >= first_free) {
+      /* code not in table */
+      *stackp++ = firstchar;
+      if(stackp - stack > sizeof(stack)) {
+	Rabort("Ooops.... error in lzw[*stackp++ = firstchar]",
+	       __FILE__,__LINE__);
+      }
+      code = oldcode;
+    }
+    
+    while (code >= 256) {
+      *stackp++ = suffix[CODE("while (code >= 256):suffix")];
+      if(stackp - stack > sizeof(stack)) {
+	Rabort("Ooops.... error in lzw[*stackp++ = suffix[code]]",
+	       __FILE__,__LINE__);
+      }
+      code      = prefix[CODE("while (code >= 256):prefix")];
+    }
+
+    *stackp++ = firstchar = suffix[CODE("*stackp++ = firstchar:suffix")];
+    
+    if(stackp - stack > sizeof(stack)) {
+      Rabort("Ooops.... error in lzw[*stackp++ = firstchar = suffix[code]]",
+	     __FILE__,__LINE__);
+    }
+
+    do {
+      if (outcount >= outlen) break;
+      OUT(*--stackp,"lzw_unpack_[stackp]",1);
+    } while (stackp > stack);
+
+    if ((code = first_free) < CODE_MAX) {
+      prefix[CODE("if ((code = first_free) < CODE_MAX):prefix")] = oldcode;
+      suffix[CODE("if ((code = first_free) < CODE_MAX):suffix")] = firstchar;
+      first_free++;
+      
+      if (first_free > maxcode) {
+	nbits++;
+	if (nbits > BITS_MAX) nbits = BITS_MAX;
+	maxcode = MAXCODE(nbits) - 1;
+      }
+    }
+
+    oldcode = incode;
+  } /* while ((code = read_code(ibuf,&bitp,nbits,inlen)) != CODE_EOI) */
+
+  *retcode = errflg ? -outcount : outcount;
+}
+
+
+void
+lzw_pack_(const unsigned char ibuf[], 
+	  const int *Ilen,
+	  unsigned char obuf[],
+	  const int *Olen,
+	  int *retcode)
+{
+  int ilen = *Ilen;
+  int olen = *Olen;
+  int string;
+  int h,disp,ent;
+  int maxcode;
+  int first_free;
+  int nbits;
+  
+  int stringtab[HSIZE];
+  int codetab[HSIZE];
+
+  /* "globals" that used to be non-threadsafe */
+  int            errflg       = 0;
+  unsigned char *outbuffer    = obuf;
+  int            outlen       = olen;
+  int            inlen        = ilen;
+  int            bitio_used   = 0;
+  unsigned int   bitio_buffer = 0;
+  int            outcount     = 0;
+  int            incount      = 0;
+
+  bzero(codetab, sizeof(codetab));
+
+  nbits      = BITS_MIN;
+  
+  init_table(stringtab,HSIZE);
+  first_free = CODE_FIRST;
+  
+  maxcode = MAXCODE(BITS_MIN);
+
+  outbuffer =
+    write_code(CODE_CLEAR,nbits,
+	       &errflg, outbuffer, &outlen, &bitio_used, &bitio_buffer, &outcount,
+	       "lzw_pack_[write_code(CODE_CLEAR)]");
+
+  NEXTBYTE(ent,ibuf,"lzw_pack_[ent]");
+
+  while (--ilen > 0) {
+    int c;
+    
+    NEXTBYTE(c,ibuf,"lzw_pack_[c]");
+
+    string = ((int)c << BITS_MAX) + ent;
+    h = (c << HSHIFT) ^ ent;        /* xor hashing */
+    
+    /* while(h<0) h+=HSIZE; h %= HSIZE; */
+    
+    if (stringtab[h] == string) {
+      ent = codetab[h];
+      continue;
+    }
+
+    if (stringtab[h] >= 0) {
+      /*
+       * Primary hash failed, check secondary hash.
+       */
+      disp = HSIZE - h;
+      if (h == 0)
+	disp = 1;
+      do {
+	if ((h -= disp) < 0)
+	  h += HSIZE;
+	if (stringtab[h] == string) {
+	  ent = codetab[h];
+	  goto hit;
+	}
+      } while (stringtab[h] >= 0);
+    }
+
+    /*
+     * New entry, emit code and add to table.
+     */
+
+    outbuffer =
+      write_code(ent,nbits,
+		 &errflg, outbuffer, &outlen, &bitio_used, &bitio_buffer, &outcount,
+		 "lzw_pack_[write_code(ent)]");
+    
+    ent          = c;
+    codetab[h]   = first_free++;
+    stringtab[h] = string;
+    
+    if (first_free == CODE_MAX - 1) {
+      /* table is full, emit clear code and reset */
+      
+      /* ratio = 0; */
+      init_table(stringtab,HSIZE);
+      first_free = CODE_FIRST;
+      outbuffer =
+	write_code(CODE_CLEAR,nbits,
+		   &errflg, outbuffer, &outlen, &bitio_used, &bitio_buffer, &outcount,
+		   "lzw_pack_[write_code(CODE_CLEAR;'if (first_free == CODE_MAX - 1)')]");
+      nbits   = BITS_MIN;
+      maxcode =  MAXCODE(BITS_MIN);
+      
+    } else {
+      
+      /*
+       * If the next entry is going to be too big for
+       * the code size, then increase it, if possible.
+       */
+      
+      if (first_free > maxcode) {
+	nbits++;
+	if(nbits > BITS_MAX) Rabort("nbits > BITS_MAX",__FILE__,__LINE__);
+	maxcode =  MAXCODE(nbits);
+      }
+    }
+
+hit:
+    ;
+  }
+
+  outbuffer =
+    write_code(ent,nbits,
+	       &errflg, outbuffer, &outlen, &bitio_used, &bitio_buffer, &outcount,
+	       "lzw_pack_[write_code(ent) at end]");
+  outbuffer =
+    write_code(CODE_EOI,nbits,
+	       &errflg, outbuffer, &outlen, &bitio_used, &bitio_buffer, &outcount,
+	       "lzw_pack_[write_code(CODE_EOI)]");
+  flush_code();
+
+  *retcode = errflg ? -outcount : outcount;
+}
diff --git a/odb/src/aux/magicwords.c b/odb/src/aux/magicwords.c
new file mode 100644
index 0000000..1363020
--- /dev/null
+++ b/odb/src/aux/magicwords.c
@@ -0,0 +1,166 @@
+
+/* magicwords.c */
+
+#include "alloc.h"
+#include "magicwords.h"
+
+/* Access functions; also Fortran-callable */
+
+void get_magic_pcma_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? PCMA : AMCP;
+}
+
+void get_magic_odb__(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? ODB_ : _BDO;
+}
+
+void get_magic_odbi_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? ODBI : IBDO;
+}
+
+void get_magic_mr2d_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? MR2D : D2RM;
+}
+
+void get_magic_hc32_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? HC32 : _23CH;
+}
+
+void get_magic_algn_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? ALGN : NGLA;
+}
+
+void get_magic_mmry_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? MMRY : YRMM;
+}
+
+void get_magic_idxb_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? IDXB : BXDI;
+}
+
+void get_magic_idxt_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? IDXT : TXDI;
+}
+
+void get_magic_dca2_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? DCA2 : _2ACD;
+}
+
+void get_magic_ocac_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? OCAC : CACO;
+}
+
+void get_magic_odbx_(const int *reversed, unsigned int *value)
+{
+  *value = (!*reversed) ? ODBX : XBDO;
+}
+
+/* Compressed file auto-detection (see aux/cma_open.c & ioknowncmd.c) */
+
+#include <string.h>
+#include <stdlib.h>
+
+static const char *Compression_schemes[4] = {
+  "#ddgzip", /* w/o dd I/O-buffering : "#gzip" */
+  "#pack",
+  "#compress",
+  "#zip"
+};
+
+const char *
+Compression_Suffix_Check(const char *filename)
+{
+  const char *scheme_change = NULL;
+  const char *suffix = filename ? strrchr(filename, '.') : NULL;
+  if (suffix) {
+    if (strequ(suffix,".gz")) {
+      /* This looks like a gzipped file !! */
+      scheme_change = Compression_schemes[0];
+    }
+    else if (strequ(suffix,".z")) {
+      /* This looks like a pack'ed file !! */
+      scheme_change = Compression_schemes[1];
+    }
+    else if (strequ(suffix,".Z")) {
+      /* This looks like a compress'ed file !! */
+      scheme_change = Compression_schemes[2];
+    }
+    else if (strequ(suffix,".zip")) {
+      /* This looks like a pkzip'ed (zip) file !! */
+      scheme_change = Compression_schemes[3];
+    }
+  }
+  return scheme_change;
+}
+
+const char *
+Compression_Magic_Check(FILE *fp, unsigned int *first_word, int close_fp)
+{
+  const char *scheme_change = NULL;
+  if (fp && first_word) {
+    /* Borrowed from gzip-1.2.4 source code, file 'gzip.h' (there they were macro-keywords) */
+    static const char PACK_MAGIC[]     = "\037\036"; /* Magic header for packed files */
+    static const char GZIP_MAGIC[]     = "\037\213"; /* Magic header for gzip files, 1F 8B */
+    static const char OLD_GZIP_MAGIC[] = "\037\236"; /* Magic header for gzip 0.5 = freeze 1.x */
+    static const char LZH_MAGIC[]      = "\037\240"; /* Magic header for SCO LZH Compress files*/
+    static const char PKZIP_MAGIC[]    = "\120\113\003\004"; /* Magic header for pkzip files */
+
+    const unsigned char *magic = (const unsigned char *)first_word;
+    fread(first_word, sizeof(*first_word), 1, fp);
+  
+    if (memcmp(magic, GZIP_MAGIC, 2) == 0 || 
+	memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+      /* This looks like a gzipped file !! */
+      scheme_change = Compression_schemes[0];
+    }
+    else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
+      /* This looks like a pack'ed file !! */
+      scheme_change = Compression_schemes[1];
+    }
+    else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
+      /* This looks like a compress'ed file !! */
+      scheme_change = Compression_schemes[2];
+    }
+    else if (memcmp(magic, PKZIP_MAGIC, 4) == 0) {
+      /* This looks like a pkzip'ed (zip) file !! */
+      scheme_change = Compression_schemes[3];
+    }
+    if (close_fp) fclose(fp);
+  }
+  return scheme_change;
+}
+
+/* Maximum # of columns permitted */
+
+/* Note: Shared between ODB/SQL compiler and libodb.a
+   If you make sure you're consistent, use the same ODB_MAXCOLS to override */
+
+int ODB_maxcols()
+{
+  static int Maxcols = 99999; /* Reasonably big, ugh ? */
+  static int first_time = 1;
+  if (first_time) { /* Not thread safe, but used by ODB/SQL compiler, too */
+    char *env = getenv("ODB_MAXCOLS");
+    int value = Maxcols;
+    if (env) value = atoi(env);
+    if (value > 1000 && value < 1000000000) Maxcols = value;
+    first_time = 0;
+  }
+  return Maxcols;
+}
+
+void codb_maxcols_(int *maxcols)
+{
+  if (maxcols) *maxcols = ODB_maxcols();
+}
diff --git a/odb/src/aux/md5sub.c b/odb/src/aux/md5sub.c
new file mode 100644
index 0000000..f26d0fa
--- /dev/null
+++ b/odb/src/aux/md5sub.c
@@ -0,0 +1,504 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.	This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* Brutally hacked by John Walker back from ANSI C to K&R (no
+   prototypes) to maintain the tradition that Netfone will compile
+   with Sun's original "cc". */
+
+/* Back to ANSI-C by Sami Saarinen, ECMWF */
+
+#include <ctype.h>
+#include "odbmd5.h"
+
+PRIVATE void MD5Transform(uint32 buf[4], uint32 in[16]);
+
+#ifdef LITTLE
+int odbmd5_is_little = 1;
+#else
+int odbmd5_is_little = 0;
+#endif
+
+#define PRTFUNC if (!psign) fprintf
+
+PUBLIC int MD5_str2sign(const char *s, unsigned char sign[16])
+{
+  char *argv[2];
+  int rc = 0;
+  int arglen = 2 + STRLEN(s) + 1;
+  char *arg = NULL;
+  ALLOC(arg, arglen);
+  snprintf(arg, arglen, "-D%s", s);
+  argv[0] = "<undef>";
+  argv[1] = arg;
+  rc = MD5_signature(2, argv, sign);
+  FREE(arg);
+  return rc;
+}
+
+PUBLIC int MD5_signature(int argc, char *argv[], unsigned char sign[16])
+{
+  int i, j, opt, cdata = false, docheck = false, showfile = true, f = 0;
+  unsigned int bp;
+  char *cp, *clabel, *ifname, *hexfmt = "%02X";
+  FILE *in = stdin;
+  FILE *out = stdout;
+  unsigned char buffer[IO_BUFSIZE_DEFAULT];
+  unsigned char signature[16], csig[16];
+  struct MD5Context md5c;
+  unsigned char *psign = sign;
+
+  if (psign) {
+    memset(psign, 0, 16);
+  }
+
+  for (i = 1; i < argc; i++) {
+    cp = argv[i];
+    if (*cp == '-') {
+      if (STRLEN(cp) == 1) {
+	i++;
+	break;	    	      /* -  --  Mark end of options; balance are files */
+      }
+      opt = *(++cp);
+      if (islower(opt)) opt = toupper(opt);
+
+      switch (opt) {
+
+      case 'C':             /* -Csignature  --  Check signature, set return code */
+	docheck = true;
+	if (STRLEN(cp + 1) != 32) {
+	  docheck = false;
+	}
+	memset(csig, 0, 16);
+	clabel = cp + 1;
+	for (j = 0; j < 16; j++) {
+	  if (isxdigit((int) clabel[0]) && isxdigit((int) clabel[1]) &&
+	      sscanf((cp + 1 + (j * 2)), hexfmt, &bp) == 1) {
+	    csig[j] = (unsigned char) bp;
+	  } 
+	  else {
+	    docheck = false;
+	    break;
+	  }
+	  clabel += 2;
+	}
+	if (!docheck) {
+	  PRTFUNC(stderr, "Error in signature specification.  Must be 32 hex digits.\n");
+	  return 2;
+	}
+	break;
+
+      case 'D':             /* -Dtext  --  Compute signature of given text */
+	MD5Init(&md5c);
+	MD5Update(&md5c, (unsigned char *) (cp + 1), STRLEN(cp + 1));
+	cdata = true;
+	f++;	      /* Mark no infile argument needed */
+	break;
+		    
+      case 'L':   	      /* -L  --  Use lower case letters as hex digits */
+	hexfmt = "%02x";
+	break;
+
+      case 'N':   	      /* -N  --  Don't show file name after sum */
+	showfile = false;
+	break;
+		    
+      case 'O':   	      /* -Ofname  --  Write output to fname (- = stdout) */
+	cp++;
+	if (strcmp(cp, "-") != 0) {
+	  if (out != stdout) {
+	    PRTFUNC(stderr, "Redundant output file specification.\n");
+	    return 2;
+	  }
+	  if ((out = fopen(cp, "w")) == NULL) {
+	    PRTFUNC(stderr, "Cannot open output file %s\n", cp);
+	    return 2;
+	  }
+	}
+	break;
+
+      case '?':             /* -U, -? -H  --  Print how to call information. */
+      case 'H':
+      case 'U':
+	PRTFUNC(stdout,"\nMD5  --  Calculate MD5 signature of file.  Usage:");
+	PRTFUNC(stdout,"\n         odbmd5sum [ options ] [file ...]");
+	PRTFUNC(stdout,"\n");
+	PRTFUNC(stdout,"\n         options:");
+	PRTFUNC(stdout,"\n              -csig   Check against sig, set exit status 0 = OK");
+	PRTFUNC(stdout,"\n              -dtext  Compute signature of text argument");
+	PRTFUNC(stdout,"\n              -l      Use lower case letters for hexadecimal digits");
+	PRTFUNC(stdout,"\n              -n      Do not show file name after sum");
+	PRTFUNC(stdout,"\n              -ofname Write output to fname (- = stdout)");
+	PRTFUNC(stdout,"\n              -u      Print this message");
+	PRTFUNC(stdout,"\n              -v      Print version information");
+#if 0
+	PRTFUNC(stdout,"\n");
+	PRTFUNC(stdout,"\nby John Walker  --  http://www.fourmilab.ch/");
+	PRTFUNC(stdout,"\nVersion %s\n", codb_versions_(NULL,NULL,NULL,NULL));
+	PRTFUNC(stdout,"\nThis program is in the public domain.\n");
+	PRTFUNC(stdout,"\n");
+#endif
+	return sign ? 3 : 0;
+		    
+      case 'V':   	      /* -V  --  Print version number */
+	PRTFUNC(stdout,"%s\n", codb_versions_(NULL,NULL,NULL,NULL));
+	return sign ? 3 : 0;
+      }
+    } 
+    else {
+      break;
+    }
+  }
+    
+  if (cdata && (i < argc)) {
+    PRTFUNC(stderr, "Cannot specify both -d option and input file.\n");
+    return 2;
+  }
+    
+  if ((i >= argc) && (f == 0)) {
+    f++;
+  }
+    
+  for (; (f > 0) || (i < argc); i++) {
+    if ((!cdata) && (f > 0)) {
+      ifname = "-";
+    } 
+    else {
+      ifname = argv[i];
+    }
+    f = 0;
+
+    if (!cdata) {
+	
+      /* If the data weren't supplied on the command line with
+	 the "-d" option, read it now from the input file. */
+	
+      if (strcmp(ifname, "-") != 0) {
+	if ((in = fopen(ifname, "rb")) == NULL) {
+	  PRTFUNC(stderr, "Cannot open input file %s\n", ifname);
+	  return 2;
+	}
+      } 
+      else {
+	in = stdin;
+      }
+
+#ifdef _WIN32
+      /** Warning!  On systems which distinguish text mode and
+	  binary I/O (MS-DOS, Macintosh, etc.) the modes in the open
+	  statement for "in" should have forced the input file into
+	  binary mode.  But what if we're reading from standard
+	  input?  Well, then we need to do a system-specific tweak
+	  to make sure it's in binary mode.  While we're at it,
+	  let's set the mode to binary regardless of however fopen
+	  set it.
+
+	  The following code, conditional on _WIN32, sets binary
+	  mode using the method prescribed by Microsoft Visual C 7.0
+	  ("Monkey C"); this may require modification if you're
+	  using a different compiler or release of Monkey C.	If
+	  you're porting this code to a different system which
+	  distinguishes text and binary files, you'll need to add
+	  the equivalent call for that system. */
+
+      _setmode(_fileno(in), _O_BINARY);
+#endif
+    
+      MD5Init(&md5c);
+      while ((j = (int) fread(buffer, 1, sizeof(buffer), in)) > 0) {
+	MD5Update(&md5c, buffer, (unsigned) j);
+      }
+    }
+    MD5Final(signature, &md5c);
+
+    if (docheck) {
+      docheck = false;
+      for (j = 0; j < sizeof(signature); j++) {
+	if (signature[j] != csig[j]) {
+	  docheck = true;
+	  break;
+	}
+      }
+      if (i < (argc - 1)) {
+	PRTFUNC(stderr, "Only one file may be tested with the -c option.\n");
+	return 2;
+      }
+    } 
+    else if (psign) {
+      memcpy(psign, signature, 16);
+    }
+    else {
+      for (j = 0; j < sizeof(signature); j++) {
+	PRTFUNC(out, hexfmt, signature[j]);
+      }
+      if ((!cdata) && showfile) {
+	PRTFUNC(out, "  %s", (in == stdin) ? "-" : ifname);
+      }
+      PRTFUNC(out, "\n");
+    }
+  }
+
+  return docheck ? 1 : 0;
+}
+
+
+PUBLIC char *MD5_sign2hex(const unsigned char sign[16], int lowercase)
+{
+  char *str = NULL;
+  if (sign) {
+    int j;
+    char tmp[33];
+    char *hexfmt = (lowercase) ? "%02x" : "%02X";
+    char *ptmp = tmp;
+    for (j=0; j<16; j++) {
+      snprintf(ptmp, 3, hexfmt, sign[j]);
+      ptmp += 2;
+    }
+    *ptmp = '\0';
+    str = STRDUP(tmp);
+  }
+  return str;
+}
+
+
+PRIVATE void byteReverse(unsigned char *buf, unsigned int longs)
+{
+  /* Not called on little-endian machine */
+  uint32 t;
+  do {
+    t = (uint32) ((unsigned int) buf[3] << 8 | buf[2]) << 16 |
+      ((unsigned int) buf[1] << 8 | buf[0]);
+    *(uint32 *) buf = t;
+    buf += 4;
+  } while (--longs);
+}
+
+#define BYTEREV(buf, longs) if (!odbmd5_is_little) byteReverse(buf, longs)
+
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+
+PUBLIC void MD5Init(struct MD5Context *ctx)
+{
+  ctx->buf[0] = 0x67452301;
+  ctx->buf[1] = 0xefcdab89;
+  ctx->buf[2] = 0x98badcfe;
+  ctx->buf[3] = 0x10325476;
+  
+  ctx->bits[0] = 0;
+  ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+
+PUBLIC void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned int len)
+{
+  uint32 t;
+  
+  /* Update bitcount */
+  
+  t = ctx->bits[0];
+  if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+    ctx->bits[1]++; 	/* Carry from low to high */
+  ctx->bits[1] += len >> 29;
+  
+  t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+  
+  /* Handle any leading odd-sized chunks */
+  
+  if (t) {
+    unsigned char *p = (unsigned char *) ctx->in + t;
+    
+    t = 64 - t;
+    if (len < t) {
+      memcpy(p, buf, len);
+      return;
+    }
+    memcpy(p, buf, t);
+    BYTEREV(ctx->in, 16);
+    MD5Transform(ctx->buf, (uint32 *) ctx->in);
+    buf += t;
+    len -= t;
+  }
+
+  /* Process data in 64-byte chunks */
+
+  while (len >= 64) {
+    memcpy(ctx->in, buf, 64);
+    BYTEREV(ctx->in, 16);
+    MD5Transform(ctx->buf, (uint32 *) ctx->in);
+    buf += 64;
+    len -= 64;
+  }
+
+  /* Handle any remaining bytes of data. */
+  
+  memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+
+PUBLIC void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+  unsigned int count;
+  unsigned char *p;
+  
+  /* Compute number of bytes mod 64 */
+  count = (ctx->bits[0] >> 3) & 0x3F;
+  
+  /* Set the first char of padding to 0x80.  This is safe since there is
+     always at least one byte free */
+  p = ctx->in + count;
+  *p++ = 0x80;
+  
+  /* Bytes of padding needed to make 64 bytes */
+  count = 64 - 1 - count;
+  
+  /* Pad out to 56 mod 64 */
+  if (count < 8) {
+    /* Two lots of padding:  Pad the first block to 64 bytes */
+    memset(p, 0, count);
+    BYTEREV(ctx->in, 16);
+    MD5Transform(ctx->buf, (uint32 *) ctx->in);
+    
+    /* Now fill the next block with 56 bytes */
+    memset(ctx->in, 0, 56);
+  } else {
+    /* Pad block to 56 bytes */
+    memset(p, 0, count - 8);
+  }
+  BYTEREV(ctx->in, 14);
+
+  /* Append length in bits and transform */
+  ((uint32 *) ctx->in)[14] = ctx->bits[0];
+  ((uint32 *) ctx->in)[15] = ctx->bits[1];
+  
+  MD5Transform(ctx->buf, (uint32 *) ctx->in);
+  BYTEREV((unsigned char *) ctx->buf, 4);
+  memcpy(digest, ctx->buf, 16);
+  memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
+}
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+
+PRIVATE void MD5Transform(uint32 buf[4], uint32 in[16])
+{
+  register uint32 a, b, c, d;
+  
+  a = buf[0];
+  b = buf[1];
+  c = buf[2];
+  d = buf[3];
+
+  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+  
+  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+  
+  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+  
+  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
diff --git a/odb/src/aux/memmap.c b/odb/src/aux/memmap.c
new file mode 100644
index 0000000..13119a1
--- /dev/null
+++ b/odb/src/aux/memmap.c
@@ -0,0 +1,95 @@
+
+/* memmap.c */
+
+/* mmap()'ed I/O : Activate by compiling with -DHAS_MMAP (unless LINUX or RS6K) */
+
+#include "memmap.h"
+#include "alloc.h"
+
+memmap_t *
+memmap_open_read(int fd, const off_t *Offset, const size_t *Len)
+{
+  memmap_t *m = NULL;
+#ifdef HAS_MMAP
+  if (fd >= 0) { /* ok */
+    struct stat st;
+    int ok = fstat(fd, &st);
+    if (ok == 0 && (   S_ISREG(st.st_mode) /* Accept regular files */
+#if defined(S_ISLNK)
+		    || S_ISLNK(st.st_mode) /* Accept symbolic links (Not in POSIX.1-1996.) */
+#endif
+	)) { 
+      caddr_t buf;
+      off_t offset = (Offset && *Offset >= 0) ? *Offset : 0;
+      size_t len = st.st_size - offset;
+      if (Len && *Len >= 0) len = MIN(len, *Len);
+      buf = mmap(NULL, len, 
+		 PROT_READ, MAP_SHARED,
+		 fd, offset);
+      if (buf && buf != MAP_FAILED) { /* ok */
+	ALLOC(m, 1);
+	m->buf = buf;
+	m->len = len;
+	m->offset = offset;
+      }
+    } /* if (ok == 0) */
+  }
+#endif
+  return m;
+}
+
+int
+memmap_close(memmap_t *m)
+{
+  int rc = 0;
+#ifdef HAS_MMAP
+  if (m && m->buf) {
+    rc = munmap(m->buf, m->len);
+    FREE(m);
+  }
+#endif
+  return rc;
+}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAS_MMAP
+#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+#endif
+
+memmap_t *
+memmap_alloc(size_t Len, int Shared)
+{
+  memmap_t *m = NULL;
+#ifdef HAS_MMAP
+#if defined(MAP_ANON)
+  int fd = -1;
+  int flags = Shared ? (MAP_ANON | MAP_SHARED) : (MAP_ANON | MAP_PRIVATE);
+#else
+  int fd = open("/dev/zero", O_RDWR);
+  int flags = Shared ? MAP_SHARED : MAP_PRIVATE;
+#endif
+  off_t offset = 0;
+  size_t len = (Len > 0) ? Len : 0;
+  if (len > 0) {
+    caddr_t buf = mmap(NULL, len,
+		       PROT_READ | PROT_WRITE,
+		       flags,
+		       fd, offset);
+    if (buf && buf != MAP_FAILED) { /* ok */
+      ALLOC(m, 1);
+      m->buf = buf;
+      m->len = len;
+      m->offset = offset;
+    }
+  }
+#if !defined(MAP_ANON)
+  close(fd); /* Is this *really* ok ? */
+#endif
+#endif
+  return m;
+}
diff --git a/odb/src/aux/memory.c b/odb/src/aux/memory.c
new file mode 100644
index 0000000..9d3af99
--- /dev/null
+++ b/odb/src/aux/memory.c
@@ -0,0 +1,581 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "alloc.h"
+#include "magicwords.h"
+
+#define WORDLEN   ((int)sizeof(ll_t))
+
+#define SETSIZE(size_in_bytes) { \
+  if (size_in_bytes < WORDLEN) size_in_bytes = WORDLEN; \
+  size_in_bytes = size_in_bytes + cushion * WORDLEN; \
+  size_in_bytes = RNDUP(size_in_bytes,WORDLEN); \
+}
+
+#define NCTRL_BYTES ((3 + cushion) * WORDLEN)
+
+#define PAD  ((u_ll_t)0xdeadbeef)
+
+#define CUSH ((u_ll_t)0xf000c0de)
+
+#define CUSHION_DEFAULT 0
+
+#if !defined(STD_MEM_ALLOC)
+#define STD_MEM_ALLOC 1
+#endif
+
+PRIVATE int memory_set_up = 0;
+PRIVATE int cushion = CUSHION_DEFAULT;
+PRIVATE int std_mem_alloc = STD_MEM_ALLOC;
+PRIVATE int memory_trace = 0;
+PRIVATE int memory_trace_with_traceback = 0;
+PRIVATE int init_memory_area = 0;
+PRIVATE int freeptr_trace = 0;
+PRIVATE FILE *fp_freeptr_trace = NULL;
+
+PRIVATE const void *pmon = NULL;
+
+PUBLIC void 
+ODB_monitor_memory_addr(const void *p, const char *pwhat, 
+			const char *file, int linenum)
+{
+  if (!memory_trace) return;
+  if (!pmon) {
+    pmon = p;
+    fprintf(stderr,"--> ODB_monitor_memory_addr(p=%p, pwhat=%s) activated in %s:%d\n",
+	    p,pwhat,file,linenum);
+  }
+}
+
+PRIVATE void 
+memory_exit(const char *routine, int size_in_bytes, void *addr,
+	    const char *extra_msg, unsigned int do_abort,
+	    const char *var, const char *file, int linenum)
+{
+  fprintf(stderr,
+	  "memory_exit(bytes=%d,addr=%p,cushion=%d): Memory problem encountered in '%s'\n",
+	  size_in_bytes,addr,cushion,routine);
+  fprintf(stderr,"\tCalled for '%s', from file='%s', line=%d\n", var, file, linenum);
+  if (extra_msg) fprintf(stderr,"\t%s\n",extra_msg);
+  if (do_abort) {
+    char *c = getenv("ODB_MEMORY_TRACE_CMD");
+    if (c) {
+      char cmd[256];
+      if (strchr(c,'%')) 
+        sprintf(cmd,"%s %d",c,getpid());
+      else
+        sprintf(cmd,"%s",c);
+      fprintf(stderr,"\tRunning command '%s' ...",cmd);
+      (void)system(cmd);
+    }
+    fprintf(stderr,"\tAborting ...\n");
+    RAISE(SIGABRT);
+  }
+}
+
+
+PRIVATE void 
+set_up_memory(const char *var, const char *file, int linenum)
+{
+  if (!memory_set_up) {
+    char *s = getenv("ODB_MEMORY_ALLOC_STANDARD");
+    char *m = getenv("ODB_MEMORY_CUSHION");
+    char *t = getenv("ODB_MEMORY_TRACE");
+    char *tbk = getenv("ODB_MEMORY_TRACE_WITH_TRACEBACK");
+    char *x = getenv("ODB_MEMORY_INIT");
+    char *z = getenv("ODB_MEMORY_FREEPTR_TRACE");
+    memory_trace = t ? atoi(t) : 0;
+    memory_trace_with_traceback = tbk ? atoi(tbk) : 0;
+    cushion = m ? atoi(m) : CUSHION_DEFAULT;
+    if (cushion < 0) cushion = 0;
+    std_mem_alloc = s ? atoi(s) : STD_MEM_ALLOC;
+    if (std_mem_alloc <= 0) std_mem_alloc = 0;
+    init_memory_area = x ? atoi(x) : 0;
+    if (init_memory_area < 0) init_memory_area = 0;
+    freeptr_trace = z ? atoi(z) : 0;
+    if (t) {
+      fprintf(stderr,
+      "set_up_memory(): Memory overflow cushion set to %d (%d-byte) words. Allocation %s. Allocated memory %s. Freepointer trace %s.\n",
+	      cushion,WORDLEN,
+	      std_mem_alloc ? "standard" : "non-standard",
+	      init_memory_area ? "will be initialized" : "will not be initialized",
+	      freeptr_trace ? "active" : "not active");
+      
+    }
+    if (WORDLEN != 8) {
+      memory_exit("set_up_memory",0,NULL,
+		  "Implementation error: WORDLEN not equal to 8",1,
+		  var,file,linenum);
+    }
+    memory_set_up = 1;
+  }
+}
+
+/* Routines available with non-standard memory allocation method only */
+
+/* Set magic word to "MMRY" */
+
+#ifdef LITTLE
+#define MAGIC_WORD YRMM
+#else
+#define MAGIC_WORD MMRY
+#endif
+
+typedef struct {
+  u_ll_t magics;
+    ll_t lenbytes;
+  u_ll_t *user_area;
+  u_ll_t *cushion;
+  u_ll_t pad;
+} Mem_t;
+
+
+PRIVATE u_ll_t *
+current_alloc_start(u_ll_t *addr, int *len,
+		    const char *var, const char *file, int linenum)
+{
+  u_ll_t *p = addr ? addr - 2 : NULL;
+  unsigned int magics = p[0];
+  *len = (int)p[1];
+  if (magics != MAGIC_WORD) {
+    char msg[256];
+    sprintf(msg,
+	    "Error: %s Word#1 = '%u' not matching the magic = '%u'; p[0]=%llu, p[1]=%llu",
+	    "A memory corruption?", magics, MAGIC_WORD, p[0], p[1]);
+    memory_exit("current_alloc_start", *len, addr, 
+		msg, 1,
+		var,file,linenum);
+  }
+  return p;
+}
+
+
+PRIVATE void
+free_mem(void *addr,
+	 const char *var, const char *file, int linenum,
+	 int do_free)
+{
+  u_ll_t *p;
+  int size_in_bytes;
+  u_ll_t pad;
+  char msg[256];
+  unsigned int do_abort = 0;
+
+  /* Check that the initial padding is reasonable (not necessarely okay) */
+  
+  p = current_alloc_start(addr, &size_in_bytes,var,file,linenum);
+
+  if (do_free && memory_trace > 0) {
+    fprintf(stderr,"free_mem(%d): Size=%d, True address of '%s' at %p at %s:%d\n",
+	    do_free,size_in_bytes,var,p,file,linenum);
+  }
+
+  if (size_in_bytes <= 0) {
+    sprintf(msg,
+	    "Error: Attempted to free corrupted memory: size_in_bytes=%d", size_in_bytes);
+    memory_exit("free_mem", size_in_bytes, addr, 
+		msg, do_free, /* No abort unless *really* free'ing call */
+		var,file,linenum);
+    do_abort++;
+  }
+
+  /* Check the cushion area */
+
+  if (cushion > 0) {
+    int j, count = 0;
+    for (j=0; j<cushion; j++) {
+      u_ll_t cush = p[2 + size_in_bytes/WORDLEN + j];
+      if (cush != CUSH) count++;
+    }
+    if (count > 0) {
+      sprintf(msg,
+      "Error: Overwrote into the cushion area? Start of expected pattern=0x%llx, but found=0x%llx",
+	      CUSH, p[2 + size_in_bytes/WORDLEN]);
+      memory_exit("free_mem", size_in_bytes, addr, 
+		  msg, 0, /* No abort ... yet */
+		  var,file,linenum);
+      do_abort++;
+    }
+  }
+
+  /* Check end padding */
+  /* Assume that the "size_in_bytes" is still correct */
+
+  pad = p[2 + size_in_bytes/WORDLEN + cushion];
+
+  if (pad != PAD) {
+    sprintf(msg,
+	    "Error: Memory overwrite problem: pad=0x%llx (expected 0x%llx)",
+	    pad, PAD);
+    memory_exit("free_mem", size_in_bytes, addr, 
+		msg, 0, /* No abort ... yet */
+		var,file,linenum);
+    do_abort++;
+  }
+
+  if (do_abort) RAISE(SIGABRT);
+
+  if (do_free) {
+    if (pmon && pmon == addr) {
+      pmon = NULL;
+      fprintf(stderr,"--> ODB_monitor_memory_addr(addr=%p) disabled\n",addr);
+    }
+    free(p);
+  }
+}
+
+PUBLIC void 
+ODB_check_memory_overwrite(const char *file, int linenum)
+{
+  if (pmon && memory_trace > 0) {
+    free_mem((void *)pmon,
+	     "<ODB_monitor_memory_address>",
+	     file, linenum, 0);
+  }
+}
+
+
+/* Memory allocation wrapper routines */
+
+
+int
+ODB_std_mem_alloc(int onoff)
+{
+  /* Use this only if you knwo what you are doing;
+     Meant for imposing the permanent standard or 
+     adjusted memory allocation method;
+     Once set at the beginning, do not re-adjust !! */
+  
+  int rc; /* previous value */
+  if (!memory_set_up) set_up_memory("ODB_std_mem_alloc()", __FILE__, __LINE__);
+  rc = std_mem_alloc;
+  std_mem_alloc = (onoff > 0) ? 1 : 0;
+  if (memory_trace > 0) 
+    fprintf(stderr,"***Warning: Allocation method is now %s\n",
+	    std_mem_alloc ? "standard" : "adjusted");
+  return rc;
+}
+
+
+void *
+ODB_reserve_mem(int size_elem, int num_elem,
+		const char *var, const char *file, int linenum) 
+{ 
+  double *dp;
+  u_ll_t *p;
+  size_t total_len;
+  size_t size_in_bytes = (size_t)size_elem * (size_t)num_elem;
+
+  if (!memory_set_up) set_up_memory(var,file,linenum);
+
+  SETSIZE(size_in_bytes);
+
+  if (std_mem_alloc) {
+    total_len = size_in_bytes;
+
+    if (memory_trace > 0 && total_len >= memory_trace) {
+      fprintf(stderr,
+	      "ODB_reserve_mem[std]: malloc(%d >= %d x %d) for '%s' at %s:%d\n",
+	      total_len, size_elem, num_elem, var, file, linenum);
+#ifdef RS6K
+      if (memory_trace_with_traceback) { xl__trbk_(); }
+#endif
+    }
+    
+    dp = (double *)malloc(total_len);
+    p = (u_ll_t *)dp;
+    if (memory_trace > 0 && total_len >= memory_trace) {
+      fprintf(stderr,"ODB_reserve_mem(std): Size=%d, True address of '%s' at %p at %s:%d\n",
+	      size_in_bytes, var, p, file, linenum);
+    }
+    if (!p) memory_exit("ODB_reserve_mem[std]",size_in_bytes,p,
+			NULL,1,
+			var,file,linenum);
+    if (init_memory_area && p) codb_zerofill_(p,&total_len);
+    return p;
+  }
+  else {
+    total_len = RNDUP(size_in_bytes + NCTRL_BYTES, WORDLEN);
+    
+    if (memory_trace > 0 && total_len >= memory_trace) {
+      fprintf(stderr,
+	      "ODB_reserve_mem[non-std]: malloc(%d >= %d x %d) for '%s' at %s:%d\n",
+	      total_len, size_elem, num_elem, var, file, linenum);
+#ifdef RS6K
+      if (memory_trace_with_traceback) {  xl__trbk_(); }
+#endif
+    }
+    
+    dp = (double *)malloc(total_len);
+    p = (u_ll_t *)dp;
+    if (memory_trace > 0 && total_len >= memory_trace) {
+      fprintf(stderr,"ODB_reserve_mem(non-std): Size=%d, True address of '%s' at %p at %s:%d\n",
+	      size_in_bytes, var, p, file, linenum);
+    }
+    if (!p) memory_exit("ODB_reserve_mem[non-std]",total_len,p,
+			NULL,1,
+			var,file,linenum);
+    if (init_memory_area && p) codb_zerofill_(p,&total_len);
+    p[0] = MAGIC_WORD;
+    p[1] = size_in_bytes;
+    /* User area is from p[2] to p[size_in_bytes/WORDLEN - 1] */
+
+    /* Possible cushion initialization */
+    if (cushion > 0) {
+      int j;
+      for (j=0; j<cushion; j++) {
+	p[2 + size_in_bytes/WORDLEN + j] = CUSH;
+      }
+    }
+
+    /* End padding */
+    p[2 + size_in_bytes/WORDLEN + cushion] = PAD;
+
+    ODB_check_memory_overwrite(file,linenum);
+
+    return p + 2;
+  }
+}
+
+
+void *
+ODB_reserve_zeromem(int size_elem, int num_elem,
+		    const char *var, const char *file, int linenum) 
+{ 
+  size_t  size_in_bytes = (size_t)size_elem * (size_t)num_elem;
+  void *p = ODB_reserve_mem(size_elem,num_elem,var,file,linenum);
+  if (p && size_in_bytes > 0) codb_zerofill_(p,&size_in_bytes);
+  return p;
+}
+
+#if defined(RS6K) && defined(__64BIT__)
+PRIVATE int
+check_freeptr(const void *p,
+	      const char *var, const char *file, int linenum)
+{
+  FILE *fp = fp_freeptr_trace;
+  int okay = 1;
+  const u_ll_t bss_lo = (u_ll_t)0x000000100000000;
+  const u_ll_t bss_hi = (u_ll_t)0x6FFFFFFF0000000;
+  u_ll_t address = (u_ll_t)p;
+  if (address < bss_lo || address > bss_hi) {
+    if (fp) {
+      fprintf(fp,
+	      " check_freeptr(): Address 0x%llx not allocated from heap (var=%s, file=%s:%d)\n",
+	      address, var, file, linenum);
+      fflush(fp);
+    }
+    okay = 0; /* Out of valid range */
+  }
+  else { /* Just print it */
+    if (fp) {
+      fprintf(fp," check_freeptr(): Valid heap address 0x%llx (var=%s, file=%s:%d)\n",
+	      address, var, file, linenum);
+      fflush(fp);
+    }
+  }
+  return okay;
+}
+#endif
+
+void 
+ODB_release_mem(void *p,
+		const char *var, const char *file, int linenum) 
+{ 
+  if (!memory_set_up) set_up_memory(var,file,linenum);
+  if (std_mem_alloc) {
+    int okay = 1;
+#if defined(RS6K) && defined(__64BIT__)
+    if (freeptr_trace) {
+      okay = check_freeptr(p, var, file, linenum);
+    }
+#endif
+    /* if (okay && p) free(p); -- not quite yet */
+    if (p) free(p); 
+  }
+  else {
+    if (p) {
+      if (pmon && p != pmon) ODB_check_memory_overwrite(file,linenum);
+      free_mem(p,var,file,linenum,1); 
+    }
+  }
+}
+
+
+void *
+ODB_re_alloc(void *p, int size_elem, int num_elem,
+	     const char *var, const char *file, int linenum)
+{
+  int size_in_bytes = size_elem * num_elem;
+  if (!memory_set_up) set_up_memory(var,file,linenum);
+  if (!p) 
+    p = ODB_reserve_mem(size_elem,num_elem,var,file,linenum); /* Revert to reserve_mem */
+  else {
+    SETSIZE(size_in_bytes);
+    if (std_mem_alloc) {
+      double *dp = (double *)realloc(p, size_in_bytes);
+      p = dp;
+      if (!p) memory_exit("ODB_re_alloc",size_in_bytes,p,
+			  NULL,1,
+			  var,file,linenum);
+    }
+    else {
+      int size_old;
+      (void) current_alloc_start(p, &size_old,var,file,linenum);
+      if (size_old < size_in_bytes) {
+	void *d = ODB_reserve_mem(size_elem,num_elem,var,file,linenum);
+	if (d) memcpy(d,p,size_old);
+	ODB_release_mem(p,var,file,linenum);
+	p = d;
+      }
+    }
+  }
+  return p;
+}
+
+
+char *
+ODB_strdup_mem(const char *s,
+	       const char *var, const char *file, int linenum)
+{
+  char *p = NULL;
+  if (!memory_set_up) set_up_memory(var,file,linenum);
+  if (std_mem_alloc) {
+    p = strdup(s ? s : "");
+  }
+  else {
+    int size_in_bytes = s ? strlen(s) : 0;
+    if (memory_trace > 0 && size_in_bytes >= memory_trace && s) {
+      fprintf(stderr,"ODB_strdup_mem(%s) : len=%d\n",
+	      s, size_in_bytes);
+#ifdef RS6K
+      if (memory_trace_with_traceback) { xl__trbk_(); }
+#endif
+    }
+    p = ODB_reserve_mem(sizeof(*p),size_in_bytes+1,var,file,linenum);
+    if (p && s) memcpy(p,s,size_in_bytes); 
+    if (p) p[size_in_bytes] = '\0';
+  }
+  return p;
+}
+
+
+int
+ODB_freeptr_trace(FILE *fp,
+		  const char *routine,
+		  const char *file,
+		  int linenum,
+		  int onoff)
+{
+  int rc = 0;
+  if (fp && freeptr_trace) {
+    fprintf(fp, "*** %s ODB_freeptr_trace() in routine=%s(), file=%s:%d\n",
+	    onoff ? "Enabling" : "Disabling",
+	    routine, file, linenum);
+    fflush(fp);
+    fp_freeptr_trace = onoff ? fp : NULL;
+    if (fp_freeptr_trace) rc = 1;
+  }
+  return rc;
+}
+
+/* Fast(er) memory initialization routines for vector machines */
+
+/* The "scalar" version should be ok for NEC SX, since its C-compiler 
+   can replace memset & memcpy with vectorized versions easily */
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+
+PRIVATE const int min_veclen = 5;  /* minimum vector length, where faster method is applied to */
+PRIVATE const long long align = 8; /* address alignment in double-word boundary */
+#endif
+
+void
+codb_strblank_(char *c,
+	       /* Hidden arguments */
+	       int len_c)
+{
+  /* Initializes F90 character string into blanks in a vector loop */
+#ifdef VPP
+  int *d;
+  if (len_c >= min_veclen*sizeof(*d)) {
+    long long int addr;
+    int j, n, rem;
+    void *v;
+
+    do {
+      addr = (long long)c;
+      if (addr%align == 0) break;
+      *c++ = ' ';
+      len_c--;
+    } while (len_c > 0);
+
+    n = len_c/sizeof(*d);
+    v = c; d = v; /* ... in order to remove complaints ;-) */
+    for (j=0; j<n; j++) d[j] = 0x20202020; /* Fill in 4 spaces in one go, hex=20 into each */
+    rem = len_c%sizeof(*d);
+    if (rem > 0) memset(&c[n*sizeof(*d)],' ',rem);
+  }
+  else {
+    memset(c,' ',len_c);
+  }
+#else
+  memset(c,' ',len_c);
+#endif
+}
+
+
+void
+codb_zerofill_(void *x, const size_t *nbytes)
+{
+  /* Initializes array of *nbytes to zero */
+  size_t len_c = *nbytes;
+  char *c = x;
+#ifdef VPP
+  int *d;
+  if (len_c >= min_veclen*sizeof(*d)) {
+    long long int addr;
+    int j, rem;
+    size_t n;
+    void *v;
+
+    do {
+      addr = (long long)c;
+      if (addr%align == 0) break;
+      *c++ = 0;
+      len_c--;
+    } while (len_c > 0);
+
+    n = len_c/sizeof(*d);
+    v = c; d = v; /* ... in order to remove complaints from compiler ;-) */
+    for (j=0; j<n; j++) d[j] = 0; /* zerofill */
+    rem = len_c%sizeof(*d);
+    if (rem > 0) memset(&c[n*sizeof(*d)],0,rem);
+  }
+  else {
+    memset(c,0,len_c);
+  }
+#else
+  memset(c,0,len_c);
+#endif
+}
+
+
+void
+codb_str2dbl_(const char str[], const int *nstr, 
+	      double dbl[], const int *ndbl)
+{
+  if (str && nstr && *nstr > 0 &&
+      dbl && ndbl && *ndbl > 0) {
+    int nbytes = (*ndbl) * sizeof(*dbl);
+    if (*nstr < nbytes) nbytes = *nstr;
+    memcpy(dbl,str,nbytes);
+  }
+}
diff --git a/odb/src/aux/newio.c b/odb/src/aux/newio.c
new file mode 100644
index 0000000..8f1df15
--- /dev/null
+++ b/odb/src/aux/newio.c
@@ -0,0 +1,1955 @@
+
+/* New I/O library for ODB (coding started : 15-Oct-2002) */
+
+#include "newio.h"
+#include "swapbytes.h"
+#include "dca.h"
+#include "cdrhook.h"
+
+extern char *IOtruename(const char *name, const int *len_str);
+#ifdef RS6K
+extern void xl__trbk_();
+#else
+#define xl__trbk_() 
+#endif
+
+#define PERMS 0644 /* R/W for owner, R for group & others */
+
+#define WORDLEN sizeof(ll_t)
+#define DIMLEN  (3*WORDLEN)
+
+PRIVATE int first_time = 1;
+PRIVATE int io_write_empty_files = 0;
+PRIVATE int io_profile = 0;
+PRIVATE int io_lock = 0;
+
+/* 
+   io_method:
+   1 = use cma_readb/cma_writeb as usual (the default)
+   2 = use read/write directly  -- 1) lacks I/O-buffering 2) not tested really well
+   3 = use QTAR-facility (via pipe i.e. popen()/pclose()) -- 1) slow 2) not tested well
+   4 = assume data has been written into memory (horizontal concatenation) -- is working
+   5 = Access to individual columns via DCA-files
+
+   For method#4, you may need to understand the coding in ../lib/msgpass_loaddata.F90 and ../lib/msgpass_storedata.F90, too.
+ */
+
+PRIVATE int io_method = 1;
+
+PRIVATE int io_bufsize = IO_BUFSIZE_DEFAULT;
+PRIVATE int io_verbose = 0;
+PRIVATE int io_keep_incore = 1;
+#if !defined(IO_FILESIZE_DEFAULT)
+#define IO_FILESIZE_DEFAULT 32
+#endif
+PRIVATE int io_filesize = IO_FILESIZE_DEFAULT; /* in megabytes */
+PRIVATE int io_grpsize = -1;
+PRIVATE char *consider_tables = NULL;
+PRIVATE int newio_myproc = 0;
+PRIVATE int newio_nproc = 1;
+
+PRIVATE int db_io_size = 0; /* How many handles allowed */
+PRIVATE IO_db_t *db_io = NULL;
+
+PRIVATE const int badnum = 2147483647;
+
+#define DB_IO_DEF(handle, poolno) \
+  IO_db_t *pdb = ((handle) >= 1) ? &db_io[(handle)-1] : NULL; \
+  int jpool = (pdb && (poolno) >= 1) ? pdb->poolaccess[(poolno)] : badnum; \
+  IO_pool_t *ppool = (pdb && jpool != badnum) ? &pdb->pool[jpool] : NULL
+
+#define Free_INCORE(ptbl, keep_incore) \
+{ if (ptbl) { \
+    if (!keep_incore) { \
+      FREE(ptbl->incore); \
+      ptbl->n_incore = -1; ptbl->n_alloc = 0; \
+      ptbl->incore_ptr = 0; ptbl->in_use = 0; \
+    } \
+    ptbl->updated = 0; \
+  } \
+}
+
+#define Alloc_INCORE(ptbl, nbytes, roundup) \
+{ if (ptbl) { \
+    Free_INCORE(ptbl, 0); \
+    ptbl->n_incore = nbytes; \
+    ptbl->n_alloc = RNDUP(DIMLEN + ptbl->n_incore, roundup); \
+    ALLOC(ptbl->incore, ptbl->n_alloc); \
+    ptbl->incore_ptr = DIMLEN; \
+    ptbl->in_use = 1; \
+  } \
+}
+
+#define	Take_INCORE(ptbl) \
+  (ptbl && (ptbl->tblname && ptbl->in_use && ptbl->updated &&  \
+ ((ptbl->tblname && ptbl->incore && ptbl->n_incore > 0) || \
+  (ptbl->tblname && ptbl->n_incore == 0 && io_write_empty_files))))
+
+#define NEWIO_OPEN_UNDEF  0
+#define NEWIO_OPEN_READ   1
+#define NEWIO_OPEN_WRITE  2
+#define NEWIO_OPEN_DELETE 4
+
+static o_lock_t NEWIO_mylock = 0; /* A specific OMP-lock; initialized only once in
+				     odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+PRIVATE char *version_env = NULL; 
+PRIVATE char *version_sw = NULL; 
+
+PRIVATE void
+init_IOs()
+{
+  DRHOOK_START(init_IOs);
+  if (first_time) { /* 1st */
+    coml_set_lockid_(&NEWIO_mylock);
+    if (first_time) { /* 2nd */
+      char *env = NULL;
+      /* Get ODB_VERSION is effect */
+      env = getenv("ODB_VERSION");
+      if (env) version_env = STRDUP(env);
+      {
+	/* Get ODB_VERSION from function call codb_versions_() */
+	const char *vers_ptr = codb_versions_(NULL,NULL,NULL,NULL);
+	version_sw = STRDUP(vers_ptr);
+      }
+      /* Get myproc */
+      codb_procdata_(&newio_myproc, &newio_nproc, NULL, NULL, NULL);
+      /* I/O locking to be used ? */
+      env = getenv("ODB_IO_LOCK");
+      if (env) io_lock = atoi(env);
+      /* Perform I/O profiling of newio's */
+      env = getenv("ODB_IO_PROFILE");
+      if (env) io_profile = atoi(env);
+      /* Change I/O method */
+      env = getenv("ODB_IO_METHOD");
+      if (env) io_method = atoi(env);
+      if (io_method < 1 || io_method > 5) io_method = 1;
+      /* Write "empty" file i.e. table files w/o any rows */
+      env = getenv("ODB_WRITE_EMPTY_FILES");
+      if (env) io_write_empty_files = atoi(env);
+      /* I/O buffer size */
+      env = getenv("ODB_IO_BUFSIZE");
+      if (env) io_bufsize = atoi(env);
+      if (io_bufsize <= 0) io_bufsize = IO_BUFSIZE_DEFAULT;
+      /* Little more verbose on ODB_IO_VERBOSE processor ? */
+      env = getenv("ODB_IO_VERBOSE");
+      if (env) io_verbose = atoi(env);
+      if (io_verbose < 0) io_verbose = -1;
+      if (io_verbose == -1) io_verbose = newio_myproc;
+      if (io_verbose == newio_myproc) {
+	/* Turn on CMA I/O dbg, too */
+	const int toggle = 1;
+	int old_value;
+	cma_debug_(&toggle, &old_value);
+      }
+      /* Keep I/O data incore as long as possible (up to end_IO_struct) */
+      env = getenv("ODB_IO_KEEP_INCORE");
+      if (env) io_keep_incore = atoi(env);
+      /*== NOTE == Make sure ODB_IO_FILESIZE & ODB_IO_GRPSIZE consistent with
+	../lib/msgpass_loaddata.F90 and ../lib/msgpass_storedata.F90*/
+      /* Display preferred filesize (used in horizontal concatenation scheme) */
+      env = getenv("ODB_IO_FILESIZE");
+      if (env) io_filesize = atoi(env);
+      if (io_filesize <= 0) io_filesize = IO_FILESIZE_DEFAULT; /* in megabytes */
+      /* Display maximum I/O group size i.e. how many pools' data will be concatenated into one file */
+      env = getenv("ODB_IO_GRPSIZE");
+      if (!env) env = getenv("NPES_AN");
+      if (env) io_grpsize = atoi(env);
+      if (io_grpsize <= 0) io_grpsize = newio_nproc;
+      /* Consider loading of these tables only, by default ; (used in horizontal concat) */
+      env = getenv("ODB_CONSIDER_TABLES");
+      if (env) consider_tables = STRDUP(env);
+      else     consider_tables = STRDUP("*"); /* i.e. all */
+      
+      if (io_profile) Profile_newio32_init(newio_myproc); 
+
+      if (newio_myproc == 1) {
+	fprintf(stderr,"*** %s:init_IOs() ***\n",__FILE__);
+	fprintf(stderr,"\tODB_WRITE_EMPTY_FILES=%d\n",io_write_empty_files);
+	fprintf(stderr,"\t  ODB_CONSIDER_TABLES=%s\n",consider_tables);
+	fprintf(stderr,"\t   ODB_IO_KEEP_INCORE=%d\n",io_keep_incore);
+	fprintf(stderr,"\t      ODB_IO_FILESIZE=%d MB\n",io_filesize);
+	fprintf(stderr,"\t       ODB_IO_BUFSIZE=%d bytes\n",io_bufsize);
+	fprintf(stderr,"\t       ODB_IO_GRPSIZE=%d (or max no. of pools)\n",io_grpsize);
+	fprintf(stderr,"\t       ODB_IO_PROFILE=%d\n",io_profile);
+	fprintf(stderr,"\t       ODB_IO_VERBOSE=%d\n",io_verbose);
+	fprintf(stderr,"\t        ODB_IO_METHOD=%d\n",io_method);
+	if (version_env) {
+	  fprintf(stderr,"\t          ODB_VERSION=%s (environment variable)\n",version_env);
+	}
+	if (version_sw) {
+	  fprintf(stderr,"\t          ODB_VERSION=%s (software release)\n",version_sw);
+	}
+	fprintf(stderr,"\t          ODB_IO_LOCK=%d\n",io_lock);
+	fprintf(stderr,"*********************\n");
+      }
+      first_time = 0;
+    } /* if (first_time) 2nd */
+    coml_unset_lockid_(&NEWIO_mylock);
+  } /* if (first_time) 1st */
+  DRHOOK_END(0);
+}
+
+PUBLIC void init_NEWIO_lock()
+{
+  INIT_LOCKID_WITH_NAME(&NEWIO_mylock,"newio.c:NEWIO_mylock");
+  init_IOs();
+}
+
+PRIVATE void
+lock_IO(int onoff)
+{
+  if (io_lock) {
+    if (io_profile) {
+      if (onoff) Profile_newio32_start(ioprof_iolock, 0);
+    }
+    ODB_iolock(onoff);
+    if (io_profile) {
+      if (!onoff) Profile_newio32_end(ioprof_iolock, 0);
+    }
+  }
+}
+
+PRIVATE void
+TableDump(FILE *fp, const IO_pool_t *ppool, const IO_tbl_t *ptbl_specific)
+{
+  if (fp) {
+    int poolno = ppool->poolno;
+    int ntables = ppool->ntables;
+    int maxtables = ppool->maxtables;
+    int jtbl;
+    fprintf(fp,
+	    "***Pool#%d, active table count %d of %d; file=%s, exist=%d,\n\tlast_write_cmd=%s\n",
+	    poolno, ntables, maxtables, 
+	    ppool->file ? ppool->file : NIL,
+	    ppool->file_exist,
+	    ppool->last_write_cmd ? ppool->last_write_cmd : NIL);
+    for (jtbl=0; jtbl<ntables; jtbl++) {
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      if (ptbl_specific && ptbl != ptbl_specific) continue;
+      if (ptbl->tblname) {
+	fprintf(fp,
+"[%d]: '%s', ksiz=%d, upd=%d, mode=%d, f=%s, incore=%p, n=%d, alloc=%d, ptr=%d, used=%d,\n\tread=%s,\n\tdel=%s\n",
+		jtbl, ptbl->tblname, ptbl->known_size, ptbl->updated, ptbl->open_mode, 
+		ptbl->file ? ptbl->file : NIL, 
+		ptbl->incore, ptbl->n_incore, ptbl->n_alloc, ptbl->incore_ptr, ptbl->in_use,
+		ptbl->read_cmd ? ptbl->read_cmd : NIL,
+		ptbl->delete_cmd ? ptbl->delete_cmd : NIL
+		);
+      }
+    } /* for (jtbl=0; jtbl<ntables; jtbl++) */
+  } /* if (fp) */
+}
+
+PRIVATE int
+LocateTable(const char *table, IO_pool_t *ppool, int create_new_entry)
+{
+  int found = 0;
+  int rc = -1;
+  int maxtables = ppool->maxtables;
+  int ntables = ppool->ntables;
+  int jtbl;
+  DRHOOK_START(LocateTable);
+
+/*printf("LocateTable \n");*/
+  coml_set_lockid_(&NEWIO_mylock);
+  for (jtbl=0; jtbl<ntables; jtbl++) {
+    IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+/*    printf("LocateTable %s \n" , table); */
+    if (ptbl->tblname && strequ(ptbl->tblname,table)) {
+      rc = jtbl;
+      found = 1;
+      break;
+    }
+  } /* for (jtbl=0; jtbl<ntables; jtbl++) */
+
+  if (!found && create_new_entry) {
+    for (jtbl=0; jtbl<maxtables; jtbl++) {
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      if (!ptbl->tblname) {
+	IO_db_t *pdb = ppool->mydb;
+	ptbl->tblname = STRDUP(table);
+	if (pdb->is_new) ptbl->known_size = 0;
+	ppool->ntables++;
+	rc = jtbl;
+	found = 1;
+	break;
+      }
+    } /* for (jtbl=0; jtbl<maxtables; jtbl++) */
+  } /* if (!found) */
+  coml_unset_lockid_(&NEWIO_mylock);
+
+  DRHOOK_END(0);
+  /* if (!found) --> error [when create_new_entry]; should be impossible, though */
+  return rc;
+}
+
+PRIVATE int
+FileExist(const char *filename)
+{
+  int exist = 0;
+  struct stat buf;
+  if (stat(filename,&buf) == 0) {
+    /* Caveat: We do not check if this file is a directory or some
+       other special file. Perhaps we should */
+    exist = 1;
+  }
+  return exist;
+}
+
+PRIVATE char *
+GetQTARFILE(int handle, int poolno, IO_pool_t *ppool, int *exist)
+{
+  char *qtarfile = ppool->file;
+  if (!qtarfile) {
+    IO_db_t *pdb = ppool->mydb;
+    char *file = NULL;
+    int len;
+    MakeFileName(file, pdb->dbname, "QTARFILE", poolno);
+    len = strlen(file);
+    ppool->file = qtarfile = IOtruename(file, &len);
+    FREEX(file);
+    ppool->file_exist = pdb->is_new ? 0 : FileExist(qtarfile);
+  }
+  if (exist) *exist = ppool->file_exist;
+  /* if (exist) *exist = FileExist(qtarfile); */
+  return qtarfile;
+}
+
+
+/* Version for 32-bit (4 byte) integer lengths i.e. one slurp "limited" to 2GB */
+
+
+PRIVATE void 
+newio_Error32(const char *what, 
+	      const char *filename,
+	      const char *desc,
+	      const char *entry,
+	      int handle,
+	      int poolno,
+	      int bytes, 
+	      int rc,
+	      int io_method_used,
+	      const char *format,
+	      ...) 
+{
+  DRHOOK_START(newio_Error32);
+  if (io_profile) Profile_newio32_flush();
+  if (io_method_used == 1 || 
+      io_method_used == 2) perror(filename);
+  fprintf(stderr,
+  "***Error: Unable to %s file=%s, desc=%s, entry=%s, handle=%d, poolno=%d: %d bytes, I/O-method=%d : rc=%d\n",
+  what, filename, desc, entry, handle, poolno, bytes, io_method_used, rc); 
+  if (format) {
+    int len = strlen(format);
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    if (format[len-1] != '\n') fprintf(stderr,"\n");
+    va_end(args);
+  }
+  if (handle > 0 && poolno > 0) {
+    DB_IO_DEF(handle, poolno);
+    TableDump(stderr, ppool, NULL);
+  }
+  RAISE(SIGABRT);
+  DRHOOK_END(0);
+}
+
+
+PUBLIC int
+newio_Size32(const char *filename,
+	     const char *dbname,
+	     const char *table,
+	     int handle,
+	     int poolno)
+{
+  DB_IO_DEF(handle, poolno);
+  int size = 0;
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_Size32);
+
+  if (this_io_method == 0) size = -2;
+
+  if (size == 0) {
+    if (this_io_method == 3 ||
+	this_io_method == 4) { /* QTAR or horizontal concat */
+      int jtbl = LocateTable(table, ppool, 0);
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	size = ptbl->known_size;
+      } /* if (jtbl >= 0) */
+    }
+    else {
+      codb_filesize_(filename, &size, strlen(filename));
+    }
+  }
+
+  DRHOOK_END(0);
+  return size;
+}
+
+
+PRIVATE int
+ReadData32(int fd, void *data, int bytes)
+{
+  int len, n;
+  char *c = data;
+  int rem = bytes;
+  int rc = 0;
+  DRHOOK_START(ReadData32);
+  for (;;) {
+    len = MIN(io_bufsize, rem);
+    if (len <= 0) break;
+    n = read(fd, c, len);
+    if (n > 0) {
+      c += n;
+      rem -= n;
+      rc += n;
+    }
+    else /* Error (the stmt "rc != bytes" below will catch it) */
+      break;
+  }
+  DRHOOK_END(rc);
+  return rc;
+} 
+
+
+PUBLIC int
+newio_GetByteswap(int *fp_idx, int handle, int poolno)
+{
+  DB_IO_DEF(handle, poolno);
+  int swp = pdb ? pdb->req_byteswap : 0;
+  return swp;
+}
+
+PUBLIC int
+newio_SetByteswap(int *fp_idx, int toggle, int handle, int poolno)
+{
+  DB_IO_DEF(handle, poolno);
+  int oldswp = pdb ? pdb->req_byteswap : 0;
+  if (pdb) {
+    int this_io_method = pdb->io_method;
+    if (this_io_method == 1) {
+      int oldvalue;
+      cma_set_byteswap_(fp_idx, &toggle, &oldvalue);
+    }
+    pdb->req_byteswap = toggle;
+  }
+  return oldswp;
+}
+
+PUBLIC int
+newio_Read32(int *fp_idx, 
+	     const char *filename, 
+	     const char *desc, 
+	     const char *entry,
+	     int handle,
+	     int poolno,
+	     void *data, 
+	     int sizeof_data, 
+	     int n)
+{
+  DB_IO_DEF(handle, poolno);
+  int rc = 0;
+  int bytes = sizeof_data * n;
+  int this_io_method = pdb ? pdb->io_method : 0;
+  int req_byteswap = pdb ? pdb->req_byteswap : -1;
+  DRHOOK_START(newio_Read32);
+
+  if (this_io_method == 0) goto finish;
+
+  if ( bytes > 0 ) {
+    if (io_profile) Profile_newio32_start(ioprof_read, bytes);
+    if (this_io_method == 3 ||
+	this_io_method == 4) { /* QTAR or horizontal concat */
+      int jtbl = *fp_idx;
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	if (ptbl->open_mode == NEWIO_OPEN_READ) {
+	  /* "read" data from incore-array */
+	  rc = bytes;
+	  if (!ptbl->incore) {
+	    rc = 0;
+	  }
+	  else if (ptbl->n_alloc - ptbl->incore_ptr < bytes) {
+	    rc = -ABS(ptbl->n_alloc - ptbl->incore_ptr);
+	  }
+	  else { /* All okay */
+	    memcpy(data, &ptbl->incore[ptbl->incore_ptr], bytes);
+	    ptbl->incore_ptr += bytes;
+	    /* Note: Do NOT update n_incore nor known_size, since they've been handled okay elsewhere */
+	  }
+	}
+      } /* if (jtbl >= 0) */
+    }      
+    else if (this_io_method == 2) {
+      rc = ReadData32(*fp_idx, data, bytes);
+    }
+    else {
+      cma_readb_(fp_idx, data, &bytes, &rc);
+      if (rc == -2) { /* Error : Invalid internal file unit : indication of too small MAXCMAIO-value ? */
+	int maxcmaio = CMA_get_MAXCMAIO();
+	newio_Error32("newio_Read32: cma_readb_() failed possibly due to too small MAXCMAIO-value",
+		      filename, desc, entry, handle, poolno, bytes, rc, this_io_method,
+		      "newio_Read32: sizeof_data=%d, n=%d, *fp_idx=%d, data=%p, req_byteswap=%d.\n"
+		      "newio_Read32: Suggesting to increase MAXCMAIO via 'export MAXCMAIO=%d' to %d before re-running",
+		      sizeof_data, n, *fp_idx, data, req_byteswap, maxcmaio, 10*maxcmaio);
+      }
+    }
+    if (io_profile) Profile_newio32_end(ioprof_read, rc);
+  }
+
+ finish:
+  if (rc != bytes) { 
+    newio_Error32("newio_Read32", 
+		  filename, desc, entry, handle, poolno, bytes, rc, this_io_method, 
+		  "newio_Read32: sizeof_data=%d, n=%d, *fp_idx=%d, data=%p, req_byteswap=%d",
+		  sizeof_data, n, *fp_idx, data, req_byteswap); 
+  }
+
+  DRHOOK_END(bytes);
+  return bytes;
+}
+
+
+PRIVATE int
+WriteData32(int fd, const void *data, int bytes)
+{
+  int len, n;
+  const char *c = data;
+  int rem = bytes;
+  int rc = 0;
+  DRHOOK_START(WriteData32);
+  for (;;) {
+    len = MIN(io_bufsize, rem);
+    if (len <= 0) break;
+    n = write(fd, c, len);
+    if (n > 0) {
+      c += n;
+      rem -= n;
+      rc += n;
+    }
+    else /* Error (the stmt "rc != bytes" below will catch it) */
+      break;
+  }
+  DRHOOK_END(rc);
+  return rc;
+} 
+
+
+PUBLIC int
+newio_Write32(int *fp_idx, 
+	      const char *filename, 
+	      const char *desc, 
+	      const char *entry,
+	      int handle,
+	      int poolno,
+	      const void *data, 
+	      int sizeof_data, 
+	      int n)
+{
+  DB_IO_DEF(handle, poolno);
+  int rc = 0;
+  int bytes = sizeof_data * n;
+  int this_io_method = pdb ? pdb->io_method : 0;
+  int req_byteswap = pdb ? pdb->req_byteswap : -1;
+  DRHOOK_START(newio_Write32);
+
+  if (this_io_method == 0) goto finish;
+
+  if (bytes > 0 && !pdb->is_readonly) {
+    if (io_profile) Profile_newio32_start(ioprof_write, bytes);
+    if (this_io_method == 3 ||
+	this_io_method == 4) { /* QTAR or horizontal concat */
+      int jtbl = *fp_idx;
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	if (ptbl->open_mode == NEWIO_OPEN_WRITE) {
+	  /* cache data to incore-array */
+	  rc = bytes;
+	  if (!ptbl->incore) {
+	    Alloc_INCORE(ptbl, bytes, io_bufsize);
+	  }
+	  else if (ptbl->n_alloc - ptbl->incore_ptr < bytes) { /* allocate more */
+	    if (io_verbose == newio_myproc) {
+	      fprintf(stderr,
+		      "\tReallocation of %d bytes (n_alloc=%d, incore_ptr=%d, n_incore=%d, incore=%p)\n", 
+		      bytes, ptbl->n_alloc, ptbl->incore_ptr, ptbl->n_incore, ptbl->incore);
+	      TableDump(stderr, ptbl->mypool, ptbl);
+	    }
+            ptbl->n_alloc = RNDUP(ptbl->n_alloc + bytes, io_bufsize);
+	    REALLOC(ptbl->incore, ptbl->n_alloc);
+	  }
+	  memcpy(&ptbl->incore[ptbl->incore_ptr], data, bytes);
+	  ptbl->incore_ptr += bytes;
+	  ptbl->known_size = ptbl->n_incore = ptbl->incore_ptr - DIMLEN;
+	  ptbl->updated = 1;
+	}
+      } /* if (jtbl >= 0) */
+    }      
+    else if (this_io_method == 2) {
+      rc = WriteData32(*fp_idx, data, bytes);
+    }
+    else {
+      cma_writeb_(fp_idx, data, &bytes, &rc);
+    }
+    if (io_profile) Profile_newio32_end(ioprof_write, rc);
+  }
+
+ finish:
+  if (rc != bytes) { 
+    newio_Error32("newio_Write32", 
+		  filename, desc, entry, handle, poolno, bytes, rc, this_io_method,
+		  "newio_Write32: sizeof_data=%d, n=%d, *fp_idx=%d, data=%p, req_byteswap=%d",
+		  sizeof_data, n, *fp_idx, data, req_byteswap); 
+  }
+
+  DRHOOK_END(bytes);
+  return bytes;
+}
+
+
+PUBLIC int
+newio_Close32(int *fp_idx, 
+	      const char *filename, 
+	      const char *dbname,
+	      const char *table,
+	      const char *desc,
+	      const char *entry,
+	      int handle,
+	      int poolno,
+	      unsigned int info[],
+	      int infolen
+	      )
+{
+  DB_IO_DEF(handle, poolno);
+  int rc = 0;
+  int nrows = (infolen >= 2) ? info[1] : -1;
+  int ncols = (infolen >= 3) ? info[2] : -1;
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_Close32);
+
+  if (this_io_method == 0) goto finish;
+
+  if (io_profile) Profile_newio32_start(ioprof_close, 0);
+
+  if (this_io_method == 3 ||
+      this_io_method == 4) { /* QTAR or horizontal concat */
+    int jtbl = *fp_idx;
+    if (jtbl >= 0) {
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      if (io_verbose == newio_myproc) {
+	fprintf(stderr,
+		"newio_Close32(%s=%d,%s='%s',%s='%s',%s='%s',\n\t%s='%s',%s='%s',%s=%d,%s=%d)\n",
+		"*fp_idx", *fp_idx,
+		"filename", filename,
+		"dbname", dbname,
+		"table", table,
+		"desc", desc,
+		"entry", entry,
+		"handle", handle,
+		"poolno", poolno);
+      }
+      if (ptbl->incore) ptbl->incore_ptr = DIMLEN;
+      ptbl->open_mode = NEWIO_OPEN_UNDEF;
+      if (nrows != -1) ptbl->nrows = nrows;
+      if (ncols != -1) ptbl->ncols = ncols;
+    }
+  }
+  else if (this_io_method == 2) {
+    int fd = *fp_idx;
+    close(fd);
+  }
+  else {
+    cma_close_(fp_idx, &rc);
+  }
+  if (io_profile) Profile_newio32_end(ioprof_close, rc);
+  if (io_profile) Profile_newio32_flush();
+  if (io_lock) lock_IO(0);  /* Release I/O-lock */
+  if (rc != 0) { 
+    newio_Error32("newio_Close32", 
+		  filename, desc, entry, handle, poolno, 0, rc, this_io_method, NULL); 
+  }
+
+ finish:
+  *fp_idx = -1;
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC int
+newio_Open32(int *fp_idx, 
+	     const char *filename, 
+	     const char *dbname,
+	     const char *table,
+	     const char *desc,
+	     const char *entry,
+	     int handle,
+	     int poolno,
+	     const char *mode,
+	     int close_too,
+	     int lookup_only,
+	     unsigned int info[],
+	     int infolen)
+{
+  DB_IO_DEF(handle, poolno);
+  int rc = 0;
+  int Nbytes = 0;
+  int nrows = 0;
+  int ncols = 0;
+  int reading = (*mode == 'r') ? 1 : 0;
+  int writing = (reading == 0);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_Open32);
+
+  *fp_idx = -1;
+  if (this_io_method == 0) goto finish;
+
+  if (!pdb->in_use && !pdb->is_new && this_io_method == 3) {
+    /* Get information of member files in QTAR via table of contents */
+    int exist = 0;
+    char *qtarfile = GetQTARFILE(handle, poolno, ppool, &exist);
+
+    if (exist) { /* Retrieve table of contents from QTAR */
+      FILE *fp;
+      char *toc_cmd = NULL;
+      int len = strlen(qtarfile) + 20;
+      ALLOC(toc_cmd, len);
+      sprintf(toc_cmd, "qtar -s -t -M -f %s", qtarfile);
+      
+      if (io_verbose == newio_myproc) {
+	fprintf(stderr,"Executing: popen(%s, r)\n",toc_cmd);
+	xl__trbk_();
+      }
+
+      fp = popen(toc_cmd, "r");
+      if (fp) {
+	char memfile[8192];
+	int j, nmem = 0;
+	int nitems = 0;
+	nitems = fscanf(fp, "%d\n", &nmem);
+	if (nitems == 1) {
+	  for (j=0; j<nmem; j++) {
+	    ll_t nbytes, offset;
+	    int nrows, ncols;
+	    nitems = fscanf(fp,"%s %lld %lld %d %d\n",memfile,&nbytes,&offset,&nrows,&ncols);
+	    if (nitems == 5) {
+	      int jtbl = LocateTable(memfile, ppool, 1);
+	      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	      ptbl->known_size = (int)nbytes;
+	      ptbl->offset = offset;
+	      ptbl->nrows = nrows;
+	      ptbl->ncols = ncols;
+	      ptbl->updated = 0; /* for security */
+	      ptbl->in_use = 0; /* for security */
+	    }
+	    else {
+	      newio_Error32("newio_Open32: Cannot retrieve member file information from QTAR's TOC-output",
+			    filename, desc, entry, handle, poolno, j+1, nmem,
+			    this_io_method,
+			    "newio_Open32: QTAR-cmd='%s'",toc_cmd);
+	    }
+	  } /* for (j=0; j<nmem; j++) */
+	}
+	else {
+	  newio_Error32("newio_Open32: Cannot retrieve no. of members from QTAR's TOC-output",
+			filename, desc, entry, handle, poolno, 1, nitems,
+			this_io_method,
+			"newio_Open32: QTAR-cmd='%s'",toc_cmd);
+	}
+	pclose(fp);
+      }
+      else {
+	newio_Error32("newio_Open32: Cannot retrieve TOC-information. QTAR corrupted ?",
+		      filename, desc, entry, handle, poolno, 0, 0,
+		      this_io_method,
+		      "newio_Open32: QTAR-cmd='%s'",toc_cmd);
+      }
+      FREE(toc_cmd);
+    }
+    else {
+      fprintf(stderr,
+	      "***Warning: Could not locate QTAR='%s' for dbname='%s', handle=%d, poolno=%d\n",
+	      qtarfile, dbname, handle, poolno);
+    }
+  }
+  pdb->in_use = 1;
+
+  if (writing) {
+    /* Get data amount indicator ; triggers whether to open/write file at all */
+    if (infolen >= 2) nrows = info[1];
+/*    printf("newioc.c nrows = %d\n", nrows); */
+  }
+
+  if (reading || (writing && (nrows > 0 || io_write_empty_files))) {
+    int perror_onoff = -1;
+    const int on = 1;
+    if (reading) { /* temporarely disable perror() messages */
+      const int off = 0;
+      cma_set_perror_(&off, &perror_onoff); 
+    }
+    if (io_lock) lock_IO(1); /* Acquire I/O-lock */
+    if (io_profile) Profile_newio32_start(ioprof_open, 0);
+    if (this_io_method == 4) { /* horizontal concat */
+      int open_new_table = (writing && (nrows > 0 || io_write_empty_files)) ? 1 : 0;
+      int jtbl = LocateTable(table, ppool, open_new_table);
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	*fp_idx = jtbl;
+	if (reading) {
+	  ptbl->open_mode = NEWIO_OPEN_READ;
+	}
+	else if (writing) {
+	  /* We do almost nothing ; just record the *fp_idx and fake rc to 1 */
+	  if (!pdb->is_readonly) {
+	    ptbl->open_mode = NEWIO_OPEN_WRITE;
+	  }
+	  else {
+	    ptbl->open_mode = NEWIO_OPEN_UNDEF;
+	  }
+	}
+	if (!ptbl->incore) Alloc_INCORE(ptbl, 0, WORDLEN);
+	ptbl->incore_ptr = DIMLEN;
+	if (reading && ptbl->n_incore == 0) {
+	  /* No data loaded/available ==> corresponds to empty file situation */
+	  rc = -1;
+	}
+	else {
+	  rc = 1;
+	}
+      }
+      else if (reading) {
+	rc = -1; /* Means: data not supplied from I/O-level i.e. 
+		    must be an "empty file" or not considered to load (<-- too bad) */
+      } /* if (jtbl >= 0) ... else if (reading) ... */
+    }
+    else if (this_io_method == 3) { /* QTAR */
+      int exist = 0;
+      int is_incore_already = 0;
+      char *qtarfile = GetQTARFILE(handle, poolno, ppool, &exist);
+      int jtbl = LocateTable(table, ppool, 1);
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      *fp_idx = jtbl;
+
+      if (io_verbose == newio_myproc) {
+	fprintf(stderr,
+"newio_Open32(%s=%d,%s='%s',%s='%s',%s='%s',\n\t%s='%s',%s='%s',\n\t%s=%d,%s=%d,%s='%s',%s=%d,%s=%p,%s=%d)\n",
+		"*fp_idx", *fp_idx,
+		"filename", filename,
+		"dbname", dbname,
+		"table", table,
+		"desc", desc,
+		"entry", entry,
+		"handle", handle,
+		"poolno", poolno,
+		"mode", mode,
+		"close_too", close_too,
+		"info[]-addr", info,
+		"infolen", infolen);
+      }
+
+      if (reading && !ptbl->read_cmd) {
+	int len = strlen(table) + strlen(qtarfile) + 50;
+	ALLOC(ptbl->read_cmd, len);
+	sprintf(ptbl->read_cmd,"qtar -s -x -M -b %d -f %s -m %s", io_bufsize, qtarfile, table);
+      }
+
+      /* check whether incore already and potentially save from re-reading */
+      if (reading) {
+	if (ptbl->n_incore >= 0 || ptbl->known_size == 0) is_incore_already = 1;
+	if (is_incore_already && !ptbl->incore) Alloc_INCORE(ptbl, 0, WORDLEN);
+      }
+
+      if (reading) {
+	FILE *fp = NULL;
+	if (!is_incore_already) Free_INCORE(ptbl, 0);
+	if (exist && !is_incore_already) {
+	  if (io_verbose == newio_myproc) {
+	    fprintf(stderr,"Executing: popen(%s, r)\n",ptbl->read_cmd);
+	    xl__trbk_();
+	  }
+	  fp = popen(ptbl->read_cmd, "r");
+	}
+	if (fp) {
+	  ll_t dim[DIMLEN/WORDLEN];
+	  int fd = fileno(fp);
+	  int nread = ReadData32(fd, dim, DIMLEN);
+	  if (nread == DIMLEN) {
+	    int bytes;
+	    ll_t nbytes;
+	    int nrows, ncols;
+	    nbytes = dim[0];
+	    nrows = dim[1];
+	    ncols = dim[2];
+	    bytes = (int)nbytes;
+	    if (bytes > 0) {
+	      Alloc_INCORE(ptbl, bytes, WORDLEN);
+	      nread = ReadData32(fd, ptbl->incore + DIMLEN, ptbl->n_incore);
+	      if (nread != ptbl->n_incore) {
+		newio_Error32("newio_Open32: Unable to ReadData32()", 
+			      filename, desc, entry, handle, poolno, ptbl->n_incore, nread, 
+			      this_io_method,
+			      "newio_Open32: QTAR-cmd='%s'",ptbl->read_cmd);
+	      }
+	      ptbl->incore_ptr = DIMLEN;
+	      ptbl->known_size = ptbl->n_incore;
+	      ptbl->nrows = nrows;
+	      ptbl->ncols = ncols;
+	      rc = 1;
+	    }
+	    else {
+	      rc = -1; /* File-member not found or length info indicates that its size is zero */
+	      Alloc_INCORE(ptbl, 0, WORDLEN);
+	    } /* if (bytes > 0) */
+	    ptbl->open_mode = NEWIO_OPEN_READ;
+	    pclose(fp);
+	  }
+	  else {
+	    newio_Error32("newio_Open32: Invalid length info from ReadData32()",
+			  filename, desc, entry, handle, poolno, DIMLEN, nread,
+			  this_io_method,
+			  "newio_Open32: QTAR-cmd='%s'",ptbl->read_cmd);
+	  } /* if (nread == DIMLEN) */
+	}
+	else if (is_incore_already) {
+	  ptbl->open_mode = NEWIO_OPEN_READ;
+	  if (ptbl->n_incore > 0) {
+	    rc = 1; /* Data is already in ptbl->incore[] */
+	  }
+	  else { /* i.e. ptbl->n_incore == 0 */
+	    rc = -1; /* Data file wasn't there when first time retrieved */
+	  }
+	}
+	else { /* i.e. NOT exist */
+	  Alloc_INCORE(ptbl, 0, WORDLEN);
+	  ptbl->open_mode = NEWIO_OPEN_UNDEF;
+	  rc = -1; /* QTARFILE not present ==> File-member not found either */
+	} /* if (fp) */
+      }
+      else if (writing) {
+	/* We do almost nothing ; just record the *fp_idx; 
+	   the newio_flush32_() will do the I/O, when called */
+	if (!pdb->is_readonly) {
+	  ptbl->open_mode = NEWIO_OPEN_WRITE;
+	}
+	else {
+	  ptbl->open_mode = NEWIO_OPEN_UNDEF;
+	}
+      }
+      if (ptbl->incore) ptbl->incore_ptr = DIMLEN;
+    }
+    else if (this_io_method == 2) {
+      int len = strlen(filename);
+      char *truename = IOtruename(filename, &len);
+      int fd = -1;
+      if (reading) {
+	fd = open(truename, O_RDONLY, 0); 
+	/* We don't care about open()-errors in reading ==> we assume empty file situation */
+	if (fd < 0) rc = -1;
+      }
+      else if (writing) {
+	(void) IOmkdir(truename); /* Makes sure the underlaying directory really exists */
+	fd = open(truename, O_WRONLY | O_CREAT | O_TRUNC, PERMS);
+	/* Abort immediately */
+	if (fd < 0) {
+	  newio_Error32("newio_Open32: open() for writing failed", 
+			filename, desc, entry, handle, poolno, 0, rc, 
+			this_io_method,
+			NULL);
+	}
+      }
+      *fp_idx = fd;
+      FREE(truename);
+    }
+    else {
+      cma_open_(fp_idx, filename, mode, &rc, strlen(filename), strlen(mode));
+      cma_get_byteswap_(fp_idx, &pdb->req_byteswap);
+    }
+
+    if (io_profile) Profile_newio32_end(ioprof_open, rc);
+    if (perror_onoff == on) { /* switch perror() output back on */
+      cma_set_perror_(&on, &perror_onoff); 
+    }
+  }
+  else if (writing && nrows == 0) {
+    if (io_lock) lock_IO(1); /* Acquire I/O-lock */
+    if (io_profile) Profile_newio32_start(ioprof_rmfile, 0);
+    if (this_io_method == 4) { /* horizontal concat */
+/* AF begin */
+      int open_new_table = (writing && (nrows >= 0 || io_write_empty_files)) ? 1 : 0;
+      int jtbl = LocateTable(table, ppool, open_new_table);
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	*fp_idx = jtbl;
+      }
+      jtbl = *fp_idx;
+/* END AF */
+ /*     int jtbl = *fp_idx;
+*/
+/*printf("AF write & nrows = 0 %d\n", jtbl);*/
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	Alloc_INCORE(ptbl, 0, WORDLEN);
+	if (!pdb->is_readonly) ptbl->updated = 1;
+	ptbl->open_mode = NEWIO_OPEN_DELETE;
+      } /* if (jtbl >= 0) */
+    }
+    else if (this_io_method == 3) { /* QTAR */
+      int exist = 0;
+      char *qtarfile = GetQTARFILE(handle, poolno, ppool, &exist);
+      int jtbl = *fp_idx;
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	if (!pdb->is_readonly && ptbl->known_size > 0) {
+	  if (exist) {
+	    int status;
+	    if (!ptbl->delete_cmd) {
+	      int len = strlen(table) + strlen(qtarfile) + 50;
+	      ALLOC(ptbl->delete_cmd, len);
+	      sprintf(ptbl->delete_cmd,"qtar -s -d -M -b %d -f %s -m %s", 
+		      io_bufsize, qtarfile, table);
+	    }
+	    if (io_verbose == newio_myproc) {
+	      fprintf(stderr,"Executing: system(%s)\n",ptbl->delete_cmd);
+	      xl__trbk_();
+	    }
+	    status = system(ptbl->delete_cmd);
+	    if (status != 0) {
+	      newio_Error32("newio_Open32: Error in deleting member-file via system()",
+			    filename, desc, entry, handle, poolno, 0, 0,
+			    this_io_method,
+			    "newio_Open32: system() QTAR-cmd='%s'",ptbl->delete_cmd);
+	    }
+	    ppool->file_exist = 1;
+	    ptbl->known_size = -1;
+	  } /* if (exist) */
+	} /* if (!pdb->is_readonly && ptbl->known_size > 0) */
+	ptbl->open_mode = NEWIO_OPEN_DELETE;
+      } /* if (jtbl >= 0) */
+    }
+    else {
+      remove_file_(filename); /* Make sure the existing file is removed */
+    }
+    if (io_profile) Profile_newio32_end(ioprof_rmfile, 0);
+    if (io_lock) lock_IO(0);  /* Release I/O-lock */
+  }
+
+  if (reading && rc == -1) { /* File not found for reading */
+    int date_now = 0, time_now = 0;
+    /* #1: Magic number */                    if (infolen >= 1) info[0] = ODB_;
+    nrows = 0;
+    /* #2: Number of rows */                  if (infolen >= 2) info[1] = nrows;
+    ncols = 0; /* undefined ==> fill it later */
+    /* #3: Number of cols */                  if (infolen >= 3) info[2] = ncols; 
+    if (infolen >= 5) codb_datetime_(&date_now, &time_now);
+    /* #4: Creation date (YYYYMMDD) */        if (infolen >= 4) info[3] = date_now;
+    /* #5: Creation time (HHMMSS) */          if (infolen >= 5) info[4] = time_now;
+    /* #6: Modification date (YYYYMMDD) */    if (infolen >= 6) info[5] = date_now;
+    /* #7: Modification time (HHMMSS) */      if (infolen >= 7) info[6] = time_now;
+    close_too = 0;
+  }
+  else if (reading) {
+    int swp = 0;
+    Nbytes += newio_Read32(fp_idx, filename, desc, entry, handle, poolno, 
+			   info, sizeof(*info), infolen);
+    if (infolen >= 1) {
+      if (info[0] == _BDO) {
+	int oldswp;
+	swp = 1;
+	oldswp = newio_SetByteswap(fp_idx, swp, handle, poolno);
+	swap4bytes_(info, &infolen);
+      }
+    }
+    if (infolen >= 2) nrows = info[1];
+    if (infolen >= 3) ncols = info[2];
+    if (swp) swap4bytes_(info, &infolen); /* need to swap back, otherwise logic fails */
+  }
+  else if (writing && (nrows > 0 || io_write_empty_files)) {
+    /* write to a non-empty file */
+/*printf("AF write to a non-empty file \n"); */
+    Nbytes += newio_Write32(fp_idx, filename, desc, entry, handle, poolno, 
+			    info, sizeof(*info), infolen);
+    if (infolen >= 2) nrows = info[1];
+    if (infolen >= 3) ncols = info[2];
+  }
+  else {
+    close_too = 0;
+  }
+
+  if (this_io_method == 4) { /* horizontal concat */
+    int jtbl = *fp_idx;
+    if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	ptbl->nrows = nrows;
+	ptbl->ncols = ncols;
+    }
+  }
+
+  if (close_too) { newio_Close32(fp_idx, filename, dbname, table, desc, 
+				 entry, handle, poolno, info, infolen); }
+
+ finish:
+  DRHOOK_END(0);
+  return Nbytes;
+}
+
+/* --- New internal I/O structures --- */
+
+PRIVATE int
+init_IO_struct(int maxhandle)
+{
+  DRHOOK_START(init_IO_struct);
+  if (!db_io) {
+    coml_set_lockid_(&NEWIO_mylock);
+    if (!db_io) {
+      IO_db_t *tmp_db_io = NULL;
+      int jdb;
+      db_io_size = MAX(1,maxhandle);
+      ALLOC(tmp_db_io, db_io_size);
+      for (jdb=0; jdb<db_io_size; jdb++) {
+	IO_db_t *pdb = &tmp_db_io[jdb];
+	pdb->dbname = NULL;
+	pdb->in_use =  0;
+	pdb->handle = -1;
+	pdb->is_new = -1;
+	pdb->is_readonly = -1;
+	pdb->req_byteswap = 0;
+	pdb->io_method = io_method; /* i.e. via ODB_IO_METHOD */
+	pdb->npools = 0;
+	pdb->pool = NULL;
+	pdb->maxpools = 0;
+	pdb->poolaccess = NULL;
+      }
+      db_io = tmp_db_io;
+    } /* if (!db_io) */
+    coml_unset_lockid_(&NEWIO_mylock);
+  }
+  DRHOOK_END(0);
+  return db_io_size;
+}
+
+
+PRIVATE int
+end_IO_struct(int handle)
+{
+  int jdb, jpool; 
+  IO_db_t *pdb = NULL;
+  int maxsize = 0;
+  int npools;
+  DRHOOK_START(end_IO_struct);
+  
+  maxsize = init_IO_struct(handle);
+
+  if (handle < 1 || handle > maxsize) { /* Out of range */
+    newio_Error32("end_IO_struct: Handle out of range",
+		  NULL, NULL, NULL,
+		  handle, -1, 0, 0,
+		  -1, NULL);
+  }
+
+  jdb = handle-1;
+  pdb = &db_io[jdb];
+  FREE(pdb->dbname);
+  pdb->in_use =  0;
+  pdb->handle = -1;
+  pdb->is_new = -1;
+  pdb->is_readonly = -1;
+  pdb->req_byteswap = 0;
+  pdb->io_method = io_method;
+  npools = pdb->npools;
+
+  for (jpool=0; jpool<npools; jpool++) {
+    int rc;
+    IO_pool_t *ppool = &pdb->pool[jpool];
+    int poolno = ppool->poolno;
+    newio_release_pool32_(&handle, &poolno, &rc);
+  } /* for (jpool=0; jpool<npools; jpool++) */
+
+  pdb->npools = 0;
+  FREE(pdb->pool);
+
+  pdb->maxpools = 0;
+  FREE(pdb->poolaccess);
+
+  DRHOOK_END(0);
+  return handle;
+}
+
+
+PRIVATE void
+copy_IO_dbstr(IO_db_t *to, IO_db_t *from)
+{
+  DRHOOK_START(copy_IO_dbstr);
+  if (to && from && to != from) {
+    int npools = to->npools;
+    int old_npools = from->npools;
+    int jpool, np = MIN(old_npools, npools);
+
+    FREE(to->dbname);
+    to->dbname = STRDUP(from->dbname);
+    FREE(from->dbname);
+
+    to->in_use = from->in_use;
+    to->handle = from->handle;
+    to->is_readonly = from->is_readonly;
+    to->req_byteswap = from->req_byteswap;
+    to->is_new = from->is_new;
+    to->io_method = from->io_method;
+  
+    for (jpool=0; jpool<np; jpool++) {
+      IO_pool_t *ppool = &to->pool[jpool];
+      IO_pool_t *old_ppool = &from->pool[jpool];
+      int poolno = ppool->poolno;
+      if (old_ppool) {
+	FREE(ppool->tbl);
+	memcpy(ppool, old_ppool, sizeof(*old_ppool)); /* Alright ? Copies ptrs etc. */
+      }
+      ppool->mydb = to;
+      ppool->poolno = poolno;
+      { /* Re-assign ptbl->mypool */
+	int jtbl, maxtables = ppool->maxtables;
+	for (jtbl=0; jtbl<maxtables; jtbl++) {
+	  IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	  ptbl->mypool = ppool; /* Used to point to old_ppool */
+	}
+      }
+    } /* for (jpool=0; jpool<np; jpool++) */
+  } /* if (to && from && to != from) */
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+init_IO_dbstr(IO_db_t *pdb,
+	      const char *dbname, 
+	      int handle, int maxhandle, int io_method_input,
+	      int maxtables, int is_new, int is_readonly,
+	      int maxpools, int npools, const int poolnos[])
+{
+  int jpool;
+  DRHOOK_START(init_IO_dbstr);
+
+  pdb->dbname = STRDUP(dbname);
+  pdb->in_use = 0;
+  pdb->handle = handle;
+  pdb->is_readonly = is_readonly;
+  pdb->req_byteswap = 0;
+  pdb->is_new = is_new;
+  /* pdb->io_method = (is_new) ? io_method : io_method_input; : this was a bug !! */
+  pdb->io_method = io_method_input; /* This is how it should always be */
+  pdb->npools = npools;
+  ALLOC(pdb->pool, npools);
+  pdb->maxpools = maxpools;
+  CALLOC(pdb->poolaccess, maxpools+1);
+  
+  for (jpool=0; jpool<npools; jpool++) {
+    int jtbl, poolno;
+    IO_pool_t *ppool = &pdb->pool[jpool];
+    ppool->mydb = pdb;
+    poolno = ppool->poolno = poolnos[jpool];
+    if (poolno >= 1 && poolno <= maxpools) {
+      pdb->poolaccess[poolno] = jpool;
+    }
+    else {
+      /* basically will trigger an error */
+      pdb->poolaccess[poolno] = badnum;
+    }
+    ppool->ntables = 0;
+    ppool->maxtables = maxtables;
+    ALLOC(ppool->tbl, maxtables);
+    for (jtbl=0; jtbl<maxtables; jtbl++) {
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      ptbl->mypool = ppool;
+      ptbl->tblname = NULL; /* initially */
+      ptbl->known_size = -1;
+      ptbl->updated = 0;
+      ptbl->nrows = 0;
+      ptbl->ncols = 0;
+      /* incore items */
+      ptbl->open_mode = NEWIO_OPEN_UNDEF; /* initially */
+      ptbl->file = NULL; /* initially */
+      ptbl->offset = 0; /* initially */
+      ptbl->incore = NULL; /* initially */
+      ptbl->n_incore = -1; /* initially */
+      ptbl->n_alloc = 0; /* initially */
+      ptbl->incore_ptr = 0; /* initially */
+      ptbl->in_use = 0; /* initially */
+      ptbl->read_cmd = NULL; /* initially */
+      ptbl->delete_cmd = NULL; /* initially */
+    } /* for (jtbl=0; jtbl<maxtables; jtbl++) */
+    ppool->file = NULL; /* initially */
+    ppool->file_exist = 0; /* initially */
+    ppool->last_write_cmd = NULL; /* initially */
+  } /* for (jpool=0; jpool<npools; jpool++) */
+  DRHOOK_END(0);
+}
+
+
+PRIVATE IO_db_t *
+copy_IO_struct(IO_db_t *curdb,
+	       const char *dbname, 
+	       int handle, int maxhandle, int io_method_input,
+	       int maxtables, int is_new, int is_readonly,
+	       int maxpools, int npools, const int poolnos[])
+{
+  IO_db_t *pdb = NULL;
+  DRHOOK_START(copy_IO_struct);
+
+  if (curdb) {
+    int jdb; 
+    int maxsize = 0;
+    
+    maxsize = init_IO_struct(maxhandle);
+    
+    if (handle < 1 || handle > maxsize) { /* Out of range */
+      newio_Error32("copy_IO_struct: Handle out of range",
+		    NULL, NULL, NULL,
+		    handle, -1, 0, 0,
+		    io_method_input,
+		    "copy_IO_struct(dbname='%s')", dbname);
+    }
+    
+    jdb = handle-1;
+    pdb = &db_io[jdb];
+    
+    if (curdb == pdb && (curdb->npools < npools || 
+			 curdb->maxpools < maxpools)) {
+
+      if (newio_myproc == 1) {
+	fprintf(stderr,
+	"copy_IO_struct(handle=%d, dbname='%s'; npools=(%d => %d); maxpools=(%d => %d)\n", 
+	handle, dbname, curdb->npools, npools, curdb->maxpools, maxpools);
+      }
+
+      /* Allocate new database structure */
+      ALLOC(pdb, 1);
+      pdb->dbname = NULL;
+      pdb->in_use =  0;
+      pdb->handle = -1;
+      pdb->is_new = -1;
+      pdb->is_readonly = -1;
+      pdb->req_byteswap = 0;
+      pdb->io_method = io_method; /* i.e. via ODB_IO_METHOD */
+      pdb->npools = 0;
+      pdb->pool = NULL;
+      pdb->maxpools = 0;
+      pdb->poolaccess = NULL;
+
+      /* Firstly, fully initialize newly allocated structure */
+
+      init_IO_dbstr(pdb,
+		    dbname, 
+		    handle, maxhandle, io_method_input,
+		    maxtables, is_new, is_readonly,
+		    maxpools, npools, poolnos);
+
+      /* Now do copying */
+      copy_IO_dbstr(pdb, curdb);
+
+      /* Finally, copy data structure "back" 
+	 (i.e. effectively replaces contents pointed by "curdb") */
+      memcpy(&db_io[jdb], pdb, sizeof(*pdb));
+      pdb = &db_io[jdb];
+    }
+    else { /* The best solution we can offer */
+      pdb = (IO_db_t *)curdb;
+    }
+  }
+
+  DRHOOK_END(0);
+  return pdb;
+}
+
+			 
+PRIVATE IO_db_t *
+start_IO_struct(const char *dbname, 
+		int handle, int maxhandle, int io_method_input,
+		int maxtables, int is_new, int is_readonly,
+		int maxpools, int npools, const int poolnos[])
+{
+  int jdb, jpool; 
+  int maxsize = 0;
+  IO_db_t *pdb = NULL;
+  DRHOOK_START(start_IO_struct);
+
+  maxsize = init_IO_struct(maxhandle);
+
+  if (handle < 1 || handle > maxsize) { /* Out of range */
+    newio_Error32("start_IO_struct: Handle out of range",
+		  NULL, NULL, NULL,
+		  handle, -1, 0, 0,
+		  io_method_input,
+		  "start_IO_struct(dbname='%s')", dbname);
+  }
+
+  jdb = handle-1;
+  pdb = &db_io[jdb];
+
+  if (!pdb->in_use) { 
+    /* I/O-requests not started yet ==> re-initialization *is* allowed */
+    (void) end_IO_struct(handle);
+
+    init_IO_dbstr(pdb,
+		  dbname, 
+		  handle, maxhandle, io_method_input,
+		  maxtables, is_new, is_readonly,
+		  maxpools, npools, poolnos);
+  }
+  else { 
+    /* I/O-requests have started => copy & extend data structures 
+       This situation may occur due to ODB_addpools() on-the-fly */
+
+    pdb = copy_IO_struct(pdb,
+			 dbname, 
+			 handle, maxhandle, io_method_input,
+			 maxtables, is_new, is_readonly,
+			 maxpools, npools, poolnos);
+			 
+  }
+
+  DRHOOK_END(0);
+  return pdb;
+}
+
+/*=== Fortran callables ===*/
+
+PUBLIC void
+newio_start32_(const char *dbname,
+	       const int *handle, const int *maxhandle, const int *io_method_input,
+               const int *maxtables, const int *is_new, const int *is_readonly,
+               const int *glbNpools, const int *locNpools, const int poolidx[],
+               int *rc
+	       /* Hidden argument */
+	       , int dbname_len)
+{
+  DECL_FTN_CHAR(dbname);
+  DRHOOK_START(newio_start32_);
+
+  ALLOC_FTN_CHAR(dbname);
+
+  init_IOs();
+
+  (void) start_IO_struct(p_dbname, 
+			 *handle, *maxhandle, *io_method_input,
+			 *maxtables, *is_new, *is_readonly,
+			 *glbNpools, *locNpools, poolidx);
+
+  FREE_FTN_CHAR(dbname);
+
+  /* for now */
+  DRHOOK_END(0);
+  *rc = 0;
+}
+
+#define SKIP_RUBBISH(p) \
+  { while (*p    && (*p == '/' || *p == '@' || *p == ' ')) p++; }
+#define NEXT_RUBBISH(p) \
+  { while (*p) { if (*p == '/' || *p == '@' || *p == ' ') { *p = '\0'; break; } else p++; } }
+
+PRIVATE char **
+TableList(const char table[], int Ntables_in, int *Ntables)
+{
+  char **t = NULL;
+  int m = Ntables_in;
+  int n = 0;
+  DRHOOK_START(TableList);
+
+  if (table && m > 0) {
+    char *p = STRDUP(table);
+    CALLOC(t, m);
+    while (*p && n < m) {
+      char *s, *saved;
+      SKIP_RUBBISH(p);
+      saved = s = STRDUP(p);
+      NEXT_RUBBISH(s);
+      SKIP_RUBBISH(s);
+      t[n++] = STRDUP(saved);
+      p = STRDUP(s+1);
+      FREE(saved);
+    }
+    FREE(p);
+  }
+
+  if (Ntables) *Ntables = n;
+  DRHOOK_END(0);
+  return t;
+}
+
+
+PUBLIC void
+newio_flush32_(const int *handle,
+	       const int *poolno,
+	       const int *enforce_to_disk,
+	       const int *ntbl,
+	       /* Tables in format "/@table1/@tables2/.../"
+		  For all tables (currently in memory), use "*" or put *ntables to -1 */
+	       const char table[],
+	       int *rc
+	       /* Hidden argument */
+	       , int table_len)
+{
+  int retcode = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  DB_IO_DEF(Handle, Poolno);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  int ef2d = *enforce_to_disk;
+
+  if (this_io_method == 0) goto finish;
+
+  if (this_io_method != 3) goto finish; /* Applies currently for QTAR-only */
+
+  /* Use of this "enforcement" not implemented yet */
+  if (*enforce_to_disk) {
+    ef2d = 1;
+  }
+  else {
+    if (io_keep_incore > 1) ef2d = 0;
+  }
+
+  if (pdb && pdb->in_use && this_io_method == 3) { /* QTAR-only */
+    if (Poolno > 0) { 
+      /* A specific pool (macro DB_IO_DEF sorted out some pointers) */
+      int Ntables = *ntbl;
+      int all_tables = (Ntables < 0 || (table_len > 0 && table && *table == '*'));
+
+      if (all_tables) {
+	int len = 0;
+	int jtbl, ntables = ppool->ntables;
+	int nt = 0;
+
+	for (jtbl=0; jtbl<ntables; jtbl++) {
+	  IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	  if (!pdb->is_readonly && Take_INCORE(ptbl)) {
+	    len += strlen(ptbl->tblname) + 1;
+	    nt++;
+	  }
+	  else {
+	    Free_INCORE(ptbl, io_keep_incore);
+	  }
+	}
+
+	if (len > 0) { /* There is indeed something to write */
+	  char *pt = NULL;
+	  len += 2;
+	  ALLOC(pt, len);
+	  strcpy(pt,"/");
+	  for (jtbl=0; jtbl<ntables; jtbl++) {
+	    IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	    if (Take_INCORE(ptbl)) {
+	      strcat(pt,ptbl->tblname);
+	      strcat(pt,"/");
+	    }
+	  }
+	  /* Call recursively */
+	  newio_flush32_(handle, &Poolno, enforce_to_disk, &nt, pt, &retcode, len);
+	  FREE(pt);
+	}
+      }
+      else { /* List of tables only */
+	DECL_FTN_CHAR(table);
+	int len = 0;
+	int n, Ntables = *ntbl;
+	int j, m = Ntables;
+	char **t = NULL;
+	int *jlist = NULL;
+
+	ALLOC_FTN_CHAR(table);
+	t = TableList(p_table, m, &Ntables);
+
+	if (io_verbose == newio_myproc) {
+	  fprintf(stderr,
+"newio_flush32_(*handle=%d, *poolno=%d, *ef2d=%d, *ntbl=%d, table[]='%s', *rc=N/A, table_len=%d)\n",
+		*handle, *poolno, ef2d, *ntbl, p_table, table_len);
+	  xl__trbk_();
+	  fprintf(stderr,"newio_flush32_(): p_table='%s', m=%d, Ntables=%d\n",p_table,m,Ntables);
+	  for (j=0; j<Ntables; j++) {
+	    fprintf(stderr,"<t[%d]='%s'\n", j, t[j] ? t[j] : NIL);
+	  }
+	}
+
+	ALLOC(jlist, Ntables);
+	n = Ntables;
+	for (j=0; j<Ntables; j++) {
+	  int jtbl = LocateTable(t[j], ppool, 0);
+	  if (jtbl >= 0) jlist[j] = jtbl;
+	  else n--;
+	} /* for (j=0; j<Ntables; j++) */
+	Ntables = n;
+
+	if (io_verbose == newio_myproc) {
+	  fprintf(stderr,"newio_flush32_(): p_table='%s', m=%d, Ntables=%d\n",p_table,m,Ntables);
+	  for (j=0; j<Ntables; j++) {
+	    int jtbl = jlist[j];
+	    IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	    fprintf(stderr,">t[%d]='%s', data bytes=%d\n", j, ptbl->tblname, ptbl->n_incore);
+	  }
+	  TableDump(stderr, ppool, NULL);
+	}
+
+	for (j=0; j<Ntables; j++) {
+	  int jtbl = jlist[j];
+	  IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	  if (!pdb->is_readonly && Take_INCORE(ptbl)) {
+	    len += strlen(ptbl->tblname) + 5;
+	  }
+	  else {
+	    Free_INCORE(ptbl, io_keep_incore);
+	  }
+	} /* for (j=0; j<Ntables; j++) */
+
+	if (len > 0) { /* There is indeed something to write */
+	  char *qtarfile = GetQTARFILE(Handle, Poolno, ppool, NULL);
+	  FILE *fp = NULL;
+	  char *cmd = NULL;
+	  len += strlen(qtarfile) + 50;
+	  /* Make command */
+	  ALLOC(cmd, len);
+	  sprintf(cmd, "qtar -s -u -M -b %d -f %s", io_bufsize, qtarfile); 
+	  for (j=0; j<Ntables; j++) {
+	    int jtbl = jlist[j];
+	    IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	    if (Take_INCORE(ptbl)) {
+	      strcat(cmd, " -m ");
+	      strcat(cmd, ptbl->tblname);
+	    }
+	  } /* for (j=0; j<Ntables; j++) */
+
+	  /* Do write */
+
+	  FREE(ppool->last_write_cmd);
+	  ppool->last_write_cmd = STRDUP(cmd);
+
+	  if (io_verbose == newio_myproc) {
+	    fprintf(stderr,"Executing: popen(%s, w)\n",cmd);
+	    xl__trbk_();
+	  }
+
+	  fp = popen(cmd, "w");
+	  if (fp) {
+	    int fd = fileno(fp);
+	    for (j=0; j<Ntables; j++) {
+	      int jtbl = jlist[j];
+	      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	      if (Take_INCORE(ptbl)) {
+		ll_t dim[DIMLEN/WORDLEN];
+		int nwrite;
+		if (!ptbl->incore && ptbl->n_incore == 0) { /* write_empty_files -situation */
+		  Alloc_INCORE(ptbl, 0, WORDLEN); /* Guarantees one WORDLEN-bytes allocation for "nbytes" */
+		}
+		dim[0] = ptbl->n_incore; /* no. of DATA bytes */
+		dim[1] = ptbl->nrows; /* not up to date yet; to be done */
+		dim[2] = ptbl->ncols; /* not up to date yet; to be done */
+		memcpy(ptbl->incore, dim, DIMLEN);
+		nwrite = WriteData32(fd, ptbl->incore, DIMLEN + ptbl->n_incore); /* All in one go */
+		if (nwrite != DIMLEN + ptbl->n_incore) {
+		  newio_Error32("newio_flush32_: Unable to write data",
+				ptbl->tblname, "(length+data)", "(all)", 
+				Handle, Poolno, DIMLEN + ptbl->n_incore, nwrite,
+				this_io_method,
+				"newio_flush32_: QTAR-cmd='%s'", cmd);
+		}
+		else {
+		  ptbl->known_size = ptbl->n_incore;
+		  Free_INCORE(ptbl, io_keep_incore);
+		} /* if (nwrite != DIMLEN + ptbl->n_incore) */
+	      } /* if (Take_INCORE(ptbl)) */
+	    } /* for (j=0; j<Ntables; j++) */
+	    pclose(fp);
+	    ppool->file_exist = 1;
+	  }
+	  else {
+	    newio_Error32("newio_flush32_: Unable open write-pipe",
+			  qtarfile, "(QTAR)", "(write-pipe)", Handle, Poolno, 0, errno,
+			  this_io_method,
+			  "newio_flush32_: QTAR-cmd='%s'", cmd);
+	  }
+	  FREE(cmd);
+	} /* if (len > 0) */
+
+	FREE(jlist);
+	for (j=0; j<m; j++) FREE(t[j]);
+	FREE(t);
+	FREE_FTN_CHAR(table);
+      }
+    }
+    else {
+      /* All pools (that contain something to flush) */
+      int jpool, npools = pdb->npools;
+      for (jpool=0; jpool<npools; jpool++) {
+	ppool = &pdb->pool[jpool];
+	Poolno = ppool->poolno;
+	/* Call recursively (one pool at a time) to simplify coding */
+	newio_flush32_(handle, &Poolno, enforce_to_disk, ntbl, table, &retcode, table_len);
+      } /* for (jpool=0; jpool<npools; jpool++) */
+    }
+  }
+
+ finish:
+  *rc = retcode;
+}
+
+
+PUBLIC void
+newio_end32_(const int *handle, int *rc)
+{
+  const char *all = "*";
+  const int all_len = 1;
+  const int Poolno = -1;
+  const int Ntables = -1;
+  const int Enforce_to_disk = 1; /* A must */
+  int Retcode = 0;
+  DRHOOK_START(newio_end32_);
+  /* Finish all outstanding I/O (except for io_method==4) */
+  newio_flush32_(handle, &Poolno, &Enforce_to_disk, &Ntables, all, &Retcode, all_len);
+  (void) end_IO_struct(*handle);
+  /* for now */
+  DRHOOK_END(0);
+  *rc = 0;
+}
+
+
+PUBLIC void
+newio_get_incore32_(const int *handle,
+		    const int *poolno, /* must be a specific pool ; -1 doesn't do */
+		    char data[],       /* data area where incore data will be memcpy'ed to */
+		    const int *nbytes, /* size of supplied data bytes array */
+		    const int *reset_updated_flag, /* if == 1 --> reset updated-flag to 0 */
+		    const char *table, /* particular table name (both "@table" or "table" do) */
+		    int *rc
+		    /* Hidden argument */
+		    , int table_len)
+{
+  int retcode = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  DB_IO_DEF(Handle, Poolno);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_get_incore32_);
+
+  if (this_io_method == 0) goto finish;
+
+  if (pdb->in_use && this_io_method == 4) { /* horizontal concat */
+    if (Poolno > 0) { 
+      /* A specific pool */
+      int Nbytes = *nbytes;
+      int jtbl;
+      char *p;
+      DECL_FTN_CHAR(table);
+
+      ALLOC_FTN_CHAR(table);
+      p = p_table;
+      if (*p == '@') p++;
+      
+      jtbl = LocateTable(p, ppool, 0);
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	int size = ptbl->n_incore;
+	if (ptbl->incore && Nbytes >= size) { /* ok : copy data to user-area */
+	  memcpy(data, ptbl->incore + DIMLEN, size);
+	  /* Data fed back to application or I/O-level ==> updated-flag reset */
+	  if (*reset_updated_flag) ptbl->updated = 0;
+	  retcode = size;
+	}
+	else { /* Data not copied ; could be zero-length, too */
+	  retcode = -size;
+	}
+      } /* if (jtbl >= 0) */  
+
+      FREE_FTN_CHAR(table);
+    } /* if (Poolno > 0) */
+  }
+
+ finish:
+  DRHOOK_END(retcode >= 0 ? retcode : 0);
+  *rc = retcode;
+}
+
+
+PUBLIC void
+newio_put_incore32_(const int *handle,
+		    const int *poolno, /* must be a specific pool ; -1 doesn't do */
+		    const char data[], /* data area from which data is copied into the incore */
+		    const int *nbytes, /* amount of data */
+		    const int *nrows,  /* no. of rows in data-matrix */
+		    const int *ncols,  /* no. of cols in data-matrix */
+		    const char *table, /* particular table name (both "@table" or "table" do) */
+		    int *rc
+		    /* Hidden argument */
+		    , int table_len)
+{
+  int retcode = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  DB_IO_DEF(Handle, Poolno);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_put_incore32_);
+
+  if (io_verbose == newio_myproc) {
+    fprintf(stderr,
+	    "newio_put_incore32_(h=%d, p=%d, d[]=%p, nb=%d, nr=%d, nc=%d, tbl_len=%d)\n",
+	    *handle, *poolno, data, *nbytes, *nrows, *ncols, table_len);
+    fprintf(stderr,"Handle=%d, Poolno=%d, this_io_method=%d, pdb=%p\n",
+	    Handle, Poolno, this_io_method, pdb);
+  }
+
+  if (this_io_method == 0) goto finish;
+
+  if ((pdb->in_use || (!pdb->in_use && !pdb->is_new)) && 
+      this_io_method == 4) { /* horizontal concat */
+    if (Poolno > 0) { 
+      /* A specific pool */
+      int Nbytes = *nbytes;
+      int jtbl;
+      char *p;
+      DECL_FTN_CHAR(table);
+
+      ALLOC_FTN_CHAR(table);
+      p = p_table;
+      if (*p == '@') p++;
+      
+      jtbl = LocateTable(p, ppool, 1);
+      if (io_verbose == newio_myproc) {
+	fprintf(stderr, "--> For table='%s', jtbl=%d, Nbytes=%d\n", p, jtbl, Nbytes);
+      }
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	if (Nbytes >= 0) { /* ok : copy data from user-area */
+	  ll_t dim[DIMLEN/WORDLEN];
+	  Alloc_INCORE(ptbl, Nbytes, WORDLEN);
+	  dim[0] = ptbl->n_incore; /* no. of DATA bytes */
+	  dim[1] = ptbl->nrows = *nrows;
+	  dim[2] = ptbl->ncols = *ncols;
+	  memcpy(ptbl->incore, dim, DIMLEN);
+	  if (Nbytes > 0) memcpy(ptbl->incore + DIMLEN, data, Nbytes);
+	  ptbl->known_size = Nbytes;
+	  ptbl->updated = 0;
+	  retcode = Nbytes;
+	}
+	else { /* Soft error */
+	  Alloc_INCORE(ptbl, 0, WORDLEN);
+	  retcode = -Nbytes;
+	}
+      } /* if (jtbl >= 0) */  
+      if (io_verbose == newio_myproc) {
+	fprintf(stderr, "<-- Out for table='%s', jtbl=%d, retcode=%d\n", p, jtbl, retcode);
+      }
+
+      FREE_FTN_CHAR(table);
+      pdb->in_use = 1;
+    } /* if (Poolno > 0) */
+  }
+
+ finish:
+  DRHOOK_END(retcode >= 0 ? retcode : 0);
+  *rc = retcode;
+}
+
+
+PUBLIC void /* Just in case we need to know this from Fortran */
+newio_dimlen32_(int *rc)
+{
+  *rc = DIMLEN; /* no. of bytes in the header of the incore-array before data actually starts */
+}
+
+
+PUBLIC void
+newio_status_incore32_(const int *handle,
+		       const int *poolno,  /* must be a specific pool ; -1 doesn't do */
+		             int status[], /* status[]-array */
+		       const int *nstatus, /* no. of words in status[]-array */
+		       const char *table, /* particular table name (both "@table" or "table" do) */
+		             int *rc       /* no. of words filled/returned */
+		       /* Hidden argument */
+		       , int table_len)
+{
+  /* status[0] (fortran index=1) : no. of data bytes */
+  /* status[1] (fortran index=2) : no. of rows */
+  /* status[2] (fortran index=3) : no. of cols */
+  /* status[3] (fortran index=4) : has been updated */
+
+  int retcode = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  DB_IO_DEF(Handle, Poolno);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_status_incore32_);
+
+  if (this_io_method == 0) goto finish;
+
+  if (pdb->in_use && this_io_method == 4) { /* horizontal concat */
+    if (Poolno > 0) { 
+      /* A specific pool */
+      int Nstatus = *nstatus;
+      int jtbl;
+      char *p;
+      DECL_FTN_CHAR(table);
+
+      ALLOC_FTN_CHAR(table);
+      p = p_table;
+      if (*p == '@') p++;
+
+      jtbl = LocateTable(p, ppool, 0);
+      if (jtbl >= 0) {
+	IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+	if (Nstatus >= 1) { status[0] = ptbl->n_incore; retcode++; }
+	if (Nstatus >= 2) { status[1] = ptbl->nrows; retcode++; }
+	if (Nstatus >= 3) { status[2] = ptbl->ncols; retcode++; }
+	if (Nstatus >= 4) { status[3] = ptbl->updated; retcode++; }
+      } /* if (jtbl >= 0) */  
+
+      FREE_FTN_CHAR(table);
+    } /* if (Poolno > 0) */
+  }
+  
+ finish:
+  DRHOOK_END(0);
+  *rc = retcode;
+}
+
+
+PUBLIC void
+newio_release_pool32_(const int *handle,
+		      const int *poolno,  /* must be a specific pool ; -1 doesn't do */
+		      int *rc)
+{
+  int retcode = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  DB_IO_DEF(Handle, Poolno);
+  int this_io_method = pdb ? pdb->io_method : 0;
+  DRHOOK_START(newio_release_pool32_);
+
+  if (this_io_method == 0) goto finish;
+
+  if (ppool) {
+    int jtbl;
+    int maxtables = ppool->maxtables;
+    for (jtbl=0; jtbl<maxtables; jtbl++) {
+      IO_tbl_t *ptbl = &ppool->tbl[jtbl];
+      FREE(ptbl->tblname);
+      ptbl->known_size = -1;
+      /* incore items */
+      ptbl->open_mode = NEWIO_OPEN_UNDEF;
+      FREE(ptbl->file);
+      Free_INCORE(ptbl, 0);
+      FREE(ptbl->read_cmd);
+      FREE(ptbl->delete_cmd);
+      ptbl->mypool = NULL;
+    } /* for (jtbl=0; jtbl<maxtables; jtbl++) */
+    FREE(ppool->tbl);
+    ppool->maxtables = 0;
+    ppool->ntables = 0;
+    ppool->poolno = 0;
+    FREE(ppool->file);
+    ppool->file_exist = 0;
+    FREE(ppool->last_write_cmd);
+    ppool->mydb = NULL;
+  }
+    
+ finish:
+  DRHOOK_END(0);
+  *rc = retcode;
+}
diff --git a/odb/src/aux/odb2mysql.c b/odb/src/aux/odb2mysql.c
new file mode 100644
index 0000000..98c0982
--- /dev/null
+++ b/odb/src/aux/odb2mysql.c
@@ -0,0 +1,131 @@
+#ifndef HAS_MYSQL
+void dummy_odb2mysql() {}
+#else
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include "mysql.h"
+
+#include "alloc.h"
+
+void codb2mysql_do_(unsigned long long int *connid,
+		    const char *query,
+		    int *retcode
+		    /* Hidden arguments */
+		    , int query_len
+		    )
+{
+  DECL_FTN_CHAR(query);
+  MYSQL *conn = (MYSQL *)(*connid);
+  static int first_time = 1;
+  if (first_time) {
+    fprintf(stderr,"do(): connection id=%llu %p\n",*connid,conn);
+    first_time = 0;
+  }
+
+  *retcode = 0;
+  ALLOC_FTN_CHAR(query);
+  {
+    int state = mysql_query(conn, p_query);
+    if (state != 0) {
+      fprintf(stderr,mysql_error(conn));
+      *retcode = -1;
+      goto finish;
+    }
+  }
+ finish:
+  FREE_FTN_CHAR(query);
+}
+
+void codb2mysql_close_(unsigned long long int *connid,
+		       int *retcode)
+{
+  MYSQL *conn = (MYSQL *)(*connid);
+  fprintf(stderr,"close(): connection id=%llu %p\n",*connid,conn);
+  *retcode = 0;
+  mysql_close(conn);
+}
+
+void codb2mysql_open_(const char *dbname,
+		      const char *mode,
+		      const char *server,
+		      const char *user,
+		      const char *password,
+		      unsigned long long int *connid
+		      /* Hidden arguments */
+		      , int dbname_len
+		      , int mode_len
+		      , int server_len
+		      , int user_len
+		      , int password_len
+		      )
+{
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(mode);
+  DECL_FTN_CHAR(server);
+  DECL_FTN_CHAR(user);
+  DECL_FTN_CHAR(password);
+
+  ALLOC_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(mode);
+  ALLOC_FTN_CHAR(server);
+  ALLOC_FTN_CHAR(user);
+  ALLOC_FTN_CHAR(password);
+
+  *connid = -1;
+
+  {
+    MYSQL *conn, mysql;
+
+    mysql_init(&mysql);
+    conn = mysql_real_connect(&mysql,
+			      p_server, p_user, NULL,
+			      p_dbname, 0, NULL, 0
+			      );
+
+    if (conn == NULL) {
+      fprintf(stderr,mysql_error(&mysql));
+      goto finish;
+    }
+
+    if (strcmp(p_mode,"NEW") == 0 || strcmp(p_mode,"new") == 0) {
+      int state;
+      char *cmd;
+      int cmdlen = strlen(p_dbname) + 100;
+      ALLOC(cmd, cmdlen);
+      sprintf(cmd, "drop database if exists %s", p_dbname);
+      state = mysql_query(conn, cmd);
+      if (state != 0) {
+	fprintf(stderr,mysql_error(conn));
+	goto finish;
+      }
+      FREE(cmd);
+      ALLOC(cmd, cmdlen);
+      sprintf(cmd, "create database %s", p_dbname);
+      state = mysql_query(conn, cmd);
+      if (state != 0) {
+	fprintf(stderr,mysql_error(conn));
+	goto finish;
+      }
+      FREE(cmd);
+    }
+    
+    *connid = (unsigned long long int) conn;
+    fprintf(stderr,"open(): connection id=%llu %p\n",*connid,conn);
+   }
+
+ finish:
+
+  FREE_FTN_CHAR(dbname);
+  FREE_FTN_CHAR(mode);
+  FREE_FTN_CHAR(server);
+  FREE_FTN_CHAR(user);
+  FREE_FTN_CHAR(password);
+}
+		      
+		      
+
+
+#endif
diff --git a/odb/src/aux/odbcrc.c b/odb/src/aux/odbcrc.c
new file mode 100644
index 0000000..66462b8
--- /dev/null
+++ b/odb/src/aux/odbcrc.c
@@ -0,0 +1,166 @@
+
+/* This is a near replica of ifsaux/support/crc.c
+   except that it does not have the unrelated ecmwf_transfer function.
+   Used by ODB/SQL-compiler, too.
+   To avoid name-conflict with crc.c all functions are prepended with 
+   ODB_ (C-callables) or fodb_ (Fortran-callables)
+*/
+
+/* odbcrc.c : in fact equivalent to Unix cksum (when crc32) */
+/* Calculates 32-bit  Cyclic Redundancy Check as in Unix cksum command */
+/* Also calculates 64-bit  Cyclic Redundancy Check */
+
+/* Sami Saarinen, 17-Feb-2005 : crc32       */
+/*                24-Jun-2005 : Added crc64 */
+/*                29-Dec-2005 : Removed static in front of C-callable cksum32() */
+/*                29-Dec-2005 : Length argument for crc64 now 64-bit int */
+/*                27-Mar-2006 : Available as odbcrc.o for libodb.a & libodbsqlcompiler.a */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "odbcrc.h"
+
+static const unsigned int crctab[256] =
+{
+  0x0,
+  0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
+  0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
+  0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
+  0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
+  0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
+  0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
+  0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
+  0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
+  0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
+  0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
+  0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
+  0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
+  0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
+  0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
+  0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
+  0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
+  0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
+  0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
+  0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
+  0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
+  0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
+  0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
+  0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
+  0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
+  0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
+  0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
+  0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
+  0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
+  0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
+  0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
+  0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
+  0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
+  0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
+  0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
+  0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
+  0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
+  0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
+  0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
+  0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
+  0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
+  0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
+  0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
+  0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
+  0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
+  0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
+  0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
+  0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
+  0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
+  0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
+  0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
+  0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
+};
+
+unsigned int 
+ODB_cksum32(const char *buf, int nbuf, unsigned int nCRC)
+{
+  while (nbuf--) {
+    nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ *(buf++)) & 0xFF];
+  }
+  return nCRC;
+}
+
+unsigned long long int
+ODB_cksum64(const char *buf, long long int nbuf, unsigned long long int nCRC)
+{
+  unsigned char c;
+  while (nbuf--) {
+    c = ((unsigned char)nCRC ^ *(buf++)) & 0xFF;
+    nCRC >>= 8;
+    nCRC ^= (unsigned long long int)crctab[c] << 32;
+  }
+  return nCRC;
+}
+
+unsigned int 
+ODB_pp_cksum32(int nbuf, unsigned int nCRC)
+{
+    while (nbuf > 0) {
+	nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ nbuf) & 0xFF];
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFF;
+    return nCRC;
+}
+
+unsigned int 
+ODB_pp_cksum32but64len(long long int nbuf, unsigned int nCRC)
+{
+    while (nbuf > 0) {
+	nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ nbuf) & 0xFF];
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFF;
+    return nCRC;
+}
+
+unsigned long long int 
+ODB_pp_cksum64(long long int nbuf, unsigned long long int nCRC)
+{
+    while (nbuf > 0) {
+	unsigned char c = ((unsigned char)nCRC ^ nbuf) & 0xFF;
+	nCRC >>= 8;
+	nCRC ^= (unsigned long long int)crctab[c] << 32;
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFFFFFFFFFFull;
+    return nCRC;
+}
+
+/* Fortran callable */
+
+void 
+fodb_crc32_(const void *vbuf, const int *pnbuf, 
+	    unsigned int *pnCRC /* Note: An in & out -variable */)
+{
+  if (vbuf && pnbuf && *pnbuf > 0 && pnCRC) {
+    const char *buf = vbuf;
+    unsigned int nCRC = *pnCRC;
+    int nbuf = *pnbuf;
+    /* checksum the data */
+    nCRC = ODB_cksum32(buf, nbuf, nCRC);
+    /* checksum the length */
+    *pnCRC = ODB_pp_cksum32(nbuf, nCRC);
+  }
+}
+
+void 
+fodb_crc64_(const void *vbuf, const long long int *pnbuf, 
+	    unsigned long long int *pnCRC /* Note: An in & out -variable */)
+{
+  if (vbuf && pnbuf && *pnbuf > 0 && pnCRC) {
+    const char *buf = vbuf;
+    unsigned long long int nCRC = *pnCRC;
+    long long int nbuf = *pnbuf;
+    /* checksum the data */
+    nCRC = ODB_cksum64(buf, nbuf, nCRC);
+    /* checksum the length */
+    *pnCRC = ODB_pp_cksum64(nbuf, nCRC);
+  }
+}
diff --git a/odb/src/aux/odbcs_conf.c b/odb/src/aux/odbcs_conf.c
new file mode 100644
index 0000000..6f354ee
--- /dev/null
+++ b/odb/src/aux/odbcs_conf.c
@@ -0,0 +1,491 @@
+/* odbcs_conf.c */
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+#include "odbcsdefs.h"
+#include "cmaio.h"
+
+/* 
+
+   Reads ODB client/server configuration file(s) in the following order :
+   
+   $ODB_SYSPATH/odbcs.conf
+   ~/odbcs.conf i.e. $HOME/odbcs.conf
+   ./odbcs.conf
+   $ODBCS_CONF (= environment variable pointing to a file name)
+
+   Each successive read overrides any previous definitions.
+
+   Author: Sami Saarinen, ECMWF, 10-Dec-2007
+
+*/
+
+/* 
+
+   Format of the odbcs.conf -files : each line contains colon (:) separated entries as follows:
+
+   Please note that the default separator ':' could be changed for every input line as long as it doesn't exits
+   in any of the data fields. If you want to change it, just supply required separator as the first character
+   for each line.
+
+   :<hostname>:<username>:<port>:<timeout>:<$ARCH>:<$CPU_TYPE>:<$OBJECT_MODE>:<$ODB_ARCH>:<$ODB_VERSION>:<$ODB_COMPDIR>:<$ODB_DIR>:<$ODB_ROOT>:
+        0           1        2        3       4         5              6           7           8              9              10         11
+
+   where the fields 0 to 11 are :
+
+   0 <hostname>     = hostname to connect to
+                      The * supplies default values for any non-specified machines.
+                      You can also supply any unix-wildcard f.ex. ^bee* would cover all hostnames starting with bee
+
+   1 <username>     = username to be used to /usr/bin/rsh into this hostname
+                      If left empty, then use the same username where the client is current logged-on
+
+   2 <port>         = Port number to connect the server with
+                      When left empty, then port id is calculated from the client user id (uid) modulo 10,000 plus 10,000
+
+   3 <timeout>      = A timeout imposed with this host.
+                      The default is TIMEOUT_DEFAULT seconds.
+
+   4 <$ARCH>        = ARCH'itecture of the hostname
+                      If not given, then the default is determined (guessed) by using either 'arch' or 'uname' commands
+
+   5 <$CPU_TYPE>    = CPU_TYPE of the hostname
+                      If not given, then the default is figured out from the $ARCH
+
+   6 <$OBJECT_MODE> = OBJECT_MODE of the hostname ; either 32 or 64
+                      If not given, then the default is assumed to be 32.
+
+   7 <$ODB_ARCH>    = ODB-architecture ; usually the same as $ARCH
+                      If not defined, then the same as $ARCH
+
+   8 <$ODB_VERSION> = ODB-version
+                      If not given, then use the same as on the client.
+		      And is still not defined, set to "current".
+
+   9 <$ODB_COMPDIR> = ODB f90 compiler used
+                      If not given, then the default is figured out from the $ARCH
+
+  10 <$ODB_DIR>     = ODB installation base directory e.g. /usr/local/apps/odb
+                      If not given, then use either the default (supplied via hostname=*) or as on the client
+
+  11 <$ODB_ROOT>    = ODB installation version base root directory e.g. /usr/local/apps/odb/current/pgf90/ILP32
+                      If not given, then set to $ODB_DIR/$ODB_VERSION/$ODB_COMPDIR/{ILP|LP}{$OBJECT_MODE}
+		      where ILP32 used for $OBJECT_MODE = 32, and LP64 for $OBJECT_MODE = 64
+
+*/
+
+
+
+#define GUESS "_UNDEF_"
+#define IS_GUESS(s) (STRLEN(s) == 0 || strequ(s,GUESS))
+
+
+PRIVATE const char *fldname[] = {
+  "hostname",
+  "username",
+  "port (int)",
+  "timeout (int)",
+  "arch",
+  "cpu_type",
+  "object_mode (int)",
+  "odb_arch",
+  "odb_version",
+  "odb_compdir",
+  "odb_dir",
+  "odb_root",
+  NULL
+};
+
+
+PRIVATE odbcs_t *the_default = NULL;
+PRIVATE odbcs_t *rock_bottom = NULL;
+
+
+PRIVATE odbcs_t *
+conf_read(const char *file, odbcs_t *conf)
+{
+  FILE *fp = NULL;
+  int iounit = -1;
+  int iret = 0;
+  int perror_onoff = -1;
+  const int on = 1;
+  const int off = 0;
+  odbcs_t *pc = rock_bottom;
+
+  if (!pc) {
+    int len;
+    char *s;
+    const char fmt_star[] = ":*:::%d:";
+    CALLOC(pc, 1);
+    len = STRLEN(fmt_star) + 20;
+    ALLOC(s, len);
+    snprintf(s,len,fmt_star,TIMEOUT_DEFAULT); /* Supply any-host, no username, no port, timeout */
+    pc->line = s;
+    rock_bottom = conf = the_default = pc;
+  }
+  else
+    pc = conf;
+
+  cma_set_perror_(&off, &perror_onoff); /* temporarely disable perror() messages */
+  cma_open_(&iounit, file, "r", &iret, STRLEN(file), 1);
+  fp = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+  if (fp) {
+    char line[ODBCS_MAXLINE];
+
+    while (pc && pc->next) pc = pc->next;
+
+    while (fgets(line, sizeof(line), fp)) {
+      char *nl = strchr(line,'\n');
+      char *s = line;
+      while (*s && isspace(*s)) ++s;
+      if (nl) *nl = '\0';
+      /* if first 2 chars are ":<", then this must be some example line --> skip */
+      if (STRLEN(s) > 0 && !strnequ(s,":<",2)) {
+	odbcs_t *pc_prev = pc;
+	odbcs_t *next = NULL;
+	CALLOC(next,1);
+	next->line = STRDUP(s);
+	pc->next = next;
+	rock_bottom = pc = next;
+	pc->prev = pc_prev;
+      }
+    } /* while (fgets(line, sizeof(line), fp)) */
+
+    cma_close_(&iounit, &iret);
+  }
+  if (perror_onoff == on) { /* switch perror() output back on */
+    cma_set_perror_(&on, &perror_onoff);
+  }
+  return conf;
+}
+
+
+PRIVATE char *
+trim_token(const char *tin, char delim, int *skipchars)
+{
+  char *s = NULL;
+  char *talloc = STRDUP(tin);
+  char *t = talloc;
+  char *next_delim = strchr(t, delim);
+  if (next_delim) {
+    char *start;
+    int len;
+    *next_delim = '\0';
+    *skipchars = STRLEN(talloc) + 1;
+    while (*t && isspace(*t)) ++t;
+    start = t;
+    while (*t && !isspace(*t)) ++t;
+    len = t - start;
+    ALLOC(s,len+1);
+    strncpy(s, start, len);
+    s[len] = '\0';
+  }
+  else {
+    *skipchars = 0;
+    s = STRDUP("");
+  }
+  FREE(talloc);
+  return s;
+}
+
+
+PRIVATE odbcs_t *
+conf_make(odbcs_t *conf)
+{
+  odbcs_t *pc = conf;
+  while (pc) {
+    char *token = pc->line;
+    char delim = *token++;
+    int token_num = 0;
+    do {
+      int num;
+      char *env;
+      char *s = NULL;
+      int len;
+      s = trim_token(token, delim, &len);
+      token += len;
+
+      switch (token_num) {
+
+      case 0: /* hostname */
+	pc->hostname = STRDUP(s);
+	if (strequ(pc->hostname,"*")) the_default = pc;
+	break;
+
+      case 1: /* username */
+	if (STRLEN(s) == 0) {
+	  char *env = getenv("USER");
+	  if (!env) env = getenv("LOGNAME");
+	  pc->username = env ? STRDUP(env) : STRDUP("unknown_user");
+	}
+	else
+	  pc->username = STRDUP(s);
+	break;
+
+      case 2: /* port */
+	num = atoi(s);
+	pc->port = (num < MIN_PORT || num > MAX_PORT) ? PORT_DEFAULT : num;
+	break;
+
+      case 3: /* timeout */
+	num = atoi(s);
+	pc->timeout = (num < 0) ? TIMEOUT_DEFAULT : num;
+	break;
+
+      case 4: /* $ARCH */
+	pc->arch = (STRLEN(s) == 0) ? STRDUP(GUESS) : STRDUP(s);
+	break;
+
+      case 5: /* $CPU_TYPE */
+	pc->cpu_type = (STRLEN(s) == 0) ? STRDUP(GUESS) : STRDUP(s);
+	break;
+
+      case 6: /* $OBJECT_MODE */
+	num = atoi(s);
+	pc->object_mode = (num == 32 || num == 64) ? num : 32;
+	break;
+
+      case 7: /* $ODB_ARCH */
+	pc->odb_arch = (STRLEN(s) == 0) ? STRDUP(pc->arch) : STRDUP(s);
+	break;
+
+      case 8: /* $ODB_VERSION */
+	env = (STRLEN(s) == 0) ? getenv("ODB_VERSION") : s;
+	pc->odb_version = (STRLEN(env) == 0) ? STRDUP("current") : STRDUP(env);
+	break;
+
+      case 9: /* $ODB_COMPDIR */
+	pc->odb_compdir = (STRLEN(s) == 0) ? STRDUP(GUESS) : STRDUP(s);
+	break;
+
+      case 10: /* $ODB_DIR */
+	pc->odb_dir = (STRLEN(s) == 0) ? STRDUP(GUESS) : STRDUP(s);
+	break;
+
+      case 11: /* $ODB_ROOT */
+	pc->odb_root = (STRLEN(s) == 0) ? STRDUP(GUESS) : STRDUP(s);
+	break;
+      } /* switch (token_num) */
+
+      FREE(s);
+    } while (++token_num <= 11);
+
+    FREE(pc->line);
+    pc = pc->next;
+  }
+
+  /* Resolve missing items in the default */
+
+  pc = the_default;
+  if (pc) {
+    char *env;
+
+    if (IS_GUESS(pc->arch)) {
+      env = getenv("ARCH");
+      pc->arch = env ? STRDUP(env) : STRDUP(GUESS);
+    }
+
+    if (IS_GUESS(pc->cpu_type)) {
+      env = getenv("CPU_TYPE");
+      FREE(pc->cpu_type);
+      pc->cpu_type = env ? STRDUP(env) : STRDUP(GUESS);
+    }
+    
+    if (IS_GUESS(pc->odb_arch)) {
+      env = getenv("ODB_ARCH");
+      FREE(pc->odb_arch);
+      if (env) {
+	pc->odb_arch = STRDUP(env);
+      }
+      else if (STRLEN(pc->arch) > 0) {
+	pc->odb_arch = STRDUP(pc->arch);
+      }
+      else {
+	pc->odb_arch = STRDUP(GUESS);
+      }
+    }
+
+    if (IS_GUESS(pc->odb_compdir)) {
+      env = getenv("ODB_COMPDIR");
+      FREE(pc->odb_compdir);
+      pc->odb_compdir = env ? STRDUP(env) : STRDUP(GUESS);
+    }
+
+    if (IS_GUESS(pc->odb_dir)) {
+      env = getenv("ODB_DIR");
+      FREE(pc->odb_dir);
+      pc->odb_dir = env ? STRDUP(env) : STRDUP(GUESS);
+    }
+
+    if (IS_GUESS(pc->odb_root)) {
+      env = getenv("ODB_ROOT");
+      FREE(pc->odb_root);
+      pc->odb_root = env ? STRDUP(env) : STRDUP(GUESS);
+    }  
+
+  } /* if (pc) */
+
+  /* 2nd pass : try to resolve as many GUESS'es as possible */
+
+  pc = conf;
+  while (pc) {
+
+    if (pc != the_default) {
+
+      if (IS_GUESS(pc->arch)) {
+	FREE(pc->arch);
+	pc->arch = STRDUP(the_default->arch);
+      }
+
+      if (IS_GUESS(pc->odb_arch)) {
+	const char *default_odb_arch = (STRLEN(pc->arch) > 0) ? pc->arch : the_default->arch;
+	FREE(pc->odb_arch);
+	pc->odb_arch = STRDUP(default_odb_arch);
+      }
+
+      if (IS_GUESS(pc->odb_dir)) {
+	FREE(pc->odb_dir);
+	pc->odb_dir = STRDUP(the_default->odb_dir);
+      }
+    } /* if (pc != the_default) */
+
+    /* In the following the "pc" could also point to "the_default" */
+
+    if (IS_GUESS(pc->odb_root) && !IS_GUESS(pc->odb_dir) && !IS_GUESS(pc->odb_compdir)) {
+      char *s = pc->odb_root;
+      int len = STRLEN(pc->odb_dir) + STRLEN(pc->odb_version) + STRLEN(pc->odb_compdir) + 30;
+      ALLOC(pc->odb_root, len);
+      snprintf(pc->odb_root, len, "%s/%s/%s/%s%d",
+	       pc->odb_dir, pc->odb_version, pc->odb_compdir,
+	       (pc->object_mode == 32) ? "ILP" : "LP",
+	       pc->object_mode);
+      FREE(s);
+    }
+    
+    if (!pc->odb_binpath) {
+      if (!IS_GUESS(pc->odb_root)) {
+	int len = STRLEN(pc->odb_root) + STRLEN("/bin") + 1;
+	ALLOC(pc->odb_binpath, len);
+	snprintf(pc->odb_binpath, len, "%s/bin", pc->odb_root);
+      }
+      else {
+	char *env = getenv("ODB_BINPATH");
+	pc->odb_binpath = env ? STRDUP(env) : STRDUP(GUESS);
+      }
+    }
+
+    pc = pc->next;
+  } /* while (pc) */
+
+  return conf;
+}
+
+
+PRIVATE int
+find_any(const char *s, const char *delims)
+{
+  int found = 0;
+  if (s && delims) {
+    while (*delims) {
+      if (strchr(s,*delims)) {
+	found = 1;
+	break;
+      }
+      ++delims;
+    }
+  }
+  return found;
+}
+
+
+PUBLIC const odbcs_t *
+odbcs_conf_match(const char *host, odbcs_t *conf, char **truehostname)
+{
+  const odbcs_t *pc = rock_bottom;
+  char *THEhost = NULL;
+  if (strequ(host, "localhost")) {
+    char thishost[255];
+    gethostname(thishost,sizeof(thishost));
+    THEhost = STRDUP(thishost);
+  }
+  else
+    THEhost = STRDUP(host);
+  while (pc) {
+    /* Try exact match first */
+    if (strcaseequ(pc->hostname, THEhost)) goto finish;
+    /* Then a wildcard match */
+    if (find_any(pc->hostname,"^*[]{}|(),$") &&
+	ODB_Common_StrEqual(pc->hostname, THEhost, 0, NULL, 1)) goto finish;
+    pc = pc->prev;
+  }
+ finish:
+  if (truehostname) *truehostname = STRDUP(THEhost);
+  FREE(THEhost);
+  if (!pc) pc = the_default;
+  return pc;
+}
+
+
+PUBLIC odbcs_t *
+odbcs_conf_create()
+{
+  odbcs_t *conf = NULL;
+  const char *conf_files[] = { 
+    "$ODB_SYSPATH/odbcs.conf",
+    "$HOME/odbcs.conf",
+    "./odbcs.conf",
+    "$ODBCS_CONF",
+    NULL 
+  };
+  const char **file = conf_files;
+  while (*file) {
+    conf = conf_read(*file, conf);
+    ++file;
+  }
+  conf = conf_make(conf);
+  return conf;
+}
+
+
+#if 0
+
+/* Just testing ... */
+
+void
+mainio_()
+{
+  odbcs_t *conf = NULL;
+  char *file = "odbcs.conf";
+  conf = conf_read(file, conf);
+  conf = conf_make(conf);
+  {
+    const char *hosts[] = { "hpce", "gylfi", "bee04", "ecgate", "localhost", NULL };
+    const char **h = hosts;
+    while (*h) {
+      char *truehostname = NULL;
+      const odbcs_t *match = odbcs_conf_match(*h, conf, &truehostname);
+      printf("host = '%s', truehostname = '%s'",*h,truehostname);
+      if (match) {
+	printf(" -- matched [via '%s']!!\n",match->hostname);
+	printf("/usr/bin/rsh %s -l %s "
+	       "'env _ARCH=%s _CPU_TYPE=%s _OBJECT_MODE=%d _ODB_ARCH=%s _ODB_COMPDIR=%s "
+	       "_ODB_DIR=%s _ODB_ROOT=%s "
+	       "%s/odbi_proxy -p %d -t %d < /dev/null'\n",
+	       truehostname, match->username,
+	       match->arch, match->cpu_type, match->object_mode, match->odb_arch, match->odb_compdir,
+	       match->odb_dir, match->odb_root,
+	       match->odb_binpath, match->port, match->timeout);
+      }
+      else
+	printf(" -- no match\n");
+      FREE(truehostname);
+      ++h;
+    }
+  }
+}
+#endif
+
+
+#endif /* ODBCS */
diff --git a/odb/src/aux/odbcs_error.c b/odb/src/aux/odbcs_error.c
new file mode 100644
index 0000000..cae3401
--- /dev/null
+++ b/odb/src/aux/odbcs_error.c
@@ -0,0 +1,96 @@
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+#include        "odbcs.h"
+
+#include <syslog.h>
+
+static void     err_doit(int, int, const char *, va_list);
+
+/* Nonfatal error related to system call
+ * Print message and return */
+
+void
+err_ret(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  err_doit(1, LOG_INFO, fmt, ap);
+  va_end(ap);
+  return;
+}
+
+/* Fatal error related to system call
+ * Print message and terminate */
+
+void
+err_sys(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  err_doit(1, LOG_ERR, fmt, ap);
+  va_end(ap);
+  exit(1);
+}
+
+/* Fatal error related to system call
+ * Print message, dump core, and terminate */
+
+void
+err_dump(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  err_doit(1, LOG_ERR, fmt, ap);
+  va_end(ap);
+  abort();                /* dump core and terminate */
+  exit(1);                /* shouldn't get here */
+}
+
+/* Nonfatal error unrelated to system call
+ * Print message and return */
+
+void
+err_msg(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  err_doit(0, LOG_INFO, fmt, ap);
+  va_end(ap);
+  return;
+}
+
+/* Fatal error unrelated to system call
+ * Print message and terminate */
+
+void
+err_quit(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  err_doit(0, LOG_ERR, fmt, ap);
+  va_end(ap);
+  exit(1);
+}
+
+/* Print message and return to caller
+ * Caller specifies "errnoflag" and "level" */
+
+static void
+err_doit(int errnoflag, int level, const char *fmt, va_list ap)
+{
+  int errno_save = errno;
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr,": [severity=%d] : %s\n",
+	  level,
+	  (errno_save > 0 || level == LOG_INFO) ? strerror(errno_save) : "Unknown error");
+  fflush(stderr);
+  return;
+}
+
+#else
+
+void dummy_odbcs_error() { }
+
+#endif /* ODBCS */
diff --git a/odb/src/aux/odbcs_signal.c b/odb/src/aux/odbcs_signal.c
new file mode 100644
index 0000000..4815a38
--- /dev/null
+++ b/odb/src/aux/odbcs_signal.c
@@ -0,0 +1,101 @@
+
+/* odbcs_signal.c */
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+static const char *Cmd = "";
+static int Verbose = 0;
+static int Timeout = -1;
+static int Server_Timeout = -1;
+
+extern const char *odb_resource_stamp_(const char *label); /* from ../lib.codb.c */
+
+void
+setup_sig(const char *cmd, const int *timeout, const int *verbose, const int *server_timeout)
+{
+  Cmd = STRDUP(cmd);
+  if (timeout) Timeout = *timeout;
+  if (verbose) Verbose = *verbose;
+  if (server_timeout) Server_Timeout = *server_timeout;
+}
+
+void
+sig_chld(int signo)
+{
+  if (signo == SIGCHLD) {
+    pid_t   pid;
+    int     status;
+    while ( (pid = waitpid(-1, &status, WNOHANG)) > 0) {
+      if (status != 0) {
+	fprintf(stdout,
+		"%s: child process %d terminated abnormally : status code = %d\n", 
+		odb_resource_stamp_(Cmd), pid, status);
+	fflush(stdout);
+	if (Verbose) fprintf(stderr,
+			     "%s: child process %d terminated (status=%d)\n", 
+			     odb_resource_stamp_(Cmd), pid, status);
+      }
+    } /* while ... */
+  } /* if (signo == SIGCHLD) */
+  return;
+}
+
+void
+sig_term(int signo)
+{
+  if (signo == SIGTERM) {
+    fprintf(stderr,"%s: received SIGTERM\n", odb_resource_stamp_(Cmd));
+    exit(signo);
+  }
+  return;
+}
+
+void
+sig_int(int signo)
+{
+  if (signo == SIGINT) {
+    fprintf(stderr,"%s: received SIGINT\n", odb_resource_stamp_(Cmd));
+    exit(signo);
+  }
+  return;
+}
+
+void
+sig_alrm(int signo)
+{
+  if (signo == SIGALRM) {
+    alarm(0);
+    fprintf(stderr,
+	    "%s: received SIGALRM (reached timeout after %d seconds)\n", 
+	    odb_resource_stamp_(Cmd), Timeout);
+    exit(signo);
+  }
+  return;
+}
+
+void
+sig_alrm_server(int signo)
+{
+  if (signo == SIGALRM) {
+    alarm(0);
+    fprintf(stderr,
+	    "%s: received SIGALRM (the master server reached timeout after %d seconds)\n", 
+	    odb_resource_stamp_(Cmd), Server_Timeout);
+    exit(signo);
+  }
+  return;
+}
+
+void
+sig_ignore(int signo)
+{
+  return;
+}
+
+#else
+
+void dummy_odbcs_signal() { }
+
+#endif
diff --git a/odb/src/aux/odbcs_wrappers.c b/odb/src/aux/odbcs_wrappers.c
new file mode 100644
index 0000000..1d8a257
--- /dev/null
+++ b/odb/src/aux/odbcs_wrappers.c
@@ -0,0 +1,482 @@
+
+/* odbcs_wrappers.c */
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+int
+Accept(int fd, SA *sa, socklen_t *salenptr)
+{
+  int             n;
+ again:
+  if ( (n = accept(fd, sa, salenptr)) < 0) {
+#ifdef  EPROTO
+    if (errno == EPROTO || errno == ECONNABORTED)
+#else
+    if (errno == ECONNABORTED)
+#endif
+      goto again;
+    else
+      err_sys("accept error");
+  }
+  return(n);
+}
+
+void
+Bind(int fd, const SA *sa, socklen_t salen)
+{
+  const int max_tries = 3;
+  int try_count = 0;
+  int sleep_secs = 10;
+  
+  for ( ; ; ) {
+    int rc = bind(fd, sa, salen);
+    if (rc < 0 && ++try_count > max_tries) {
+      err_sys("bind error");
+    }
+    else if (rc < 0) {
+      err_msg("bind failed; re-try#%d (out of %d) after %d secs",
+	      try_count, max_tries, sleep_secs);
+      sleep(sleep_secs);
+      sleep_secs *= 2;
+    }
+    else
+      break;
+  }
+}
+
+void
+Close(int fd)
+{
+  if (close(fd) == -1)
+    err_sys("close error");
+}
+
+static char *
+StartServer(const char *hostname, int port, int timeout, int verbose)
+{
+  static odbcs_t *conf = NULL;
+  char *truehostname = NULL;
+  const odbcs_t *match = NULL;
+  if (!conf) conf = odbcs_conf_create();
+  match = odbcs_conf_match(hostname, conf, &truehostname);
+  if (match) {
+    const char fmt[] =
+      "/usr/bin/rsh %s -l %s "
+      "'env _ARCH=%s _CPU_TYPE=%s _OBJECT_MODE=%d _ODB_VERSION=%s "
+      "_ODB_ARCH=%s _ODB_DIR=%s _ODB_ROOT=%s "
+      "%s/odbi_proxy -p %d -t %d"
+      " %s </dev/null' &";
+    char *cmd = NULL;
+    int len = 1 + STRLEN(fmt);
+    len += STRLEN(truehostname) + STRLEN(match->username);
+    len += STRLEN(match->arch) + STRLEN(match->cpu_type) + 20 + STRLEN(match->odb_version);
+    len += STRLEN(match->odb_arch) + STRLEN(match->odb_dir) + STRLEN(match->odb_root);
+    len += STRLEN(match->odb_binpath) + 20 + 20;
+    len += 20;
+    ALLOCX(cmd,len);
+    snprintf(cmd,len,fmt,
+	     truehostname, match->username,
+	     match->arch, match->cpu_type, match->object_mode, match->odb_version,
+	     match->odb_arch, match->odb_dir, match->odb_root,
+	     match->odb_binpath, port, timeout,
+	     verbose ? "-v" : ">/dev/null");
+    if (verbose) fprintf(stderr,"StartServer(%s, %d, %d, %d): %s\n",
+			 truehostname,port,timeout,verbose,cmd);
+    system(cmd);
+    FREEX(cmd);
+    sleep(2); /* Gives a little grace period for the server to get started ... */
+  }
+  else {
+    err_sys("Unable to start server @ host = '%s' (port=%d,timeout=%d) via odbi_proxy. "
+	    "Check your odbcs.conf file(s)\n",
+	    hostname,port,timeout);
+  }
+  return truehostname;
+}
+
+void
+Connect(int fd, SA *sa, socklen_t salen,
+	const char *host, int port, int timeout, const char *hostname,
+	int verbose)
+{
+  const int max_tries = 3;
+  int try_count = 0;
+  int sleep_secs = 5;
+  int first_time = 1;
+  char *THEhost = NULL;
+  struct sockaddr_in *Servaddr = (struct sockaddr_in *)sa;
+  char *ip_addr = STRDUP(host);
+
+  if (!hostname) hostname = host;
+  THEhost = STRDUP(hostname);
+  
+  for ( ; ; ) {
+    int rc = connect(fd, sa, salen);
+    if (rc < 0 && first_time) {
+      char *truehostname = NULL;
+      if (verbose) {
+	err_msg("unable to connect (host=%s[%s], port=%d); trying to start server remotely",
+		ip_addr,THEhost,port);
+      }
+      truehostname = StartServer(THEhost, port, timeout, verbose);
+      if (truehostname) {
+	FREE(THEhost);
+	THEhost = truehostname;
+	{
+	  bzero(Servaddr, salen);
+	  Servaddr->sin_family = AF_INET;
+	  Servaddr->sin_port = htons(port);
+	  struct hostent *h;
+	  h = gethostbyname(THEhost);
+	  if (h && h->h_addrtype == AF_INET) {
+	    char **pptr;
+	    char str[ODBCS_INET_ADDRSTRLEN];
+	    const char *p = NULL;
+	    pptr = h->h_addr_list;
+	    for ( ; *pptr != NULL ; pptr++) {
+	      p = Inet_ntop(h->h_addrtype, *pptr, str, sizeof(str));
+	    }
+	    if (p) {
+	      FREE(ip_addr);
+	      ip_addr = STRDUP(p);
+	    }
+	  }
+	  Inet_pton(AF_INET, ip_addr, &Servaddr->sin_addr);
+	}
+      }
+      first_time = 0;
+    }
+    else if (rc < 0 && ++try_count > max_tries) {
+      err_sys("unable to connect (host=%s[%s], port=%d)",ip_addr,THEhost,port);
+    }
+    else if (rc < 0) {
+      err_msg("unable to connect (host=%s[%s], port=%d); re-try#%d (out of %d) after %d secs",
+	      ip_addr,THEhost,port,try_count, max_tries, sleep_secs);
+      sleep(sleep_secs);
+      sleep_secs *= 2;
+    }
+    else
+      break;
+  }
+  FREE(ip_addr);
+  FREE(THEhost);
+}
+
+void
+Fclose(FILE *fp)
+{
+  if (fclose(fp) != 0)
+    err_sys("fclose error");
+}
+
+FILE *
+Fdopen(int fd, const char *mode)
+{
+  FILE    *fp;
+  if ( (fp = fdopen(fd, mode)) == NULL)
+    err_sys("fdopen error");
+  return(fp);
+}
+
+char *
+Fgets(char *ptr, int n, FILE *stream)
+{
+  char    *rptr;
+  if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
+    err_sys("fgets error");
+  return (rptr);
+}
+
+FILE *
+Fopen(const char *filename, const char *mode)
+{
+  FILE    *fp;
+  if ( (fp = fopen(filename, mode)) == NULL)
+    err_sys("fopen error");
+  return(fp);
+}
+
+pid_t
+Fork(void)
+{
+  pid_t   pid;
+  if ( (pid = fork()) == -1)
+    err_sys("fork error");
+  return(pid);
+}
+
+void
+Fputs(const char *ptr, FILE *stream)
+{
+  if (fputs(ptr, stream) == EOF)
+    err_sys("fputs error");
+}
+
+const char *
+Inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
+{
+  const char      *ptr;
+  if (strptr == NULL)             /* check for old code */
+    err_quit("NULL 3rd argument to inet_ntop");
+  if ( (ptr = inet_ntop(family, addrptr, strptr, len)) == NULL)
+    err_sys("inet_ntop error");             /* sets errno */
+  return(ptr);
+}
+
+void
+Inet_pton(int family, const char *strptr, void *addrptr)
+{
+  int             n;
+  if ( (n = inet_pton(family, strptr, addrptr)) < 0)
+    err_sys("inet_pton error for %s", strptr);      /* errno set */
+  else if (n == 0)
+    err_quit("inet_pton error for %s", strptr);     /* errno not set */
+  /* nothing to return */
+}
+
+void
+Listen(int fd, int backlog)
+{
+  if (listen(fd, backlog) < 0)
+    err_sys("listen error");
+}
+
+static int	read_cnt = 0;
+static char	*read_ptr = NULL;
+static char	read_buf[ODBCS_MAXLINE];
+
+static ssize_t
+my_read(int fd, char *ptr)
+{
+  if (read_cnt <= 0) {
+  again:
+    if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
+      if (errno == EINTR)
+	goto again;
+      return(-1);
+    } else if (read_cnt == 0)
+      return(0);
+    read_ptr = read_buf;
+  }
+  read_cnt--;
+  *ptr = *read_ptr++;
+  return(1);
+}
+
+static ssize_t
+readline(int fd, void *vptr, size_t maxlen)
+{
+  ssize_t	n, rc;
+  char	c, *ptr;
+  ptr = vptr;
+  for (n = 1; n < maxlen; n++) {
+    if ( (rc = my_read(fd, &c)) == 1) {
+      *ptr++ = c;
+      if (c == '\n')
+	break;	/* newline is stored, like fgets() */
+    } else if (rc == 0) {
+      *ptr = 0;
+      return(n - 1);	/* EOF, n - 1 bytes were read */
+    } else
+      return(-1);		/* error, errno set by read() */
+  }
+  *ptr = 0;	/* null terminate like fgets() */
+  return(n);
+}
+
+ssize_t
+Readline(int fd, void *ptr, size_t maxlen)
+{
+  ssize_t		n = 0;
+  if (ptr && maxlen > 0) {
+    if ( (n = readline(fd, ptr, maxlen)) < 0)
+      err_sys("readline error");
+  }
+  return(n);
+}
+
+ssize_t
+Readline_timeo(int fd, void *ptr, size_t maxlen, int timeout)
+{
+  ssize_t		n = 0;
+  if (ptr && maxlen > 0) {
+    Sigfunc        *sigfunc;
+    if (timeout > 0) {
+      sigfunc = Signal(SIGALRM, sig_alrm);
+      if (alarm(timeout) != 0)
+	err_msg("Readline_timeo: alarm was already set");
+    }
+    n = Readline(fd, ptr, maxlen);
+    if (timeout > 0) { /* Restore */
+      alarm(0);
+      Signal(SIGALRM, sigfunc);
+    }
+  }
+  return(n);
+}
+
+static ssize_t /* Read "n" bytes from a descriptor. */
+readn(int fd, void *vptr, size_t n)
+{
+  size_t  nleft;
+  ssize_t nread;
+  char    *ptr;
+
+  ptr = vptr;
+  nleft = n;
+  while (nleft > 0) {
+    if ( (nread = read(fd, ptr, nleft)) < 0) {
+      if (errno == EINTR)
+	nread = 0;              /* and call read() again */
+      else
+	return(-1);
+    } else if (nread == 0)
+      break;                          /* EOF */
+    
+    nleft -= nread;
+    ptr   += nread;
+  }
+  return(n - nleft);              /* return >= 0 */
+}
+
+ssize_t
+Readn(int fd, void *ptr, size_t nbytes)
+{
+  ssize_t         n = 0;
+  if (ptr && nbytes > 0) {
+    if ( (n = readn(fd, ptr, nbytes)) < 0)
+      err_sys("readn error");
+  }
+  return(n);
+}
+
+ssize_t
+Readn_timeo(int fd, void *ptr, size_t nbytes, int timeout)
+{
+  ssize_t         n = 0;
+  if (ptr && nbytes > 0) {
+    Sigfunc        *sigfunc;
+    if (timeout > 0) {
+      sigfunc = Signal(SIGALRM, sig_alrm);
+      if (alarm(timeout) != 0)
+	err_msg("Readn_timeo: alarm was already set");
+    }
+    n = Readn(fd, ptr, nbytes);
+    if (timeout > 0) { /* Restore */
+      alarm(0);
+      Signal(SIGALRM, sigfunc);
+    }
+  }
+  return(n);
+}
+
+int
+Select(int nfds, 
+       fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+       struct timeval *timeout)
+{
+  int             n;
+  if ( (n = select(nfds, readfds, writefds, exceptfds, timeout)) < 0)
+    err_sys("select error");
+  return(n);              /* can return 0 on timeout */
+}
+
+void
+Shutdown(int fd, int how)
+{
+  if (shutdown(fd, how) < 0)
+    err_sys("shutdown error");
+}
+
+#if 0
+Sigfunc *
+signal(int signo, Sigfunc *func)
+{
+  struct sigaction        act, oact;
+  
+  act.sa_handler = func;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  if (signo == SIGALRM) {
+#ifdef  SA_INTERRUPT
+    act.sa_flags |= SA_INTERRUPT;   /* SunOS 4.x */
+#endif
+  } else {
+#ifdef  SA_RESTART
+    act.sa_flags |= SA_RESTART;     /* SVR4, 44BSD */
+#endif
+  }
+  if (sigaction(signo, &act, &oact) < 0)
+    return(SIG_ERR);
+  return(oact.sa_handler);
+}
+#endif
+
+Sigfunc *
+Signal(int signo, Sigfunc *func) /* for our signal() function */
+{
+  Sigfunc *sigfunc;
+  if ( (sigfunc = signal(signo, func)) == SIG_ERR)
+    err_sys("signal error");
+  return(sigfunc);
+}
+
+int
+Socket(int family, int type, int protocol)
+{
+  int             n;
+  if ( (n = socket(family, type, protocol)) < 0)
+    err_sys("socket error");
+  return(n);
+}
+
+pid_t
+Waitpid(pid_t pid, int *iptr, int options)
+{
+  pid_t   retpid;
+  if ( (retpid = waitpid(pid, iptr, options)) == -1)
+    err_sys("waitpid error");
+  return(retpid);
+}
+
+static ssize_t /* Write "n" bytes to a descriptor. */
+writen(int fd, const void *vptr, size_t n)
+{
+  size_t          nleft;
+  ssize_t         nwritten;
+  const char      *ptr;
+
+  ptr = vptr;
+  nleft = n;
+  while (nleft > 0) {
+    if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
+      if (nwritten < 0 && errno == EINTR)
+	nwritten = 0;           /* and call write() again */
+      else
+	return(-1);                     /* error */
+    }
+    
+    nleft -= nwritten;
+    ptr   += nwritten;
+  }
+  return(n);
+}
+
+ssize_t
+Writen(int fd, const void *ptr, size_t nbytes)
+{
+  ssize_t n = 0;
+  if (ptr && nbytes > 0) {
+    if ((n = writen(fd, ptr, nbytes)) != nbytes)
+      err_sys("writen error");
+  }
+  return(n);
+}
+
+#else
+
+void dummy_odbcs_wrappers() { }
+
+#endif /* ODBCS */
diff --git a/odb/src/aux/odbdump.c b/odb/src/aux/odbdump.c
new file mode 100644
index 0000000..b8a9789
--- /dev/null
+++ b/odb/src/aux/odbdump.c
@@ -0,0 +1,490 @@
+
+/* odbdump.c */
+
+#include "odb.h"
+#include "info.h"
+#include "result.h"
+#include "odbdump.h"
+#include "pcma_extern.h"
+
+PUBLIC Bool odbdump_on = false;
+
+typedef struct {
+  char *dbname;
+
+  char *database;
+  char *sql_query;
+  char *poolmask;
+
+  int db_handle;
+  int maxcols;
+  int npools_all;
+
+  int *poolnos;
+  int npools;
+  int curpoolno_idx;
+  int currow;
+
+  int nrows;
+
+  info_t *info;
+  info_t *curinfo;
+
+  set_t *setvar;
+  int nsetvar;
+
+  result_t *r;
+} odbdump_t;
+
+
+PRIVATE FILE *f_stderr = NULL; /* not thread safe */
+
+
+/*!
+  Get rid of unnecessary stderr-output by redirecting "stderr" to 
+  the filename (or /dev/null if cannot open). Do only once.
+  
+  @param fp           File pointer to write outputs
+  @param filename     Filename where stderr will be redirected
+  @param mode         Opening mode ("w" by default)
+ */
+PUBLIC void
+odbdump_reset_stderr(FILE *fp, const char *filename, const char *mode)
+{
+  if (!f_stderr) {
+    /* Get rid of unnecessary stderr-output by
+       redirecting "stderr" to the filename (or /dev/null if cannot open).
+       Do only once */
+    if (!fp) fp = stderr;
+    if (!filename) filename = "odbdump.stderr";
+    if (!mode) mode = "w";
+    f_stderr = freopen(filename, mode, fp);
+    if (!f_stderr) f_stderr = freopen("/dev/null", mode, fp);
+  }
+}
+
+
+PRIVATE char *
+SlurpMe(const char *path) /* Nearly as in odb/compiler/odb98.c */
+{
+  char *s = NULL;
+  if (path) {
+    extern int IOgetsize(const char *path, int *filesize, int *blksize);
+    int filesize = 0;
+    int rc = IOgetsize(path, &filesize, NULL);
+    if (rc == 0 && filesize > 0) {
+      FILE *fp = fopen(path,"r");
+      if (fp) {
+	int len = filesize + 1;
+	ALLOC(s, len);
+	if (s) {
+	  rc = fread(s, sizeof(*s), filesize, fp); /* slurp!! */
+	  if (rc == filesize) { /* Success */
+	    char *ps = s;
+	    s[filesize] = '\0';
+	    while (*ps) {
+	      if (isspace(*ps) || !isprint(*ps)) *ps = ' ';
+	      ++ps;
+	    } /* while (*ps) */
+	  }
+	  else {
+	    FREE(s); /* Failure */
+	  }
+	}
+	fclose(fp);
+      } /* if (fp) */
+    }
+  }
+  if (!s) {
+    fprintf(stderr,"***Error: Unable to inline from the non-existent (or empty) file '%s'\n",
+	    path ? path : NIL);
+  }
+  return s;
+}
+
+
+/*!
+  Open and initialise an existing ODB database.
+  @param database  path of an existing ODB database (default .) 
+  @param sql_query ODB-SQL auery. Precedence on this over the queryfile, if both present
+  @param queryfile Filename where an ODB-SQL query is stored
+  @param poolmask  List of pools (i.e. "1,2" for pool 1 and 2)
+  @param varvalue  string containing "SET" variables
+  @param ncols     number of columns associated with the given SQL request.
+  @return ODB-dump handle (odbdump_t)
+ */
+PUBLIC void *
+odbdump_open(const char *database,
+	     const char *sql_query, /* Precedence on this over the queryfile, if both present */
+	     const char *queryfile,
+	     const char *poolmask,
+	     const char *varvalue,
+	     int *ncols)
+{
+  static Bool do_once = true; /* Not thread safe */
+  odbdump_t *h = NULL;
+  if (ncols) *ncols = 0;
+
+  if (!database) {
+    /* Try current dir for database */
+    database = ".";
+  }
+
+  if (do_once) {
+    /* 
+       Avoid hangs in gdb/dbx debugger called by Dr.Hook in odb98.x :
+       export GNUDEBUGGER=0
+       export DBXDEBUGGER=0
+    */
+    char *env1, *env2;
+    env1 = STRDUP("GNUDEBUGGER=0");
+    putenv(env1); /* "env1" remains allocated ; cannot be free'd due to putenv() */
+    env2 = STRDUP("DBXDEBUGGER=0");
+    putenv(env2); /* "env2" remains allocated ; cannot be free'd due to putenv() */
+    do_once = false;
+  }
+
+  if (!f_stderr) odbdump_reset_stderr(NULL, NULL, NULL);
+
+  if (database && (sql_query || queryfile)) {
+    int npools, ntables, db_handle;
+    odbdump_on = true;
+    db_handle = ODBc_open(database, "r", &npools, &ntables, poolmask);
+    odbdump_on = false;
+    if (db_handle >= 1) {
+      int nsetvar = 0;
+      set_t *setvar = ODBc_make_setvars(varvalue, &nsetvar);
+      void *(*sql_prepare_func)(int , const char *, const set_t *, int) = /* showing off ? */
+	sql_query ? ODBc_sql_prepare : ODBc_sql_prepare_via_sqlfile;
+      info_t *info = sql_prepare_func(db_handle, sql_query ? sql_query : queryfile, setvar, nsetvar);
+      info_t *info_chain = info;
+      int maxcols = 0;
+
+      while (info) {
+	if (info->create_index == 0) {
+	  /* We skip ANY CREATE/DROP INDEX -statements */
+	  maxcols = MAX(maxcols, info->ncols);
+	}
+	else {
+	  fprintf(stderr,"***Warning: odbdump currently ignores CREATE/DROP INDEX -statements\n");
+	}
+	info = ODBc_next(info);
+      } /* while (info) */
+      info = info_chain;
+
+      if (maxcols >= 1) {
+	ODBc_print_info(ODBc_get_debug_fp(), info);
+
+	CALLOC(h, 1);
+	h->dbname = STRDUP(info->ph->dbname);
+	h->database = STRDUP(database);
+	h->sql_query = sql_query ? STRDUP(sql_query) : SlurpMe(queryfile);
+	h->poolmask = poolmask ? STRDUP(poolmask) : NULL;
+	h->db_handle = db_handle;
+	h->maxcols = maxcols;
+	h->npools_all = h->npools = npools;
+	h->poolnos = ODB_get_permanent_poolmask(h->db_handle, &h->npools);
+	h->curpoolno_idx = 0;
+	h->currow = 0;
+	h->nrows = 0;
+	h->info = info;
+	h->curinfo = NULL;
+	h->setvar = setvar;
+	h->nsetvar = nsetvar;
+	h->r = NULL;
+      }
+      else {
+	info = ODBc_sql_cancel(info);
+      }
+    } /* if (db_handle >= 1) */
+  } /* if (database && sql_query) */
+
+  if (h) {
+    if (h->npools == 0) {
+      odbdump_close(h);
+      h = NULL;
+    }
+    else if (ncols) {
+      *ncols = h->maxcols;
+    }
+  }
+	    
+  return h;
+}
+
+/*!
+  @param Handle ODB-dump handle
+  @param v variable where a new packed row will be returned
+  @param npk
+  @param new_dataset
+  @return the number of bytes 
+ */
+PUBLIC int
+odbdump_nextrow_packed(void *Handle, 
+		       void *v, /* at least npk elements of sizeof(char) */
+		       int npk,
+		       int *new_dataset)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int nd = npk/sizeof(double);
+  double *d = v;
+  rc = odbdump_nextrow(Handle, d, nd, new_dataset);
+  if (rc > 0) {
+    void *pk = PackDoubles(d, rc, &nbytes);
+    if (pk && nbytes > 0 && nbytes <= npk) {
+      memcpy(v, pk, nbytes);
+    }
+    else { /* Do not pack at all */
+      uint *Pk = NULL;
+      double *tmp = NULL;
+      const int ratio = sizeof(*tmp)/sizeof(*Pk); /* Usually 2 */
+      const int offset = 2/ratio;
+      int ntmp = offset + rc;
+      ALLOC(tmp, ntmp);
+      Pk = (uint *)tmp;
+      Pk[0] = (uint)-1;
+      Pk[1] = rc;
+      memcpy(&tmp[offset], d, rc * sizeof(*d));
+      nbytes = ntmp * sizeof(*tmp);
+      if (nbytes <= npk) memcpy(d, tmp, nbytes);
+      else nbytes = -nbytes;
+      FREE(tmp);
+    }
+    FREE(pk);
+  }
+  return nbytes;
+}
+
+
+/*!
+ @param Handle ODB-dump handle
+ @param v variable where a new row will be returned
+ @param nd
+ @param new_dataset
+ @return an error code
+ */
+PUBLIC int
+odbdump_nextrow(void *Handle, 
+		void *v, /* at least nd elements of sizeof(double) */
+		int nd,
+		int *new_dataset)
+{
+  double *d = v;
+  int rc = 0;
+  if (new_dataset) *new_dataset = 0;
+  if (Handle && d && nd > 0) {
+    DEF_IT;
+    const Bool row_wise_preference = true;
+    odbdump_t *h = Handle;
+    info_t *info = h->curinfo ? h->curinfo : h->info;
+
+  again:
+
+    while (info && info->create_index != 0) {
+      /* We skip ANY CREATE/DROP INDEX -statements */
+      info = ODBc_next(info);
+    }
+    
+    if (h->curinfo != info) {
+      /* Reset previous infos */
+      h->r = ODBc_unget_data(h->r);
+      h->currow = 0;
+      h->nrows = 0;
+      h->curpoolno_idx = 0;
+      if (h->curinfo && h->curinfo->need_hash_lock) {
+	/* UNIQUEBY-clause present (or has SELECT DISTINCT) */
+	codb_hash_init_();
+	codb_hash_unset_lock_();
+      }
+      h->curinfo = info;
+      if (h->curinfo && h->curinfo->need_hash_lock) {
+	/* UNIQUEBY-clause present (or has SELECT DISTINCT) */
+	codb_hash_init_();
+	codb_hash_unset_lock_();
+      }
+      if (new_dataset) *new_dataset = info ? 1 : 0;
+    }
+
+    if (!info) goto finish;
+
+    if (info->need_global_view) {
+      /* A global view */
+      if (!h->r && h->curpoolno_idx < h->npools) {
+	int ip, npools = h->npools;
+	int nrows = 0;
+	result_t *res = NULL;
+	
+	h->r = ODBc_unget_data(h->r);
+	
+	for (ip=0; ip<npools; ip++) {
+	  /* This is a loop over effective pools i.e. those which
+	     were left in the poolmask */
+	  int nr, jp = h->poolnos[ip];
+	  if (info->has_thin) codb_thin_reset_(&it);
+	  nr = ODBc_sql_exec(h->db_handle, info, jp, NULL, NULL);
+	  if (nr > 0) {
+	    nrows += nr;
+	    res = ODBc_get_data(h->db_handle, res, info, jp, 1, nr, false, &row_wise_preference);
+	  }
+	  if (info->has_thin) codb_thin_reset_(&it);
+	  info = ODBc_reset_info(info);
+	  if (info->is_bc && nrows >= 1) break;
+	} /* for (ip=0; ip<npools; ip++) */
+	
+	h->nrows = 0;
+	if (res && nrows > 0) {
+	  if (info->has_aggrfuncs) res = ODBc_aggr(res, 1);
+	  res = ODBc_operate(res, "count(*)");
+	  res = ODBc_sort(res, NULL, 0);
+	  h->r = res;
+	  h->nrows = res->nrows_out;
+	}
+	h->currow = 0;
+	h->curpoolno_idx = h->npools; /* means: don't redo this block, since active pools already "looped over" */
+      } /* if (!h->r && h->curpoolno_idx < h->npools) */
+    }
+    else {
+      /* NOT a global view */
+      while (!h->r && h->curpoolno_idx < h->npools) {
+	int jp = h->poolnos[(h->curpoolno_idx)++];
+	if (info->has_thin) codb_thin_reset_(&it);
+	h->nrows = ODBc_sql_exec(h->db_handle, info, jp, NULL, NULL);
+	if (h->nrows > 0) {
+	  h->r = ODBc_get_data(h->db_handle, NULL, info, jp, 1, h->nrows, false, &row_wise_preference);
+	  h->currow = 0;
+	} /* if (h->nrows > 0) */
+      } /* while (!h->r && h->curpoolno_idx < h->poolnos) */
+    }
+
+    if (h->r) {
+      if (h->currow >= h->nrows) {
+	h->r = ODBc_unget_data(h->r);
+	h->currow = 0;
+	h->nrows = 0;
+	if (info->has_thin) codb_thin_reset_(&it);
+	info = ODBc_reset_info(info);
+	if (info->need_global_view) info = ODBc_next(info);
+	goto again;
+      }
+      else {
+	int currow = h->currow;
+	result_t *res = h->r;
+	Bool row_wise = res->row_wise;
+	nd = MIN(nd, res->ncols_out);
+
+	if (row_wise) { /* Stride == 1 */
+	  const double *in = &res->d[currow][0];
+	  memcpy(d, in, nd * sizeof(*d));
+	}
+	else { /* Access with stride >> 1 */
+	  int i;
+	  for (i=0; i<nd; i++) d[i] = res->d[i][currow];
+	}
+
+	h->currow = ++currow;
+	rc = nd;
+      }
+    } /* h->r */
+  }
+ finish:
+  return rc;
+}
+
+/*!
+ @param Handle ODB-dump handle
+ @param ncols  Number of element of the returned colinfo_t array
+ @return fill an array of colinfo_t structure and return it 
+ */
+PUBLIC colinfo_t *
+odbdump_create_colinfo(void *Handle,
+		       int *ncols)
+{
+  colinfo_t *ci = NULL;
+  odbdump_t *h = Handle;
+  if (ncols) *ncols = 0;
+  if (h && h->curinfo) {
+    const info_t *info = h->curinfo;
+    int ncols_true = info->ncols_true;
+    int j, nc = 0;
+    for (j=0; j<ncols_true; j++) {
+      const col_t *colthis = &info->c[j];
+      if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) ++nc;
+    } /* for (j=0; j<ncols_true; j++) */
+    if (nc > 0) {
+      int k = 0;
+      colinfo_t *pci;
+      CALLOC(ci, nc);
+      pci = ci;
+      for (j=0; j<ncols_true; j++) {
+	const col_t *colthis = &info->c[j];
+	if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	  pci->id = ++k;
+	  pci->name = STRDUP(colthis->name);
+	  pci->nickname = colthis->nickname ? STRDUP(colthis->nickname) : NULL;
+	  pci->type_name = STRDUP(colthis->dtype);
+	  pci->dtnum = colthis->dtnum;
+	  ++pci;
+	}
+      } /* for (j=0; j<ncols_true; j++) */
+      if (ncols) *ncols = nc;
+    } /* if (nc > 0) */
+  }
+  return ci;
+}
+
+/*!
+  Free colinfo_t array
+  @param ci     colinfo_t array to free
+  @param ncols  number of elements of ci
+ */
+PUBLIC colinfo_t *
+odbdump_destroy_colinfo(colinfo_t *ci, 
+			int ncols)
+{
+  if (ci && ncols > 0) {
+    colinfo_t *pci = ci;
+    int j;
+    for (j=0; j<ncols; j++) {
+      FREE(pci->name);
+      FREE(pci->nickname);
+      FREE(pci->type_name);
+      ++pci;
+    }
+    FREE(ci);
+  }
+  return NULL;
+}
+
+/*!
+  Close ODB database and free ODB-dump handle
+  @param Handle  ODB-dump handle
+ */
+PUBLIC int
+odbdump_close(void *Handle)
+{
+  int rc = -1;
+  if (Handle) {
+    odbdump_t *h = Handle;
+    int nsetvar = h->nsetvar;
+    if (h->setvar && nsetvar > 0) {
+      int j;
+      for (j=0; j<nsetvar; j++) {
+	FREE(h->setvar[j].name);
+      }
+    }
+    FREE(h->setvar);
+    FREE(h->dbname);
+    FREE(h->database);
+    FREE(h->sql_query);
+    FREE(h->poolmask);
+    h->info = ODBc_sql_cancel(h->info);
+    h->r = ODBc_unget_data(h->r);
+    FREE(h->poolnos);
+    rc = ODBc_close(h->db_handle);
+    FREE(h);
+  }
+  return rc;
+}
+
+
diff --git a/odb/src/aux/odbi_client.c b/odb/src/aux/odbi_client.c
new file mode 100644
index 0000000..5d56bed
--- /dev/null
+++ b/odb/src/aux/odbi_client.c
@@ -0,0 +1,1579 @@
+
+/* odbi_client.c */
+
+/* 
+
+   Contains the same functions as in ODBI_direct.c,
+   but these are communicating with ODBI_server.c
+   to exchange data with the "askodb", that is run by this server.
+   The "askodb" in turn runs ODBI_direct.c locally on server's 
+   -machine !!
+
+   Advantage: direct & client -interface identical, and thus
+   you can choose between static linkage or client/server
+   model without changing your application.
+
+   In addition client is the only one at the moment who can 
+   also supply SQL's dynamically (on-the-fly) !!
+
+*/
+
+#define ODBI_CLIENT 1
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+#include "odb.h"
+
+#include "odbi.h"
+
+#include "pcma_extern.h"
+#include "magicwords.h"
+#include "cdrhook.h"
+
+#include "odbi_struct.h"
+#include "odbcsdefs.h"
+
+#define DBCLI db->cli
+#define QDB   q->db
+
+typedef struct _db_chain_t {
+  ODBI_db_t *db;
+  struct _db_chain_t *next;
+} db_chain_t;
+
+static db_chain_t *dbch = NULL;
+
+/* Local subroutines */
+
+PRIVATE void
+atexit_db_chain()
+{
+  db_chain_t *pdbch = dbch;
+  while (pdbch) {
+    if (pdbch->db) {
+      /* This db-ptr has been forgotten to release */
+      (int) ODBI_disconnect(pdbch->db);
+    }
+    pdbch = pdbch->next;
+  } /* while (pdbch) */
+}
+
+PRIVATE void
+add_db_chain(ODBI_db_t *db)
+{
+  if (db) {
+    db_chain_t *pdbch = NULL;
+    if (!dbch) {
+      CALLOC(dbch, 1);
+      /* The following should stop child process errors
+	 whilst user has forgotten to call ODBI_disconnect */
+      atexit(atexit_db_chain);
+    }
+    pdbch = dbch;
+    for (;;) {
+      if (!pdbch->db) {
+	pdbch->db = db;
+	break;
+      }
+      else {
+	if (!pdbch->next) CALLOC(pdbch->next, 1);
+	pdbch = pdbch->next;
+      }
+    } /* for (;;) */
+  }
+}
+
+PRIVATE int
+rm_db_chain(ODBI_db_t *db)
+{
+  int rc = 0;
+  if (db) {
+    db_chain_t *pdbch = dbch;
+    while (pdbch) {
+      if (pdbch->db == db) {
+	pdbch->db = NULL;
+	rc = 1;
+	break;
+      }
+      pdbch = pdbch->next;
+    } /* while (pdbch) */
+  }
+  return rc;
+}
+
+PRIVATE int
+is_ipv4_addr(const char *ip_addr)
+{
+  int rc;
+  int n1 = -1, n2 = -1, n3 = -1, n4 = -1;
+  int n = sscanf(ip_addr,"%d.%d.%d.%d", &n1, &n2, &n3, &n4);
+#if 0
+  fprintf(stderr,
+	  "client: is_ipv4_addr(%s) : n=%d, n1=%d, n2=%d, n3=%d, n4=%d\n",
+	  ip_addr, n, n1, n2, n3, n4);
+#endif
+  rc = (n == 4
+	&& n1 >= 0 && n1 <= 255
+	&& n2 >= 0 && n2 <= 255
+	&& n3 >= 0 && n3 <= 255
+	&& n4 >= 0 && n4 <= 255);
+  return rc;
+}
+
+PRIVATE int 
+find_int(const char *s, 
+	 const char *substr,
+	 int *found)
+{
+  int rc = 0;
+  if (found) *found = 0;
+  if (s && substr) {
+    char *p = strstr(s,substr);
+    if (p) {
+      p += STRLEN(substr);
+      rc = atoi(p);
+      if (found) *found = 1;
+    }
+  }
+  return rc;
+}
+
+PRIVATE char *
+find_str(const char *s, 
+	 const char *substr,
+	 int *found)
+{
+  char *x = NULL;
+  if (found) *found = 0;
+  if (s && substr) {
+    char *p = strstr(s,substr);
+    if (p) {
+      char *nl;
+      p += STRLEN(substr);
+      nl = strchr(p,'\n');
+      if (nl) {
+	int len = nl - p;
+	ALLOC(x,len+1);
+	strncpy(x,p,len);
+	x[len] = '\0';
+      }
+      else {
+	x = STRDUP(p);
+      }
+      if (found) *found = 1;
+    }
+  }
+  return x;
+}
+
+PRIVATE char *
+find_strnum(const char *s, 
+	    const char *substr0,
+	    int number,
+	    int *found)
+{
+  char *x = NULL;
+  if (found) *found = 0;
+  if (s && substr0 && number >= 0) {
+    char *p = NULL;
+    int lensubstr = STRLEN(substr0) + 20;
+    char *substr;
+    ALLOC(substr,lensubstr);
+    sprintf(substr,"%s%d=",substr0,number);
+    p = strstr(s,substr);
+    if (p) {
+      char *nl;
+      p += STRLEN(substr);
+      nl = strchr(p,'\n');
+      if (nl) {
+	int len = nl - p;
+	ALLOC(x,len+1);
+	strncpy(x,p,len);
+	x[len] = '\0';
+      }
+      else {
+	x = STRDUP(p);
+      }
+      if (found) *found = 1;
+    }
+    FREE(substr);
+  }
+  return x;
+}
+
+PUBLIC void 
+Vparam(void *v, 
+       int is_a_query,
+       char *fmt, 
+       va_list ap)
+{
+  ODBI_db_t *db = NULL;
+  ODBI_query_t *q = NULL;
+
+  if (is_a_query) q  = v;
+  else            db = v;
+  
+#if 0
+  fprintf(stderr,"Vparam(in): is_a_query=%d, v=%p, fmt=[%s]\n",
+	  is_a_query, v, fmt ? fmt : NIL);
+#endif
+
+  if (v && fmt) {
+    const char *delim = ";";
+    char *token = strtok(fmt,delim);
+    
+    while (token) {
+      char *ss = STRDUP(token);
+      char *t = strchr(ss,'=');
+      char *lhs = ss;
+      union {
+	char *s;
+	int ii;
+	double dd;
+	FILE *fp;
+      } rhs;
+      int free_rhss = 0;
+      int do_process = 0;
+
+      fmt = token;
+	
+      if (t) {
+	rhs.s = STRDUP(t+1);
+	do_process = 1;
+	*t = '\0'; /* affects "lhs" */
+      }
+	
+      if (do_process) {
+	do_process = 0;
+	if (*rhs.s == '%') {
+	  char *s = strchr(fmt,'%');
+	  if (s) {
+	    fmt = s;
+	    fmt++;
+	    switch (*fmt++) {
+	    case 's':
+	      FREE(rhs.s);
+	      s = va_arg(ap, char *);
+	      rhs.s = STRDUP(s);
+	      /* fprintf(stderr,"Vparam(at %%s): '%s'\n",rhs.s); */
+	      free_rhss = 1;
+	      do_process = 1;
+	      break;
+	    case 'd':
+	      FREE(rhs.s);
+	      rhs.ii = va_arg(ap, int);
+	      /* fprintf(stderr,"Vparam(at %%f): %d\n",rhs.ii); */
+	      free_rhss = 0;
+	      do_process = 1;
+	      break;
+	    case 'f':
+	      FREE(rhs.s);
+	      rhs.dd = va_arg(ap, double);
+	      /* fprintf(stderr,"Vparam(at %%f): %g\n",rhs.dd); */
+	      free_rhss = 0;
+	      do_process = 1;
+	      break;
+	    case 'F':
+	      FREE(rhs.s);
+	      rhs.fp = va_arg(ap, FILE *);
+	      /* fprintf(stderr,"Vparam(at %%F): %p, fileno=%d\n",rhs.fp,fileno(rhs.fp)); */
+	      free_rhss = 0;
+	      do_process = 1;
+	      break;
+	    }
+	  } /* if (*rhs.s == '%') */
+	}
+      }
+	
+      if (do_process) {
+	if (db) {
+	  if (DBCLI) {
+	    if      (strcaseequ(lhs,"host"))       DBCLI->host       = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"port"))       DBCLI->port       = rhs.ii;
+	    else if (strcaseequ(lhs,"timeout"))    DBCLI->timeout    = rhs.ii;
+	    else if (strcaseequ(lhs,"datapath"))   DBCLI->datapath   = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"poolmask"))   DBCLI->poolmask   = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"user"))       DBCLI->user       = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"clihost"))    DBCLI->clihost    = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"cliaddr"))    DBCLI->cliaddr    = STRDUP(rhs.s);
+	    else if (strcaseequ(lhs,"silent"))     DBCLI->silent     = rhs.ii;
+	    else if (strcaseequ(lhs,"verbose"))    DBCLI->verbose    = rhs.ii;
+	    else if (strcaseequ(lhs,"metadata"))   DBCLI->metadata   = rhs.ii;
+	    else if (strcaseequ(lhs,"clean"))      DBCLI->clean      = rhs.ii;
+	    else if (strcaseequ(lhs,"keep"))       DBCLI->keep       = rhs.ii;
+	    else if (strcaseequ(lhs,"bufsize"))    DBCLI->bufsize    = rhs.ii;
+	    else if (strcaseequ(lhs,"odbsql"))     DBCLI->odbsql     = rhs.ii;
+	  }
+	  if (strcaseequ(lhs,"io_method"))       db->io_method     = rhs.ii;
+	  else if (strcaseequ(lhs,"iomethod"))   db->io_method     = rhs.ii;
+	  else if (strcaseequ(lhs,"fp"))         db->fp            = rhs.fp;
+	}
+      }
+      else {
+	if (db) {
+	  if (DBCLI) {
+	    if (strcaseequ(lhs,"silent"))          DBCLI->silent   = 1;
+	    else if (strcaseequ(lhs,"verbose"))    DBCLI->verbose  = 1;
+	    else if (strcaseequ(lhs,"metadata"))   DBCLI->metadata = 1;
+	    else if (strcaseequ(lhs,"clean"))      DBCLI->clean    = 1;
+	    else if (strcaseequ(lhs,"keep"))       DBCLI->keep     = 1;
+	    else if (strcaseequ(lhs,"odbsql"))     DBCLI->odbsql   = 1;
+	    if (strcaseequ(lhs,"nosilent"))        DBCLI->silent   = 0;
+	    else if (strcaseequ(lhs,"noverbose"))  DBCLI->verbose  = 0;
+	    else if (strcaseequ(lhs,"nometadata")) DBCLI->metadata = 0;
+	    else if (strcaseequ(lhs,"noclean"))    DBCLI->clean    = 0;
+	    else if (strcaseequ(lhs,"nokeep"))     DBCLI->keep     = 0;
+	    else if (strcaseequ(lhs,"noodbsql"))   DBCLI->odbsql   = 0;
+	  }
+	}
+      }
+      
+      if (free_rhss) FREE(rhs.s);
+      FREE(ss);
+
+      token = strtok(NULL,delim);
+    } /* while (token) */
+  } /* if (v && fmt) */
+#if 0
+  fprintf(stderr,"Vparam(out)\n");
+#endif
+}
+
+
+PRIVATE char *
+echo(int *retcode,
+     const char *what,
+     int infd, int outfd, 
+     int timeout, int verbose, int byteswap, 
+     int *Outlen)
+{
+  int nbytes, n;
+  char *outbuf = NULL;
+  int outlen = 0;
+  int yksi = 1;
+  if (Outlen) *Outlen = 0;
+  if (retcode) *retcode = 0;
+  if (verbose) fprintf(stderr,"client: now expecting '%s'\n",what);
+  while ( (nbytes = Readn_timeo(infd, &n, sizeof(n), timeout)) > 0) {
+    char *buf = NULL;
+    char *whatmsg = "";
+    const int one = 1;
+    if (byteswap) swap4bytes_(&n, &one);
+    if (n == 0) whatmsg = " (EOM)";
+    else if (n < 0) whatmsg = " (FAILURE)";
+    if (verbose) fprintf(stderr,"client(%s): read length = %d%s\n",
+			 what, n, whatmsg);
+    if (n == 0) break; /* end of message */
+    if (n < 0) { /* popen() has failed or pclose() detected an error */
+      int istat = n;
+      err_msg("client: Server has detected a problem : status code = %d",istat);
+      if (retcode) *retcode = istat;
+      if (outbuf) FREE(outbuf);
+      if (Outlen) *Outlen = 0;
+      goto finish;
+    }
+    ALLOC(buf,n);
+    nbytes = Readn_timeo(infd, buf, n, timeout);
+    if (verbose) fprintf(stderr,"client(%s): read from socket, %d bytes\n",
+			 what,n);
+    if (Outlen) {
+      REALLOC(outbuf, outlen + n + yksi);
+      yksi = 0;
+      memcpy(outbuf+outlen,buf,n);
+      outlen += n;
+    }
+    if (outfd >= 0) {
+      Writen(outfd, buf, n);
+    }
+    FREE(buf);
+  }
+  if (Outlen) {
+    *Outlen = outlen;
+    if (outlen > 0) outbuf[outlen] = '\0'; /* due to "yksi" */
+  }
+ finish:
+  return outbuf;
+}
+
+/* Maximum name length (can be *INCREASED* via ODBI_maxnamelen(newlength)) */
+PRIVATE int max_name_len = 64;
+/***************************************************************************/
+/*                                 PUBLIC                                  */
+/***************************************************************************/
+int ODBI_maxnamelen(int new_len)
+{
+  int old_len = max_name_len;
+  DRHOOK_START(ODBI_maxnamelen);
+  if (new_len >= max_name_len) max_name_len = new_len;
+  DRHOOK_END(0);
+  return old_len;
+}
+
+/* Max int */
+#define ODBI_MAX_INT 2147483647
+
+/* For db->poolstat[] */
+#define ODBI_POOL_UNLOADED   0
+#define ODBI_POOL_LOADED     1
+#define ODBI_POOL_RELEASED   2
+
+
+void ODBI_print_db_metadata(FILE *fp, 
+			    void *vdb,
+			    int complete_info)
+{
+  ODBI_db_t *db = vdb;
+  DRHOOK_START(ODBI_print_db_metadata);
+  
+  if (db && complete_info) { 
+    int retcode = 0;
+    /* Database metadata (only complete info returned) */
+    /* ODBI_connect already returns partial metadata */
+    
+    int tag = ODBCS_TAG_DB_METADATA;
+    
+    if (!fp) fp = db->fp;
+    
+    Writen(DBCLI->sockfd, &tag, sizeof(tag));
+    if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+    
+    /* now reading from socket */
+    echo(&retcode, odbcs_tagname[tag],
+	 DBCLI->sockfd, fileno(fp), 
+	 DBCLI->timeout, DBCLI->verbose, db->swapbytes, NULL);
+  } /* if (db) */
+  
+  DRHOOK_END(0);
+}
+
+
+void ODBI_print_query_metadata(FILE *fp, 
+			       void *vq)
+{
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_print_query_metadata);
+  
+  if (q) { /* Query metadata */
+    /* not implemented yet */
+  } /* if (q) */
+  
+  DRHOOK_END(0);
+}
+
+
+void *ODBI_connect(const char *dbname,
+                   const char *params,
+                   ...)
+{
+  FILE *fp = NULL;
+  ODBI_db_t *db = NULL;
+  DRHOOK_START(ODBI_connect);
+  
+  if (dbname) { /* Skip leading whitespace */
+    while (*dbname && isspace(*dbname)) dbname++;
+  }
+  
+  if (STRLEN(dbname) > 0) {
+    int db_is_devnull = strequ(dbname,"/dev/null");
+    char                *pdbname = STRDUP(dbname);
+    /* int                  serv_port = 11998; */
+    int                  serv_port = PORT_DEFAULT;
+    /* int                  timeout = 600; */
+    int                  timeout = TIMEOUT_DEFAULT;
+    int                  timeout_env = 0;
+    int                  timeout_changed = 0;
+    int                  verbose = 0;
+    int                  verbose_env = 0;
+    int                  verbose_changed = 0;
+    struct sockaddr_in   servaddr;
+    const char          *IP_addr = "127.0.0.1"; /* i.e. localhost */
+    int n;
+    const unsigned int expected_magic_word = ODBI;
+    unsigned int magic_word;
+    int info[ODBCS_INFO];
+    int datapath_found = 0;
+    int server_version = 0;
+    const int ref1_server_version = 323515; /* The version on which the new ODBCS_TAGs verbose & timeout became available */
+    
+    CALLOC(db,1);
+    CALLOC(DBCLI,1);
+    
+    DBCLI->silent = 1;
+    
+    {
+      char *env = getenv("ODBCS_TIMEOUT");
+      if (env) {
+	timeout_env = atoi(env);
+	timeout_changed = 1;
+      }
+      else {
+	timeout_env = TIMEOUT_DEFAULT;
+	timeout_changed = 0;
+      }
+      if (timeout_env <= 0) {
+	timeout_env = TIMEOUT_DEFAULT;
+	timeout_changed = 0;
+      }
+    }
+    DBCLI->timeout = timeout = timeout_env;
+
+    {
+      char *env = getenv("ODBCS_VERBOSE");
+      if (env) {
+	verbose_env = atoi(env);
+	verbose_changed = 1;
+      }
+      else {
+	verbose_env = 0;
+	verbose_changed = 0;
+      }
+      if (verbose_env != 0 && verbose_env != 1) {
+	verbose_env = 0;
+	verbose_changed = 0;
+      }
+    }
+    DBCLI->verbose = verbose = verbose_env;
+
+    (void) codb_versions_(NULL, NULL, &DBCLI->version, NULL);
+    DBCLI->odbsql = 1; /* By default *do use* fast odbsql -approach (no compilations) */
+
+    if (params) {
+      va_list ap;
+      va_start(ap, params);
+#if 0
+      fprintf(stderr,"client: params='%s'\n",params);
+#endif
+      {
+	char *s, *fmt;
+	int fmtlen = STRLEN(params) + 1;
+	ALLOC(fmt,fmtlen);
+	s = fmt;
+	while (*params) {
+	  if (!isspace(*params)) *s++ = *params;
+	  params++;
+	}
+	*s = '\0';
+	Vparam(db, 0, fmt, ap);
+	FREE(fmt);
+      }
+      va_end(ap);
+    }
+    fp = db->fp;
+
+    if (!datapath_found)
+    {
+      /* check whether dbname explicitly begins with "odb://", in which case
+	 chase for "odb://host/datapath/DBNAME" or "odb://host:port/datapath/DBNAME" */
+
+#if 0
+      fprintf(stderr,"odb://>pdbname='%s'\n",pdbname);
+      fprintf(stderr,"odb://>DBCLI->host='%s'\n",DBCLI->host ? DBCLI->host : NIL);
+      fprintf(stderr,"odb://>DBCLI->datapath='%s'\n",DBCLI->datapath ? DBCLI->datapath : NIL);
+      fprintf(stderr,"odb://>DBCLI->port=%d\n",DBCLI->port);
+#endif
+      if (strncaseequ(pdbname,"odb://",6)) {
+	char *p = STRDUP(pdbname+6);
+	char *colon = strchr(p,':');
+	char *first_slash = strchr(p,'/');
+	char *last_slash = strrchr(p,'/');
+	if (colon) {
+	  *colon = '\0';
+	  DBCLI->port = atoi(colon+1);
+	  FREE(DBCLI->host);
+	  DBCLI->host = STRDUP(p);
+	}
+	if (last_slash) { /* xxx/path/xxx/DBNAME */
+	  FREE(pdbname);
+	  pdbname = STRDUP(last_slash+1);
+	  *last_slash = '\0';
+	}
+	if (first_slash) {
+	  FREE(DBCLI->datapath);
+	  DBCLI->datapath = STRDUP(first_slash);
+   
+	  if (!colon) {
+	    *first_slash = '\0';
+	    FREE(DBCLI->host);
+	    DBCLI->host = STRDUP(p);
+	  }
+	  datapath_found = 1;
+	}
+	FREE(p);
+      } /* if (strncaseequ(pdbname,"odb://",6)) */
+#if 0
+      fprintf(stderr,"odb://<pdbname='%s'\n",pdbname);
+      fprintf(stderr,"odb://<DBCLI->host='%s'\n",DBCLI->host ? DBCLI->host : NIL);
+      fprintf(stderr,"odb://<DBCLI->datapath='%s'\n",DBCLI->datapath ? DBCLI->datapath : NIL);
+      fprintf(stderr,"odb://<DBCLI->port=%d\n",DBCLI->port);
+#endif
+    }
+
+    if (!datapath_found)
+    {
+      /* check whether dbname explicitly contains host and/or datapath + dbname
+	 i.e. "rcp"-format : host:/datapath and DBNAME is guessed from datapath
+	 Use odb://host:port/datapath/DBNAME if you want to supply port-number or DBNAME */
+
+      char *p = STRDUP(pdbname);
+      char *colon = strchr(p,':');
+      char *last_slash = strrchr(p,'/');
+#if 0
+      fprintf(stderr,">pdbname='%s'\n",pdbname);
+      fprintf(stderr,">DBCLI->host='%s'\n",DBCLI->host ? DBCLI->host : NIL);
+      fprintf(stderr,">DBCLI->datapath='%s'\n",DBCLI->datapath ? DBCLI->datapath : NIL);
+      fprintf(stderr,"p='%s'\n",p);
+#endif
+      if (last_slash) { /* xxx/path/xxx  and xxx is DBNAME */
+	char *dot;
+	FREE(pdbname);
+	pdbname = STRDUP(last_slash+1);
+/*AF */
+    dot = strchr(pdbname,'.'); /* xxx can be DBNAME.* */
+        if (dot)
+	  *dot = '\0';       /* remove .* if xxx is DBNAME.* */
+
+/* AF
+	*last_slash = '\0';
+     if dbname cannot be extracted from dbname input then choose option odb://
+*/
+      }
+      if (colon) {
+	*colon = '\0';
+	FREE(DBCLI->host);
+	DBCLI->host = STRDUP(p);  /* host */
+      }
+      if (last_slash) {
+	FREE(DBCLI->datapath);
+	if (colon) {
+	  DBCLI->datapath = STRDUP(colon+1);  /* host:xxx/path/xxx */
+	}
+	else {
+	  DBCLI->datapath = STRDUP(p); /* xxx/path/xxx */
+	}
+      }
+#if 0
+      fprintf(stderr,"<pdbname='%s'\n",pdbname);
+      fprintf(stderr,"<DBCLI->host='%s'\n",DBCLI->host ? DBCLI->host : NIL);
+      fprintf(stderr,"<DBCLI->datapath='%s'\n",DBCLI->datapath ? DBCLI->datapath : NIL);
+#endif
+      FREE(p);
+      if (STRLEN(DBCLI->datapath) > 0) datapath_found = 1;
+    }
+
+    db->fp_opened_here = 0;
+    if (!fp) {
+      db->fp = fopen("/dev/null","w");
+      if (db->fp) db->fp_opened_here = 1;
+      else db->fp = stdout;
+    }
+
+    if (STRLEN(DBCLI->datapath) == 0) {
+      err_msg("client: datapath not given");
+      db = NULL;
+      goto finish;
+    }
+
+    db->name = pdbname;
+    db->mode = STRDUP("READONLY"); /* for now */
+
+    DBCLI->hostname = STRDUP(DBCLI->host); /* Usually the non-IP-address hostname */
+    if (STRLEN(DBCLI->host) > 0 && !is_ipv4_addr(DBCLI->host)) { /* get server's IP-address */
+      int errflg = 0;
+      char *host = STRDUP(DBCLI->host);
+      struct hostent *h;
+      h = gethostbyname(host);
+      if (h && h->h_addrtype == AF_INET) {
+	char **pptr;
+	char str[ODBCS_INET_ADDRSTRLEN];
+	const char *p = NULL;
+	pptr = h->h_addr_list;
+	for ( ; *pptr != NULL ; pptr++) {
+	  p = Inet_ntop(h->h_addrtype, *pptr, str, sizeof(str));
+	}
+	if (p) {
+	  FREE(DBCLI->host);
+	  DBCLI->host = STRDUP(p);
+	}
+	else
+	  errflg++;
+      }
+      else
+	errflg++;
+      if (errflg) {
+	err_msg("client: unable to determine the server-host's (%s) IP-address", host);
+	db = NULL;
+	goto finish;
+      }
+      FREE(host);
+    }
+    else if (STRLEN(DBCLI->host) == 0) { /* assume server is a localhost */
+      DBCLI->host = STRDUP(IP_addr);
+    }
+    if (DBCLI->port <= MIN_PORT) DBCLI->port = serv_port;
+
+    DBCLI->sockfd = Socket(AF_INET, SOCK_STREAM, 0);
+
+    bzero(&servaddr, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons(DBCLI->port);
+    Inet_pton(AF_INET, DBCLI->host, &servaddr.sin_addr);
+
+    Connect(DBCLI->sockfd, (SA *) &servaddr, sizeof(servaddr), 
+	    DBCLI->host, DBCLI->port, DBCLI->timeout, DBCLI->hostname,
+	    DBCLI->verbose);
+
+    /* Initial handshake : determine whether client/server have the same endianity */
+    
+    Writen(DBCLI->sockfd, &expected_magic_word, sizeof(expected_magic_word));
+
+    n = Readn_timeo(DBCLI->sockfd, info, sizeof(info), 10); /* Give 10 seconds max to get this info */
+    if (n != sizeof(info)) {
+      err_msg("client: initial handshake failed");
+      db = NULL;
+      goto finish;
+    }
+
+    magic_word = info[0];
+    db->swapbytes = (magic_word != expected_magic_word);
+
+    if (db->swapbytes) {
+      n = ODBCS_INFO - 1;
+      swap4bytes_(&info[1], &n);
+    }
+
+    DBCLI->timeout = MAX(DBCLI->timeout, 10);
+    timeout = DBCLI->timeout;
+    if (info[1] < DBCLI->timeout) {
+      DBCLI->timeout = timeout = info[1];
+    }
+    verbose = info[2];
+    DBCLI->verbose |= verbose;
+
+    server_version = info[3];
+
+    if (DBCLI->verbose) {
+      fprintf(stderr,"client: swapbytes = %d (expected=%u, got=%u); timeout=%d/verbose=%d/server_version=%d\n", 
+	      db->swapbytes, expected_magic_word, magic_word,
+	      DBCLI->timeout, DBCLI->verbose, server_version);
+    }
+
+    if (db_is_devnull) {
+      /* This was for starting server at remote_host purposes only */
+      (void) ODBI_disconnect(db);
+      exit(0);
+    }
+
+    setup_sig("client",&DBCLI->timeout,&DBCLI->verbose,NULL);
+
+    { /* for now */
+      int n;
+      int tag;
+      char *params = NULL;
+
+      tag = ODBCS_TAG_CONNECT;
+      Writen(DBCLI->sockfd, &tag, sizeof(tag));
+      if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+
+      n = 0;
+      if (STRLEN(db->name) > 0) n += STRLEN("dbname=") + STRLEN(db->name) + 1;
+      if (STRLEN(db->mode) > 0) n += STRLEN("mode=") + STRLEN(db->mode) + 1;
+      if (STRLEN(DBCLI->datapath) > 0) n += STRLEN("datapath=") + STRLEN(DBCLI->datapath) + 1;
+      if (STRLEN(DBCLI->workdir) > 0) n += STRLEN("workdir=") + STRLEN(DBCLI->workdir) + 1;
+      FREE(DBCLI->user);
+      DBCLI->user = STRDUP(getlogin());
+      if (STRLEN(DBCLI->user) == 0) {
+	char *env = getenv("LOGNAME");
+	if (!env) env = getenv("USER");
+	if (env) {
+	  FREE(DBCLI->user);
+	  DBCLI->user = STRDUP(env);
+	}
+      }
+      if (STRLEN(DBCLI->user) > 0) n += STRLEN("user=") + STRLEN(DBCLI->user) + 1;
+      if (STRLEN(DBCLI->password) > 0) n += STRLEN("password=") + STRLEN(DBCLI->password) + 1;
+      if (STRLEN(DBCLI->poolmask) > 0) n += STRLEN("poolmask=") + STRLEN(DBCLI->poolmask) + 1;
+      if (STRLEN(DBCLI->exe) > 0) n += STRLEN("exe=") + STRLEN(DBCLI->exe) + 1;
+      FREE(DBCLI->clihost);
+      FREE(DBCLI->cliaddr);
+      {
+	int errflg = 0;
+	char host[255];
+	struct hostent *h;
+	gethostname(host,sizeof(host));
+	h = gethostbyname(host);
+	if (h && h->h_addrtype == AF_INET) {
+	  char **pptr;
+	  char str[ODBCS_INET_ADDRSTRLEN];
+	  const char *p = NULL;
+	  pptr = h->h_addr_list;
+	  DBCLI->clihost = STRDUP(h->h_name);
+	  for ( ; *pptr != NULL ; pptr++) {
+	    p = Inet_ntop(h->h_addrtype, *pptr, str, sizeof(str));
+	  }
+	  if (p) {
+	    DBCLI->cliaddr = STRDUP(p);
+	  }
+	  else
+	    errflg++;
+	}
+	else
+	  errflg++;
+	if (errflg) {
+	  err_msg("client: unable to determine client-host's (%s) IP-address", host);
+	  db = NULL;
+	  goto finish;
+	}
+      }
+      if (STRLEN(DBCLI->clihost) > 0) n += STRLEN("clihost=") + STRLEN(DBCLI->clihost) + 1;
+      if (STRLEN(DBCLI->cliaddr) > 0) n += STRLEN("cliaddr=") + STRLEN(DBCLI->cliaddr) + 1;
+      if (DBCLI->verbose) n += STRLEN("verbose") + 1;
+      if (DBCLI->silent) n += STRLEN("silent") + 1;
+      if (DBCLI->metadata) n += STRLEN("metadata") + 1;
+      if (DBCLI->clean) n += STRLEN("clean") + 1;
+      if (DBCLI->keep) n += STRLEN("keep") + 1;
+      if (db->io_method > 0) n += STRLEN("io_method=") + 20;
+      if (DBCLI->timeout > 0) n += STRLEN("timeout=") + 20;
+      n += STRLEN("version=") + 20;
+      n += ((DBCLI->odbsql == 0) ? STRLEN("noodbsql") : STRLEN("odbsql")) + 1;
+
+      ALLOC(params,n);
+      *params = '\0';
+
+      if (STRLEN(db->name) > 0) 
+	{ strcat(params,"dbname="); strcat(params,db->name); strcat(params,";"); }
+      if (STRLEN(db->mode) > 0) 
+	{ strcat(params,"mode="); strcat(params,db->mode); strcat(params,";"); }
+      if (STRLEN(DBCLI->datapath) > 0) 
+	{ strcat(params,"datapath="); strcat(params,DBCLI->datapath); strcat(params,";"); }
+      if (STRLEN(DBCLI->workdir) > 0) 
+	{ strcat(params,"workdir="); strcat(params,DBCLI->workdir); strcat(params,";"); }
+      if (STRLEN(DBCLI->user) > 0) 
+	{ strcat(params,"user="); strcat(params,DBCLI->user); strcat(params,";"); }
+      if (STRLEN(DBCLI->password) > 0) 
+	{ strcat(params,"password="); strcat(params,DBCLI->password); strcat(params,";"); }
+      if (STRLEN(DBCLI->poolmask) > 0) 
+	{ strcat(params,"poolmask="); strcat(params,DBCLI->poolmask); strcat(params,";"); }
+      if (STRLEN(DBCLI->exe) > 0) 
+	{ strcat(params,"exe="); strcat(params,DBCLI->exe); strcat(params,";"); }
+      if (STRLEN(DBCLI->clihost) > 0) 
+	{ strcat(params,"clihost="); strcat(params,DBCLI->clihost); strcat(params,";"); }
+      if (STRLEN(DBCLI->cliaddr) > 0) 
+	{ strcat(params,"cliaddr="); strcat(params,DBCLI->cliaddr); strcat(params,";"); }
+      if (DBCLI->verbose) 
+	{ strcat(params,"verbose"); strcat(params,";"); }
+      if (DBCLI->silent) 
+	{ strcat(params,"silent"); strcat(params,";"); }
+      if (DBCLI->metadata) 
+	{ strcat(params,"metadata"); strcat(params,";"); }
+      if (DBCLI->clean) 
+	{ strcat(params,"clean"); strcat(params,";"); }
+      if (DBCLI->keep) 
+	{ strcat(params,"keep"); strcat(params,";"); }
+      if (db->io_method > 0) { 
+	char s[19]; 
+	snprintf(s,sizeof(s),"%d;",db->io_method);
+	strcat(params,"io_method="); 
+	strcat(params,s); 
+      }
+      if (DBCLI->timeout > 0) { 
+	char s[19];
+	snprintf(s,sizeof(s),"%d;",DBCLI->timeout);
+	strcat(params,"timeout=");
+	strcat(params,s); 
+      }
+      {
+	char s[19];
+	snprintf(s,sizeof(s),"%d;",DBCLI->version);
+	strcat(params,"version=");
+	strcat(params,s); 
+      }
+      if (DBCLI->odbsql == 0)
+	{ strcat(params, "noodbsql"); strcat(params,";"); }
+      else
+	{ strcat(params, "odbsql"); strcat(params,";"); }
+
+      n = STRLEN(params);
+      Writen(DBCLI->sockfd, &n, sizeof(n));
+      if (DBCLI->verbose) fprintf(stderr,"client: written length = %d\n", n);
+      Writen(DBCLI->sockfd, params, n);
+      if (DBCLI->verbose) fprintf(stderr,"client: written params = %d bytes\n", n);
+
+      FREE(params);
+
+      /* now reading from socket */
+      {
+	int retcode = 0;
+	int outlen = 0;
+	char *out = 
+	  echo(&retcode, 
+	       odbcs_tagname[tag],
+	       DBCLI->sockfd, -1, 
+	       DBCLI->timeout, DBCLI->verbose, db->swapbytes, &outlen);
+	if (retcode != 0 || !out) { /* Failure */
+	  db = NULL;
+	  goto finish;
+	}
+	/* Writen(fileno(db->fp), out, outlen); */
+	{ /* Get some (partial) DB metadata */
+	  int found = 0;
+	  db->npools = find_int(out,"\nnumber_of_pools=",&found);
+	  if (DBCLI->verbose) fprintf(stderr,"client: number_of_pools=%d, found=%d\n",
+				      db->npools, found);
+	  db->io_method = find_int(out,"\nio_method=",&found);
+	  if (DBCLI->verbose) fprintf(stderr,"client: io_method=%d, found=%d\n",
+				      db->npools, found);
+	}
+	FREE(out);
+      }
+
+      if (verbose_changed || timeout_changed) {
+	setup_sig("client",&DBCLI->timeout,&DBCLI->verbose,NULL);
+      }
+
+      if (server_version >= ref1_server_version) {
+	/* Send the current values of timeout & verbose (i.e. possibly different values 
+	   than the server is having right now), but only if they have changed from their defaults */
+
+	if (verbose_changed) {
+	  tag = ODBCS_TAG_VERBOSE;
+	  Writen(DBCLI->sockfd, &tag, sizeof(tag));
+	  if (DBCLI->verbose || verbose_env) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+	  Writen(DBCLI->sockfd, &verbose_env, sizeof(verbose_env));
+	  if (DBCLI->verbose || verbose_env) fprintf(stderr,"client: new verbose value = %d\n",verbose_env);
+	  DBCLI->verbose = verbose_env;
+	}
+
+	if (timeout_changed) {
+	  tag = ODBCS_TAG_TIMEOUT;
+	  Writen(DBCLI->sockfd, &tag, sizeof(tag));
+	  if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+	  Writen(DBCLI->sockfd, &timeout_env, sizeof(timeout_env));
+	  if (DBCLI->verbose) fprintf(stderr,"client: new timeout value = %d secs\n",timeout_env);
+	  DBCLI->timeout = timeout_env;
+	}
+      } /* if (server_version >= ref1_server_version) */
+    }
+
+  } /* if (dbname) */
+
+  add_db_chain(db);
+ finish:
+  DRHOOK_END(0);
+  return db;
+}
+
+
+void *ODBI_prepare(void *vdb,
+		   const char *viewname,
+		   const char *query_string)
+{
+  char *out = NULL;
+  ODBI_db_t *db = vdb;
+  ODBI_query_t *q = NULL;
+  DRHOOK_START(ODBI_prepare);
+
+  if (DBCLI->verbose) 
+    fprintf(stderr,
+	    "client[ODBI_prepare]: viewname=\"%s\", query_string=\"%s\"\n",
+	    viewname ? viewname : NIL,
+	    query_string ? query_string : NIL);
+	  
+  if (db) {
+    db->nquery++;
+    REALLOC(db->query, db->nquery);
+    q = &db->query[db->nquery-1];
+    q->name = viewname ? STRDUP(viewname) : STRDUP("@");
+    q->is_table = (*q->name == '@') ? 1 : 0;
+    q->query_string = NULL;
+    if (!q->is_table && STRLEN(query_string) > 0) 
+      q->query_string = STRDUP(query_string);
+    else 
+      q->query_string = STRDUP("");
+    q->fpcache = NULL; /* for now */
+    q->a = NULL;
+    q->poolno = 0;
+    q->nrows = 0;
+    q->ncols = 0;
+    q->ncols_fixed = 0;
+    q->ncols_all = 0;
+    q->start_row = 1;
+    q->maxrows = ODBI_MAX_INT;
+    q->ntot = 0;
+    q->nra = 0;
+    q->row_offset = 0;
+    q->string_count = 0;
+    QDB = db;
+    
+    if (q) {
+      int tag = ODBCS_TAG_PREPARE_QUERY;
+      int n;
+
+      db = QDB;
+      
+      Writen(DBCLI->sockfd, &tag, sizeof(tag));
+      if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+      
+      n = STRLEN(q->name);
+      Writen(DBCLI->sockfd, &n, sizeof(n));
+      if (DBCLI->verbose) fprintf(stderr,"client: written length = %d\n", n);
+      Writen(DBCLI->sockfd, q->name, n);
+      if (DBCLI->verbose) fprintf(stderr,"client: written viewname = %d bytes\n", n);
+
+      n = STRLEN(q->query_string);
+      Writen(DBCLI->sockfd, &n, sizeof(n));
+      if (DBCLI->verbose) fprintf(stderr,"client: written length = %d\n", n);
+      Writen(DBCLI->sockfd, q->query_string, n);
+      if (DBCLI->verbose) fprintf(stderr,"client: written query_string = %d bytes\n", n);
+
+      /* now reading from socket */
+
+      {
+	int retcode = 0;
+	int outlen = 0;
+	out = /* a null-terminated string with actual length of outlen */
+	  echo(&retcode, 
+	       odbcs_tagname[tag],
+	       DBCLI->sockfd, -1,
+	       DBCLI->timeout, DBCLI->verbose, db->swapbytes, &outlen);
+	if (retcode != 0 || !out || outlen <= 0) { /* Failure */
+	  q = NULL;
+	  goto finish;
+	}
+	Writen(fileno(db->fp), out, outlen);
+	if (out) {
+	  int found = 0;
+	  q->ncols_all = q->ncols_fixed = find_int(out,"\nnumber_of_columns=",&found);
+	  if (DBCLI->verbose) fprintf(stderr,"client: number_of_columns=%d, found=%d\n",
+				      q->ncols_fixed, found);
+	  if (found) {
+	    int jcol;
+	    int min_bufsize = MIN(10000,100*q->ncols_fixed);
+	    ODBI_limits(q,NULL,NULL,&min_bufsize);
+	    q->string_count = 0;
+	    CALLOC(q->cols, q->ncols_all);
+	    for (jcol=0; jcol<q->ncols_all; jcol++) {
+	      char *s = find_strnum(out,"\ncolumn_",jcol+1,&found); /* don't be fooled by extra_column_ */
+	      if (DBCLI->verbose) fprintf(stderr,"client: jcol=%d, s='%s'\n",jcol,s);
+	      if (found && s) {
+		char *p;
+		char delim = *s;
+		q->cols[jcol].type = STRDUP(s+1);
+		p = strchr(q->cols[jcol].type,delim);
+		if (p) {
+		  *p = '\0';
+		  q->cols[jcol].name = STRDUP(p+1);
+		  p = strchr(q->cols[jcol].name,delim);
+		  if (p) *p = '\0';
+		}
+		else {
+		  q->cols[jcol].name = STRDUP("????");
+		}
+		q->cols[jcol].dtnum = get_dtnum(q->cols[jcol].type);
+		if (q->cols[jcol].dtnum == DATATYPE_STRING) q->string_count++;
+		if (DBCLI->verbose) fprintf(stderr,"client: <col#%d> type='%s', name='%s', dtnum=%d\n",
+					    jcol+1, q->cols[jcol].type, 
+					    q->cols[jcol].name, q->cols[jcol].dtnum);
+	      }
+	      FREE(s);
+	    }
+	  }
+	  else {
+	    /* Failure */
+	    q = NULL;
+	    goto finish;
+	  }
+	}
+      }
+    }
+  }
+ finish:
+  FREE(out);
+  DRHOOK_END(0);
+  return q;
+}
+
+
+int ODBI_execute(void *vq)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_execute);
+  if (q) {
+    static int cnt = 0;
+    const int tag = ODBCS_TAG_EXECUTE_QUERY;
+    const int three = 3;
+    int limits[3];
+    ODBI_db_t *db = QDB;
+    int bufsize = DBCLI->bufsize;
+    int start_row = q->start_row;
+    int maxrows = MIN(bufsize/q->ncols_fixed, q->maxrows);
+
+    if (maxrows <= 0) goto finish; /* We are done */
+
+    Writen(DBCLI->sockfd, &tag, sizeof(tag));
+    if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+      
+    limits[0] = start_row;
+    limits[1] = maxrows;
+    limits[2] = bufsize;
+
+    Writen(DBCLI->sockfd, &limits, sizeof(limits));
+
+    if (DBCLI->verbose) fprintf(stderr,
+				"client#%d written limits[ODBI_execute] : %d, %d, %d\n",
+				++cnt, limits[0],limits[1],limits[2]);
+
+    /* now reading from socket */
+
+    {
+      const int one = 1;
+      int nbytes;
+      double drc = 0;
+      int len = 0;
+      int n = 0;
+      q->ncols = q->ncols_fixed;
+      nbytes = Readn_timeo(DBCLI->sockfd, &len, sizeof(len), DBCLI->timeout);
+      if (nbytes != sizeof(len)) {
+	int istat = -1;
+	err_msg("client: Server has detected a problem while in ODBI_execute()/INITIAL : status code = %d",
+		  istat);
+	rc = istat;
+	goto finish;
+      }
+      if (db->swapbytes) swap4bytes_(&len,&one);
+      if (DBCLI->verbose) fprintf(stderr,"client: obtained INITIAL len = %d, nbytes = %d\n",len,nbytes);
+      if (len > 0) {
+	while ((nbytes = 
+		Readn_timeo(DBCLI->sockfd, &drc, sizeof(drc), DBCLI->timeout)) == sizeof(drc)) {
+	  int nold = q->nrows * q->ncols; /* length of q->a so far */
+	  int inc_rows = 0;
+	  if (db->swapbytes) swap8bytes_(&drc,&one);
+	  n = drc;
+	  if (DBCLI->verbose) fprintf(stderr,
+				      "client: [ODBI_execute] nold = %d, n = %d, q->a=%p\n",
+				      nold,n,q->a);
+	  if (n <= 0) break; /* check the case "n < 0" later on ... */
+	  REALLOC(q->a, nold + n);
+	  nbytes = Readn_timeo(DBCLI->sockfd, &q->a[nold], sizeof(double) * n, DBCLI->timeout);
+	  if (nbytes != sizeof(double)*n) {
+	    int istat = -2;
+	    err_msg("client: Server has detected a problem while in ODBI_execute()/DATA : status code = %d",
+		    istat);
+	    rc = istat;
+	    goto finish;
+	  }
+	  inc_rows = n/q->ncols;
+	  if (DBCLI->verbose) fprintf(stderr,
+				      "client: [ODBI_execute] inc_rows=%d, n=%d, nrows=%d, ncols=%d\n",
+				      inc_rows, n, q->nrows, q->ncols);
+	  if (db->swapbytes) {
+	    swap8bytes_(&q->a[nold], &n);
+	    if (q->string_count > 0) { /* swap strings back */
+	      int jrow, jcol;
+	      double *d = &q->a[nold];
+	      for (jcol=0; jcol<q->ncols; jcol++) {
+		if (q->cols[jcol].dtnum == DATATYPE_STRING) {
+		  for (jrow=0; jrow<inc_rows; jrow++) {
+		    int offset = jrow * q->ncols + jcol;
+		    swap8bytes_(&d[offset], &one);
+		  } /* for (jrow=0; jrow<inc_rows; jrow++) */
+		} /* if (q->cols[jcol].dtnum == DATATYPE_STRING) */
+	      } /* for (jcol=0; jcol<q->ncols; jcol++) */
+	    } /* if (q->string_count > 0) */
+	  }
+#if 0
+	  {
+	    int jj, nn = nold + n;
+	    fprintf(stderr,"--> data items [%d:%d)=\n",nold,nn);
+	    for (jj=nold ; jj<nn; jj++) {
+	      fprintf(stderr,"jj=%d : %.14g\n",jj,q->a[jj]);
+	    }
+	    fprintf(stderr,"<-- end of data items\n");
+	  }
+#endif
+	  q->nrows += inc_rows;
+	  rc += n;
+	  q->start_row += inc_rows;
+	  q->maxrows -= inc_rows;
+	} /* while */
+	/* Read the final EOF-length away from the socket */
+	nbytes = Readn_timeo(DBCLI->sockfd, &len, sizeof(len), DBCLI->timeout);
+	if (db->swapbytes) swap4bytes_(&len,&one);
+	if (DBCLI->verbose) fprintf(stderr,"client: obtained EOF-length = %d, nbytes = %d\n",len,nbytes);
+	if (len < 0) { /* popen() has failed or pclose() detected an error */
+	  int istat = len;
+	  err_msg("client: Server has detected a problem while in ODBI_execute()/EOF-processing : status code = %d",
+		  istat);
+	  rc = istat;
+	  goto finish;
+	}
+      }
+    }
+  }
+ finish:
+  DRHOOK_END(rc);
+  return rc;
+}
+
+
+int ODBI_fetchonerow_array(void *vq,
+			int *nrows,
+			int *ncols,
+			double d[],
+			int nd)
+{
+ return ODBI_fetchrow_array(vq,nrows,ncols,d,nd);
+}
+
+int ODBI_fetchrow_array(void *vq,
+			int *nrows,
+			int *ncols,
+			double d[],
+			int nd)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_fetchrow_array);
+  if (nrows) *nrows = 0;
+  if (ncols) *ncols = 0;
+  if (q && d) {
+    ODBI_db_t *db = QDB;
+    int navail = q->nrows * q->ncols;
+    if (ncols) *ncols = q->ncols_fixed;
+    if (DBCLI->verbose)
+      fprintf(stderr,
+	      "client[1]: row_offset=%d, navail=%d, nrows=%d, ncols=%d, ncols_fixed=%d, a=%p\n",
+	      q->row_offset, navail, q->nrows, q->ncols, q->ncols_fixed, q->a);
+    if (q->row_offset == q->nrows) {
+      FREE(q->a);
+      q->row_offset = q->nrows = 0;
+      if (q->maxrows > 0) {
+	navail = ODBI_execute(q); /* get next chunk */
+	if (navail < 0) { /* Failure */
+	  rc = navail;
+	  goto finish;
+	}
+      }
+      else {
+	navail = 0; /* we are done already */
+      }
+    }
+    if (DBCLI->verbose)
+      fprintf(stderr,
+	      "client[2]: row_offset=%d, navail=%d, nrows=%d, ncols=%d, ncols_fixed=%d, a=%p\n",
+	      q->row_offset, navail, q->nrows, q->ncols, q->ncols_fixed, q->a);
+    if (navail > 0 && q->a) {
+      int j, offset = q->row_offset * q->ncols;
+      rc = MIN(navail-offset, nd);
+    if (DBCLI->verbose)
+      fprintf(stderr,
+	      "client[3]: offset=%d, navail=%d, nd=%d, rc=%d\n",
+	      offset, navail, nd, rc);
+      for (j=0; j<rc; j++) d[j] = q->a[j+offset];
+      if (nrows) *nrows = rc/q->ncols;
+      if (ncols) *ncols = q->ncols;
+      q->row_offset += rc/q->ncols;
+    }
+    if (DBCLI->verbose)
+      fprintf(stderr,
+	      "client[4]: row_offset=%d, navail=%d, nrows=%d, ncols=%d, ncols_fixed=%d, a=%p\n",
+	      q->row_offset, navail, q->nrows, q->ncols, q->ncols_fixed, q->a);
+  }
+ finish:
+  DRHOOK_END(nrows ? *nrows : 0);
+  return rc;
+}
+
+
+int ODBI_finish(void *vq)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_finish);
+  /* not implemented yet */
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+int ODBI_disconnect(void *vdb)
+{
+  ODBI_db_t *db = vdb;
+  int rc = 0;
+  DRHOOK_START(ODBI_disconnect);
+  if (db) {
+    int j;
+    const int save = 0;
+    if (DBCLI) {
+      int tag = ODBCS_TAG_BYEBYE;
+      Writen(DBCLI->sockfd, &tag, sizeof(tag));
+      if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+      Shutdown(DBCLI->sockfd,SHUT_WR); /* used to be: Close(DBCLI->sockfd); */
+      FREE(DBCLI->host);
+      FREE(DBCLI->hostname);
+      FREE(DBCLI->datapath);
+      FREE(DBCLI->poolmask);
+      FREE(DBCLI->user);
+      FREE(DBCLI->password);
+      FREE(DBCLI->workdir);
+      FREE(DBCLI->exe);
+      FREE(DBCLI->clihost);
+      FREE(DBCLI->cliaddr);
+    }
+    FREE(db->name);
+    FREE(db->mode);
+    for (j=0; j<db->nquery; j++) {
+      ODBI_query_t *q = &db->query[j];
+      /* (void) ODBI_finish(q); */ /* for now */
+      FREE(q->name);
+      FREE(q->query_string);
+      if (q->cols) {
+	int jcol;
+	for (jcol=0; jcol<q->ncols_all; jcol++) {
+	  FREE(q->cols[jcol].name);
+	  FREE(q->cols[jcol].type);
+	}
+	FREE(q->cols);
+      }
+    }
+    FREE(db->query);
+    FREE(db->poolstat);
+    if (db->fp_opened_here) fclose(db->fp);
+    rm_db_chain(db);
+    FREE(db);
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+double ODBI_bind_param(void *vq, 
+		       const char *param_name, 
+		       double new_value)
+{
+  ODBI_query_t *q = vq;
+  double old_value = 0;
+  DRHOOK_START(ODBI_bind_param);
+  if (param_name && q) {
+    ODBI_db_t *db = QDB;
+    int len;
+    int tag = ODBCS_TAG_BIND_PARAM;
+    if (*param_name == '$') param_name++;
+    len = STRLEN(param_name);
+    Writen(DBCLI->sockfd, &tag, sizeof(tag));
+    if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+    Writen(DBCLI->sockfd, &len, sizeof(len));
+    if (DBCLI->verbose) fprintf(stderr,"client: written length = %d\n",len);
+    Writen(DBCLI->sockfd, param_name, len);
+    if (DBCLI->verbose) fprintf(stderr,"client: written param name of length %d bytes\n",len);
+    Writen(DBCLI->sockfd, &new_value, sizeof(new_value));
+    if (DBCLI->verbose) fprintf(stderr,"client: written param itself, length %d bytes\n",len);
+  }
+  DRHOOK_END(0);
+  return old_value;
+}
+
+
+void ODBI_limits(void *vq,
+		 int *start_row,
+		 int *maxrows,
+		 int *bufsize)
+{
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_limits);
+  if (q) {
+    ODBI_db_t *db = QDB;
+
+    if (start_row) {
+      if (*start_row <= 0) *start_row = 1;
+      q->start_row = *start_row;
+    }
+
+    if (maxrows) {
+      if (*maxrows < 0) *maxrows = ODBI_MAX_INT;
+      q->maxrows = *maxrows;
+    }
+
+    if (bufsize) {
+      if (*bufsize < q->ncols_fixed) *bufsize = q->ncols_fixed;
+      DBCLI->bufsize = *bufsize;
+    }
+  }
+  DRHOOK_END(0);
+}
+
+
+int ODBI_fetchfile(void *vq,
+		   const char *filename,
+		   const char *fileformat)
+{
+#if 0
+  const char dbgfile[] = "/tmp/fetchfile.client";
+#else
+  const char dbgfile[] = "/dev/null";
+#endif
+  FILE *dbgfp = fopen(dbgfile, "w");
+  int rc = 0;
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_fetchfile);
+  setvbuf(dbgfp, (char *)NULL, _IONBF, 0);
+  if (q && filename && fileformat) {
+    int len;
+    const int tag = ODBCS_TAG_FETCHFILE;
+    const int one = 1;
+    const int three = 3;
+    int limits[3];
+    ODBI_db_t *db = QDB;
+    int bufsize = DBCLI->bufsize;
+    int start_row = q->start_row;
+    int maxrows = q->maxrows;
+    int nbytes;
+
+    /* tag */
+    Writen(DBCLI->sockfd, &tag, sizeof(tag));
+    if (DBCLI->verbose) fprintf(stderr,"client: written tag = %d (%s)\n",tag,odbcs_tagname[tag]);
+      
+    /* limits */
+    limits[0] = start_row;
+    limits[1] = maxrows;
+    limits[2] = bufsize;
+
+    Writen(DBCLI->sockfd, &limits, sizeof(limits));
+
+    if (DBCLI->verbose) fprintf(stderr,
+				"client written limits[ODBI_fetchfile] : %d, %d, %d\n",
+				limits[0],limits[1],limits[2]);
+
+    /* filename */
+    len = STRLEN(filename);
+    Writen(DBCLI->sockfd, &len, sizeof(len));
+    if (DBCLI->verbose) fprintf(stderr,"client: written filename length = %d\n",len);
+    Writen(DBCLI->sockfd, filename, len);
+    if (DBCLI->verbose) fprintf(stderr,"client: written filename = '%s'\n",filename);
+
+    /* fileformat */
+    len = STRLEN(fileformat);
+    Writen(DBCLI->sockfd, &len, sizeof(len));
+    if (DBCLI->verbose) fprintf(stderr,"client: written fileformat length = %d\n",len);
+    Writen(DBCLI->sockfd, fileformat, len);
+    if (DBCLI->verbose) fprintf(stderr,"client: written fileformat = '%s'\n",fileformat);
+
+    /* recv from server */
+
+    nbytes = Readn_timeo(DBCLI->sockfd, &len, sizeof(len), DBCLI->timeout);
+    if (nbytes != sizeof(len)) {
+      int istat = -1;
+      err_msg("client: Server has detected a problem while in ODBI_fetchfile()/INITIAL : status code = %d",
+	      istat);
+      rc = istat;
+      goto finish;
+    }
+    if (db->swapbytes) swap4bytes_(&len,&one);
+    if (DBCLI->verbose) fprintf(stderr,"client: obtained INITIAL len = %d, nbytes = %d\n",len,nbytes);
+
+    /* receive contents of the file */
+
+    if (len > 0) {
+      int timeout = MIN(10,DBCLI->timeout); /* No more that 10 sec wait accepted here; even that's too much */
+      int filesize = 0;
+      FILE *fp = NULL;
+
+      /* get the file size (even zero length) */
+      nbytes = Readn_timeo(DBCLI->sockfd, &filesize, sizeof(filesize), timeout);
+      if (nbytes != sizeof(filesize)) {
+	int istat = -2;
+	err_msg("client: Server has detected a problem while in ODBI_fetchfile(), "
+		"total file length: status code = %d",
+		istat);
+	rc = istat;
+	goto finish;
+      }
+      if (db->swapbytes) swap4bytes_(&filesize,&one);
+      if (DBCLI->verbose) fprintf(stderr,"client: obtained total file length = %d (nbytes = %d)\n",filesize,nbytes);
+
+      if (filesize > 0) {
+	nbytes = 0;
+	fp = Fopen(filename, "w");
+	fprintf(dbgfp, "filename = '%s' opened fp=%p, fileno(fp)=%d, filesize = %d\n",filename,fp,fileno(fp),filesize);
+	if (fp) {
+	  int nread = 0;
+	  char buf[IO_BUFSIZE_DEFAULT];
+	  while (nread < filesize) {
+	    int nlen = MIN(sizeof(buf), filesize - nread);
+	    nbytes = Readn_timeo(DBCLI->sockfd, buf, sizeof(*buf) * nlen, timeout);
+	    fprintf(dbgfp, "\tnbytes = %d, nlen = %d [IO_BUFSIZE_DEFAULT = %d]\n",
+		    nbytes, nlen, IO_BUFSIZE_DEFAULT);
+	    if (nbytes > 0) {
+	      int nwritten = fwrite(buf, sizeof(*buf), nbytes, fp);
+	      fprintf(dbgfp, "\t\tnwritten = %d bytes [incr]\n",nwritten);
+	      if (nwritten != nbytes) {
+		err_msg("client: Cannot write desired no. of bytes (%d) to file '%s' [format='%s']. "
+			"Written only %d bytes of %d. Is client's disk full or is there a permission problem ?",
+			nbytes, filename, fileformat, nwritten, nbytes);
+		rc = -4;
+		goto finish;
+	      }
+	      nread += nwritten;
+	      fprintf(dbgfp, "\t\tnread = %d bytes so far; filesize = %d bytes\n",nread,filesize);
+	    }
+	    else {
+	      break;
+	    }
+	  } /* while (nread < filesize) */
+	  Fclose(fp);
+	  if (nread != filesize) {
+	    err_msg("client: Couldn't write all data to file '%s' [format='%s']. "
+		    "Expected filesize %d, but written %d bytes",
+		    filename, fileformat, filesize, nread);
+	    rc = -5;
+	    goto finish;
+	  }
+	  rc = filesize;
+	}
+	else {
+	  err_msg("client: Unable to open file '%s' [format='%s'] for writing", filename, fileformat);
+	  rc = -3;
+	  goto finish;
+	}
+      } /* if (filesize > 0) */
+      else {
+	err_msg("client: Unable to create file '%s' [format='%s'] : filesize = %d\n",
+		filename, fileformat, filesize);
+	rc = -6;
+	goto finish;
+      }
+
+      /* Read the final EOF-length away from the socket */
+      nbytes = Readn_timeo(DBCLI->sockfd, &len, sizeof(len), timeout);
+      if (db->swapbytes) swap4bytes_(&len,&one);
+      if (DBCLI->verbose) fprintf(stderr,"client: obtained EOF-length = %d, nbytes = %d\n",len,nbytes);
+      if (len < 0) { /* popen() has failed or pclose() detected an error */
+	int istat = len;
+	err_msg("client: Server has detected a problem while in ODBI_fetchfile()/EOF-processing : status code = %d",
+		istat);
+	rc = istat;
+	goto finish;
+      }
+
+    } /* if (len > 0) */
+
+  finish:
+    ODBI_finish(q);
+
+  }
+  DRHOOK_END(rc >= 0 ? rc : 0);
+  fprintf(dbgfp,"rc = %d\n",rc);
+  fclose(dbgfp);
+  return rc;
+}
+
+
+#include "odbi_shared.c"
+
+#else
+
+void dummy_ODBI_client() { }
+void Vparam() {}
+#endif
diff --git a/odb/src/aux/odbi_common.c b/odb/src/aux/odbi_common.c
new file mode 100644
index 0000000..ca67c86
--- /dev/null
+++ b/odb/src/aux/odbi_common.c
@@ -0,0 +1,385 @@
+/*! 
+    \file odbi_common.c
+    \brief ODB API both for client-server and direct usage
+
+     Contains a set of high-level subroutines to be used to interrogate ODB database (read-only).
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "privpub.h"
+#include "cdrhook.h"
+
+#include "odbi.h"
+#include "odbi_direct.h"
+#include "odbi_cs.h"
+#include "odb.h"
+#include "odbi_struct.h"
+
+#define ODBI_DIRECT 1
+#define ODBI_CLIENT 1
+
+int ODBI_errno;      /*!< Variable to store ODBI error code. 0 if OK */   
+
+
+int ODBI_direct = 0; /*!< 1 if local database and 0 otherwise. Default 0 */
+
+
+/*!
+  SET $var = value. Overrides $-variable defaults found in the given SQL request; $ can be missing
+  @param q ODBI query i.e. contains all information concerning the current SQL query. 
+         q->info may be updated to contain the parameter name (var) and its value
+  @param param_name The variable name ($var or var)
+  @param new_value The new value for this parameter.
+  @return The old value for this parameter or 0 if the variable was never set before.
+ */
+double ODBI_bind_param
+(void *q, 
+ const char *param_name, 
+ double new_value) {
+
+  if (ODBI_direct)
+    return D_ODBI_bind_param(q, param_name, new_value);
+  else
+    return CS_ODBI_bind_param(q, param_name, new_value);
+}
+
+
+/*!
+  Connect to a given a database name and initialise the database structure ODBI_db_t. If the database name contains ":", the client/server mode is disabled and the database will be directly accessed from disk.
+  @param dbname The ODB database name. Its form will depend on the access mode:
+                - direct access: the database name contains the path to the database. The database name (associated with *.sch file) will be guessed from the path (ex:/hugetmp/data/CCMA --> CCMA database)
+                - remote access (client/server mode): the database name can be given in various way:
+		    -# odb://host/datapath/DBNAME         
+                    -# odb://host:port/datapath/DBNAME    
+                    -# host:/datapath in which case the DBNAME is guessed from datapath     
+                    -# /datapath in which case the DBNAME is guessed from datapath                       
+                    -# DBNAME  in which case the list of parameters "params" is mandatory
+   The default dbname is ECMA.
+  @param params The list of parameter types to be used to connect to a remote database. It is usually set to NULL in direct mode (no client/server) or if the database name was given as a), b) or c) i.e. containing all information for remote connection. The following can be specified:
+     - fp=\%F               a FILE pointer to return output results (associated to /dev/null by default)
+     - host=\%s             the remote hostname or its IP address. Default: 127.0.0.1
+     - port=\%d             the server port number. Default: mod(uid,10000)+10000)
+     - timeout=\%d          timeout in seconds. Default: 3600 
+     - datapath=\%s         path to the database. No default.
+     - poolmask=\%s         the list of pools to be used (use "," as a separator i.e. "1,2,3") Can be used for both direct and client/server database access.
+     Use ";" as a separator i.e. "fp=%F;host=%s;port=%d;timeout=%d;datapath=%s;poolmask=%s"
+     Defaults are given in odb/include/odbcsdefs.h
+  @param ... Meant to be used for client/server mode and is associated to params (which give the type of the variable argument).
+  @return The ODB handle (ODBI_db_t) associated to the connected database
+*/
+void *ODBI_connect
+(const char *dbname,
+ const char *params, 
+ ...)  {
+  FILE *fp = NULL;
+  char *server_host = NULL;
+  int server_port = 0;
+  int server_timeout = 3600;
+  char *server_datapath = NULL;
+  char *poolmask = strdup(""); 
+  char *options = /* compulsory parameters for C/S */
+      strdup("fp=%F;host=%s;port=%d;timeout=%d;datapath=%s;poolmask=%s"); 
+
+  ODBI_direct = 1; 
+
+  if (params) {
+
+    va_list ap;
+
+    char *s, *fmt;
+    int fmtlen = STRLEN(params) + 1;
+  
+    if (strstr(params,"host") || strstr(params,"port"))
+      ODBI_direct=0;
+
+    va_start(ap, params);
+    ALLOC(fmt,fmtlen);
+    s = fmt; 
+    while (*params) {
+      if (!isspace(*params)) *s++ = *params;
+      params++;
+    }
+    *s = '\0';
+
+    {
+      const char *delim = ";";
+      char *token = strtok(fmt,delim);
+    
+    /* Read list of arguments */
+      while (token) {
+	char *ss = STRDUP(token);
+	char *t = strchr(ss,'=');
+	char *lhs = ss;
+	union {
+	  char *s;
+	  int ii;
+	  double dd;
+	  FILE *fp;
+	} rhs;
+	int free_rhss = 0;
+	int do_process = 0;
+	
+	fmt = token;
+	if (t) {
+	  rhs.s = STRDUP(t+1);
+	  do_process = 1;
+	  *t = '\0'; /* affects "lhs" */
+	}
+	if (do_process) {
+	  do_process = 0;
+	  if (*rhs.s == '%') {
+	    char *s = strchr(fmt,'%');
+	    if (s) {
+	      fmt = s;
+	      fmt++;
+	      switch (*fmt++) {
+	      case 's':
+	      FREE(rhs.s);
+	      s = va_arg(ap, char *);
+	      rhs.s = STRDUP(s);
+	       fprintf(stderr,"Vparam(at %%s): '%s'\n",rhs.s); 
+	      free_rhss = 1;
+	      do_process = 1;
+	      break;
+	      case 'd':
+		FREE(rhs.s);
+		rhs.ii = va_arg(ap, int);
+		 fprintf(stderr,"Vparam(at %%f): %d\n",rhs.ii); 
+		free_rhss = 0;
+		do_process = 1;
+		break;
+	      case 'f':
+		FREE(rhs.s);
+		rhs.dd = va_arg(ap, double);
+		 fprintf(stderr,"Vparam(at %%f): %g\n",rhs.dd); 
+		free_rhss = 0;
+		do_process = 1;
+		break;
+	      case 'F':
+		FREE(rhs.s);
+		rhs.fp = va_arg(ap, FILE *);
+		 fprintf(stderr,"Vparam(at %%F): %p, fileno=%d\n",rhs.fp,fileno(rhs.fp)); 
+		free_rhss = 0;
+		do_process = 1;
+		break;
+	      } /* end switch *fmt++ */
+	    } /* end if s */
+	  } /* end if *rhs.s == '%' */
+	  if (strcaseequ(lhs,"fp"))              fp                = rhs.fp;
+	  else if (strcaseequ(lhs,"host"))       server_host       = STRDUP(rhs.s);
+	  else if (strcaseequ(lhs,"port"))       server_port       = rhs.ii;
+	  else if (strcaseequ(lhs,"timeout"))    server_timeout    = rhs.ii;
+	  else if (strcaseequ(lhs,"datapath"))   server_datapath   = STRDUP(rhs.s);
+	  else if (strcaseequ(lhs,"poolmask"))   poolmask          = STRDUP(rhs.s);
+	  
+	} /* end if do_process */
+	if (free_rhss) FREE(rhs.s);
+	FREE(ss);
+	
+	token = strtok(NULL,delim);
+	
+      } /* while (token) */
+    } 
+    va_end(ap);
+  }  /* if params NOT NULL */
+  
+  if (strchr(dbname, ':') || ODBI_direct == 0) {
+    ODBI_direct = 0; 
+    printf("Client/Server \n");
+    return (void *) CS_ODBI_connect(dbname,options
+		    , fp
+		    , server_host
+		    , server_port
+		    , server_timeout
+		    , server_datapath
+		    , poolmask );
+  } else {  
+    ODBI_direct = 1;   
+    printf("Direct access \n");
+    if (poolmask) 
+      setenv("ODB_PERMANENT_POOLMASK",poolmask, 1);
+    return (void *) D_ODBI_connect(dbname, NULL );
+  }
+}
+
+
+/*!
+   Disconnect from a local or remote database and free the ODB handle (ODBI_db_t). 
+   @param db Database handle (ODBI_db_t) 
+   @return an error code. 0 if OK.
+ */
+int ODBI_disconnect
+(void *db)  {
+  if (ODBI_direct)
+    return D_ODBI_disconnect(db);
+  else
+    return CS_ODBI_disconnect(db);
+}
+
+/*!
+   - In direct mode (fast_odbsql = 1):
+     -# When called first time (usually outside ODBI_fetchrow_array), it only initialises q->info (see odb/include/info.h).
+     -# When called later (usually in ODBI_fetchrow_array), it executes the SQL request associated to the query handle. 
+   - In client/server mode:
+     -# Execute the SQL request
+  @param q  Query handle (ODBI_query_t) to be executed
+  @return an error code. 0 if OK.
+ */
+int ODBI_execute
+(void *q)  {
+ if (ODBI_direct)
+    return D_ODBI_execute(q);
+  else
+    return CS_ODBI_execute(q);
+}
+/*!
+   Fetch a given number of rows associated to an existing query handle in an output array.
+   @param q      Query handle (ODBI_query_t)
+   @param nrows  [in] the number of rows to fetch and [out] the actual number of rows fetched 
+   @param ncols  Number of columns for this Query handle
+   @param d      Array where the result of the SQL query will be fetched. It has to be allocated and has a minimum size of nrows*ncols (nd) 
+   @param nd     Size of d (nrows*ncols)
+   @return An error code. 0 if OK.
+ */
+int ODBI_fetchrow_array
+(void *q,
+ int *nrows, 
+ int *ncols,
+ double d[],
+ int nd) {
+  if (ODBI_direct)
+    return D_ODBI_fetchrow_array(q,nrows,ncols,d,nd);
+  else
+    return CS_ODBI_fetchrow_array(q,nrows,ncols,d,nd);
+}
+
+/*!
+  - Meaningful for direct access only and when data is fetched pool by pool. It release the current query handle for the current pool and increase the pool number    
+  - In Client/server mode, it is not implemented yet.
+  @param q Query handle (ODBI_query_t)
+  @ return An error code. 0 if OK.
+ */
+int ODBI_finish 
+(void *q) {
+ if (ODBI_direct)
+    return D_ODBI_finish(q);
+  else
+    return CS_ODBI_finish(q);
+}
+
+/*!
+  Set limits for a given query handle
+  @param q          Query handle (ODBI_query_t)
+  @param start_row  if <=0 then sets the start row of the query handle to 1 else sets to its value
+  @param maxrows    if <=0 then sets to ODBI_MAX_INT (2147483647) else sets ot its value
+  @param bufsize    Sets the buffer size to be used for SQL retrievals. The minimum size is the number of columns in the SQL query
+ */
+void ODBI_limits
+(void *q,
+ int *start_row,
+ int *maxrows,
+ int *bufsize) {
+  if (ODBI_direct)
+    D_ODBI_limits(q,start_row,maxrows,bufsize);
+  else
+    CS_ODBI_limits(q,start_row,maxrows,bufsize);
+}
+
+
+/*!
+   Set the maximum name length. Default: 64
+   @param new_len Set the maximum name length to new_len
+   @return the old value for the maximum length
+ */
+int ODBI_maxnamelen
+(int new_len) {
+ if (ODBI_direct)
+    return D_ODBI_maxnamelen(new_len);
+  else
+    return CS_ODBI_maxnamelen(new_len);
+}
+
+/*!
+  Associate an SQL query to a given ODB database handle and return the associated query handle
+  @param db             ODB database handle (ODBI_db_t)
+  @param viewname       View name associated to the given SQL query (query_string)
+  @param query_string   Query
+  @return Query handle
+ */
+void *ODBI_prepare
+(void *db,
+ const char *viewname,
+ const char *query_string /* For now: applicable only for client */
+ ) {
+  if (ODBI_direct)
+    return (void *) D_ODBI_prepare(db, viewname, query_string);
+  else
+    return (void *) CS_ODBI_prepare(db, viewname, query_string);
+}
+
+/*!
+  Write the result of the SQL query associated to the given query handle in an output file. The output format is given as an argument of this function. Available output format:
+      - default           Ascii where field delimiter is space (" "), and output is rather compressed
+      - binary            binary format will be used for output
+      - plotobs           $ODB_PLOTTER compatible binary file for Magics will be created
+      - wplotobs          $ODB_PLOTTER compatible binary file for Magics will be created (wind-arrows)
+      - odbtool           input(s) for IDL/odbtool (by Phil Watts while at ECMWF, now in Eumetsat) will be created
+      - odbtk             field delimiters become "!,!" and unique column ids ($uniq#) will be printed as "zero-th" column
+      - odb               "odbviewer"/"odbless" .rpt-file format is emulated 
+      - netcdf            create NetCDF-file with ODB Conventions (lat/lon are in degrees)
+      - unetcdf           as "netcdf" above, but create without packing (lat/lon are in degrees)
+      - dump              similar to "default", but delimiter is comma "," (lat/lon are in degrees)
+      - bindump           similar to "binary", but all data will be printed row_wise + metadata & title-structure always embedded (lat/lon are in degrees)
+      - geo               (standard) Metview GEO-points file with "lat lon level date time value"
+      - geo:xyv           GEO-points file with "x/long y/lat value"
+      - geo:xy_vector     GEO-points file with "lat lon height date time u v"
+      - geo:polar_vector  GEO-points file with "lat lon height date time speed direction"
+
+  @param q           Query handle (ODBI_query_t)
+  @param filename    output filename
+  @param fileformat  output format. The default output format is "default"
+  @return Error code. 0 if OK.
+ */
+int ODBI_fetchfile
+(void *q,
+ const char *filename,
+ const char *fileformat) {
+  if (ODBI_direct)
+    return D_ODBI_fetchfile(q, filename, fileformat);
+  else
+    return CS_ODBI_fetchfile(q, filename, fileformat);
+}
+
+/*!
+   Write metadata of a given ODB database handle
+   @param fp             File pointer (where to print outputs)
+   @param db             ODB database handle (ODBI_db_t)
+   @param complete_info  write metadata only if complete_info is not null
+ */
+void ODBI_print_db_metadata
+(FILE *fp,
+ void *db,
+ int complete_info) {
+  if (ODBI_direct)
+    D_ODBI_print_db_metadata(fp, db, complete_info);
+  else
+    CS_ODBI_print_db_metadata(fp, db, complete_info);
+}
+
+/*!
+  Write metadata of a given query handle
+  @param fp File pointer  (where to print outputs)
+  @param q  Query handle
+ */
+void ODBI_print_query_metadata
+(FILE *fp,
+ void *q) {
+  if (ODBI_direct)
+    D_ODBI_print_query_metadata(fp, q);
+  else
+    CS_ODBI_print_query_metadata(fp, q);
+}
+
+#include "odbi_shared.c"
diff --git a/odb/src/aux/odbi_direct.c b/odb/src/aux/odbi_direct.c
new file mode 100644
index 0000000..458948e
--- /dev/null
+++ b/odb/src/aux/odbi_direct.c
@@ -0,0 +1,1341 @@
+
+/* odbi_direct.c */
+
+#include "privpub.h"
+#include "odb.h"
+#define ODBI_DIRECT 1
+#include "odbi.h"
+#include "pcma_extern.h"
+#include "iostuff.h"
+#include "cdrhook.h"
+
+#include "odbi_struct.h"
+#include "vparam.h"
+
+#define QDB q->db
+
+#include "info.h"
+#include "result.h"
+
+extern int fast_odbsql; /* =1, if -F was *not* supplied, otherwise =0 */
+
+
+static int version_threshold = 321533; /* ODB-version (CY32R1.533) after which
+					  the client version number becomes available */
+
+extern int odb_version; /* As supplied via -n option in the main-program */
+
+/* Local subroutines */
+
+PRIVATE void print_paths(FILE *fp,
+			 const char *dbname)
+{  
+  const char fmt[] = "ODB_%sPATH%s%s";
+  char *env = NULL;
+  int slen = STRLEN(fmt) + 4 + STRLEN(dbname) + 1; /* 4 for max("DATA","SRC","IDX") */
+  char *s;
+  DRHOOK_START(print_paths);
+  ALLOC(s, slen);
+
+  snprintf(s,slen,fmt,"SRC","_",dbname);
+  env = getenv(s);
+  if (!env) {
+    snprintf(s,slen,fmt,"SRC","","");
+    env = getenv(s);
+  }
+  if (env) fprintf(fp,"srcpath=%s\n",env);
+
+  snprintf(s,slen,fmt,"DATA","_",dbname);
+  env = getenv(s);
+  if (!env) {
+    snprintf(s,slen,fmt,"DATA","","");
+    env = getenv(s);
+  }
+  if (env) fprintf(fp,"datapath=%s\n",env);
+
+  snprintf(s,slen,fmt,"IDX","_",dbname);
+  env = getenv(s);
+  if (!env) {
+    snprintf(s,slen,fmt,"IDX","","");
+    env = getenv(s);
+  }
+  if (env) fprintf(fp,"idxpath=%s\n",env);
+  FREE(s);
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void print_consider_tables(FILE *fp,
+				   const char *dbname)
+{
+  const char fmt[] = "ODB_CONSIDER_TABLES%s%s";
+  char *env = NULL;
+  int slen = STRLEN(fmt) + 1 + STRLEN(dbname) + 1;
+  char *s;
+  DRHOOK_START(print_consider_tables);
+  ALLOC(s, slen);
+  snprintf(s,slen,fmt,"_",dbname);
+  env = getenv(s);
+  if (!env) {
+    snprintf(s,slen,fmt,"","");
+    env = getenv(s);
+  }
+  if (env) fprintf(fp,"consider_tables=%s\n",env);
+  FREE(s);
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void print_permanent_poolmask(FILE *fp,
+				      const char *dbname)
+{
+  const char fmt[] = "ODB_PERMANENT_POOLMASK%s%s";
+  char *env = NULL;
+  int slen = STRLEN(fmt) + 1 + STRLEN(dbname) + 1;
+  char *s;
+  DRHOOK_START(print_permanent_poolmask);
+  ALLOC(s, slen);
+  snprintf(s,slen,fmt,"_",dbname);
+  env = getenv(s);
+  if (!env) {
+    snprintf(s,slen,fmt,"","");
+    env = getenv(s);
+  }
+  if (env) fprintf(fp,"permanent_poolmask=%s\n",env);
+  FREE(s);
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void print_setvars(FILE *fp,
+			   const char *dbname,
+			   const char *viewname,
+			   void *vq)
+{
+  Boolean mdi_found = false;
+  double missing_value = 2147483647;
+  DRHOOK_START(print_setvars);
+  if (fp && dbname) { /* Print values of the SET-variables */
+    int it = viewname ? 1 : 0; /* A "feature" from OpenMP-port ;-( */
+    char *true_ddfile = NULL;
+    int nsetvar;
+    info_t *info = NULL;
+    if (fast_odbsql) {
+      ODBI_query_t *q = vq;
+      info = q ? q->info : NULL;
+      nsetvar = info ? info->nset : 0;
+      if (!viewname && nsetvar == 0 && dbname) {
+	/* Prepare to read dd-file directly */
+	int len = STRLEN(dbname);
+	true_ddfile = IOtruename(dbname, &len); /* $ODB_SRCPATH_<dbname>/<dbname>.dd */
+      }
+    }
+    else {
+      nsetvar = ODB_get_vars(dbname, viewname, it, 0, NULL);
+    }
+#if 0
+    {
+      fprintf(stderr,
+	      "print_setvars: dbname='%s', viewname='%s', it=%d : nsetvar=%d, true_ddfile = '%s'\n",
+	      dbname ? dbname : NIL,
+	      viewname ? viewname : NIL,
+	      it, nsetvar,
+	      true_ddfile ? true_ddfile : NIL);
+    }
+#endif
+    if (nsetvar > 0 || true_ddfile) {
+      int rc, j;
+      ODB_Setvar *setvar = NULL;
+
+      if (!true_ddfile) ALLOC(setvar, nsetvar);
+      else rc = nsetvar = 0;
+      
+      if (true_ddfile) {
+	FILE *fp = fopen(true_ddfile,"r");
+	if (fp) {
+	  char line[MAXLINE+1];
+	  while (fp && !feof(fp) && fgets(line, MAXLINE, fp)) {
+	    if (line[0] == '$') ++nsetvar;
+	  }
+	  rewind(fp);
+	  ALLOC(setvar, nsetvar);
+	  j = 0;
+	  while (fp && !feof(fp) && fgets(line, MAXLINE, fp)) {
+	    if (line[0] == '$') {
+	      char *blank = strchr(line, ' ');
+	      if (blank) {
+		*blank++ = '\0';
+		setvar[j].symbol = STRDUP(line+1);
+		setvar[j].value = atof(blank);
+		++j;
+	      }
+	    }
+	  }
+	  rc = nsetvar = j;
+	  fclose(fp);
+	} /* fp */
+	FREE(true_ddfile);
+      }
+      else if (info) {
+	rc = nsetvar;
+	for (j=0; j<rc; j++) {
+	  setvar[j].symbol = STRDUP(info->s[j].name);
+	  setvar[j].value = info->s[j].value;
+	}
+      }
+      else {
+	rc = ODB_get_vars(dbname, viewname, it, nsetvar, setvar);
+      }
+      fprintf(fp,"number_of_set_variables=%d\n",rc);
+      for (j=0; j<rc; j++) {
+	char *s = setvar[j].symbol;
+	if (s && *s == '$') s++;
+	if (s) {
+	  if (!mdi_found && strequ(s,"mdi")) {
+	    mdi_found = true;
+	    missing_value = setvar[j].value;
+	  }
+	  fprintf(fp,"set_%s=%.14g\n",s,setvar[j].value);
+	  FREE(setvar[j].symbol);
+	}
+      } /* for (j=0; j<nsetvar; j++) */
+      FREE(setvar);
+    } /* if (nsetvar > 0) */
+    else {
+      fprintf(fp,"number_of_set_variables=0\n");
+    }
+  }
+  fprintf(fp,"missing_value=%.14g\n", missing_value);
+  DRHOOK_END(0);
+}
+
+
+/* Maximum name length (can be *INCREASED* via ODBI_maxnamelen(newlength)) */
+PRIVATE int max_name_len = 64;
+
+int ODBI_maxnamelen(int new_len)
+{
+  int old_len = max_name_len;
+  DRHOOK_START(ODBI_maxnamelen);
+  if (new_len >= max_name_len) max_name_len = new_len;
+  DRHOOK_END(0);
+  return old_len;
+}
+
+/* Max int */
+#define ODBI_MAX_INT 2147483647
+
+/* For db->poolstat[] */
+#define ODBI_POOL_UNLOADED   0
+#define ODBI_POOL_LOADED     1
+#define ODBI_POOL_RELEASED   2
+
+
+void ODBI_print_db_metadata(FILE *fp,
+			    void *vdb,
+			    int complete_info)
+{
+  ODBI_db_t *db = vdb;
+  DRHOOK_START(ODBI_print_db_metadata);
+
+  if (db) { /* Database metadata */
+    if (!fp) fp = db->fp;
+    fprintf(fp,"ODBI\n");
+    fprintf(fp,"database=%s\n",db->name);
+    fprintf(fp,"open_mode=%s\n",db->mode);
+    fprintf(fp,"number_of_pools=%d\n",db->npools);
+    fprintf(fp,"io_method=%d\n",db->io_method);
+    print_paths(fp, db->name);
+    print_consider_tables(fp, db->name);
+    print_permanent_poolmask(fp, db->name);
+    if (complete_info) { /* behind a flag, since we don't always need this */
+      int jt, jcol;
+      fprintf(fp,"number_of_tables=%d\n",db->ntables);
+      for (jt=0; jt<db->ntables; jt++) {
+	fprintf(fp,"table_%d=%s\n",jt+1,db->tables[jt]);
+      }
+      for (jt=0; jt<db->ntables; jt++) {
+	ODBI_query_t *tq = ODBI_prepare(db,db->tables[jt],NULL);
+	ODBI_print_query_metadata(fp,tq);
+      }
+      print_setvars(fp, db->name, NULL, NULL);
+    }
+  } /* if (db) */
+  DRHOOK_END(0);
+}
+
+
+void ODBI_print_query_metadata(FILE *fp,
+			       void *vq)
+{
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_print_query_metadata);
+
+  if (q) { /* Query metadata */
+    int jcol;
+    /* Keep compatibility with older clients (before version_threshold);
+       however, formulas with division ('/') lead to a problem unless
+       client is relinked with newer libraries */
+    char *delim = (odb_version >= version_threshold) ? ODB_tag_delim : "/";
+    if (!fp) fp = QDB->fp;
+    fprintf(fp,"%s=%s\n",
+	    /* (q->is_table && is_a_query == 2) ? "table" : "query", q->name); [fix this] */
+	    (q->is_table) ? "table" : "query", q->name);
+    fprintf(fp,"number_of_columns=%d\n",q->ncols_fixed);
+
+    for (jcol=0; jcol<q->ncols_fixed; jcol++) {
+      unsigned int dtnum = ODBI_coltypenum(q,jcol+1);
+      const char *coltype = ODBI_coltype(q,jcol+1);
+      const char *colname = ODBI_colname(q,jcol+1);
+      const char *colnickname = ODBI_colnickname(q,jcol+1);
+      fprintf(fp,"column_%d=%s%s%s%s%s%u%s%s%s\n",
+	      jcol+1,
+	      delim, coltype,
+	      delim, colname,
+	      delim, dtnum,
+	      delim, colnickname,
+	      delim);
+    } /* for (jcol=0; jcol<q->ncols_fixed; jcol++) */
+
+    if (q->is_table && /* complete_info && */
+	q->ncols_all > q->ncols_fixed) { 
+      int jextra = 0;
+      fprintf(fp,"number_of_extra_columns=%d\n",q->ncols_all-q->ncols_fixed);
+      /* Print excess columns (valid for tables only) */
+      for (jcol=q->ncols_fixed; jcol<q->ncols_all; jcol++) {
+	unsigned int dtnum = ODBI_coltypenum(q,jcol+1);
+	const char *coltype = ODBI_coltype(q,jcol+1);
+	const char *colname = ODBI_colname(q,jcol+1);
+	int bitpos = q->cols[jcol].bitpos;
+	int bitlen = q->cols[jcol].bitlen;
+	fprintf(fp,"extra_column_%d=%s%s%s%s%s%u%s%d%s%d%s\n",
+		++jextra,
+		delim, coltype,
+		delim, colname,
+		delim, dtnum,
+		delim, bitpos,
+		delim, bitlen,
+		delim);
+      } /* for (jcol=0; jcol<q->ncols_fixed; jcol++) */
+    }
+    if (!q->is_table /* && complete_info */) {
+      print_setvars(fp, QDB->name, q->name, q);
+    }
+  } /* if (q) */
+
+  DRHOOK_END(0);
+}
+
+
+void *ODBI_connect(const char *dbname,
+		   const char *params,
+		   ...)
+{
+  FILE *fp = NULL;
+  ODBI_db_t *db = NULL;
+  DRHOOK_START(ODBI_connect);
+
+  if (dbname) {
+    int npools = 0;
+    int ntables = 0;
+    const char *mode = "READONLY";
+
+    CALLOC(db,1);
+    db->cli = NULL; /* this is *not* for client/server-model */
+
+    if (params) { /* Not implemented yet */
+      va_list ap;
+      va_start(ap, params);
+#if 0
+      fprintf(stderr,"direct: params='%s'\n",params);
+#endif
+      {
+	char *s, *fmt;
+	int fmtlen = STRLEN(params) + 1;
+	ALLOC(fmt,fmtlen);
+	s = fmt;
+	while (*params) {
+	  if (!isspace(*params)) *s++ = *params;
+	  params++;
+	}
+	*s = '\0';
+	Vparam(db, 0, fmt, ap);
+	FREE(fmt);
+      }
+      va_end(ap);
+    }
+    fp = db->fp;
+
+    db->fp_opened_here = 0;
+    if (!fp) {
+      db->fp = fopen("/dev/null","w");
+      if (db->fp) db->fp_opened_here = 1;
+      else db->fp = stdout;
+    }
+    db->name = STRDUP(dbname);
+    db->mode = STRDUP(mode);
+
+    if (fast_odbsql) {
+      db->handle = ODBc_open(dbname, "r", &npools, &ntables, NULL);
+      db->io_method = 5;
+    }
+    else {
+      f_odb_open_(dbname, mode, &npools, &db->handle
+		  /* Hidden arguments */
+		  , STRLEN(dbname), STRLEN(mode)
+		  );
+
+      f_odb_io_method_(&db->handle, &db->io_method);
+    }
+    if (db-> handle <=0) { /* database not found */
+      FREE(db);
+      db = NULL;
+    } else {
+      db->npools = npools;
+      CALLOC(db->poolstat, 1+npools); /* Implies ODBI_POOL_UNLOADED; 
+					 The "1+" is just to allow direct accessing with poolno=[1..npools] */
+      db->nquery = 0;
+      db->query = NULL;
+      db->swapbytes = 0;
+      db->tables = NULL;
+      
+      if (fast_odbsql) {
+	const char **tblname = ODBc_get_tablenames(db->handle, &ntables);
+	if (tblname && ntables > 0) {
+	  int jt;
+	  CALLOC(db->tables, ntables);
+	  for (jt=0; jt<ntables; jt++) db->tables[jt] = STRDUP(tblname[jt]);
+	}
+      }
+      else {
+	char *token = NULL;
+	char *saved = NULL;
+	int maxcols = ODB_maxcols();
+	int jt, len;
+	len = max_name_len * maxcols;
+	
+	ALLOC(saved, len * maxcols + 1);
+	f_odb_get_tablenames_(&db->handle, saved, &ntables
+			      /* Hidden arguments */
+			      , len
+			      );
+	
+	CALLOC(db->tables, ntables);
+	
+	token = strtok(saved,ODB_tag_delim);
+	jt = 0;
+	while (token) {
+	  db->tables[jt++] = STRDUP(token);
+	  token = strtok(NULL,ODB_tag_delim);
+	}
+	FREE(saved);
+      }
+      
+      db->ntables = ntables;
+    }  
+  } /* if (dbname) */
+    
+  DRHOOK_END(0);
+  return db;
+}
+
+
+void *ODBI_prepare(void *vdb,
+		   const char *viewname,
+		   const char *query_string)
+{
+  ODBI_db_t *db = vdb;
+  ODBI_query_t *q = NULL;
+  DRHOOK_START(ODBI_prepare);
+  if (db) {
+    db->nquery++;
+    REALLOC(db->query, db->nquery);
+    q = &db->query[db->nquery-1];
+    q->name = STRDUP(viewname);
+    q->is_table = (*q->name == '@') ? 1 : 0;
+    q->query_string = NULL;
+    if (!q->is_table && query_string) q->query_string = STRDUP(query_string);
+    q->fpcache = NULL; /* for now */
+    q->a = NULL;
+    q->poolno = 0;
+    q->nrows = 0;
+    q->ncols = 0;
+    q->ncols_fixed = 0;
+    q->ncols_all = 0;
+    q->start_row = 1;
+    q->maxrows = ODBI_MAX_INT;
+    q->ntot = 0;
+    q->nra = 0;
+    q->row_offset = 0;
+    q->string_count = 0;
+    q->info = NULL;
+    q->need_global_picture = -1;
+    q->first_time = 1;
+    q->all_processed = 0;
+    q->re_eval_info = 0;
+    QDB = db;
+
+    if (fast_odbsql) {
+      if (q->is_table) {
+	const char fmt[] = "CREATE VIEW %s SELECT * FROM %s ;";
+	int query_len = STRLEN(fmt) + 2 * STRLEN(q->name+1) + 1;
+	ALLOC(q->query_string, query_len);
+	snprintf(q->query_string, query_len, fmt, q->name+1, q->name+1);
+      }
+      q->info = ODBc_sql_prepare(QDB->handle, q->query_string, NULL, 0);
+    }
+    else {
+      f_odb_addview_(&QDB->handle, q->name, &q->vhandle
+		     /* Hidden arguments */
+		     , STRLEN(q->name)
+		     );
+    }
+
+    if (fast_odbsql) {
+      int jcol;
+      info_t *info = q->info;
+      int ncols = info->ncols_true;
+      int nadd = q->is_table ? (MAXBITS * ncols) : 0; /* each column could be have up to maxbits sub-members */
+      char *bitfields = NULL;
+      CALLOC(q->cols, ncols + nadd);
+      for (jcol=0; jcol<ncols; jcol++) {
+	const char *name = info->c[jcol].name;
+	const char *nickname = info->c[jcol].nickname ? info->c[jcol].nickname : info->c[jcol].name;
+	q->cols[jcol].name = STRDUP(name);
+	q->cols[jcol].nickname = STRDUP(nickname);
+	q->cols[jcol].type = STRDUP(info->c[jcol].dtype);
+	q->cols[jcol].dtnum = info->c[jcol].dtnum;
+	q->cols[jcol].bitpos = 0;
+	q->cols[jcol].bitlen = 0;
+
+	if (q->is_table && info->c[jcol].dtnum == DATATYPE_BITFIELD) {
+	  /* Constructing columns for additional query to get 
+	     the Bitfield members for "number_of_extra_columns" */
+	  char *pure_name = STRDUP(info->c[jcol].name);
+	  char *has_at = strchr(pure_name,'@');
+	  if (has_at) *has_at = '\0';
+	  {
+	    const char *table_name = q->name; /* Note: starting with '@' */
+	    char *field = NULL;
+	    /* The +6 accounts for the following 6 chars ".*", and \0 */
+	    int field_len = STRLEN(pure_name) + STRLEN(table_name) + 6; 
+	    ALLOC(field, field_len);
+	    snprintf(field, field_len, "\"%s.*%s\",", pure_name, table_name);
+	    if (!bitfields) {
+	      bitfields = STRDUP(field);
+	    }
+	    else {
+	      char *copy = NULL;
+	      int copylen = STRLEN(bitfields) + STRLEN(field) + 1;
+	      ALLOC(copy, copylen);
+	      snprintf(copy, copylen, "%s%s", bitfields, field);
+	      FREE(bitfields);
+	      bitfields = copy;
+	    }
+	    FREE(field);
+	  }
+	  FREE(pure_name);
+	} /* if (q->is_table && info->c[jcol].dtnum == DATATYPE_BITFIELD) */
+      }
+
+      q->ncols_fixed = ncols;
+      if (!bitfields) {
+	q->ncols_all = q->ncols_fixed;
+      }
+      else {
+	info_t *meminfo = NULL;
+	int jcols, mem_ncols = 0;
+	const char fmt[] = "CREATE VIEW meminfo_%s SELECT %s FROM %s ;";
+	int query_len = STRLEN(fmt) + STRLEN(bitfields) + 2 * STRLEN(q->name+1) + 1;
+	char *query_string = NULL;
+	ALLOC(query_string, query_len);
+	snprintf(query_string, query_len, fmt, q->name+1, bitfields, q->name+1);
+	meminfo = ODBc_sql_prepare(QDB->handle, query_string, NULL, 0);
+	mem_ncols = meminfo->ncols_true;
+	for (jcol=ncols; jcol<ncols+mem_ncols; jcol++) {
+	  int jj_col = jcol - ncols;
+	  const char *name = meminfo->c[jj_col].name;
+	  q->cols[jcol].name = STRDUP(name);
+	  q->cols[jcol].nickname = STRDUP(name);
+	  q->cols[jcol].type = STRDUP(meminfo->c[jj_col].dtype);
+	  q->cols[jcol].dtnum = meminfo->c[jj_col].dtnum;
+	  q->cols[jcol].bitpos = meminfo->c[jj_col].bitpos;
+	  q->cols[jcol].bitlen = meminfo->c[jj_col].bitlen;
+	}
+	q->ncols_all = q->ncols_fixed + mem_ncols;
+	meminfo = ODBc_sql_cancel(meminfo);
+	FREE(query_string);
+	FREE(bitfields);
+      }
+    }
+    else {
+      char *token = NULL;
+      char *saved = NULL;
+      int jcol, len;
+      int extname;
+      int ncols = ODB_maxcols(); /* Quite big ? */
+
+      len = max_name_len * ncols + 1;
+      ALLOC(saved, len);
+
+      extname = 0;
+      f_odb_get_colnames_(&QDB->handle, q->name, saved, &extname, &q->ncols_fixed
+			  /* Hidden arguments */
+			  , STRLEN(q->name), len
+			  );
+
+      if (q->is_table) {
+	extname = 1;
+	f_odb_get_colnames_(&QDB->handle, q->name, saved, &extname, &q->ncols_all
+			    /* Hidden arguments */
+			    , STRLEN(q->name), len
+			    );
+      }
+      else {
+	q->ncols_all = q->ncols_fixed;
+      }
+
+      CALLOC(q->cols, q->ncols_all);
+
+      token = strtok(saved,ODB_tag_delim);
+      jcol = 0;
+      while (token) {
+	q->cols[jcol].name = STRDUP(token);
+	q->cols[jcol].nickname = STRDUP(token);
+	jcol++;
+	token = strtok(NULL,ODB_tag_delim);
+      }
+
+      f_odb_get_typenames_(&QDB->handle, q->name, saved, &extname, &q->ncols_all
+			  /* Hidden arguments */
+			  , STRLEN(q->name), len
+			   );
+
+      token = strtok(saved,ODB_tag_delim);
+      jcol = 0;
+      while (token) {
+	q->cols[jcol].type = STRDUP(token);
+	q->cols[jcol].dtnum = get_dtnum(token);
+	jcol++;
+	token = strtok(NULL,ODB_tag_delim);
+      }
+
+      FREE(saved);
+    }
+
+  }
+  /*  finish: */
+  DRHOOK_END(0);
+  return q;
+}
+
+
+PRIVATE int Res2Q(const result_t *res,
+		  ODBI_query_t *q)
+{
+  const int method = 1; /* Changed from 2 to 1 by SS/25-Feb-2014 */
+  int n = 0;
+  if (res) {
+    int i,j,k;
+    int nrows, ncols;
+    q->nrows = nrows = res->nrows_out;
+    q->ncols = ncols = res->ncols_out;
+    q->nra = ODBc_lda(q->nrows, method);
+    
+    n = q->nra * (1 + q->ncols);
+    ALLOC(q->a, n);
+    
+    if (res->row_wise) {
+      for (k=0; k<nrows; k++) {
+	i = q->nra + k;
+	for (j=0; j<ncols; j++) {
+	  q->a[i] = res->d[k][j];
+	  i += q->nra;
+	} /* for (j=0; j<ncols; j++) */
+      } /* for (k=0; k<nrows; k++) */
+    }
+    else {
+      for (j=0; j<ncols; j++) {
+	i = (j+1) * q->nra;
+	/* for (k=0; k<nrows; k++) q->a[i++] = res->d[j][k]; */
+	memcpy(&q->a[i], &res->d[j][0], nrows * sizeof(*q->a));
+      } /* for (j=0; j<ncols; j++) */
+    }
+  }
+  else {
+    q->nrows = 0;
+    q->nra = ODBc_lda(q->nrows, method);
+    n = q->nra * (1 + q->ncols);
+    CALLOC(q->a, n);
+  }
+  return n;
+}
+
+int ODBI_execute(void *vq)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_execute);
+  if (q) {
+#if 0
+    fprintf(stderr,"ODBI_execute(%s):start; fast_odbsql=%d, q->need_global_picture=%d\n", 
+	    q->name,fast_odbsql,q->need_global_picture);
+#endif
+
+    if (fast_odbsql) {
+      info_t *info = q->info;
+
+      if (!info) q->re_eval_info = 1;
+
+      if (q->re_eval_info) {
+	int j, nset = 0;
+	set_t *s = NULL;
+	if (info && info->nset > 0 && info->s) {
+	  nset = info->nset;
+	  ALLOC(s, nset);
+	  for (j=0; j<nset; j++) {
+	    s[j].name = STRDUP(info->s[j].name);
+	    s[j].value = info->s[j].value;
+	  }
+	}
+	info = q->info = ODBc_sql_cancel(q->info);
+	info = q->info = ODBc_sql_prepare(QDB->handle, q->query_string, s, nset);
+	if (nset > 0 && s) {
+	  for (j=0; j<nset; j++) {
+	    FREE(s[j].name);
+	  }
+	  FREE(s);
+	}
+	q->first_time = 1;
+	q->re_eval_info = 0;
+      }
+
+      if (q->first_time) {
+	/* Usually the very first AND standalone ODBI_execute() i.e. not called from ODB_fetchrow_array() */
+	q->first_time = 0;
+	rc = 0;
+	goto finish;
+      }
+      else if (q->all_processed) {
+	rc = 0;
+	ODBI_finish(q);
+	goto finish;
+      }
+
+      if (q->need_global_picture == -1) {
+	if ((info->u && info->nuniqueby > 0) ||
+	    info->has_select_distinct ||
+	    info->has_aggrfuncs ||
+	    (info->o && info->norderby > 0) ||
+	    ((info->optflags & 0x1) == 0x1) ||
+	    info->create_index > 0) {
+	  q->need_global_picture = 1;
+	}
+	else if (info->has_select_distinct &&
+		 !info->has_aggrfuncs &&
+		 !(info->o && info->norderby > 0) &&
+		 (info->create_index == 0) &&
+		 (info->ncols == info->ncols_true) &&
+		 (info->nwhere == 0) &&
+		 (info->wherecond && strnequ(info->wherecond,"Unique(",7))) {
+	  /* f.ex. SELECT 1+2*3 */
+	  q->need_global_picture = 2;
+	}
+	else {
+	  q->need_global_picture = 0;
+	}
+      }
+#if 0
+    fprintf(stderr,
+	    "q->need_global_picture=%d now, q->row_offset=%d, q->start_row=%d, q->poolno/QDB->npools=%d/%d\n", 
+	    q->need_global_picture, q->row_offset, q->start_row, q->poolno, QDB->npools);
+#endif
+
+    } /* if (fast_odbsql) */
+
+    if (q->need_global_picture >= 1 && fast_odbsql) {
+      const Bool row_wise_preference = true;
+      int iret = -99999;
+      if (q->need_global_picture == 1) {
+	/* make sure you do this only once */
+	/* loop over all pools and gather data to the result-chain */
+	/* then copy all that data to the current "q" */
+	info_t *info = q->info;
+	int jp, nrows, npools = QDB->npools;
+	result_t *res = NULL;
+	for (jp=1; jp<=npools; jp++) {
+	  /* Accumulate res for further postprocessing & merge */
+	  q->poolno = jp;
+	  nrows = ODBc_sql_exec(QDB->handle, q->info, jp, NULL, NULL);
+	  QDB->poolstat[jp] = ODBI_POOL_LOADED;
+	  res = ODBc_get_data(QDB->handle, res, q->info, jp, 1, nrows, false, &row_wise_preference);
+	  info = q->info = ODBc_reset_info(q->info);
+	}
+	if (info->has_aggrfuncs) res = ODBc_aggr(res, 1);
+	res = ODBc_operate(res, "count(*)");
+	res = ODBc_sort(res, NULL, 0);
+	iret = Res2Q(res, q);
+	res = ODBc_unget_data(res);
+	q->row_offset = q->start_row - 1;
+	q->need_global_picture = 101; /* done */
+      }
+      else if (q->need_global_picture == 2) {
+	/* f.ex. SELECT 1+2*3 */
+ 	/* make sure you do this only once */
+	/* loop over all pools until at least one row found */
+	/* then copy all that data to the current "q" */
+	info_t *info = q->info;
+	int jp, nrows, npools = QDB->npools;
+	result_t *res = NULL;
+	for (jp=1; !res && jp<=npools; jp++) {
+	  /* Accumulate res for further postprocessing & merge */
+	  q->poolno = jp;
+	  nrows = ODBc_sql_exec(QDB->handle, q->info, jp, NULL, NULL);
+	  QDB->poolstat[jp] = ODBI_POOL_LOADED;
+	  if (nrows == 1) {
+	    res = ODBc_get_data(QDB->handle, NULL, q->info, jp, 1, nrows, false, &row_wise_preference);
+	  }
+	  info = q->info = ODBc_reset_info(q->info);
+	}
+	iret = Res2Q(res, q);
+	res = ODBc_unget_data(res);
+	q->row_offset = q->start_row - 1;
+	q->need_global_picture = 201; /* done */
+	q->all_processed = 1;
+      }
+      rc = q->nrows - q->row_offset;
+#if 0
+      fprintf(stderr,
+	      "Changing[pool#%d,glbpic=%d]> row_offset=%d, start_row=%d, ntot=%d, nrows=%d (rc=%d, iret=%d)\n",
+	      q->poolno, q->need_global_picture,
+	      q->row_offset, q->start_row, q->ntot, q->nrows, rc, iret);
+#endif
+      if (rc <= 0) {
+	ODBI_finish(q);
+      }
+    } /* if (q->need_global_picture >= 1 && fast_odbsql) */
+    else {
+      do {
+	int iret = 0;
+	(void) ODBI_finish(q);
+	
+	if (q->poolno <= QDB->npools && 
+	    QDB->poolstat[q->poolno] == ODBI_POOL_UNLOADED) {
+	  
+	  if (fast_odbsql) {
+	    const int method = 1; /* Changed from 2 to 1 by SS/25-Feb-2014 */
+	    rc = q->nrows = ODBc_sql_exec(QDB->handle, q->info, q->poolno, NULL, NULL);
+	    q->ncols = q->ncols_fixed;
+	    q->nra = ODBc_lda(q->nrows, method);
+	  }
+	  else {
+	    f_odb_select_(&QDB->handle, q->name, 
+			  &q->nrows, &q->ncols, &q->nra, &q->poolno,
+			  &rc
+			  /* Hidden arguments */
+			  , STRLEN(q->name)
+			  );
+	  }
+	
+	  QDB->poolstat[q->poolno] = ODBI_POOL_LOADED;
+	
+	  if (q->fpcache) {
+	    fprintf(q->fpcache,"%d %d\n",q->poolno,q->nrows);
+	  }
+	
+#if 0
+	  fprintf(stderr,"Changing[#%d]> row_offset=%d, start_row=%d, ntot=%d, nrows=%d\n",
+		  q->poolno, q->row_offset, q->start_row, q->ntot, q->nrows);
+#endif
+	  if (q->nrows > 0 && 
+	      q->ntot + 1        <= q->start_row &&
+	      q->ntot + q->nrows >= q->start_row) {
+	    int n;
+
+	    if (fast_odbsql) {
+	      const Bool row_wise_preference = false; /* We prefer Fortran-wise major column order */
+	      result_t *res = 
+		ODBc_get_data(QDB->handle, NULL, q->info, q->poolno, 1, q->nrows, 
+			      false, &row_wise_preference);
+	      n = Res2Q(res, q);
+	      res = ODBc_unget_data(res);
+	    }
+	    else { /* ! fast_odbsql */
+	      n = q->nra * (1 + q->ncols);
+	      ALLOC(q->a, n);
+	      f_odb_get_(&QDB->handle, q->name, q->a, 
+			 &q->nrows, &q->ncols, &q->nra, &q->poolno, 
+			 &iret
+			 /* Hidden arguments */
+			 , STRLEN(q->name)
+			 );
+	    }
+
+	    q->row_offset = q->start_row - q->ntot - 1;
+	  }
+	  else {
+	    q->row_offset = q->nrows;
+	    rc = 0;
+	  } /* if (q->nrows > 0 ...) else ... */
+	  q->ntot += q->nrows;
+#if 0
+	  fprintf(stderr,"Changing[#%d]< row_offset=%d, start_row=%d, ntot=%d, nrows=%d\n",
+		  q->poolno, q->row_offset, q->start_row, q->ntot, q->nrows);
+#endif
+
+	  if (fast_odbsql) {
+	    q->info = ODBc_reset_info(q->info);
+	  }
+	  else {
+	    f_odb_cancel_(&QDB->handle, q->name, &q->poolno, 
+			  &iret
+			  /* Hidden arguments */
+			  , STRLEN(q->name)
+			  );
+
+	    f_odb_release_(&QDB->handle, &q->poolno, &iret);
+	  }
+
+	  QDB->poolstat[q->poolno] = ODBI_POOL_RELEASED;
+	} /* if (q->poolno <= QDB->npools && ...) */
+      } while (rc == 0 && q->poolno < QDB->npools);
+    } /* if (q->need_global_picture == 1 && ...) ... else ... */
+
+#if 0
+    {
+      fprintf(stderr,"ODBI_execute(%s) : rc=%d ; nrows=%d, ncols=%d, nra=%d, poolno=%d, row_offset=%d, ntot=%d\n",
+	      q->name, rc, q->nrows, q->ncols, q->nra, q->poolno, q->row_offset, q->ntot);
+    }
+#endif
+  }
+ finish:
+  DRHOOK_END(rc);
+  return rc;
+}
+
+
+int ODBI_fetchonerow_array(void *vq,
+			int *nrows,
+			int *ncols,
+			double d[],
+			int nd)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_fetchonerow_array);
+  if (nrows) *nrows = 0;
+  if (ncols) *ncols = 0;
+  if (q && d) {
+
+    if (q->all_processed) {
+      if (ncols) *ncols = q->ncols;
+      rc = 0;
+      goto finish;
+    }
+
+    if (q->row_offset == q->nrows) {
+      int rc_exec = 0;
+      q->first_time = 0;
+      rc_exec = ODBI_execute(q);
+      if (rc_exec < 0) {
+	rc = rc_exec;
+	goto finish;
+      }
+    }
+
+    if (q->a) {
+      int maxrows   = nd/q->ncols;
+      int row_chunk = MIN(maxrows, q->nrows - q->row_offset);
+      row_chunk = MIN(row_chunk, q->maxrows);
+      f_odb_copydata_(d, &row_chunk, &q->row_offset, 
+		      q->a, &q->nrows, &q->ncols, &q->nra,
+		      &QDB->swapbytes,
+		      &rc);
+#if 0
+      {
+	fprintf(stderr,
+		"ODBI_fetchonerow_array at f_odb_copydata_[1]> rc=%d, row_chunk=%d, maxrows=%d, nrows=%d, row_offset=%d\n",
+		rc, row_chunk, maxrows, q->nrows, q->row_offset);
+      }
+#endif
+      rc *= q->ncols;
+      q->row_offset += row_chunk;
+      q->start_row += row_chunk;
+      q->maxrows -= row_chunk;
+      if (nrows) *nrows = row_chunk;
+      if (ncols) *ncols = q->ncols;
+#if 0
+      {
+	fprintf(stderr,
+		"ODBI_fetchonerow_array at f_odb_copydata_[2]< rc=%d, row_chunk=%d, maxrows=%d, nrows=%d, row_offset=%d\n",
+		rc, row_chunk, maxrows, q->nrows, q->row_offset);
+      }
+#endif
+    }
+  }
+ finish:
+  DRHOOK_END(nrows ? *nrows : 0);
+  return rc;
+}
+
+int ODBI_fetchrow_array(void *vq,
+			int *nrows,
+			int *ncols,
+			double d[],
+			int nd)
+{
+  ODBI_query_t *q = vq;
+  int total_rows=0;
+  int local_rows=-1;
+  int local_cols=0;
+  int bufsize;
+  int rc = 0;
+
+  DRHOOK_START(ODBI_fetchrow_array);
+  if (q && d) {
+    if (*nrows) local_rows = *nrows;
+    if (*ncols) local_cols = *ncols;
+ 
+    if (local_rows < 0 ) { /* fetch pool by pool in direct mode (default mode) */
+      rc=ODBI_fetchonerow_array(vq,nrows,ncols,d,nd);
+      /* fprintf(stderr, "pool nbrows to be retrieved: %d %d\n", q->poolno, q->nrows);*/
+      total_rows += q->nrows;
+    } else {
+      bufsize = nd;
+      rc=ODBI_fetchonerow_array(vq,nrows,ncols,&d[0],bufsize);
+      while (rc > 0) {
+/*AF 16/03/09 wrong number of rows
+	total_rows += q->nrows;
+	bufsize -= q->nrows * *ncols;
+*/
+	total_rows += *nrows;
+	bufsize -= *nrows * *ncols;
+	/*	fprintf(stderr, "all nbrows to be retrieved: %d %d\n", q->poolno, q->nrows);*/
+	rc=ODBI_fetchonerow_array(vq,nrows,ncols,&d[total_rows* *ncols],bufsize);
+      }
+    }
+  }
+  if (nrows) *nrows = total_rows;
+  if (ncols) *ncols = local_cols;
+  DRHOOK_END(rc);
+  return total_rows;
+}
+
+int ODBI_finish(void *vq)
+{
+  ODBI_query_t *q = vq;
+  int rc = 0;
+  DRHOOK_START(ODBI_finish);
+  if (q) {
+    FREE(q->a);
+    if (q->poolno >= 1 && q->poolno <= QDB->npools) {
+#if 0
+      {
+	fprintf(stderr,
+		"ODBI_finish(%s at pool#%d) ; nrows=%d, ncols=%d, nra=%d, row_offset=%d, ntot=%d\n",
+		q->name, q->poolno, q->nrows, q->ncols, q->nra, q->row_offset, q->ntot);
+      }
+#endif
+      if (!fast_odbsql) {
+	if (QDB->poolstat[q->poolno] == ODBI_POOL_LOADED) {
+	  /* To circumvent a bug in ODB ; the bug naturally to be fixed soon ! */
+	  f_odb_release_(&QDB->handle, &q->poolno, &rc);
+	}
+      } 
+    }
+    if (q->poolno <= QDB->npools) q->poolno++;
+    q->nrows = 0;
+    q->ncols = 0;
+    q->nra = 0;
+    q->row_offset = 0;
+    if (fast_odbsql) {
+      q->need_global_picture = -1;
+    }
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+int ODBI_disconnect(void *vdb)
+{
+  ODBI_db_t *db = vdb;
+  int rc = 0;
+  DRHOOK_START(ODBI_disconnect);
+  if (db) {
+    int j;
+    const int save = 0;
+    if (fast_odbsql) {
+      rc = ODBc_close(db->handle);
+    }
+    else {
+      f_odb_close_(&db->handle, &save, &rc);
+    }
+    FREE(db->name);
+    FREE(db->mode);
+    for (j=0; j<db->nquery; j++) {
+      ODBI_query_t *q = &db->query[j];
+      (void) ODBI_finish(q);
+      FREE(q->name);
+      FREE(q->query_string);
+      if (q->cols) {
+	int jcol;
+	for (jcol=0; jcol<q->ncols_all; jcol++) {
+	  FREE(q->cols[jcol].name);
+	  FREE(q->cols[jcol].nickname);
+	  FREE(q->cols[jcol].type);
+	}
+	FREE(q->cols);
+      }
+      if (fast_odbsql) {
+	q->info = ODBc_sql_cancel(q->info);
+      }
+    }
+    FREE(db->query);
+    FREE(db->poolstat);
+    if (db->fp_opened_here) fclose(db->fp);
+    FREE(db);
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+double ODBI_bind_param(void *vq, 
+		       const char *param_name, 
+		       double new_value)
+{
+  ODBI_query_t *q = vq;
+  double old_value = 0;
+  DRHOOK_START(ODBI_bind_param);
+  if (param_name && q && q->name) {
+    if (fast_odbsql) {
+      info_t *info = q->info;
+      if (info) {
+	int j, nset = info->nset;
+	Boolean found = false;
+	if (*param_name == '$') ++param_name;
+	for (j=0; j<nset && !found; ++j) {
+	  const char *varname = info->s[j].name;
+	  if (varname && *varname == '$') ++varname;
+	  if (strequ(varname, param_name)) {
+	    old_value = info->s[j].value;
+	    info->s[j].value = new_value;
+	    found = 1;
+	  }
+	} /* for (j=0; j<nset && !found; j++) */
+	if (!found) {
+	  int len = STRLEN(param_name) + 2;
+	  j = nset++;
+	  REALLOC(info->s, nset);
+	  ALLOC(info->s[j].name, len);
+	  snprintf(info->s[j].name, len, "$%s", param_name);
+	  info->s[j].value = new_value;
+	}
+	fprintf(QDB->fp,"set_%s=%.14g\n",param_name,new_value);
+	q->re_eval_info = 1; /* Next time ODBI_execute() is run, re-evaluate the q->info */
+      }
+    }
+    else {
+      f_odb_setval_(&QDB->handle, q->name, param_name, 
+		    &new_value, &old_value
+		    /* Hidden arguments */
+		    , STRLEN(q->name), STRLEN(param_name)
+		    );
+      if (*param_name == '$') ++param_name;
+      fprintf(QDB->fp,"set_%s=%.14g\n",param_name,new_value);
+    }
+  }
+  DRHOOK_END(0);
+  return old_value;
+}
+
+
+void ODBI_limits(void *vq,
+		 int *start_row,
+		 int *maxrows,
+		 int *bufsize)
+{
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_limits);
+  if (q) {
+    if (start_row) {
+      if (*start_row <= 0) *start_row = 1;
+      q->start_row = *start_row;
+      fprintf(QDB->fp,"start_row=%d\n",q->start_row);
+    }
+    if (maxrows) {
+      if (*maxrows < 0) *maxrows = ODBI_MAX_INT;
+      q->maxrows = *maxrows;
+      fprintf(QDB->fp,"maxrows=%d\n",q->maxrows);
+    }
+    if (bufsize) {
+      if (*bufsize < q->ncols_fixed) *bufsize = q->ncols_fixed;
+      (*bufsize)++; /* Accomodate one slot for binary data */
+      fprintf(QDB->fp,"buffer_size=%d\n",*bufsize);
+    }
+  }
+  DRHOOK_END(0);
+}
+
+
+int ODBI_fetchfile(void *vq,
+		   const char *filename,
+		   const char *fileformat)
+{
+#if 0
+  const char dbgfile[] = "/tmp/fetchfile.direct";
+#else
+  const char dbgfile[] = "/dev/null";
+#endif
+  FILE *dbgfp = fopen(dbgfile, "w");
+  int rc = 0;
+  FILE *outfp = stdout; /* That's the "dump" for ODBI_DIRECT */
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_fetchfile);
+  setvbuf(dbgfp, (char *)NULL, _IONBF, 0);
+  if (q && outfp && filename && fileformat) {
+    info_t *info = q->info;
+    int filesize = 0;
+    if (fast_odbsql && info) {
+      const char fmt[] = "$ODB_FEBINPATH/odbsql -q '%s' -f %s -o %s -B -i '%s' -m%d,%d -n%s";
+      const char *srcpath = info->dbcred.srcpath;
+      const char *sql_query = info->sql_query;
+      const char search_str[] = "The original query follows\n\n";
+      const char *matched = strstr(sql_query, search_str); /* see also aux/result.c & aux/info.c */
+      char *cmd = NULL;
+      char *nl;
+      int iret, len, dummy;
+      char *fname = NULL;
+      extern int csopt; /* Flag for indicating that c/s-infra is on, if == 1 i.e. when odbi_direct.x -C */
+      extern char *ncpus_nchunk; /* Parallelism (and pool-chunking) */
+
+      if (strcmp(fileformat,"netcdf") == 0 || strcmp(fileformat,"unetcdf") == 0) {
+	/* Try to allocate at least 2 cpus/cores for NetCDF-file creation, pool-chunking of 16 */
+	if (!ncpus_nchunk) ncpus_nchunk = strdup("2.16");
+      }
+      if (!ncpus_nchunk) ncpus_nchunk = strdup("1");
+
+      fprintf(dbgfp,"csopt = %d [c/s-infra], ncpus[.nchunk]=%s\n",
+	      csopt,ncpus_nchunk);
+
+      if (csopt) {
+	int pid = (int)getpid();
+	const char *last_slash = strrchr(filename,'/');
+	char *env = getenv("TMPDIR");
+	if (!env) env = ".";
+	if (last_slash) filename = last_slash + 1;
+	len = STRLEN(env) + STRLEN(filename) + 30;
+	ALLOC(fname, len);
+	snprintf(fname, len, "%s/__.%s.%d", env, filename, pid);
+      }
+      else {
+	fname = STRDUP(filename);
+      }
+
+      if (matched) sql_query = matched + STRLEN(search_str);
+      len = 
+	STRLEN(fmt) + STRLEN(sql_query) + STRLEN(fileformat) + 
+	STRLEN(fname) + STRLEN(srcpath) + STRLEN(ncpus_nchunk) + 100;
+      ALLOC(cmd, len);
+      snprintf(cmd, len, fmt, sql_query, fileformat, fname, srcpath, q->start_row, q->maxrows,
+	       ncpus_nchunk);
+
+      /* Replace newlines with blanks */
+      nl = cmd-1;
+      while (*++nl) if (*nl == '\n') *nl = ' ';
+
+      fprintf(dbgfp,"cmd=[%s]\n",cmd);
+
+      codb_remove_file_(fname, &dummy, STRLEN(fname));
+      iret = system(cmd);
+      fprintf(dbgfp,"iret = %d, dummy = %d\n",iret,dummy);
+
+      if (iret == 0) {
+	/* Now copy file to outfp, unless a terminal */
+	FILE *fp = NULL;
+
+	codb_filesize_(fname, &filesize, STRLEN(fname));
+	fprintf(dbgfp,"filesize = %d\n",filesize);
+
+	if (!csopt) {
+	  rc = filesize;
+	  goto finish;
+	}
+
+	fwrite(&filesize, sizeof(filesize), 1, outfp);
+	fflush(outfp);
+
+	if (filesize > 0) fp = fopen(fname, "r");
+	fprintf(dbgfp,"fname = '%s', open fp = %p,%d [outfp = %p,%d]\n", 
+		fname, fp, fileno(fp), outfp, fileno(outfp));
+
+	if (fp) {
+	  int nread = 0;
+	  char buf[IO_BUFSIZE_DEFAULT];
+	  while (nread < filesize) {
+	    int nbytes = fread(buf, sizeof(*buf), sizeof(buf), fp);
+	    fprintf(dbgfp,"\tnbytes = %d\n",nbytes);
+	    if (nbytes > 0) {
+	      int nwritten = fwrite(buf, sizeof(*buf), nbytes, outfp);
+	      if (nwritten == nbytes) {
+		nread += nwritten;
+		fprintf(dbgfp,"\t\tnread = %d bytes so far (nwritten = %d [incr]); filesize = %d bytes\n",
+			nread,nwritten,filesize);
+	      }
+	      else {
+		fprintf(stderr,"direct: ODBI_fetchfile() failed to write from file '%s' to pipe [rc=-2]\n",fname);
+		fprintf(dbgfp,"direct: ODBI_fetchfile() failed to write from file '%s' to pipe [rc=-2]\n",fname);
+		rc = -2;
+		break;
+	      }
+	    }
+	    else {
+	      if (nbytes < 0) {
+		fprintf(stderr,"direct: ODBI_fetchfile() failed to read from file '%s' [rc=-3]\n",fname);
+		fprintf(dbgfp,"direct: ODBI_fetchfile() failed to read from file '%s' [rc=-3]\n",fname);
+		rc = -3;
+	      }
+	      break;
+	    }
+	  } /* while (nread < filesize) */
+	  fclose(fp);
+	  if (rc == 0) rc = filesize;
+	}
+	else {
+	  fprintf(stderr,"direct: ODBI_fetchfile() unable to open file '%s' for reading [rc=-4]\n",fname);
+	  fprintf(dbgfp,"direct: ODBI_fetchfile() unable to open file '%s' for reading [rc=-4]\n",fname);
+	  rc = -4;
+	}
+      }
+      else {
+	fwrite(&filesize, sizeof(filesize), 1, outfp);
+	fprintf(stderr,"direct: ODBI_fetchfile() failed in command '%s' [rc=-1]\n",cmd);
+	fprintf(dbgfp,"direct: ODBI_fetchfile() failed in command '%s' [rc=-1]\n",cmd);
+	rc = -1;
+      }
+
+      fflush(outfp);
+      
+      codb_remove_file_(fname, &dummy, STRLEN(fname));
+
+    finish:
+      FREE(cmd);
+      FREE(fname);
+    }
+    else {
+      fwrite(&filesize, sizeof(filesize), 1, outfp);
+      fprintf(stderr,"direct: ODBI_fetchfile() implemented only via odbsql i.e. do NOT use askodb -F [rc=-5]\n");
+      fprintf(dbgfp,"direct: ODBI_fetchfile() implemented only via odbsql i.e. do NOT use askodb -F [rc=-5]\n");
+      rc = -5;
+    }
+  }
+  ODBI_finish(q);
+  DRHOOK_END(rc >= 0 ? rc : 0);
+  fprintf(dbgfp,"rc = %d\n",rc);
+  fclose(dbgfp);
+  return rc;
+}
+
+			  
+#include "odbi_shared.c"
diff --git a/odb/src/aux/odbi_server.c b/odb/src/aux/odbi_server.c
new file mode 100644
index 0000000..4dcb547
--- /dev/null
+++ b/odb/src/aux/odbi_server.c
@@ -0,0 +1,708 @@
+
+/* odbi_server.c */
+
+/* 
+   Manages ODB client/server communication between
+   client and askodb-script
+*/
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+PRIVATE pid_t Pid = -1;
+PRIVATE char *Server = "";
+
+typedef struct _askodb_t {
+  char *dbname;
+  char *mode;
+  char *datapath;
+  char *poolmask;
+  char *viewname;
+  char *query_string;
+  char *param;
+  char *user;
+  char *password;
+  char *workdir;
+  char *exe;
+  char *clihost;
+  char *cliaddr;
+  char *binary;
+  char *ncpus;
+  char *outfil;
+  int byteswap;
+  int start_row;
+  int maxrows;
+  int silent;
+  int verbose;
+  int metadata;
+  int clean;
+  int io_method;
+  int keep;
+  int data_only;
+  int bufsize;
+  int timeout;
+  int version;
+  int odbsql;
+} askodb_t;
+
+PRIVATE askodb_t *
+init_askodb_t(askodb_t *in)
+{
+  if (!in) CALLOC(in,1);
+  if (!in->dbname)       in->dbname       = STRDUP("");
+  if (!in->mode)         in->mode         = STRDUP("");
+  if (!in->datapath)     in->datapath     = STRDUP("");
+  if (!in->poolmask)     in->poolmask     = STRDUP("");
+  if (!in->viewname)     in->viewname     = STRDUP("");
+  if (!in->query_string) in->query_string = STRDUP("");
+  if (!in->param)        in->param        = STRDUP("");
+  if (!in->user)         in->user         = STRDUP("");
+  if (!in->password)     in->password     = STRDUP("");
+  if (!in->workdir)      in->workdir      = STRDUP("");
+  if (!in->exe)          in->exe          = STRDUP("");
+  if (!in->clihost)      in->clihost      = STRDUP("");
+  if (!in->cliaddr)      in->cliaddr      = STRDUP("");
+  if (!in->ncpus)        in->ncpus        = STRDUP("1");
+  return in;
+}
+
+PRIVATE askodb_t *
+create_askodb_t(const askodb_t *in)
+{
+  askodb_t *out = NULL;
+  ALLOC(out,1);
+  memcpy(out,in,sizeof(*out));
+  if (in->dbname)       out->dbname       = STRDUP(in->dbname);
+  if (in->mode)         out->mode         = STRDUP(in->mode);
+  if (in->datapath)     out->datapath     = STRDUP(in->datapath);
+  if (in->poolmask)     out->poolmask     = STRDUP(in->poolmask);
+  if (in->viewname)     out->viewname     = STRDUP(in->viewname);
+  if (in->query_string) out->query_string = STRDUP(in->query_string);
+  if (in->param)        out->param        = STRDUP(in->param);
+  if (in->user)         out->user         = STRDUP(in->user);
+  if (in->password)     out->password     = STRDUP(in->password);
+  if (in->workdir)      out->workdir      = STRDUP(in->workdir);
+  if (in->exe)          out->exe          = STRDUP(in->exe);
+  if (in->clihost)      out->clihost      = STRDUP(in->clihost);
+  if (in->cliaddr)      out->cliaddr      = STRDUP(in->cliaddr);
+  if (in->binary)       out->binary       = STRDUP(in->binary);
+  if (in->ncpus)        out->ncpus        = STRDUP(in->ncpus);
+  if (in->outfil)       out->outfil       = STRDUP(in->outfil);
+  return out;
+}
+
+PRIVATE void
+free_askodb_t(askodb_t *in, int free_all)
+{
+  if (in) {
+    if ((free_all && in->dbname)       || STRLEN(in->dbname) == 0)       FREE(in->dbname);
+    if ((free_all && in->mode)         || STRLEN(in->mode) == 0)         FREE(in->mode);
+    if ((free_all && in->datapath)     || STRLEN(in->datapath) == 0)     FREE(in->datapath);
+    if ((free_all && in->poolmask)     || STRLEN(in->poolmask) == 0)     FREE(in->poolmask);
+    if ((free_all && in->viewname)     || STRLEN(in->viewname) == 0)     FREE(in->viewname);
+    if ((free_all && in->query_string) || STRLEN(in->query_string) == 0) FREE(in->query_string);
+    if ((free_all && in->param)        || STRLEN(in->param) == 0)        FREE(in->param);
+    if ((free_all && in->user)         || STRLEN(in->user) == 0)         FREE(in->user);
+    if ((free_all && in->password)     || STRLEN(in->password) == 0)     FREE(in->password);
+    if ((free_all && in->workdir)      || STRLEN(in->workdir) == 0)      FREE(in->workdir);
+    if ((free_all && in->exe)          || STRLEN(in->exe) == 0)          FREE(in->exe);
+    if ((free_all && in->clihost)      || STRLEN(in->clihost) == 0)      FREE(in->clihost);
+    if ((free_all && in->cliaddr)      || STRLEN(in->cliaddr) == 0)      FREE(in->cliaddr);
+    if ((free_all && in->binary)       || STRLEN(in->binary) == 0)       FREE(in->binary);
+    if ((free_all && in->ncpus)        || STRLEN(in->ncpus) == 0)        FREE(in->ncpus);
+    if ((free_all && in->outfil)       || STRLEN(in->outfil) == 0)       FREE(in->outfil);
+    if (free_all) FREE(in);
+  }
+}
+
+
+PRIVATE askodb_t *
+vparam(const askodb_t *ask, char *fmt, va_list ap)
+{
+  askodb_t *a = NULL;
+  if (fmt) {
+    static int cnt = 0;
+    const char *delim = ";";
+    char *token = strtok(fmt,delim);
+
+    if (ask) {
+      a = create_askodb_t(ask);
+    }
+    else {
+      CALLOC(a,1);
+    }
+
+    while (token) {
+      char *ss = STRDUP(token);
+      char *t = strchr(ss,'=');
+      char *lhs = ss;
+      char *rhs = NULL;
+      fmt = token;
+	
+      if (t) {
+	rhs = STRDUP(t+1);
+	*t = '\0'; /* affects "lhs" */
+      }
+	
+      if (rhs) {
+	if (*rhs == '%') {
+	  char *s = strchr(fmt,'%');
+	  if (s) {
+	    int d;
+	    fmt = s;
+	    fmt++;
+	    switch (*fmt++) {
+	    case 's':
+	      s = va_arg(ap, char *);
+	      rhs = STRDUP(s);
+	      break;
+	    case 'd':
+	      d = va_arg(ap, int);
+	      ALLOC(rhs, 20);
+	      snprintf(rhs, 20, "%d", d);
+	    }
+	  } /* if (*rhs == '%') */
+	}
+      }
+	
+      if (rhs) {
+	if (strcaseequ(lhs,"dbname"))            a->dbname       = STRDUP(rhs);
+	else if (strcaseequ(lhs,"mode"))         a->mode         = STRDUP(rhs);
+	else if (strcaseequ(lhs,"datapath"))     a->datapath     = STRDUP(rhs);
+	else if (strcaseequ(lhs,"poolmask"))     a->poolmask     = STRDUP(rhs);
+	else if (strcaseequ(lhs,"viewname"))     a->viewname     = STRDUP(rhs);
+	else if (strcaseequ(lhs,"query_string")) a->query_string = STRDUP(rhs);
+	else if (strcaseequ(lhs,"user"))         a->user         = STRDUP(rhs);
+	else if (strcaseequ(lhs,"password"))     a->password     = STRDUP(rhs);
+	else if (strcaseequ(lhs,"workdir"))      a->workdir      = STRDUP(rhs);
+	else if (strcaseequ(lhs,"exe"))          a->exe          = STRDUP(rhs);
+	else if (strcaseequ(lhs,"clihost"))      a->clihost      = STRDUP(rhs);
+	else if (strcaseequ(lhs,"cliaddr"))      a->cliaddr      = STRDUP(rhs);
+	else if (strcaseequ(lhs,"binary"))       a->binary       = STRDUP(rhs);
+	else if (strcaseequ(lhs,"ncpus"))        a->ncpus        = STRDUP(rhs);
+	else if (strcaseequ(lhs,"outfil"))       a->outfil       = STRDUP(rhs);
+	else if (strcaseequ(lhs,"start_row"))    a->start_row    = atoi(rhs);
+	else if (strcaseequ(lhs,"maxrows"))      a->maxrows      = atoi(rhs);
+	else if (strcaseequ(lhs,"silent"))       a->silent       = atoi(rhs);
+	else if (strcaseequ(lhs,"verbose"))      a->verbose      = atoi(rhs);
+	else if (strcaseequ(lhs,"metadata"))     a->metadata     = atoi(rhs);
+	else if (strcaseequ(lhs,"clean"))        a->clean        = atoi(rhs);
+	else if (strcaseequ(lhs,"io_method"))    a->io_method    = atoi(rhs);
+	else if (strcaseequ(lhs,"iomethod"))     a->io_method    = atoi(rhs);
+	else if (strcaseequ(lhs,"keep"))         a->keep         = atoi(rhs);
+	else if (strcaseequ(lhs,"data_only"))    a->data_only    = atoi(rhs);
+	else if (strcaseequ(lhs,"bufsize"))      a->bufsize      = atoi(rhs);
+	else if (strcaseequ(lhs,"timeout"))      a->timeout      = atoi(rhs);
+	else if (strcaseequ(lhs,"version"))      a->version      = atoi(rhs);
+	else if (strcaseequ(lhs,"odbsql"))       a->odbsql       = atoi(rhs);
+      }
+      else {
+	if (!strncaseequ(lhs,"no",2)) {
+	  if (strcaseequ(lhs,"silent"))            a->silent    = 1;
+	  else if (strcaseequ(lhs,"verbose"))      a->verbose   = 1;
+	  else if (strcaseequ(lhs,"metadata"))     a->metadata  = 1;
+	  else if (strcaseequ(lhs,"clean"))        a->clean     = 1;
+	  else if (strcaseequ(lhs,"keep"))         a->keep      = 1;
+	  else if (strcaseequ(lhs,"data_only"))    a->data_only = 1;
+	  else if (strcaseequ(lhs,"odbsql"))       a->odbsql    = 1;
+	}
+	else {
+	  if (strcaseequ(lhs,"nosilent"))          a->silent    = 0;
+	  else if (strcaseequ(lhs,"noverbose"))    a->verbose   = 0;
+	  else if (strcaseequ(lhs,"nometadata"))   a->metadata  = 0;
+	  else if (strcaseequ(lhs,"noclean"))      a->clean     = 0;
+	  else if (strcaseequ(lhs,"nokeep"))       a->keep      = 0;
+	  else if (strcaseequ(lhs,"nodata_only"))  a->data_only = 0;
+	  else if (strcaseequ(lhs,"noodbsql"))     a->odbsql    = 0;
+	}
+      }
+      
+      FREE(rhs);
+      FREE(ss);
+
+      token = strtok(NULL,delim);
+    } /* while (token) */
+  } /* if (fmt) */
+  return a;
+}
+
+PRIVATE askodb_t *
+run_askodb(const askodb_t *ask, int rawform, int dorun,
+	   int sockfd, int timeout, int verbose,
+	   const char *params, ...)
+{
+  askodb_t *a = NULL;
+  if (params) {
+    va_list ap;
+    va_start(ap, params);
+    {
+      char *s, *fmt;
+      int fmtlen = STRLEN(params) + 1;
+      ALLOC(fmt,fmtlen);
+      s = fmt;
+      while (*params) {
+	if (!isspace(*params)) *s++ = *params;
+	params++;
+      }
+      *s = '\0';
+      a = vparam(ask, fmt, ap);
+      FREE(fmt);
+    }
+    va_end(ap);
+  }
+  else {
+    a = create_askodb_t(ask);
+  }
+
+  if (!dorun) return a;
+
+  if (a) {
+    /* run askodb with the requested parameters */
+    
+    const char *askodb_cmd = "$ODB_BINPATH/askodb -C";
+    char *cmd = NULL;
+    int n, pipefd, len = STRLEN(askodb_cmd);
+    FILE *fp;
+    int istat = 0;
+    free_askodb_t(a,0); /* Release char strings with STRLEN == 0 */
+    if (a->ncpus) len += STRLEN(" -# ") + STRLEN(a->ncpus);
+    if (a->binary) len += STRLEN(" -b ") + STRLEN(a->binary);
+    if (a->outfil) len += STRLEN(" -O ") + STRLEN(a->outfil);
+    if (a->clean) len += STRLEN(" -c");
+    if (a->data_only) len += STRLEN(" -D");
+    if (a->keep) len += STRLEN(" -k");
+    if (!verbose || a->silent) len += STRLEN(" -s");
+    if (verbose && a->verbose) len += STRLEN(" -v");
+    if (a->io_method > 0 && a->io_method != 5) len += STRLEN(" -5");
+    if (a->datapath) len += STRLEN(" -i ") + STRLEN(a->datapath) + 2;
+    if (a->workdir) len += STRLEN(" -o ") + STRLEN(a->workdir);
+    if (a->exe) len += STRLEN(" -x ") + STRLEN(a->exe);
+    if (a->user) len += STRLEN(" -u ") + STRLEN(a->user);
+    if (a->poolmask) len += STRLEN(" -p ") + STRLEN(a->poolmask) + 2;
+    if (a->viewname) len += STRLEN(" -f ") + STRLEN(a->viewname);
+    if (a->query_string) len += STRLEN(" -q ") + STRLEN(a->query_string) + 2;
+    if (a->bufsize > 0)  len += STRLEN(" -B ") + 20; /* bufsize */
+    if (a->metadata) len += STRLEN(" -m");
+    else             len += STRLEN(" -l ") + 30; /* start_row & maxrows */
+    if (a->param) len += STRLEN(" -V '") + STRLEN(a->param) + 1;
+    if (a->version > 0) len += STRLEN(" -n ") + 20; /* version */ 
+    if (a->odbsql == 0) len += STRLEN(" -F "); /* fast odbsql turned off */
+    if (a->dbname) len += 1 + STRLEN(a->dbname);
+    len++; /* for the '\0' at the end */
+
+    ALLOC(cmd,len);
+    strcpy(cmd,askodb_cmd);
+    if (a->binary) {
+      strcat(cmd," -b ");
+      strcat(cmd,a->binary);
+    }
+    if (a->outfil) {
+      strcat(cmd," -O ");
+      strcat(cmd,a->outfil);
+    }
+    if (a->clean) strcat(cmd," -c");
+    if (a->data_only) strcat(cmd," -D");
+    if (a->keep) strcat(cmd," -k");
+    if (!verbose || a->silent) strcat(cmd," -s");
+    if (verbose && a->verbose) strcat(cmd," -v");
+    if (a->io_method > 0 && a->io_method != 5) strcat(cmd," -5");
+    if (a->datapath) {
+      strcat(cmd," -i '");
+      strcat(cmd,a->datapath);
+      strcat(cmd,"'");
+    }
+    if (a->workdir) {
+      strcat(cmd," -o ");
+      strcat(cmd,a->workdir);
+    }
+    if (a->exe) {
+      strcat(cmd," -x ");
+      strcat(cmd,a->exe);
+    }
+    if (a->poolmask) {
+      strcat(cmd," -p '");
+      strcat(cmd,a->poolmask);
+      strcat(cmd,"'");
+    }
+    if (a->user) {
+      strcat(cmd," -u ");
+      strcat(cmd,a->user);
+    }
+    if (a->viewname) {
+      strcat(cmd," -f ");
+      strcat(cmd,a->viewname);
+    }
+    if (a->query_string) {
+      strcat(cmd," -q '");
+      strcat(cmd,a->query_string);
+      strcat(cmd,"'");
+    }
+    if (a->bufsize > 0)  {
+      int curlen = STRLEN(cmd);
+      char *pcmd = &cmd[curlen];
+      snprintf(pcmd,len-curlen," -B %d",a->bufsize);
+    }
+    if (a->metadata) {
+      strcat(cmd," -m");
+    }
+    else {
+      int curlen = STRLEN(cmd);
+      char *pcmd = &cmd[curlen];
+      if (a->start_row > 1) {
+	snprintf(pcmd,len-curlen," -l %d,%d",a->start_row,a->maxrows);
+      } else {
+	snprintf(pcmd,len-curlen," -l %d",a->maxrows);
+      }
+    }
+    if (a->param) {
+      strcat(cmd," -V '");
+      strcat(cmd,a->param);
+      strcat(cmd,"'");
+    }
+    if (a->version > 0) {
+      int curlen = STRLEN(cmd);
+      char *pcmd = &cmd[curlen];
+      snprintf(pcmd,len-curlen," -n %d",a->version);
+    }
+    if (a->odbsql == 0) {
+      strcat(cmd," -F");
+    }
+    if (a->dbname) {
+      strcat(cmd," ");
+      strcat(cmd,a->dbname);
+    }
+
+    /* run askodb and pipe stdout result back to socket, chunk-by-chunk */
+    
+    fprintf(stdout,"%s : \"%s\"\n",odb_resource_stamp_(Server),cmd);
+    fflush(stdout);
+    fp = popen(cmd,"r");
+    pipefd = fileno(fp);
+    if (verbose) fprintf(stderr,"%s: pipe fp=%p, fd=%d\n",Server,fp,pipefd);
+    if (fp) {
+      int errno_save = 0;
+      char buf[ODBCS_MAXLINE];
+      int first_time = 1;
+      errno = 0;
+      while ( (n = Readn_timeo(pipefd, buf, sizeof(buf), timeout)) > 0) {
+	if (!rawform || first_time) {
+	  Writen(sockfd, &n, sizeof(n));
+	  if (verbose) fprintf(stderr,"%s: written %slength = %d\n",
+			       Server,rawform ? "INITIAL " : "", n);
+	}
+	first_time = 0;
+	Writen(sockfd, buf, n);
+	if (verbose) {
+	  fprintf(stderr,"%s: echoed from pipe to client: %d bytes\n",Server,n);
+	  fflush(stderr);
+	}
+      }
+      if (verbose) fprintf(stderr,"%s: Last n = %d\n",Server,n);
+      if (n == 0) errno = 0;
+      istat = pclose(fp);
+      errno_save = errno;
+      if (verbose) fprintf(stderr,"%s: pclose status = %d, errno = %d\n",Server,istat,errno_save);
+      if (istat != 0 && errno_save == 0) istat = 0; /* Since nothing bad, I presume */
+      if (istat != 0 || errno_save != 0) {
+	FILE *errout = (istat != 0) ? stdout : stderr;
+	char *errmsg = strerror(errno_save);
+	fprintf(errout,
+		"%s : status = %d [errno=%d: %s] : %s error(s) in \"%s\"\n",
+		odb_resource_stamp_(Server),istat,errno_save,errmsg,
+		(istat != 0) ? "Unidentified" : "Watch these",
+		cmd);
+	fflush(errout);
+      }
+    }
+    else { /* failed to popen() altogether */
+      fprintf(stdout,"%s : popen() failed for \"%s\"\n",odb_resource_stamp_(Server),cmd);
+      fflush(stdout);
+      istat = -1;
+    }
+    if (istat > 0) istat = -istat;
+    n = (istat == 0) ? 0 : istat; /* An end of message : length == 0 or istat-error (< 0)*/
+    Writen(sockfd, &n, sizeof(n));
+    if (verbose) fprintf(stderr,"%s: written EOF-length/istat = %d\n",Server,n);
+
+    /* clean up */
+
+    FREE(cmd);
+  }
+
+  free_askodb_t(a,1);
+  return NULL;
+}
+
+PRIVATE char *
+read_str(const char *what, int sockfd, int timeout, int verbose, int byteswap)
+{
+  const int one = 1;
+  int n, nbytes;
+  char *buf = NULL;
+  nbytes = Readn_timeo(sockfd, &n, sizeof(n), timeout);
+  if (nbytes != sizeof(n))
+    err_sys("read_str(%s;%s): unable to read length info (expected %d, got %d bytes)",
+	    Server, what, sizeof(n), nbytes);
+  if (byteswap) swap4bytes_(&n, &one);
+  if (verbose) fprintf(stderr,"%s;%s: obtained length = %d\n",Server,what,n);
+  ALLOC(buf, n + 1);
+  nbytes = Readn_timeo(sockfd, buf, n, timeout);
+  if (nbytes != n)
+    err_sys("read_str(%s;%s): unable to read info from client (expected %d, got %d bytes)",
+	    Server, what, n, nbytes);
+  buf[n] = '\0';
+  if (verbose) fprintf(stderr,"%s;%s: obtained info from client, %d bytes : %s\n",Server,what,n,buf);
+  return buf;
+}
+
+
+PUBLIC int
+odbi_server(int sockfd, int timeout, int verbose)
+{
+  int rc = 0;
+  ssize_t    n;
+  const unsigned int expected_magic_word = ODBI;
+  unsigned int magic_word;
+  askodb_t *a = NULL;
+  int array[ODBCS_INFO];
+  int connect_count = 0;
+  int server_version = 0;
+
+  memset(array,0,sizeof(array));
+
+  Pid = getpid();
+  ALLOC(Server,100);
+  snprintf(Server,100,">s[%d]",Pid);
+
+  a = init_askodb_t(NULL);
+  a->silent = verbose ? 0 : 1;
+  a->verbose = verbose;
+  a->timeout = timeout;
+  (void) codb_versions_(NULL, NULL, &server_version, NULL);
+  a->version = server_version;
+  a->odbsql = 1; /* By default *do use* the fast odbsql -approach (no compilations) */
+
+  Signal(SIGCHLD,SIG_DFL);
+  /* Signal(SIGCHLD,sig_chld); */
+  Signal(SIGPIPE,SIG_IGN);
+
+  /* Initial handshake */
+
+  n = Readn_timeo(sockfd, &magic_word, sizeof(magic_word), timeout);
+  if (n != sizeof(magic_word))
+    err_sys("%s: initial handshake between client & server has failed",Server);
+
+  a->byteswap = (magic_word != expected_magic_word);
+
+  if (verbose) fprintf(stderr,"%s: byteswap = %d (expected=%u, got=%u)\n", 
+		       Server, a->byteswap, expected_magic_word, magic_word);
+
+  array[0] = expected_magic_word;
+  array[1] = timeout;
+  array[2] = verbose;
+  array[3] = server_version;
+
+  Writen(sockfd, array, sizeof(array));
+
+  for ( ; ; ) { /* Loop until client is finished */
+    const int one = 1;
+    const int two = 2;
+    const int three = 3;
+    int limits[3];
+    int nbytes, tag = -1;
+    double value;
+
+    nbytes = Readn_timeo(sockfd, &tag, sizeof(tag), timeout);
+    if (nbytes != sizeof(tag))
+      err_sys("odbi_server(%s): unable to read tag (expected %d, got %d bytes)",
+	      Server, sizeof(tag), nbytes);
+
+    if (a->byteswap) swap4bytes_(&tag, &one);
+
+    if (verbose) fprintf(stderr,"%s: obtained tag = %d (%s)\n",
+			 Server, tag,
+			 (tag >= 0 && tag < ODBCS_MAXTAGS) ? odbcs_tagname[tag] : "????");
+    
+    switch (tag) {
+
+    case ODBCS_TAG_CONNECT:
+      if (connect_count > 0) break; /* allow only one connect/session */
+      {
+	askodb_t *asave = a;
+	char *params = read_str("connect_data",sockfd,timeout,verbose,a->byteswap);
+	a = run_askodb(asave, 0, 0,
+		       sockfd,timeout,verbose,
+		       params);
+	FREE(params);
+	free_askodb_t(asave,0);
+	FREE(asave);
+      }
+
+      fprintf(stdout,
+	      "%s : Connect user=%s@%s;ip_addr=%s;pw=%s;db=%s;mode=%s;datapath=%s;"
+	      "workdir=%s;poolmask=%s;exe=%s;version=%d;odbsql=%d;timeout=%d\n",
+	      odb_resource_stamp_(Server),
+	      a->user, a->clihost, a->cliaddr,
+	      a->password, a->dbname, a->mode, a->datapath, a->workdir,
+	      a->poolmask, a->exe, a->version, a->odbsql, a->timeout);
+      fflush(stdout);
+
+      /* server imposed restrictions for defaults */
+      if (!verbose) a->verbose = 0;
+      if (!verbose) a->silent = 1;
+      if (a->timeout > timeout) a->timeout = timeout;
+
+      run_askodb(a, 0, 1,
+		 sockfd,timeout,verbose,
+		 "nometadata; maxrows=0; viewname=@");
+
+      a->clean = 0; /* prevents further re-clean/re-compiles in this run */
+      connect_count++;
+      break;
+
+    case ODBCS_TAG_DB_METADATA:
+      run_askodb(a, 0, 1,
+		 sockfd,timeout,verbose,
+		 "metadata");
+      break;
+
+    case ODBCS_TAG_PREPARE_QUERY:
+      FREE(a->viewname);
+      a->viewname = read_str("viewname",sockfd,timeout,verbose,a->byteswap);
+      FREE(a->query_string);
+      a->query_string = read_str("query_string",sockfd,timeout,verbose,a->byteswap);
+      if (STRLEN(a->query_string) == 0 || strstr(a->viewname,".so")) {
+	FREE(a->query_string);
+      }
+
+      run_askodb(a, 0, 1,
+		 sockfd,timeout,verbose,
+		 "maxrows=0; nometadata");
+      break;
+
+    case ODBCS_TAG_FETCHFILE:
+    case ODBCS_TAG_EXECUTE_QUERY:
+      nbytes = Readn_timeo(sockfd, limits, sizeof(limits), timeout);
+      if (nbytes != sizeof(limits))
+	err_sys("odbi_server(%s): unable to read limits (expected %d, got %d bytes)",
+		Server, sizeof(limits), nbytes);
+      if (a->byteswap) swap4bytes_(limits, &three);
+
+      a->start_row = limits[0];
+      a->maxrows = limits[1];
+      a->bufsize = limits[2];
+
+      if (verbose)
+	fprintf(stderr,"%s: limits are now as follows: start_row=%d, maxrows=%d, bufsize=%d\n",
+		Server, a->start_row, a->maxrows, a->bufsize);
+	
+      if (tag == ODBCS_TAG_FETCHFILE) {
+
+	FREE(a->outfil);
+	a->outfil = read_str("outfil",sockfd,timeout,verbose,a->byteswap);
+	FREE(a->binary);
+	a->binary = read_str("binary",sockfd,timeout,verbose,a->byteswap);
+	
+	if (verbose)
+	  fprintf(stderr,"%s: Fetching file='%s', format='%s'\n",
+		  Server, a->outfil, a->binary);
+	
+	run_askodb(a, 1, 1,
+		   sockfd,timeout,verbose,
+		   "nometadata; data_only;");
+
+      } 
+      else if (tag == ODBCS_TAG_EXECUTE_QUERY) {
+	run_askodb(a, 1, 1,
+		   sockfd,timeout,verbose,
+		   "nometadata; data_only; binary=%s",
+		   a->binary ? a->binary : "binary");
+      }
+      break;
+
+    case ODBCS_TAG_BIND_PARAM:
+      {
+	int len;
+	char *c;
+	char *new_param = read_str("param",sockfd,timeout,verbose,a->byteswap);
+	nbytes = Readn_timeo(sockfd, &value, sizeof(value), timeout);
+	if (nbytes != sizeof(value))
+	  err_sys("odbi_server(%s): unable to read bind_param() value (expected %d, got %d bytes)",
+		  Server, sizeof(value), nbytes);
+	if (a->byteswap) swap8bytes_(&value, &one);
+	if (!a->param) a->param = STRDUP("");
+	len = STRLEN(a->param) + 1 + STRLEN(new_param) + 50;
+	REALLOC(a->param,len);
+	c = &a->param[STRLEN(a->param)];
+	snprintf(c,len,";%s=%.14g",new_param,value);
+	FREE(new_param);
+      }
+      break;
+
+    case ODBCS_TAG_BYEBYE:
+      fprintf(stdout,
+	      "%s : Bye,bye user=%s@%s;ip_addr=%s;pw=%s;db=%s;mode=%s;datapath=%s;"
+	      "workdir=%s;poolmask=%s;exe=%s;version=%d;odbsql=%d;timeout=%d\n",
+	      odb_resource_stamp_(Server),
+	      a->user, a->clihost, a->cliaddr,
+	      a->password, a->dbname, a->mode, a->datapath, a->workdir,
+	      a->poolmask, a->exe, a->version, a->odbsql, a->timeout);
+      fflush(stdout);
+      /* Finished */
+      goto finish;
+
+    case ODBCS_TAG_TIMEOUT:
+      {
+	int new_timeout = timeout;
+	nbytes = Readn_timeo(sockfd, &new_timeout, sizeof(new_timeout), timeout);
+	if (nbytes != sizeof(new_timeout))
+	  err_sys("odbi_server(%s): unable to read new timeout value (expected %d, got %d bytes)",
+		  Server, sizeof(new_timeout), nbytes);
+	if (a->byteswap) swap4bytes_(&new_timeout, &one);
+	if (new_timeout > 0) {
+	  int old_timeout = timeout;
+	  a->timeout = timeout = new_timeout;
+	  if (verbose)
+	    fprintf(stderr,"%s: new timeout is now %d secs (was %d)\n",
+		    Server, a->timeout, old_timeout);
+	}
+      }
+      break;
+
+    case ODBCS_TAG_VERBOSE:
+      {
+	int new_verbose = verbose;
+	nbytes = Readn_timeo(sockfd, &new_verbose, sizeof(new_verbose), timeout);
+	if (nbytes != sizeof(new_verbose))
+	  err_sys("odbi_server(%s): unable to read new verbose value (expected %d, got %d bytes)",
+		  Server, sizeof(new_verbose), nbytes);
+	if (a->byteswap) swap4bytes_(&new_verbose, &one);
+	if (new_verbose == 0 || new_verbose == 1) {
+	  int old_verbose = verbose;
+	  a->verbose = verbose = new_verbose;
+	  a->silent = verbose ? 0 : 1;
+	  if (verbose || old_verbose)
+	    fprintf(stderr,"%s: verbose is now turned %s\n",
+		    Server, a->verbose ? "ON" : "OFF");
+	}
+      }
+      break;
+
+    default:
+      fprintf(stderr,"%s: Unrecognized tag '%d'\n", Server, tag);
+      rc = 1;
+      goto finish;
+    } /* switch (tag) */
+  } /* for ( ; ; ) */
+
+ finish:
+  return rc;
+}
+
+#else
+
+void dummy_odbi_server() { }
+
+#endif
+
diff --git a/odb/src/aux/odbi_shared.c b/odb/src/aux/odbi_shared.c
new file mode 100644
index 0000000..7995d4b
--- /dev/null
+++ b/odb/src/aux/odbi_shared.c
@@ -0,0 +1,310 @@
+/*!
+     \file odbi_shared.c
+     \brief ODBI API with functions common to Client/server and Direct access 
+     Intended to be include from odbi_direct.c or odbi_client.c or odbi_common.c
+ */
+
+#if defined(ODBI_DIRECT) || defined(ODBI_CLIENT)
+
+/*!
+  Given an SQL request, it returns the jcol column name with its associated table name (col_name\@table_name)
+
+   @param vq   ODBI query handle i.e. contains information about the current SQL query (read only).
+   @param jcol index of the column name. Note: the range is [1..ncols]
+   @return The jcol column name for the current SQL query. Please note that it also contains the table name i.e. lat\@hdr and not lat only.
+ */
+const char *ODBI_colname(const void *vq, 
+			 int jcol)
+{
+  const ODBI_query_t *q = vq;
+  const char *colname = NULL;
+  DRHOOK_START(ODBI_colname);
+  if (q && q->cols && jcol >= 1 && jcol <= q->ncols_all) {
+    colname = q->cols[--jcol].name;
+  }
+  DRHOOK_END(0);
+  return colname;
+}
+
+/*!
+  Given an SQL request, it returns the jcol column nickname. The column nickname is the nickname given in the SQL query (select lat\@hdr as lat) and if not given it returns the column name.
+
+   @param vq   ODBI query handle i.e. contains information about the current SQL query (read only).
+   @param jcol index of the column nickname. Note: the range is [1..ncols]
+   @return The jcol column nickname for the current SQL query. If no nickname is defined for this column name then it returns the full column name (col_name\@table_name).
+ */
+const char *ODBI_colnickname(const void *vq, 
+			 int jcol)
+{
+  const ODBI_query_t *q = vq;
+  const char *colnickname = NULL;
+  DRHOOK_START(ODBI_colnickname);
+  if (q && q->cols && jcol >= 1 && jcol <= q->ncols_all) {
+    colnickname = q->cols[--jcol].nickname;
+  }
+  DRHOOK_END(0);
+  return colnickname;
+}
+
+/*!
+  Given an SQL request, it returns the "ascii" type of the jcol column (pk1int, pk9real, string, etc.).
+   @param vq   ODBI query handle i.e. contains information about the current SQL query (read only).
+   @param jcol index of a column. Note: the range is [1..ncols]
+   @return The ODB type of the jcol column (pk1int, pk9real, string, etc.)
+ */
+const char *ODBI_coltype(const void *vq, 
+			 int jcol)
+{
+  const ODBI_query_t *q = vq;
+  const char *coltype = NULL;
+  DRHOOK_START(ODBI_coltype);
+  if (q && q->cols && jcol >= 1 && jcol <= q->ncols_all) {
+    coltype = q->cols[--jcol].type;
+  }
+  DRHOOK_END(0);
+  return coltype;
+}
+
+/*!
+  Given an SQL request, it returns the type of the jcol column as a numerical value. See include/privpub.h for more details.
+   @param vq   ODBI query handle i.e. contains information about the current SQL query (read only).
+   @param jcol index of a column. Note: the range is [1..ncols]
+   @return The ODB type of the jcol column as a numerical value
+ */
+unsigned int ODBI_coltypenum(const void *vq, 
+			     int jcol)
+{
+  const ODBI_query_t *q = vq;
+  unsigned int coltypenum = 0;
+  DRHOOK_START(ODBI_coltypenum);
+  if (q && q->cols && jcol >= 1 && jcol <= q->ncols_all) {
+    coltypenum = q->cols[--jcol].dtnum;
+  }
+  DRHOOK_END(0);
+  return coltypenum;
+}
+
+/*!
+  Return the number of columns for a given SQL query
+   @param  vq  ODBI query handle i.e. contains information about the current SQL query (read only).
+   @return The number of columns for the given SQL query
+ */
+int ODBI_ncols(const void *vq)
+{
+  const ODBI_query_t *q = vq;
+  int ncols = 0; /* ODB_maxcols() ?? */
+  DRHOOK_START(ODBI_ncols);
+  if (q) {
+    ncols = q->ncols_fixed;
+  }
+  DRHOOK_END(0);
+  return ncols;
+}
+
+/*!
+  Check whether a value corresponds to NULL or not (compared to $mdi). Please note that this function is not thread safe.
+  @param d column value
+  @return 1 if d is NULL else 0
+ */
+int ODBI_is_null(double d)
+{
+  int is_null;
+  static int first_time = 1; /* not thread safe */
+  static double nmdi = 0;
+  static double rmdi = 0;
+  DRHOOK_START(ODBI_is_null);
+  if (first_time) {
+    pcma_get_mdis_(&nmdi, &rmdi);
+    first_time = 0;
+  }
+  is_null = ((d == rmdi) || (d == nmdi)) ? 1 : 0;
+  DRHOOK_END(0);
+  return is_null;
+}
+
+/*!
+  Get the IO method for a given database handle
+   @param vdb ODB database handle (ODBI_db_t)
+   @return the IO method
+ */
+int ODBI_io_method(void *vdb)
+{
+  ODBI_db_t *db = vdb;
+  int io_method = 0;
+  DRHOOK_START(ODBI_io_method);
+  if (db) {
+    io_method = db->io_method;
+  }
+  DRHOOK_END(0);
+  return io_method;
+}
+
+/*!
+  Return the number of pools of a given ODB database
+  @param vdb ODB database handle (ODBI_db_t)
+  @return The total number of pools
+ */
+int ODBI_npools(void *vdb)
+{
+  ODBI_db_t *db = vdb;
+  int npools = 0;
+  DRHOOK_START(ODBI_npools);
+  if (db) {
+    npools = db->npools;
+  }
+  DRHOOK_END(0);
+  return npools;
+}
+
+/*!
+  Swap bytes (conversion little/big endian). 
+  @param v a vector of consecutive 2,4 or 8-bytes to be swapped. vlen elements of v will be swapped.
+  @param vlen length of v
+  @param elemsize set to 2,4 or 8 ==> v[] is treated as 2,4 or 8-byte vector
+ */
+void ODBI_swapbytes(void *v,
+		    int vlen,
+		    int elemsize)
+{
+  DRHOOK_START(ODBI_swapbytes);
+  if (v) {
+    switch (elemsize) {
+    case 2:
+      swap2bytes_(v, &vlen);
+      break;
+    case 4:
+      swap4bytes_(v, &vlen);
+      break;
+    case 8:
+      swap8bytes_(v, &vlen);
+      break;
+    default: /* do nothing */
+      break;
+    } /* switch (elemsize) */
+  }
+  DRHOOK_END(0);
+}
+
+/*!
+  Prints a column value according to its ODB type (make conversion when necessary)
+  @param fp File pointer (where to output data)
+  @param vq SQL query handle (ODBI_query_t)
+  @param jcol Column index to be printed
+  @param d value to be printed
+  @param delim Delimiter character to use
+  @param print_nulls if >0 then prints NULL if d is null (use ODBI_is_null) else prints the integer value $mdi
+ */
+void ODBI_printcol(FILE *fp,
+		   void *vq,
+		   int jcol,
+		   const double d,
+		   const char *delim,
+		   int print_nulls)
+{
+  ODBI_query_t *q = vq;
+  DRHOOK_START(ODBI_printcol);
+  if (q && q->cols && jcol >= 1 && jcol <= q->ncols_fixed) {
+    /* More later */
+    unsigned int dtnum = ODBI_coltypenum(q,jcol);
+    if (!delim) delim = ",";
+    fprintf(fp,"%s",delim);
+    if (dtnum == DATATYPE_STRING) {
+      int i;
+      union {
+	double d;
+	char s[sizeof(double)+1];
+      } u;
+      u.d = d;
+      for (i=0; i<sizeof(double); i++) {
+	int c = u.s[i];
+	if (!isprint(c)) u.s[i] = ' '; /* replace non-printables with spaces */
+      }
+      u.s[sizeof(double)] = '\0';
+      fprintf(fp,"\"%s\"",u.s);
+    }
+    else {
+      if (print_nulls && ODBI_is_null(d)) {
+	fprintf(fp,"NULL");
+      }
+      else {
+	if (dtnum == DATATYPE_YYYYMMDD) {
+	  yyyymmdd x = d;
+	  fprintf(fp,"%8.8d",x);
+	}
+	else if (dtnum == DATATYPE_HHMMSS) {
+	  hhmmss x = d;
+	  fprintf(fp,"%6.6d",x);
+	}
+	else {
+	  fprintf(fp,"%.14g",d);
+	}
+      } /* if (print_nulls && ODBI_is_null(d)) */
+    }
+  }
+  DRHOOK_END(0);
+}
+			  
+#include <sys/time.h>
+
+static 
+double cs_walltime()
+{
+  static double time_init = 0;
+  double time_in_secs;
+  struct timeval tbuf;
+  if (gettimeofday(&tbuf,NULL) == -1) perror("CS_WALLTIME");
+
+  if (time_init == 0) time_init =
+    (double) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0);
+
+  time_in_secs =
+  (double) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0) - time_init;
+
+  return time_in_secs;
+}
+
+/*!
+  ODB timer (in seconds)
+  @param reftime reference time to use to compute the wall clock time
+  @return The time difference (in seconds) between the current time and the reference time.
+ */
+double ODBI_timer(const double *reftime)
+{
+  double delta = 0;
+  DRHOOK_START(ODBI_timer);
+  delta = cs_walltime();
+  if (reftime) delta -= *reftime;
+  DRHOOK_END(0);
+  return delta;
+}
+
+/* The following will check [when implemented] the value of ODBI_errno */
+/*!
+  It will print [when implemented] and error message to stderr
+  @param s error message to be printed
+ */
+void ODBI_perror(const char *s)
+{
+  /* To be implemented */
+}
+
+/*!
+  It will check [when implemented] the error code (ODBI_error) and return an error message
+  @param errnum error code
+  @return The error message corresponding to the given error code.
+ */
+const char *ODBI_strerror(int errnum)
+{
+  return (const char *)NULL; /* To be implemented */
+}
+
+
+#else
+
+/*!
+ A dummy, when compiled alone 
+*/
+
+void dummy_ODBI_shared() { }
+
+#endif
diff --git a/odb/src/aux/odbsql.c b/odb/src/aux/odbsql.c
new file mode 100644
index 0000000..3cf731f
--- /dev/null
+++ b/odb/src/aux/odbsql.c
@@ -0,0 +1,563 @@
+#include "odb.h"
+#include "info.h"
+#include "result.h"
+#include "idx.h"
+#include "evaluate.h"
+#include "cdrhook.h"
+#include "cargs.h" /* from ifsaux/include/ */
+
+#define USAGE_1 "Usage: %s /dir/database.sch ODB/SQL-query_file begin_row end_row {debug_on=1|off=0} \\\n"
+#define USAGE_2 "       {konvert_latlon_to_degrees=1|no_conversion=0} output_format output_file\n"
+#define USAGE_3 "       {write_title_header=1|do_not_write=0} {global_row_count_on=1|off=0}\n"
+#define USAGE_4 "       {progress_bar_on=1|off=0} {launch_report_viewer_on=1|off=0} cmap-file\n"
+#define USAGE_5 "       {fmt_string=[-|%%15.7g (for example)]} {joinstr_on=1|off=0} {comma_separated_varvalues|-}\n"
+
+extern double util_walltime_();
+
+/* The following unit number must be 6 (stdout) and cannot be 0 (for stderr), 
+   since stderr is normally re-directed to /dev/null by the odbsql-script */
+#define PROGRESS_BAR_IOUNIT 6
+
+#define PROGRESS_BEGIN(zwall) \
+{ \
+  if (progress_bar) { \
+    zwall[0] = util_walltime_(); \
+  } \
+}
+
+#define PROGRESS_END(zwall, ipoolno) \
+{ \
+  if (progress_bar) { \
+    const int iounit = PROGRESS_BAR_IOUNIT; \
+    double wtime; \
+    zwall[1] = util_walltime_(); \
+    wtime = zwall[1] - zwall[0]; \
+    totalrows += nrows; \
+    codb_progress_bar_(&iounit, \
+		       info->view, \
+		       &ipoolno, \
+		       &npools, \
+		       &nrows, \
+		       &totalrows, \
+		       &wtime, \
+		       NULL \
+		       , STRLEN(info->view)); \
+  } \
+}
+
+#define PROGRESS_INIT() \
+{ \
+  if (progress_bar) { \
+    int ipoolno = 0; \
+    int nrows = 0; \
+    double zwall[2]; \
+    PROGRESS_BEGIN(zwall); \
+    codb_set_progress_bar_("totalrows", &totalrows, STRLEN("totalrows")); \
+    PROGRESS_END(zwall, ipoolno); \
+  } \
+}
+
+#define PROGRESS_NL() \
+{ \
+  if (progress_bar) { \
+    const int iounit = PROGRESS_BAR_IOUNIT; \
+    codb_progress_nl_(&iounit); \
+  } \
+}
+
+
+#define PROGRESS_FINISH() \
+{ \
+  if (progress_bar) { \
+    const int iounit = PROGRESS_BAR_IOUNIT; \
+    const int newline = 1; \
+    double wtime = util_walltime_(); \
+    wtime -= walltot[0]; \
+    codb_progress_bar_(&iounit, \
+		       info->view, \
+		       &npools, \
+		       &npools, \
+		       &totalrows, \
+		       &totalrows, \
+		       &wtime, \
+		       &newline \
+		       , STRLEN(info->view)); \
+  } \
+}
+
+
+PRIVATE void
+Launch(const char *outfile, const char *viewname, Bool reporter, Bool warrow)
+{
+  char *env = reporter ? getenv("ODB_REPORTER") : getenv("ODB_PLOTTER");
+  if (!env) {
+    if (reporter) 
+      env = "$ODB_FEBINPATH/b4.x";
+    else if (warrow)
+      env = "$ODB_FEBINPATH/plotobs.x -s -D$MAGICS_DEVICE -W -b";
+    else
+      env = "$ODB_FEBINPATH/plotobs.x -s -D$MAGICS_DEVICE -b";
+  }
+  if (!strequ(env,"0") && !strequ(env,"/dev/null")) {
+    int len = STRLEN(env) + STRLEN(outfile) + 10;
+    int viewlen = STRLEN(viewname);
+    if (viewlen == 0) {
+      if (access(outfile,R_OK) == 0) {
+	char *cmd = NULL;
+	ALLOC(cmd, len);
+	snprintf(cmd, len, "%s%s%s &", env, reporter ? " " : "", outfile);
+	if (!reporter) {
+	  char *magics_device = getenv("MAGICS_DEVICE");
+	  if (!magics_device) {
+	    magics_device = STRDUP("MAGICS_DEVICE=JPEG");
+	    putenv(magics_device);
+	    /* do NOT FREE(magics_device) !! */
+	  }
+	} /* if (!reporter) */
+	(void) system(cmd);
+	FREE(cmd);
+      }
+      else {
+	fprintf(stderr,
+		"***Warning in Launch(outfile=%s, viewname=%s, reporter=%s): "
+		"Cannot access the file '%s'\n",
+		outfile, viewname ? viewname : NIL, reporter ? "true" : "false",
+		outfile);
+      }
+    }
+    else {
+      char *ppfile = NULL;
+      len += viewlen;
+      ALLOC(ppfile, len);
+      snprintf(ppfile, len, outfile, viewname);
+      Launch(ppfile, NULL, reporter, warrow);
+      FREE(ppfile);
+    }
+  }
+}
+
+
+PUBLIC void
+odbsql_(int *iret)
+{
+  int rc = 0;
+  DRHOOK_START(odbsql);
+  {
+    int argc = ec_argc();
+    char **argv = ec_argv();
+    char *dbname = NULL;
+    char *sql_query_file = NULL;
+    int begin_row = 1;
+    int end_row = 0;
+    int debug_on = false;
+    int konvert = 0;
+    char *format = "default";
+    char *outfile = "/dev/null";
+    int write_title = 1;
+    int global_row_count = 0;
+    int progress_bar = 0;
+    int launch_b4x = 0;
+    int launch_plotobs = 0;
+    char *cmapfile = "/dev/null";
+    char *fmt_string = NULL;
+    int joinstr = 0;
+    char *varvalue = NULL;
+    int nsetvar = 0;
+    set_t *setvar = NULL;
+
+    int numargs = argc-1;
+    
+    if (numargs != 16) {
+      fprintf(stderr,USAGE_1,argv[0]);
+      fprintf(stderr,USAGE_2);
+      fprintf(stderr,USAGE_3);
+      fprintf(stderr,USAGE_4);
+      fprintf(stderr,USAGE_5);
+      rc = -argc;
+      goto finish;
+    }
+    else {
+      int npools = 0;
+      int ntables = 0;
+      int handle = 0;
+      int save_begin_row;
+      int save_end_row;
+      int save_write_title;
+      int save_global_row_count;
+      int save_progress_bar;
+      Bool need_global_view;
+      Bool is_odb, is_plotobs, is_binary, is_odbtool, warrow, is_geo;
+      Bool is_netcdf;
+      Bool trigger_odbtool_write = false;
+
+      dbname = argv[1];
+      sql_query_file = argv[2];
+      begin_row = atoi(argv[3]);
+      end_row = atoi(argv[4]);
+      debug_on = atoi(argv[5]);
+      konvert = atoi(argv[6]);
+      format = argv[7];
+      outfile = argv[8];
+      write_title = atoi(argv[9]);
+      global_row_count = atoi(argv[10]);
+      progress_bar = atoi(argv[11]);
+      launch_b4x = atoi(argv[12]);
+      cmapfile = argv[13];
+      fmt_string = argv[14];
+      joinstr = atoi(argv[15]);
+      varvalue = strequ(argv[16],"-") ? NULL : argv[16];
+
+      setvar = ODBc_make_setvars(varvalue, &nsetvar);
+
+      save_begin_row = begin_row;
+      save_end_row = end_row;
+      save_write_title = write_title;
+      save_global_row_count = global_row_count;
+      save_progress_bar = progress_bar;
+
+      if (debug_on) (void) ODBc_debug_fp(stderr);
+      
+      handle = ODBc_open(dbname, "r", &npools, &ntables, NULL);
+      
+      ODB_fprintf(ODBc_get_debug_fp(),
+		  "%s: handle = %d, npools = %d, ntables = %d\n",
+		  dbname, handle, npools, ntables);
+
+      ODBc_set_format(format);
+
+      is_odb = ODBc_test_format_1("odb");
+      is_plotobs = ODBc_test_format_1("plotobs");
+      warrow = ODBc_test_format_1("wplotobs");
+      is_binary = (ODBc_test_format_1("binary") || ODBc_test_format_1("bindump"));
+      is_odbtool = ODBc_test_format_1("odbtool");
+      is_geo = ODBc_test_format_3(NULL, "geo", 3);
+      is_netcdf = ODBc_test_format_1("netcdf");
+
+      if (handle >= 1) {
+	int npools_saved = npools;
+	int *poolnos = NULL;
+	Bool reopen_per_view = false;
+	Bool reopen_per_pool = false;
+	Bool use_gzip_pipe = false;
+	FILE *fp_out = NULL;
+	int fpunit = -1;
+	int ip;
+	info_t *info = ODBc_sql_prepare_via_sqlfile(handle, sql_query_file, setvar, nsetvar);
+
+	/* The following returns the effective list of pools in poolmask
+	   and the length of this list == npools i.e. npools gets changed */
+	poolnos = ODB_get_permanent_poolmask(handle, &npools);
+
+	if (npools == 0) {
+	  rc = ODBc_close(handle);
+	  goto finish;
+	}
+
+	/* Obtain initial values for fp_out and for Bool-variables
+	   reopen_per_view, reopen_per_pool & use_gzip_pipe */
+
+	fp_out = ODBc_print_file(fp_out, &fpunit,
+				 outfile, format,
+				 -1, NULL,
+				 true,
+				 &reopen_per_view,
+				 &reopen_per_pool,
+				 &use_gzip_pipe);
+
+	if (launch_b4x) {
+	  if (fp_out == stdout || 
+	      reopen_per_pool || use_gzip_pipe ||
+	      is_binary || is_plotobs || warrow ||
+	      strequ(outfile,"/dev/null")) {
+	    launch_b4x = 0;
+	  }
+	}
+
+	launch_plotobs = 0;
+	if ((is_plotobs || warrow) && fp_out != stdout &&
+	    !reopen_per_pool && !reopen_per_view &&
+	    !strequ(outfile,"/dev/null")) {
+	  launch_plotobs = 1;
+	}
+
+	if ((is_plotobs || warrow) && !strequ(cmapfile,"/dev/null")) {
+	  (void) ODBc_set_kolor_map(cmapfile);
+	}
+
+	/* Ignore ORDERBY-clause when plotting */ 
+	if ((is_plotobs || warrow) && info->o && info->norderby > 0) info->norderby  = -info->norderby;
+
+	if (info->need_global_view ||
+	    is_netcdf) {
+	  need_global_view = true;
+	}
+	else {
+	  need_global_view = false;
+	}
+
+	if (progress_bar) {
+	  if (debug_on) progress_bar = 0;
+	  else if (fp_out == stdout && !need_global_view) progress_bar = 0;
+	  save_progress_bar = progress_bar;
+	}
+
+	if (progress_bar) {
+	  codb_set_progress_bar_("maxpoolno", &npools, STRLEN("maxpoolno"));
+	}
+      
+	while (info) {
+	  int the_first_print = 1;
+	  double walltot[2];
+	  void *next_info = ODBc_next(info);
+	  result_t *res = NULL;
+	  int totalrows = 0;
+	  const char *ascii_file = is_odbtool ? "temp_ascii.000001" : NULL;
+	  info_t *infoaux = NULL;
+	  int create_index = info->create_index;
+	  odbidx_t *stored_idx = NULL;
+	  Bool is_bc = false; /* In case used as basic calculator (bc) e.g. SELECT 1+2*3 */
+
+	  walltot[0] = util_walltime_();
+
+	  ODBc_print_info(ODBc_get_debug_fp(), info);
+
+	  if ((is_plotobs || warrow || is_odbtool || is_geo) && ODBc_nothing_to_plot(info)) {
+	    /* Check if $ODB_LAT & $ODB_LON present in SELECT-columns */
+	    goto next;
+	  }
+
+	  if (is_odbtool && info->ncols_true < 4) {
+	    /* Consider nothing to output for ODB-tool */
+	    goto next;
+	  }
+
+	  if (create_index < 0) {
+	    /* 'DROP INDEX name' or 'DROP INDEX *' */
+	    (void) codb_IDXF_drop(info);
+	    goto next;
+	  }
+	  else if (create_index > 0) {
+	    /* 'CREATE [UNIQUE|DISTINCT|BITMAP] INDEX name ...' */
+	    infoaux = ODBc_create_index_prepare(handle, info, NULL);
+	    if (infoaux) {
+	      stored_idx = ODBc_create_index_prepare(handle, info, infoaux);
+	    }
+	  }
+
+	  if (is_odbtool) trigger_odbtool_write = true; /* Triggers write of the ASCII-file */
+
+	  fp_out = ODBc_print_file(fp_out, &fpunit,
+				   outfile, format,
+				   -1, info->view,
+				   false,
+				   &reopen_per_view,
+				   &reopen_per_pool,
+				   &use_gzip_pipe);
+
+	  /* Ignore ORDERBY-clause when plotting */ 
+	  if ((is_plotobs || warrow) && info->o && info->norderby  > 0) 
+	    info->norderby  = -info->norderby;
+
+	  if (info->need_global_view ||
+	      is_netcdf) {
+	    need_global_view = true;
+	  }
+	  else {
+	    need_global_view = false;
+	  }
+
+	  begin_row = save_begin_row;
+	  end_row = save_end_row;
+	  write_title = save_write_title;
+	  global_row_count = save_global_row_count;
+	  progress_bar = save_progress_bar;
+
+	  if (info->is_bc) {
+	    /* This must be a basic calculator (bc) mode !! */
+	    is_bc = true;
+	    progress_bar = 0; /* Switch progress bar off in bc-mode */
+	    begin_row = end_row = global_row_count = 1; /* Expect just one result row */
+	  }
+	  else {
+	    is_bc = false;
+	  }
+
+	  if (info->need_hash_lock) {
+	    /* UNIQUEBY-clause present (or has SELECT DISTINCT) */
+	    codb_hash_set_lock_();
+	    codb_hash_init_();
+	  }
+
+	  if (global_row_count && need_global_view && !is_netcdf) global_row_count = 0;
+	  
+	  PROGRESS_INIT();
+
+	  for (ip=0; ip<npools; ip++) {
+	    /* This is a loop over effective pools i.e. those which
+	       were left in the poolmask */
+	    int jp = poolnos[ip];
+	    DEF_IT; /* defines variable "it" */
+	    double wall[2];
+	    PROGRESS_BEGIN(wall);
+	    if (create_index == 0) {
+	      int nrows = 0;
+	      if (info->has_thin) codb_thin_reset_(&it);
+	      nrows = ODBc_sql_exec(handle, info, jp, &begin_row, &end_row);
+	      if (nrows > 0) {
+		const Bool row_wise_preference = true;
+		res = ODBc_get_data(handle, res, info, jp, begin_row, end_row, false, &row_wise_preference);
+		PROGRESS_END(wall, ip);
+		if (!need_global_view && res) {
+		  fp_out = ODBc_print_file(fp_out, &fpunit,
+					   outfile, format,
+					   jp, info->view,
+					   false,
+					   &reopen_per_view,
+					   &reopen_per_pool,
+					   &use_gzip_pipe);
+		  res = ODBc_print_data(outfile, fp_out, res,
+					format, fmt_string,
+					konvert, write_title, joinstr,
+					the_first_print, (ip == npools-1) ? 1 : 0, 
+					NULL);
+		  the_first_print = 0;
+		  if (is_odbtool && trigger_odbtool_write) {
+		    (void) ODBc_ODBtool(NULL, NULL, ascii_file, true, res, info);
+		    trigger_odbtool_write = false;
+		  }
+		  else if (!is_odb) write_title = 0;
+		  res = ODBc_unget_data(res);
+		}
+		if (global_row_count) end_row -= nrows; /* This many rows left to retrieve */
+	      } /* if (nrows > 0) */
+	      else if (nrows == 0) {
+		PROGRESS_END(wall, ip);
+	      }
+	      if (info->has_thin) codb_thin_reset_(&it);
+	      info = ODBc_reset_info(info);
+	      if (global_row_count && end_row <= 0) break; /* Stop scanning now */
+	    }
+	    else if (stored_idx) { /* Handling of CREATE [UNIQUE|BITMAP] INDEX -stuff */
+	      int nrows = 0;
+	      stored_idx = codb_IDXF_create_index(handle,
+						  stored_idx, jp, 
+						  create_index, 
+						  infoaux, &nrows);
+	      infoaux = ODBc_reset_info(infoaux);
+	      PROGRESS_END(wall, ip);
+	    }
+	  } /* for (ip=0; ip<npools; ip++) */
+
+	  if (stored_idx) {
+	    int io_idx = -1;
+	    char *wherecond = S2D_fix(info, stored_idx->wherecond);
+	    char *filename = codb_IDXF_filename(true,
+						info->ph->idxpath, 
+						stored_idx->tblname, 
+						stored_idx->idxname,
+						info->ncols_true,
+						stored_idx->colnames,
+						wherecond,
+						".gz");
+	    char *true_filename = codb_IDXF_open(&io_idx, filename, "w");
+	    if (true_filename && io_idx >= 0) {
+	      int rc_idx;
+	      stored_idx->filename = true_filename;
+	      FREE(stored_idx->wherecond);
+	      stored_idx->wherecond = wherecond;
+	      rc_idx = codb_IDXF_write(io_idx, stored_idx, 
+				       info->binary_index ? 1 : 0,
+				       0, /* PCMA-packing method; 0 = no packing */
+				       0  /* idxtype; change idxtype from 1 to 2 or vice versa */
+				       );
+	      (void) codb_IDXF_close(io_idx, NULL);
+	      stored_idx = codb_IDXF_freeidx(stored_idx, 0);
+	    }
+	    else {
+	      fprintf(stderr, 
+		      "***Warning: Unable to open index file '%s' for writing\n",
+		      filename);
+	    }
+	    FREE(filename);
+	  }
+
+	  if (info->need_hash_lock) {
+	    /* UNIQUEBY-clause present (or has SELECT DISTINCT) */
+	    codb_hash_init_();
+	    codb_hash_unset_lock_();
+	  }
+
+	  if (need_global_view && res) {
+	    if (info->has_aggrfuncs) res = ODBc_aggr(res, 1);
+	    res = ODBc_operate(res, "count(*)");
+	    res = ODBc_sort(res, NULL, 0);
+	    if (is_netcdf) res = ODBc_merge_res("Final merge for NetCDF",
+						__FILE__, __LINE__,
+						res, res->ncols_out, info, false);
+	    if (!launch_b4x) PROGRESS_NL();
+	    res = ODBc_print_data(outfile, fp_out, res,
+				  format, fmt_string,
+				  konvert, write_title, joinstr,
+				  the_first_print, 1, 
+				  NULL);
+	    if (progress_bar) {
+	      int nrows = res->nrows_out;
+	      totalrows = 0;
+	      PROGRESS_END(walltot, npools);
+	    }
+	    if (is_odbtool && trigger_odbtool_write) {
+	      (void) ODBc_ODBtool(NULL, NULL, ascii_file, true, res, info);
+	      trigger_odbtool_write = false;
+	    }
+	    res = ODBc_unget_data(res);
+	  }
+
+	  PROGRESS_FINISH();
+
+	  if (launch_b4x && reopen_per_view) {
+	    if (fp_out) fflush(fp_out);
+	    Launch(outfile, info->view, true, false);
+	  }
+	  
+	next:
+
+	  if (infoaux) (void) ODBc_sql_cancel(infoaux);
+
+	  info = ODBc_sql_cancel(info);
+	  info = next_info;
+	} /* while (info) */
+
+	/* Close the print file */
+	fp_out = ODBc_print_file(fp_out, &fpunit,
+				 outfile, format,
+				 -1, NULL,
+				 false,
+				 &reopen_per_view,
+				 &reopen_per_pool,
+				 &use_gzip_pipe);
+
+	if (launch_b4x && !reopen_per_view) {
+	  Launch(outfile, NULL, true, false);
+	}
+
+	if (launch_plotobs) {
+	  Launch(outfile, NULL, false, warrow);
+	}
+
+	FREE(poolnos);
+
+	rc = ODBc_close(handle);
+      }
+      else { /* if (handle >= 1) ... */
+	rc = -255;
+      }
+    }
+  }
+ finish:
+  (void) ODBc_set_kolor_map(NULL);
+  DRHOOK_END(rc);
+  if (iret) *iret = rc;
+}
+  
+void odbsql(int *iret) { odbsql_(iret); }
+
diff --git a/odb/src/aux/pcma.c b/odb/src/aux/pcma.c
new file mode 100644
index 0000000..0e41756
--- /dev/null
+++ b/odb/src/aux/pcma.c
@@ -0,0 +1,305 @@
+#define PCMA_C 1
+
+#include "pcma.h"
+
+int pcma_blocksize = MINBLOCK;
+int pcma_verbose   = 0;
+int pcma_restore_packed = 0;
+
+/* These two following lines moved to pcma_mdis.c on 23-Nov-2004 by SS
+double pcma_nmdi = NMDI;
+double pcma_rmdi = RMDI;
+ */
+
+static 
+int (*pack_func_list[MAXPACKFUNC])
+(int method,
+ FILE *fp_out, 
+ const double cma[], int lencma, 
+ double nmdi,
+ double rmdi,
+ Packbuf *pbuf) = 
+{
+  pcma_1_driver,  /* Method 1 : adaptive, averaged */
+  pcma_2_driver,  /* Method 2 : Integer ZERO, RMDI_1 & RMDI_2 packing */
+  pcma_3_driver,  /* Method 3 : Lempel-Ziv-Welch  (does not vectorize) */
+  pcma_5_driver,  /* Method 5 : Same as 2, but also compresses small numbers [1..255] */
+  pcma_9_driver,  /* Method 9 : repeated word */
+  /* Methods 11..19 : 10 + # of signicant digits ; loss of flp. pnt. accurracy */
+  pcma_11to19_driver, 
+  /* Methods 21..29 : 20 + # of signicant digits ; loss of flp. pnt. accurracy ;
+     with 10^exponent scaling (a sort of merger of method#1 and methods#11..19) */
+  pcma_21to29_driver,
+  pcma_4_driver,   /* Method  4 : Delta packing (does not vectorize) */
+  pcma_4_driver,   /* Method 94 : Just a filler/pseudo-method for use by pcma_9.c */
+  pcma_31to39_driver, /* Methods 31..39 : The same as 21..29, but preserves 32-bit ints */
+};
+
+
+PUBLIC int
+pcma(        FILE *fp_in,
+             FILE *fp_out,
+              int  method,
+     const double  cma[],
+              int  lencma,
+	  Packbuf *pbuf,
+              int *bytes_in,
+              int *bytes_out)
+{
+  int rc = 0;
+  int (*pack_func)(int method,
+		   FILE *fp_out, 
+		   const double cma[], int lencma, 
+		   double nmdi, 
+		   double rmdi,
+		   Packbuf *pbuf) = NULL;
+  double nmdi = pcma_nmdi;
+  double rmdi = pcma_rmdi;
+
+  *bytes_in  = 0;
+  *bytes_out = 0;
+
+  switch (method) {
+    /* CMA-specific bitmap methods */
+  case 1: /* Adaptive, averaged */
+  case 2:
+  case 5:
+  case 9:
+  case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19:
+  case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29:
+  case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
+  case 4:  case 94:
+    if (sizeof(double)/sizeof(unsigned int) != 2) {
+      fprintf(stderr,
+	      "pcma(#%d): There ain't exactly two uint words per double prec. word\n",
+	      method);
+      rc = -2;
+      goto finish;
+    }
+    if (method == 4) {
+      if (sizeof(u_ll_t)/sizeof(unsigned int) != 2) {
+      fprintf(stderr,
+	      "pcma(#%d): There ain't exactly two uint words per unsigned long long int\n",
+	      method);
+	rc = -7;
+	goto finish;
+      }
+    }
+    break;
+ 
+  case 3: /* ECMWF's internal LZW-packing (used with the MARS as well) */
+    break;
+
+  default:
+    /* Error : Unrecognized packing method */
+    fprintf(stderr,"pcma(#%d): Invalid packing method\n",method);
+    rc = -1;
+    goto finish;
+  } /* switch (method) */
+  
+  pack_func = pack_func_list[look_up[method]];  
+
+  if (!fp_in) {
+    /* CMA-array is assumed to be provided */
+
+    int j, replen;
+    j=0;
+
+    while (j<lencma) { 
+      /* No PCMA-check is needed since a genuine CMA comes now from an application */
+      replen = cma[j];
+
+      *bytes_in += replen * sizeof(double);
+
+      rc = pack_func(method, fp_out, &cma[j], replen, nmdi, rmdi, pbuf);
+      if (rc >= 0) {
+	*bytes_out += rc;
+	rc = 0;
+      }
+      else {
+	/* Error */
+	break;
+      }
+
+      j += replen;
+    }
+  }
+
+  else {  
+    /* Read one report at a time from CMA-file and pack it */
+    int maxalloc;
+    int n, minlen = MINLEN;
+    double oneword;
+    double *report = NULL;
+    int replen;
+    union {
+      double d;
+      int    PCMA_word;
+    } jack;
+    int done = 0;
+
+    rc = 0;
+    ALLOC(report, pcma_blocksize);
+    if (!report) {
+      fprintf(stderr,
+	      "pcma(#%d): Unable to allocate initial space (%d DP-words) for a CMA-data\n",
+	      method, pcma_blocksize);
+      rc = errno;
+      goto finish;
+    }
+    maxalloc = pcma_blocksize;
+
+    for (;;) {
+      n = fread(&oneword, sizeof(double), 1, fp_in);
+      if (n != 1) {
+	if (!feof(fp_in)) rc = errno; /* Error : EOF was expected ... */
+	break;
+      }
+
+      if (!done) {
+	jack.d = oneword;
+	if (jack.PCMA_word == PCMA) {
+	  /* Sorry, this ain't going to work; file is PCMA-packed already */
+	  fprintf(stderr,"pcma(#%d): File has already been packed\n",method);
+	  rc = -3;
+	  break;
+	}
+	done = 1; /* Do it once only to save some time */
+      }
+      
+      replen = oneword;
+      if (replen > maxalloc) {
+	REALLOC(report, replen);
+	maxalloc = replen;
+      }
+
+      if (!report) {
+	fprintf(stderr,
+		"pcma(#%d): Unable to allocate space (%d DP-words) for a CMA-report\n",
+		method, replen);
+	rc = errno;
+	break;
+      }
+      
+      report[0] = oneword;
+      n = fread(&report[1], sizeof(double), replen-1, fp_in);
+      if (n != (replen-1)) {
+	rc = errno; /* Error : Probably an unexpected EOF */
+	break;
+      }
+
+      *bytes_in  += replen * sizeof(double);
+      n = pack_func(method, fp_out, report, replen, nmdi, rmdi, pbuf);
+
+      if (n < minlen) {
+	/* Error : Invalid no. of packed bytes */
+	rc = n;
+	break;
+      }
+
+      *bytes_out += n;
+    };
+
+    FREE(report);    
+  }
+
+ finish:
+
+  return rc;
+}
+
+PUBLIC void *
+PackDoubles(const double v[],
+	    const int nv,
+	    int *nbytes)
+{
+  const int min_bytes = 2 * sizeof(uint);
+  uint *pk = NULL;
+  int Nbytes = 0;
+
+  ALLOC(pk, 2);
+
+  if (nv > 0) {
+    int nv_bytes = nv * sizeof(double);
+    int npk = nv_bytes / sizeof(uint); /* First guess */
+    do { /* See how it's done in aux/pcma_3.c */
+      int npk_bytes = npk * sizeof(uint);
+      REALLOC(pk, 2 + npk);
+      lzw_pack_((const unsigned char *)v, &nv_bytes,
+		(unsigned char *)&pk[2], &npk_bytes,
+		&Nbytes);
+      if (Nbytes < 0) {
+	int nb = -Nbytes;
+	npk = RNDUP(nb,b4)/b4;
+      }
+    } while (Nbytes < 0);
+  }
+
+  pk[0] = (uint)Nbytes;     /* No of packed bytes */
+  pk[1] = (uint)MAX(nv,0);  /* Length of the double vector just packed (in double-words) */
+  Nbytes += min_bytes;      /* Total no. of bytes in "pk" */
+
+  if (nbytes) *nbytes = Nbytes;
+  return pk;
+}
+
+
+/*============= Intended for Fortran-access, but rather general ===============*/
+
+PUBLIC void
+cma2pcma_(const    int *method,
+          const double  cma[],
+	  const    int *lencma,
+	  unsigned int  packed_stream[],
+	  const    int *lenpacked_stream,
+                   int *bytes_in,
+                   int *bytes_out,
+	           int *retcode)
+{
+  int rc = 0;
+  int packingmethod = *method;
+  int cmalen = *lencma;
+  Packbuf pbuf;
+
+  pbuf.counter = 0;
+  pbuf.maxalloc = *lenpacked_stream;
+  pbuf.len = 0;
+  pbuf.p = packed_stream;
+  pbuf.allocatable = 0;
+
+  if (packingmethod == 0) {
+    *bytes_in  = cmalen * sizeof(double);
+    *bytes_out = *bytes_in; 
+
+    if (pbuf.maxalloc * sizeof(unsigned int) >= *bytes_out) {
+      pbuf.len = (*bytes_out)/sizeof(unsigned int);
+
+      pcma_copy_uint((unsigned int *)packed_stream, 
+		     (const unsigned int *)cma, pbuf.len);
+
+      /* The old coding with memcpy() did not necessarely vectorize:
+	 memcpy(packed_stream, cma, *bytes_out); */
+    }
+    else {
+      /* Error: packed_stream is this many words too short */
+      rc = (pbuf.maxalloc * sizeof(unsigned int) - *bytes_out) / sizeof(unsigned int);
+    }
+  }
+  else {
+    rc = pcma(NULL,  /* CMA-input channel ; N/A */
+	      NULL,  /* Packed output channel ; N/A */
+	      packingmethod, /* Packing method */
+	      cma, cmalen, /* In-core CMA is available */
+	      &pbuf,  /* Buffer of concatenated packed messages */
+	      bytes_in, bytes_out); /* Bytes in/out count */
+
+    if (*bytes_in != cmalen * sizeof(double)) {
+      fprintf(stderr,
+	      "cma2pcma(): Inconsistent 'bytes_in'; Not equal to 'cmalen x %d' : bytes_in=%d, cmalen=%d\n",
+	      (int)sizeof(double),*bytes_in,cmalen);
+      rc = -1;
+    }
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/pcma_1.c b/odb/src/aux/pcma_1.c
new file mode 100644
index 0000000..52fcd3b
--- /dev/null
+++ b/odb/src/aux/pcma_1.c
@@ -0,0 +1,575 @@
+/* === CMA-packing method#1 (revised) === */
+
+/* Bugfixed on 20/02/2003 by SS :
+   Method: 
+   -- Set avg == 0, when ABS(vmax - vmin) >= INT_MAX
+   Bug spotted/generated by Lueder van Bremen (ECMWF) in his experiment with MODIS (satob) winds */
+
+/* Thanks to Bob Carruthers from Cray for supplying Cray X1 (SV2) 
+   directives & mods for better vectorization (Aug-Sep/2004) */
+
+#include "pcma.h"
+
+#include <signal.h>
+#include <math.h>
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+/*		      0U * (((u) - avg) >= ZERO && (u) != nmdi && (u) != rmdi) + */
+
+#define IS_ONE_OF(u) ( \
+		      1U * (((u) - avg) <  ZERO && (u) != nmdi && (u) != rmdi) + \
+		      2U * ((u) == nmdi) + \
+		      3U * ((u) == rmdi))
+
+#define TWO (N32BITS/b16)
+
+#define DEFMASK(x) unsigned int mask##x = ( IS_ONE_OF(cma[i+(x)]) << (TWO*(x)) )
+
+/* pcma_1_prepare: Prepare for compression */
+
+static int *
+pcma_1_prepare(double nmdi,
+	       double rmdi,
+	       const double cma[], /* double CMA[] */
+	       int  lencma,        /* length of the double CMA[] */
+	       int *Nbits,         /* No. of bits required */
+	       int *Noffset,       /* Length of offset array [with the sign preserved] */
+	       int *Npacked,       /* Minimum length for output packed array */
+	       double *Avg         /* Value of the average */
+	       )
+{
+  double avg = 0;
+  double vmax = -INT_MAX;
+  double vmin =  INT_MAX;
+  int i, j, n;
+  int nbits = 1;
+  unsigned int maxval;
+  int *Offset = NULL;
+  
+  n = 0;
+  /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  */
+  for (i=0; i<lencma; i++) {
+    if (cma[i] != nmdi && cma[i] != rmdi) {
+      n++;
+      avg += cma[i];
+      if (vmax < cma[i]) vmax = cma[i];
+      if (vmin > cma[i]) vmin = cma[i];
+    }
+  }
+
+  if (vmin == vmax) {
+    nbits = 0; /* Special case: all non-MDI's are the same */
+    avg = vmax;
+  }
+  else if (ABS(vmax - vmin) < INT_MAX) {
+    if (n > 1) avg /= n;
+    /* floor'ing towards zero; trunc() works erratically on Linux */
+    if (avg >= 0) 
+      avg = floor(avg);
+    else {
+      avg = -avg;
+      avg = -floor(avg);
+    }
+  }
+  else { /* Play safe */
+    avg = 0;
+  }
+
+  if (nbits > 0) {
+    ALLOC(Offset, n);
+    if (n > 0) {
+      const double dmin = -INT_MAX;
+      const double dmax =  INT_MAX;
+      j = 0;
+      /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+      */
+      for (i=0; i<lencma; i++) {
+	if (cma[i] != nmdi && cma[i] != rmdi) {
+	  /* Offset[j] = (int)(cma[i] - avg); --- the BUG : a potential integer overflow */
+	  double tmp = cma[i] - avg;
+	  if      (tmp < dmin) Offset[j] = -INT_MAX;
+	  else if (tmp > dmax) Offset[j] =  INT_MAX;
+	  else                 Offset[j] = (int)tmp;
+	  j++;
+	}
+      }
+      
+      maxval = 0;
+      /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+      */
+      for (j=0; j<n; j++) {
+	int offset = Offset[j];
+	if (offset < 0) offset = -offset;
+	if (offset > maxval) maxval = offset;
+      }
+      nbits = 1;
+      while (maxval >>= 1) nbits++;
+    } /* if (n > 0) */
+  }
+  else {
+    n = 0;
+  }
+
+  *Nbits = nbits;
+  *Noffset = n;
+  *Npacked = RNDUP(n * nbits,N32BITS)/N32BITS;
+  *Avg = avg;
+
+  return Offset;
+}
+
+/* pcma_1: perform the actual packing of a buffer */
+
+static int 
+pcma_1(double avg,
+       double nmdi,
+       double rmdi,
+       const double  cma[],   /* double CMA[] */
+       int    lencma,   /* length of the double CMA[] */
+       int Offset[],    /* preprocessed offset data */
+       int noffset,     /* no. of elements in offset data */
+       int nbits,       /* no. of bits involved */
+       unsigned int    bitmap[], /* bitmap: 0=positive values, 1=negative, 2=nmdi, 3=rmdi */
+       int lenbitmap,  /* length of bitmap[] */
+       unsigned int    outbuf[], /* Effective packed output; w/o bitmap though */
+       int noutbuf              /* No. of elements in outbuf[] */
+       )
+{
+  int rc = 0;
+  int i, j;
+  int istart, iend;
+
+  istart = 0;
+  iend   = lencma - lencma%b16;
+  /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  */
+  for (i=istart; i<iend; i+=b16) {
+#if defined(SV2)
+    int offset = i >> 4;
+#else
+    int offset = i/b16;
+#endif
+
+    DEFMASK(0) ; DEFMASK(1) ; DEFMASK(2) ; DEFMASK(3) ;
+    DEFMASK(4) ; DEFMASK(5) ; DEFMASK(6) ; DEFMASK(7) ;
+    DEFMASK(8) ; DEFMASK(9) ; DEFMASK(10); DEFMASK(11);
+    DEFMASK(12); DEFMASK(13); DEFMASK(14); DEFMASK(15);
+
+#if defined(SV2)
+    bitmap[offset] =   
+      mask0  |  mask1 |  mask2 |  mask3 | 
+      mask4  |  mask5 |  mask6 |  mask7 |
+      mask8  |  mask9 | mask10 | mask11 |
+      mask12 | mask13 | mask14 | mask15;
+#else
+    bitmap[offset] =   
+      mask0  +  mask1 +  mask2 +  mask3 + 
+      mask4  +  mask5 +  mask6 +  mask7 +
+      mask8  +  mask9 + mask10 + mask11 +
+      mask12 + mask13 + mask14 + mask15;
+#endif
+  }
+
+  if (iend < lencma) {
+    unsigned int sum = 0;
+    int offset = lencma/b16;
+
+    /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+    */
+    for (i=iend; i<lencma; i++) {
+      int shift = TWO*(i-iend);
+      unsigned int mask = IS_ONE_OF(cma[i]);
+      sum += mask * PWR2(shift);
+    }
+
+    bitmap[offset] = sum;
+  }
+
+  /* Pack offsets */
+
+  if (nbits > 0) {
+    /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+    */
+    for (j=0; j<noffset; j++) {
+      if (Offset[j] < 0) Offset[j] = -Offset[j];
+    }
+  }
+
+  if (nbits > 0) {
+    vpack_bits_(&nbits,
+		(const unsigned int *)Offset,
+		&noffset,
+		outbuf,
+		&noutbuf,
+		&rc);
+  }
+  else
+    rc = 0;
+
+  rc = (rc == noutbuf) ? lencma : -1;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of CMA-words packed */
+
+  if (rc != lencma) {
+    perror("pcma_1: (rc != lencma)");
+  }
+
+  return rc; 
+}
+
+
+int
+pcma_1_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+              int  lencma,
+	      double nmdi,
+	      double rmdi,
+	      Packbuf *pbuf)
+{
+  int rc = 0;
+  int replen, chunk;
+  int count, nw, nwrt, nbits;
+  int total_count = 0;
+  int lenextra, lenbitmap, lenactive;
+  unsigned int *packed_data = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  double avg = 0;
+  int noffset = 0;
+  int *Offset = NULL;
+  DRHOOK_START(pcma_1_driver);
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + no_of_unpacked + 2 x double MDIs */
+
+  if (replen > 1) {
+    Offset = pcma_1_prepare(nmdi, rmdi, 
+			    &cma[1], chunk, 
+			    &nbits, &noffset, &lenactive, &avg); /* Active no. of words that are non-MDI */
+    lenbitmap = RNDUP(chunk,b16)/b16;  /* Bitmap (roundep up and truncated) */
+    lenextra = 1 + 1 + 1 * (sizeof(double)/sizeof(int)); /* nbits, noffset, avg */
+  }
+  else {
+    lenextra = lenbitmap = lenactive = 0;
+  }
+  count += (lenextra + lenbitmap + lenactive);
+    
+  packed_data = pcma_alloc(pbuf, count);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = 1 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, 
+					packed_data[3] contains
+					report length; ==> no_of_unpacked can now 
+					be over 16megawords */
+   /* extra + bitmap + packed_data */
+  packed_data[2] = (lenextra + lenbitmap + lenactive) * sizeof(*packed_data);
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *extra  = &packed_data[hdrlen];
+    unsigned int *bitmap = &packed_data[hdrlen + lenextra];
+    unsigned int *data   = (nbits > 0) ? &packed_data[hdrlen + lenextra + lenbitmap] : NULL;
+    extra[0] = nbits;
+    extra[1] = noffset;
+    memcpy(&extra[2],&avg,sizeof(avg));
+
+    nw = pcma_1(avg, nmdi, rmdi,
+		&cma[1], chunk,
+		Offset, noffset, nbits,
+		bitmap, lenbitmap,
+		data, lenactive);
+    FREE(Offset);
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+  /* finish: */
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+
+#define POS_BITSET  0
+#define NEG_BITSET  1
+#define NMDI_BITSET 2
+#define RMDI_BITSET 3
+
+/* upcma_1: perform the actual unpacking of a buffer */
+
+static int 
+upcma_1(int swp,
+	double avg,
+	double nmdi,
+	double rmdi,
+	double  cma[],   /* double CMA[] */
+	int    stacma,   /* Starting loop index (>=0) for the CMA[] */
+	int    endcma,   /* Ending loop index for the CMA[] */
+	int Offset[],    /* preprocessed offset data */
+	int noffset,     /* no. of elements in offset data */
+	int nbits,       /* no. of bits involved */
+	const unsigned int    bitmap[], /* bitmap: 0=positive values, 1=negative, 2=NMDI, 3=RMDI */
+	int lenbitmap,  /* length of bitmap[] */
+	const unsigned int    outbuf[], /* Effective packed output; w/o bitmap though */
+	int noutbuf              /* No. of elements in outbuf[] */
+	)
+{
+  int rc = 0;
+  int i;
+
+  if (swp) { /* swap bytes */
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    swap4bytes_((unsigned int *)outbuf,&noutbuf);
+  }
+
+  if (nbits > 0) {
+    /* Unpack offsets */
+    vunpack_bits_(&nbits,
+		  outbuf,
+		  &noutbuf,
+		  (unsigned int *)Offset,
+		  &noffset,
+		  &rc);
+  }
+  else
+    rc = 0;
+
+  if (rc == noffset) {
+    int j = 0;
+
+    for (i=0; i<stacma; i++) { /* get the right starting point for "j" */
+      int offset = i/b16;
+      int shift  = (TWO*i)%N32BITS;
+      unsigned int bitset = ((bitmap[offset] & (3U * PWR2(shift))) / PWR2(shift));
+      if (bitset == POS_BITSET || bitset == NEG_BITSET) j++;
+    }
+
+    if (nbits > 0) {
+      /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+      */
+      for (i=stacma; i<endcma; i++) {
+#if defined(SV2)
+        int mask_size = TWO;
+        int offset;
+        int shift;
+        unsigned int bitset;
+
+        offset = (i >> 4) & 0x07FFFFFF;
+        shift = mask_size*i;
+        shift = (((shift >> 5) & 0x03FFFFFF) << 5) ^ shift;
+        bitset = ((bitmap[offset] & (3U << shift)) >> shift) & 0x3;
+#else
+        int offset = i/b16;
+	int shift  = (TWO*i)%N32BITS;
+        unsigned int bitset = ((bitmap[offset] & (3U * PWR2(shift))) / PWR2(shift));
+#endif
+
+	if (bitset == POS_BITSET || bitset == NEG_BITSET) {
+	  /* Important: 
+	     In the following stmt, keep "+ avg" for compatibility reasons, 
+	     since avg is 0 only for databases created with the bugfixed version */
+	  cma[i] = (1 - 2 * (int)bitset) * Offset[j] + avg; 
+	  j++;
+	}
+	else if (bitset == NMDI_BITSET) {
+	  cma[i] = nmdi;
+	}
+	else if (bitset == RMDI_BITSET) {
+	  cma[i] = rmdi;
+	}
+      }
+    }
+    else {
+      /*
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+      */
+      for (i=stacma; i<endcma; i++) {
+#if defined(SV2)
+        int mask_size = TWO;
+        int offset;
+        int shift;
+        unsigned int bitset;
+
+        offset = (i >> 4) & 0x07FFFFFF;
+        shift = mask_size*i;
+        shift = (((shift >> 5) & 0x03FFFFFF) << 5) ^ shift;
+        bitset = ((bitmap[offset] & (3U << shift)) >> shift) & 0x3;
+#else
+        int offset = i/b16;
+	int shift  = (TWO*i)%N32BITS;
+        unsigned int bitset = ((bitmap[offset] & (3U * PWR2(shift))) / PWR2(shift));
+#endif
+	
+	if (bitset == POS_BITSET || bitset == NEG_BITSET) {
+	  cma[i] = avg;
+	  j++;
+	}
+	else if (bitset == NMDI_BITSET) {
+	  cma[i] = nmdi;
+	}
+	else if (bitset == RMDI_BITSET) {
+	  cma[i] = rmdi;
+	}
+      }
+    }
+    
+    rc = endcma - stacma;
+  }
+  else
+    rc = -1;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words unpacked */
+
+  if (rc != endcma-stacma) {
+    perror("upcma_1: (rc != endcma-stacma)");
+  }
+
+  if (rc == endcma-stacma && swp && pcma_restore_packed) { /* restore */
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    swap4bytes_((unsigned int *)outbuf,&noutbuf);
+  }
+
+  return rc; 
+}
+
+int
+upcma_1_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_1_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int lenextra  = 1 + 1 + 1 * (sizeof(double)/sizeof(int));
+    int lenbitmap = RNDUP(chunk,b16)/b16;
+    int lenactive = len_packed_data - lenbitmap - lenextra;
+
+    const unsigned int *extra  = &packed_data[0];
+    const unsigned int *bitmap = &packed_data[lenextra];
+    const unsigned int *data;
+
+    int nbits = extra[0];
+    int noffset = extra[1];
+    int *Offset = NULL;
+    double avg;
+    const int one = 1;
+    double *cma_addr = &cma[fill_zeroth_cma];
+
+    memcpy(&avg,&extra[2],sizeof(avg));
+
+    if (swp) {
+      swap4bytes_(&nbits, &one);
+      swap4bytes_(&noffset, &one);
+      swap8bytes_(&avg, &one);
+    }
+
+#ifdef DEBUG
+    fprintf(stdout,
+	    "upcma_1_driver(method=%d,swp=%d): avg=%.20g, nbits=%d, noffset=%d\n",
+	    method, swp, avg, nbits, noffset);
+#endif
+
+    if (nbits > 0) {
+      ALLOC(Offset, noffset);
+      data = &packed_data[lenextra + lenbitmap];
+    }
+    else {
+      Offset = NULL;
+      data = NULL;
+    }
+
+    STAEND_FIX();
+
+    rc = upcma_1(swp,
+		 avg,nmdi,rmdi,
+		 cma_addr, stacma, endcma,
+		 Offset, noffset, nbits,
+		 bitmap, lenbitmap,
+		 data, lenactive);
+
+    SWAP_DATA_BACKv2(swp,can_swap_data,cma,stacma,endcma);
+
+    FREE(Offset);
+    
+    rc = (rc == endcma-stacma) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_11to19.c b/odb/src/aux/pcma_11to19.c
new file mode 100644
index 0000000..8652c35
--- /dev/null
+++ b/odb/src/aux/pcma_11to19.c
@@ -0,0 +1,510 @@
+
+/* === CMA-packing methods#11 to 19 === */
+
+#include "pcma.h"
+
+#include <signal.h>
+#include <math.h>
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#define IS_RMDI(u) ((u) == rmdi)
+
+#define DEFMASK(x) unsigned int mask##x = ( IS_RMDI(cma[i+(x)]) << (x) )
+
+PRIVATE int Nbits[10] = { 0, 4, 7, 10, 14, 17, 20, 24, 27, 30 };
+
+/* pcma_11to19_prepare: Prepare for compression */
+
+PRIVATE unsigned int *
+pcma_11to19_prepare(double rmdi,
+		    const double cma[], /* double CMA[] */
+		    int  lencma,        /* length of the double CMA[] */
+		    int *Nbits,         /* No. of bits requested */
+		    int *Noffset,       /* Length of offset array <all non-negative> */
+		    int *Npacked,       /* Minimum length for output packed array */
+		    double *Vmax        /* Value of the absolute maximum */
+		    )
+{
+  double vmax = -INT_MAX;
+  double vmin =  INT_MAX;
+  int nbits = *Nbits;
+  int i, j, n;
+  unsigned int *Offset = NULL;
+  
+  n = 0;
+  for (i=0; i<lencma; i++) {
+    if (!IS_RMDI(cma[i])) {
+      n++;
+      if (vmax < cma[i]) vmax = cma[i];
+      if (vmin > cma[i]) vmin = cma[i];
+    }
+  }
+
+  if (vmin >= 0) nbits--; /* Still always > 0 */
+  if (vmin == vmax) nbits = 0; /* Special case: all non-RMDI's are the same */
+
+#ifdef DEBUG
+  fprintf(stderr,"vmin=%f, vmax=%f, *Nbits=%d, nbits=%d\n",vmin,vmax,*Nbits,nbits);
+#endif
+
+  vmin = ABS(vmin);
+  vmax = MAX(vmax, vmin);
+
+  if (nbits > 0) {
+    ALLOC(Offset, n);
+    if (n > 0) {
+      unsigned int p2 = PWR2(nbits)-1;
+      double mult = (0.5 * p2)/vmax;
+
+#ifdef DEBUG
+      fprintf(stderr,"mult=%f, p2=%u 0x%8.8x\n",mult,p2,p2);
+#endif
+
+      j = 0;
+      for (i=0; i<lencma; i++) {
+	if (!IS_RMDI(cma[i])) {
+	  double value = (vmax - cma[i]) * mult;
+	  Offset[j] = value;
+#ifdef DEBUG
+	  if (j<20) {
+	    fprintf(stderr,
+		    "value=%f, cma[%d]=%f, Offset[%d]=%u\n",
+		    value, i, cma[i], j, Offset[j]);
+	  }
+#endif
+	  j++;
+	}
+      }
+    } /* if (n > 0) */
+  }
+  else {
+    n = 0;
+  }
+
+  *Noffset = n;
+  *Npacked = RNDUP(n * nbits,N32BITS)/N32BITS;
+  *Nbits = nbits;
+  *Vmax = vmax;
+
+  return Offset;
+}
+
+/* pcma_11to19: perform the actual packing of a buffer */
+
+PRIVATE int 
+pcma_11to19(double vmax,
+	    double rmdi,
+	    const double  cma[],   /* double CMA[] */
+	    int    lencma,   /* length of the double CMA[] */
+	    const unsigned int Offset[],    /* preprocessed offset data */
+	    int noffset,     /* no. of elements in offset data */
+	    int nbits,       /* no. of bits involved */
+	    unsigned int    bitmap[], /* bitmap: 0=positive values, 1=negative, 2=nmdi, 3=rmdi */
+	    int lenbitmap,  /* length of bitmap[] */
+	    unsigned int    outbuf[], /* Effective packed output; w/o bitmap though */
+	    int noutbuf              /* No. of elements in outbuf[] */
+	    )
+{
+  int rc = 0;
+  int i;
+  int istart, iend;
+
+  istart = 0;
+  iend   = lencma - lencma%b32;
+
+  for (i=istart; i<iend; i+=b32) {
+    int offset = i/b32;
+
+    DEFMASK(0) ; DEFMASK(1) ; DEFMASK(2) ; DEFMASK(3) ;
+    DEFMASK(4) ; DEFMASK(5) ; DEFMASK(6) ; DEFMASK(7) ;
+    DEFMASK(8) ; DEFMASK(9) ; DEFMASK(10); DEFMASK(11);
+    DEFMASK(12); DEFMASK(13); DEFMASK(14); DEFMASK(15);
+    DEFMASK(16); DEFMASK(17); DEFMASK(18); DEFMASK(19);
+    DEFMASK(20); DEFMASK(21); DEFMASK(22); DEFMASK(23);
+    DEFMASK(24); DEFMASK(25); DEFMASK(26); DEFMASK(27);
+    DEFMASK(28); DEFMASK(29); DEFMASK(30); DEFMASK(31);
+
+    bitmap[offset] =   
+      mask0  +  mask1 +  mask2 +  mask3 + 
+      mask4  +  mask5 +  mask6 +  mask7 +
+      mask8  +  mask9 + mask10 + mask11 +
+      mask12 + mask13 + mask14 + mask15 +
+      mask16 + mask17 + mask18 + mask19 + 
+      mask20 + mask21 + mask22 + mask23 +
+      mask24 + mask25 + mask26 + mask27 +
+      mask28 + mask29 + mask30 + mask31;
+  }
+
+  if (iend < lencma) {
+    unsigned int sum = 0;
+    int offset = lencma/b32;
+
+    for (i=iend; i<lencma; i++) {
+      int shift = (i-iend);
+      unsigned int mask = IS_RMDI(cma[i]);
+      sum += mask * PWR2(shift);
+    }
+
+    bitmap[offset] = sum;
+  }
+
+  if (nbits > 0) {
+    /* Pack offsets */
+    vpack_bits_(&nbits,
+		Offset,
+		&noffset,
+		outbuf,
+		&noutbuf,
+		&rc);
+  }
+  else
+    rc = 0;
+
+  rc = (rc == noutbuf) ? lencma : -1;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of CMA-words packed */
+
+  if (rc != lencma) {
+    perror("pcma_11to19: (rc != lencma)");
+  }
+
+  return rc; 
+}
+
+
+int
+pcma_11to19_driver(int method,
+		   FILE *fp_out,
+		   const double  cma[],
+		   int  lencma,
+		   double nmdi,
+		   double rmdi,
+		   Packbuf *pbuf)
+{
+  int rc = 0;
+  int replen, chunk;
+  int count, nw, nwrt, nbits;
+  int total_count = 0;
+  int lenextra, lenbitmap, lenactive;
+  unsigned int *packed_data = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  double vmax = 0;
+  int noffset = 0;
+  unsigned int *Offset = NULL;
+  int prec = method - 10;
+  DRHOOK_START(pcma_11to19_driver);
+
+  if (prec < 1) {
+    prec = 1;
+  }
+  else if (prec > 9) {
+    prec = 9;
+  }
+  nbits = Nbits[prec];
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + 
+		       no_of_unpacked + 2 x double MDIs */
+
+  if (replen > 1) { 
+    Offset = pcma_11to19_prepare(rmdi, 
+				 &cma[1], chunk, 
+				 &nbits, &noffset, 
+				 &lenactive, /* Active no. of words that are non-RMDIs */
+				 &vmax); 
+    
+    lenbitmap = RNDUP(chunk,b32)/b32;  /* Bitmap (roundep up and truncated) */
+    lenextra = 1 + 1 + 1 * (sizeof(double)/sizeof(int)); /* nbits, noffset, vmax */
+  }
+  else {
+    lenextra = lenbitmap = lenactive = 0;
+  }
+  count += (lenextra + lenbitmap + lenactive);
+    
+  packed_data = pcma_alloc(pbuf, count);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = (10 + prec) * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, 
+						  packed_data[3] contains report length; 
+						  ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = 
+    (lenextra + lenbitmap + lenactive) 
+      * sizeof(*packed_data); /* extra + bitmap + packed_data */
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *extra  = &packed_data[hdrlen];
+    unsigned int *bitmap = &packed_data[hdrlen + lenextra];
+    unsigned int *data   = (nbits > 0) ? &packed_data[hdrlen + lenextra + lenbitmap] : NULL;
+    extra[0] = nbits;
+    extra[1] = noffset;
+    memcpy(&extra[2],&vmax,sizeof(vmax));
+    nw = pcma_11to19(vmax, rmdi,
+		     &cma[1], chunk,
+		     Offset, noffset, nbits,
+		     bitmap, lenbitmap,
+		     data, lenactive);
+    FREE(Offset);
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+  /* finish: */
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+
+/* upcma_1: perform the actual unpacking of a buffer */
+
+PRIVATE int 
+upcma_11to19(int swp,
+	     double vmax,
+	     double rmdi,
+	     double  cma[],   /* double CMA[] */
+	     int    stacma,   /* starting address of the double CMA[] */
+	     int    endcma,   /* ending address of the double CMA[] */
+	     const int idx[],
+	     int       idxlen,
+	     unsigned int Offset[],    /* preprocessed offset data */
+	     int noffset,     /* no. of elements in offset data */
+	     int nbits,       /* no. of bits involved */
+	     const unsigned int    bitmap[], /* bitmap: 0=normal values, 1=RMDI */
+	     int lenbitmap,  /* length of bitmap[] */
+	     const unsigned int    outbuf[], /* Effective packed output; w/o bitmap though */
+	     int noutbuf              /* No. of elements in outbuf[] */
+	     )
+{
+  int rc = 0;
+  int i;
+
+  if (swp) { /* swap bytes */
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    swap4bytes_((unsigned int *)outbuf,&noutbuf);
+  }
+
+  if (nbits > 0) {
+    /* Unpack offsets */
+    vunpack_bits_(&nbits,
+		  outbuf,
+		  &noutbuf,
+		  Offset,
+		  &noffset,
+		  &rc);
+  }
+  else
+    rc = 0;
+
+  if (rc == noffset) {
+    int j = 0;
+
+    if (nbits > 0) {
+      unsigned int p2 = PWR2(nbits)-1;
+      double mult = (2 * vmax)/p2;
+
+#ifdef DEBUG
+      fprintf(stderr,"vmax=%f, mult=%f, p2=%u 0x%8.8x, nbits=%d\n",vmax,mult,p2,p2,nbits);
+#endif
+
+      for (i=0; i<stacma; i++) { /* get the right starting point for "j" */
+	int offset = i/b32;
+	int shift  = i%N32BITS;
+	unsigned int bitset = (bitmap[offset] & PWR2(shift));
+	if (!bitset) j++;
+      }
+
+      for (i=stacma; i<endcma; i++) {
+	int offset = i/b32;
+	int shift  = i%N32BITS;
+	unsigned int bitset = (bitmap[offset] & PWR2(shift));
+	if (bitset) {
+	  cma[i] = rmdi;
+	}
+	else {
+	  double value = Offset[j];
+	  cma[i] = vmax - value * mult;
+#ifdef DEBUG
+	  if (j<20) {
+	    fprintf(stderr,
+		    "value=%f, value * mult=%f, cma[%d]=%f, Offset[%d]=%u\n",
+		    value, value * mult, i, cma[i], j, Offset[j]);
+	  }
+#endif
+	  j++;
+	}
+      }
+    }
+    else { /* All non-RMDIs must be the same */
+      if (idx && idxlen > 0 && idxlen < endcma-stacma) {
+	int ii;
+	for (i=0; i<idxlen; i++) { /* ultra-fast :-) */
+	  ii = idx[i];
+	  if (ii >= stacma && ii < endcma) {
+	    int offset = ii/b32;
+	    int shift  = ii%N32BITS;
+	    unsigned int bitset = (bitmap[offset] & PWR2(shift));
+	    if (bitset) {
+	      cma[ii] = rmdi;
+	    }
+	    else {
+	      cma[ii] = vmax;
+	    }
+	  } /* if (ii >= stacma && ii < endcma) */
+	} /* for (i=0; i<idxlen; i++) */
+      }
+      else {
+	for (i=stacma; i<endcma; i++) {
+	  int offset = i/b32;
+	  int shift  = i%N32BITS;
+	  unsigned int bitset = (bitmap[offset] & PWR2(shift));
+	  if (bitset) {
+	    cma[i] = rmdi;
+	  }
+	  else {
+	    cma[i] = vmax;
+	  }
+	}
+      }
+    }
+    
+    rc = endcma-stacma;
+  }
+  else
+    rc = -1;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words unpacked */
+
+  if (rc != endcma-stacma) {
+    perror("upcma_11to19: (rc != endcma-stacma)");
+  }
+
+  if (rc == endcma-stacma && swp && pcma_restore_packed) { /* restore */
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    swap4bytes_((unsigned int *)outbuf,&noutbuf);
+  }
+
+  return rc; 
+}
+
+int
+upcma_11to19_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int packed_data[],
+		    int len_packed_data,
+		    int msgbytes,
+		    double nmdi,
+		    double rmdi,
+		    FILE *fp_out, 
+		    const int idx[], int idxlen,
+		    int fill_zeroth_cma,
+		    double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_11to19_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int lenextra  = 1 + 1 + 1 * (sizeof(double)/sizeof(int)); /* i.e. 4 */
+    int lenbitmap =  RNDUP(chunk,b32)/b32;
+    int lenactive = len_packed_data - lenbitmap - lenextra;
+
+    const unsigned int *extra  = &packed_data[0];
+    const unsigned int *bitmap = &packed_data[lenextra];
+    const unsigned int *data;
+
+    int nbits = extra[0];
+    int noffset = extra[1];
+    unsigned int *Offset = NULL;
+    double vmax;
+
+    const int one = 1;
+    const int two = 2;
+
+    memcpy(&vmax,&extra[2],sizeof(vmax));
+
+    if (swp) {
+      swap4bytes_(&nbits, &one);
+      swap4bytes_(&noffset, &one);
+      swap8bytes_(&vmax, &one);
+    }
+
+#ifdef DEBUG
+    fprintf(stderr,
+	    "upcma_11to19_driver(method=%d): vmax=%g, nbits=%d, noffset=%d\n",
+	    method, vmax, nbits, noffset);
+#endif
+
+    if (nbits > 0) {
+      ALLOC(Offset, noffset);
+      data = &packed_data[lenextra + lenbitmap];
+    }
+    else {
+      Offset = NULL;
+      data = NULL;
+    }
+
+    STAEND_FIX();
+
+    {
+      double *cma_addr = &cma[fill_zeroth_cma];
+      rc = upcma_11to19(swp,
+			vmax,rmdi,
+			cma_addr, 
+			stacma, endcma,
+			idx, idxlen,
+			Offset, noffset, nbits,
+			bitmap, lenbitmap,
+			data, lenactive);
+    }
+
+    FREE(Offset);
+    
+    rc = (rc == endcma-stacma) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_2.c b/odb/src/aux/pcma_2.c
new file mode 100644
index 0000000..73e958d
--- /dev/null
+++ b/odb/src/aux/pcma_2.c
@@ -0,0 +1,412 @@
+
+/* === CMA-packing method#2 === */
+
+/* Thanks to Bob Carruthers from Cray for supplying Cray X1 (SV2) 
+   directives & mods for better vectorization (Aug-Sep/2004) */
+
+#include "pcma.h"
+
+#ifdef VPP
+#pragma global noalias
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#ifdef LITTLE
+#define RMDI_1 4294959041U
+#define RMDI_2      49407U
+#else
+#define RMDI_1 3252682751U
+#define RMDI_2 4290772992U
+#endif
+
+#define IS_ONE_OF(u) ( 3U*((u) == ZERO) + 2U*((u) == i_rmdi_1) + ((u) == i_rmdi_2) )
+
+#define DEFMASK(x) unsigned int mask##x = ( IS_ONE_OF(icma[i+(x)]) << ((N32BITS/b16)*(x)) )
+
+/* pcma_2_count: Count no. of words that are not one of {ZERO, RMDI_1, RMDI_2}'s */
+
+static int
+pcma_2_count(unsigned int i_rmdi_1,
+	     unsigned int i_rmdi_2,
+	     const unsigned int  icma[],    /* uint representation of the double CMA[] */
+    	                    int  lenicma    /* 2 x length of the double CMA[] */
+	     )
+{
+  int rc = 0;
+  int i;
+  int zero_count   = 0;
+  int rmdi_1_count = 0;
+  int rmdi_2_count = 0;
+
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  for (i=0; i<lenicma; i++) {
+    /* Check if an uint CMA-word (a half of the double CMA-words) 
+       contains any of the {ZERO, RMDI_1, RMDI_2} */
+
+    if (icma[i] == ZERO) {
+      zero_count++;
+    }
+    else if (icma[i] == i_rmdi_1) {
+      rmdi_1_count++;
+    }
+    else if (icma[i] == i_rmdi_2) {
+      rmdi_2_count++;
+    }
+  }
+
+  rc = lenicma - (zero_count + rmdi_1_count + rmdi_2_count);
+
+  /* finish: */
+  return rc;
+}
+
+/* pcma_2: perform the actual packing of a buffer */
+
+static int 
+pcma_2(unsigned int i_rmdi_1,
+       unsigned int i_rmdi_2,
+       const unsigned int  icma[],    /* uint representation of the double CMA[] */
+                      int  lenicma,   /* 2 x length of the double CMA[] */
+             unsigned int  bitmap[],  /* bitmap: 0=raw uint CMA-data; 1=RMDI_2; 2=RMDI_1; 3=ZERO */
+             unsigned int  outbuf[]   /* Effective packed output; w/o bitmap though */
+       )
+{
+  int rc = 0;
+  int i, k;
+  int istart, iend;
+
+  istart = 0;
+  iend   = lenicma - lenicma%b16;
+
+  /*
+#if defined(SV2)
+#pragma _CRI ivdep
+  for (i=istart; i<iend; i+=b16) {
+    int offset = (i >> 4) & 0x07FFFFFF;
+
+    bitmap[offset]=0u;
+  }
+#pragma _CRI unroll
+  for (k=0; k<16; k++) {
+    int mask_size = (N32BITS >> 4);
+    int mask_shift = (mask_size*k);
+#pragma _CRI concurrent
+    for (i=istart; i<iend; i+=b16) {
+      int offset = (i >> 4) & 0x07FFFFFF;
+
+      bitmap[offset] = bitmap[offset] | (IS_ONE_OF(icma[i+k]) << mask_shift);
+    }
+  }
+
+#else
+  */
+
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  for (i=istart; i<iend; i+=b16) {
+#if defined(SV2)
+    int offset = i >> 4;
+#else
+    int offset = i/b16;
+#endif
+
+    DEFMASK(0) ; DEFMASK(1) ; DEFMASK(2) ; DEFMASK(3) ;
+    DEFMASK(4) ; DEFMASK(5) ; DEFMASK(6) ; DEFMASK(7) ;
+    DEFMASK(8) ; DEFMASK(9) ; DEFMASK(10); DEFMASK(11);
+    DEFMASK(12); DEFMASK(13); DEFMASK(14); DEFMASK(15);
+
+#if defined(SV2)
+    bitmap[offset] =   
+      mask0  |  mask1 |  mask2 |  mask3 | 
+      mask4  |  mask5 |  mask6 |  mask7 |
+      mask8  |  mask9 | mask10 | mask11 |
+      mask12 | mask13 | mask14 | mask15;
+#else
+    bitmap[offset] =   
+      mask0  +  mask1 +  mask2 +  mask3 + 
+      mask4  +  mask5 +  mask6 +  mask7 +
+      mask8  +  mask9 + mask10 + mask11 +
+      mask12 + mask13 + mask14 + mask15;
+#endif
+  }
+  /*
+#endif
+  */
+
+  if (iend < lenicma) {
+    unsigned int sum = 0;
+    int offset = lenicma/b16;
+
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+    for (i=iend; i<lenicma; i++) {
+      int shift = (N32BITS/b16)*(i-iend);
+      unsigned int mask = IS_ONE_OF(icma[i]);
+      /* sum += (mask << shift); */
+      sum += mask * PWR2(shift);
+    }
+
+    bitmap[offset] = sum;
+  }
+
+  k = 0;
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  for (i=0; i<lenicma; i++) {
+    if (! IS_ONE_OF(icma[i]) ) {
+      outbuf[k] = icma[i];
+      k++;
+    }
+  }
+
+  rc = lenicma;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words packed */
+
+  return rc; 
+}
+
+
+int
+pcma_2_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	      double nmdi,
+	      double rmdi,
+	           Packbuf *pbuf)
+{
+  int rc = 0;
+  int count, nw, nwrt, chunk, replen;
+  int total_count = 0;
+  int lenbitmap, lenactive;
+  unsigned int *packed_data = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  unsigned int *i_rmdi = (unsigned int *)&rmdi;
+  DRHOOK_START(pcma_2_driver);
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count  = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + no_of_unpacked + 2 x double MDIs */
+
+  if (replen > 1) {
+    lenbitmap = RNDUP(2*chunk,b16)/b16;  /* Bitmap (roundep up and truncated) */
+    lenactive = pcma_2_count(i_rmdi[0], i_rmdi[1], 
+			     (unsigned int *)&cma[1], 2*chunk); /* Active packed uint(s) */
+  }
+  else {
+    lenbitmap = lenactive = 0;
+  }
+  count += (lenbitmap + lenactive);
+    
+  packed_data = pcma_alloc(pbuf, count);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = 2 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, packed_data[3] contains
+					report length; ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = (lenbitmap + lenactive) * sizeof(*packed_data); /* bitmap + packed_data */
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *bitmap = &packed_data[hdrlen];
+    unsigned int *data   = &packed_data[hdrlen + lenbitmap];
+    nw = pcma_2(i_rmdi[0], i_rmdi[1],
+		(unsigned int *)&cma[1], 2*chunk, 
+		bitmap, data);
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+  /* finish: */
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+#define ZERO_BITSET   3
+#define RMDI_1_BITSET 2
+#define RMDI_2_BITSET 1
+
+/* upcma_2: perform the actual unpacking of a buffer */
+
+static int 
+upcma_2(int swp,
+	unsigned int i_rmdi_1,
+	unsigned int i_rmdi_2,
+	unsigned int  icma[],    /* output : uint representation of the double CMA[] */
+	int  staicma,            /* 2 x stacma of the double CMA[] */
+	int  endicma,            /* 2 x endcma of the double CMA[] */
+        const unsigned int  bitmap[],  /* bitmap: 0=raw uint CMA-data; 1=RMDI_2; 2=RMDI_1; 3=ZERO */
+	int lenbitmap,
+        const unsigned int  inbuf[],   /* Packed input; w/o bitmap though */
+	int leninbuf
+	)
+{
+  int rc = 0;
+  int i, k;
+
+  if (swp) {
+    int len = leninbuf/2;
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    /* swap8bytes_((double *)inbuf,&len); */
+  }
+
+  k = 0;
+  for (i=0; i<staicma; i++) { /* get the right starting point for "k" */
+    int offset = i/b16;
+    int shift  = ((N32BITS/b16)*i)%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & (3U * PWR2(shift))) / PWR2(shift));
+    if (bitset == 0) k++;
+  }
+
+#if defined(SV2)
+#pragma _CRI ivdep
+#endif
+  for (i=staicma; i<endicma; i++) {
+#if defined(SV2)
+    int mask_size = (N32BITS >> 4);
+    int offset;
+    int shift;
+    unsigned int bitset;
+
+    offset = (i >> 4) & 0x07FFFFFF;
+    shift = mask_size*i;
+    shift = (((shift >> 5) & 0x03FFFFFF) << 5) ^ shift;
+    bitset = ((bitmap[offset] & (3U << shift)) >> shift) & 0x3;
+#else
+    int offset = i/b16;
+    int shift  = ((N32BITS/b16)*i)%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & (3U * PWR2(shift))) / PWR2(shift));
+#endif
+
+         if (bitset ==   ZERO_BITSET) icma[i] = ZERO;
+    else if (bitset == RMDI_1_BITSET) icma[i] = i_rmdi_1;
+    else if (bitset == RMDI_2_BITSET) icma[i] = i_rmdi_2;
+    else {
+      icma[i] = inbuf[k];
+      k++;
+    }
+  }
+
+  rc = endicma-staicma;
+
+  if (swp) {
+    int len = (endicma-staicma)/2;
+    swap8bytes_((double *)&icma[staicma], &len);
+  }
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words unpacked */
+
+  if (swp && pcma_restore_packed) {
+    int len = leninbuf/2;
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+    /* swap8bytes_((double *)inbuf,&len); */
+  }
+
+  return rc; 
+}
+
+int
+upcma_2_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_2_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int lenbitmap = RNDUP(2*chunk,b16)/b16;
+    int lenactive = len_packed_data - lenbitmap;
+
+    const unsigned int *bitmap = &packed_data[0];
+    const unsigned int *data   = &packed_data[lenbitmap];
+
+    unsigned int *i_rmdi = (unsigned int *)&rmdi;
+    const int one = 1;
+    double *cma_addr = &cma[fill_zeroth_cma];
+
+#ifdef DEBUG
+    fprintf(stderr,"upcma_2_driver(swp=%d, new_version=%d, can_swp_data=%d) : chunk=%d\n",
+	    swp,new_version,can_swp_data,chunk);
+    fprintf(stderr,">rmdi=%.16g (nmdi=%.16g)\n",rmdi,nmdi);
+    fprintf(stderr,">i_rmdi[0]=%u, RMDI_1=%u\n",i_rmdi[0],RMDI_1);
+    fprintf(stderr,">i_rmdi[1]=%u, RMDI_2=%u\n",i_rmdi[1],RMDI_2);
+#endif
+
+    if (swp) {
+      swap8bytes_(&rmdi, &one); /* note: swapped the i_rmdi[0] & i_rmdi[1], too */
+#ifdef DEBUG
+      fprintf(stderr,"<i_rmdi[0]=%u, RMDI_1=%u\n",i_rmdi[0],RMDI_1);
+      fprintf(stderr,"<i_rmdi[1]=%u, RMDI_2=%u\n",i_rmdi[1],RMDI_2);
+      fprintf(stderr,"<rmdi=%.16g (nmdi=%.16g)\n",rmdi,nmdi);
+#endif
+    }
+
+    STAEND_FIX();
+
+    rc = upcma_2(swp,
+		 i_rmdi[0], i_rmdi[1],
+		 (unsigned int *)cma_addr,
+		 2*stacma, 2*endcma,
+		 bitmap, lenbitmap,
+		 data, lenactive);
+    rc /= 2;
+
+    SWAP_DATA_BACKv2(swp,can_swap_data,cma,stacma,endcma);
+
+    rc = (rc == endcma-stacma) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_21to29.c b/odb/src/aux/pcma_21to29.c
new file mode 100644
index 0000000..14061a1
--- /dev/null
+++ b/odb/src/aux/pcma_21to29.c
@@ -0,0 +1,442 @@
+
+/* === CMA-packing methods#21 to 29 === */
+
+#include "pcma.h"
+
+#include <signal.h>
+#include <math.h>
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#define IS_RMDI(u) ((u) == rmdi)
+
+#define LARGEPOW 305
+#define POW10LEN (2*LARGEPOW+1)
+
+PRIVATE int pow10_created = 0;
+PRIVATE double pow10[POW10LEN];
+
+#define INRANGE(x) ((int)(x) >= -LARGEPOW && (int)(x) <= LARGEPOW)
+
+#ifdef DEBUG
+#define POW10(x) (INRANGE(x) ? pow10[(int)(x) + LARGEPOW] : pow10abort((int)(x)))
+#else
+#ifdef NOT_CACHED_MODE
+#define POW10(x) pow(10,x)
+#else
+/* Cached mode (the default) */
+#define POW10(x) pow10[(int)(x) + LARGEPOW]
+#endif
+#endif
+
+PRIVATE void /* NOT THREAD SAFE */
+pow10_init()
+{
+  if (!pow10_created) {
+    /* Cache pow(10,x)'s */
+    int j;
+    int n = POW10LEN;
+    for (j=0; j<n; j++) {
+      pow10[j] = pow(10,j-LARGEPOW);
+    }
+    pow10_created = 1;
+  }
+}
+
+PRIVATE int
+pow10abort(int p10)
+{
+  fprintf(stderr,
+	  "***Error: power in POW10-macro (obtaining cached 10^%d) out of range [%d,%d]\n",
+	  p10, -LARGEPOW, LARGEPOW);
+  RAISE(SIGABRT);
+  return 0;
+}
+
+PRIVATE int
+pcma_21to29_prepare(double rmdi, 
+		    const double d[], int n,
+		    double power[], double frac[])
+{
+  int j;
+  unsigned int large = 0;
+  int num_mdis = 0;
+
+  for (j=0; j<n; j++) {
+    double x = d[j];
+
+    if (IS_RMDI(x)) {
+      power[j] = rmdi;
+      num_mdis++;
+    }
+    else if (x==0) {
+      power[j] = 0;
+    }
+    else {
+      if (x<0) x = -x;
+      power[j] = (int)log10(x);
+    }
+    if (!IS_RMDI(power[j]) && 
+	(power[j] > LARGEPOW || power[j] < -LARGEPOW)) large++;
+  } /* for (j=0; j<n; j++) */
+
+  if (num_mdis < n) {
+    /* Do only if at least one non-MDI */
+
+    if (large > 0) {
+      /* Slower due to division & explicit pow()-function invocation */
+      for (j=0; j<n; j++) {
+	double x = d[j];
+	if (IS_RMDI(x)) {
+	  frac[j] = rmdi;
+	}
+	else {
+	  frac[j] = x / pow(10,power[j]);
+	}
+      } /* for (j=0; j<n; j++) */
+    }
+    else {
+      /* Faster (the normal case) */
+
+      if (!pow10_created) pow10_init();
+
+      for (j=0; j<n; j++) {
+	double x = d[j];
+	if (IS_RMDI(x)) {
+	  frac[j] = rmdi;
+	}
+	else {
+	  frac[j] = x * POW10(-power[j]);
+	  if (frac[j] != 0 && frac[j] > -1 && frac[j] < 1) {
+	    /* Get an extra digit for fractional part */
+	    frac[j] *= 10;
+	    power[j]--;
+	  }
+	}
+      } /* for (j=0; j<n; j++) */
+    }
+  } /* if (num_mdis < n) */
+
+  return num_mdis;
+}
+
+int
+pcma_21to29_driver(int method,
+		   FILE *fp_out,
+		   const double  cma[],
+		   int  lencma,
+		   double nmdi,
+		   double rmdi,
+		   Packbuf *pbuf)
+{
+  int rc = 0;
+  int replen, chunk;
+  int count, nw, nwrt;
+  int total_count = 0;
+  unsigned int *packed_data = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  int prec = method - 20;
+  int lenextra, lenpower, lenfrac;  
+  Packbuf powerbuf, fracbuf;
+  DRHOOK_START(pcma_21to29_driver);
+
+  if (prec < 1) {
+    prec = 1;
+  }
+  else if (prec > 9) {
+    prec = 9;
+  }
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + 
+		       no_of_unpacked + 2 x double MDIs */
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "pcma_21to29_driver(method=%d, prec=%d): hdrlen=%d, replen=%d\n",
+	  method, prec, hdrlen, replen);
+#endif
+
+  if (replen > 1) { 
+    double *power, *frac;
+    int num_mdis;
+
+    ALLOC(power, replen);
+    ALLOC(frac, replen);
+
+    power[0] = replen;
+    frac[0] = replen;
+
+    num_mdis = pcma_21to29_prepare(rmdi, 
+				   &cma[1], chunk,
+				   &power[1], &frac[1]);
+
+    if (num_mdis < chunk) {
+      int powerbytes, fracbytes;
+
+      powerbuf.counter = 0;
+      powerbuf.maxalloc = 0;
+      powerbuf.len = 0;
+      powerbuf.p = NULL;
+      powerbuf.allocatable = 1;
+      powerbytes = pcma_1_driver(1, NULL, power, replen, nmdi, rmdi, &powerbuf);
+      lenpower = powerbuf.len - hdrlen; /* Header is excluded */
+#ifdef DEBUG
+      fprintf(stderr,
+	      "powerbytes=%d, powerbuf.len=%d, lenpower=%d\n",
+	      powerbytes, powerbuf.len, lenpower);
+#endif
+      FREE(power);
+      if (powerbuf.len < 0) {
+	rc = -1; /* Unable to pack power parts with method#1 */
+	goto finish;
+      }
+
+      fracbuf.counter = 0;
+      fracbuf.maxalloc = 0;
+      fracbuf.len = 0;
+      fracbuf.p = NULL;
+      fracbuf.allocatable = 1;
+      fracbytes = pcma_11to19_driver(10+prec, NULL, frac, replen, nmdi, rmdi, &fracbuf);
+      lenfrac = fracbuf.len - hdrlen; /* Header is excluded */
+#ifdef DEBUG
+      fprintf(stderr,
+	      "fracbytes=%d, fracbuf.len=%d, lenfrac=%d\n",
+	      fracbytes, fracbuf.len, lenfrac);
+#endif
+      FREE(frac);
+      if (fracbuf.len < 0) {
+	rc = -2; /* Unable to pack fractional parts */
+	goto finish;
+      }
+    }
+    else {
+      /* All MDIs ==> don't call those auxiliary drivers */
+      lenpower = 0;
+      lenfrac = 0;
+    }
+
+    lenextra = 1 + 1; /* For lenpower & lenfrac */
+  }
+  else {
+    lenextra = lenpower = lenfrac = 0;
+  }
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "lenextra = %d, lenpower = %d,  lenfrac = %d\n",
+	  lenextra, lenpower, lenfrac);
+#endif
+
+  count += (lenextra + lenpower + lenfrac);
+    
+  packed_data = pcma_alloc(pbuf, count);
+  
+  packed_data[0] = PCMA;
+  packed_data[1] = (20 + prec) * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, 
+						  packed_data[3] contains report length; 
+						  ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = 
+    (lenextra + lenpower + lenfrac)
+      * sizeof(*packed_data); /* packed_data */
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *extra     = &packed_data[hdrlen];
+    unsigned int *powerdata = (lenpower > 0) ? &packed_data[hdrlen + lenextra] : NULL;
+    unsigned int *fracdata  = (lenfrac  > 0) ? &packed_data[hdrlen + lenextra + lenpower] : NULL;
+    extra[0] = lenpower;
+    extra[1] = lenfrac;
+
+    /* Packed power part */
+    if (lenpower > 0) {
+      pcma_copy_uint(powerdata, &powerbuf.p[hdrlen], lenpower);
+      FREE(powerbuf.p);
+    }
+
+    /* Packed fractional part */
+    if (lenfrac  > 0) {
+      pcma_copy_uint(fracdata, &fracbuf.p[hdrlen], lenfrac);
+      FREE(fracbuf.p);
+    }
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+ finish:
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+int
+upcma_21to29_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int packed_data[],
+		    int len_packed_data,
+		    int msgbytes,
+		    double nmdi,
+		    double rmdi,
+		    FILE *fp_out, 
+		    const int idx[], int idxlen,
+		    int fill_zeroth_cma,
+		    double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_21to29_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int can_swp_data_here = 1;
+    int chunk = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int j;
+    int lenextra  = 1 + 1;
+    double *power = NULL;
+    const unsigned int *extra  = &packed_data[0];
+    int lenpower = extra[0];
+    int lenfrac = extra[1];
+    int hdrlen = new_version ? PCMA_HDRLEN : HDRLEN;
+    const int one = 1;
+
+#ifdef DEBUG
+    fprintf(stderr,
+"upcma_21to29_driver(method=%d): lenpower=%d, lenfrac=%d, len_packed_data=%d, hdrlen=%d, msgbytes=%d, v=%d\n",
+	    method, lenpower, lenfrac, len_packed_data, hdrlen, msgbytes, new_version);
+#endif
+
+    if (swp) {
+      swap4bytes_(&lenpower, &one);
+      swap4bytes_(&lenfrac, &one);
+    }
+
+    STAEND_FIX();
+
+    if (lenfrac > 0) {
+      const unsigned int *frac_packed;
+
+      frac_packed = &packed_data[lenextra + lenpower];
+      rc = upcma_11to19_driver(method,
+			       swp, can_swp_data_here,
+			       new_version,
+			       frac_packed,
+			       lenfrac,
+			       (lenfrac - hdrlen) * sizeof(*frac_packed),
+			       nmdi,
+			       rmdi,
+			       NULL, 
+			       idx, idxlen, 
+			       fill_zeroth_cma,
+			       cma, replen);
+
+      if (rc != replen) {
+	rc = -2;
+	goto finish;
+      }
+
+      if (lenpower > 0) {
+	const unsigned int *power_packed;
+
+	ALLOC(power, replen);
+
+	power_packed = &packed_data[lenextra];
+	rc = upcma_1_driver(method,
+			    swp, can_swp_data_here,
+			    new_version,
+			    power_packed,
+			    lenpower,
+			    (lenpower - hdrlen) * sizeof(*power_packed),
+			    nmdi,
+			    rmdi,
+			    NULL, 
+			    idx, idxlen, 
+			    fill_zeroth_cma,
+			    power, replen);
+
+	if (rc != replen) {
+	  rc = -1;
+	  goto finish;
+	}
+
+	if (!pow10_created) pow10_init();
+
+	{
+	  int jj;
+	  for (jj=stacma; jj<endcma; jj++) {
+	    j = fill_zeroth_cma + jj;
+	    if (IS_RMDI(cma[j])) {
+	      cma[j] = rmdi;
+	    }
+	    else if (INRANGE(power[j])) {
+	      cma[j] *= POW10(power[j]); /* Use the cached 10^power's */
+	    }
+	    else {
+	      cma[j] *= pow(10,power[j]); /* Calculate explicitly the 10^power */
+	    }
+	  } /* for (jj=stacma; jj<endcma; jj++) */
+	}
+      } /* if (lenpower > 0) */
+    }
+    else {
+      int jj;
+      if (idx && idxlen > 0 && idxlen < endcma-stacma) {
+	for (jj=0; jj<idxlen; jj++) { /* ultra-fast :-) */
+	  j = idx[jj];
+	  if (j >= stacma && j < endcma) {
+	    cma[fill_zeroth_cma+j] = rmdi;
+	  }
+	} /* for (jj=0; jj<idxlen; jj++) */
+      }
+      else {
+	for (jj=stacma; jj<endcma; jj++) {
+	  j = fill_zeroth_cma + jj;
+	  cma[j] = rmdi;
+	} /* for (jj=stacma; jj<endcma; jj++) */
+      }
+      rc = replen;
+    }
+
+  finish:
+    FREE(power);
+
+    rc = (rc == replen) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_255.c b/odb/src/aux/pcma_255.c
new file mode 100644
index 0000000..900cce4
--- /dev/null
+++ b/odb/src/aux/pcma_255.c
@@ -0,0 +1,48 @@
+
+/* === CMA-packing method#255 === */
+
+/* This method does not exist */
+
+#include "pcma.h"
+
+#include <signal.h>
+
+int
+pcma_255_driver(int method, /* ignored */
+		FILE *fp_out,
+		const double  cma[],
+		int  lencma,
+		double nmdi,
+		double rmdi,
+		Packbuf *pbuf)
+{
+  DRHOOK_START(pcma_255_driver);
+  fprintf(stderr,
+	  "pcma_255_driver: This packing method#%d (%d) has not been implemented\n", 
+	  255, method);
+  RAISE(SIGABRT);
+  DRHOOK_END(0);
+  return 0;
+}
+
+
+int
+upcma_255_driver(int method,
+		 int swp, int can_swp_data,
+		 int new_version,
+		 const unsigned int packed_data[],
+		 int len_packed_data,
+		 int msgbytes,
+		 double nmdi,
+		 double rmdi,
+		 FILE *fp_out, 
+		 double cma[], int lencma)
+{
+  DRHOOK_START(upcma_255_driver);
+  fprintf(stderr,
+	  "upcma_255_driver: This unpacking method#%d (%d) has not been implemented\n", 
+	  255, method);
+  RAISE(SIGABRT);
+  DRHOOK_END(0);
+  return 0;
+}
diff --git a/odb/src/aux/pcma_3.c b/odb/src/aux/pcma_3.c
new file mode 100644
index 0000000..2db0706
--- /dev/null
+++ b/odb/src/aux/pcma_3.c
@@ -0,0 +1,146 @@
+
+/* === CMA-packing method#3 === */
+
+#include "pcma.h"
+
+int
+pcma_3_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+	               int  lencma,
+	      double nmdi,
+	      double rmdi,
+	           Packbuf *pbuf)
+{
+  int rc = 0;
+  int count, nbytes, chunk, replen;
+  int total_count = 0;
+  int lenactive;
+  unsigned int *packed_data = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  DRHOOK_START(pcma_3_driver);
+
+  replen = lencma;
+  chunk = replen - 1; /* Report w/o length information */
+
+  lenactive = chunk;      /* Active packed uint(s); a first guess */
+
+  do {
+    count  = hdrlen;      /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + no_of_unpacked + 2 x double MDIs */
+    count += lenactive;   /* No. of uint words reserved for packed buffer */
+    
+    REALLOC(packed_data, count);
+      
+    packed_data[0] = PCMA;
+    packed_data[1] = 3 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, packed_data[3] contains
+					  report length; ==> no_of_unpacked can now be over 16megawords */
+    packed_data[2] = 0; /* no. of bytes packed; for the moment equal to zero */
+    packed_data[3] = replen;
+    memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+    memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+    if (replen > 1) {
+      int Chunk = chunk * sizeof(double);
+      int Lenactive = lenactive * sizeof(*packed_data);
+
+      pcma_zero_uint(&packed_data[hdrlen], lenactive);
+
+      lzw_pack_((const unsigned char *)&cma[1], &Chunk,
+		(unsigned char *)&packed_data[hdrlen], &Lenactive,
+		&nbytes);
+    }
+    else {
+      nbytes = 0;
+    }
+
+    /* If didn't fit, then adjust length "lenactive" */
+    if (nbytes < 0) {
+      int nb = -nbytes;
+      lenactive = RNDUP(nb,b4)/b4;
+    }
+
+  } while (nbytes < 0);
+
+  count          = hdrlen + RNDUP(nbytes,b4)/b4;    /* Actual count of uint words */
+  packed_data[2] = nbytes; /* True no. of bytes packed */
+
+  if (fp_out) (void) fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  if (pbuf) {
+    unsigned int *tmp = pcma_alloc(pbuf, count);
+    pcma_copy_uint(tmp, packed_data, count);
+  }
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+  /* finish: */
+  FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+int
+upcma_3_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int replen;
+  DRHOOK_START(upcma_3_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk = replen - 1;
+    int endcma = chunk;
+    double *cma_addr = &cma[fill_zeroth_cma];
+
+    chunk = endcma * sizeof(double);
+    lzw_unpack_((const unsigned char *)packed_data, &msgbytes,
+		(unsigned char *)cma_addr, &chunk,
+		&rc);
+
+    if (rc != chunk) {
+      /* Error : Not all data was unpacked */
+      goto finish;
+    }
+
+    rc /= sizeof(double);
+    rc = (rc == endcma) ? replen : rc;
+
+    if (swp && can_swp_data) {
+      int len = endcma;
+      swap8bytes_(cma_addr, &len);
+    }
+  }
+
+  if (fp_out) (void) fwrite(cma, sizeof(double), lencma, fp_out);
+
+ finish:
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_31to39.c b/odb/src/aux/pcma_31to39.c
new file mode 100644
index 0000000..be47acd
--- /dev/null
+++ b/odb/src/aux/pcma_31to39.c
@@ -0,0 +1,468 @@
+
+/* === CMA-packing methods#31 to 39 === */
+
+#include "pcma.h"
+#include "bits.h"
+
+#include <signal.h>
+#include <math.h>
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#define MAXINT   2147483647
+#define MININT  (-MAXINT-1)
+#define TRUNC(x) ((int)(x))
+
+#define IS_INT32(x) ((x) <= MAXINT && (x) >= MININT && (x) == TRUNC((x)))
+
+PRIVATE int
+pcma_31to39_prepare(const double d[], int n, int flag[],
+		    double auxint[], double auxdbl[])
+{
+  int j, kr = 0, ki = 0;
+  for (j=0; j<n; j++) {
+    double x = d[j];
+    if (IS_INT32(x)) {
+      auxint[ki++] = TRUNC(x);
+      flag[j] = 1;
+    }
+    else {
+      auxdbl[kr++] = x;
+      flag[j] = 0;
+    }
+  } /* for (j=0; j<n; j++) */
+  return ki;
+}
+
+int
+pcma_31to39_driver(int method,
+		   FILE *fp_out,
+		   const double  cma[],
+		   int  lencma,
+		   double nmdi,
+		   double rmdi,
+		   Packbuf *pbuf)
+{
+  int rc = 0;
+  int replen, chunk;
+  int count, nw, nwrt;
+  int total_count = 0;
+  unsigned int *packed_data = NULL;
+  unsigned int *bitmap = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  int prec = method - 30;
+  int lenextra, lenbitmap, lenint, lendbl;
+  int intbytes, dblbytes;
+  int num_ints = 0;
+  int num_dbls = 0;
+  Packbuf intbuf, dblbuf;
+  DRHOOK_START(pcma_31to39_driver);
+
+  if (prec < 1) {
+    prec = 1;
+  }
+  else if (prec > 9) {
+    prec = 9;
+  }
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + 
+		       no_of_unpacked + 2 x double MDIs */
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "pcma_31to39_driver(method=%d, prec=%d): hdrlen=%d, replen=%d\n",
+	  method, prec, hdrlen, replen);
+#endif
+
+  if (replen > 1) { 
+    double *auxint, *auxdbl;
+    int *flag;
+
+    ALLOC(flag, chunk);
+    ALLOC(auxint, replen);
+    ALLOC(auxdbl, replen);
+
+#ifdef DEBUG
+    {
+	int j;
+	fprintf(stderr,"Numbers to pack (replen = %d, chunk= %d)\n",replen,chunk);
+	for (j=0; j<replen; j++) {
+	    fprintf(stderr," %.12g", cma[j]);
+	    if ((j+1)%10 == 0 || j == replen-1) fprintf(stderr,"\n");
+	}
+    }
+#endif
+
+    num_ints = pcma_31to39_prepare(&cma[1], chunk, flag,
+				   &auxint[1], &auxdbl[1]);
+    num_dbls = chunk - num_ints;
+
+#ifdef DEBUG
+    fprintf(stderr,"# of ints = %d, doubles = %d\n", num_ints, num_dbls);
+#endif
+    
+    auxint[0] = 1 + num_ints;
+    auxdbl[0] = 1 + num_dbls;
+
+    if (num_ints > 0) {
+      intbuf.counter = 0;
+      intbuf.maxalloc = 0;
+      intbuf.len = 0;
+      intbuf.p = NULL;
+      intbuf.allocatable = 1;
+      intbytes = pcma_1_driver(1, NULL, auxint, 1 + num_ints, nmdi, rmdi, &intbuf);
+      lenint = intbuf.len - hdrlen; /* Header is excluded */
+      FREE(auxint);
+      if (intbuf.len < 0) {
+	rc = -1; /* Unable to pack integer part with method#1 */
+	goto finish;
+      }
+    }
+    else {
+      intbytes = 0;
+      lenint = 0;
+      FREE(auxint);
+    }
+
+    if (num_dbls > 0) {
+      dblbuf.counter = 0;
+      dblbuf.maxalloc = 0;
+      dblbuf.len = 0;
+      dblbuf.p = NULL;
+      dblbuf.allocatable = 1;
+      dblbytes = pcma_21to29_driver(20+prec, NULL, auxdbl, 1 + num_dbls, nmdi, rmdi, &dblbuf);
+      lendbl = dblbuf.len - hdrlen; /* Header is excluded */
+      FREE(auxdbl);
+      if (dblbuf.len < 0) {
+	rc = -2; /* Unable to pack double part with method#21..29 */
+	goto finish;
+      }
+    }
+    else {
+      dblbytes = 0;
+      lendbl = 0;
+      FREE(auxdbl);
+    }
+
+    if (num_ints > 0 && num_dbls > 0) { 
+      /* Note: An optimization : The bitmap is stored only if there exists BOTH ints & doubles !! */
+      int j;
+      lenbitmap = RNDUP(chunk,N32BITS)/N32BITS;
+      CALLOC(bitmap, lenbitmap);
+      for (j=0; j<chunk; j++) { /* More "modern" way */
+	if (flag[j]) ODBIT_set(bitmap, chunk, N32BITS, j, j); 
+      }
+
+#ifdef DEBUG
+      fprintf(stderr,"flags=");
+      for (j=0; j<chunk; j++) {
+	  fprintf(stderr," %d",flag[j]);
+      }
+      fprintf(stderr,"\n");
+#endif
+
+    }
+    else {
+      lenbitmap = 0;
+      bitmap = NULL;
+    }
+    FREE(flag);
+    
+    lenextra = 1 + 1 + 1; /* For lenint, lendbl, num_ints */
+  }
+  else {
+    lenextra = lenbitmap = lenint = lendbl = 0;
+    bitmap = NULL;
+  }
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "lenextra = %d, lenbitmap = %d, lenint = %d, lendbl = %d, num_ints = %d, num_dbls = %d\n",
+	  lenextra, lenbitmap, lenint, lendbl, num_ints, num_dbls);
+#endif
+
+  count += (lenextra + lenbitmap + lenint + lendbl);
+    
+  packed_data = pcma_alloc(pbuf, count);
+  
+  packed_data[0] = PCMA;
+  packed_data[1] = (30 + prec) * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, 
+						  packed_data[3] contains report length; 
+						  ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = 
+    (lenextra + lenbitmap + lenint + lendbl)
+      * sizeof(*packed_data); /* packed_data length in bytes */
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *extra    = &packed_data[hdrlen];
+    unsigned int *bitdata  = (lenbitmap > 0) ? &packed_data[hdrlen + lenextra] : NULL;
+    unsigned int *intdata  = (lenint    > 0) ? &packed_data[hdrlen + lenextra + lenbitmap] : NULL;
+    unsigned int *dbldata  = (lendbl    > 0) ? &packed_data[hdrlen + lenextra + lenbitmap + lenint] : NULL;
+
+    /* Note: No need to store lenbitmap, since it can be figured out "chunk" upon unpacking */
+    /*       We also do not need to stored num_dbls, since it is "chunk - num_ints" by definition */
+
+    extra[0] = lenint;
+    extra[1] = lendbl;
+    extra[2] = num_ints;
+
+    /* Bitmap */
+    if (lenbitmap > 0) {
+      pcma_copy_uint(bitdata, bitmap, lenbitmap);
+      FREE(bitmap);
+    }
+
+    /* Packed integer part */
+    if (lenint > 0) {
+      pcma_copy_uint(intdata, &intbuf.p[hdrlen], lenint);
+      FREE(intbuf.p);
+    }
+
+    /* Packed double part */
+    if (lendbl  > 0) {
+      pcma_copy_uint(dbldata, &dblbuf.p[hdrlen], lendbl);
+      FREE(dblbuf.p);
+    }
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+ finish:
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+/* ======================================================================================== */
+
+int
+upcma_31to39_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int packed_data[],
+		    int len_packed_data,
+		    int msgbytes,
+		    double nmdi,
+		    double rmdi,
+		    FILE *fp_out, 
+		    const int idx[], int idxlen,
+		    int fill_zeroth_cma,
+		    double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_31to39_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int can_swp_data_here = 1;
+    int chunk = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int j;
+    int lenextra  = 1 + 1 + 1;
+    const unsigned int *extra = &packed_data[0];
+    int lenbitmap = 0;
+    int lenint = extra[0];
+    int lendbl = extra[1];
+    int num_ints = extra[2];
+    int num_dbls = 0;
+    int hdrlen = new_version ? PCMA_HDRLEN : HDRLEN;
+    double *auxint = NULL;
+    double *auxdbl = NULL;
+    int auxint_allocated = 0;
+    int auxdbl_allocated = 0;
+    int *flag = NULL;
+
+    if (swp) {
+      const int one = 1;
+      swap4bytes_(&lenint, &one);
+      swap4bytes_(&lendbl, &one);
+      swap4bytes_(&num_ints, &one);
+    }
+    num_dbls = chunk - num_ints;
+
+    if (num_ints > 0 && num_dbls > 0) {
+      lenbitmap = RNDUP(chunk,N32BITS)/N32BITS;
+    }
+    else { /* Otherwise no bitmap stored !! */
+      lenbitmap = 0;
+    }
+
+#ifdef DEBUG
+    fprintf(stderr,
+	    "upcma_31to39_driver(method=%d): lenbitmap=%d lenint=%d, lendbl=%d, "
+	    "len_packed_data=%d, hdrlen=%d, msgbytes=%d, v=%d, num_ints=%d, num_dbls=%d\n",
+	    method, lenbitmap, lenint, lendbl, 
+	    len_packed_data, hdrlen, msgbytes, new_version,
+	    num_ints, num_dbls);
+#endif
+
+    /* STAEND_FIX(); not applicable */
+
+    if (lenbitmap > 0) { /* bitmap part */
+      const unsigned int *bitmap = &packed_data[lenextra];
+      if (swp) { /* Enforce to swap bytes */
+	swap4bytes_((unsigned int *)bitmap, &lenbitmap);
+      }
+      CALLOC(flag, chunk);
+      for (j=0; j<chunk; j++) {
+	flag[j] = ODBIT_get(bitmap, chunk, N32BITS, j);
+      }
+      if (swp) { /* Restore : Swap bytes back */
+	swap4bytes_((unsigned int *)bitmap, &lenbitmap);
+      }
+    }
+    else if (!fill_zeroth_cma) { /* A rare possibility ... */
+      if (num_ints > 0 && num_dbls == 0) {
+	ALLOC(flag, chunk);
+	for (j=0; j<chunk; j++) flag[j] = 1;
+      }
+      else if (num_dbls > 0 && num_ints == 0) {
+	CALLOC(flag, chunk); /* All flag[]'s now zero */
+      }
+    }
+
+    if (lenint > 0) { /* Integer part */
+      const unsigned int *int_packed;
+      int rc1;
+
+      if (flag) {
+	ALLOC(auxint, 1 + num_ints);
+	auxint_allocated = 1;
+      }
+      else { /* ALL ints --> a direct copy to cma[] */
+	auxint = cma;
+	auxint_allocated = 0;
+      }
+
+      int_packed = &packed_data[lenextra + lenbitmap];
+      rc1 = upcma_1_driver(method,
+			   swp, can_swp_data_here,
+			   new_version,
+			   int_packed,
+			   lenint,
+			   (lenint - hdrlen) * sizeof(*int_packed),
+			   nmdi,
+			   rmdi,
+			   NULL, 
+			   NULL, 0,
+			   1,
+			   auxint, 1 + num_ints);
+      
+      if (rc1 != 1 + num_ints) {
+#ifdef DEBUG
+	fprintf(stderr,"(rc1 != 1 + num_ints) : rc1=%d, 1 + num_ints = %d\n",rc1,1 + num_ints);
+#endif
+	rc = -1;
+	goto finish;
+      }
+      rc += rc1 - 1;
+    }
+
+    if (lendbl > 0) { /* Double part (with truncated precision, that is) */
+      const unsigned int *dbl_packed;
+      int rc2;
+
+      if (flag) {
+	ALLOC(auxdbl, 1 + num_dbls);
+	auxdbl_allocated = 1;
+      }
+      else { /* ALL dbls --> a direct copy to cma[] */
+	auxdbl = cma;
+	auxdbl_allocated = 0;
+      }
+
+      dbl_packed = &packed_data[lenextra + lenbitmap + lenint];
+      rc2 = upcma_21to29_driver(method,
+				swp, can_swp_data_here,
+				new_version,
+				dbl_packed,
+				lendbl,
+				(lendbl - hdrlen) * sizeof(*dbl_packed),
+				nmdi,
+				rmdi,
+				NULL, 
+				NULL, 0,
+				1,
+				auxdbl, 1 + num_dbls);
+
+      if (rc2 != 1 + num_dbls) {
+#ifdef DEBUG
+	fprintf(stderr,"(rc2 != 1 + num_dbls) : rc2=%d, 1 + num_dbls = %d\n",rc2,1 + num_dbls);
+#endif
+	rc = -2;
+	goto finish;
+      }
+      rc += rc2 - 1;
+    }
+
+    /* Finally ... */
+
+    if (flag) {
+      int ki = 1;
+      int kr = 1;
+      int k = 1;
+      if (!fill_zeroth_cma) --k;
+      if (auxint && auxdbl) {
+	for (j=0; j<chunk; j++) {
+	  if (flag[j]) { /* IS_INT32 */
+	    cma[k] = auxint[ki++];
+	  }
+	  else {
+	    cma[k] = auxdbl[kr++];
+	  }
+	  k++;
+	}
+      }
+      else if (auxint && !auxdbl) {
+	for (j=0; j<chunk; j++) cma[k++] = auxint[ki++];
+      }
+      else if (!auxint && auxdbl) {
+	for (j=0; j<chunk; j++) cma[k++] = auxdbl[kr++];
+      }
+    }
+
+  finish:
+    FREE(flag);
+    if (auxint_allocated) FREE(auxint);
+    if (auxdbl_allocated) FREE(auxdbl);
+
+    rc = (rc == replen) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_4.c b/odb/src/aux/pcma_4.c
new file mode 100644
index 0000000..c4c4a36
--- /dev/null
+++ b/odb/src/aux/pcma_4.c
@@ -0,0 +1,722 @@
+#ifdef RS6K
+/* Until we solve packing method#4 problems with -O2, disable optimization on IBMs */
+#pragma options noopt
+#endif
+
+/*=== Packing method#4 ===*/
+
+#include "pcma.h"
+
+#define REPBITS_DEFAULT      7
+#define REPLIM(nb)        (1<<(nb))
+
+#define MASK64(x,nbits)  \
+  ( ((nbits) < 64) ? ((x) & ((1ull << (nbits)) - 1)) : ((x) & 0xffffffffffffffffull) )
+
+#define SIGNBIT64(x)  ( ((x)>>63) & 0x1 )
+#define SIGN2LSB64(x) ( ((x)<<1) | SIGNBIT64(x) )
+#define LSB642SIGN(x) ( ((x)>>1) | (((x) & 0x1)<<63) )
+
+#define SIGNBIT32(x)  ( ((x)>>31) & 0x1 )
+#define SIGN2LSB32(x) ( ((x)<<1) | SIGNBIT32(x) )
+
+#define MAXINT   2147483647
+#define MININT  (-MAXINT-1)
+
+#define TRUNC(x) ((int)(x))
+
+#define PACK64(u,nb)   pack64bits(u,nb,packbuf,packbuf_maxlen,&packbuf_offset,&bitpos,__LINE__)
+#define UNPACK64(u,nb) unpack64bits(&u,nb,packbuf,packbuf_maxlen,&packbuf_offset,&bitpos,1,swp)
+#define UNPACK32(u,nb) unpack32bits(&u,nb,packbuf,packbuf_maxlen,&packbuf_offset,&bitpos,swp)
+
+typedef union {
+    double d;
+    u_ll_t llu;
+} alias_t;
+
+#define GENBITS(nb,utype) \
+static char * \
+genbits##nb(utype z, int maxlsbbits) \
+{ \
+  static char s[nb+1]; \
+  int j; \
+  s[nb] = 0; \
+  for (j=nb-1; j>=0; j--) { \
+    s[j] = (z & 0x1) ? '1' : '0'; \
+    z >>= 1; \
+  } \
+  if (maxlsbbits < nb) { \
+    int offset = nb-maxlsbbits; \
+    for (j=0; j<offset; j++) s[j] = ' '; \
+    for (j=0; j<maxlsbbits; j++) s[j] = s[j+offset]; \
+    s[maxlsbbits] = 0; \
+  } \
+  return s; \
+}
+
+GENBITS(64,u_ll_t)
+
+static int
+pack64bits(u_ll_t u, int nb,
+	   u_ll_t packbuf[], int packbuf_maxlen,
+	   int *packbuf_offset, int *bitpos,
+	   int line)
+{
+#if 0
+  char *s;
+#endif
+  int bpos = *bitpos;
+  u_ll_t *cur = &packbuf[*packbuf_offset]; /* Add array bound checks later on */
+  int spill = 0;
+  if (*packbuf_offset == 0 && bpos == 0) {
+    *cur = 0; /* Add array bound checks later on */
+  }
+  if (bpos == 64) {
+    *++cur = 0; /* Add array bound checks later on */
+    bpos = 0;
+  }
+#if 0
+  s = genbits64(u,nb);
+  fprintf(stderr,"%4d) pk64<%d>: %20llu : %*s%s : nb=%d, bpos=%d, spill=%d\n",
+	  __LINE__,line,u,64-nb,"",s,nb,bpos,spill);
+#endif
+  if (nb < 64) u = MASK64(u,nb); /* Just a precaution */
+  spill = bpos + nb - 64;
+#if 0
+  s = genbits64(u,nb);
+  fprintf(stderr,"%4d) pk64(): %20llu : %*s%s : nb=%d, bpos=%d, spill=%d\n",
+	  __LINE__,u,64-nb,"",s,nb,bpos,spill);
+#endif
+  if (spill > 0) { 
+    /* u has to be split between cur[0] & cur[1] */
+    u_ll_t umsb = (u >> spill);
+    u_ll_t ulsb = MASK64(u,spill);
+
+#if 0
+    s = genbits64(umsb,nb-spill);
+    fprintf(stderr,"%4d)  umsb: %20llu : %*s%s : nb-spill=%d\n",
+	    __LINE__,umsb,64-(nb-spill),"",s,nb-spill);
+#endif
+
+    *cur |= umsb; /* cur[0] */
+
+#if 0
+    s = genbits64(*cur,64);
+    fprintf(stderr,"%4d) cur[0]: %20llu : %s :\n",
+	    __LINE__,*cur,s);
+    s = genbits64(ulsb,spill);
+    fprintf(stderr,"%4d)  ulsb: %20llu : %s%*s :\n",
+	    __LINE__,umsb,s,64-spill,"");
+#endif
+
+    *++cur = (ulsb << (64-spill)); /* cur[1]; Add array bound checks later on */
+    bpos = spill;
+
+#if 0
+    s = genbits64(*cur,64);
+    { int j; for (j=bpos; j<64; j++) s[j] = '-'; }
+    fprintf(stderr,"%4d) cur[1]: %20llu : %s : bpos=%d\n",
+	    __LINE__,*cur,s,bpos);
+#endif
+  }
+  else {
+    /* u fully fits into current cur[0] */
+    *cur |= (u << (-spill));
+    bpos += nb;
+
+#if 0
+    s = genbits64(*cur,64);
+    { int j; for (j=bpos; j<64; j++) s[j] = '-'; }
+    fprintf(stderr,"%4d)  *cur: %20llu : %s : nb=%d, bpos=%d\n",
+	    __LINE__,*cur,s,nb,bpos);
+#endif
+  }
+  *packbuf_offset = cur - packbuf;
+  *bitpos = bpos;
+  return nb;
+}
+
+static int
+zc64(u_ll_t u, int limit)
+{
+  int lzc = 0;
+  u_ll_t mask = 0x8000000000000000ull; /* 1000 0000 0000 0000 0000 0000 0000 0000 
+					  0000 0000 0000 0000 0000 0000 0000 0000 */
+  if (SIGNBIT64(u)) u = ~u; /* Reverse bits */
+  lzc = 0;
+  while (lzc < limit && u < mask) {
+    lzc++;
+    mask >>= 1;
+  }
+  if (lzc < 7 || lzc > 21) lzc = 1;
+  return lzc;
+}
+
+static int
+zc32(unsigned int u, int limit)
+{
+  int lzc = 0;
+  unsigned int mask = 0x80000000U; /* 1000 0000 0000 0000 0000 0000 0000 0000 */
+  if (SIGNBIT32(u)) u = ~u; /* Reverse bits */
+  lzc = 0;
+  while (lzc < limit && u < mask) {
+    lzc++;
+    mask >>= 1;
+  }
+  return lzc;
+}
+
+static int 
+opt_repbits(const u_ll_t u[], int n)
+{
+  int repbits = 1;
+  if (n > 0) {
+    int j;
+    int repmax = 0;
+    int repcnt = 0;
+    u_ll_t lastu = 0;
+    int replim = n;
+    for (j=0; j<n; j++) {
+      if (u[j] == lastu) {
+	if (++repcnt == replim) { /* limit reached */
+	  if (repcnt > repmax) repmax = repcnt;
+	  repcnt = 0;
+	}
+      }
+      else {
+	if (repcnt > 0) {
+	  if (repcnt > repmax) repmax = repcnt;
+	  repcnt = 0;
+	}
+      }
+      lastu = u[j];
+    }
+    if (repcnt > 0) {
+      if (repcnt > repmax) repmax = repcnt;
+      repcnt = 0;
+    }
+    if (repmax > 1) {
+      while (REPLIM(repbits) < repmax) repbits++;
+    }
+  }
+  return repbits;
+}
+
+static u_ll_t *
+pcma_4(const double x[], int xmax, int *packbuf_len)
+{
+  int m = xmax;
+  int packbuf_maxlen = 1 + 2 * m;
+  int packbuf_offset = 0;
+  u_ll_t *packbuf = NULL;
+  int bitpos = 0;
+  alias_t pk;
+  u_ll_t u;
+  int thesame, winner, lzc, nbw, numbits;
+  u_ll_t ulast, lastu, pkword;
+  int repcnt = 0;
+  int repbits = REPBITS_DEFAULT;
+  int replim = REPLIM(repbits);
+  int repmax = 0;
+  int j;
+  u_ll_t outbits = 0;
+
+  ALLOC(packbuf, packbuf_maxlen);
+  if (packbuf_len) *packbuf_len = 0;
+
+  pk.d = x[0];
+  u = pk.llu;
+  repbits = opt_repbits(&u, MIN(m, replim));
+  replim = REPLIM(repbits);
+
+  { /* Pack input data block length (m) & no. of replication bits */
+    u_ll_t v = m;
+    v <<= 1;
+    if (m < 0) v++; /* Never true though; just for consistency */
+    lzc = zc32(v,32);
+    nbw = 32 - lzc + 1;
+    numbits = 1 + 1 + 5 + nbw + 6;
+    thesame = 0;
+    winner = 1;
+    pkword = (((u_ll_t)winner  << (5+nbw+6)) | 
+	      ((u_ll_t)(lzc-1) << (  nbw+6)) | 
+	      (MASK64(v,nbw)   <<        6 ) | 
+	      (repbits-1));
+#if 0
+    {
+      char *s = genbits64(pkword,numbits);
+      fprintf(stderr,"%4d) pcma_4(xmax=%d, m=%d, winner=%d, lzc=%d, v=%llu, repbits=%d)\n",
+	      __LINE__,xmax, m, winner, lzc, v, repbits);
+      fprintf(stderr,"\tnbw=%d, numbits=%d\n",nbw,numbits);
+      fprintf(stderr,"pkword=%20llu : %s\n",pkword,s);
+    }
+#endif
+    /* No. of bits (=numbits) guaranteed to be <= 64 */
+    outbits += PACK64(pkword,numbits);
+  }
+
+  ulast = 0; /* Last u with sign-bit moved to least significant */
+  lastu = 0; /* True last u */
+  repcnt = 0;
+
+  for (j=0; j<m; j++) {
+    double d = (x[j] == 0) ? 0 : x[j]; /* Since sign-bit may have been set */
+    alias_t xx;
+    u_ll_t uj;
+
+    xx.d = d;
+    uj = SIGN2LSB64(xx.llu);
+
+#if 0
+    fprintf(stderr,"%4d) x[%d] = %.20g ; d = %.20g, %.20g ; uj=%llu ; xx.llu=%llu\n",
+	    __LINE__,j,x[j],d,xx.d,uj,xx.llu);
+#endif
+    
+    if (xx.llu == lastu) {
+      /* Replicated word */
+      if (++repcnt == 1) {
+	thesame = 1;
+	outbits += PACK64(thesame,1);
+	numbits = 1;
+      }
+      else if (repcnt == replim) { /* i.e. 2^repbits-bits reached */
+	outbits += PACK64(repcnt-1,repbits);
+	if (repcnt > repmax) repmax = repcnt;
+	numbits = repbits;
+	repcnt = 0;
+      }
+      else {
+	numbits = 0;
+      }
+    }
+    else {
+      if (repcnt > 0) { /* Flush replication counter */
+	outbits += PACK64(repcnt-1,repbits);
+	if (repcnt > repmax) repmax = repcnt;
+	repcnt = 0;
+      }
+
+      if (d <= MAXINT && d >= MININT && d == TRUNC(d)) {
+	/* Word is a 32-bit integer */
+	u_ll_t v = ABS(d);
+	v <<= 1;
+	if (d < 0) v++;
+	lzc = zc32(v,32);
+	nbw = 32 - lzc + 1;
+	numbits = 1 + 1 + 5 + nbw;
+	thesame = 0;
+	winner = 1;
+	pkword = (((u_ll_t)winner << (5+nbw)) | (((u_ll_t)lzc-1) << nbw) | MASK64(v,nbw));
+	/* No. of bits (= numbits) guaranteed to be <= 64 */
+#if 0
+	fprintf(stderr,"%4d) --> winner=%d: numbits=%d, nbw=%d, lzc_eff=%d\n", 
+		__LINE__,winner, numbits, nbw, lzc-1);
+#endif
+	outbits += PACK64(pkword,numbits);
+      }
+      else {
+	int lzc_eff;
+	u_ll_t diff = uj ^ ulast;
+	lzc = zc64(diff,32);
+	nbw = 64 - lzc + 1;
+	numbits = 1 + 1 + 4 + nbw;
+	lzc_eff = (lzc == 1) ? 0 : lzc-6;
+	thesame = 0;
+	winner = 0;
+#if 0
+	fprintf(stderr,"%4d) --> winner=%d: numbits=%d, nbw=%d, lzc_eff=%d, uj=%llu, ulast=%llu\n", 
+		__LINE__, winner, numbits, nbw, lzc_eff, uj, ulast);
+#endif
+	/* May need two packs, since no. of bits (= numbits) may go beyond 64 */
+	if (numbits > 64) {
+	  outbits += PACK64(lzc_eff,6); /* thesame=0 + winner=0 + 4-bits of lzc_eff == 6 bits */
+
+
+	  outbits += PACK64(diff,nbw);
+	}
+	else {
+	  pkword = ( ((u_ll_t)lzc_eff << nbw) | MASK64(diff,nbw));
+	  outbits += PACK64(pkword,numbits);
+	}
+      }
+    }
+      
+    ulast = uj;
+    lastu = xx.llu;
+  } /* for (j=0; j<m; j++) */
+    
+  if (repcnt > 0) {  /* Flush replication counter */
+    outbits += PACK64(repcnt-1,repbits);
+    if (repcnt > repmax) repmax = repcnt;
+    repcnt = 0;
+  }
+
+  {
+    u_ll_t *cur = &packbuf[packbuf_offset]; /* Add array bound checks later on */
+    if (bitpos > 0) {
+      cur++;
+      packbuf_offset = cur - packbuf;
+    }
+  }
+
+  if (packbuf_len) *packbuf_len = packbuf_offset;
+  return packbuf;
+}
+
+static int
+unpack64bits(u_ll_t *u, int nb,
+	     const u_ll_t packbuf[], int packbuf_maxlen,
+	     int *packbuf_offset, int *bitpos,
+	     int fillprefix, int swp)
+{
+  int bpos = *bitpos;
+  const u_ll_t *cur = &packbuf[*packbuf_offset]; /* Add array bound checks later on */
+  int spill;
+  u_ll_t cur0;
+  if (bpos == 64) {
+    ++cur; /* Add array bound checks later on */
+    bpos = 0;
+  }
+  *u = 0;
+  cur0 = swp ? bswap64bits(cur[0]) : cur[0];
+  if (fillprefix && nb > 0 && nb < 64) {
+    u_ll_t sign = (((cur0) << bpos) >> 63) & 0x1;
+    if (sign) *u = (0xffffffffffffffffull << (nb-1));
+  }
+  spill = bpos + nb - 64;
+  if (spill > 0) { 
+    /* bit pattern has been split between cur[0] & cur[1] */
+    /* Add array bound checks later on */
+    u_ll_t umsb = MASK64(cur0,nb-spill);
+    u_ll_t cur1 = swp ? bswap64bits(cur[1]) : cur[1];
+    u_ll_t ulsb = (cur1 >> (64-spill));
+    *u |= ((umsb << spill) | ulsb);
+#if 0
+    {
+      char *s = genbits64(cur0,64);
+     { int j; for (j=0; j<bpos; j++) s[j] = '-'; }
+     fprintf(stderr,"%4d)  cur0: %20llu : %s : nb=%d, bpos=%d, spill=%d\n",
+	     __LINE__,cur0,s,nb,bpos,spill);
+    }
+    {
+      char *s = genbits64(cur1,64);
+      { int j; for (j=spill; j<64; j++) s[j] = '-'; }
+      fprintf(stderr,"%4d)  cur1: %20llu : %s : nb=%d, bpos=%d, spill=%d\n",
+	      __LINE__,cur1,s,nb,bpos,spill);
+    }
+#endif
+    bpos = spill;
+    ++cur; /* Add array bound checks later on */
+  }
+  else {
+    /* the current cur[0] fully accomocates u */
+    u_ll_t utmp = (cur0 >> (-spill));
+    *u |= MASK64(utmp,nb);
+#if 0
+    {
+      char *s = genbits64(*cur,64);
+      { int j; for (j=0; j<bpos; j++) s[j] = '-'; }
+      { int j; for (j=bpos+nb; j<64; j++) s[j] = '-'; }
+      fprintf(stderr,"%4d)  *cur: %20llu : %s : nb=%d, bpos=%d, spill=%d\n",
+	      __LINE__,*cur,s,nb,bpos,spill);
+    }
+#endif
+    bpos += nb;
+  }
+  *packbuf_offset = cur - packbuf;
+  *bitpos = bpos;
+#if 0
+  {
+    char *s = genbits64(*u,64);
+    { int j; for (j=0; j<64-nb; j++) s[j] = '-'; }
+    fprintf(stderr,"%4d)  *u  > %20llu : %s : nb=%d  (bpos now = %d)\n",
+	    __LINE__,*u,s,nb,bpos);
+  }
+#endif
+  return nb;
+}
+
+static int
+unpack32bits(int *i, int nb,
+	     const u_ll_t packbuf[], int packbuf_maxlen,
+	     int *packbuf_offset, int *bitpos,
+	     int swp)
+{
+  u_ll_t u;
+  int numbits;
+  numbits = unpack64bits(&u, nb,
+			 packbuf, packbuf_maxlen,
+			 packbuf_offset, bitpos, 0, swp);
+  *i = u;
+  return numbits;
+}
+
+static int
+upcma_4(double x[], int xmax,
+	const u_ll_t packbuf[], int packbuf_maxlen,
+	int swp)
+{
+  int j;
+  int m = xmax;
+  int packbuf_offset = 0;
+  int bitpos = 0;
+  u_ll_t ulast = 0;
+  double lastdbl = 0;
+  u_ll_t *u = (u_ll_t *)x;
+  int repcnt = 0;
+  int repbits = REPBITS_DEFAULT;
+  u_ll_t inbits = 0;
+
+#if 0
+  fprintf(stderr,"%4d) upcma_4(xmax=m=%d, packbuf_maxlen=%d, swp=%d)\n",
+	  __LINE__,xmax,packbuf_maxlen,swp);
+#endif
+
+  for (j = -1; j<m; j++) {
+    int winner, lzc, nbw, thesame;
+    if (repcnt > 0) {
+      thesame = 1;
+    }
+    else {
+      inbits += UNPACK32(thesame,1);
+#if 0
+      fprintf(stderr,"%4d) j=%d ; thesame = %d\n",__LINE__,j,thesame);
+#endif
+    }
+    if (thesame == 0) {
+      u_ll_t z;
+      inbits += UNPACK32(winner,1);
+#if 0
+      fprintf(stderr,"%4d) --> winner = %d\n",__LINE__,winner);
+#endif
+      if (winner == 0) {
+	inbits += UNPACK32(lzc,4);
+#if 0
+	fprintf(stderr,"\t%4d) --> lzc = %d\n",__LINE__,lzc);
+#endif
+	lzc = (lzc == 0) ? lzc+1 : lzc+6;
+	nbw = 64 - lzc + 1;
+	inbits += UNPACK64(z,nbw);
+#if 0
+	{
+	  char *s = genbits64(z,nbw);
+	  fprintf(stderr,"\t%4d) --> lzc = %d , nbw = %d : %20llu : %s\n",
+		  __LINE__,lzc, nbw, z, s);
+	}
+#endif
+	z ^= ulast;
+	ulast = z;
+      }
+      else {
+	inbits += UNPACK32(lzc,5);
+#if 0
+	fprintf(stderr,"\t%4d) --> lzc = %d\n",__LINE__,lzc);
+#endif
+	lzc++;
+	nbw = 32 - lzc + 1;
+	inbits += UNPACK64(z,nbw);
+#if 0
+	{
+	  char *s = genbits64(z,nbw);
+	  fprintf(stderr,"\t%4d) --> lzc = %d, nbw = %d : %20llu : %s\n",
+		  __LINE__, lzc, nbw, z, s);
+	}
+#endif
+	z = MASK64(z,32);
+	ulast = z;
+      }
+      if (j == -1) { /* Determine "m" */
+	m = (ulast >> 1);
+	if (ulast & 0x1) m = -m;
+#if 0
+	fprintf(stderr,"%4d) ==> ulast = %llu, m=%d, xmax=%d\n",
+		__LINE__,ulast,m,xmax);
+#endif
+	m = MIN(m,xmax);
+	ulast = 0; /* Important !! */
+	/* no. of replication bits in this dataset */
+	inbits += UNPACK32(repbits,6);
+	repbits++;
+#if 0
+	fprintf(stderr,"%4d) ==> repbits = %d\n", __LINE__, repbits);
+#endif
+      }
+      else  {
+	if (winner == 0) { /* Value was a xor-red "difference" */
+	  u[j] = LSB642SIGN(ulast); /* Implicitly alters x[j], too */
+	}
+	else { /* Value is a 32-bit integer */
+	  if (ulast == 1) 
+	    x[j] = MININT; /* A special case */
+	  else {
+	    x[j] = (ulast >> 1);
+	    if (ulast & 0x1) x[j] = -x[j];
+	  }
+	  ulast = SIGN2LSB64(u[j]);
+	}
+	lastdbl = x[j];
+      }
+    }
+    else {
+      if (repcnt > 0) {
+	repcnt--;
+      }
+      else {
+	UNPACK32(repcnt, repbits);
+      }
+      x[j] = lastdbl;
+    }
+
+#if 0
+    if (j >= 0) {
+      fprintf(stderr,"%4d) x[%d] = %.20g, lastdbl = %.20g : Remaining repcnt now %d\n",
+	      __LINE__, j,x[j],lastdbl,repcnt);
+    }
+#endif
+  }
+  
+#if 0
+  if (repcnt > 0) fprintf(stderr,"REPCNT error !!!\n"); /* Should abort ??? (what if xmax < m ?) */
+#endif
+  
+  return m;
+}
+
+
+int
+pcma_4_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	      double nmdi,
+	      double rmdi,
+	           Packbuf *pbuf)
+{
+  int rc = 0;
+  int count, nw, nwrt, chunk, replen;
+  int total_count;
+  int lenactive;
+  unsigned int *packed_data = NULL;
+  u_ll_t *pkbuf = NULL;
+  int pkbuf_bytes = 0;
+  int hdrlen = PCMA_HDRLEN;
+  DRHOOK_START(pcma_4_driver);
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk  = replen-1; /* Report w/o length information */
+
+  count = hdrlen; /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + 
+		     no_of_unpacked  + 2 x double MDIs */
+
+  if (replen > 1) {
+    const int ratio = sizeof(*pkbuf)/sizeof(*packed_data);
+    int pkbuf_len = 0;
+    pkbuf = pcma_4(&cma[1], chunk, &pkbuf_len);
+    pkbuf_bytes = pkbuf_len * sizeof(*pkbuf);
+    count += pkbuf_len * ratio;
+  }
+
+  packed_data = pcma_alloc(pbuf, count);
+  if (pkbuf && pkbuf_bytes > 0) {
+    memcpy(&packed_data[hdrlen],pkbuf,pkbuf_bytes);
+  }
+  FREE(pkbuf);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = 4 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, packed_data[3] contains
+					report length; ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = pkbuf_bytes;
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count = count;
+
+  rc = total_count * sizeof(*packed_data);
+
+  /* finish: */
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+int
+upcma_4_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_4_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+#if 0
+  {
+    fprintf(stderr,"\fupcma_4_driver(method=%d, swp=%d, can_swp_data=%d, new_version=%d, ...\n",
+	   method, swp, can_swp_data, new_version);
+    fprintf(stderr,"\tlen_packed_data=%d, msgbytes=%d, nmdi=%.20g, rmdi=%.20g, idxlen=%d, ...\n",
+	   len_packed_data, msgbytes, nmdi, rmdi, idxlen);
+    fprintf(stderr,"\tlencma=%d, fill_zeroth_cma=%d)\n",lencma, fill_zeroth_cma);
+  }
+#endif
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    const u_ll_t *pkbuf = (const u_ll_t *)packed_data;
+    int pkbuf_bytes = msgbytes;
+    int pkbuf_len = pkbuf_bytes/sizeof(*pkbuf);
+    double *cma_addr = &cma[fill_zeroth_cma];
+
+#if 0
+    fprintf(stderr,
+	    "\t>chunk=%d, stacma=%d, endcma=%d, len_packed_data=%d, pkbuf_bytes=%d, pkbuf_len=%d\n",
+	    chunk, stacma, endcma, len_packed_data, pkbuf_bytes, pkbuf_len);
+#endif
+
+    END_FIX();
+
+#if 0
+    fprintf(stderr,
+	    "\t<chunk=%d, stacma=%d, endcma=%d, len_packed_data=%d, pkbuf_bytes=%d, pkbuf_len=%d\n",
+	    chunk, stacma, endcma, len_packed_data, pkbuf_bytes, pkbuf_len);
+#endif
+
+    rc = upcma_4(cma_addr, endcma, pkbuf, pkbuf_len, swp);
+
+    SWAP_DATA_BACKv2(swp,can_swap_data,cma,stacma,endcma);
+
+    rc = (rc == endcma-stacma) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_5.c b/odb/src/aux/pcma_5.c
new file mode 100644
index 0000000..6d2b951
--- /dev/null
+++ b/odb/src/aux/pcma_5.c
@@ -0,0 +1,547 @@
+
+/* === CMA-packing method#5 === */
+
+#include "pcma.h"
+
+#include <signal.h>
+#include <math.h>
+
+#ifdef VPP
+#pragma global noalias
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#ifdef VPP
+/* Alters vectorization pattern to prevent flp exception in certain loops */
+PRIVATE int kdummy = 0; 
+
+#endif
+
+#define LOW    1U
+#define HIGH 255U
+
+/* #define IS_DBL_IN_RANGE(d,low,high) (((d) >= (low)) && ((d) <= (high)) && ((d) == (int)(d))) */
+PRIVATE double one = 1;
+#define IS_DBL_IN_RANGE(d,low,high) (((d) >= (low)) && ((d) <= (high)) && (fmod(d,one) == 0))
+
+#define DEFMASK(x) unsigned int mask##x = ((IS_DBL_IN_RANGE(cma[i+(x)],LOW,HIGH)) << (x))
+
+
+/* pcma_5_dbls: Count no. of words that are *not* between [1..255] and creates auxcma[] */
+
+PRIVATE int
+pcma_5_dbls(const double cma[],    /* double CMA[] */
+                     int lencma,   /* length of the double CMA[] */
+	          double auxcma[]
+	     )
+{
+  int rc = 0;
+  int i;
+  int count = 0;
+
+  for (i=0; i<lencma; i++) {
+    if (!IS_DBL_IN_RANGE(cma[i], LOW, HIGH)) {
+      auxcma[count] = cma[i];
+      count++;
+    }
+  }
+
+  rc = count;
+
+  /* finish: */
+  return rc;
+}
+
+PRIVATE int
+pcma_5(const double cma[], 
+                int lencma,
+       unsigned int bitmap[], 
+       unsigned int small_data[], 
+                int len_tmpbuf)
+{
+  int rc = 0;
+  int i, j, k, n;
+  int istart, iend;
+  unsigned int *tmpbuf = NULL;
+
+  istart = 0;
+  iend   = lencma - lencma%b32;
+
+  for (i=istart; i<iend; i+=b32) {
+    int offset = i/b32;
+
+    DEFMASK(0) ; DEFMASK(1) ; DEFMASK(2) ; DEFMASK(3) ;
+    DEFMASK(4) ; DEFMASK(5) ; DEFMASK(6) ; DEFMASK(7) ;
+    DEFMASK(8) ; DEFMASK(9) ; DEFMASK(10); DEFMASK(11);
+    DEFMASK(12); DEFMASK(13); DEFMASK(14); DEFMASK(15);
+    DEFMASK(16); DEFMASK(17); DEFMASK(18); DEFMASK(19);
+    DEFMASK(20); DEFMASK(21); DEFMASK(22); DEFMASK(23);
+    DEFMASK(24); DEFMASK(25); DEFMASK(26); DEFMASK(27);
+    DEFMASK(28); DEFMASK(29); DEFMASK(30); DEFMASK(31);
+
+    bitmap[offset] =   
+      mask0  +  mask1 +  mask2 +  mask3 + 
+      mask4  +  mask5 +  mask6 +  mask7 +
+      mask8  +  mask9 + mask10 + mask11 +
+      mask12 + mask13 + mask14 + mask15 +
+      mask16 + mask17 + mask18 + mask19 +
+      mask20 + mask21 + mask22 + mask23 +
+      mask24 + mask25 + mask26 + mask27 +
+      mask28 + mask29 + mask30 + mask31;
+  }
+
+  if (iend < lencma) {
+    int offset = lencma/b32;
+    unsigned int sum = 0;
+
+    for (i=iend; i<lencma; i++) {
+      int shift = (i - iend);
+      unsigned int mask = (IS_DBL_IN_RANGE(cma[i], LOW, HIGH));
+      /* sum += (mask << shift); */
+      sum += mask * PWR2(shift);
+    }
+
+    bitmap[offset] = sum;
+  }
+
+  /* Copy small data to tmpbuf[] */
+
+  ALLOC(tmpbuf, len_tmpbuf);
+
+#ifdef VPP
+  kdummy = 0;
+#endif
+
+  k = 0;
+  for (i=0; i<lencma; i++) {
+    int offset = i/b32;
+    int shift  = i%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & PWR2(shift)) / PWR2(shift));
+
+    if (bitset) {
+      tmpbuf[k] = cma[i];
+      k++;
+    }
+#ifdef VPP
+    else {
+      /* A real trick: Prevents flp exception by disabling
+	 any attempts to copy too large doubles to the VECTOR REGISTER
+	 as unsigned ints */
+      kdummy++;
+    }
+#endif
+  }
+
+  for (i=k; i<len_tmpbuf; i++)
+    tmpbuf[i] = 0;
+
+  /* Fill in with small data */
+
+  k = 0;
+  n = len_tmpbuf/b4;
+
+  for (j=0; j<n; j++) {
+    small_data[j] = 
+      (((tmpbuf[k]*256U + tmpbuf[k+1])*256U + tmpbuf[k+2])*256U + tmpbuf[k+3]);
+    k += 4;
+  }
+
+  FREE(tmpbuf);
+
+  rc = lencma;
+
+  return rc;
+}
+
+
+int
+pcma_5_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	      double nmdi,
+	      double rmdi,
+	           Packbuf *pbuf)
+{
+  int rc = 0;
+  int count, nw, nwrt, chunk, replen;
+  int total_count = 0;
+  int lenbitmap, lenactive;
+  int numsmall, numsmall_packed;
+  unsigned int *packed_data = NULL;
+  Packbuf  auxpbuf;
+  Packbuf *pauxpbuf = NULL;
+  int hdrlen = PCMA_HDRLEN;
+  int lenextra = 0;
+  int lenm2 = 0;
+  int len_auxcma = 0;
+  DRHOOK_START(pcma_5_driver);
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk = replen-1;  /* Report w/o length information */
+
+  count  = hdrlen;   /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + no_of_unpacked + 2 x double MDIs */
+
+  if (replen > 1) {
+    double *auxcma;
+    int auxbytes;
+    int numdbls;
+
+    ALLOC(auxcma, replen);
+
+    lenbitmap = RNDUP(chunk,b32)/b32; /* Bitmap (roundep up and truncated) */
+    numdbls  = pcma_5_dbls(&cma[1], chunk, &auxcma[1]);  /* Count no. of genuine doubles */
+    numsmall = chunk - numdbls;               /* No. of smallish [1..255] numbers */
+    numsmall_packed = RNDUP(numsmall,b4)/b4;
+
+    len_auxcma = 1 + numdbls; /* True length; and +1 comes from "report" length */
+    auxcma[0] = len_auxcma;   /* "report" length */
+
+    pauxpbuf = &auxpbuf;
+    pauxpbuf->counter = 0;
+    pauxpbuf->maxalloc = 0;
+    pauxpbuf->len = 0;
+    pauxpbuf->p = NULL;
+    pauxpbuf->allocatable = 1;
+
+    auxbytes = pcma_2_driver(2, NULL, auxcma, len_auxcma, nmdi, rmdi, pauxpbuf);
+    FREE(auxcma);
+
+    if (pauxpbuf->len < 0) {
+      /* Error : pcma_2_driver() was unable to deliver a packed buffer */
+      rc = -1;
+      goto finish;
+    }
+
+    /* Active set is:
+       small numbers (rounded up) +
+       output from pcma_2_driver() excluding header (new_version only) */
+       
+    lenm2 = pauxpbuf->len - hdrlen;
+
+    lenactive = numsmall_packed + lenm2;
+
+    lenextra = 1 + 1 + 1; /* no. of smallish numbers +
+			     no. of packed words with method#2 (excluding header) +
+			     length of auxiliary CMA */
+
+    count += (lenextra + lenbitmap + lenactive); /* One word for no. of smallish numbers */
+  }
+  else {
+    lenextra = lenbitmap = lenactive = lenm2 = 0;
+  }
+
+  packed_data = pcma_alloc(pbuf, count);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = 5 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, packed_data[3] contains
+					report length; ==> no_of_unpacked can now be over 16megawords */
+
+  packed_data[2] = (lenextra + lenbitmap + lenactive) * sizeof(*packed_data); /* bitmap + packed_data */
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (replen > 1) {
+    unsigned int *extra      = &packed_data[hdrlen];
+    unsigned int *bitmap     = &packed_data[hdrlen + lenextra];
+    unsigned int *small_data = &packed_data[hdrlen + lenextra + lenbitmap];
+    unsigned int *pcma2_data = (lenm2 > 0) ? &packed_data[hdrlen + lenextra + lenbitmap + numsmall_packed] : NULL;
+
+    extra[0] = numsmall;
+    extra[1] = lenm2;
+    extra[2] = len_auxcma;
+    {
+      /* Handle smallish numbers */
+      int len_tmpbuf = numsmall_packed * b4;
+      nw = pcma_5(&cma[1], chunk, bitmap, small_data, len_tmpbuf);
+    }
+
+    if (lenm2 > 0) {
+      /* Append the already packed stuff with method#2 */
+      pcma_copy_uint(pcma2_data, &pauxpbuf->p[hdrlen], lenm2);
+    }
+
+    FREE(pauxpbuf->p);
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count += count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+ finish:
+  if (!pbuf) FREE(packed_data);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
+/* ======================================================================================== */
+
+/* upcma_5: perform the actual unpacking of a buffer */
+
+PRIVATE int 
+upcma_5(int swp,
+	double  cma[],         /* output : double CMA[] */
+	int  stacma,           /* starting address of the double CMA[] */
+	int  endcma,           /* ending address of the double CMA[] */
+        const unsigned int  bitmap[],      /* bitmap: 0=raw double CMA-data; 1=dbl */
+	int lenbitmap,
+	const double  indbl[],             /* Packed data: double input part; after upcma_2 */
+	const unsigned int  small_data[],  /* Packed data: small data input part */
+	int  len_tmpbuf
+	)
+{
+  int rc = 0;
+  int i, j, kdbl, k, n;
+  unsigned int *tmpbuf = NULL; /* Temporary buffer for expanded small data input */
+ 
+  /* Expand small_data[] into the tmpbuf[] */
+
+  if (len_tmpbuf%b4 != 0) {
+    fprintf(stderr,"upcma_5: len_tmpbuf%%b4 != 0 (len_tmpbuf=%d, b4=%d)\n",
+	    len_tmpbuf, b4);
+    RAISE(SIGABRT);
+    exit(1);
+  }
+
+  ALLOC(tmpbuf, len_tmpbuf);
+
+  k = 0;
+  n = len_tmpbuf/b4;
+
+  if (swp) {
+    swap4bytes_((unsigned int *)small_data, &n);
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+  }
+
+  for (j=0; j<n; j++) {
+    tmpbuf[k  ] =  small_data[j] / 16777216U;
+    tmpbuf[k+1] = (small_data[j] % 16777216U) / 65536U;
+    tmpbuf[k+2] = (small_data[j] % 65536U) / 256U;
+    tmpbuf[k+3] =  small_data[j] % 256U;
+    k += 4;
+  }
+
+  /* Expand from indbl[] and tmpbuf[] to output CMA-array cma[]
+     with bitmap[] as a driver */
+
+  k = 0;
+  kdbl = 0;
+  for (i=0; i<stacma; i++) { /* get the right starting point for "k" and "kdb" */
+    int offset = i/b32;
+    int shift  = i%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & PWR2(shift)) / PWR2(shift));
+    if (bitset) k++;
+    else kdbl++;
+  }
+
+  for (i=stacma; i<endcma; i++) {
+    int offset = i/b32;
+    int shift  = i%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & PWR2(shift)) / PWR2(shift));
+    if (bitset) {
+      cma[i] = tmpbuf[k];
+      k++;
+    }
+  }
+
+  if (k > len_tmpbuf) {
+    fprintf(stderr,"upcma_5: endcma=%d, stacma=%d, k != len_tmpbuf (k=%d, len_tmpbuf=%d)\n",
+	    endcma, stacma, k, len_tmpbuf);
+    RAISE(SIGABRT);
+    exit(1);
+  }
+
+  FREE(tmpbuf);
+
+  for (i=stacma; i<endcma; i++) {
+    int offset = i/b32;
+    int shift  = i%N32BITS;
+    unsigned int bitset = ((bitmap[offset] & PWR2(shift)) / PWR2(shift));
+    if (!bitset) {
+      cma[i] = indbl[kdbl]; /* already in right endian format due to job done by upcma_2() !! */
+      kdbl++;
+    }
+  }
+
+  if (k + kdbl != endcma) {
+    fprintf(stderr,"upcma_5: k + kdbl != endcma (k=%d, kdbl=%d, endcma=%d, stacma=%d)\n",
+	    k, kdbl, endcma, stacma);
+    RAISE(SIGABRT);
+    exit(1);
+  }
+
+  rc = endcma-stacma;
+
+  /* finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words unpacked */
+
+  if (swp && pcma_restore_packed) {
+    swap4bytes_((unsigned int *)small_data, &n);
+    swap4bytes_((unsigned int *)bitmap,&lenbitmap);
+  }
+
+  return rc; 
+}
+
+int
+upcma_5_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  const int one = 1;
+  int numsmall = 0;
+  DRHOOK_START(upcma_5_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+
+  if (replen > 1) {
+    numsmall = packed_data[0];
+    if (swp) swap4bytes_(&numsmall, &one);
+  }
+
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int lenbitmap = RNDUP(chunk,b32)/b32;
+
+    int numsmall_packed = RNDUP(numsmall,b4)/b4;
+    int len_tmpbuf = numsmall_packed * b4;
+
+    int lenextra = new_version ? 3 : 1;
+
+    const unsigned int *extra             = &packed_data[0];
+    const unsigned int *bitmap            = &packed_data[lenextra];
+    const unsigned int *small_data        = &packed_data[lenextra + lenbitmap];
+    const unsigned int *pcma_auxpack_data = &packed_data[lenextra + lenbitmap + numsmall_packed];
+
+    unsigned int aux0 = pcma_auxpack_data[0];
+
+    double *auxcma = NULL;
+    int auxreplen; 
+
+    if (swp) {
+      swap4bytes_((unsigned int *)extra, &lenextra);
+      swap4bytes_(&aux0, &one);
+    }
+
+    auxreplen = new_version ? extra[2] : aux0%MAXSHIFT;
+
+    ALLOC(auxcma, auxreplen);
+
+    if (new_version) {
+      int hdrlen = PCMA_HDRLEN;
+      int lenm2 = extra[1];
+      
+      if (lenm2 > 0) {
+	int can_swp_data_here = 1; /* to avoid undoing of byte swapping twice */
+	rc = upcma_2_driver(2,
+			    swp, can_swp_data_here,
+			    new_version,
+			    pcma_auxpack_data,
+			    lenm2,
+			    (lenm2 - hdrlen) * sizeof(*pcma_auxpack_data),
+			    nmdi,
+			    rmdi,
+			    NULL, 
+			    NULL, 0, 
+			    fill_zeroth_cma,
+			    auxcma, auxreplen);
+	
+	if (rc != auxreplen) {
+	  rc = -1;
+	  goto finish;
+	}
+      }
+    }
+    else {
+      /* Old version only */
+
+      /* Handle the second level of unpacking first */
+
+      unsigned int hdr[HDRLEN];
+
+      hdr[0] = swp ? AMCP : PCMA;
+      hdr[1] = pcma_auxpack_data[0]; /* must be w/o byte swapping */
+      hdr[2] = pcma_auxpack_data[1]; /* must be w/o byte swapping */
+
+      {
+	int can_swp_data_here = 1; /* to avoid undoing of byte swapping twice */
+	upcmaTOcma(&can_swp_data_here,
+		   (const unsigned int *)hdr, 
+		   &pcma_auxpack_data[HDRLEN-1], 
+		   NULL, 0, fill_zeroth_cma,
+		   auxcma, &auxreplen, &rc);
+      }
+	
+      if (rc != auxreplen) {
+	/* Error: Unable to unpack data into the auxcma[] */
+	rc = -2;
+	goto finish;
+      }
+    }
+
+    /* Handle the first level here */
+
+    {
+      int stacma = 0;
+      int endcma = chunk;
+      double *cma_addr = &cma[fill_zeroth_cma];
+
+      STAEND_FIX();
+
+      rc = upcma_5(swp,
+		   cma_addr,
+		   stacma,endcma,
+		   bitmap, lenbitmap,
+		   &auxcma[fill_zeroth_cma],
+		   small_data,
+		   len_tmpbuf);
+
+      SWAP_DATA_BACKv2(swp,can_swap_data,cma,stacma,endcma);
+
+      rc = (rc == endcma-stacma) ? replen : rc;
+    }
+    
+  finish:
+    FREE(auxcma);
+
+    if (swp && pcma_restore_packed) {
+      swap4bytes_((unsigned int *)extra, &lenextra);
+    }
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
+
diff --git a/odb/src/aux/pcma_9.c b/odb/src/aux/pcma_9.c
new file mode 100644
index 0000000..8a4273c
--- /dev/null
+++ b/odb/src/aux/pcma_9.c
@@ -0,0 +1,320 @@
+
+/* === CMA-packing method#9 === */
+
+#include "pcma.h"
+
+#ifdef VPP
+#pragma global noalias
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+/* ODB_packing() moved here from ../lib/errtrap.c on 09/03/2005 by SS */
+
+int
+ODB_packing(const int *packing_method)
+{
+  static boolean first_time = 1;
+  static int packing = -1;
+  static int done[1+MAXPACKINGMETHOD];
+  static int mapped2[1+MAXPACKINGMETHOD];
+  int rc;
+
+  if (first_time) {
+    int j;
+    char *p = getenv("ODB_PACKING");
+    int value = p ? atoi(p) : packing;
+    packing = (value == 0) ? 0 : packing;
+    for (j=0; j<=MAXPACKINGMETHOD; j++) {
+      done[j] = 0;
+      /* 
+	 By default the method given in *packing_method will map to the same number/pmethod ;
+
+	 Can be altered via environment setting "ODB_PACKING_MAP_<method>=<alternate_method>",
+	 where the <method> is the default method >0 mapped to use <alternate_method>, >=0;
+
+	 Note that the no-packing situation (method=0) can *NOT* be altered afterwards,
+	 since it will lead into unstable database management
+       */
+      mapped2[j] = j; 
+    }
+    first_time = 0;
+  }
+
+  rc = packing;
+
+  if (packing_method) {
+    int pmethod = *packing_method;
+    pmethod = MAX(0,pmethod);
+    pmethod = MIN(pmethod,MAXPACKINGMETHOD);
+    rc = pmethod;
+    if (pmethod > 0 && pmethod <= MAXPACKINGMETHOD) {
+      if (!done[pmethod]) {
+	char env[64];
+	char *p;
+	int alternate_method = pmethod;
+	sprintf(env,"ODB_PACKING_MAP_%d",pmethod);
+	p = getenv(env);
+	if (p) alternate_method = atoi(p);
+	alternate_method = MAX(0,alternate_method);
+	alternate_method = MIN(alternate_method,MAXPACKINGMETHOD);
+	rc = mapped2[pmethod] = alternate_method;
+	done[pmethod] = 1;
+#if 0
+	/* No access to Myproc at the moment ; hmm ... thinking ... okay, may take years to solve ;-) */
+	if (Myproc == 1) {
+#endif
+	  if (p) {
+	    fprintf(stderr,
+		    "***Warning: Packing method#%d maps to method#%d, since environment variable %s=%s\n",
+		    pmethod, alternate_method, env, p);
+	  }
+#if 0
+	} /* if (Myproc == 1) */
+#endif
+      }
+      else {
+	rc = mapped2[pmethod];
+      } /* if (!done[pmethod]) else ... */
+    } /* if (pmethod > 0 && pmethod <= MAXPACKINGMETHOD) */
+  } /* if (packing_method) */
+
+  return rc;
+}
+
+static int
+pcma_9_similar(const double  cma[],    /* double CMA[] */
+	                int  lencma    /* length of the double CMA[] */
+	       )
+{
+  int rc = 0;
+  int i;
+  double refval = cma[0];
+  int count = 1;
+
+#if defined(VPP) || defined(NECSX)
+  for (i=1; i<lencma; i++) { /* Vectorizable */
+    if (cma[i] == refval) count++;
+  }
+#else
+  for (i=1; i<lencma; i++) { /* Scalar machines : not vectorizable */
+    if (cma[i] != refval) break; /* Get out immediately when false */
+    count++;
+  }
+#endif
+
+  rc = (count == lencma);
+
+  return rc;
+}
+	       
+
+int
+pcma_9_driver(int method, /* ignored */
+	      FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	      double nmdi,
+	      double rmdi,
+	           Packbuf *pbuf)
+{
+  int rc = 0;
+  int count, nw, nwrt, chunk, replen;
+  int total_count;
+  double refval;
+  int lenactive = 2;
+  int dbl_align = 0;
+  unsigned int *packed_data = NULL;
+  int similar = 0;
+  int hdrlen = PCMA_HDRLEN;
+  DRHOOK_START(pcma_9_driver);
+
+  nwrt = 0;
+
+  replen = lencma;
+  chunk  = replen-1; /* Report w/o length information */
+
+  if (replen >= 1) {
+    similar = (replen == 1) ? 1 : pcma_9_similar(&cma[1], chunk);
+  }
+
+  if (!similar) {
+    /*** This is where we use the filler/pseudo-method 94 ***/
+
+    /* Switch for more effective packing */
+
+    /* 
+       For better performance, change on vector machines ("VPP") to
+
+         export ODB_PACKING_MAP_94=2
+
+       This is also compatible with previous releases.
+       Databases can be 30% larger than with method#3 or #4,
+       but at least packing fully vectorizes with method#2.
+
+       In order to be compatible on scalar machines, use the following:
+
+         export ODB_PACKING_MAP_94=3
+
+    */
+
+    const int method = 94;
+    int mapped_method = ODB_packing(&method);
+
+    /* If no change method, then ... */
+#if defined(VPP) || defined(NECSX)
+    if (mapped_method == method) mapped_method = 2; /* Vectorizable */
+#else
+    if (mapped_method == method) mapped_method = 3; /* Scalar */
+#endif
+
+    /* Allow only these 3 methods : 2, 3 or 4 (= future default ?) */
+    if (mapped_method == 4) { /* Packs often a mixture of integers & real numbers well ; New */
+      rc = pcma_4_driver(4, fp_out, cma, lencma, nmdi, rmdi, pbuf);
+    }
+    else if (mapped_method == 2) { /* The oldest packing method in ODB ? */
+      rc = pcma_2_driver(2, fp_out, cma, lencma, nmdi, rmdi, pbuf);
+    }
+    else { /* a Lemper-Ziv-Welch -variation */
+      rc = pcma_3_driver(3, fp_out, cma, lencma, nmdi, rmdi, pbuf);
+    }
+    goto finish;
+  }
+
+  /* Otherwise replication is okay! */
+
+  refval = (replen == 1) ? 0 : cma[1];
+
+  count = hdrlen; /* 'PCMA' + method & 3 zero bytes + no_of_packed_bytes + no_of_unpacked  + 2 x double MDIs */
+  count += (dbl_align + lenactive);
+
+  packed_data = pcma_alloc(pbuf, count);
+
+  packed_data[0] = PCMA;
+  packed_data[1] = 9 * MAXSHIFT + 0; /* zero no_of_unpacked means that 4th word, packed_data[3] contains
+					report length; ==> no_of_unpacked can now be over 16megawords */
+  packed_data[2] = (dbl_align + lenactive) * sizeof(*packed_data);
+  packed_data[3] = replen;
+  memcpy(&packed_data[4],&nmdi,sizeof(nmdi));
+  memcpy(&packed_data[6],&rmdi,sizeof(rmdi));
+
+  if (!dbl_align) {
+    memcpy(&packed_data[hdrlen], &refval, sizeof(refval));
+  }
+  else {
+    packed_data[hdrlen] = ALGN;
+    memcpy(&packed_data[hdrlen+1], &refval, sizeof(refval));
+  }
+
+  if (fp_out) nwrt = fwrite(packed_data, sizeof(*packed_data), count, fp_out);
+
+  total_count = count;
+
+  rc = total_count *  sizeof(*packed_data);
+
+  /*  finish: */
+  if (!pbuf) FREE(packed_data);
+
+ finish:
+  DRHOOK_END(0);
+  return rc;
+}
+
+/* ======================================================================================== */
+
+/* upcma_9: perform the actual unpacking of a buffer */
+
+static int 
+upcma_9(double  cma[],     /* output :  double CMA[] */
+	int     stacma,    /* starting address of CMA[] */
+	int     endcma,    /* ending address of CMA[] */
+	const int idx[],
+	int       idxlen,
+	double  refval
+	)
+{
+  int rc = 0;
+  int i;
+
+  if (idx && idxlen > 0 && idxlen < endcma-stacma) {
+    int ii;
+    for (i=0; i<idxlen; i++) { /* ultra-fast :-) */
+      ii = idx[i];
+      if (ii >= stacma && ii < endcma) {
+	cma[ii] = refval;
+      }
+    }
+  }
+  else {
+    for (i=stacma; i<endcma; i++) {
+      cma[i] = refval;
+    }
+  }
+
+  rc = endcma-stacma;
+
+  /*  finish: */
+
+  /* Upon successful completion returns no. of uint CMA-words unpacked */
+
+  return rc; 
+}
+
+int
+upcma_9_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int packed_data[],
+	       int len_packed_data,
+	       int msgbytes,
+	       double nmdi,
+	       double rmdi,
+	       FILE *fp_out, 
+	       const int idx[], int idxlen,
+	       int fill_zeroth_cma,
+	       double cma[], int lencma)
+{
+  int rc = 0;
+  int nwrt = 0;
+  int replen;
+  DRHOOK_START(upcma_9_driver);
+
+  replen = lencma;
+  if (fp_out) { /* backward compatibility */
+    idxlen = 0;
+    fill_zeroth_cma = 1;
+  }
+  if (fill_zeroth_cma) {
+    cma[0] = replen;
+    fill_zeroth_cma = 1;
+  }
+  rc = 1;
+
+  if (replen > 1) {
+    int chunk  = replen - 1;
+    int stacma = 0;
+    int endcma = chunk;
+    int dbl_align = new_version ? 0 : 1;
+    int lenactive = len_packed_data - dbl_align;
+    const double *data = (const double *)&packed_data[dbl_align];
+    double refval = *data;
+    const int one = 1;
+    double *cma_addr = &cma[fill_zeroth_cma];
+
+    if (swp && can_swp_data) swap8bytes_(&refval, &one);
+    
+    STAEND_FIX();
+
+    rc = upcma_9(cma_addr,
+		 stacma, endcma,
+		 idx, idxlen,
+		 refval);
+
+    rc = (rc == endcma-stacma) ? replen : rc;
+  }
+
+  if (fp_out) nwrt = fwrite(cma, sizeof(double), lencma, fp_out);
+
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/pcma_mdis.c b/odb/src/aux/pcma_mdis.c
new file mode 100644
index 0000000..bf62fca
--- /dev/null
+++ b/odb/src/aux/pcma_mdis.c
@@ -0,0 +1,26 @@
+
+/* 
+   Alter PCMA's missing data indicators (a new version feature):
+   Say: NMDI -> 2147483647 and RMDI -> 1.7e+38 (instead of -2147483647)
+   Fortran callable.
+   Author: Sami Saarinen, ECMWF, 14/12/2000
+ */
+
+#include "pcma.h"
+
+double pcma_nmdi = NMDI;
+double pcma_rmdi = RMDI;
+
+void
+pcma_set_mdis_(const double *nmdi, const double *rmdi)
+{
+  if (nmdi) pcma_nmdi = *nmdi;
+  if (rmdi) pcma_rmdi = *rmdi;
+}
+
+void
+pcma_get_mdis_(double *nmdi, double *rmdi)
+{
+  if (nmdi) *nmdi = pcma_nmdi;
+  if (rmdi) *rmdi = pcma_rmdi;
+}
diff --git a/odb/src/aux/qtar_sub.c b/odb/src/aux/qtar_sub.c
new file mode 100644
index 0000000..8a7f28c
--- /dev/null
+++ b/odb/src/aux/qtar_sub.c
@@ -0,0 +1,848 @@
+
+/* qtar_sub.c */
+
+#include "qtar.h"
+
+#define QTAR_FLAGS "b:cCdDf:H:m:MR:stuvVx"
+
+#define USAGE \
+  "Usage: %s\n" \
+  "       [-b I/O_bufsize; default=%d bytes]\n" \
+  "       [-d(elete_member(s)_from_qtar-archive)]\n" \
+  "       [-D (debug ON)]\n" \
+  "       [-H size (file header size; default=%d bytes)]\n" \
+  "       [-c(reate_new_qtar-archive)]\n" \
+  "       [-C(ompress) [not in use yet]]\n" \
+  "       [-M(atrix_dimensions_will_be_sought)\n" \
+  "       [-R alloc_roundup_for_a_member_file; default=%d bytes]\n" \
+  "       [-s (read/write member-data from/to Unix-stream/pipe)]\n" \
+  "       [-t(able_of_contents_of_qtar-archive)]\n" \
+  "       [-u(pdate_qtar-archive)]\n" \
+  "       [-v(erbose)]\n" \
+  "       [-V(ersion)]\n" \
+  "       [-x (extract_member(s)_from_qtar-archive)]\n" \
+  "       [-m member1] [-m member2] ... [-m memberN]\n" \
+  "       [-f qtarfile]\n" \
+  "       [qtarfile] [member1] [member2] ... [memberN]\n"
+
+#define QTAR         1364476242U
+#define QTAR_STR    "QTAR"
+#define QTARFILE    "QTARFILE"
+
+#define HDRSIZE_DEFAULT 65536
+#define ALLOC_RNDUP     1024
+#define IO_BUFSIZE      1048576
+#define PERMS 0644
+
+PRIVATE int standalone_job = 0;
+
+PRIVATE char *qtarfile = NULL;
+PRIVATE char *option = "";
+PRIVATE int compress = 0;
+PRIVATE int errflg = 0;
+PRIVATE int debug = 0;
+PRIVATE int delete = 0;
+PRIVATE int create = 0;
+PRIVATE int update = 0;
+PRIVATE int verbose = 0;
+PRIVATE int Version = 0;
+PRIVATE int extract = 0;
+PRIVATE int toc = 0;
+PRIVATE int hdrsize = HDRSIZE_DEFAULT;
+PRIVATE int is_stream = 0;
+PRIVATE int io_bufsize = IO_BUFSIZE;
+PRIVATE int alloc_rndup = ALLOC_RNDUP;
+PRIVATE int matrix_dim = 0;
+
+PRIVATE const char hdr_fmt[] = "%s\n%d %d %lld %d\n";
+PRIVATE const int nlcnt_hdr_fmt = 2; /* newline count in header-format */
+
+PRIVATE const char mem_fmt[] = "%s %s %lld %lld %lld %d %d %lld %lld %lld %lld %lld %lld %lld %d %d\n";
+PRIVATE const int nlcnt_mem_fmt = 1; /* newline count in member-format */
+
+PRIVATE const char eofhdr_fmt[] = "\f\n";
+PRIVATE const int nlcnt_eofhdr_fmt = 1; /* newline count in EOF header-format */
+
+#define WORDLEN sizeof(ll_t)
+
+typedef struct member_t {
+  char *file;
+  char *alias; /* future */
+  ll_t offset;
+  ll_t bytes; /* no. of bytes BEFORE packing */
+  ll_t freespace;
+  int update_cnt;
+  int pmethod; /* future : packing [method] if > 0; no packing = 0 */
+  ll_t packed_bytes; /* future : no. of bytes AFTER packing */
+  /* future */
+  ll_t mode;
+  ll_t uid;
+  ll_t gid;
+  ll_t atim;
+  ll_t mtim;
+  ll_t ctim;
+  /* end of future */
+  /* matrix dimensions */
+  int nrows;
+  int ncols;
+  struct member_t *next;
+} Member_t;
+
+typedef struct file_t {
+  char *file;
+  ll_t bytes;
+  int nrows;
+  int ncols;
+  Member_t *m;
+  struct file_t *next;
+} File_t;
+
+PRIVATE int Nf = 0;
+PRIVATE File_t *f = NULL;
+PRIVATE File_t *p_f = NULL;
+
+PRIVATE int Nmem = 0;
+PRIVATE Member_t *memfile = NULL;
+PRIVATE Member_t *p_memfile = NULL;
+
+PRIVATE ll_t next_free_offset = 0;
+PRIVATE int ngaps = 0; /* Future extension to handle gaps i.e. fragmentation in QTARFILE */
+
+#define OPEN_MACRO(fd, file, flags, perms) \
+  { fd = open(file, flags, perms); \
+    if (fd<0) myexit(1,"qtar[%s]: fd=%d=open(file=%s)",option,fd,file); }
+
+#define READ_MACRO(n, fd, c, len)  \
+  { n = read(fd, c, len); \
+    if (n<0) myexit(1,"qtar[%s]: n=%lld=read(fd=%d,c=%p,len=%lld)",option,n,fd,c,len); }
+
+#define WRITE_MACRO(n, fd, c, len)  \
+  { n = write(fd, c, len); \
+    if (n<0) myexit(1,"qtar[%s]: n=%lld=write(fd=%d,c=%p,len=%lld)",option,n,fd,c,len); }
+
+#define CLOSE_MACRO(fd) \
+  { int n = close(fd); \
+    if (n<0) myexit(1,"qtar[%s]: n=%d=close(fd=%d)",option,n,fd); }
+
+#define LSEEK_MACRO(fd, offset, whence) \
+  { int n = lseek(fd, offset, whence); \
+    if (n<0) myexit(1,"qtar[%s]: n=%d=lseek(fd=%d,offset=%lld,whence=%d)",\
+                       option,n,fd,offset,(int)whence); }
+
+PRIVATE void
+errmsg(const char *format, ...)
+{
+  va_list args;
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  fprintf(stderr,"\n");
+  va_end(args);
+  errflg++;
+}
+
+
+PRIVATE void
+myexit(int rc, const char *format, ...)
+{
+  va_list args;
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  fprintf(stderr,": rc=%d\n",rc);
+  va_end(args);
+  if (!standalone_job) RAISE(SIGABRT); /* to get a proper traceback */
+  exit(rc);
+}
+
+
+PRIVATE int
+FileExist(const char *filename)
+{
+  int exist = 0;
+  struct stat buf;
+  if (stat(filename,&buf) == 0) {
+    /* Caveat: We do not check if this file is a directory or some
+       other special file. Perhaps we should */
+    exist = 1;
+  }
+  return exist;
+}
+
+
+PRIVATE int
+FileSize(const char *filename)
+{
+  int bytes = 0;
+  struct stat buf;
+  if (stat(filename,&buf) == 0) bytes = buf.st_size;
+  return bytes;
+}
+
+
+PRIVATE Member_t *
+PresentMember(const char *filename)
+{
+  Member_t *m = NULL;
+  Member_t *mf = memfile;
+  while (mf) { /* Currently only a linear search */
+    if (strcmp(mf->file,filename) == 0) {
+      /* Found */
+      m = mf;
+      break;
+    }
+    mf = mf->next;
+  }
+  return m;
+}
+
+
+PRIVATE Member_t *
+AddMember(const char *filename, const char *alias, 
+	  ll_t offset, ll_t bytes, ll_t freespace, 
+	  int update_cnt, int nrows, int ncols,
+	  int replace)
+{
+  Member_t *mf = PresentMember(filename);
+  if (!mf) replace = 0;
+  if (!mf || replace) {
+    if (!mf) ALLOC(mf,1);
+    mf->offset = offset;
+    mf->bytes = bytes;
+    mf->freespace = freespace;
+    mf->update_cnt = update_cnt;
+    mf->pmethod = 0;            /* not used yet */
+    mf->packed_bytes = bytes; /* not used yet */
+    mf->alias = alias ? STRDUP(alias) : STRDUP(filename); /* not used yet */
+    mf->mode = -1;  /* not used yet */
+    mf->uid = -1;   /* not used yet */
+    mf->gid = -1;   /* not used yet */
+    mf->atim = -1;  /* not used yet */
+    mf->mtim = -1;  /* not used yet */
+    mf->ctim = -1;  /* not used yet */
+    mf->nrows = nrows;
+    mf->ncols = ncols;
+    if (!replace) {
+      mf->file = STRDUP(filename);
+      mf->next = NULL;
+      if (!memfile) {
+	p_memfile = memfile = mf;
+      }
+      else {
+	p_memfile->next = mf;
+	p_memfile = mf;
+      }
+      Nmem++;
+    }
+  }
+  return mf;
+}
+
+
+PRIVATE File_t *
+AddFile(const char *filename)
+{
+  File_t *xf;
+  ALLOC(xf,1);
+  xf->file = STRDUP(filename);
+  xf->bytes = 0;
+  xf->nrows = 0;
+  xf->ncols = 0;
+  xf->m = NULL;
+  xf->next = NULL;
+  if (!f) {
+    p_f = f = xf;
+  }
+  else {
+    p_f->next = xf;
+    p_f = xf;
+  }
+  Nf++;
+  return xf;
+}
+
+
+PRIVATE void
+SetFileSizes()
+{
+  if (!is_stream) {
+    File_t *xf = f;
+    while (xf) {
+      xf->bytes = FileSize(xf->file);
+      xf = xf->next;
+    }
+  }
+}
+
+
+PRIVATE int
+CountMember(const Member_t *m)
+{
+  int n = 0;
+  while (m) {
+    if (m->offset >= 0) n++;
+    m = m->next;
+  }
+  return n;
+}
+
+
+PRIVATE int 
+WriteChunk(int fd, const char *c, ll_t bytes)
+{
+  ll_t rem = bytes;
+  ll_t rc = 0;
+  for (;;) {
+    ll_t n, len = MIN(io_bufsize, rem);
+    if (len <= 0) break;
+    WRITE_MACRO(n, fd, c, len);
+    if (n > 0) {
+      c += n;
+      rem -= n;
+      rc += n;
+    }
+    else /* Error (the stmt "rc != bytes" below will catch it) */
+      break;
+  } 
+  if (rc != bytes) myexit(1,"Error in WriteChunk(): rc != bytes; rc=%d, bytes=%d",rc,bytes);
+  return bytes;
+}
+
+
+PRIVATE int 
+ReadChunk(int fd, char *c, ll_t bytes)
+{
+  ll_t rem = bytes;
+  ll_t rc = 0;
+  for (;;) {
+    ll_t n, len = MIN(io_bufsize, rem);
+    if (len <= 0) break;
+    READ_MACRO(n, fd, c, len);
+    if (n > 0) {
+      c += n;
+      rem -= n;
+      rc += n;
+    }
+    else /* Error (the stmt "rc != bytes" below will catch it) */
+      break;
+  } 
+  if (rc != bytes) myexit(1,"Error in ReadChunk(): rc != bytes; rc=%d, bytes=%d",rc,bytes);
+  return bytes;
+}
+
+
+PRIVATE void
+Size2Stream(ll_t nbytes, ll_t nrows, ll_t ncols, const char *file)
+{
+  if (is_stream) {
+    int fd_out = fileno(stdout);
+    ll_t dim[3];
+    int nwrite;
+    int nsize;
+    if (matrix_dim) {
+      dim[0] = nbytes; dim[1] = nrows; dim[2] = ncols;
+      nsize = sizeof(dim);
+    }
+    else {
+      dim[0] = nbytes; dim[1] = 0; dim[2] = 0;
+      nsize = sizeof(nbytes);
+    }
+    nwrite = WriteChunk(fd_out, (const char *)dim, nsize);
+    if (nwrite != nsize) {
+      myexit(1, 
+	     "Size2Stream(): Unable to write size information on member-file='%s' to stream", 
+	     file);
+    }
+  }
+}
+
+PRIVATE void
+ExtractMember(int fd, const Member_t *m)
+{
+  if (m) {
+    int fd_out = (is_stream) ? fileno(stdout) : -1;
+    char *c;
+    ll_t rem = m->bytes;
+    ll_t rc = 0;
+    ALLOC(c,io_bufsize);
+    LSEEK_MACRO(fd, hdrsize + m->offset, SEEK_SET);
+    if (!is_stream) {
+      OPEN_MACRO(fd_out, m->file, (O_WRONLY | O_CREAT | O_TRUNC), PERMS);
+    }
+    else { /* Write size info first to stream */
+      Size2Stream(m->bytes, m->nrows, m->ncols, m->file);
+    }
+    for (;;) {
+      ll_t n, len = MIN(io_bufsize, rem);
+      if (len <= 0) break;
+      n = ReadChunk(fd, c, len);
+      if (n > 0) {
+	WriteChunk(fd_out, c, n);
+	rem -= n;
+	rc += n;
+      }
+    }
+    if (!is_stream) CLOSE_MACRO(fd_out);
+    FREE(c);
+  }
+}
+
+
+PRIVATE void
+UpdateMember(int fd, Member_t *m)
+{
+  if (m) {
+    int fd_in = (is_stream) ? fileno(stdin) : -1;
+    char *c;
+    ll_t rem = m->bytes;
+    ll_t rc = 0;
+    ALLOC(c,io_bufsize);
+    m->update_cnt++;
+    LSEEK_MACRO(fd, hdrsize + m->offset, SEEK_SET);
+    if (!is_stream) OPEN_MACRO(fd_in, m->file, O_RDONLY, 0);
+    for (;;) {
+      ll_t n, len = MIN(io_bufsize, rem);
+      if (len <= 0) break;
+      n = ReadChunk(fd_in, c, len);
+      if (n > 0) {
+	WriteChunk(fd, c, n);
+	rem -= n;
+	rc += n;
+      }
+    }
+    FREE(c);
+    LSEEK_MACRO(fd, m->freespace, SEEK_CUR);
+    if (!is_stream) CLOSE_MACRO(fd_in);
+  }
+}
+
+	
+PRIVATE int
+WriteHDR(int fd)
+{
+  int nmem = 0;
+  {
+    Member_t *m = memfile;
+    char *hdr;
+    char *phdr;
+    int inc;
+    ALLOC(hdr,hdrsize);
+    phdr = hdr;
+    nmem = CountMember(m);
+    memset(hdr,'\n',hdrsize);
+    inc = sprintf(phdr, hdr_fmt, QTAR_STR, hdrsize, nmem, next_free_offset, ngaps);
+    while(m) {
+      if (m->offset >= 0) {
+	phdr += inc;
+	inc = sprintf(phdr, mem_fmt,
+		      m->file, m->alias, 
+		      m->offset, m->bytes, m->freespace, m->update_cnt, m->pmethod, m->packed_bytes,
+		      m->mode, m->uid, m->gid, m->atim, m->mtim, m->ctim, m->nrows, m->ncols);
+      }
+      m = m->next;
+    }
+    phdr += inc;
+    inc = sprintf(phdr, eofhdr_fmt);
+    LSEEK_MACRO(fd, 0, SEEK_SET); /* Rewound */
+    WriteChunk(fd, hdr, hdrsize);
+    FREE(hdr);
+  }
+  return nmem;
+}
+
+
+PRIVATE int
+ReadHDR(int fd)
+{
+  char s[8192], alias[8192];
+  int j, nmem, nelem;
+  FILE *fp = fdopen(fd, "r");
+  rewind(fp);
+  nelem = fscanf(fp, hdr_fmt, s, &hdrsize, &nmem, &next_free_offset, &ngaps);
+  if (strcmp(s,QTAR_STR) != 0) myexit(1,"File %s is not a QTAR-file",qtarfile);
+  if (nelem != 5) myexit(2,"Corrupted QTAR-file %s",qtarfile);
+  for (j=0; j<nmem; j++) {
+    ll_t offset, bytes, freespace;
+    int update_cnt, pmethod;
+    ll_t packed_bytes;
+    ll_t mode, uid, gid, atim, mtim, ctim;
+    int nrows, ncols;
+    nelem = fscanf(fp, mem_fmt,
+		   s, alias, 
+		   &offset, &bytes, &freespace, &update_cnt, &pmethod, &packed_bytes,
+		   &mode, &uid, &gid, &atim, &mtim, &ctim, &nrows, &ncols);
+    if (nelem != 16) {
+      myexit(3,"Invalid header in QTAR-file %s: nelem=%d at j=%d (nmem=%d)",qtarfile,nelem,j,nmem);
+    }
+    (void) AddMember(s, alias, offset, bytes, freespace, update_cnt, nrows, ncols, 1);
+    if (offset + bytes + freespace > next_free_offset) {
+      next_free_offset = offset + bytes + freespace;
+      next_free_offset = RNDUP(next_free_offset, WORDLEN);
+    }
+  } /* for (j=0; j<nmem; j++) */
+  return hdrsize;
+}
+
+
+PUBLIC int
+CloseQTAR(int fd)
+{
+  CLOSE_MACRO(fd);
+  return 0;
+}
+
+
+PUBLIC int
+OpenQTAR()
+{
+  int fd;
+  int other = (update || delete) ? O_RDWR : O_RDONLY;
+  int flags = create ? (O_WRONLY | O_CREAT | O_TRUNC) : other;
+  int perms = create ? PERMS : 0;
+
+  OPEN_MACRO(fd, qtarfile, flags, perms);
+
+  if (create) {
+    WriteHDR(fd);
+    CloseQTAR(fd);
+    OPEN_MACRO(fd, qtarfile, other, perms);
+  }
+
+  return fd;
+}
+
+
+PUBLIC int 
+UpdateQTAR(int fd)
+{
+  File_t *xf = f;
+  int nmem = 0;
+  if (xf) {
+    char *key = NULL;
+    Member_t *m;
+    int hdrsize_new = ReadHDR(fd);
+    xf = f;
+    while (xf) {
+      if (is_stream) {
+	/* Obtain size information from stream */
+	int fd_in = fileno(stdin);
+	ll_t dim[3];
+	ll_t nbytes;
+	int nread;
+	if (matrix_dim) {
+	  nread = ReadChunk(fd_in, (char *)dim, sizeof(dim));
+	}
+	else {
+	  nread = ReadChunk(fd_in, (char *)&nbytes, sizeof(nbytes));
+	}
+	if (( matrix_dim && nread == sizeof(dim)) ||
+	    (!matrix_dim && nread == sizeof(nbytes))) {
+	  if (!matrix_dim) {
+	    dim[0] = nbytes; dim[1] = 0; dim[2] = 0;
+	  }
+	  xf->bytes = dim[0];
+	  xf->nrows = dim[1];
+	  xf->ncols = dim[2];
+	}
+	else {
+	  myexit(1, 
+		 "UpdateQTAR: Unable to obtain size information on member-file='%s' from stream", 
+		 xf->file);
+	}
+      } /* if (is_stream) */
+      if (xf->bytes >= 0) {
+	m = PresentMember(xf->file);
+	if (m) {
+	  ll_t total = m->bytes + m->freespace;
+	  if (xf->bytes > total) { 
+	    /* Doesn't fit into the existing slot */
+	    m->bytes = xf->bytes;
+	    m->offset = next_free_offset;
+	    m->freespace = RNDUP(m->bytes, alloc_rndup) - m->bytes;
+	    next_free_offset += m->bytes + m->freespace;
+	    next_free_offset = RNDUP(next_free_offset, WORDLEN);
+	    m->freespace = (next_free_offset - m->offset) - m->bytes;
+	    if (verbose) key = "u+";
+	    if (ngaps <= 0) ngaps--; /* fragmentation count ... for now */
+	  }
+	  else {
+	    /* Fits into the existing slot */
+	    m->freespace = total - xf->bytes;
+	    m->bytes = xf->bytes;
+	    if (verbose) key = "u";
+	  }
+	  m->nrows = xf->nrows;
+	  m->ncols = xf->ncols;
+	}
+	else { /* not present ==> create it */
+	  ll_t freespace = RNDUP(xf->bytes, alloc_rndup) - xf->bytes;
+	  m = AddMember(xf->file, NULL, next_free_offset, xf->bytes, freespace, 
+			xf->nrows, xf->ncols, -1, 0);
+	  next_free_offset += xf->bytes + freespace;
+	  next_free_offset = RNDUP(next_free_offset, WORDLEN);
+	  m->freespace = (next_free_offset - m->offset) - m->bytes;
+	  if (verbose) key = "a";
+	}
+	UpdateMember(fd, m);
+	if (key) fprintf(stderr,"%s %s %lld %lld %lld\n",key,m->file,m->bytes,m->offset,m->freespace);
+	nmem++;
+      }
+      xf = xf->next;
+    }
+    if (nmem > 0) WriteHDR(fd);
+  }
+  return nmem;
+}
+
+
+PUBLIC int 
+ExtractQTAR(int fd)
+{
+  File_t *xf = f;
+  int nmem = 0;
+  int hdrsize_new = ReadHDR(fd);
+  if (xf) {
+    xf = f;
+    while (xf) {
+      Member_t *m = PresentMember(xf->file);
+      if (m) {
+	ExtractMember(fd, m);
+	nmem++;
+      }      
+      else {
+	Size2Stream(0, 0, 0, xf->file);
+      }
+      xf = xf->next;
+    }
+  }
+  else {
+    Member_t *m = memfile;
+    while (m) {
+      if (m) {
+	ExtractMember(fd, m);
+	nmem++;
+      }
+      m = m->next;
+    }
+  }
+  return nmem;
+}
+
+
+PUBLIC int 
+DeleteQTAR(int fd)
+{
+  int ndel = 0;
+  File_t *xf = f;
+  if (xf) {
+    int hdrsize_new = ReadHDR(fd);
+    while (xf) {
+      Member_t *m = PresentMember(xf->file);
+      if (m) {
+	m->freespace += m->bytes;
+	m->bytes = 0;
+	m->nrows = 0;
+	ndel++;
+      }
+      xf = xf->next;
+    }
+    if (ndel > 0) WriteHDR(fd);
+  }
+  return ndel;
+}
+
+
+PUBLIC int 
+TocQTAR(int fd)
+{
+  File_t *xf = f;
+  Member_t *m;
+  int nmem;
+  hdrsize = ReadHDR(fd);
+  nmem = (xf) ? 0 : Nmem;
+  if (xf) {
+    while (xf) {
+      m = PresentMember(xf->file);
+      if (m) nmem++;
+      xf = xf->next;
+    }
+    if (!is_stream) fprintf(stdout,"%d %d %lld %d\n",hdrsize,nmem,next_free_offset,ngaps);
+    else            fprintf(stdout,"%d\n",nmem);
+    xf = f;
+    while (xf) {
+      m = PresentMember(xf->file);
+      if (m) {
+	if (!is_stream) fprintf(stdout,"%s %lld %lld %lld %d %d\n",m->file,m->offset,m->bytes,m->freespace,m->nrows,m->ncols);
+	else            fprintf(stdout,"%s %lld %lld %d %d\n",m->file,m->offset,m->bytes,m->nrows,m->ncols);
+      }
+      xf = xf->next;
+    }
+  }
+  else {
+    m = memfile;
+    if (!is_stream) fprintf(stdout,"%d %d %lld %d\n",hdrsize,nmem,next_free_offset,ngaps);
+    else            fprintf(stdout,"%d\n",nmem);
+    while (m) {
+      if (!is_stream) fprintf(stdout,"%s %lld %lld %lld %d %d\n",m->file,m->offset,m->bytes,m->freespace,m->nrows,m->ncols);
+      else            fprintf(stdout,"%s %lld %lld %d %d\n",m->file,m->offset,m->bytes,m->nrows,m->ncols);
+      m = m->next;
+    }
+  }
+  return nmem;
+}
+
+PUBLIC int
+QTAR_main(int argc, char *argv[])
+{
+  int c;
+  int fd = -1;
+  int saved_argc = argc;
+  char **saved_argv = argv;
+  int exist;
+
+  standalone_job = 1;
+
+  while ((c = getopt(argc, argv, QTAR_FLAGS)) != -1) {
+    switch (c) {
+    case 'f': /* qtar-file */
+      if (!qtarfile) qtarfile = STRDUP(optarg);
+      else errmsg("Multiple QTAR-files supplied");
+      break;
+    case 'm': /* a member-file */
+      AddFile(optarg);
+      break;
+    case 'D': /* Debug ON */
+      debug = 1;
+      break;
+    case 'd': /* Delete */
+      if (!toc && !update && !extract) delete = 1;
+      else errmsg("-d -t -u -x flags are mutually exclusive");
+      break;
+    case 'x': /* Extract */
+      if (!toc && !update && !delete) extract = 1;
+      else errmsg("-d -t -u -x flags are mutually exclusive");
+      break;
+    case 't': /* Table of contents */
+      if (!update && !extract && !delete) toc = 1;
+      else errmsg("-d -t -u -x flags are mutually exclusive");
+      break;
+    case 'C': /* Compress */
+      compress = 1;
+      break;
+    case 'c': /* Create new */
+      create = 1;
+      /* no break; i.e. fall through */
+    case 'u': /* Update */
+      if (!toc && !extract && !delete) update = 1;
+      else errmsg("-d -t -u -x flags are mutually exclusive");
+      break;
+    case 'v': /* Verbose */
+      verbose = 1;
+      break;
+    case 'V': /* Version */
+      Version = 1;
+      break;
+    case 's': /* read/write from/to stream i.e. pipe */
+      is_stream = 1;
+      break;
+    case 'M': /* Respect matrix dimensions */
+      matrix_dim = 1;
+      break;
+    case 'b': /* I/O-bufsize */
+      io_bufsize = atoi(optarg);
+      if (io_bufsize < HDRSIZE_DEFAULT) io_bufsize = HDRSIZE_DEFAULT;
+      io_bufsize = RNDUP(io_bufsize, WORDLEN);
+      break;
+    case 'R': /* Alloc roundup for each member file */
+      alloc_rndup = atoi(optarg);
+      if (alloc_rndup < WORDLEN) alloc_rndup = WORDLEN;
+      alloc_rndup = RNDUP(alloc_rndup, WORDLEN);
+      break;
+    case 'H': /* Change HDR-size (minimum is HDRSIZE_DEFAULT, though) */
+      hdrsize = atoi(optarg);
+      if (hdrsize < HDRSIZE_DEFAULT) hdrsize = HDRSIZE_DEFAULT;
+      hdrsize = RNDUP(hdrsize, WORDLEN);
+      break;
+    default:
+      errflg++;
+      break;
+    } /* switch (c) */
+  } /* while */
+
+  if (argc - 1 >= optind) {
+    if (!qtarfile) qtarfile = STRDUP(argv[optind]);
+    else AddFile(argv[optind]);
+    optind++;
+  }
+
+  if (argc > optind) {
+    /* More than one file supplied */
+    for ( ; optind < argc; optind++) {
+      AddFile(argv[optind]);
+    }
+  }
+
+  /* Default is QTARFILE or its environment value, if not supplied */
+  if (!qtarfile) {
+    char *env = getenv(QTARFILE);
+    qtarfile = env ? STRDUP(env) : STRDUP(QTARFILE);
+  }
+
+  exist = FileExist(qtarfile);
+  if (!exist) {
+    if (update || delete) create = 1;
+    if (!delete && !toc) {
+      if (!create) errmsg("QTARFILE %s does not exist",qtarfile);
+    }
+  }
+
+  if (!create && !update && !toc && !extract && !delete) {
+    errmsg("None of the options -c, -d, -t, -u or -x were supplied");
+  }
+
+  /* to remove unnecessary complaints/warning msgs from compilation */
+  if (Version); /* Not implemented yet */
+  if (debug); /* Do nothing */
+  if (nlcnt_hdr_fmt); /* do nothing */
+  if (nlcnt_mem_fmt); /* do nothing */
+  if (nlcnt_eofhdr_fmt); /* do nothing */
+
+  if (errflg) {
+    fprintf(stderr,USAGE,argv[0],IO_BUFSIZE,HDRSIZE_DEFAULT,ALLOC_RNDUP);
+    {
+      int j;
+      fprintf(stderr,"*** Supplied arguments (count=%d) ***\n",saved_argc);
+      for (j=0; j<saved_argc; j++) {
+	fprintf(stderr,"%s ",saved_argv[j]);
+      }
+      fprintf(stderr,"\n");
+    }
+    return errflg;
+  }
+
+  if (toc && !exist) {
+    if (is_stream) fprintf(stdout,"0\n");
+    return 0; /* Do nothing */
+  }
+
+  if (create && exist) (void) remove(qtarfile);
+
+  if (compress); /* Not implemented yet */
+
+  /* Record the master option */
+  if (update)  option="-u";
+  if (update && create)  option="-c -u";
+  if (extract) option="-x";
+  if (delete)  option="-d";
+  if (delete && create)  option="-c -d";
+  if (toc)     option="-t";
+
+  if (update) SetFileSizes();
+
+  fd = OpenQTAR();
+  if (update)  UpdateQTAR(fd);
+  if (extract) ExtractQTAR(fd);
+  if (delete)  DeleteQTAR(fd);
+  if (toc)     TocQTAR(fd);
+  CloseQTAR(fd);
+
+  return errflg;
+}
diff --git a/odb/src/aux/result.c b/odb/src/aux/result.c
new file mode 100644
index 0000000..03ab943
--- /dev/null
+++ b/odb/src/aux/result.c
@@ -0,0 +1,3486 @@
+
+/*!
+ \file result.c
+ \brief write the result of an SQL query in an output file. 
+ The output format can be:
+      - default           Ascii where field delimiter is space (" "), and output is rather compressed
+      - binary            binary format will be used for output
+      - plotobs           $ODB_PLOTTER compatible binary file for Magics will be created
+      - wplotobs          $ODB_PLOTTER compatible binary file for Magics will be created (wind-arrows)
+      - odbtool           input(s) for IDL/odbtool (by Phil Watts while at ECMWF, now in Eumetsat) will be created
+      - odbtk             field delimiters become "!,!" and unique column ids ($uniq#) will be printed as "zero-th" column
+      - odb               "odbviewer"/"odbless" .rpt-file format is emulated
+      - netcdf            create NetCDF-file with ODB Conventions (lat/lon are in degrees)
+      - unetcdf           as "netcdf" above, but create without packing (lat/lon are in degrees)
+      - dump              similar to "default", but delimiter is comma "," (lat/lon are in degrees)
+      - bindump           similar to "binary", but all data will be printed row_wise + metadata & title-structure always embedded (lat/lon are in degrees)
+      - geo               (standard) Metview GEO-points file with "lat lon level date time value"
+      - geo:xyv           GEO-points file with "x/long y/lat value"
+      - geo:xy_vector     GEO-points file with "lat lon height date time u v"
+      - geo:polar_vector  GEO-points file with "lat lon height date time speed direction"
+
+
+*/
+
+#include "odb.h"
+#include "odb_macros.h"
+#include "dca.h"
+#include "evaluate.h"
+#include "info.h"
+#include "result.h"
+#include "iostuff.h"
+#include "cdrhook.h"
+#include "magicwords.h"
+#include "swapbytes.h"
+#include "idx.h"
+#include "bits.h"
+#include "cmaio.h"
+#include "codb_netcdf.h"
+
+#define COLUMN_FETCH_ERROR() \
+fprintf(stderr, \
+	"***Error: Unable to fetch column '%s' for pool#%d. " \
+	"Expecting %d (= # of rows in table '%s'), but got %d rows.\n", \
+	s, poolno, tc->nrows, tc->name, Nrows)
+
+/*!
+ Modified from the version in odb/compiler/odb98.c. 
+ The same as fprintf(), but does nothing when fp points to NULL
+  @param fp File pointer
+  @param format Format of the format string (see fprintf manual for more information)
+  @return Upon successful return, it returns the number of characters
+       printed  (not  including  the  trailing  '\0'  used  to  end  output to
+       strings).
+ */
+PUBLIC int
+ODB_fprintf(FILE *fp, const char *format, ...)
+{ 
+  int n = 0;
+  if (fp) {
+    va_list args;
+    va_start(args, format);
+    n = vfprintf(fp, format, args);
+    va_end(args);
+  }
+  return n;
+}
+
+
+typedef struct _cmap_t {
+  char *fname;
+  char text[80+1];
+  char var[80+1];
+  float value_min;
+  float value_max;
+  float scale[6];
+} cmap_t;
+
+PRIVATE cmap_t *cmap = NULL; /* Not thread safe */
+
+PUBLIC Bool
+ODBc_set_kolor_map(const char *cmapfile)
+{
+  cmap_t *p = NULL;
+  DRHOOK_START(ODBc_set_kolor_map);
+  if (cmap) {
+    FREE(cmap->fname);
+    FREE(cmap);
+  }
+  if (cmapfile && !strequ(cmapfile,"/dev/null")) {
+    FILE *fp = NULL;
+    int iounit = -1;
+    int iret = 0;
+    cma_open_(&iounit, cmapfile, "r", &iret, STRLEN(cmapfile), 1);
+    fp = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+    if (fp) {
+      char line[80+1];
+      char *s;
+      CALLOC(p, 1);
+      p->fname = STRDUP(cmapfile);
+      memset(p->text, ' ', 80);
+      memset(p->var, ' ', 80);
+      p->value_min = 0;
+      p->value_max = -1;
+      memset(p->scale, 0, sizeof(float) * 6);
+      /* Read 1st line */
+      if ((s = fgets(line, sizeof(line), fp)) != NULL) {
+	int len;
+	char *nl = strchr(s, '\n'); if (nl) *nl = '\0';
+	strcpy(p->text, s);
+	len = strlen(p->text);
+	if (len < 80) memset(p->text+len,' ',80-len);
+	/* Read 2nd line */
+	s = fgets(line, sizeof(line), fp);
+	if (s) {
+	  nl = strchr(s, '\n'); if (nl) *nl = '\0'; 
+	  strcpy(p->var, s);
+	  len = strlen(p->var);
+	  if (len < 80) memset(p->var+len,' ',80-len);
+	  /* Read 3rd line */
+	  s = fgets(line, sizeof(line), fp);
+	  if (s) {
+	    nl = strchr(s, '\n'); if (nl) *nl = '\0';
+	    while (*s) {
+	      if (*s == '!') {
+		*s = '\0';
+		break;
+	      }
+	      else if (*s == ',') {
+		*s = ' ';
+	      }
+	      s++;
+	    }
+	    {
+	      float x,y;
+	      int nelem = sscanf(line, "%f %f", &x, &y);
+	      if (nelem == 2) {
+		p->value_min = x;
+		p->value_max = y;
+		/* Read 4th and last line */
+		s = fgets(line, sizeof(line), fp);
+		if (s) {
+		  int iscale = 0;
+		  nl = strchr(s, '\n'); if (nl) *nl = '\0';
+		  while (*s) {
+		    if (*s == '!') {
+		      *s = '\0';
+		      break;
+		    }
+		    else if (*s == ',') {
+		      *s = ' ';
+		    }
+		    s++;
+		  }
+		  nelem = sscanf(line, "%d", &iscale);
+		  if (nelem == 1) {
+		    if (iscale >= 1 && iscale <= 4) {
+		      nelem = sscanf(line, "%d %f %f", &iscale, &x, &y);
+		      if (nelem == 3) {
+			p->scale[0] = iscale;
+			p->scale[1] = x;
+			p->scale[2] = y;
+		      } /* if (nelem == 3) */
+		    } /* if (iscale >= 1 && iscale <= 4) */
+		  } /* if (nelem == 1) */
+		} /* if (s) */
+	      } /* if (nelem == 2) */
+	    }
+	  } /* if (s) */
+	} /* if (s) */
+      } /* if ((s = fgets(line, sizeof(line), fp)) != NULL) */
+      p->text[80] = '\0';
+      p->var[80] = '\0';
+      cma_close_(&iounit, &iret);
+      cmap = p;
+    } /* if (fp) */
+  }
+  DRHOOK_END(0);
+  return p ? true : false;
+}
+
+PUBLIC Bool 
+ODBc_get_kolor_map(float *value_min, float *value_max, float scale[], 
+		   char *text, int textlen)
+{ 
+  Bool ok = false;
+  DRHOOK_START(ODBc_get_kolor_map);
+  if (cmap) {
+    cmap_t *p = cmap;
+    int len = MIN(textlen,80);
+    if (text) strncpy(text, p->text, textlen);
+    if (scale) memcpy(scale, p->scale, sizeof(float) * 6);
+    if (value_min) *value_min = p->value_min;
+    if (value_max) *value_max = p->value_max;
+    ok = true;
+  }
+  DRHOOK_END(0);
+  return ok;
+}
+
+
+PRIVATE char *output_format = NULL; /* Not thread safe */
+
+PUBLIC void
+ODBc_set_format(const char *format)
+{
+  FREE(output_format);
+  if (format) output_format = STRDUP(format);
+}
+
+PUBLIC Bool
+ODBc_test_format_1(const char *test_format)
+{
+  return strequ(output_format, test_format) ? true : false;
+}
+
+PUBLIC Bool
+ODBc_test_format_2(const char *format, const char *test_format)
+{
+  return format ? strequ(format, test_format) : ODBc_test_format_1(test_format);
+}
+
+PUBLIC Bool
+ODBc_test_format_3(const char *format, const char *test_format, int len)
+{
+  return format ? strnequ(format, test_format, len) : strnequ(output_format, test_format, len);
+}
+
+
+PRIVATE int
+GeoFormat()
+{
+  int fmt = 0;
+  Bool is_geo = ODBc_test_format_3(output_format, "geo", 3);
+  if (is_geo) {
+    if (ODBc_test_format_2(output_format, "geo")) fmt = 1;
+    else if (ODBc_test_format_2(output_format, "geo:xyv")) fmt = 2;
+    else if (ODBc_test_format_2(output_format, "geo:xy_vector")) fmt = 3;
+    else if (ODBc_test_format_2(output_format, "geo:polar_vector")) fmt = 4;
+    else fmt = 0;
+  }
+  return fmt;
+}
+
+
+PUBLIC
+Bool ODBc_nothing_to_plot(void *Info)
+{
+  Bool nothing = true;
+  FILE *fp_echo = ODBc_get_debug_fp();
+
+  DRHOOK_START(ODBc_nothing_to_plot);
+  if (Info) {
+    info_t *info = Info;
+    int cnt = 0;
+
+    if (info->create_index == 0 && info->odb_lat && info->odb_lon) {
+      Bool is_plotobs = ODBc_test_format_1("plotobs");
+      Bool warrow = ODBc_test_format_1("wplotobs");
+      Bool is_odbtool = ODBc_test_format_1("odbtool");
+      int geofmt = GeoFormat();
+      const char *lat = info->odb_lat->name;
+      const char *lon = info->odb_lon->name;
+      int j, ncols = info->ncols_true;
+
+      ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): ncols = %d\n",ncols);
+      ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): lat = '%s'\n",lat);
+      ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): lon = '%s'\n",lon);
+
+      if (is_plotobs || warrow) {
+	/* Any two $ODB_LAT & $ODB_LON entries would do */
+	ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): For %splotobs\n",
+		    warrow ? "w" : "");
+
+	for (j=0; j<ncols && cnt < 2; j++) {
+	  col_t *colthis = &info->c[j];
+	  const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  if (strequ(s, lat)) {
+	    cnt++;
+	    lat = NULL; /* don't bovver to test me anymore */
+	  }
+	  else if (strequ(s, lon)) {
+	    cnt++;
+	    lon = NULL; /* don't bovver to test me anymore */
+	  }
+	  ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): cnt now = %d\n",cnt);
+	}
+
+	nothing = (cnt == 2) ? false : true;
+      }
+      else if (is_odbtool) {
+	/* Following restrictions apply:
+	   1) lat and lon exactly in the first & second columns, in this order
+	   2) body.len in the third (but here we accept "$hdr.body#", too
+	   3) At least 4 columns must be present
+	*/
+
+	if (ncols >= 4) {
+	  col_t *colthis;
+	  const char *s;
+
+	  /* First column */
+	  j=0;
+	  colthis = &info->c[j];
+	  s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  if (strequ(s, lat)) cnt++;
+
+	  /* Second column */
+	  j=1;
+	  colthis = &info->c[j];
+	  s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  if (strequ(s, lon)) cnt++;
+
+	  /* Third column */
+	  j=2;
+	  colthis = &info->c[j];
+	  s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  {
+	    const char bodylen1[] = "$hdr.body#";
+	    const char bodylen2[] = "body.len at hdr";
+	    const char bodylen3[] = "body.len";
+	    const char bodylen4[] = "LINKLEN(body)@hdr";
+	    if (strequ(s, bodylen1) || strequ(s, bodylen2) ||
+		strequ(s, bodylen3) || strequ(s, bodylen4)) cnt++;
+	  }
+
+	  nothing = (cnt == 3) ? false : true;
+	}
+      }
+      else if (geofmt) {
+	/* 
+	   Recognized MetView GEO-points formats :
+	   --------------------------------------
+	   1 = lat      long       level          date      time        value
+	   2 = #FORMAT XYV = x/long       y/lat       value
+	   3 = #FORMAT XY_VECTOR = lat        lon height      date        time        u       v
+	   4 = #FORMAT POLAR_VECTOR = lat        lon     height      date        time        speed   direction
+
+	   !!! Please note, that for some reason the 2nd format (XYV) requires longitude first !!!
+	*/
+
+	/* 
+	   First check the number of columns :
+	   1 == 6 columns
+	   2 == 3 columns
+	   3 == 7 columns
+	   4 == 7 columns
+	*/
+	
+	Bool is_okay = false;
+	const int req_ncols[1+4] = { -1, 6, 3, 7, 7 };
+
+	if      (geofmt == 1 && ncols == req_ncols[geofmt]) is_okay = true;
+	else if (geofmt == 2 && ncols == req_ncols[geofmt]) is_okay = true;
+	else if (geofmt == 3 && ncols == req_ncols[geofmt]) is_okay = true;
+	else if (geofmt == 4 && ncols == req_ncols[geofmt]) is_okay = true;
+
+	if (is_okay) {
+	  /* So far ok; now check that (lat,lon) exist, and (date,time) [except for fmt=2] */
+	  col_t *colthis;
+	  const char *s;
+
+	  /* First column */
+	  j=0;
+	  colthis = &info->c[j];
+	  s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  if (strequ(s, (geofmt == 2) ? lon : lat)) cnt++;
+
+	  /* Second column */
+	  j=1;
+	  colthis = &info->c[j];
+	  s = colthis->nickname ? colthis->nickname : colthis->name;
+	  ODB_fprintf(fp_echo,
+		      "ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+		      j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	  if (strequ(s, (geofmt == 2) ? lat : lon)) cnt++;
+
+	  if (geofmt != 2) {
+	    const char *date = info->odb_date->name;
+	    const char *time = info->odb_time->name;
+
+	    /* Fourth column */
+	    j=3;
+	    colthis = &info->c[j];
+	    s = colthis->nickname ? colthis->nickname : colthis->name;
+	    ODB_fprintf(fp_echo,
+			"ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+			j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	    if (strequ(s, date)) cnt++;
+
+	    /* Fifth column */
+	    j=4;
+	    colthis = &info->c[j];
+	    s = colthis->nickname ? colthis->nickname : colthis->name;
+	    ODB_fprintf(fp_echo,
+			"ODBc_nothing_to_plot(): info->c[%d].%s = '%s'\n",
+			j, colthis->nickname ? "nickname" : "name", s ? s : NIL);
+	    if (strequ(s, time)) cnt++;
+
+	    is_okay = (cnt == 4) ? true : false;
+	  }
+	  else {
+	    is_okay = (cnt == 2) ? true : false;
+	  }
+	} /* if (is_okay) */
+
+	if (!is_okay) {
+	  ODB_fprintf(stderr,
+		      "***Warning: Nothing to plot for GEO-points format#%d. Check your SQL.\n",geofmt);
+	  nothing = true;
+	}
+	else {
+	  nothing = false;
+	}
+
+      } /* if (is_plotobs || warrow) ... else if (is_odbtool) ... else if (geofmt) ... */
+    } /* if (info->create_index == 0 && info->odb_lat && info->odb_lon) */
+
+    ODB_fprintf(fp_echo,"ODBc_nothing_to_plot(): cnt = %d\n",cnt);
+  }
+
+  ODB_fprintf(fp_echo,"ODBc_nothing_to_plot() = %s\n",nothing ? "true" : "false");
+  DRHOOK_END(0);
+  return nothing;
+}
+
+PRIVATE table_t *
+GetTable(info_t *info, const char *colname)
+{
+  table_t *tc = NULL;
+  DRHOOK_START(GetTable);
+  if (info && colname) { 
+    const char *tblname = IS_HASH(colname) ? colname : strchr(colname, '@');
+    if (tblname++) {
+      table_t *t = info->t;
+      const char *poffset = GET_OFFSET(tblname);
+      int len = poffset ? (int)(poffset - tblname) : STRLEN(tblname);
+      while (t) {
+	if (strnequ(t->name, tblname, len)) {
+	  tc = t;
+	  break;
+	}
+	t = t->next;
+      } /* while (t) */
+    } /* if (tblname) */
+  } /* if (info && colname) */
+  DRHOOK_END(0);
+  return tc;
+}
+
+
+PRIVATE Bool
+isPowerOfTwo(int iarg)
+{
+  return (IAND(iarg,-iarg) == iarg) ? true : false;
+}
+
+
+PUBLIC int
+ODBc_lda(int m, int method)
+{ /* As in odb/module/odbshared.F90 */
+  int lda;
+  DRHOOK_START(ODBc_lda);
+  m = MAX(1,m);
+  switch (method) {
+  case 0: lda = m + (m+1)%2; break;
+  case 1: lda = m; break;
+  case 2: if (isPowerOfTwo(m)) m++; lda = m; break;
+  default: lda = m; break;
+  }
+  DRHOOK_END(0);
+  return lda;
+}
+
+
+PUBLIC void *
+ODBc_new_res(const char *label, const char *file, int lineno,
+	     int nrows, int ncols, void *Info, Bool row_wise, int poolno)
+{
+  FILE *fp_echo = ODBc_get_debug_fp();
+  const int method = 1; /* Changed from 2 to 1 by SS/25-Feb-2014 */
+  int nra = row_wise ? ODBc_lda(ncols, method) : ODBc_lda(nrows, method);
+  int nmem = row_wise ? nra * nrows : nra * ncols;
+  int i, k;
+  info_t *info = Info;
+  result_t *newres = NULL;
+  DRHOOK_START(ODBc_new_res);
+
+  /* Allocate and initialize */
+
+  CALLOC(newres, 1);
+
+  if (fp_echo && label) {
+    ODB_fprintf(fp_echo,"ODBc_new_res => %s (%s:%d) : addr=%p "
+		"nrows=%d, ncols=%d, nra=%d, row_wise=%s, poolno=%d\n",
+		label, file, lineno, newres,
+		nrows, ncols, nra, row_wise ? "true" : "false", poolno);
+  }
+
+  CALLOC(newres->mem, nmem);
+  newres->nmem = nmem;
+  newres->ncols_in = newres->ncols_out = ncols;
+  newres->nrows_in = newres->nrows_out = nrows;
+  newres->nra = nra;
+  newres->row_wise = row_wise;
+  newres->poolno = poolno;
+  newres->info = info;
+  newres->next = NULL;
+  newres->backup = false;
+  newres->backup_file = NULL;
+  
+  if (row_wise) {
+    ALLOC(newres->d, nrows);
+    k = 0;
+    for (i=0; i<nrows; i++) {
+      newres->d[i] = &newres->mem[k];
+      k += nra;
+    }
+  }
+  else {
+    ALLOC(newres->d, ncols);
+    k = 0;
+    for (i=0; i<ncols; i++) {
+      newres->d[i] = &newres->mem[k];
+      k += nra;
+    }
+  }
+
+  DRHOOK_END(0);
+  return newres;
+}
+
+
+PUBLIC void *
+ODBc_merge_res(const char *label, const char *file, int lineno,
+	       void *Res, int ncols, void *Info, Bool row_wise)
+{
+  FILE *fp_echo = ODBc_get_debug_fp();
+  info_t *info = Info;
+  result_t *res = Res;
+  result_t *newres = NULL;
+  result_t *r = res;
+  int chain_len = 0;
+  int count_row_wises_are_the_same = 0;
+  int nrows = 0;
+  DRHOOK_START(ODBc_merge_res);
+
+#if 0
+  fprintf(stderr,"ODBc_merge_res() < res follows\n");
+  ODBc_print_data(NULL, stderr, res, 
+		  "odb", "-",
+		  0, 1, 0,
+		  NULL);
+#endif
+
+  while (r) {
+    nrows += r->nrows_out;
+    if (r->row_wise == row_wise) count_row_wises_are_the_same++;
+    r = r->next;
+    chain_len++;
+  } /* while (r) */
+
+  if (fp_echo && label) {
+    ODB_fprintf(fp_echo,"ODBc_merge_res => %s (%s:%d) : addr=%p, info=%p "
+		"nrows=%d, ncols=%d, chain_len=%d, row_wise=%s\n",
+		label, file, lineno, res, info,
+		nrows, ncols, chain_len, row_wise ? "true" : "false");
+  }
+
+  if (res && nrows > 0 && (chain_len > 1 || count_row_wises_are_the_same < chain_len)) {
+    int i, j, k;
+
+    newres = ODBc_new_res("ODBc_merge_res => newres", 
+			  __FILE__, __LINE__,
+			  nrows, ncols, info, row_wise, 
+			  (chain_len > 1) ? -1 : res->poolno);
+
+    /* Copy from the existing res-chain */
+    k = 0;
+    r = res;
+    while (r) {
+      int nr = r->nrows_out;
+      for (i=0; i<ncols; i++) {
+	for (j=0; j<nr; j++) {
+	  double value = r->row_wise ? r->d[j][i] : r->d[i][j];
+	  if (row_wise) {
+	    newres->d[k+j][i] = value;
+	  }
+	  else {
+	    newres->d[i][k+j] = value;
+	  }
+	}
+      }
+      k += nr;
+      r = r->next;
+    } /* while (r) */
+
+    /* Get rid off the old res, which potentially releases a lot of memory */
+    (void) ODBc_unget_data(res);
+  }
+  else {
+    newres = res;
+  }
+
+#if 0
+  fprintf(stderr,"ODBc_merge_res() > newres follows\n");
+  ODBc_print_data(NULL, stderr, newres, 
+		  "odb", "-",
+		  0, 1, 0,
+		  NULL);
+#endif
+  DRHOOK_END(0);
+  return newres;
+}
+
+
+PRIVATE int
+DynFill(double data[], int ndata,
+	const int idx[], int idxlen,
+	int istart, int iend, int ioffset)
+{
+  int rc = 0;
+  int inc = iend - istart;
+  DRHOOK_START(DynFill);
+  if (idx && idxlen > 0 && idxlen >= inc &&
+      data && ndata >= inc && inc >= 1) {
+    int j, js, prev, len;
+    js = istart;
+    prev = idx[js];
+    len = 1;
+    for (j=istart+1; j<iend; j++) {
+      if (prev != idx[j]) {
+	int i, je = j;
+	for (i=js; i<je; i++) data[i-ioffset] = len;
+	js = j;
+	prev = idx[js];
+	len = 1;
+      }
+      else
+	len++;
+    } /* for (j=istart+1; j<iend; j++) */
+    if (len > 0) {
+      int i, je = iend;
+      for (i=js; i<je; i++) data[i-istart] = len;
+    }
+    rc = inc;
+  } /* if (idx && idxlen > 0 && ... */
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC int
+ODB_dynfill(const char *s,
+	    void *V,
+	    int *(*getindex)(void *V, const char *table, int *lenidx),
+	    double data[], int ndata,
+	    int istart, int iend, int ioffset)
+{
+  int rc = 0;
+  DRHOOK_START(ODB_dynfill);
+  if (getindex && IS_USDDOTHASH(s) && 
+      data && ndata > 0) {
+    char *p = STRDUP(s);
+    char *dot = strchr(p, '.');
+    if (dot) {
+      int *idx = NULL;
+      int lenidx = 0;
+      char *parent_table = p+1;
+      *dot = '\0';
+      idx = getindex(V, parent_table, &lenidx);
+      rc = DynFill(data, ndata,
+		   idx, lenidx,
+		   istart, iend, ioffset);
+    }
+    FREE(p);
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC void
+ODBc_DebugPrintRes(const char *when, const result_t *r)
+{
+  FILE *fp_echo = ODBc_get_debug_fp();
+  if (fp_echo && when && r) {
+    int i, j, maxrows;
+    uresult_t u;
+    fprintf(fp_echo,"\n");
+    fprintf(fp_echo,
+	    "ODBc_DebugPrintRes for '%s' : nrows = %d, ncols = %d, nra=%d, row_wise = %s\n",
+	    when, r->nrows_out, r->ncols_out, r->nra, r->row_wise ? "true" : "false");
+    u.res = (result_t *)r; /* not changing the const value, though */
+    fprintf(fp_echo,
+	    "ODBc_DebugPrintRes: u.res = %p, u.alias = %.14g, u.i[0:1] = (%d, %d)\n",
+	    u.res, u.alias, u.i[0], u.i[1]);
+    maxrows = MIN(100,r->nrows_out);
+    for (j=0; j<maxrows; j++) {
+      fprintf(fp_echo,"row#%d: ",j+1);
+      for (i=0; i<r->ncols_out; i++) {
+	fprintf(fp_echo," %.14g",r->row_wise ? r->d[j][i] : r->d[i][j]);
+      }
+      fprintf(fp_echo,"\n");
+    }
+    if (maxrows < r->nrows_out) fprintf(fp_echo, "... etc.\n");
+    fprintf(fp_echo,"\n");
+  }
+}
+
+PUBLIC void *
+ODBc_get_data_from_binary_file(const char *filename, Boolean sort_unique)
+{
+  result_t *res = NULL;
+  DRHOOK_START(ODBc_get_data_from_binary_file);
+  {
+    Boolean is_pipe = (filename && *filename == '|');
+    FILE *fp = is_pipe ? popen(++filename,"r") : fopen(filename,"r");
+    if (fp) {
+      Boolean on_error = false;
+      int nrows_tot = 0;
+      int ncols_here = 0;
+      result_t *last = NULL;
+      int word[2];
+      /* setvbuf here */
+      while (!on_error && fread(word, sizeof(*word), 2, fp) == 2) {
+	if (word[0] == ODBX) { /* initially no byteswapping; assuming the same machine */
+	  int *hdr = NULL;
+	  int nhdr = word[1];
+	  ALLOCX(hdr, nhdr);
+	  hdr[0] = word[0];
+	  hdr[1] = word[1];
+	  if (fread(hdr+2, sizeof(*hdr), nhdr-2, fp) == nhdr - 2) {
+	    int poolno = hdr[5];
+	    int nrows = hdr[6];
+	    int ncols = hdr[7];
+	    Boolean row_wise = hdr[8] ? true : false;
+	    result_t *r = ODBc_new_res("ODBc_get_data_from_binary_file => r",
+				       __FILE__, __LINE__,
+				       nrows, ncols, NULL, row_wise, poolno);
+	    int i;
+	    if (ncols_here == 0) ncols_here = ncols;
+	    nrows_tot += nrows;
+	    if (row_wise) { /* Row-wise (C) */
+	      for (i=0; i<nrows; i++) {
+		double *value = &r->d[i][0];
+		if (fread(value, sizeof(*value), ncols, fp) != ncols) {
+		  on_error = true;
+		  goto bailout;
+		}
+	      } /* for (i=0; i<nrows; i++) */
+	    }
+	    else { /* Column-wise (Fortran) */
+	      for (i=0; i<ncols; i++) {
+		double *value = &r->d[i][0];
+		if (fread(value, sizeof(*value), nrows, fp) != nrows) {
+		  on_error = true;
+		  goto bailout;
+		}
+	      } /* for (i=0; i<ncols; i++) */
+	    }
+	  bailout:
+	    if (!res) {
+	      res = last = r;
+	    }
+	    else {
+	      last->next = r;
+	      last = r;
+	    }
+	  } /* if (fread(hdr+2, sizeof(*hdr), nhdr-2, fp) == nhdr - 2) */
+	  else {
+	    on_error = true;
+	  }
+	  FREEX(hdr);
+	} /* if (word[0] == ODBX) */
+	else {
+	  on_error = true;
+	}
+      } /* while (!on_error && fread(word, sizeof(*word), 2, fp) == 2) */ 
+
+      is_pipe ? pclose(fp) : fclose(fp);
+
+      if (on_error) {
+	res = ODBc_unget_data(res); /* Some error(s) were encountered */
+      }
+      else if (res && sort_unique) {
+	/* Create a new result set with just 
+	   unique numbers across row sorted in an ascending order (w.r.t column#1 only) */
+	result_t *r, *pr;
+	int *idx = NULL;
+	Boolean row_wise = false;
+	int nrows = nrows_tot;
+	int ncols = ncols_here;
+	int jj = 0;
+	int lda;
+	r = ODBc_new_res("ODBc_get_data_from_binary_file => sort_unique",
+			 __FILE__, __LINE__,
+			 nrows, ncols, NULL, row_wise, -1);
+	lda = r->nra;
+	pr = res;
+	while (pr) {
+	  /* Note : the new result set (r) is column-wise (Fortran) i.e. its r->row_wise == false */
+	  int nr = pr->nrows_out;
+	  int nc = MIN(pr->ncols_out, ncols);
+	  int i, j;
+	  if (pr->row_wise) { /* Row-wise (C) */
+	    for (i=0; i<nc; i++) {
+	      for (j=0; j<nr; j++) {
+		r->d[i][jj+j] = pr->d[j][i];
+	      } /* for (j=0; j<nr; j++) */
+	    } /* for (i=0; i<nc; i++) */
+	  }
+	  else { /* Column-wise (Fortran) */
+	    for (i=0; i<nc; i++) {
+	      const double *value = &pr->d[i][0];
+	      memcpy(&r->d[i][jj], value, nr * sizeof(*value));
+	    } /* for (i=0; i<nc; i++) */
+	  }
+	  jj += nr;
+	  pr = pr->next;
+	} /* while (pr) */
+	res = ODBc_unget_data(res);
+
+	/* Keep distinct values (across all cols in rows) only */
+
+	{
+	  const int method = 1; /* Changed from 2 to 1 by SS/25-Feb-2014 */
+	  int *idx = NULL;
+	  double *d = NULL;
+	  int i, j, k, ncard = 0;
+	  int lda_ncard;
+	  int nmem;
+
+	  ALLOC(idx, nrows);
+	  codb_cardinality_(&ncols, &nrows, &lda,
+			    r->mem, &ncard, idx, &nrows, NULL);
+
+	  lda_ncard = ODBc_lda(ncard, method);
+	  nmem = lda_ncard * ncols;
+	  ALLOC(d, nmem);
+
+	  for (i=0; i<ncols; i++) {
+	    for (j=0; j<ncard; j++) {
+	      k = idx[j] - 1; /* "-1" due to C -> Fortran indexing conversion in codb_cardinality_() */
+	      d[i*lda_ncard + j] = r->d[i][k];
+	    }
+	  } /* for (i=0; i<ncols; i++) */
+
+	  FREE(idx);
+	  FREE(r->mem);
+
+	  r->mem = d;
+	  r->nmem = nmem;
+	  lda = r->nra = lda_ncard;
+	  r->nrows_in = r->nrows_out = ncard;
+
+	  k = 0;
+	  for (i=0; i<ncols; i++) {
+	    r->d[i] = &r->mem[k];
+	    k += lda;
+	  }
+
+	  ODBc_DebugPrintRes("ODBc_get_data_from_binary_file @ before sort", r);
+	}
+
+	/* Then sort */
+
+	{
+	  const int key = 1;
+	  r = ODBc_sort(r, &key, 1);
+	  ODBc_DebugPrintRes("ODBc_get_data_from_binary_file @ after sort", r);
+	}
+
+	res = r;
+      }
+    } /* if (fp) */
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+#define SKIPCOL(j) if (skipcol && skipcol[j]) continue
+
+PRIVATE result_t *
+GetData(const DB_t *ph, info_t *info, int poolno, 
+	int begin_row, int end_row, const Bool *row_wise_preference)
+{
+  result_t *res = NULL;
+  DRHOOK_START(GetData);
+  if (ph && info) {
+    int nrows = info->idxlen;
+    int ncols = info->ncols;
+
+    if ((info->optflags & 0x1) == 0x1) {
+      /* A special case : SELECT count(*) FROM table */
+      table_t *t = info->t;
+      double value = t->nrows;
+      Bool row_wise = true; /* doesn't matter ; just one value involved */
+      nrows = 1;
+      ncols = 1;
+      res = ODBc_new_res("GetData => res of count(*)", 
+			 __FILE__, __LINE__,
+			 nrows, ncols, info, row_wise, poolno);
+      res->d[0][0] = value;
+      res->nrows_out = nrows;
+      res->ncols_out = ncols;
+    }
+    else if (nrows > 0 && ncols > 0) {
+      DEF_IT;
+      thsafe_parse_t *thsp = (thsafe_parse_t *)GetTHSP(); /* Wanna change aggr_argno directly !! */
+      int i, j, k;
+      int errflg = 0;
+      int ncols_true = info->ncols_true;
+      Bool *skipcol = NULL;
+      Bool is_plotobs = ODBc_test_format_1("plotobs");
+      Bool warrow = ODBc_test_format_1("wplotobs");
+      Bool is_netcdf = ODBc_test_format_1("netcdf");
+      Bool has_orderby = (info->o && info->norderby > 0) ? true : false;
+      Bool row_wise = (has_orderby || info->has_aggrfuncs || is_netcdf) ? false : 
+	(row_wise_preference ? *row_wise_preference : true);
+      double *_poolno = getsymaddr(_POOLNO);
+      double *_uniqnum = getsymaddr(_UNIQNUM);
+      double *_rownum = getsymaddr(_ROWNUM);
+      double *_colnum = getsymaddr(_COLNUM);
+      double *_nrows = getsymaddr(_NROWS);
+      double *_ncols = getsymaddr(_NCOLS);
+      int ndyn = info->ndyn;
+      int istart, iend;
+      int *colmask = NULL;
+
+      if (is_plotobs || warrow) {
+	/* When plotting and all columns are non-formulas, then
+	   we can load only those columns, which are
+	   indicated by $ODB_LAT, $ODB_LON and $ODB_COLOR 
+	   
+	   But, but ... we MUST also not forget to load the nonassociated columns (kind=0)
+	   i.e. those which are possibly used in function call of the primary columns !!
+	*/
+	int maxcol = 0;
+	int cnt = 0;
+	ALLOC(skipcol, ncols);
+	for (j=0; j<ncols; j++) {
+	  col_t *colthis = &info->c[j];
+	  skipcol[j] = true;
+	  if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	    /* Note: We accept the same columns as in ODBc_get_info() just before MakePlotColumns() */
+	    const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	    if (strequ(s, info->odb_lat->name) ||
+		strequ(s, info->odb_lon->name)) {
+	      skipcol[j] = false;
+	      maxcol = j+1;
+	      cnt++;
+	    }
+	    else if (strequ(s, info->odb_color->name)) {
+	      skipcol[j] = false;
+	      maxcol = j+1;
+	    }
+	    else if (warrow && (strequ(s, info->odb_u->name) ||
+				strequ(s, info->odb_v->name))) {
+	      skipcol[j] = false;
+	      maxcol = j+1;
+	    }
+	  }
+	  else if (colthis->kind == 0) {
+	    /* Now not forgetting the nonassociated columns */
+	    skipcol[j] = false;
+	    maxcol = j+1;
+	  }
+	} /* for (j=0; j<ncols; j++) */
+
+	if (cnt >= 2 && maxcol > 0) {
+	  info->ncols_true = ncols_true = maxcol;
+	  info->ncols = ncols = maxcol;
+	  if (_ncols) *_ncols = maxcol;
+	}
+	else {
+	  FREE(skipcol);
+	}
+      }
+
+      res = ODBc_new_res("GetData => res", 
+			 __FILE__, __LINE__,
+			 nrows, ncols, info, row_wise, poolno);
+
+      if (ndyn > 0 && skipcol) {
+	/* Recalculate "ndyn", since "ncols" may have changed */
+	ndyn = 0;
+	for (j=0; j<info->ndyn; j++) {
+	  dyn_t *dyn = &info->dyn[j];
+	  int colid = dyn->colid;
+	  SKIPCOL(colid);
+	  ndyn++;
+	}
+      }
+
+      /* Determine istart & iend */
+      istart = -1;
+      k = 0;
+      for (i=0; i<nrows; i++) {
+	int ii = i+1;
+	if (end_row >= 1 && ii > end_row) break;
+	if (begin_row >= 1 && ii < begin_row) continue;
+	if (istart == -1) istart = i;
+	k++;
+      }
+      if (istart == -1) istart = 0;
+      iend = istart + k;
+
+      /* Update also _nrows */
+      if (_nrows) *_nrows = k;
+
+      if (ndyn > 0) {
+	/* Initialize "$<parent_tblname>.<child_tblname>#" -variables */
+	int nalloc = iend - istart;
+	for (j=0; j<info->ndyn; j++) {
+	  dyn_t *dyn = &info->dyn[j];
+	  int colid = dyn->colid;
+	  col_t *colthis = &info->c[colid];
+	  const char *s = colthis->name;
+	  SKIPCOL(colid);
+	  FREE(dyn->data);
+	  CALLOC(dyn->data, nalloc);
+	  dyn->ndata = nalloc;
+	  colthis->dinp = dyn->data;
+	  colthis->dinp_alloc = false;
+	  colthis->dsym = putsymvec(s, 0, colthis->dinp, nalloc);
+	  if (dyn && dyn->data) {
+	    table_t *tp = dyn->parent;
+	    table_t *tc = dyn->child;
+	    if (tp && tp->idx && tc && tc->idx &&
+		tp->info && tp->info == tc->info) {
+	      info_t *info = tp->info;
+	      (void) DynFill(dyn->data, dyn->ndata,
+			     tp->idx, info->idxlen,
+			     istart, iend, istart);
+	    }
+	  } /* if (dyn && dyn->data) */
+	} /* for (j=0; j<info->ndyn; j++) */
+      }
+
+      CALLOC(colmask, ncols);
+
+      for (j=0; j<ncols; j++) {
+	/* Initial sweep over columns to make sure "dsym"'s are defined */
+	col_t *colthis = &info->c[j];
+	const char *s = colthis->name;
+	SKIPCOL(j);
+	if (colthis->kind == 0 && IS_POOLNO(s)) {
+	  /* This is the current pool number */
+	  double *testvalue = getsymaddr(s);
+	  /* Initialize, if not already available */
+	  if (!testvalue) testvalue = putsym(s, 0);
+	  if (testvalue) *testvalue = poolno;
+	  colthis->dsym = testvalue;
+	  colthis->dinp = NULL;
+	  colthis->dinp_alloc = false;
+	}
+	else if (colthis->kind == 0 && IS_USDDOTHASH(s)) {
+	  /* One of the special "$<parent_tblname>.<child_tblname>#" -variables */
+	  /* "dsym" should already be initialized ; if not then do it ! */
+	  double *testvalue = getsymaddr(s);
+	  /* Initialize, if not already available */
+	  if (!testvalue) {
+	    colthis->dinp = NULL;
+	    colthis->dinp_alloc = false;
+	    testvalue = putsym(s, 0);
+	    if (testvalue) *testvalue = mdi;
+	  }
+	  colthis->dsym = testvalue;
+	  colmask[j] = 1;
+	  continue; 
+	}
+	else if (colthis->kind == 0 && IS_USDHASH(s)) {
+	  /* One of the special '$...#' variables (excluding _POOLNO, covered already above) */
+	  double *testvalue = getsymaddr(s);
+	  /* Initialize, if not already available */
+	  if (!testvalue) testvalue = putsym(s, 0);
+	  if      (IS_(UNIQNUM,s)) _uniqnum = testvalue;
+	  else if (IS_(ROWNUM,s))  _rownum = testvalue;
+	  else if (IS_(COLNUM,s))  _colnum = testvalue;
+	  else if (IS_(NROWS,s))   _nrows = testvalue;
+	  else if (IS_(NCOLS,s))   _ncols = testvalue;
+	  colthis->dsym = testvalue;
+	  colthis->dinp = NULL;
+	  colthis->dinp_alloc = false;
+	}
+	else if (colthis->kind == 0 && IS_DOLLAR(s)) {
+	  /* This is a $-variable */
+	  double *testvalue = getsymaddr(s);
+	  /* Initialize, if not already available (should be available) */
+	  if (!testvalue) testvalue = putsym(s, mdi);
+	  colthis->dsym = testvalue;
+	  colthis->dinp = NULL;
+	  colthis->dinp_alloc = false;
+	}
+	else if (colthis->kind == 0 && IS_HASH(s)) {
+	  /* This is '#table_name' -variable */
+	  double *testvalue = getsymaddr(s);
+	  table_t *tc = colthis->t ? colthis->t : GetTable(info, s);
+	  if (!tc) {
+	    fprintf(stderr,"***Error: Unable to locate table for #-variable '%s'\n",s);
+	    errflg++;
+	  }
+	  else {
+	    colthis->t = tc;
+	  }
+	  /* Initialize, if not already available */
+	  if (!testvalue) testvalue = putsym(s, 0);
+	  colthis->dsym = testvalue;
+	  colthis->dinp = NULL;
+	  colthis->dinp_alloc = false;
+	  colmask[j] = 2;
+	}
+	else if (colthis->kind == 0 || colthis->kind == 1) {
+	  double *testvalue = getsymaddr(s);
+	  table_t *tc = colthis->t ? colthis->t : GetTable(info, s);
+
+	  if (!tc) {
+	    fprintf(stderr,"***Error: Unable to locate table for column '%s'\n",s);
+	    errflg++;
+	  }
+	  else {
+	    colthis->t = tc;
+	  }
+
+	  if (testvalue) {
+	    colthis->dinp = getsymvec(s, &colthis->dinp_len);
+	    colthis->dinp_alloc = false;
+	    colthis->dsym = testvalue;
+	  }
+	  else {
+	    int Nrows;
+	    colthis->dinp = DCA_fetch_double(ph->h, ph->dbname, tc->name, colthis->fetch_name,
+					     poolno, NULL, 0, &Nrows);
+	    if (Nrows != tc->nrows) {
+	      COLUMN_FETCH_ERROR();
+	      errflg++;
+	    }
+	    else {
+	      Bool thesame = strequ(s,colthis->fetch_name) ? true : false;
+	      ODB_fprintf(ODBc_get_debug_fp(),
+			  "  %s:%d: Successfully fetched (double) %s%s%s (Nrows=%d/%d) : poolno#%d\n",
+			  __FILE__, __LINE__,
+			  thesame ? s : colthis->fetch_name,
+			  thesame ? "" : " alias ",
+			  thesame ? (const char *)"" : s,
+			  Nrows, tc->nrows, poolno);
+	      colthis->dinp_len = Nrows;
+	      colthis->dinp_alloc = true;
+	      if (colthis->dtnum == DATATYPE_INT4 && 
+		  colthis->bitpos >= 0 && colthis->bitpos <  MAXBITS &&
+		  colthis->bitlen >= 1 && colthis->bitlen <= MAXBITS) {
+		ODBc_vget_bits(colthis->dinp, colthis->dinp_len, colthis->bitpos, colthis->bitlen);
+	      }
+	      colthis->dsym = putsymvec(s, mdi, colthis->dinp, Nrows);
+	    }
+	  }
+	  colmask[j] = 3;
+	}
+      } /* for (j=0; j<ncols; j++) */
+
+      if (errflg) RAISE(SIGABRT);
+
+      k = 0;
+      for (i=istart; i<iend; i++) {
+	double *dk = row_wise ? &res->d[k][0] : NULL;
+
+	for (j=0; j<ncols; j++) { 
+	  if (colmask[j] > 0) {
+	    /* 1st sweep : assign values to symbol table entries */
+	    col_t *colthis = &info->c[j];
+	    const char *s = colthis->name;
+	    if (colmask[j] == 1) {
+	      /* One of the special "$<parent_tblname>.<child_tblname>#" -variables */
+	      *colthis->dsym = colthis->dinp ? colthis->dinp[i-istart] : mdi;
+	    }
+	    else if (colmask[j] == 2) {
+	      /* This is a '#table_name' -variable */
+	      table_t *tc = colthis->t;
+	      int jr = tc->idx[i];
+	      *colthis->dsym = jr + 1;
+	    }
+	    else if (colmask[j] == 3) {
+	      /* As if (colthis->kind == 0 || colthis->kind == 1) */
+	      table_t *tc = colthis->t;
+	      int jr = tc->idx[i];
+	      if (colthis->dinp && jr >= 0 && jr < tc->nrows) {
+		/* Extra safeguarding */
+		*colthis->dsym = colthis->dinp[jr];
+	      }
+	      else {
+		*colthis->dsym = mdi;
+	      }
+	    }
+	  } /* if (colmask[j] > 0) */
+	} /* for (j=0; j<ncols; j++) */
+
+	if (_rownum) *_rownum = k+1;
+
+	if (_uniqnum) *_uniqnum = ODB_put_one_control_word(k, poolno);
+
+	if (info->has_aggrfuncs) {
+	  /* Note : Aggr_argnO is a macro #define'd in include/evaluate.h !! */
+	  Aggr_argnO = 1; /* Uses *thsp ;
+			     The value "1" means: we return the 1st arg from a multi-argument
+			     aggregate function call (like corr(x,y)), and set this to "2", when 
+			     j >= ncols_true, after which we return the 2nd arg ;
+			     See include/funcs.h and also include/evaluate.h
+			  */
+	}
+
+	for (j=0; j<ncols; j++) {
+	  /* 2nd sweep : evaluate & store data */
+	  col_t *colthis = &info->c[j];
+	  const char *s = colthis->name;
+	  double value = mdi;
+	  SKIPCOL(j);	  
+	  if (_colnum) *_colnum = j+1; /* Live update !! */
+
+	  if (colthis->kind == 1) {
+	    value = *colthis->dsym;
+	  }
+	  else if (colthis->kind == 2) { /* Standard formulas */
+	    int iret = 0;
+	    value = RunTree(colthis->formula_ptree, NULL, &iret);
+	    if (iret != 0) {
+	      fprintf(stderr,
+		      "***Error: Unable to evaluate the column#%d expression '%s'\n",
+		      j+1,s);
+	      RAISE(SIGABRT);
+	    }
+	  }
+	  else if (colthis->kind == 4 || colthis->kind == 8) { /* Aggregate functions */
+	    int iret = 0;
+	    Aggr_argnO = (colthis->kind == 4) ? 1 : 2;
+	    value = RunTree(colthis->formula_ptree, NULL, &iret);
+	    if (iret != 0) {
+	      fprintf(stderr,
+		      "***Error: Unable to evaluate the aggregate column#%d expression '%s'\n",
+		      j+1,s);
+	      RAISE(SIGABRT);
+	    }
+	  }
+	  if (row_wise) dk[j] = value; else res->d[j][k] = value;
+	} /* for (j=0; j<ncols; j++) */
+
+	if (info->has_aggrfuncs) Aggr_argnO = 1;
+
+	++k;
+      } /* for (i=istart; i<iend; i++) */
+
+      res->nrows_out = k;
+      res->ncols_out = ncols_true;
+
+      /* Clean-up */
+
+      FREE(skipcol);
+      FREE(colmask);
+
+      for (j=0; j<info->ndyn; j++) {
+	dyn_t *dyn = &info->dyn[j];
+	FREE(dyn->data);
+	dyn->ndata = 0;
+      } /* for (j=0; j<info->ndyn; j++) */
+
+    } /* if (nrows > 0 && ncols > 0) */
+  } /* if (ph && info) */
+#if 0
+  fprintf(stderr,"res follows ... (at end of GetData)\n");
+  ODBc_print_data(NULL, stderr, res, 
+		  "odb", "-",
+		  0, 1, 0,
+		  NULL);
+#endif
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC void *
+ODBc_get_data(int handle, void *Result, void *Info, int poolno, 
+	      int begin_row, int end_row, 
+	      Bool do_sort, const Bool *row_wise_preference)
+{
+  result_t *res = Result;
+  info_t *info = Info;
+  DRHOOK_START(ODBc_get_data);
+  if (info) {
+    int maxhandle = 0;
+    DB_t *free_handles = ODBc_get_free_handles(&maxhandle);
+    if (free_handles && handle >= 1 && handle <= maxhandle) {
+      DB_t *ph = &free_handles[handle-1];
+      if (ph->h == handle) {
+	int npools = ph->npools;
+	if (poolno >= 1 && poolno <= npools) {
+	  Bool poolno_okay = ODB_in_permanent_poolmask(handle, poolno) ? true : false;
+	  if (poolno_okay) { /* Finally !!! */
+	    result_t *p_res = res;
+	    result_t *thisres = GetData(ph, info, poolno, begin_row, end_row, row_wise_preference);
+	    if (thisres) {
+	      if (info->has_aggrfuncs) {
+		/* Perform phase#0-processing for aggregate functions */
+		thisres = ODBc_aggr(thisres, 0);
+	      }
+	      else if (do_sort && info->norderby > 0) {
+		thisres = ODBc_sort(thisres, NULL, 0);
+	      }
+	      if (p_res) {
+		/* Add to the chain */
+		while (p_res) {
+		  if (p_res->next) {
+		    p_res = p_res->next;
+		  }
+		  else {
+		    p_res->next = thisres;
+		    break;
+		  }
+		} /* while (p_res) */
+	      }
+	      else {
+		res = thisres;
+	      }
+	    } /* if (thisres) */
+	  } /* if (poolno_okay) */
+	} /* if (poolno >= 1 && poolno <= npools) */
+      } /* if (ph->h == handle) */
+    } /* if (free_handles && handle >= 1 && handle <= maxhandle) */
+  } /* if (info) */
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC void *
+ODBc_unget_data(void *Result)
+{
+  DRHOOK_START(ODBc_unget_data);
+  if (Result) {
+    FILE *fp_echo = ODBc_get_debug_fp();
+    int cnt = 0;
+    result_t *res = Result;
+    while (res) {
+      result_t *nextres = res->next;
+      if (res->mem) FREE(res->mem);
+      if (res->d) FREE(res->d);
+      if (res->backup_file) FREE(res->backup_file);
+      ODB_fprintf(fp_echo,"ODBc_unget_data: releasing res @ %p [#%d] : %d %d-byte words\n", 
+		  res, ++cnt, res->nmem, sizeof(*res->mem));
+      FREE(res);
+      res = nextres;
+    } /* while (res) */
+  }
+  DRHOOK_END(0);
+  return NULL;
+}
+
+
+PUBLIC void *
+ODBc_remove_duplicates(void *Result, const int keys[], int n_keys)
+{
+  result_t *res = Result;
+  FILE *fp_echo = ODBc_get_debug_fp();
+  DRHOOK_START(ODBc_remove_duplicates);
+  ODB_fprintf(fp_echo, "ODBc_remove_duplicates(): res @ %p, "
+	      "res->nrows_out = %d, keys @ %p, n_keys = %d\n",
+	      res, res ? res->nrows_out : -1,
+	      keys, n_keys);
+#if 0
+  fprintf(stderr,"n_keys = %d\n",n_keys);
+  fprintf(stderr,"res follows ... (i.e. before sort)\n");
+  ODBc_print_data(NULL, stderr, res, 
+		  "odb", "-",
+		  0, 1, 0,
+		  NULL);
+#endif
+  if (res && res->nrows_out > 0 && keys && n_keys > 0) {
+    /* For now : no checks on keys[]-values */
+    info_t *info = res->info;
+    result_t *r1 = ODBc_sort(res, keys, n_keys); /* result set NOT row_wise */
+    int nrows = r1->nrows_out;
+    int ncols = r1->ncols_out;
+    int poolno = r1->poolno;
+    Bool row_wise = true;
+    result_t *r2 = ODBc_new_res("ODBc_remove_duplicates => r2", 
+				__FILE__, __LINE__,
+				nrows, ncols, info, row_wise, poolno);
+    int i, j;
+    int ngrp = 0;
+    int jj = 0;
+
+#if 0
+    fprintf(stderr,"r1 follows ... (i.e. after sort)\n");
+    ODBc_print_data(NULL, stderr, r1, 
+		    "odb", "-",
+		    0, 1, 0,
+		    NULL);
+#endif
+
+    for (i=0; i<nrows; i++) {
+      Bool changed = (i > 0) ? false : true;
+      
+      for (j=0; j<n_keys && !changed; j++) {
+	int akey = keys[j]-1;
+	double djj = r1->d[akey][jj]; /* this is NOT row_wise */ 
+	double di  = r1->d[akey][i]; /* this is NOT row_wise */
+	if (djj != di) changed = true;
+      } /* for (j=0; j<n_keys; j++) */
+	  
+      if (changed) {
+	jj = i;
+	for (j=0; j<ncols; j++) {
+	  const double *din = &r1->d[j][jj]; /* this is NOT row_wise */
+	  double *dout = &r2->d[ngrp][j]; /* this is indeed row_wise */
+	  *dout = *din;
+	}
+	ngrp++;
+      }
+    } /* for (i=0; i<nrows; i++) */
+
+    r2->nrows_out = ngrp;
+    (void) ODBc_unget_data(r1);
+    res = r2;
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC int
+ODBc_conv2degrees(void *Res, Bool to_degrees)
+{
+  int converted = 0;
+  result_t *res = Res;
+  info_t *info = res ? res->info : NULL;
+  DRHOOK_START(ODBc_conv2degrees);
+  if (res && info && info->c &&
+      info->odb_lat && info->odb_lon) {
+    int j;
+    int nrows = res->nrows_out;
+    int ncols = res->ncols_out;
+    Bool row_wise = res->row_wise;
+    Bool *do_this_col = NULL;
+    ALLOCX(do_this_col,ncols);
+    for (j=0; j<ncols; j++) {
+      col_t *colthis = &info->c[j];
+      do_this_col[j] = false;
+      if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	if (strequ(s, info->odb_lat->name) || strequ(s, info->odb_lon->name)) {
+	  do_this_col[j] = true;
+	  converted++;
+	}
+      }
+    } /* for (j=0; j<ncols; j++) */
+
+    if (converted == 2) {
+      /* Make sure the conversion is needed by looking at the
+	 prevailing latlon_rad -value that will be used in lldegrees/llradians -funcs */
+      /* -- See lib/funcs.c for more:
+	 latlon_rad =  1 --> values were originally in radians
+	 latlon_rad =  0 --> values were originally in degrees
+	   [Note: we don't allow to going back to radians, if the original was in degrees!!]
+	 latlon_rad = -1 --> don't know what they were [shouldn't happen]
+	 latlon_rad = -2 --> latlon_rad wasn't initialized [shouldn't happen either]
+      */
+      int latlon_rad = codb_change_latlon_rad_(NULL);
+      if (latlon_rad == 0) {
+	/* Already in degrees --> conversion to degrees abandoned */
+	/* Also "back"-conversion to radians ignored; see the note above */
+	converted = 0;
+      }
+      /* So we convert to degrees, if latlon_rad != 0, and
+	 we "back"-convert to radians,  if latlon_rad != 0. Finally correct ? */
+    }
+
+    if (converted == 2) {
+      for (j=0; j<ncols; j++) {
+	if (do_this_col[j]) {
+	  int i;
+	  for (i=0; i<nrows; i++) {
+	    double value = row_wise ? res->d[i][j] : res->d[j][i];
+	    value = to_degrees ? ODB_lldegrees(value) : ODB_llradians(value);
+	    if (row_wise)  res->d[i][j] = value; else res->d[j][i] = value;
+	  } /* for (i=0; i<nrows; i++) */
+	} /* if (do_this_col[j]) */
+      } /* for (j=0; j<ncols; j++) */
+    } /* if (converted) */
+    FREEX(do_this_col);
+  }
+  DRHOOK_END(0);
+  return (converted == 2) ? 1 : 0;
+}
+
+
+PRIVATE char *
+GetColArrayBaseName(const col_t *col)
+{
+  /* Get the "column array" basename e.g. for satname[1:4] = {satname_1,satname_2,satname_3,satname_4} 
+     it will be "satname_" as it would for satname[-2:1] = { satname__2,satname__1,satname_0,satname_1}.
+     This infor is used when "joinstr" condition is on to compare consecutive
+     common base prefixes (like "satname_" followed by a number) */
+
+  char *basename = NULL;
+  if (col) {
+    char *last_uscore = NULL;
+    const char *nick = col->nickname ? col->nickname : col->name;
+    char *thisnick = STRDUP(nick);
+    char *first_at = strchr(thisnick, '@');
+
+    if (first_at) *first_at = '\0';
+    last_uscore = strrchr(thisnick,'_');
+    
+    if (last_uscore) {
+      /* Check that the rest of the string, after last '_', is digital */
+      int is_digital = 1;
+      char *x = last_uscore;
+      while (is_digital && *++x) is_digital = isdigit(*x);
+      if (!is_digital) last_uscore = NULL;
+    }
+    
+    if (last_uscore) {
+      /* May not be yet exactly right; f.ex. x[-1:+1] = {x__1, x_0, x_1} --> make it right */
+      if (last_uscore != thisnick && last_uscore[-1] == '_') --last_uscore;
+      last_uscore[1] = '\0';
+      basename = STRDUP(thisnick);
+    }
+
+    FREE(thisnick);
+  } /* if (col) */
+  return basename;
+}
+
+#define PRINT_STRING(prt_func, v) \
+{ \
+  char cc[sizeof(double)+1]; \
+  char *scc = cc; \
+  union { \
+    char s[sizeof(double)]; \
+    double d; \
+  } u; \
+  u.d = v; \
+  for (js=0; js<sizeof(double); js++) { \
+    char c = u.s[js]; \
+    *scc++ = isprint(c) ? c : (is_odb ? '?' : ' '); \
+  } /* for (js=0; js<sizeof(double); js++) */ \
+  *scc = '\0'; \
+  prt_func(fp,"%s",cc); \
+}
+
+#if 0
+: 2 1 2524
+: VIEW="myview" on 20061107 at 114223
+: Pool#1: no. of rows x cols = 2524 x 2
+:                   lat                   lon
+:                  @hdr                  @hdr
+:                  ====                  ====
+#endif
+
+PRIVATE void *
+PrintData(const char *filename, FILE *fp, void *Result, 
+	  const char *format, const char *fmt_string, 
+	  int konvert, int write_title, int joinstr,
+	  int the_first_print, int the_final_print, 
+	  int *iret)
+{
+  result_t *res = Result;
+  info_t *info = res ? res->info : NULL;
+  int rc = 0;
+  DRHOOK_START(PrintData);
+  if (fp && info && res && res->mem && res->d) {
+    FILE *fp_echo = ODBc_get_debug_fp();
+    int i, j;
+    char *env;
+    Bool is_default = (!format || strequ(format,"default")) ? true : false;
+    Bool is_dump    = strequ(format,"dump") ? true : false;
+    Bool is_bindump = strequ(format,"bindump") ? true : false;
+    Bool is_binary  = ODBc_test_format_2(format,"binary");
+    Bool is_odbtk   = ODBc_test_format_2(format,"odbtk");
+    Bool is_odb     = ODBc_test_format_2(format,"odb");
+    Bool is_odbtool = ODBc_test_format_2(format,"odbtool");
+    Bool is_plotobs = ODBc_test_format_2(format,"plotobs");
+    Bool warrow = ODBc_test_format_2(format,"wplotobs");
+    Bool is_netcdf = ODBc_test_format_2(format,"netcdf");
+    int geofmt = GeoFormat();
+    Bool print_mdi = true;
+    const char *delim = (is_odbtk ? "!,!" : (is_dump ? "," : " "));
+    const char *Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+    int poolno = res->poolno;
+    int nrows = res->nrows_out;
+    int ncols = res->ncols_out;
+    int row_wise = res->row_wise ? 1 : 0;
+    int resdate, restime;
+    int *width = NULL;
+    int ndigits = log10(MAX(1,info->npools)) + 1; /* ~ digits in "npools" */
+
+    env = getenv("ODB_PRINT_MDI");
+    if (env) {
+      int value = atoi(env);
+      print_mdi = (value != 0) ? true : false;
+    }
+
+    (void) odb_datetime_(&resdate, &restime);
+
+    if (is_dump) is_default = true;
+    if (is_bindump) is_binary = true;
+
+    if (konvert) konvert = (is_plotobs || warrow || is_odbtool || geofmt || is_netcdf) ? 
+		   0 : ODBc_conv2degrees(res, true);
+    if (joinstr && !is_default) joinstr = 0;
+
+    if (is_odbtool) {
+      (void) ODBc_ODBtool(fp, NULL, NULL, false, res, info);
+      goto finish;
+    }
+    else if (is_netcdf) {
+      double *d = res->mem;
+      int nra = res->nra;
+      uint *dtnum = NULL;
+      int len_ODB_tag_delim = STRLEN(ODB_tag_delim); /* ODB_tag_delim from "privpub.h" */
+      char *odb_type_tag = NULL; int len_odb_type_tag = len_ODB_tag_delim + 1;
+      char *odb_name_tag = NULL; int len_odb_name_tag = len_ODB_tag_delim + 1;
+      char *odb_nickname_tag = NULL; int len_odb_nickname_tag = len_ODB_tag_delim + 1;
+
+      konvert = ODBc_conv2degrees(res, true); /* Convert to degrees, if applicable */
+
+      ODB_fprintf(fp_echo,
+		  "is_netcdf: row_wise=%d, nra=%d, nrows=%d, ncols=%d, poolno=%d, "
+		  "nrows_in=%d, ncols_in=%d, res->next=%p, konvert=%d\n",
+		  row_wise, nra, nrows, ncols, poolno,
+		  res->nrows_in, res->nrows_out, res->next, konvert);
+
+      CALLOC(dtnum, ncols);
+      
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	const char *type = colthis->dtype;
+	const char *name = colthis->name;
+	const char *nickname = colthis->nickname ? colthis->nickname : colthis->name;
+	len_odb_type_tag += STRLEN(type) + len_ODB_tag_delim;
+	len_odb_name_tag += STRLEN(name) + len_ODB_tag_delim;
+	len_odb_nickname_tag += STRLEN(nickname) + len_ODB_tag_delim;
+	dtnum[j] = colthis->dtnum;
+      }
+
+      ALLOCX(odb_type_tag, len_odb_type_tag); strcpy(odb_type_tag,ODB_tag_delim);
+      ALLOCX(odb_name_tag, len_odb_name_tag); strcpy(odb_name_tag,ODB_tag_delim);
+      ALLOCX(odb_nickname_tag, len_odb_nickname_tag); strcpy(odb_nickname_tag,ODB_tag_delim);
+
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	const char *type = colthis->dtype;
+	const char *name = colthis->name;
+	const char *nickname = colthis->nickname ? colthis->nickname : colthis->name;
+	strcat(odb_type_tag,type); strcat(odb_type_tag,ODB_tag_delim);
+	strcat(odb_name_tag,name); strcat(odb_name_tag,ODB_tag_delim);
+	strcat(odb_nickname_tag,nickname); strcat(odb_nickname_tag,ODB_tag_delim);
+      }
+
+      {
+	const char *sql_query = ODBc_get_sql_query(info);
+	const char search_str[] = "The original query follows\n\n";
+	const char *matched = strstr(sql_query, search_str);
+	const char title_fmt[] = "Database schema in %s/%s.sch ; Viewname=%s ; pool#%d";
+	char *title = NULL;
+	const char ncfile_fmt[] = "%s.nc";
+	char *ncfile = NULL;
+	char *viewname = NULL;
+	const char namecfg[] = "/dev/null";
+	int len;
+
+	if (filename) {
+	  char *pdot;
+	  char *pslash = strrchr(filename,'/');
+	  viewname = pslash ? STRDUP(pslash+1) : STRDUP(filename);
+	  pdot = strchr(viewname, '.');
+	  if (pdot) *pdot = '\0';
+	  ncfile = STRDUP(filename);
+	}
+	else {
+	  viewname = STRDUP(info->view);
+	  len = STRLEN(ncfile_fmt) + STRLEN(viewname) + 20;
+	  ALLOC(ncfile, len);
+	  snprintf(ncfile, len, ncfile_fmt, viewname);
+	}
+
+	len = STRLEN(title_fmt) + 
+	  STRLEN(info->dbcred.srcpath) + 
+	  STRLEN(info->dbcred.dbname) + 
+	  STRLEN(viewname) + 50;
+	ALLOCX(title, len);
+	snprintf(title, len, title_fmt, 
+		 info->dbcred.srcpath ? info->dbcred.srcpath : "???",
+		 info->dbcred.dbname ? info->dbcred.dbname : "???",
+		 viewname,
+		 poolno);
+
+	if (matched) sql_query = matched + STRLEN(search_str);
+
+	codb2netcdf_(title, ncfile, namecfg, sql_query,
+		     d, &nra, &nrows, &ncols,
+		     dtnum, &poolno,
+		     odb_type_tag, odb_name_tag, odb_nickname_tag
+		     /* Hidden arguments */
+		     , STRLEN(title)
+		     , STRLEN(ncfile)
+		     , STRLEN(namecfg)
+		     , STRLEN(sql_query)
+		     , STRLEN(odb_type_tag)
+		     , STRLEN(odb_name_tag)
+		     , STRLEN(odb_nickname_tag)
+		     );
+	
+	FREEX(title);
+	FREE(viewname);
+	FREE(ncfile);
+      }
+
+      FREEX(odb_nickname_tag);
+      FREEX(odb_name_tag);
+      FREEX(odb_type_tag);
+
+      FREE(dtnum);
+      goto finish;
+    }
+    else if (is_binary) {
+      int yyyymmdd;
+      int hhmmss; /* analysis date & time */
+      codb_analysis_datetime_(&yyyymmdd, &hhmmss);
+
+      if (is_bindump) {
+	ll_t nbytes = (ll_t) nrows * ncols * sizeof(double);
+	extern int ec_is_little_endian();
+	int i_am_little = ec_is_little_endian();
+
+	char *pq, *query = NULL;
+	const char *sql_query = info->sql_query;
+	const char search_str[] = "The original query follows\n\n";
+	const char *matched = strstr(sql_query, search_str);
+	if (matched) sql_query = matched + STRLEN(search_str);
+
+	query = STRDUP(sql_query);
+	pq = query - 1;
+	while (*++pq) {
+	  if (isspace(*pq) || !isprint(*pq)) *pq = ' ';
+	}
+
+	/* -f bindump dumps the title-structure (text-format) even if it is not requested */
+
+	if (the_first_print) {
+	  int jj = 0;
+	  fprintf(fp,"ODB binary data dump created on %8.8d at %6.6d\n", resdate, restime);
+	  fprintf(fp,"\ntitle = {\n");
+	  fprintf(fp," // column_number %s type_name %s column_name %s table_name %s\n",
+		  ODB_tag_delim, ODB_tag_delim, ODB_tag_delim, ODB_tag_delim);
+	  for (j=0; j<ncols; j++) {
+	    col_t *colthis = &info->c[j];
+	    if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	      const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	      const table_t *tc = colthis->t;
+	      const char *st = (colthis->kind == 1) ? tc->name : "Formula";
+	      const char *dtype = colthis->dtype;
+	      fprintf(fp, "\t%d %s %s %s %s %s %s %s\n",
+		      ++jj, ODB_tag_delim,
+		      dtype, ODB_tag_delim,
+		      s, ODB_tag_delim,
+		      st, ODB_tag_delim);
+	    }
+	  } /* for (j=0; j<ncols; j++) */
+	  fprintf(fp,"};\n");
+	}
+
+	fprintf(fp,"\nmetadata = {\n");
+	fprintf(fp,"\tpool_number = %d\n", poolno);
+	fprintf(fp,"\tnumber_of_rows = %d\n", nrows);
+	fprintf(fp,"\tnumber_of_columns = %d\n", ncols);
+	fprintf(fp,"\tnumber_of_data_bytes = %lld\n", nbytes);
+	fprintf(fp,"\tdata_endianess = %s_endian\n",i_am_little ? "little" : "big");
+
+	if (the_first_print) {
+	  fprintf(fp,"\tanalysis_date = %8.8d\n", yyyymmdd);
+	  fprintf(fp,"\tanalysis_time = %6.6d\n", hhmmss);
+	  fprintf(fp,"\tdata_query = %s\n", query); FREE(query);
+	  fprintf(fp,"\tdatabase = %s\n",info->dbcred.dbname);
+	  if (info->dbcred.srcpath)  fprintf(fp,"\tdatabase_srcpath = %s\n", info->dbcred.srcpath);
+	  if (info->dbcred.datapath) fprintf(fp,"\tdatabase_datapath = %s\n", info->dbcred.datapath);
+	  if (info->dbcred.idxpath)  fprintf(fp,"\tdatabase_idxpath = %s\n", info->dbcred.idxpath);
+	  fprintf(fp,"\tpoolmask = %s\n", info->dbcred.poolmask ? info->dbcred.poolmask : "-1");
+	  fprintf(fp,"\tlatlon_output_in_degrees = %s\n", 
+		  (info->latlon_rad == 0 || konvert) ? 
+		  "yes" : ((info->latlon_rad == 1) ? "no" : "unknown"));
+	} /* if (the_first_print) */
+
+	fprintf(fp,"};\n");
+
+	/* Note: 
+	   The data section for this pool starts after the form-feed character ('\f') has been found 
+	   and it will be nrows x ncols x sizeof(double) -bytes long 
+	 */
+
+	fprintf(fp,fp_echo ? "\n" : "\f");
+
+	/* bindump also is always row_wise (even is res->row_wise indicates otherwise) */
+	if (!row_wise) { /* Was column-wise (Fortran) */
+	  /* Note: we enforce row-wise output */
+	  result_t *newres = ODBc_merge_res("PrintData [is_bindump] => newres",
+					    __FILE__, __LINE__,
+					    res, ncols, info, true);
+	  res = newres;
+	  row_wise = true;
+	}
+
+	/* Now always row-wise (C) */
+
+	if (fp_echo) {
+	  /* Note: when debugging output is on, the data will be printed in text-mode */
+	  fprintf(fp, 
+		  "<The following %d lines (%d columns) are normally printed in a binary %s-endian mode"
+		  " and would contain %lld bytes of data>\n",
+		  nrows, ncols,
+		  i_am_little ? "little" : "big",
+		  nbytes);
+	  for (i=0; i<nrows; i++) {
+	    const double *value = &res->d[i][0];
+	    for (j=0; j<ncols; j++) {
+	      col_t *colthis = &info->c[j];
+	      if (print_mdi && colthis->dtnum != DATATYPE_STRING && ABS(value[j]) == mdi) {
+		fprintf(fp, "NULL");
+	      }
+	      else {
+		switch (colthis->dtnum) {
+		case DATATYPE_STRING:
+		  {
+		    int js;
+		    fprintf(fp, "'");
+		    PRINT_STRING(fprintf, value[j]);
+		    fprintf(fp, "'");
+		  }
+		  break;
+		case DATATYPE_YYYYMMDD:
+		  fprintf(fp, "%8.8d", (int)value[j]);
+		  break;
+		case DATATYPE_HHMMSS:
+		  fprintf(fp, "%6.6d", (int)value[j]);
+		  break;
+		default:
+		  fprintf(fp, "%.14g", value[j]);
+		  break;
+		}
+	      }
+	      fprintf(fp, "%c", (j < ncols-1) ? ',' : '\n');
+	    } /* for (j=0; j<ncols; j++) */
+	  } /* for (i=0; i<nrows; i++) */
+	}
+	else {
+	  for (i=0; i<nrows; i++) {
+	    const double *value = &res->d[i][0];
+	    (void) fwrite(value, sizeof(*value), ncols, fp);
+	  } /* for (i=0; i<nrows; i++) */
+	}
+      }
+      else { /* !is_bindump */
+	const int nhdr = 13;
+	const int nversion = 1;
+	const int double_precision = 1; /* 1 = values in double precision , 0 = in float, single prec. */
+	int *hdr = NULL;
+	ALLOCX(hdr, nhdr);
+	hdr[0] = ODBX;
+	hdr[1] = nhdr;
+	hdr[2] = nversion;
+	hdr[3] = resdate;
+	hdr[4] = restime;
+	hdr[5] = poolno;
+	hdr[6] = nrows;
+	hdr[7] = ncols;
+	hdr[8] = row_wise;
+	hdr[9] = double_precision;
+	hdr[10] = konvert;
+	hdr[11] = yyyymmdd;
+	hdr[12] = hhmmss;
+	(void) fwrite(hdr, sizeof(*hdr), 2, fp);
+	(void) fwrite(hdr+2, sizeof(*hdr), nhdr-2, fp);
+	if (row_wise) { /* Row-wise (C) */
+	  for (i=0; i<nrows; i++) {
+	    const double *value = &res->d[i][0];
+	    (void) fwrite(value, sizeof(*value), ncols, fp);
+	  } /* for (i=0; i<nrows; i++) */
+	}
+	else { /* Column-wise (Fortran) */
+	  for (i=0; i<ncols; i++) {
+	    const double *value = &res->d[i][0];
+	    (void) fwrite(value, sizeof(*value), nrows, fp);
+	  } /* for (i=0; i<ncols; i++) */
+	}
+	FREEX(hdr);
+      }
+      goto finish;
+    }
+    else if (is_plotobs || warrow) {
+      /* Write for plotobs.x -executable */
+      /* This will re-allocate the "res" */
+      const int iswp1234 = 1234;
+      float scale[6] = { 0 };
+      float value_min = 0, value_max = 0;
+      int iscale = 1;
+      int nobs, nobs_actual;
+      int latcol, loncol, colorcol;
+      int ucol, vcol;
+      int k, targetcols[5];
+      int nt;
+      Bool pseudo_color = false;
+      const char *prefix = warrow ? "warrow" : "is_plotobs";
+      char text1[80+1],text2[80+1],text3[80+1];
+      char user_text[256+1];
+      Bool cmap_ok = ODBc_get_kolor_map(&value_min, &value_max, scale, text3, sizeof(text3));
+      
+      {
+	char *dbname = STRDUP(info->dbcred.dbname);
+	char *last_slash = strrchr(dbname,'/');
+	char *last_dot = strrchr(dbname,'/');
+	char *p = NULL;
+	int len;
+	if (last_slash) {
+	  *last_slash = '\0';
+	  p = ++last_slash;
+	}
+	if (last_dot) *last_dot = '\0';
+	if (p) {
+	  FREE(dbname);
+	  dbname = STRDUP(p);
+	}
+	snprintf(text1,80,"ODB database : %s       Query: %s", dbname, info->view);
+	len = STRLEN(text1);
+	memset(text1+len,' ',80-len);
+	text1[80] = '\0';
+	FREE(dbname);
+      }
+      
+      memset(text2,' ',80); text2[80] = '\0'; /* Filled/used by Plotobs.F90 */
+      if (cmap_ok) {
+	iscale = (int)scale[0];
+      }
+      else {
+	memset(text3,' ',80);
+      }
+      text3[80] = '\0';
+
+      latcol = -1;
+      loncol = -1;
+      colorcol = -1;
+      ucol = vcol = -1;
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	  const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	  if (strequ(s, info->odb_lat->name)) latcol = j;
+	  else if (strequ(s, info->odb_lon->name)) loncol = j;
+	  else if (strequ(s, info->odb_color->name)) colorcol = j;
+	  else if (warrow && strequ(s, info->odb_u->name)) ucol = j;
+	  else if (warrow && strequ(s, info->odb_v->name)) vcol = j;
+	}
+      }
+
+      if (warrow && (ucol == -1 || vcol == -1)) {
+	ucol = vcol = -1;
+	warrow = false;
+	ODBc_set_format("plotobs");
+      }
+
+      targetcols[0] = latcol;
+      targetcols[1] = loncol;
+      if (warrow) {
+	targetcols[2] = ucol;
+	targetcols[3] = vcol;
+	targetcols[4] = colorcol;
+	nt = (colorcol == -1) ? 4 : 5;
+	if (nt == 4) pseudo_color = true; /* Calculate & put wind-speed to the 5th column */
+      }
+      else {
+	targetcols[2] = colorcol;
+	targetcols[3] = -1;
+	targetcols[4] = -1;
+	nt = 3;
+      }
+
+      ODB_fprintf(fp_echo,"%s: poolno=%d, nrows=%d, ncols=%d\n", 
+		  prefix, poolno, nrows, ncols);
+      ODB_fprintf(fp_echo,"%s: latcol=%d, loncol=%d, colorcol=%d, ucol=%d, vcol=%d\n", 
+		  prefix, latcol, loncol, colorcol, ucol, vcol);
+
+      if (latcol == -1 || loncol == -1) {
+	nobs = 0;
+      }
+      else {
+	konvert = ODBc_conv2degrees(res, true); /* Convert to degrees, if applicable */
+	if (!info->has_select_distinct) {
+	  /* Remove duplicate (lat,lon)'s -- basically per pool to keep it cheap */
+	  const int n_keys = 2;
+	  int keys[2];
+	  keys[0] = latcol + 1;
+	  keys[1] = loncol + 1;
+	  res = ODBc_remove_duplicates(res, keys, n_keys);
+	}
+	nobs = res->nrows_out;
+      }
+
+      fwrite(&iswp1234, sizeof(iswp1234), 1, fp);
+
+      res->nrows_out = nobs; /* this many useful rows left !! */
+      fwrite(&nobs, sizeof(int), 1, fp);
+      nobs_actual = nrows;
+      fwrite(&nobs_actual, sizeof(int), 1, fp);
+
+      ODB_fprintf(fp_echo,"%s: nobs=%d, nobs_actual=%d\n",
+		  prefix,nobs,nobs_actual);
+
+      fwrite(text1, sizeof(char), 80, fp);
+      fwrite(text2, sizeof(char), 80, fp);
+      fwrite(text3, sizeof(char), 80, fp);
+
+      fwrite(&value_min, sizeof(float), 1, fp);
+      fwrite(&value_max, sizeof(float), 1, fp);
+      fwrite(&iscale, sizeof(int), 1, fp);
+      fwrite(&scale[1], sizeof(float), 5, fp);
+
+      memset(user_text, ' ', 256);
+      if (info->dbcred.dbname) {
+	int len = STRLEN(info->dbcred.dbname);
+	len = MIN(len, 256);
+	strncpy(user_text, info->dbcred.dbname, len);
+      }
+      else {
+	getcwd(user_text,sizeof(user_text));
+      }
+      user_text[256] = '\0';
+      fwrite(user_text, sizeof(char), 256, fp);
+
+      if (nobs > 0) {
+	float *f = NULL;
+	ALLOC(f, nobs);
+	for (k=0; k<nt; k++) {
+	  j = targetcols[k];
+	  ODB_fprintf(fp_echo,"%s: targetcols[%d] = %d (j=%d)\n",prefix,k,targetcols[k],j);
+	  if (j >= 0 && j<ncols) {
+	    for (i=0; i<nobs; i++) {
+	      double value = res->row_wise ? res->d[i][j] : res->d[j][i];
+	      f[i] = (float)value; /* May potentially cause a SIGFPE */
+	    } /* for (i=0; i<nobs; i++) */
+	  }
+	  else {
+	    memset(f, 0, nobs*sizeof(*f));
+	  }
+	  {
+	    int nelem = fwrite(f, sizeof(*f), nobs, fp);
+	    ODB_fprintf(fp_echo,"%s: nelem's from fwrite = %d\n",prefix,nelem);
+	  }
+	} /* for (k=0; k<nt; k++) */
+	if (warrow && pseudo_color) {
+	  ODB_fprintf(fp_echo,"%s: Applying wind-speed as pseudo-color\n",prefix);
+	  for (i=0; i<nobs; i++) {
+	    double u = res->row_wise ? res->d[i][ucol] : res->d[ucol][i];
+	    double v = res->row_wise ? res->d[i][vcol] : res->d[vcol][i];
+	    double value = ODB_speed(u,v);
+	    f[i] = (float)value; /* May potentially cause a SIGFPE */
+	  }
+	  {
+	    int nelem = fwrite(f, sizeof(*f), nobs, fp);
+	    ODB_fprintf(fp_echo,"%s: nelem's from fwrite = %d (pseudo-color)\n",prefix,nelem);
+	  }
+	}
+	FREE(f);
+      }
+      /* Re-adjust "nrows" for return code (rc) */
+      nrows = nobs;
+      goto finish;
+    }
+    
+    if (is_odb) {
+      ODB_fprintf(fp,": %d %d %d\n",ncols,poolno,nrows);
+      ODB_fprintf(fp,": VIEW=\"%s\" on %8.8d at %6.6d\n",info->view,resdate,restime);
+      ODB_fprintf(fp,": Pool#%d: no. of rows x cols = %d x %d\n",poolno,nrows,ncols);
+    }
+    else if (geofmt) {
+      write_title = 0;
+      ODB_fprintf(fp,"#GEO\n");
+      konvert = ODBc_conv2degrees(res, true); /* Convert to degrees, if applicable */
+    }
+      
+    ALLOCX(width, ncols);
+
+    /* Write the pure name and determine max width per column */
+    if (write_title && is_odb) {
+      ODB_fprintf(fp,":");
+    }
+    else if (write_title && is_odbtk) {
+      ODB_fprintf(fp,"%sUniqueID%sPoolNum%sRowIndex",Delim,delim,delim);
+    }
+
+    Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+    for (j=0; j<ncols; j++) {
+      col_t *colthis = &info->c[j];
+      if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	const table_t *tc = colthis->t;
+	const char *st = (colthis->kind == 1) ? tc->name : "Formula";
+	const char *dtype = colthis->dtype;
+	int w, ws, wt, wd;
+	char *sc = STRDUP(s); /* Pure column name */
+	if (colthis->kind == 1) { /* A regular column variable */
+	  char *p_at = strchr(sc, '@');
+	  if (p_at) { *p_at = '\0'; }
+	}
+	ws = STRLEN(sc);
+	wt = 1 + STRLEN(st); /* "1 + " due to '@' */
+	wd = STRLEN(dtype);
+	w = MAX(ws, wt);
+	w = MAX(w, wd);
+	w = MAX(4,w); /* To accomodate the "NULL" string at least */
+	switch (colthis->dtnum) {
+	case DATATYPE_UINT8: w = MAX(w, ndigits+12); break;
+	case DATATYPE_INT4: w = MAX(w, 12); break;
+	case DATATYPE_BITFIELD: w = MAX(w, MAXBITS); break;
+	case DATATYPE_YYYYMMDD: w = MAX(w, 8); break;
+	case DATATYPE_HHMMSS: w = MAX(w, 6); break;
+	case DATATYPE_BUFR:
+	case DATATYPE_GRIB: w = MAX(w, 10); break;
+	case DATATYPE_STRING: w = MAX(w, 10); break;
+	default: w = MAX(w,21); break;
+	} /* switch (colthis->dtnum) */
+	width[j] = w;
+	if (write_title) {
+	  if (is_odb) {
+	    ODB_fprintf(fp,"%s%*.*s", Delim, w, w, sc);
+	  }
+	  else /* if (is_odbtk || is_default) */ {
+	    ODB_fprintf(fp,"%s%s%s%s", Delim, 
+			is_dump ? dtype : "", 
+			is_dump ? ":" : "", 
+			s);
+	  }
+	}
+	FREE(sc);
+      }
+      else {
+	width[j] = 0;
+      }
+      Delim = delim;
+    } /* for (j=0; j<ncols; j++) */
+
+    if (write_title) ODB_fprintf(fp,"\n");
+
+    Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+    if (write_title && is_odb) {
+      /* Write the table name for each column */
+      Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+      ODB_fprintf(fp,":");
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	  const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	  const table_t *tc = colthis->t;
+	  const char *st = (colthis->kind == 1) ? tc->name : "Formula";
+	  int wt = STRLEN(st);
+	  int w = width[j] - 1; /* "-1" for '@' */
+	  int wspaces = w - wt;
+	  int js;
+	  ODB_fprintf(fp,"%s",Delim);
+	  for (js=0; js<wspaces; js++) ODB_fprintf(fp," ");
+	  ODB_fprintf(fp,"@%s", st);
+	  Delim = delim;
+	}
+      }
+      ODB_fprintf(fp,"\n");
+
+      /* Write the "====" for each column */
+      Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+      ODB_fprintf(fp,":");
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	if (colthis->kind == 1 || colthis->kind == 2 || colthis->kind == 4) {
+	  const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	  const table_t *tc = colthis->t;
+	  const char *st = (colthis->kind == 1) ? tc->name : "Formula";
+	  int js, w, ws, wt, wspaces;
+	  char *sc = STRDUP(s); /* Pure column name */
+	  if (colthis->kind == 1) { /* A regular column variable */
+	    char *p_at = strchr(sc, '@');
+	    if (p_at) { *p_at = '\0'; }
+	  }
+	  ws = STRLEN(sc);
+	  wt = 1 + STRLEN(st); /* "1 + " due to '@' */
+	  w = MAX(ws,wt);
+	  wspaces = width[j] - w;
+	  ODB_fprintf(fp,"%s",Delim);
+	  for (js=0; js<wspaces; js++) ODB_fprintf(fp," ");
+	  for (js=wspaces; js<width[j]; js++) ODB_fprintf(fp,"=");
+	  FREE(sc);
+	}
+	Delim = delim;
+      }
+      ODB_fprintf(fp,"\n");
+    } /* if (write_title && is_odb) */
+    else if (write_title && is_odbtk) {
+      Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+      ODB_fprintf(fp,"%s========%s=======%s========",Delim,delim,delim);
+      for (j=0; j<ncols; j++) {
+	const col_t *colthis = &info->c[j];
+	const char *dtype = colthis->dtype;
+	ODB_fprintf(fp,"%s%s",Delim,dtype);
+	Delim = delim;
+      }      
+      ODB_fprintf(fp,"\n");
+    } /* else if (write_title && is_odbtk) */
+
+    if (geofmt) {
+      /* For MetView GEO-points formats only */
+      switch (geofmt) {
+      case 1 : 
+	ODB_fprintf(fp,"# lat      long       level          date      time        value\n");
+	break;
+      case 2 : 
+	ODB_fprintf(fp,"# x/long       y/lat       value\n");
+	ODB_fprintf(fp,"#FORMAT XYV\n");
+	break;
+      case 3 :
+	ODB_fprintf(fp,"# lat        lon height      date        time        u       v\n");
+	ODB_fprintf(fp,"#FORMAT XY_VECTOR\n");
+	break;
+      case 4 :
+	ODB_fprintf(fp,"# lat        lon     height      date        time        speed   direction\n");
+	ODB_fprintf(fp,"#FORMAT POLAR_VECTOR\n");
+	break;
+      }
+      ODB_fprintf(fp,"#DATA\n");
+    }
+
+    /* Print data itself */
+
+    for (i=0; i<nrows; i++) {
+
+      Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+
+      if (is_odb) {
+	ODB_fprintf(fp,"%s",Delim);
+      }
+      else if (is_odbtk) {
+	double value = ODB_put_one_control_word(i, poolno);
+	union { 
+	  u_ll_t llu;
+	  double d;
+	} u;
+	u.d = value;
+	ODB_fprintf(fp,"%s%llu%s%d%s%d", Delim, u.llu, delim, poolno, delim, i+1);
+      }
+      else if (geofmt) {
+	/* If any of the values to be printed is missing data, then skip this row.
+	   Checking done in reverse order for speed (usually a higher probability for a match) */
+	Bool is_mdi = false;
+	for (j=ncols-1; j>=0; j--) {
+	  double value = res->row_wise ? res->d[i][j] : res->d[j][i];
+	  if (ABS(value) == mdi) {
+	    is_mdi = true;
+	    break;
+	  }
+	}
+	if (is_mdi) continue; /* for (i=0; i<nrows; i++) */
+      }
+
+      Delim = is_dump ? (const char *)"" : delim; /* The actual delimiter used */
+      for (j=0; j<ncols; j++) {
+	col_t *colthis = &info->c[j];
+	double value = res->row_wise ? res->d[i][j] : res->d[j][i];
+	int w = width[j];
+	if (!geofmt && print_mdi && colthis->dtnum != DATATYPE_STRING && ABS(value) == mdi) {
+	  if (is_odb) {
+	    ODB_fprintf(fp,"%s%*.*s",Delim,w,w,"NULL");
+	  }
+	  else /* if (is_odbtk || is_default) */ {
+	    ODB_fprintf(fp,"%sNULL", Delim);
+	  }
+	}
+	else {
+	  switch (colthis->dtnum) {
+	  case DATATYPE_UINT8: 
+	    {
+	      union { 
+		u_ll_t llu;
+		double d;
+	      } u;
+	      u.d = value;
+	      if (is_odb) {
+		ODB_fprintf(fp,"%s%*llu", Delim, w, u.llu);
+	      }
+	      else /* if (is_odbtk || is_default) */ {
+		ODB_fprintf(fp,"%s%llu", Delim, u.llu);
+	      }
+	    }
+	  case DATATYPE_INT4:
+	    if (is_odb) {
+	      ODB_fprintf(fp,"%s%*d", Delim, w, (int) value);
+	    }
+	    else {
+	      ODB_fprintf(fp,"%s%d", Delim, (int) value);
+	    }
+	    break;
+	  case DATATYPE_YYYYMMDD:
+	    if (is_odb) {
+	      ODB_fprintf(fp,"%s%*.8d", Delim, w, (int) value);
+	    }
+	    else {
+	      ODB_fprintf(fp,"%s%8.8d", Delim, (int) value);
+	    }
+	    break;
+	  case DATATYPE_HHMMSS:
+	    if (is_odb) {
+	      ODB_fprintf(fp,"%s%*.6d", Delim, w, (int) value);
+	    }
+	    else {
+	      int theval = (int)value;
+	      if (geofmt) theval /= 100;
+	      ODB_fprintf(fp,geofmt ? "%s%4.4d" : "%s%6.6d", Delim, theval);
+	    }
+	    break;
+
+	  case DATATYPE_BITFIELD:
+	    if (is_odb || is_odbtk) {
+	      /* Borrowed from lib/prt.c : codb_fill_bitfield_() */
+	      char ss[MAXBITS+1]; /* MAXBITS == 32 from "privpub.h" */
+	      char *c = ss;
+	      unsigned int one = 1U << (MAXBITS - 1); /* 1 << 31 */
+	      int j;
+	      union {
+		unsigned int u;
+		int v;
+	      } u;
+	      u.v = (int) value;
+	      for (j=0; j<MAXBITS; j++) {
+		*c++ = (u.u & one) ? '1' : '0';
+		one >>= 1;
+	      }
+	      *c = 0;
+	      if (is_odb) {
+		ODB_fprintf(fp,"%s%*.*s", Delim, w, w, ss);
+	      }
+	      else {
+		ODB_fprintf(fp,"%s%s", Delim, ss);
+	      }
+	    }
+	    else {
+	      ODB_fprintf(fp,"%s%d", Delim, (int) value);
+	    }
+	    break;
+
+	  case DATATYPE_BUFR:
+	  case DATATYPE_GRIB:
+	    {
+	      int js;
+	      ODB_fprintf(fp,"%s",Delim);
+	      for (js=0; js<w-10; js++) ODB_fprintf(fp," ");
+	      ODB_fprintf(fp,"0x%8.8X", (int) value);
+	    }
+	    break;
+	  case DATATYPE_STRING:
+	    {
+	      col_t *colprev = (j > 0) ? &info->c[j-1] : NULL;
+	      uint prevdtnum = colprev ? colprev->dtnum : 0;
+	      col_t *colnext = (j-1 < ncols) ? &info->c[j+1] : NULL;
+	      uint nextdtnum = colnext ? colnext->dtnum : 0;
+	      int js;
+
+	      if (joinstr && 
+		  (prevdtnum == DATATYPE_STRING || nextdtnum == DATATYPE_STRING)
+		  ) {
+		char *thisbase = GetColArrayBaseName(colthis);
+		char *prevbase = (prevdtnum == DATATYPE_STRING && thisbase) ? 
+		  GetColArrayBaseName(colprev) : NULL;
+		char *nextbase = (nextdtnum == DATATYPE_STRING && thisbase) ?
+		  GetColArrayBaseName(colnext) : NULL;
+		if (!strequ(thisbase, prevbase)) prevdtnum = 0;
+		if (!strequ(thisbase, nextbase)) nextdtnum = 0;
+		FREE(nextbase);
+		FREE(prevbase);
+		FREE(thisbase);
+	      }
+
+	      if (!joinstr || prevdtnum != DATATYPE_STRING) ODB_fprintf(fp,"%s",Delim);
+	      if (is_odb) for (js=0; js<w-10; js++) ODB_fprintf(fp," ");
+	      if (!joinstr || prevdtnum != DATATYPE_STRING) ODB_fprintf(fp,"'");
+
+	      PRINT_STRING(ODB_fprintf, value);
+
+	      if (!joinstr || nextdtnum != DATATYPE_STRING) ODB_fprintf(fp,"'");
+	    }
+	    break;
+	  default:
+	    if (is_odb) {
+	      ODB_fprintf(fp,"%s%*.14g", Delim, w, value);
+	    }
+	    else /* if (is_odbtk || is_default) */ {
+	      if (fmt_string && *fmt_string == '%') {
+		ODB_fprintf(fp,"%s", Delim);
+		ODB_fprintf(fp,fmt_string, value);
+	      }
+	      else {
+		ODB_fprintf(fp,"%s%.14g", Delim, value);
+	      }
+	    }
+	  } /* switch (colthis->dtnum) */
+	}
+	Delim = delim;
+      } /* for (j=0; j<ncols; j++) */
+      ODB_fprintf(fp,"\n");
+    } /* for (i=0; i<nrows; i++) */
+    FREEX(width);
+
+  finish:
+    if (konvert && !the_final_print) (void) ODBc_conv2degrees(res, false); /* Convert back */
+    rc = nrows;
+    fflush(fp);
+  } /* if (fp && info && res && res->mem && res->d) */
+  if (iret) *iret = rc;
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC void *
+ODBc_print_data(const char *filename, FILE *fp, void *Result, 
+		const char *format, const char *fmt_string,
+		int konvert, int write_title, int joinstr,
+		int the_first_print, int the_final_print, 
+		int *iret)
+{
+  int rc = 0;
+  result_t *res = Result;
+  result_t *outres = res;
+  DRHOOK_START(ODBc_print_data);
+  if (fp && res) {
+    Bool is_odb = ODBc_test_format_2(format,"odb");
+    while (res) {
+      int rc_local = 0;
+      result_t *newres = PrintData(filename, fp, res, 
+				   format, fmt_string,
+				   konvert, write_title, joinstr,
+				   the_first_print, the_final_print, 
+				   &rc_local);
+      rc += rc_local;
+      if (newres == res) {
+	if (!is_odb) write_title = 0;
+	res = res->next;
+      }
+      else {
+	outres = newres;
+	break; /* while (res) */
+      }
+    } /* while (res) */
+  }
+  if (iret) *iret = rc;
+  DRHOOK_END(0);
+  return outres;
+}
+
+
+PUBLIC void *
+ODBc_operate(void *Result, const char *whatkey)
+{
+  result_t *res = Result;
+  info_t *info = res ? res->info : NULL;
+  DRHOOK_START(ODBc_operate);
+  if (res && info && whatkey) {
+    if (strequ(whatkey,"count(*)")) {
+      if ((info->optflags & 0x1) == 0x1) {
+	/* A special case : SELECT count(*) FROM table */
+	double value = 0;
+	int nrows = 1;
+	int ncols = 1;
+	int poolno = -1;
+	Bool row_wise = true; /* doesn't matter ; just one value involved */
+	result_t *newres = ODBc_new_res("ODBc_operate => newres of count(*)", 
+					__FILE__, __LINE__,
+					nrows, ncols, info, row_wise, poolno);
+	while (res) {
+	  if (res->d && res->d[0] &&
+	      res->nrows_out == 1 && res->ncols_out == 1) {
+	    value += res->d[0][0];
+	  }
+	  res = res->next;
+	}
+	newres->d[0][0] = value;
+	newres->nrows_out = 1;
+	newres->ncols_out = 1;
+
+	res = Result;
+	(void) ODBc_unget_data(res);
+	res = newres;
+      } /* if ((info->optflags & 0x1) == 0x1) */
+    } /* if (strequ(whatkey,"count(*)")) */
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC void *
+ODBc_sort(void *Result, const int Keys_override[], int Nkeys_override)
+{
+  result_t *res = Result;
+  info_t *info = res ? res->info : NULL;
+  DRHOOK_START(ODBc_sort);
+  if (res) {
+    if ((info && (info->norderby > 0 || info->has_select_distinct)) ||
+	(Keys_override && Nkeys_override > 0)) { 
+      int ncols = 0;
+
+      if (info) {
+	if (Keys_override && Nkeys_override > 0) {
+	  ncols = info->ncols_true + info->ncols_aux;
+	}
+	else {
+	  ncols = info->ncols_true;
+	}
+      }
+      else {
+	ncols = res->ncols_in;
+      }
+
+      if (ncols > 0) { /* Apart from insane cases this should always be true */
+	result_t *newres = ODBc_merge_res("ODBc_sort => newres",
+					  __FILE__, __LINE__,
+					  res, ncols, info, false);
+	int nrows = newres->nrows_out;
+	int nra = newres->nra;
+	int i, j, k;
+
+	if (!info) newres->typeflag = res->typeflag;
+
+	{
+	  /* Use F90-routine to perform multikey-"keysort" */
+	  extern int ec_is_little_endian(); /* from ifsaux/support/endian.c */
+	  int *keys = NULL;
+	  int nkeys = 0;
+	  int *idx = NULL;
+	  int nidx = 0;
+	  int init_idx = 0;
+	  int numabs = 0;
+	  int *abscols = NULL;
+	  int *swapstr = NULL;
+	  int nswap = 0;
+	  result_t *copyres = NULL;
+
+	  if (Keys_override && Nkeys_override > 0) { 
+	    /* (#1) The highest precedence : User supplied sorting key(s) */
+	    nkeys = Nkeys_override;
+	    ALLOC(keys, nkeys);
+	    k = 0;
+	    for (j=0; j<nkeys; j++) {
+	      /* keys are assumed to be in terms of Fortran column [1..ncols] or [-ncols..-1] */
+	      /* Also, no ABS()-sorting option available with this */
+	      int abskey = ABS(Keys_override[j]);
+	      if (abskey >= 1 && abskey <= ncols) {
+		keys[k++] = Keys_override[j];
+	      }
+	    }
+	    nkeys = k;
+	  }
+	  else if (info && info->norderby > 0) { 
+	    /* (#2) Has precedence over the 'SELECT DISTINCT' */
+	    int maxcols = info->maxcols; /* odb98.x compile-time ODB_maxcols() */
+	    nkeys = info->norderby;
+	    ALLOC(keys, nkeys);
+	    CALLOC(abscols, nkeys);
+	    k = 0;
+	    for (j=0; j<nkeys; j++) {
+	      col_t *colthis = &info->o[j];
+	      int kind = colthis->kind;
+	      int abskind = ABS(kind);
+	      if (abskind >= 1 && abskind <= ncols) {
+		keys[k++] = kind; /* Fortran column [1..ncols] or [-ncols..-1] */
+	      }
+	      else if (abskind > maxcols &&
+		       abskind <= ncols + maxcols) { /* ABS-sorting */
+		int colid = (kind > 0) ? ABS(kind - maxcols) : ABS(kind + maxcols);
+		abscols[numabs++] = --colid;
+		keys[k++] = (kind > 0) ? (kind - maxcols) : (kind + maxcols);
+	      }
+	    }
+	    nkeys = k; /* The actual number of valid keys */
+	    if (numabs > 0) {
+	      /* Switch on index-sorting, when numabs > 0 */
+	      nidx = nrows;
+	      ALLOC(idx, nidx);
+	      init_idx = 1;
+	    }
+	    else {
+	      FREE(abscols);
+	    }
+	  }
+	  else if (info && info->has_select_distinct) {
+	    /* (#3) Lowest precedence : 'SELECT DISTINCT' */
+	    nkeys = ncols;
+	    ALLOC(keys, nkeys);
+	    for (j=0; j<nkeys; j++) keys[j] = j+1; /* "+1" due to Fortran column indexing */
+	  }
+
+	  if (nkeys == 0) goto sort_done;
+
+	  if (ec_is_little_endian()) {
+	    /* Applies really to little-endian machines only:
+	       Check if any of the columns to be sorted are strings --
+	       if true, then instruct swap bytes on those columns 
+	       BEFORE entering the ckeysort() and 
+	       to swap then back after the sort
+	    */
+	    unsigned int typeflag = info ? 0 : newres->typeflag;
+	    ALLOC(swapstr, nkeys);
+	    nswap = 0;
+	    for (j=0; j<nkeys; j++) {
+	      int colid = ABS(keys[j]) - 1;
+	      if (colid >= 0 && colid < ncols) {
+		if (info) {
+		  col_t *colthis = &info->c[colid];
+		  if (colthis && colthis->dtnum == DATATYPE_STRING) swapstr[nswap++] = colid;
+		}
+		else {
+		  int is_string = (typeflag == 0) ? 0 : 
+		    ODBIT_test(&typeflag, MAXBITS, MAXBITS, colid, colid);
+		  if (is_string == 1) swapstr[nswap++] = colid;
+		}
+	      }
+	    }
+
+	    if (nswap == 0) {
+	      FREE(swapstr);
+	    }
+	    else { /* nswap > 0 */
+	      for (j=0; j<nswap; j++) {
+		int colid = swapstr[j];
+		double *colptr = &newres->d[colid][0];
+		swap8bytes_(colptr, &nrows);
+	      } /* for (j=0; j<nswap; j++) */
+	    }
+	  }
+
+	  /* Take absolute of the ABS-sorting columns, but before that
+	     save a copy of the original column value */
+
+	  if (numabs > 0 && abscols) {
+	    CALLOC(copyres, 1);
+	    copyres->nrows_in = nrows;
+	    copyres->ncols_in = numabs;
+	    copyres->nra = nra;
+	    copyres->nmem = nra * numabs;
+	    ALLOC(copyres->mem, copyres->nmem);
+	    copyres->row_wise = false;
+	    ALLOC(copyres->d, numabs);
+	    k = 0;
+	    for (j=0; j<numabs; j++) { /* since not row_wise */
+	      copyres->d[j] = &copyres->mem[k];
+	      k += nra;
+	    }
+	    copyres->next = NULL; /* no chain */
+	    for (j=0; j<numabs; j++) {
+	      int colid = abscols[j];
+	      double *colptr_in = &newres->d[colid][0];
+	      double *colptr_out = &copyres->d[j][0];
+	      memcpy(colptr_out, colptr_in, nrows * sizeof(double));
+	      for (i=0; i<nrows; i++) {
+		if (colptr_in[i] < 0) colptr_in[i] = -colptr_in[i];
+	      }
+	    } /* for (j=0; j<numabs; j++) */
+	  }
+
+	  {
+	    int iret = 0;
+	    int dummy_idx = 0;
+	    
+	    /* Fortran90-routine from lib/ckeysort.F90 */
+	    ckeysort_(newres->mem, &nra, &nrows, &ncols, 
+		      keys, &nkeys,
+		      idx ? idx : &dummy_idx, &nidx, &init_idx,
+		      &iret);
+
+	    if (iret != nrows) {
+	      fprintf(stderr,"***Error in ODBc_sort(): "
+		      "Multikeysort has failed : iret = %d, "
+		      "expecting nrows=%d (ncols=%d, nra=%d, memptr=%p, nidx=%d)\n",
+		      iret, nrows, ncols, nra, newres->mem, nidx);
+	      RAISE(SIGABRT);
+	    }
+	  } /* if (nkeys > 0) */
+
+	  if (copyres) { 
+	    /* Restore values that were "ABSoluted" */
+	    for (j=0; j<numabs; j++) {
+	      int colid = abscols[j];
+	      double *colptr_out = &newres->d[colid][0];
+	      double *colptr_in = &copyres->d[j][0];
+	      memcpy(colptr_out, colptr_in, nrows * sizeof(double));
+	    }
+	    FREE(abscols);
+	    (void) ODBc_unget_data(copyres);
+	  }
+
+	  if (swapstr && nswap > 0) {
+	    /* Swap string's back */
+	    for (j=0; j<nswap; j++) {
+	      int colid = swapstr[j];
+	      double *colptr = &newres->d[colid][0];
+	      swap8bytes_(colptr, &nrows);
+	    } /* for (j=0; j<nswap; j++) */
+	    FREE(swapstr);
+	  }
+
+	  if (idx && nidx > 0) {
+	    /* Finally, if index sorting was requested, perform physical reordering */
+	    /* Note that the index idx[] is a Fortran-index with range [1..nrows],
+	       so we need to subtract 1 */
+	    double *tmp;
+	    ALLOC(tmp, nrows);
+	    for (j=0; j<ncols; j++) {
+	      double *colptr = &newres->d[j][0];
+	      for (i=0; i<nrows; i++) {
+		tmp[i] = colptr[idx[i]-1];
+	      } /* for (i=0; i<nrows; i++) */
+	      memcpy(colptr, tmp, nrows * sizeof(double));
+	    } /* for (j=0; j<ncols; j++) */
+	    FREE(tmp);
+	    FREE(idx);
+	  }
+	  
+	sort_done:
+	  FREE(keys);
+	}
+
+	res = newres;
+      } /* if (ncols > 0) */
+    } 
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PRIVATE int
+which_aggr(const col_t *c, int *ncols_aux)
+{
+  /* See also compiler/tree.c for similar function ODB_which_aggr() */
+  const char *s = c ? c->name : NULL;
+  int Ncols_aux = 0;
+  uint aggr_flag = ODB_AGGR_NONE;
+  DRHOOK_START(which_aggr);
+  if (s && *s == '_') s++;
+  if (s && *s) {
+    char *name = STRDUP(s);
+    char *p_br = strchr(name, '(');
+    if (p_br) {
+      *p_br = '\0';
+      if (strequ(name,"min")) aggr_flag = ODB_AGGR_MIN;
+      else if (strequ(name,"max")) aggr_flag = ODB_AGGR_MAX;
+      else if (strequ(name,"density")) aggr_flag = ODB_AGGR_DENSITY;
+      else if (strequ(name,"sum")) aggr_flag = ODB_AGGR_SUM;
+      else if (strequ(name,"sum_distinct")) aggr_flag = ODB_AGGR_SUM_DISTINCT;
+      else if (strequ(name,"avg")) aggr_flag = ODB_AGGR_AVG;
+      else if (strequ(name,"avg_distinct")) aggr_flag = ODB_AGGR_AVG_DISTINCT;
+      else if (strequ(name,"median")) aggr_flag = ODB_AGGR_MEDIAN;
+      else if (strequ(name,"median_distinct")) aggr_flag = ODB_AGGR_MEDIAN_DISTINCT;
+      else if (strequ(name,"stdev")) aggr_flag = ODB_AGGR_STDEV;
+      else if (strequ(name,"stdev_distinct")) aggr_flag = ODB_AGGR_STDEV_DISTINCT;
+      else if (strequ(name,"var")) aggr_flag = ODB_AGGR_VAR;
+      else if (strequ(name,"var_distinct")) aggr_flag = ODB_AGGR_VAR_DISTINCT;
+      else if (strequ(name,"rms")) aggr_flag = ODB_AGGR_RMS;
+      else if (strequ(name,"rms_distinct")) aggr_flag = ODB_AGGR_RMS_DISTINCT;
+      else if (strequ(name,"count")) aggr_flag = ODB_AGGR_COUNT;
+      else if (strequ(name,"count_distinct")) aggr_flag = ODB_AGGR_COUNT_DISTINCT;
+      else if (strequ(name,"bcount")) aggr_flag = ODB_AGGR_BCOUNT;
+      else if (strequ(name,"bcount_distinct")) aggr_flag = ODB_AGGR_BCOUNT_DISTINCT;
+      else if (strequ(name,"dotp")) aggr_flag = ODB_AGGR_DOTP;
+      else if (strequ(name,"dotp_distinct")) aggr_flag = ODB_AGGR_DOTP_DISTINCT;
+      else if (strequ(name,"norm")) aggr_flag = ODB_AGGR_NORM;
+      else if (strequ(name,"norm_distinct")) aggr_flag = ODB_AGGR_NORM_DISTINCT;
+      else if (strequ(name,"covar")) { aggr_flag = ODB_AGGR_COVAR; Ncols_aux = 1; }
+      else if (strequ(name,"corr")) { aggr_flag = ODB_AGGR_CORR; Ncols_aux = 1; }
+      else if (strequ(name,"linregr_a")) { aggr_flag = ODB_AGGR_LINREGR_A; Ncols_aux = 1; }
+      else if (strequ(name,"linregr_b")) { aggr_flag = ODB_AGGR_LINREGR_B; Ncols_aux = 1; }
+      else if (strequ(name,"minloc")) { aggr_flag = ODB_AGGR_MINLOC; Ncols_aux = 1; }
+      else if (strequ(name,"maxloc")) { aggr_flag = ODB_AGGR_MAXLOC; Ncols_aux = 1; }
+    }
+    FREE(name);
+  }
+  if (ncols_aux) *ncols_aux = Ncols_aux;
+  DRHOOK_END(0);
+  return (int)aggr_flag;
+}
+
+
+PUBLIC void *
+ODBc_aggr(void *Result, int phase_id)
+{
+  result_t *res = Result;
+  info_t *info = res ? res->info : NULL;
+  DRHOOK_START(ODBc_aggr);
+  if ((phase_id == 0 || phase_id == 1) &&
+      res && info && info->has_aggrfuncs && info->colaux) {
+    /* This is supposed to be similar to the F90-coding in include/fodb.h */
+    FILE *fp_echo = ODBc_get_debug_fp();
+    int i, j, k;
+    int ncols, ncols_aux, ncols_aggr, ncols_tot;
+    double tmpval[2];
+    Bool all_aggr_funcs;
+
+    ncols = info->ncols_true;
+    ncols_aux = info->ncols_aux;
+    ncols_aggr = info->ncols_aggr_formula;
+    ncols_tot = ncols + ncols_aux;
+
+    all_aggr_funcs = (ncols_aggr == ncols) ? true : false;
+
+    if (all_aggr_funcs) {
+      /* Here all columns are aggregate functions */
+      if (res->next) { /* Has chain */
+	/* Note below: "ncols_tot", not "ncols" : we need both SELECT + aux -columns */
+	result_t *newres = ODBc_merge_res("ODBc_aggr => newres",
+					  __FILE__, __LINE__,
+					  res, ncols_tot, info, false);
+	res = ODBc_aggr(newres, phase_id); /* Ends up with the "else"-block below */
+      }
+      else { /* No chain --> plain sailing ! */
+	int nrows = res->nrows_out;
+	for (j=0; j<ncols; j++) { /* i.e. run up to "ncols_true" */
+	  col_t *colthis = &info->c[j];
+	  int aggrfuncflag = which_aggr(colthis, NULL);
+	  int jj, i2nd;
+	  double *d = &res->d[j][0]; /* always column-wise (i.e. not row_wise) */
+	  double *daux;
+	  if (phase_id == 1 || info->colaux[j] == j+1) {
+	    jj = j;
+	    daux = NULL;
+	    i2nd = 1;
+	  }
+	  else { /* The sibling column */
+	    jj = info->colaux[j] - 1;
+	    daux = &res->d[jj][0]; 
+	    i2nd = 2;
+	  }
+	  codb_calc_aggr_(&phase_id, &aggrfuncflag, &i2nd, tmpval, &nrows, d, daux);
+	  jj = j;
+	  for (i=0; i<i2nd; i++) {
+	    d = &res->d[jj][0];
+	    d[0] = tmpval[i];
+	    jj = info->colaux[jj] - 1;
+	  }
+	} /* for (j=0; j<ncols; j++) */
+	res->nrows_out = 1;
+	res->ncols_out = ncols; /* i.e. "ncols_true" */
+      } /* if (res->next) ... else ... */
+    }
+    else {
+      /* Not all columns are aggregate functions => perform binned aggregate function calc */
+      int n_keys = ncols - ncols_aggr; /* i.e. # of non-aggr. funcs */
+      int *keys = NULL;
+      CALLOC(keys, n_keys);
+      k = 0;
+      for (j=0; j<ncols; j++) { /* i.e. run up to the "ncols_true" */
+	col_t *colthis = &info->c[j];
+	if (colthis->kind != 4) {
+	  keys[k++] = j+1; /* "+1" due to Fortran column numbering */
+	}
+      }
+      n_keys = k;
+      res = ODBc_sort(res, keys, n_keys); /* Sorted + merged into a single result-set */
+
+      {
+	result_t *tmp = NULL;
+	int nrows = res->nrows_out;
+	int ngrp, jj, maxlen, i2nd, ii;
+	int *grpsta = NULL;
+
+	CALLOC(grpsta, nrows+1);
+	ngrp = 0;
+	jj = 0;
+	grpsta[ngrp] = jj;
+
+	for (i=1; i<nrows; i++) {
+	  Bool changed = false;
+	  
+	  for (j=0; j<n_keys; j++) {
+	    int akey = keys[j]-1;
+	    double djj = res->d[akey][jj]; 
+	    double di  = res->d[akey][i];
+	    if (djj != di) {
+	      changed = true;
+	      break; /* for (j=0; j<n_keys; j++) */
+	    }
+	  } /* for (j=0; j<n_keys; j++) */
+	  
+	  if (changed) {
+	    jj = i;
+	    grpsta[++ngrp] = jj;
+	  }
+	} /* for (i=1; i<nrows; i++) */
+	grpsta[++ngrp] = nrows;
+
+	FREE(keys);
+
+	maxlen = 0;
+	for (ii=0; ii<ngrp; ii++) {
+	  int nr = grpsta[ii+1] - grpsta[ii];
+	  maxlen = MAX(maxlen, nr);
+	}
+
+	if (phase_id == 1 || ncols_aux == 0) {
+	  i2nd = 1;
+	}
+	else {
+	  i2nd = 2;
+	}
+
+	ODB_fprintf(fp_echo, 
+		    "ODBc_aggr: phase_id=%d, ncols=%d, ncols_aux=%d, ncols_aggr=%d, nrows=%d, "
+		    "ngrp=%d, n_keys=%d, maxlen=%d, i2nd=%d\n",
+		    phase_id, ncols, ncols_aux, ncols_aggr, nrows, 
+		    ngrp, n_keys, maxlen, i2nd);
+	
+	tmp = ODBc_new_res("ODBc_aggr => tmp", 
+			   __FILE__, __LINE__,
+			   maxlen, i2nd, NULL, false, -1);
+
+	if (tmp) {
+	  result_t *newres = ODBc_new_res("ODBc_aggr => newres",
+					  __FILE__, __LINE__,
+					  ngrp, ncols_tot, info, false, res->poolno);
+	
+	  int *aggrflag = NULL;
+	  ALLOCX(aggrflag, ncols);
+
+	  for (j=0; j<ncols; j++) { /* i.e. run up to the "ncols_true" */
+	    col_t *colthis = &info->c[j];
+	    aggrflag[j] = which_aggr(colthis, NULL);
+	  }
+	  
+	  for (ii=0; ii<ngrp; ii++) {
+	    int nr = grpsta[ii+1] - grpsta[ii];
+	    jj = grpsta[ii];
+	    for (j=0; j<ncols; j++) { /* i.e. run up to the "ncols_true" */
+	      col_t *colthis = &info->c[j];
+	      int aggrfuncflag = aggrflag[j];
+
+	      if (aggrfuncflag == ODB_AGGR_NONE) {
+		/* A non-aggregate function column */
+		double *dres  = &newres->d[j][ii];
+		double *d     = &res->d[j][jj]; 
+		dres[0] = d[0];
+	      }
+	      else {
+		/* This is an aggregate function column */
+		i2nd = 0;
+		{
+		  double *dtmp = &tmp->d[i2nd++][0];
+		  double *d = &res->d[j][0]; 
+		  for (k=0; k<nr; k++) {
+		    dtmp[k] = d[jj+k];
+		  }
+		}
+
+		{
+		  if (!(phase_id == 1 || info->colaux[j] == j+1)) {
+		    double *dtmp = &tmp->d[i2nd++][0];
+		    int colid = info->colaux[j] - 1;
+		    double *d = &res->d[colid][0]; 
+		    for (k=0; k<nr; k++) {
+		      dtmp[k] = d[jj+k];
+		    }
+		  }
+		}
+
+		{
+		  int j2;
+		  double *dtmp = &tmp->d[0][0]; /* always column-wise (i.e. not row_wise) */
+		  double *daux = (i2nd == 2) ? &tmp->d[i2nd-1][0] : NULL;
+#if 0
+		  ODB_fprintf(fp_echo,
+			      "ii=%d, j=%d : before codb_calc_aggr_(phase_id=%d): i2nd=%d, "
+			      "info->colaux[%d] = %d, dtmp=%p, daux=%p, nr=%d\n",
+			      ii, j, phase_id, i2nd, j, info->colaux[j], dtmp, daux, nr);
+#endif
+		  codb_calc_aggr_(&phase_id, &aggrfuncflag, &i2nd, tmpval, &nr, dtmp, daux);
+		  j2 = j;
+		  for (i=0; i<i2nd; i++) {
+		    double *dres = &newres->d[j2][ii]; /* Note: [ii], not [i] */
+		    *dres = tmpval[i];
+		    j2 = info->colaux[j2] - 1;
+		  }
+		}
+	      } /* if (aggrfuncflag == ODB_AGGR_NONE) ... else ... */
+	    } /* for (j=0; j<ncols; j++) */
+	  } /* for (ii=0; ii<ngrp; ii++) */
+	  FREEX(aggrflag);
+	  
+	  (void) ODBc_unget_data(res);
+	  res = newres;
+	  if (phase_id == 1) res->ncols_out = ncols; /* i.e. "ncols_true" */
+
+	  (void) ODBc_unget_data(tmp);
+	} /* if (tmp) */
+	FREE(grpsta);
+      }
+    } /* if (all_aggr_funcs) ... else ... */
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+#define FCLOSE_FP_OUT() \
+if (fp_out) { \
+  fflush(fp_out); \
+  /* if (use_gzip_pipe) pclose(fp_out); else fclose(fp_out); */ \
+  if (iounit >= 0) cma_close_(&iounit, &iret); else fclose(fp_out); \
+  fp_out = NULL; \
+  iounit = -1; \
+}
+
+PUBLIC FILE *
+ODBc_print_file(FILE *fp_out, int *fpunit,
+		const char *outfile, const char *format,
+		int poolno, const char *view,
+		Bool first_time,
+		Bool *Reopen_per_view,
+		Bool *Reopen_per_pool,
+		Bool *Use_gzip_pipe)
+{
+  char *gzip = getenv("ODB_GZIP");
+  FILE *fp_echo = ODBc_get_debug_fp();
+  Bool reopen_per_view = Reopen_per_view ? *Reopen_per_view : false;
+  Bool reopen_per_pool = Reopen_per_pool ? *Reopen_per_pool : false;
+  Bool use_gzip_pipe = Use_gzip_pipe ? *Use_gzip_pipe : false;
+  int iounit = fpunit ? *fpunit : ((int)-ABS(mdi));
+  int iret = 0;
+  Bool some_plotobs = (strequ(format,"plotobs") || strequ(format,"wplotobs")) ? true : false;
+  DRHOOK_START(ODBc_print_file);
+
+  ODB_fprintf(fp_echo,
+	      "<ODBc_print_file(fp_out=%p [stdout=%p], fpunit=(%d @ %p), first_time=%s\n"
+	      "\toutfile='%s', format='%s', poolno=%d, view='%s')\n",
+	      fp_out, stdout, iounit, fpunit,
+	      first_time ? "true" : "false",
+	      outfile ? outfile : NIL, format ? format : NIL,
+	      poolno, view ? view : NIL);
+
+  if (first_time) {
+    if (strequ(outfile,"/dev/null")) {
+      if (some_plotobs) {
+	/* Prevent [w]plotobs output to end up on the "screen" */
+	cma_open_(&iounit, outfile, "w", &iret, STRLEN(outfile), 1);
+	fp_out = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+      }
+      else {
+	fp_out = stdout;
+	iounit = -1;
+      }
+      reopen_per_view = false;
+      reopen_per_pool = false;
+      use_gzip_pipe = false;
+    }
+    else {
+      int outlen = STRLEN(outfile);
+      reopen_per_view = strstr(outfile,"%s") ? true : false;
+      reopen_per_pool = strstr(outfile,"%d") ? true : false;
+      use_gzip_pipe = (outlen >= 3 && strnequ(&outfile[outlen-3],".gz",3)) ? true : false;
+      if (!reopen_per_view && !reopen_per_pool) {
+	ODB_fprintf(fp_echo, "Opening file '%s'\n",outfile);
+	cma_open_(&iounit, outfile, "w", &iret, STRLEN(outfile), 1);
+	fp_out = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+      } /* if (!reopen_per_view && !reopen_per_pool) */
+    }
+  }
+  else if (fp_out != stdout && poolno <= 0 && view){
+    if (reopen_per_view && !reopen_per_pool) {
+      char *ppfile = NULL;
+      int pplen = STRLEN(outfile) + STRLEN(view) + 1;
+      FCLOSE_FP_OUT();
+      ALLOC(ppfile,pplen);
+      snprintf(ppfile,pplen,outfile,view); /* Has just '%s' */
+      ODB_fprintf(fp_echo, "Opening file '%s'\n",ppfile);
+      cma_open_(&iounit, ppfile, "w", &iret, STRLEN(ppfile), 1);
+      fp_out = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+      FREE(ppfile);
+    } /* if (reopen_per_view && !reopen_per_pool) */
+  }
+  else if (fp_out != stdout && poolno > 0 && view) {
+    if (reopen_per_pool) {
+      char *ppfile = NULL;
+      int pplen = STRLEN(outfile) + STRLEN(view) + 12 + 1;
+      FCLOSE_FP_OUT();
+      ALLOC(ppfile,pplen);
+      if (!reopen_per_view) { /* Has just '%d' */
+	snprintf(ppfile,pplen,outfile,poolno);
+      }
+      else { /* Has both '%d' & '%s'; need to find which comes first */
+	const char *pcd = strstr(outfile,"%d");
+	const char *pcs = strstr(outfile,"%s");
+	if (pcd < pcs) { /* '%d' before '%s' */
+	  snprintf(ppfile,pplen,outfile,poolno,view);
+	}
+	else { /* '%s' before '%d' */
+	  snprintf(ppfile,pplen,outfile,view,poolno);
+	}
+      }
+      ODB_fprintf(fp_echo, "Opening file '%s'\n",ppfile);
+      cma_open_(&iounit, ppfile, "w", &iret, STRLEN(ppfile), 1);
+      fp_out = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+      FREE(ppfile);
+    } /* if (reopen_per_pool) */
+  }
+  else if (fp_out == stdout) {
+    fflush(fp_out);
+  }
+  else if (fp_out) {
+    FCLOSE_FP_OUT();
+  }
+
+  if (Reopen_per_view) *Reopen_per_view = reopen_per_view;
+  if (Reopen_per_pool) *Reopen_per_pool = reopen_per_pool;
+  if (Use_gzip_pipe) *Use_gzip_pipe = use_gzip_pipe;
+
+  if (fpunit) *fpunit = iounit;
+
+  ODB_fprintf(fp_echo,
+	      ">ODBc_print_file(fp_out=%p [stdout=%p], fpunit=(%d @ %p) ...)\n"
+	      "\t>reopen_per_view=%s, reopen_per_pool=%s, use_gzip_pipe=%s\n",
+	      fp_out, stdout,
+	      iounit, fpunit,
+	      reopen_per_view ? "true" : "false",
+	      reopen_per_pool ? "true" : "false",
+	      use_gzip_pipe ? "true" : "false");
+
+  DRHOOK_END(0);
+  return fp_out;
+}
+
+static const double RMiss = 1.7e38; /* Traditional GRIB/BUFR missing data indicator that fits
+				       into single precision (float) values */
+
+#if defined(sngl)
+#undef sngl
+#endif
+
+/* Provide single precision (float) conversion */
+#define sngl(d) (ABS(d) > RMiss ? (float)(-RMiss) : (float)d)
+
+#define WRITE_FORTRAN_RECLEN(fp) \
+{ \
+  int x = reclen; \
+  if (swap_endian) swap4bytes_(&x, &oneword); \
+  (void) fwrite(&x, sizeof(x), 1, fp); \
+}
+
+#define WRITE_PADDING(fp, npad) if ((npad) > 0) fprintf(fp,"%*.*s",(npad),(npad)," ")
+
+
+PUBLIC int 
+ODBc_ODBtool(FILE *fpin,  int *fpunit,
+	     const char *file, Bool ascii, void *Result, void *Info)
+{
+  /* Compatible with IDL-procedure $ODB_SYSPATH/read_odb.pro */
+  int rc = 0; /* No. of records (binary) or lines (ascii) written */
+  DRHOOK_START(ODBc_ODBtool);
+  if ((fpin || file) && Result) {
+    result_t *res = Result;
+    info_t *info = Info;
+    const char *sql_query = ODBc_get_sql_query(info);
+    const char create_view[] = "CREATE VIEW odbtool";
+    const char select_stmt_start[] = "SELECT lat, lon, body.len,";
+    const char end_sql[] = "END-SQL";
+    int iounit = fpunit ? *fpunit : ((int)-ABS(mdi));
+    int iret = 0;
+    FILE *fp = NULL;
+    if (fpin) {
+      fp = fpin;
+    }
+    else {
+      cma_open_(&iounit, file, "w", &iret, STRLEN(file), 1);
+      fp = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+      if (fpunit) *fpunit = iounit;
+    }
+    if (fp) {
+      if (ascii) {
+	int nlcnt = 0; /* No. of newlines */
+	int ncols = res->ncols_out;
+	int nfrom = info ? info->nfrom : 0;
+	
+	fprintf(fp, "%s\n",create_view); nlcnt++;
+	fprintf(fp, "%s\n",select_stmt_start); nlcnt++;
+
+	if (info && ncols >= 4 && nfrom > 0) {
+	  int j;
+	  for (j=3; j<ncols; j++) {
+	    const col_t *colthis = &info->c[j];
+	    const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	    fprintf(fp, "%s,\n", s); nlcnt++;
+	  }
+	  fprintf(fp, "FROM\n"); nlcnt++;
+	  for (j=0; j<nfrom; j++) {
+	    const table_t *t = &info->t[j];
+	    const char *s = t->name;
+	    fprintf(fp, "%s,\n", s); nlcnt++;
+	  }
+	  if (sql_query) {
+	    const char *where = strstr(sql_query, "WHERE");
+	    if (!where) where = strstr(sql_query, "where");
+	    if (where) {
+	      char *s = STRDUP(where);
+	      char *sc = strchr(s,';');
+	      if (sc) *sc = '\0';
+	      fprintf(fp, "%s",s);
+	      FREE(s);
+	      while (*where && *where != ';') {
+		if (*where == '\n') nlcnt++;
+		where++;
+	      }
+	    }
+	    fprintf(fp, "\n"); nlcnt++;
+	  } /* if (sql_query) */
+	}
+
+	fprintf(fp, "%s\n", end_sql); nlcnt++;
+
+	if (res->nrows_out > 0 && ncols >= 4) {
+	  /* Now write the first set of results */
+	  Bool row_wise = res->row_wise;
+	  int irow = 0;
+	  double r_chan = row_wise ? res->d[irow][2] : res->d[2][irow];
+	  r_chan = sngl(r_chan);
+	  if (r_chan >= 1 && r_chan <= res->nrows_out) {
+	    int k, jcol, nchan = r_chan;
+	    int cnt;
+	    float f;
+	    double lat = row_wise ? res->d[irow][0] : res->d[0][irow];
+	    double lon = row_wise ? res->d[irow][1] : res->d[1][irow];
+	    lat = ODB_lldegrees(lat);
+	    f = sngl(lat); fprintf(fp, "%20.12e", f);
+	    lon = ODB_lldegrees(lon);
+	    f = sngl(lon); fprintf(fp, "%20.12e", f);
+	    fprintf(fp, "%8d\n", nchan);
+	    nlcnt++;
+	    cnt = 0;
+	    for (k=0; k<nchan; k++) {
+	      for (jcol=3; jcol<ncols; jcol++) {
+		double d = row_wise ? res->d[irow][jcol] : res->d[jcol][irow];
+		f = sngl(d); fprintf(fp, "%20.12e", f);
+		cnt++;
+		if (cnt == 12) { cnt = 0; fprintf(fp, "\n"); nlcnt++; }
+	      }
+	      irow++;
+	    }
+	    fprintf(fp, "\n"); nlcnt++;
+	  } /* if (ABS(r_nchan) != mdi && r_chan >= 1 && r_chan <= res->nrows_out) */
+	} /* if (res->nrows_out > 0 && ncols >= 4) */
+	rc += nlcnt;
+      }
+      else {
+	/* Binary */
+	/* If at the beginning of file, then dump the SQL-query, too */
+	extern int ec_is_little_endian();
+	char *env_swap_endian = getenv("ODBTOOL_SWAP_ENDIAN");
+	Bool swap_endian = ec_is_little_endian() ? true : false; /* we rely on big-endian files */
+	Bool temp_header = (!fpin || (ftell(fpin) == 0)) ? true : false;
+	int reclen;
+	const int oneword = 1;
+
+	if (env_swap_endian) {
+	  /* Override the default via export ODBTOOL_SWAP_ENDIAN=0 or 1 */
+	  int what = atoi(env_swap_endian);
+	  swap_endian = (what == 0) ? false : true;
+	}
+
+	if (temp_header) {
+	  /* For debugging etc. purposes do not write temp_header at all ? */
+	  char *env_write_temp_header = getenv("ODBTOOL_WRITE_TEMP_HEADER");
+	  if (env_write_temp_header) {
+	    int what = atoi(env_write_temp_header);
+	    temp_header = (what == 0) ? false : true;
+	  }
+	}
+
+	if (temp_header) {
+	  int ncols = res->ncols_out;
+	  int nfrom = info ? info->nfrom : 0;
+	  int len;
+	  reclen = 80; /* fixed */
+	  
+	  /* CREATE VIEW ... */
+	  WRITE_FORTRAN_RECLEN(fp);
+	  len = STRLEN(create_view);
+	  (void) fwrite(create_view, len, 1, fp);
+	  WRITE_PADDING(fp, reclen-len);
+	  WRITE_FORTRAN_RECLEN(fp);
+	  rc++;
+
+	  /* SELECT ... */
+	  WRITE_FORTRAN_RECLEN(fp);
+	  len = STRLEN(select_stmt_start);
+	  (void) fwrite(select_stmt_start, len, 1, fp);
+	  WRITE_PADDING(fp, reclen-len);
+	  WRITE_FORTRAN_RECLEN(fp);
+	  rc++;
+
+	  if (info && ncols >= 4 && nfrom > 0) {
+	    int j;
+	    /* The rest of the columns */
+	    for (j=3; j<ncols; j++) {
+	      const col_t *colthis = &info->c[j];
+	      const char *s = colthis->nickname ? colthis->nickname : colthis->name;
+	      WRITE_FORTRAN_RECLEN(fp);
+	      len = STRLEN(s);
+	      (void) fwrite(s, len, 1, fp);
+	      (void) fwrite(",", 1, 1, fp);
+	      len++;
+	      WRITE_PADDING(fp, reclen-len);
+	      WRITE_FORTRAN_RECLEN(fp);
+	      rc++;
+	    }
+
+	    /* FROM */
+	    WRITE_FORTRAN_RECLEN(fp);
+	    len = STRLEN("FROM");
+	    (void) fwrite("FROM", len, 1, fp);
+	    WRITE_PADDING(fp, reclen-len);
+	    WRITE_FORTRAN_RECLEN(fp);
+	    rc++;
+
+	    /* FROM-tables */
+	    for (j=0; j<nfrom; j++) {
+	      const table_t *t = &info->t[j];
+	      const char *s = t->name;
+	      WRITE_FORTRAN_RECLEN(fp);
+	      len = STRLEN(s);
+	      (void) fwrite(s, len, 1, fp);
+	      (void) fwrite(",", 1, 1, fp);
+	      len++;
+	      WRITE_PADDING(fp, reclen-len);
+	      WRITE_FORTRAN_RECLEN(fp);
+	      rc++;
+	    }
+
+	    /* Possible WHERE-stmt */
+	    if (sql_query) {
+	      const char *where = strstr(sql_query, "WHERE");
+	      if (!where) where = strstr(sql_query, "where");
+	      if (where) {
+		char *s = STRDUP(where);
+		char *sc = strchr(s,';');
+		if (sc) *sc = '\0';
+		WRITE_FORTRAN_RECLEN(fp);
+		len = STRLEN(s);
+		if (len > reclen) len = reclen;
+		(void) fwrite(s, len, 1, fp);
+		WRITE_PADDING(fp, reclen-len);
+		WRITE_FORTRAN_RECLEN(fp);
+		rc++;
+		FREE(s);
+	      }
+	    } /* if (sql_query) */
+	  }
+
+	  /* END-SQL */
+	  WRITE_FORTRAN_RECLEN(fp);
+	  len = STRLEN(end_sql);
+	  (void) fwrite(end_sql, len, 1, fp);
+	  WRITE_PADDING(fp, reclen-len);
+	  WRITE_FORTRAN_RECLEN(fp);
+	  rc++;
+	} /* if (temp_header) */
+
+	while (res) {
+	  int nrows = res->nrows_out;
+	  int ncols = res->ncols_out;
+	  if (nrows > 0 && ncols >= 4) {
+	    Bool row_wise = res->row_wise;
+	    int irow = 0;
+	    double r_chan = row_wise ? res->d[irow][2] : res->d[2][irow];
+        double r_chanref = r_chan;
+        int nchan = r_chan;
+	    int fbuflen = nchan * (ncols - 3);
+	    float *fbuf=NULL, *pfbuf=NULL;
+	    ALLOCX(fbuf, fbuflen);
+	    while (irow < nrows) {
+	      int nrows_left = nrows - irow;
+	      if (r_chan >= 1 && r_chan <= nrows_left) {
+		int k, jcol, tmp;
+		
+		float f;
+		double lat = row_wise ? res->d[irow][0] : res->d[0][irow];
+		double lon = row_wise ? res->d[irow][1] : res->d[1][irow];
+        r_chan = row_wise ? res->d[irow][2] : res->d[2][irow];
+		if (r_chan != r_chanref) {
+		  /* free fbuf and reallocate fbuf */
+		  
+		  FREEX(fbuf);
+		  nchan = r_chan;
+		  fbuflen = nchan * (ncols - 3);
+		  r_chanref = r_chan;
+		  ALLOCX(fbuf, fbuflen);
+		}
+		/* (lat,lon,chan) */
+		reclen = 2 * sizeof(f) + sizeof(tmp);
+		WRITE_FORTRAN_RECLEN(fp);
+
+		lat = ODB_lldegrees(lat);
+		f = sngl(lat); 
+		if (swap_endian) swap4bytes_(&f, &oneword);
+		(void) fwrite(&f, sizeof(f), 1, fp);
+
+		lon = ODB_lldegrees(lon);
+		f = sngl(lon); 
+		if (swap_endian) swap4bytes_(&f, &oneword);
+		(void) fwrite(&f, sizeof(f), 1, fp);
+
+		tmp = nchan;
+		if (swap_endian) swap4bytes_(&tmp, &oneword);
+		(void) fwrite(&tmp, sizeof(tmp), 1, fp);
+
+		WRITE_FORTRAN_RECLEN(fp);
+		rc++;
+
+		/* channel data */
+		reclen = fbuflen * sizeof(*fbuf);
+		/*AF 27/11/08	ALLOCX(fbuf, fbuflen);  outside the loop on rows */
+		pfbuf = fbuf;
+		WRITE_FORTRAN_RECLEN(fp);
+		for (jcol=3; jcol<ncols; jcol++) {
+		  for (k=0; k<nchan; k++) {
+		    double d = row_wise ? res->d[irow][jcol] : res->d[jcol][irow];
+		    f = sngl(d); 
+		    *pfbuf++ = f; 
+		    irow++;
+		    if (irow > nrows) {
+		      fprintf(stderr,"***Error: Unexpected end of channel data\n");
+		      RAISE(SIGABRT);
+		    }
+		  } /* for (k=0; k<nchan; k++) */
+		  irow -= nchan;
+		}
+		if (swap_endian) swap4bytes_(fbuf, &fbuflen);
+		(void) fwrite(fbuf, sizeof(*fbuf), fbuflen, fp);
+		/*AF FREEX(fbuf); */
+		WRITE_FORTRAN_RECLEN(fp);
+
+		irow += nchan;
+	      } /* if (r_chan >= 1 && r_chan <= nrows_left) */
+	      else {
+		/* To avoid infinite loop */
+		fprintf(stderr,"***Error: Invalid value for # of channels (nchan) = %.0f\n",r_chan);
+		RAISE(SIGABRT);
+	      }
+	    } /* while (irow < nrows) */
+	    if (fbuf)
+	      FREEX(fbuf);
+	  } /* if (nrows > 0 && ncols >= 4) */
+	  res = res->next;
+	} /* while (res) */
+ 	
+      }
+      if (!fpin) {
+	cma_close_(&iounit, &iret);
+	if (fpunit) *fpunit = -1;
+      }
+    } /* if (fp) */
+  }
+  DRHOOK_END(0);
+  return rc;
+}
diff --git a/odb/src/aux/runcmd.c b/odb/src/aux/runcmd.c
new file mode 100644
index 0000000..526fb26
--- /dev/null
+++ b/odb/src/aux/runcmd.c
@@ -0,0 +1,87 @@
+
+/* Author: Sami Saarinen, ECMWF, 26-Feb-2002 */
+
+#include "odb.h"
+
+PUBLIC void
+runcmd_(int *myproc,
+	int *nproc,
+	const char *cmd,
+	int *retcode
+	/* Hidden arguments */
+	,int  cmd_len)
+{
+  int Myproc = *myproc; /* Assumed to be numbered from 1 to Nproc, inclusive */
+  int Nproc = *nproc;
+  char *env;
+  int ignore_errors = 0;
+  int myproc_offset = 0;
+  int last_myproc = Nproc;
+  int verbose = 0;
+  int i, rc = 0;
+  int old;
+  int dcount = 0; /* count of %d's or -- say -- count of %5.5d's */
+  char *c;
+  DECL_FTN_CHAR(cmd);
+
+  old = ODB_std_mem_alloc(1); /* Always enforce standard memory alloc
+				 since we intend *not* to rely on libodb.a's memory alloc */
+
+  ALLOC_FASTFTN_CHAR(cmd);
+
+  env = getenv("MPI_SCHEDULER_IGNORE_ERRORS");
+  if (env) ignore_errors = atoi(env);
+  env = getenv("MPI_SCHEDULER_MYPROC_OFFSET");
+  if (env) myproc_offset = atoi(env);
+  env = getenv("MPI_SCHEDULER_LAST_MYPROC");
+  if (env) last_myproc = atoi(env);
+  env = getenv("MPI_SCHEDULER_VERBOSE");
+  if (env) verbose = atoi(env);
+
+  i = Myproc + myproc_offset;
+  if (i > last_myproc) goto finish;
+
+  c = p_cmd;
+  while (*c) {
+    if (*c++ == '%') dcount++;
+  }
+
+  ALLOC(c, strlen(p_cmd) + 20 * dcount + 1);
+  sprintf(c,p_cmd,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
+	          i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i); /* Enough i's ?? ; must be >= dcount */
+
+  if (verbose) {
+    printf("(PE#%d): Executing '%s'\n", Myproc, c);
+    fflush(stdout);
+  }
+
+  rc = system(c);
+
+  if (ignore_errors) rc = 0;
+
+  if (rc != 0) {
+    printf("***Errors found on PE#%d : rc=%d\n", Myproc, rc);
+    if (!verbose) printf("Command was on PE#%d : '%s'\n",Myproc,c);
+    fflush(stdout);
+  }
+  FREE(c);
+
+ finish:
+
+  FREE_FASTFTN_CHAR(cmd);
+
+  (void) ODB_std_mem_alloc(old); /* Restore old settings */
+  *retcode = rc;
+}
diff --git a/odb/src/aux/simul.c b/odb/src/aux/simul.c
new file mode 100644
index 0000000..5064536
--- /dev/null
+++ b/odb/src/aux/simul.c
@@ -0,0 +1,305 @@
+#include "odb.h"
+
+extern FILE *CMA_get_fp(const int *unit);
+
+
+static int linecnt = 0;
+
+PRIVATE int
+readline(FILE *fp, char line[], int linelen, int skip_comment_lines)
+{
+  int ilen = 0;
+  while (fp && !feof(fp) && fgets(line, linelen, fp)) {
+    linecnt++;
+#ifdef DEBUG
+    if (linecnt < 30) fprintf(stderr,"dbg-line#%d:%s",linecnt,line);
+#endif
+    ilen = strlen(line);
+    if (ilen > 0 && line[ilen-1] == '\n') { line[ilen-1] = '\0'; ilen--; }
+    if (skip_comment_lines) {
+      char *p = line;
+      while (*p && isspace(*p)) p++;
+      ilen = strlen(p);
+      /* fprintf(stderr,"dbg-line[ilen=%d]#%d:<%s>\n",ilen,linecnt,p); */
+      if (*p == '#' || *p == '!' || ilen == 0) continue;
+    }
+    if (ilen > 0) break;
+  }
+  return ilen;
+}
+
+
+PRIVATE int
+findcol(const char *target, const char *from)
+{
+  int n = 0;
+  if (target && from) {
+    char *p;
+    char *s = NULL;
+    int len = strlen(target) + 3;
+    ALLOC(s, len);
+    sprintf(s,"/%s/",target);
+    p = strstr(from,s);
+    if (p) {
+      while (*from && from <= p) {
+	if (*from++ == '/')  n++;
+      }
+    }
+    FREE(s);
+  }
+#ifdef DEBUG
+  fprintf(stderr,"findcol: n=%d, target='%s'\n",n,target);
+#endif
+  return n;
+}
+
+
+PRIVATE double
+evaluate(const char *value, double Missing_Data_Indicator, int is_string)
+{
+  union {
+    double d;
+    char s[sizeof(double)+1];
+  } jack;
+
+  const char *saved = value;
+
+  if (*value == '"') {
+    char *v = STRDUP(value);
+    char *pv = v;
+    int ilen, iptr, dsz=sizeof(double);
+    char *p = strchr(++pv, '"');
+    if (p) *p = '\0';
+    ilen = strlen(pv);
+    iptr = MAX(0,dsz - ilen);
+    memset(jack.s,' ',dsz);
+    strncpy(&jack.s[iptr],pv,dsz);
+    FREE(v);
+  }
+  else if (strequ(value,"NULL")) {
+    jack.d = Missing_Data_Indicator;
+  }
+  else if (is_string) {
+    int dsz=sizeof(double);
+    int ilen = strlen(value);
+    int iptr = MAX(0,dsz - ilen);
+    memset(jack.s,' ',dsz);
+    strncpy(&jack.s[iptr],value,dsz);
+  }
+  else {
+    jack.d = atof(value);
+  }
+  jack.s[sizeof(double)] = '\0';
+
+  /*
+  {
+    char s[sizeof(double)+1];
+    char *pin = jack.s;
+    char *pout = s;
+    memset(s,' ',sizeof(double));
+    while (*pin) { 
+      if (*pin >= ' ' && *pin < 127) *pout++ = *pin;
+      else *pout++ = '?';
+      pin++;
+    }
+    s[sizeof(double)] = '\0';
+    fprintf(stderr,"evaluate: %s => (%.20g,'%s')\n",saved,jack.d,s);
+  }
+  */
+
+  return jack.d;
+}
+
+
+PUBLIC void
+read_basic_info_(const int *io,
+		 char *tblname,
+		 int *nrows,
+		 int *ncols,
+		 int *poolno,
+		 int *width,
+		 int *retcode
+		 /* Hidden arguments */
+		 , const int tblname_len)
+{
+  int i, rc = 0;
+  FILE *fp = CMA_get_fp(io);
+  DECL_FTN_CHAR(tblname);
+  char line[80];
+
+  ALLOC_OUTPUT_FTN_CHAR(tblname);
+  *nrows = 0;
+  *ncols = 0;
+  *poolno = 0;
+  *width = sizeof(line);
+
+  if (fp && !feof(fp)) {
+    int finish = 0;
+    linecnt = 0;
+    if (readline(fp,line,sizeof(line), 0) > 0) {
+      char *p = line;
+      while (*p && (*p == '#' || *p == '!' || *p == '@' || isspace(*p))) p++;
+      strncpy(p_tblname, p, tblname_len);
+    }
+    while (!finish) {
+      if (readline(fp,line,sizeof(line), 0) > 0) {
+	char *p = line;
+	while (*p && (*p == '#' || *p == '!' || isspace(*p))) p++;
+	/* fprintf(stderr,"dbg(3):%s\n",p); */
+	if (strnequ(p,"/nrows=",7)) {
+	  if (sscanf(p+7,"%d",nrows) == 1) /*fprintf(stderr,"dbg:nrows=%d\n",*nrows)*/;
+	}
+	else if (strnequ(p,"/ncols=",7)) {
+	  if (sscanf(p+7,"%d",ncols) == 1) /*fprintf(stderr,"dbg:ncols=%d\n",*ncols)*/;
+	}
+	else if (strnequ(p,"/poolno=",8)) {
+	  if (sscanf(p+8,"%d",poolno) == 1) /*fprintf(stderr,"dbg:poolno=%d\n",*poolno)*/;
+	}
+	else if (strnequ(p,"/width=",7)) {
+	  if (sscanf(p+7,"%d",width) == 1) /*fprintf(stderr,"dbg:width=%d\n",*width)*/;
+	}
+	else if (strnequ(p,"/END",4)) {
+	  finish = 1;
+	}
+      }
+      else if (feof(fp)) {
+	finish = 1;
+      }
+    } 
+    COPY_2_FTN_CHAR(tblname);
+  }
+
+  /* finish: */
+  FREE_FTN_CHAR(tblname);
+
+  *retcode = rc;
+}
+
+
+PUBLIC void
+read_col_info_(const int *io,
+	       const char *cvarall,
+	       const double *mdi,
+	       double z[],
+	       const int is_string[],
+	       const int *ncols_aux,
+	       int colmap[],
+	       const int *ncols,
+	       const int *width,
+	       int *retcode
+	       /* Hidden arguments */
+	       , int cvarall_len)
+{
+  int rc = 0;
+  double Mdi = *mdi;
+  int Ncolz = *ncols_aux;
+  int Ncolmap = *ncols;
+  FILE *fp = CMA_get_fp(io);
+  DECL_FTN_CHAR(cvarall);
+
+  ALLOC_FTN_CHAR(cvarall);
+
+  if (fp && !feof(fp)) {
+    int finish = 0;
+    int bufsize = 1 + MAX(*width, 80);
+    char *line = NULL;
+    ALLOC(line,bufsize);
+    while (!finish) {
+      if (readline(fp, line, bufsize, 1) > 0) {
+	char *p = line;
+	while (*p && isspace(*p)) p++;
+	if (*p) {
+	  char *eq_sign = strchr(p,'=');
+	  /* fprintf(stderr,"dbg(1):%s\n",p); */
+	  if (eq_sign) {
+	    int icol;
+	    char *colname = p;
+	    char *value = eq_sign + 1;
+	    *eq_sign = '\0';
+	    icol = findcol(colname,p_cvarall);
+	    if (icol >= 1 && icol <= Ncolz) {
+	      z[icol-1] = evaluate(value, Mdi, is_string[icol-1]);
+	    }
+	    else {
+	      fprintf(stderr,
+		      "***Error: Unrecognized variable/value in assignment: %s=%s\n",
+		      colname,value);
+	      rc++;
+	    }
+	  }
+	  else {
+	    int k = 0;
+	    for (;k<Ncolmap;) {
+	      int icol;
+	      char *colname = p;
+	      char *next = strchr(p,',');
+	      /* fprintf(stderr,"dbg(2):p=<%s>,next=<%s>\n",p,next?next:"NIL"); */
+	      if (next) {
+		*next++ = '\0';
+		while (*next && isspace(*next)) next++;
+	      }
+	      icol = findcol(colname,p_cvarall);
+	      if (icol >= 1 && icol <= Ncolz) {
+		colmap[k++] = icol;
+	      }
+	      else {
+		fprintf(stderr,"***Error: Unrecognized column name: %s\n",colname);
+		rc++;
+	      }
+	      if (!next) break;
+	      p = next;
+	    }
+	    finish = 1;
+	  }
+	}
+      }
+      else
+	finish = 1;
+    }
+    FREE(line);
+  }
+
+  /* finish: */
+  FREE_FTN_CHAR(cvarall);
+
+  *retcode = rc;
+}
+
+
+PUBLIC void
+read_row_data_(const int *io,
+	       const double *mdi,
+	       double z[],
+	       const int colmap[],
+	       const int *ncols,
+	       const int *width,
+	       int *retcode)
+{
+  int rc = 0; 
+  FILE *fp = CMA_get_fp(io);
+
+  if (fp && !feof(fp)) {
+    double Mdi = *mdi;
+    int j,Nz = *ncols;  
+    int bufsize = 1 + MAX(*width, 80);
+    char *line = NULL;
+    ALLOC(line,bufsize);
+    if (readline(fp, line, bufsize, 1) > 0) {
+      char *p = line;
+      while (p && *p && isspace(*p)) p++;
+      for (j=0; p && *p && j<Nz; j++) {
+	char *next = strchr(p,',');
+	if (next) {
+	  *next++ = '\0';
+	  while (next && *next && isspace(*next)) next++;
+	}	      
+	z[j] = evaluate(p, Mdi, colmap[j] < 0);
+	rc++;
+	p = next;
+      }
+    }
+    FREE(line);
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/aux/swapbytes.c b/odb/src/aux/swapbytes.c
new file mode 100644
index 0000000..de029f9
--- /dev/null
+++ b/odb/src/aux/swapbytes.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <signal.h>
+#include <math.h>
+
+#include "swapbytes.h"
+
+PUBLIC void
+swap1bytes_(void *v, const int *vlen)
+{
+  /* does nothing; for convenience */
+}
+
+PUBLIC void
+swap2bytes_(void *v, const int *vlen)
+{
+  unsigned short int *u = v;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap16bits(u[j]);
+  }
+}
+
+PUBLIC void
+swap2bytes_via_copy_(void *v, const void *vin, const int *vlen)
+{
+  unsigned short int *u = v;
+  const unsigned short int *uin = vin;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap16bits(uin[j]);
+  }
+}
+
+PUBLIC void
+swap4bytes_(void *v, const int *vlen)
+{
+  unsigned int *u = v;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap32bits(u[j]);
+  }
+}
+
+PUBLIC void
+swap4bytes_via_copy_(void *v, const void *vin, const int *vlen)
+{
+  unsigned int *u = v;
+  const unsigned int *uin = vin;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap32bits(uin[j]);
+  }
+}
+
+PUBLIC void
+swap8bytes_(void *v, const int *vlen)
+{
+  u_ll_t *u = v;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap64bits(u[j]);
+  }
+}
+
+PUBLIC void
+swap8bytes_via_copy_(void *v, const void *vin, const int *vlen)
+{
+  u_ll_t *u = v;
+  const u_ll_t *uin = vin;
+  int j,ulen = vlen ? *vlen : 0;
+  for (j=0; j<ulen; j++) {
+    u[j] = bswap64bits(uin[j]);
+  }
+}
+
+PUBLIC void
+swapANYbytes(void *v, int elsize, int n, unsigned int dtype, 
+	     const char *dtype_name, const char *varname)
+{
+  union {
+    odb_types_t t;
+    unsigned int ui;
+  } u;
+  u.ui = (dtype << 8); /* shift over the pmethod-member */
+#ifdef DEBUG
+  fprintf(stderr,
+	  "swapANYbytes(%s:%s): elsize=%d, n=%d, dtype=%u (0x%x)\n",
+	  dtype_name, varname, elsize, n, dtype, dtype);
+  fprintf(stderr,
+	  "\tpmethod=%u,sign=%u,bswaple=%u,prec=%u,base=%u,other=%u (0x%x)\n",
+	  u.t.pmethod,u.t.signbit,u.t.byte_swappable,u.t.precision_bits,
+	  u.t.base_type,u.t.other_type);
+#endif
+  if (u.t.byte_swappable) {
+    double bits = (1 << u.t.precision_bits); /* pow(2,u.t.precision_bits); */
+#ifdef DEBUG
+    fprintf(stderr,"\tbits=%.20g := 2^%u\n",bits,u.t.precision_bits);
+#endif
+    if (bits == 16 && elsize == 2) {
+      swap2bytes_(v, &n);
+    }
+    else if (bits == 32 && elsize == 4) {
+      swap4bytes_(v, &n);
+    }
+    else if (bits == 64 && elsize == 8) {
+      swap8bytes_(v, &n);
+    }
+    else {
+      fprintf(stderr,
+	      " ***Error in swapANYbytes() [elsize=%d]: Can't swap bytes for dtype=0x%x (type=%s, var='%s')\n",
+	      elsize, dtype, dtype_name, varname);
+      fprintf(stderr,
+	      "signbit=%u, byte_swappable=%u, precision_bits=%u, base_type=%u, other_type=0x%x (%u)\n",
+	      u.t.signbit, u.t.byte_swappable, u.t.precision_bits,
+	      u.t.base_type, u.t.other_type, u.t.other_type);
+      RAISE(SIGABRT);
+    }
+  }
+}
+
diff --git a/odb/src/aux/upcma.c b/odb/src/aux/upcma.c
new file mode 100644
index 0000000..4218328
--- /dev/null
+++ b/odb/src/aux/upcma.c
@@ -0,0 +1,638 @@
+#define UPCMA_C 1
+
+#include "pcma.h"
+
+#define UPCMA_INFOLEN (PCMA_HDRLEN + 1)
+
+static 
+int (*unpack_func_list[MAXPACKFUNC])
+     (int method,
+      int swp, int can_swp_data,
+      int new_version,
+      const unsigned int packed_data[], 
+      int len_packed_data,
+      int msgbytes,
+      double nmdi,
+      double rmdi,
+      FILE *fp_out, 
+      const int idx[], int idxlen,
+      int fill_zeroth_cma,
+      double cma[], int lencma) = 
+{
+  upcma_1_driver,  /* Method 1 : adaptive, averaged */
+  upcma_2_driver,  /* Method 2 : Integer ZERO, RMDI_1 & RMDI_2 packing */
+  upcma_3_driver,  /* Method 3 : Lempel-Ziv-Welch (does not vectorize) */
+  upcma_5_driver,  /* Method 5 : Same as 2, but also compresses small numbers [1..255] */
+  upcma_9_driver,  /* Method 9 : repeated word */
+  /* Methods 11..19 : 10 + # of signicant digits ; loss of flp. pnt. accurracy */
+  upcma_11to19_driver, 
+  /* Methods 21..29 : 20 + # of signicant digits ; loss of flp. pnt. accurracy ;
+     with 10^exponent scaling (a sort of merger of method#1 and methods#11..19) */
+  upcma_21to29_driver, 
+  upcma_4_driver,  /* Method 4 : Delta packing (does not vectorize) */
+  upcma_4_driver,  /* Method 94 : Just a filler/pseudo-method for use by pcma_9.c */
+  upcma_31to39_driver, /* Methods 31..39 : The same as 21..29, but preserves 32-bit ints */
+};
+
+
+PUBLIC int
+upcma_hdr(FILE *fp_in, int *swp,
+	  unsigned int *hdr, int read_hdr,
+	  int *method, int *replen, int *msgbytes,
+	  double *nmdi, double *rmdi,
+	  int *new_version)
+{
+  int rc = 0;
+  int errflg = 0;
+  unsigned int word4 = 0;
+  unsigned int undef =  0x8B8B8B8B;
+
+  *swp = 0;
+  *nmdi = undef;
+  *rmdi = undef;
+  *new_version = 0;
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "upcma_hdr(fp_in=%p, read_hdr=%d) : HDRLEN=%d\n",
+	  fp_in, read_hdr, HDRLEN);
+#endif
+
+  rc = (fp_in && read_hdr) ? fread(hdr, sizeof(*hdr), HDRLEN, fp_in) : HDRLEN;
+
+  if (rc != HDRLEN) {
+    if (fp_in && feof(fp_in)) rc = 0;
+  }
+  else {
+    const int hdrlen = HDRLEN;
+    *swp = (hdr[0] == AMCP) ? 1 : 0;
+
+#ifdef DEBUG
+    fprintf(stderr,"upcma_hdr(0): swap bytes (*swp) is %d\n",*swp);
+#endif
+
+    if (*swp) swap4bytes_(hdr,&hdrlen); /* swap bytes */
+
+#ifdef DEBUG
+    fprintf(stderr,"upcma_hdr(1): hdr[0]=%u, PCMA=%u\n",hdr[0],PCMA);
+#endif
+
+    if (hdr[0] == PCMA) {
+      *new_version = PCMA_NEW_VERSION(hdr); /* Also the same as PCMA_HDRLEN - HDRLEN, if new */
+      *method   = hdr[1]/MAXSHIFT;
+      *replen   = hdr[1]%MAXSHIFT;
+      *msgbytes = hdr[2];
+      if (*swp) swap4bytes_(hdr,&hdrlen); /* restore */
+
+#ifdef DEBUG
+      fprintf(stderr,
+	      "upcma_hdr(2): *new_version=%d, *method=%d, *replen=%d, *msgbytes=%d\n",
+	      *new_version, *method, *replen, *msgbytes);
+#endif
+
+      if (*new_version) {
+	int rc2 = (fp_in && read_hdr) ? 
+	  fread(&hdr[3], sizeof(*hdr), *new_version, fp_in) : *new_version;
+	if (rc2 != *new_version) {
+	 if (fp_in && feof(fp_in)) 
+	   rc = 0;
+	 else 
+	   errflg++;
+	}
+	else {
+	  const int one = 1;
+	  const int two = 2;
+	  *replen = hdr[3];
+	  if (*swp) swap4bytes_(replen,&one); /* swap bytes */
+	  word4 = *replen;
+	  if (*swp) swap8bytes_(&hdr[4],&two); /* swap bytes */
+	  memcpy(nmdi, &hdr[4], sizeof(*nmdi));
+	  memcpy(rmdi, &hdr[6], sizeof(*rmdi));
+	  if (*swp) swap8bytes_(&hdr[4],&two); /* restore */
+	  rc += *new_version;
+	}
+      }
+      else {
+	/* old version */
+	*nmdi = NMDI;
+	*rmdi = RMDI;
+	*new_version = 0;
+      } /* if (*new_version) ... else */
+    }
+    else {
+      errflg++;
+    }
+
+    if (errflg) {
+      perror("upcma_hdr(unrecognized msg)"); /* Remove this later on ... */
+      fprintf(stderr,"hdr[0] = %u : Should be = %u (PCMA)\n",hdr[0],PCMA);
+      fprintf(stderr,"hdr[1] = %u : Should be = method & {report length or zero}\n",hdr[1]);
+      fprintf(stderr,"hdr[2] = %u : Should be = No. of packed bytes\n",hdr[2]);
+      fprintf(stderr,"The following are present only if the report length in hdr[1] is zero:\n");
+      fprintf(stderr,"word4  = %u ; Should be = report length (in new version)\n",word4);
+      fprintf(stderr,"nmdi   = %.20g ; Should be = NMDI used in the msg\n",*nmdi);
+      fprintf(stderr,"rmdi   = %.20g ; Should be = RMDI used in the msg\n",*rmdi);
+      rc = -2; /* Unrecognized message */
+    }
+
+  }
+
+  return rc;
+}
+
+
+PUBLIC int 
+upcma_data(FILE *fp_in, const unsigned int *hdr, 
+	   int new_version,
+	   unsigned int *packed_data, int count)
+{
+  int rc = 0;
+  int hdrlen = HDRLEN;
+
+  if (hdr) {
+    new_version = PCMA_NEW_VERSION(hdr);
+    hdrlen += new_version;
+    memcpy(packed_data, hdr, hdrlen);
+  }
+  else
+    hdrlen += new_version;
+
+  count -= hdrlen;
+  packed_data += hdrlen;
+
+  rc = fread(packed_data, sizeof(*packed_data), count, fp_in);
+
+  if (rc != count) {
+    perror("upcma_data(rc != count)"); /* Remove this later on ... */
+    rc = -4; /* Not all data was read */
+    if (feof(fp_in)) rc = 0; /* Unexpected EOF */
+  }
+  else
+    rc += hdrlen;
+
+  return rc;
+}
+
+
+
+PUBLIC int
+upcma(          int can_swp_data,
+              FILE *fp_in,
+              FILE *fp_out,
+	 const int  idx[], int  idxlen,
+	       int  fill_zeroth_cma,
+            double  cma[],
+              int   lencma,
+     unsigned int  *hdr_in,
+	  Packbuf  *pbuf,
+              int  *bytes_in,
+              int  *bytes_out
+      )
+{
+  int rc = 0;
+  unsigned int hdr[PCMA_HDRLEN];
+  double *ptrcma = cma;
+  double *cmabuf = NULL;
+  int maxalloc_cma = 0;
+  int maxalloc_pcma = 0;
+  unsigned int *packed_data = NULL;
+
+  *bytes_in  = 0;
+  *bytes_out = 0;
+
+  if (fp_out || lencma > 0) {
+    if (fp_out) {
+      ALLOC(cmabuf, pcma_blocksize);
+      maxalloc_cma = pcma_blocksize;
+    }
+
+    ALLOC(packed_data, pcma_blocksize);
+    maxalloc_pcma = pcma_blocksize;
+  }
+
+  while (fp_out || lencma > 0) {
+    int hdrlen = HDRLEN;
+    int swp, new_version;
+    int method, replen, msgbytes;
+    double nmdi, rmdi;
+    int count;
+    unsigned int *phdr = hdr_in ? hdr_in : hdr;
+
+    rc = upcma_hdr(fp_in, &swp,
+		   phdr, (hdr_in == NULL),
+		   &method, &replen, &msgbytes,
+		   &nmdi, &rmdi,
+		   &new_version);
+    hdr_in = NULL;
+
+    hdrlen += new_version;
+
+    if (rc == hdrlen) {
+      switch (method) {
+
+      case 1: 
+      case 2:
+      case 5:
+      case 9:
+      case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19:
+      case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29:
+      case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
+      case 4:  case 94:
+	if (sizeof(double)/sizeof(unsigned int) != 2) {
+	  fprintf(stderr,
+		  "upcma(#%d): There ain't exactly two uint words per double prec. word\n",
+		  method);
+	  rc = -2;
+	  goto finish;
+	}
+	if (method == 4) {
+	  if (sizeof(u_ll_t)/sizeof(unsigned int) != 2) {
+	    fprintf(stderr,
+		    "upcma(#%d): There ain't exactly two uint words per unsigned long long int\n",
+		    method);
+	    rc = -7;
+	    goto finish;
+	  }
+	}
+	break;
+      case 3:
+	break;
+      default:
+	/* Unpacking not implemented yet for this method */
+	fprintf(stderr,"upcma(#%d): Unpacking method not implemented\n",method);
+	rc = -3;
+	goto finish;
+      } /* switch (method) */
+
+      if (fp_out) {
+	if (replen > maxalloc_cma) {
+	  REALLOC(cmabuf, replen);
+	  maxalloc_cma = replen;
+	}
+	ptrcma = cmabuf;
+      }
+      else {
+	if (replen > lencma) {
+	  fprintf(stderr,
+	  "upcma(#%d): Not enough space reserved for (external) CMA-array. Short %d words\n",
+		  method, replen - lencma);
+	  rc = -5;
+	  goto finish;
+	}
+      }
+      
+      count = hdrlen + RNDUP(msgbytes,b4)/b4; /* Total no. of packed uint words in msg */
+
+      if (count > maxalloc_pcma) {
+	REALLOC(packed_data, count);
+	maxalloc_pcma = count;
+      } 
+
+      rc = upcma_data(fp_in, NULL, new_version, packed_data, count);
+      if (rc != count) goto finish;
+
+      if (pbuf) { 
+	/* Return packed data to the caller */
+	pbuf->counter = 0;
+	pbuf->maxalloc = count;
+	pbuf->len = count;
+	ALLOC(pbuf->p,count); /* Beware of dangling pointers; 
+				 doesn't check whether pbuf->p was already allocated !! */
+	/* Note: packed_data did NOT contain the 'hdr' */
+	memcpy(pbuf->p, phdr, hdrlen * sizeof(*phdr));
+	/* And now the rest */
+	memcpy(&pbuf->p[hdrlen], &packed_data[hdrlen], (count-hdrlen) * sizeof(*packed_data));
+	pbuf->allocatable = 1;
+      }
+      
+      rc = unpack_func_list[look_up[method]](method,
+					     swp, can_swp_data,
+					     new_version,
+					     &packed_data[hdrlen],
+					     count-hdrlen,         /* excluding header */
+					     msgbytes,
+					     nmdi, rmdi,
+					     fp_out, 
+					     idx, idxlen,
+					     fill_zeroth_cma,
+					     ptrcma, replen);
+
+      if (rc != replen) {
+	fprintf(stderr,"upcma(#%d): rc=%d, replen=%d\n", method, rc, replen);
+	goto finish;
+      }
+
+      if (!fp_out) {
+	ptrcma += replen;
+	lencma -= replen;
+      }
+
+      *bytes_in  += count * b4;
+      *bytes_out += replen * sizeof(double);
+    }
+    else {
+      if (feof(fp_in))
+	rc = 0;  /* EOF => no error */
+      else
+	rc = -6; /* Error */
+      goto finish;
+    }
+  } /* while (fp_out || lencma > 0) */
+
+ finish:
+  FREE(packed_data);
+  FREE(cmabuf);
+
+  return rc;
+}
+
+
+PUBLIC void
+upcmaTOcma(const          int *can_swp_data,
+	   const unsigned int  packed_hdr[],
+           const unsigned int  packed_stream[],
+	            const int  idx[], int  idxlen,
+	                  int  fill_zeroth_cma,
+                       double  cma[],
+                    const int *lencma,
+                          int *retcode)
+{
+  int rc = 0;
+  int hdrlen = HDRLEN;
+  int swp, new_version;
+  const unsigned int *hdr  = &packed_hdr[0];
+  const unsigned int *data = &packed_stream[0];
+  int method, replen, msgbytes;
+  double nmdi, rmdi;
+
+  rc = upcma_hdr(NULL, &swp,
+		 (unsigned int *)hdr, 0,
+		 &method, &replen, &msgbytes,
+		 &nmdi, &rmdi,
+		 &new_version);
+
+#ifdef DEBUG
+  fprintf(stderr,"upcmaTOcma(): swp=%d, *can_swp_data=%d\n",swp,*can_swp_data);
+#endif
+
+  hdrlen += new_version;
+
+  if (rc != hdrlen) {
+    /* Error : Possibly not a packed CMA-report at all */
+    rc = -1;
+  }
+  else if (replen > *lencma) {
+    /* Error : Not enough room reserved for unpacked data in cma[] -array */
+    rc = -2;
+  }
+  else {
+    int count   = hdrlen + RNDUP(msgbytes,b4)/b4; /* Total no. of packed uint words in msg */
+    int datalen = count - hdrlen;
+
+    if (   method == 2
+	|| method == 3
+	|| method == 5
+	|| method == 9
+	|| method == 1
+	|| (method >= 11 && method <= 19)
+	|| (method >= 21 && method <= 29)
+	|| (method >= 31 && method <= 39)
+	|| method == 4
+	|| method == 94
+	) {
+      rc = unpack_func_list[look_up[method]](method,
+					     swp, *can_swp_data,
+					     new_version,
+					     data,
+					     datalen,
+					     msgbytes,
+					     nmdi, rmdi,
+					     NULL,
+					     idx, idxlen,
+					     fill_zeroth_cma,
+					     cma, replen);
+      if (rc != replen) {
+	/* Error: Unable to decode exactly the replen no. of CMA-words */
+	rc = -3;
+      }
+    }
+    else {
+      /* Error: Invalid packing method; or at least no unpacking available */
+      rc = -4;
+    }
+  }
+
+  *retcode = rc;
+}
+
+
+PUBLIC double *
+UnPackDoubles(const void *pk,
+	      const int nbytes,
+	      int *nv)
+{
+  const int min_bytes = 2 * sizeof(uint);
+  double *v = NULL;
+  int Nv = 0;
+  if (pk && nbytes >= min_bytes) {
+    const uint *Pk = pk;
+    int Nbytes = (int)Pk[0];
+    Nv = (int)Pk[1];
+    ALLOC(v, Nv);
+    if (Nbytes == -1) {
+      /* Not packed at all */
+      int nv_bytes = Nv * sizeof(double);
+      memcpy(v, &Pk[2], nv_bytes);
+    }
+    else if (Nv > 0) {
+      int rc = 0;
+      int nv_bytes = Nv * sizeof(double);
+      lzw_unpack_((const unsigned char *)&Pk[2], &Nbytes,
+                (unsigned char *)v, &nv_bytes,
+                &rc);
+      if (rc == nv_bytes) {
+	rc /= sizeof(double);
+	rc = (rc == Nv) ? Nv : -ABS(rc);
+      }
+      else {
+	rc = -ABS(rc);
+      }
+      if (rc /= Nv) {
+	FREE(v);
+	Nv = rc;
+      }
+    } /* if (Nv > 0) */
+  }
+  if (nv) *nv = Nv;
+  return v;
+}
+
+/*============= Intended for Fortran-access, but rather general ===============*/
+
+void 
+upcma_info_(const unsigned int  packed_hdr[],
+	                   int  info[],
+	             const int *infolen,
+	                   int *retcode)
+     /* Intended for Fortran-access, but rather general 
+	NOTE: Data assumed to be in packed_stream and thus
+	      no I/O is performed to get it there */
+{
+  int rc = 0;
+  int hdrlen = HDRLEN;
+  int swp, new_version;
+  const unsigned int *hdr  = &packed_hdr[0];
+  int method, replen, msgbytes;
+  double nmdi, rmdi;
+
+  rc = upcma_hdr(NULL, &swp,
+		 (unsigned int *)hdr, 0,
+		 &method, &replen, &msgbytes,
+		 &nmdi, &rmdi,
+		 &new_version);
+
+  hdrlen += new_version;
+
+  if (rc != hdrlen) {
+    /* Error : Possibly not a packed CMA at all */
+    rc = -1;
+  }
+  else {
+    int jlen, j;
+    int Info[UPCMA_INFOLEN];
+    int count   = hdrlen + RNDUP(msgbytes,b4)/b4; /* Total no. of packed uint words in msg */
+    int datalen = count - hdrlen;
+    
+    Info[1-1] = replen;   /* CMA report length (when unpacked) */
+    Info[2-1] = method;   /* Packing method */
+    Info[3-1] = hdrlen;   /* Length of packed header, in unsigned ints */
+    Info[4-1] = datalen;  /* Length of packed data (after hdr), in unsigned ints */
+    Info[5-1] = msgbytes; /* Exact no. of bytes packed in data part (i.e. msgbytes <= 4*datalen) */
+    memcpy(&Info[6-1], &nmdi, sizeof(nmdi));
+    memcpy(&Info[8-1], &rmdi, sizeof(rmdi));
+    
+    jlen = MIN(*infolen, UPCMA_INFOLEN);
+    jlen = MAX(0, jlen);
+    for (j=0; j<jlen; j++) {
+      info[j] = Info[j];
+    }
+
+    rc = jlen;
+  }
+
+  *retcode = rc;
+}
+
+
+void
+pcma2cma_(const          int *can_swp_data,
+	  const unsigned int  packed_data[],
+	           const int *packed_len,
+	           const int  idx[], const int *idxlen,
+	           const int *fill_zeroth_cma,
+                      double  cma[],
+                   const int *lencma,
+                         int *packed_count,
+                         int *retcode)
+{
+  int rc = 0;
+  int pklen = *packed_len;
+  int cmalen = *lencma;
+  const unsigned int *pdata = packed_data;
+  double *ptr_cma = cma;
+
+  *packed_count = 0;
+  *retcode = 0;
+
+  while (rc >= 0 && pklen > HDRLEN && cmalen > 0) { /* yes: HDRLEN, *not* PCMA_HDRLEN */
+    int hdrlen = HDRLEN;
+    int swp, new_version;
+    const unsigned int *hdr  = pdata;
+    const unsigned int *data;
+    int method, replen, msgbytes;
+    double nmdi, rmdi;
+
+    rc = upcma_hdr(NULL, &swp,
+		   (unsigned int *)hdr, 0,
+		   &method, &replen, &msgbytes,
+		   &nmdi, &rmdi,
+		   &new_version);
+
+    hdrlen += new_version;
+    data = pdata + hdrlen;
+
+    /*
+    fprintf(stderr,
+	    "pcma2cma_(): method=%d, replen=%d, msgbytes=%d, swp=%d, can_swp=%d, new_version=%d\n",
+	    method, replen, msgbytes, swp, *can_swp_data, new_version);
+    */
+
+    if (rc != hdrlen) {
+      /* Error : Possibly not a packed CMA-report at all */
+      rc = -1;
+    }
+    else if (replen > cmalen) {
+      /* NOT an error: Not enough room left for unpacked data in cma[] -array */
+      break;
+    }
+    else {
+      int count   = hdrlen + RNDUP(msgbytes,b4)/b4; /* Total no. of packed uint words in msg */
+      int datalen = count - hdrlen;
+      
+      if (   method == 2
+	  || method == 3
+	  || method == 5
+	  || method == 9
+	  || method == 1
+	  || (method >= 11 && method <= 19)
+	  || (method >= 21 && method <= 29)
+	  || (method >= 31 && method <= 39)
+	  || method == 4
+	  || method == 94
+	  ) {
+	rc = unpack_func_list[look_up[method]](method,
+					       swp, *can_swp_data,
+					       new_version,
+					       data,
+					       datalen,
+					       msgbytes,
+					       nmdi, rmdi,
+					       NULL,
+					       idx, *idxlen,
+					       *fill_zeroth_cma,
+					       ptr_cma, replen);
+
+	/*
+	if (replen >= 3) {
+	  fprintf(stderr,
+		  "\tunpack: rc=%d; replen=%d, cma[0]=%.20g; cma[1]=%.20g .. cma[last]=%.20g\n",
+		  rc, replen, ptr_cma[0], ptr_cma[1], ptr_cma[replen-1]);
+	}
+	*/
+
+	/* printf("rc=%d, count=%d, datalen=%d\n",rc, count, datalen); */
+
+	if (rc != replen) {
+	  /* Error: Unable to decode exactly the replen no. of CMA-words */
+	  rc = -3;
+	}
+      }
+      else {
+	/* Error: Invalid packing method; or at least no unpacking available */
+	rc = -4;
+      }
+
+      pklen  -= count;
+      cmalen -= replen;
+      *packed_count += count;
+      *retcode += replen;
+      pdata  += count;
+      ptr_cma += replen;
+    } /* else */
+
+  } /* while (rc >= 0 && pklen > HDRLEN && cmalen > 0) */
+
+
+  if (rc < 0) *retcode = rc;
+}
+
diff --git a/odb/src/aux/util.c b/odb/src/aux/util.c
new file mode 100644
index 0000000..68b469b
--- /dev/null
+++ b/odb/src/aux/util.c
@@ -0,0 +1,252 @@
+#include "pcma.h"
+#include <signal.h>
+
+#ifdef VPP
+#pragma global noalias
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+extern int
+pcma_error(const char *where,
+	   int how_much,
+	   const char *what,
+	   const char *srcfile,
+	   int srcline,
+	   int perform_abort)
+{
+  int rc = errno;
+
+  fprintf(stderr,
+	  "pcma_error: %s failed to allocate %d bytes for variable '%s' (in %s:%d)\n",
+	  where, how_much, what,
+	  srcfile, srcline);
+
+  if (perform_abort) {
+    fprintf(stderr,"pcma_error: Aborting ...\n");
+    RAISE(SIGABRT);
+  }
+
+  return rc;
+}
+
+void
+pcma_zero_uint(unsigned int u[], int n)
+{
+  int j;
+  for (j=0; j<n; j++) {
+    u[j] = 0;
+  }
+}
+
+void 
+pcma_copy_uint(      unsigned int to[],
+	       const unsigned int from[],
+	       int n)
+{
+  int j;
+  for (j=0; j<n; j++) {
+    to[j] = from[j];
+  }
+}
+
+void 
+pcma_copy_dbl(      double to[],
+	      const double from[],
+	      int n)
+{
+  int j;
+  for (j=0; j<n; j++) {
+    to[j] = from[j];
+  }
+}
+
+unsigned int *
+pcma_alloc(Packbuf *pbuf, int count)
+{
+  unsigned int *ptr = NULL;
+
+  if (pbuf) {
+    int curlen = pbuf->len;
+
+    if (curlen >= 0 && count >= 0) {
+      int newlen = curlen + count;
+
+      if (pbuf->allocatable && pbuf->maxalloc == 0) {
+	/* Initial allocation */
+	pbuf->maxalloc = MAX(count, pcma_blocksize);
+	ALLOC(pbuf->p, pbuf->maxalloc);
+	pbuf->counter++;
+      }
+
+      if (newlen > pbuf->maxalloc) {
+	if (pbuf->allocatable) {
+	  REALLOC(pbuf->p, newlen);
+	  pbuf->maxalloc = newlen;
+	  pbuf->counter++;
+	}
+	else {
+	  /* Error */
+	  pbuf->len = -newlen; /* A sort of an error code */
+	  ptr = NULL;
+	  fprintf(stderr,
+		  "pcma_alloc(): No enough space in the user pack-buffer : needed=%d, available=%d int-words\n",
+		  newlen, pbuf->maxalloc);
+	  goto finish;
+	}
+      }
+
+      if (pbuf->p) {
+	ptr = &pbuf->p[curlen];
+	pbuf->len = newlen;
+      }
+      else {
+	/* Error */
+	perror("pcma_alloc()");
+	if (pbuf->allocatable) {
+	  FREE(pbuf->p);
+	}
+	pbuf->len = -newlen; /* A sort of an error code */
+	ptr = NULL;
+	goto finish;
+      }
+    }
+  }
+  else {
+    ALLOC(ptr, count);
+  }
+
+ finish:
+  if (ptr) pcma_zero_uint(ptr, count);
+
+  return ptr;
+}
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef VPP
+#include <sys/fs/vfl.h>
+#endif
+
+#ifdef CRAYXT
+
+#include <sys/stat.h>
+#define STATVFS stat
+#define STAT_FS(p,pb) stat(p,pb)
+#define STAT_BSIZE st_blksize
+
+#elif defined(CRAY) || defined(NECSX)
+
+#include <sys/statfs.h>
+#define STATVFS statfs
+#define STAT_FS(p,pb) statfs(p,pb,sizeof(struct statfs),0)
+#define STAT_BSIZE f_bsize
+
+#else
+
+#include <sys/statvfs.h>
+#define STATVFS statvfs
+#define STAT_FS(p,pb) statvfs(p,pb)
+#define STAT_BSIZE f_bsize
+
+#endif
+
+static int
+get_path_blocksize(const char *filename)
+{
+  int blk_size = 0;
+  struct STATVFS buf;
+  char *path = STRDUP(filename);
+  char *s = strrchr(path,'/');
+
+  if (s) {
+    *s = '\0';
+  }
+  else {
+    FREE(path);
+    path = STRDUP(".");
+  }
+  
+  if (STAT_FS(path,&buf) != -1) {
+    blk_size = buf.STAT_BSIZE;
+  }
+
+  FREE(path);
+
+  return blk_size;
+}
+
+FILE *
+pcma_prealloc(const char *filename,
+	      int         prealloc,
+	      int         extent,
+	      int        *blksize,
+	      int        *retcode)
+{
+  int fd = -1;
+  int blk_size = 0;
+  FILE *fp = NULL;
+  const char *write_mode = "w";
+  unsigned char allocated = 0;
+
+  if (prealloc > 0) {
+    blk_size = get_path_blocksize(filename);
+
+#ifdef VPP
+    if (blk_size > 0) {
+      const int vfl_mode = 0664;
+      prealloc = RNDUP(prealloc,blk_size)/blk_size;
+      if (extent <= 0) extent = blk_size;
+      extent = RNDUP(extent,blk_size)/blk_size;
+
+      (void) remove(filename);
+
+      fd = vfl_create(filename, prealloc, extent,
+		      VFL_ZERO, vfl_mode,
+		      VFL_REPLACE);
+
+      if (fd == -1) {
+	perror(filename);
+      }
+      else{
+	allocated = 1;
+      }
+    }
+#endif
+  }
+
+  if (!allocated) {
+    fp = fopen(filename, write_mode);
+    if (fp) fd = fileno(fp);
+  }
+  else {
+    fp = fdopen(fd, write_mode);
+  }
+
+  if (retcode)                 *retcode  = fd;
+  if (blksize && blk_size > 0) *blksize = blk_size;
+
+  return fp;
+}
+
+
+
+int 
+pcma_filesize(const char *path)
+{
+  struct stat buf;
+  long file_size = 0;
+
+  if (stat(path,&buf) != 0) {
+    file_size = -1;
+  }
+  else {
+    file_size = buf.st_size;
+  }
+
+  return file_size;
+}
+ 
diff --git a/odb/src/aux/util_ccode.c b/odb/src/aux/util_ccode.c
new file mode 100644
index 0000000..cc548a5
--- /dev/null
+++ b/odb/src/aux/util_ccode.c
@@ -0,0 +1,148 @@
+
+/* util_ccode.c */
+
+#include <stdio.h>
+#include <string.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <signal.h>
+
+#include "alloc.h"
+
+#define FORTRAN_CALL
+
+#ifdef CRAY
+#include <fortran.h>
+#else
+#define _fcd         char *
+#define _fcdtocp(x)  x
+#endif
+
+#define COPY_TO(to,from_ftn,len) \
+{ strncpy((to),_fcdtocp((from_ftn)),(len)); (to)[(len)] = '\0'; }
+
+#define COPY_FROM(to_ftn,from,len) \
+{ strncpy(_fcdtocp(to_ftn),(from),(len)); }
+
+#define STRINGLEN(x) strlen(_fcdtocp(x))
+
+/* Not needed; We use -qextname while linking with Fortran (SS/23.07.2001)
+#ifdef RS6K
+#define util_cgetenv_  util_cgetenv
+#define util_igetenv_  util_igetenv
+#define util_abort_    util_abort
+#define util_cputime_  util_cputime
+#define util_walltime_ util_walltime
+#define util_ihpstat_  util_ihpstat
+#define util_remove_file_ util_remove_file
+#endif
+*/
+
+#ifdef CRAY
+#define util_cgetenv_  UTIL_CGETENV
+#define util_igetenv_  UTIL_IGETENV
+#define util_abort_    UTIL_ABORT
+#define util_cputime_  UTIL_CPUTIME
+#define util_walltime_ UTIL_WALLTIME
+#define util_remove_file_ UTIL_REMOVE_FILE
+#endif
+
+FORTRAN_CALL
+void util_cgetenv_(_fcd envname, _fcd def, _fcd output, 
+		  int *actual_len
+#ifndef CRAY
+		 , int envname_len, int def_len, int output_len
+#endif
+) 
+{
+#ifdef CRAY
+  int envname_len = _fcdlen(envname);
+  int def_len     = _fcdlen(def);
+  int output_len  = _fcdlen(output);
+#endif
+  char *p_envname = NULL;
+  char *p;
+  char *p_def = NULL;
+
+  ALLOC(p_envname, envname_len+1);
+
+  COPY_TO(p_envname, envname, envname_len);
+  p = getenv(p_envname);
+  FREE(p_envname);
+
+  if (!p) {
+    ALLOC(p_def, def_len+1);
+    p = p_def;
+    COPY_TO(p_def, def, def_len);
+  }
+
+  COPY_FROM(output, p, output_len);
+
+  *actual_len = (strlen(p) < output_len) ? STRINGLEN(output) : output_len;
+  if (*actual_len < output_len) {
+    memset(&_fcdtocp(output)[*actual_len],' ',output_len - *actual_len);
+  }
+
+  FREE(p_def);
+}
+
+
+FORTRAN_CALL
+void util_igetenv_(_fcd envname, int *def, int *output
+#ifndef CRAY
+		  , int envname_len
+#endif
+) 
+{
+#ifdef CRAY
+  int envname_len = _fcdlen(envname);
+#endif
+  char *p_envname = NULL;
+  char *p;
+
+  ALLOC(p_envname, envname_len+1);
+
+  COPY_TO(p_envname, envname, envname_len);
+  p = getenv(p_envname);
+
+  *output = p ? atoi(p) : *def;
+  
+  FREE(p_envname);
+}
+
+
+FORTRAN_CALL
+void util_remove_file_(_fcd file, int *rc
+#ifndef CRAY
+		  , int file_len
+#endif
+) 
+{
+#ifdef CRAY
+  int file_len = _fcdlen(file);
+#endif
+  char *p_file = NULL;
+
+  ALLOC(p_file, file_len+1);
+  
+  COPY_TO(p_file, file, file_len);
+
+  *rc = remove(p_file);
+  
+  FREE(p_file);
+}
+
+FORTRAN_CALL
+void util_abort_()
+{
+  fprintf(stderr,"util_abort_(): Raising an abort ...\n");
+  RAISE(SIGABRT);
+}
+
+/* Portable CPU-timer (User + Sys) ; also WALL CLOCK-timer */
+
+/* 
+   These have been moved to libifsaux.a, 
+   file ifsaux/support/drhook.c on 16-Jan-2004/SS,
+   to simplify linking
+*/
diff --git a/odb/src/aux/util_filehandler.c b/odb/src/aux/util_filehandler.c
new file mode 100644
index 0000000..853224b
--- /dev/null
+++ b/odb/src/aux/util_filehandler.c
@@ -0,0 +1,102 @@
+#include <stdio.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "alloc.h"
+
+void 
+util_filesize_(const char *file_in, 
+	         integer4 *iret, 
+	       /* A hidden argument */
+	              int  lenfile_in)
+{
+  struct stat buf;
+  integer4 file_size = 0;
+  char *file = NULL;
+
+  ALLOC(file, lenfile_in + 1);
+
+  memcpy(file, file_in, lenfile_in);
+  file[lenfile_in] = '\0';
+
+  if (stat(file,&buf) != 0) {
+    perror(file);
+    file_size = -1;
+  }
+  else {
+    file_size = buf.st_size;
+  }
+
+  FREE(file);
+
+  *iret = file_size;
+}
+
+
+void 
+util_readraw_(const char *file_in, 
+	            char  data[],
+	        integer4 *lendata,
+	        integer4 *iret, 
+	       /* A hidden argument */
+	             int  lenfile_in)
+{
+  int rc = 0;
+  FILE *fp;
+  char *file = NULL;
+
+  ALLOC(file, lenfile_in + 1);
+
+  memcpy(file, file_in, lenfile_in);
+  file[lenfile_in] = '\0';
+ 
+  fp = fopen(file,"r");
+  if (fp) {
+    rc = fread(data, sizeof(char), *lendata, fp);
+    fclose(fp);
+  }
+  else {
+    perror(file);
+    rc = -1;
+  }
+
+  FREE(file);
+
+  *iret = rc;
+}
+
+
+void 
+util_writeraw_(const char *file_in, 
+	             char  data[],
+	         integer4 *lendata,
+	         integer4 *iret, 
+	       /* A hidden argument */
+	              int  lenfile_in)
+{
+  int rc = 0;
+  FILE *fp;
+  char *file = NULL;
+
+  ALLOC(file, lenfile_in + 1);
+
+  memcpy(file, file_in, lenfile_in);
+  file[lenfile_in] = '\0';
+ 
+  fp = fopen(file,"w");
+  if (fp) {
+    rc = fwrite(data, sizeof(char), *lendata, fp);
+    fclose(fp);
+  }
+  else {
+    perror(file);
+    rc = -1;
+  }
+
+  FREE(file);
+
+  *iret = rc;
+}
diff --git a/odb/src/aux/util_iobuf.c b/odb/src/aux/util_iobuf.c
new file mode 100644
index 0000000..fa6e7a6
--- /dev/null
+++ b/odb/src/aux/util_iobuf.c
@@ -0,0 +1,147 @@
+/*
+
+   UTIL_ALLOC_IOBUF: Activates full, partial or no I/O-buffering for opened file
+   UTIL_FREE_IOBUF : Frees allocated I/O-buffer space
+
+   Sami Saarinen, ECMWF, 13/03/96
+     "              "    16/08/99 : Change to use filehandle via pbfp()            
+
+*/
+
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc.h"
+
+extern FILE *pbfp(integer4 khandle);
+
+/* Not needed; We use -qextname while linking with Fortran (SS/23.07.2001)
+#ifdef RS6K
+#define util_alloc_iobuf_  util_alloc_iobuf
+#define util_free_iobuf_   util_free_iobuf
+#endif
+*/
+
+#ifdef CRAY
+#define util_alloc_iobuf_  UTIL_ALLOC_IOBUF
+#define util_free_iobuf_   UTIL_FREE_IOBUF
+#endif
+
+typedef struct _Iobuf {
+  char *buffer;
+  int   length;
+} Iobuf;
+
+PRIVATE Iobuf *iobuf_data = NULL;
+PRIVATE int maxfdsize      = 0;
+
+PRIVATE void allocate_iobuf_data()
+{
+  if (!iobuf_data) {
+#ifdef CRAYXT
+    maxfdsize = sysconf(_SC_OPEN_MAX);
+#else
+    maxfdsize = getdtablesize();
+#endif
+#ifdef DEBUG
+    fprintf(stderr,"allocate_iobuf_data: maxfdsize = %d\n",maxfdsize);
+#endif
+    CALLOC(iobuf_data, maxfdsize);
+  }
+}
+
+void util_alloc_iobuf_(integer4 *khandle,      /* Already opened file handle */
+		 integer4 *ibufsize,     /* 0      : "no" buffering => use system defaults & return
+					n  < 0 : device specific optimal buffer size is allocated 
+					n  > 0 : full buffering up to n bytes
+					n != 0 : User provides the buffer space for setvbuf() */
+		 integer4 *kret)         /* Return value: 0 = successful */
+{
+  struct stat buf;
+  FILE *fp = pbfp(*khandle);
+
+  *kret = 0;
+
+  if (fstat(fileno(fp),&buf) != 0) {    
+    perror("UTIL_ALLOC_IOBUF");
+    *kret = -1;
+  }
+  else if (*ibufsize != 0) {
+    int fildes = fileno(fp);
+    int length = 0;
+    int bufsize = abs(*ibufsize);
+    int optimal_size = (buf.st_blksize > 0) ? buf.st_blksize : BUFSIZ;
+    
+    if (!iobuf_data) allocate_iobuf_data();
+    length = iobuf_data[fildes].length;
+
+    if (length == 0) {
+      int n = (*ibufsize > 0) ? 
+	((bufsize + 2*optimal_size - 1)/optimal_size) * optimal_size : 
+	  optimal_size;
+      char *buffer; 
+
+      ALLOC(buffer, n + 8); /* This is freed upon UTIL_FREE_IOBUF() */
+
+      if (!buffer) {
+	perror("UTIL_ALLOC_IOBUF");
+	*kret = -1;
+      }
+
+      if (setvbuf(fp, buffer, _IOFBF, n) != 0) {
+	perror("UTIL_ALLOC_IOBUF");
+	*kret = -1;
+      }
+
+      iobuf_data[fildes].buffer = buffer;
+      iobuf_data[fildes].length = n;
+#ifdef DEBUG
+      fprintf(stderr,
+	      "UTIL_ALLOC_IOBUF: Allocated I/O-buffer space %d bytes for fileno %d\n",
+	      n, fildes);
+#endif
+    }
+    else {
+      fprintf(stderr,
+	      "UTIL_ALLOC_IOBUF: I/O-buffer space at fileno %d was already in use\n",
+	      fildes);
+      *kret = -1;
+    }
+  } /* else if (*ibufsize != 0) */
+}
+
+
+void util_free_iobuf_(integer4 *khandle,  /* Already opened file handle */
+		      integer4 *kret)     /* Return value: 0 = successful */
+{
+  FILE *fp = pbfp(*khandle);
+  int fildes = fileno(fp);
+  *kret = 0;
+
+  if (!iobuf_data) return;
+
+  {
+    int  *length  = &iobuf_data[fildes].length;
+    char **buffer = &iobuf_data[fildes].buffer;
+
+    if (*length > 0 && *buffer) {
+#ifdef DEBUG
+      int n = *length;
+      fprintf(stderr,
+	      "UTIL_FREE_IOBUF: Released I/O-buffer space %d bytes for fileno %d\n",
+	      n, fildes);
+#endif
+      *length = 0;
+      FREE(*buffer);
+      *buffer = NULL;
+    }
+  }
+}
+
+
diff --git a/odb/src/aux/util_stat.c b/odb/src/aux/util_stat.c
new file mode 100644
index 0000000..6aee385
--- /dev/null
+++ b/odb/src/aux/util_stat.c
@@ -0,0 +1,47 @@
+
+/*
+
+   UTIL_STAT: Obtains information about the size of the opened file
+
+   Sami Saarinen, ECMWF, 27/11/95
+     "              "    16/08/99 : Change to use filehandle via pbfp()            
+
+*/
+
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "privpub.h"
+
+extern FILE *pbfp(integer4 khandle);
+
+/* Not needed; We use -qextname while linking with Fortran (SS/23.07.2001)
+#ifdef RS6K
+#define util_stat_ util_stat
+#endif
+*/
+
+#ifdef CRAY
+#define util_stat_ UTIL_STAT
+#endif
+
+void util_stat_(integer4 *khandle,      /* Already opened file handle */
+		integer4 *ifile_size)   /* Return value: size of the UTIL-file in bytes */
+{
+  integer4 file_size = 0;
+  struct stat buf;
+  FILE *fp = pbfp(*khandle);
+
+  if (fstat(fileno(fp),&buf) != 0) {
+    perror("UTIL_STAT");
+    file_size = -1;
+  }
+  else {
+    file_size = buf.st_size;
+  }
+
+  if (ifile_size) *ifile_size = file_size;
+}
diff --git a/odb/src/aux/vpack_bits.c b/odb/src/aux/vpack_bits.c
new file mode 100644
index 0000000..6516ac8
--- /dev/null
+++ b/odb/src/aux/vpack_bits.c
@@ -0,0 +1,333 @@
+
+/* === Vectorizable bit-packing (resembles GBYTES) === */
+
+/* Author: Sami Saarinen, ECMWF, sometime in 2001 meant mainly for packing method = 1 */
+
+/* Thanks to John Chambers (ECMWF) for discussions & program extracts on how GRIB-packing works */
+
+/* == Check for thread-safeness of this utility ; looks bad says author ;-( == */
+
+#include "odb.h"
+
+#include "pcma.h"
+
+#include <signal.h>
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+/* these below are "brilliant" for thread-safeness ... sigh! */
+
+PRIVATE int maxbits = 0;
+PRIVATE int I_inc[N32BITS];
+PRIVATE int J_inc[N32BITS];
+PRIVATE int Mask[N32BITS];
+
+PRIVATE void init();
+
+PUBLIC char *
+bit_pattern(unsigned int mask)
+{
+  unsigned int one = 1;
+  int j;
+  char c[N32BITS+1];
+  if (maxbits == 0) init();
+  c[maxbits] = '\0';
+  for (j=maxbits-1; j>=0; j--) {
+    c[j] = (mask & one) ? '1' : '0';
+    one <<= 1;
+  }
+  return STRDUP(c);
+}
+
+PRIVATE void
+get_incs(int nbits, int *i_inc, int *j_inc)
+{
+  int inc = maxbits/nbits;
+  int inc_nbits = inc * nbits;
+  int gap = maxbits - inc_nbits;
+  int ncycles = 0;
+
+  if (gap > 0) {
+    int spill = 0;
+    do {
+      ncycles++;
+      gap = maxbits - inc_nbits - spill;
+      if (gap >= 0) {
+	spill = (nbits - gap)%nbits;
+      }
+      else {
+	spill = -gap;
+      }
+    } while (spill != 0);
+    *i_inc = ncycles;
+    *j_inc = maxbits/(nbits/ncycles);
+  }
+  else {
+    ncycles = maxbits/nbits;
+    *i_inc = 1;
+    *j_inc = ncycles;
+  }
+}
+
+PRIVATE void
+init()
+{
+  int j;
+  unsigned int mask = 0xFFFFFFFFU;
+
+  /* no. of bits per word */
+  maxbits = 0;
+  while (maxbits++, mask >>= 1);
+
+  if (maxbits != N32BITS) {
+    fprintf(stderr,
+	    "***Error in init()@%s: maxbits = %d not equal to %d\n",
+	    __FILE__,maxbits,N32BITS);
+    RAISE(SIGABRT);
+  }
+
+  for (j=1; j<=maxbits; j++) {
+    get_incs(j, &I_inc[j-1], &J_inc[j-1]);
+    Mask[j-1] = (~0U) >> (maxbits-j);
+  } /* for (j=1; j<=maxbits; j++) */
+
+#ifdef DEBUG
+  fprintf(stderr,"init(): I_inc, J_inc, Mask follow ...\n");
+  for (j=1; j<=maxbits; j++) {
+    extern char *bit_pattern(unsigned int mask);
+    char *c = bit_pattern(Mask[j-1]);
+    fprintf(stderr,"(%2d): I_inc = %4d, J_inc = %4d, Mask = %12u [0x%8.8x] %s\n",
+	    j, I_inc[j-1], J_inc[j-1], Mask[j-1], Mask[j-1], c);
+    FREE(c);
+  }
+#endif
+}
+
+
+/* packing */
+
+void
+vpack_bits_(const int *N_bits,
+	    const unsigned int    unpacked[],
+	             const int *N_unpacked,
+	          unsigned int    packed[],
+	             const int *N_packed,
+	          int *retcode)
+{
+  int rc = 0;
+  int nbits = *N_bits;
+  int nupk = (unpacked && (*N_unpacked > 0)) ? *N_unpacked : 0;
+  int npk  = (packed   && (*N_packed   > 0)) ? *N_packed   : 0;
+  int shift;
+  int i, i_inc, i_start, i_max; /* for packed data */
+  int j, j_inc, j_start, j_max; /* for unpacked data */
+
+  if (maxbits == 0) init();
+
+  if (nbits < 1 || nbits > maxbits) {
+    fprintf(stderr,
+	    "vpack_bits_(): Invalid # of bits (=%d); must be between [1..%d]\n",
+	    nbits,maxbits);
+    goto finish;
+  }
+
+  i_start = 0;
+  j_start = 0;
+
+  i_inc = I_inc[nbits-1];
+  j_inc = J_inc[nbits-1];
+
+  j_max = nupk;
+  i_max = RNDUP(j_max * nbits,maxbits)/maxbits;
+
+  if (i_max > npk) {
+    rc = -i_max;
+    goto finish;
+  }
+
+  for (i=0; i<i_max; i++) packed[i] = 0;
+
+  shift = maxbits - nbits;
+
+  for (;;) {
+    int k, k_max;
+    unsigned int mask, notmask, negshift;
+
+    j = j_start;
+    if (j >= j_inc) break;
+    i = i_start;
+
+    k_max = (j_max-j)/j_inc + 1;
+    if ((k_max-1)*j_inc + j >= j_max) k_max--;
+
+    if (shift >= 0) {
+      mask = Mask[nbits-1] << shift;
+      notmask = ~mask;
+      for (k=0; k<k_max; k++) {
+	packed[i] = (packed[i] & notmask) | ((unpacked[j] << shift) & mask);
+	i += i_inc;
+	j += j_inc;
+      } /* for (k=0; k<k_max; k++) */
+    }
+    else { /* shift < 0 */
+      mask = Mask[nbits+shift-1];
+      notmask = ~mask;
+      negshift = -shift;
+      for (k=0; k<k_max; k++) {
+	packed[i] = (packed[i] & notmask) | ((unpacked[j] >> negshift) & mask);
+	i += i_inc;
+	j += j_inc;
+      } /* for (k=0; k<k_max; k++) */
+    }
+
+    if (shift == 0) {
+      break;
+    }
+    else if (shift > 0) {
+      shift -= nbits;
+      j_start++;
+    }
+    else { /* shift < 0 */
+      shift += maxbits;
+      i_start++;
+    }
+
+  } /* for (;;) */
+
+  rc = i_max;
+
+#ifdef DEBUG
+  {
+    char *env = getenv("KKMAX");
+    int kkmax = env ? atoi(env) : 3;
+    int k, kmax = MIN(i_max,kkmax);
+    fprintf(stderr,"vpack_bits_: in j_max=%d, out i_max=%d words [kmax=%d]\n",j_max,i_max,kmax);
+    for (k=0; k<kmax; k++) {
+      extern char *bit_pattern(unsigned int mask);
+      char *c = bit_pattern(packed[k]);
+      fprintf(stderr,"\tunpacked[%4d] = %12u, packed[%4d] = %12u : %s\n",k,unpacked[k],k,packed[k],c);
+      FREE(c);
+    }
+  }
+#endif
+
+ finish:
+  *retcode = rc;
+}
+
+
+/* unpacking */
+
+void
+vunpack_bits_(const int *N_bits,
+	      const unsigned int    packed[],
+	               const int *N_packed,
+	            unsigned int    unpacked[],
+	               const int *N_unpacked,
+	            int *retcode)
+	      
+{
+  int rc = 0;
+  int nbits = *N_bits;
+  int nupk = (unpacked && (*N_unpacked > 0)) ? *N_unpacked : 0;
+  int npk  = (packed   && (*N_packed   > 0)) ? *N_packed   : 0;
+  int shift;
+  int i, i_inc, i_start, i_max; /* for packed data */
+  int j, j_inc, j_start, j_max; /* for unpacked data */
+
+  if (maxbits == 0) init();
+
+  if (nbits < 1 || nbits > maxbits) {
+    fprintf(stderr,
+	    "vunpack_bits_(): Invalid # of bits (=%d); must be between [1..%d]\n",
+	    nbits,maxbits);
+    goto finish;
+  }
+
+  i_start = 0;
+  j_start = 0;
+
+  i_inc = I_inc[nbits-1];
+  j_inc = J_inc[nbits-1];
+
+  i_max = npk;
+  j_max = RNDUP(i_max * maxbits, nbits)/nbits;
+  if (nupk > 0 && j_max > nupk) j_max = nupk;
+  
+  if (nupk == 0) {
+    rc = -j_max;
+    goto finish;
+  }
+	      
+  for (j=0; j<j_max; j++) unpacked[j] = 0;
+
+  shift = maxbits - nbits;
+
+  for (;;) {
+    int k, k_max;
+    unsigned int mask, notshift;
+
+    j = j_start;
+    if (j >= j_inc) break;
+    i = i_start;
+
+    k_max = (j_max-j)/j_inc + 1;
+    if ((k_max-1)*j_inc + j >= j_max) k_max--;
+
+    if (shift >= 0) {
+      mask = Mask[nbits-1] << shift;
+      for (k=0; k<k_max; k++) {
+	unpacked[j] |= ((packed[i] & mask) >> shift);
+	i += i_inc;
+	j += j_inc;
+      } /* for (k=0; k<k_max; k++) */
+    }
+    else { /* shift < 0 */
+      mask = Mask[nbits+shift-1];
+      notshift = -shift;
+      for (k=0; k<k_max; k++) {
+	unpacked[j] |= ((packed[i] & mask) << notshift);
+	i += i_inc;
+	j += j_inc;
+      } /* for (k=0; k<k_max; k++) */
+    }
+
+    if (shift == 0) {
+      break;
+    }
+    else if (shift > 0) {
+      shift -= nbits;
+      j_start++;
+    }
+    else { /* shift < 0 */
+      shift += maxbits;
+      i_start++;
+    }
+
+  } /* for (;;) */
+
+  rc = j_max;
+
+#ifdef DEBUG
+  {
+    char *env = getenv("KKMAX");
+    int kkmax = env ? atoi(env) : 3;
+    int k, kmax = MIN(i_max,kkmax);
+    fprintf(stderr,"vUNpack_bits_: in j_max=%d, out i_max=%d words [kmax=%d]\n",j_max,i_max,kmax);
+    for (k=0; k<kmax; k++) {
+      extern char *bit_pattern(unsigned int mask);
+      char *c = bit_pattern(packed[k]);
+      fprintf(stderr,"\tunpacked[%4d] = %12u, packed[%4d] = %12u : %s\n",k,unpacked[k],k,packed[k],c);
+      FREE(c);
+    }
+  }
+#endif
+
+ finish:
+  *retcode = rc;
+}
diff --git a/odb/src/compiler/CMakeLists.txt b/odb/src/compiler/CMakeLists.txt
new file mode 100644
index 0000000..1de9b16
--- /dev/null
+++ b/odb/src/compiler/CMakeLists.txt
@@ -0,0 +1,25 @@
+list(APPEND source_files
+
+    cmd.c
+    copyfile.c
+    defines.c
+    genc.c
+    list.c
+    regex.c
+    tree.c
+)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${ODB_INCLUDE_DIRS})
+
+ecbuild_generate_yy(YYPREFIX yy YACC yacc LEX lex DEPENDANT cmd.c odb98.c YACC_TARGET y.tab)
+
+ecbuild_add_library(TARGET odbsqlcompiler
+    TYPE ${ODB_LIBS_TYPE}
+    SOURCES ${source_files} lex.c y.tab.c
+    LIBS odb_lib)
+
+ecbuild_add_executable(TARGET odb98.x SOURCES odb98.c LIBS odbsqlcompiler)
+
+install(CODE "EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E create_symlink
+    odb98.x \${CMAKE_INSTALL_PREFIX}/bin/odb98be.x)")
diff --git a/odb/src/compiler/cmd.c b/odb/src/compiler/cmd.c
new file mode 100644
index 0000000..80c8fd8
--- /dev/null
+++ b/odb/src/compiler/cmd.c
@@ -0,0 +1,38 @@
+#include "defs.h"
+
+PUBLIC int ODB_ncmds = 0;
+
+PRIVATE ODB_Cmd *first_cmd = NULL;
+PRIVATE ODB_Cmd *last_cmd = NULL;
+
+PUBLIC ODB_Cmd *
+ODB_start_cmd() { return first_cmd; }
+
+PUBLIC ODB_Cmd *
+ODB_new_cmd(ODB_Tree *node)
+{
+  extern int ODB_lineno;
+  ODB_Cmd *pcmd;
+
+  ALLOC(pcmd,1);
+
+  if (first_cmd)  
+    last_cmd->next = pcmd;
+  else 
+    first_cmd = pcmd;
+
+  last_cmd = pcmd;
+
+  pcmd->node = node;
+  pcmd->lineno = ODB_lineno;
+  pcmd->next = NULL;
+
+  /*
+  fprintf(stderr,"ODB_new_cmd(#%d) : %p\n",
+	  ODB_lineno, pcmd);
+	  */
+
+  ODB_ncmds++;
+
+  return pcmd;
+}
diff --git a/odb/src/compiler/copyfile.c b/odb/src/compiler/copyfile.c
new file mode 100644
index 0000000..6e563da
--- /dev/null
+++ b/odb/src/compiler/copyfile.c
@@ -0,0 +1,106 @@
+/* copyfile.c */
+
+/* copies file into a file-stream pointed by fpout */
+
+#include "defs.h"
+#undef MAXLINE
+#include "iostuff.h"
+
+PRIVATE void
+shared_code(int *rc,
+	    FILE *fpout, FILE *fp,
+	    const char *start_mark, const char *end_mark,
+	    Boolean backslash_dblquote,
+	    Boolean keep_backslash)
+{
+  int c;
+  int newline = 1;
+  int start_mark_printed = 0;
+  int end_mark_printed = 0;
+  
+  while ((c = fgetc(fp)) != EOF) {
+    if (keep_backslash || c != '\\') {
+      (*rc)++;
+      if (newline && start_mark) {
+	fprintf(fpout,"%s", start_mark);
+	start_mark_printed = 1;
+	newline = 0;
+	end_mark_printed = 0;
+      }
+      newline = (c == '\n');
+      if (newline && end_mark) {
+	fprintf(fpout,"%s", end_mark);
+	end_mark_printed = 1;
+      }
+      if (c == '"' &&  backslash_dblquote) fprintf(fpout,"\\");
+      fprintf(fpout,"%c", c);
+    } /* if (c != '\\') */
+  } /* while ((c = fgetc(fp)) != EOF) */
+  
+  if (start_mark_printed && !end_mark_printed && end_mark) {
+    /* In case file does not end with newline */
+    fprintf(fpout,"%s", end_mark);
+  }
+}
+
+int 
+ODB_copyfile(FILE *fpout, const char *file,
+	     const char *start_mark, const char *end_mark,
+	     Boolean backslash_dblquote,
+	     Boolean keep_backslash)
+{
+  int rc = 0;
+  if (fpout && file) {
+    FILE *fp = FOPEN(file, "r");
+    if (fp) {
+      shared_code(&rc,
+		  fpout, fp,
+		  start_mark, end_mark,
+		  backslash_dblquote,
+		  keep_backslash);
+      FCLOSE(fp);
+    }
+    else {
+      PERROR(file);
+      rc = -1;
+    }
+  }
+  return rc;
+}
+
+#define EGREP "egrep"
+
+int 
+ODB_grepfile(FILE *fpout, const char *pattern, const char *file,
+	     const char *start_mark, const char *end_mark,
+	     Boolean backslash_dblquote,
+	     Boolean keep_backslash)
+{
+  int rc = 0;
+  char *truefile = (fpout && file && pattern) ? IOtruename(file,NULL) : NULL;
+  if (truefile) {
+    FILE *fp = NULL;
+    char *cmd = NULL;
+    char *env = getenv("ODB_EGREP"); /* Just in case 'egrep' was not found from the PATH */
+    char *egrep = env ? STRDUP(env) : STRDUP(EGREP);
+    ALLOC(cmd, strlen(egrep) + strlen(pattern) + strlen(truefile) + 10);
+    sprintf(cmd,"%s '%s' %s", egrep, pattern, truefile);
+    fp = popen(cmd, "r");
+    if (fp) {
+      shared_code(&rc,
+		  fpout, fp,
+		  start_mark, end_mark,
+		  backslash_dblquote,
+		  keep_backslash);
+      pclose(fp);
+    }
+    else {
+      PERROR(cmd);
+      rc = -1;
+    }
+    FREE(cmd);
+    FREE(egrep);
+    FREE(truefile);
+  }
+  return rc;
+}
diff --git a/odb/src/compiler/defines.c b/odb/src/compiler/defines.c
new file mode 100644
index 0000000..a8125c3
--- /dev/null
+++ b/odb/src/compiler/defines.c
@@ -0,0 +1,109 @@
+#include "defs.h"
+
+extern Boolean verbose;
+
+typedef struct _Defines {
+  char *s;
+  double value;
+  struct _Defines *next;
+} Defines_t;
+
+static Defines_t *first = NULL;
+static Defines_t *last  = NULL;
+
+void
+ODB_put_define(const char *s, double default_value)
+{
+  if (s) {
+    char *x;
+    Defines_t *p = NULL;
+    
+    ALLOC(p, 1);
+    if (first) last->next = p;
+    else       first = p;
+    last = p;
+    
+    while (isspace(*s)) s++;
+    p->s = STRDUP(s);
+
+    x = strchr(p->s,'=');
+    if (x && default_value == 0) {
+      /* for use by -Ukey or #undef key */
+      *x = '\0';
+      x = NULL;
+    }
+    if (x) {
+      *x = '\0';
+      x++;
+      p->value = atof(x);
+    }
+    else {
+      x = p->s;
+      while (isspace(*x)) x++;
+      while (*x) {
+	if (isspace(*x)) {
+	  *x = '\0';
+	  break;
+	}
+	x++;
+      }
+      p->value = default_value;
+    }
+    p->next = NULL;
+    /* if (verbose) fprintf(stderr,"\t-D\"%s=%g\"\n",p->s,p->value); */
+  }
+}
+
+double
+ODB_get_define(const char *s)
+{
+  if (s) {
+    char *ws;
+    char *x = STRDUP(s);
+    char *tmp = x;
+    ws = strchr(x,'\n');
+    if (ws) *ws = '\0';
+    /* if (verbose) fprintf(stderr,"ODB_get_define(\"%s\");\n",x); */
+
+    while (isspace(*x)) x++;
+    if (strnequ(x,"#ifdef",6)) x += 6;
+    else if (strnequ(x,"#ifndef",7)) x += 7;
+    while (isspace(*x)) x++;
+
+    ws = x;
+    while ( *ws ) {
+      if (isspace(*ws)) {
+	*ws = '\0';
+	break;
+      }
+      ws++;
+    }
+    /* if (verbose) fprintf(stderr,"\tComparing '%s' ...\n",x); */
+    {
+      Defines_t *p;
+      for (p = first; p; p = p->next) {
+	if (strequ(p->s,x)) {
+	  /* if (verbose) fprintf(stderr,"\t==> value for '%s' = %g\n",p->s,p->value); */
+          FREE(tmp);
+	  return p->value;
+	}
+      }
+    }
+    FREE(tmp);
+  }
+  return 0;
+}
+
+Boolean
+ODB_has_define(const char *s)
+{
+  if (s) {
+    Defines_t *p;
+    for (p = first; p; p = p->next) {
+      if (strequ(p->s,s)) {
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/odb/src/compiler/genc.c b/odb/src/compiler/genc.c
new file mode 100644
index 0000000..c0f1e46
--- /dev/null
+++ b/odb/src/compiler/genc.c
@@ -0,0 +1,5912 @@
+
+/* genc.c */
+
+#define SETMSG 1
+#include "defs.h"
+#include "magicwords.h"
+#include "pcma_extern.h"
+
+PRIVATE ODB_Filelist *flist_start = NULL;
+PRIVATE ODB_Filelist *flist_last = NULL;
+PRIVATE ODB_Filelist *flist = NULL;
+
+PRIVATE const int linelen_threshold = 50;
+
+PRIVATE char **tmpsym = NULL;
+PRIVATE int ntmpsym = 0;
+
+extern int ODB_lineno;
+extern char *odb_label;
+extern int optlevel;
+extern int genstatic;
+extern int incremental;
+extern int merge_table_indices;
+extern Boolean verbose;
+extern char *one_tables;
+extern Boolean reset_align_issued;
+extern Boolean reset_onelooper_issued;
+extern Boolean has_USD_symbols;
+extern ODB_Table **table_hier;
+extern int ODB_ntables;
+extern Boolean readonly_mode;
+extern Boolean insert_drhook;
+extern int ddl_piped;
+extern char *ARGH;
+
+extern FILE *fpdevnull;
+PRIVATE FILE *fphdr     = NULL;
+PRIVATE FILE *fptable   = NULL;
+
+extern int filtered_info;
+PUBLIC FILE *fpinf  = NULL; /* Provides filtered (-F<level>) compilation information for generic select */
+PRIVATE int info_dump = 0;
+
+extern int GetSign(const char *poffset); /* from tree.c */
+
+static const char usd_maxcount[] = "$__maxcount__";
+static const double mdi = ABS(RMDI);
+
+#define FPINF_MAGIC()             if (fpinf) ODB_fprintf(fpinf, "INFO\n");
+#define FPINF_KEYLINE(name,item)  if (fpinf) ODB_fprintf(fpinf, "\n/%s=%s\n", #name, item)
+#define FPINF_KEYNUM(name,num)    if (fpinf) ODB_fprintf(fpinf, "\n/%s %d\n", #name, num)
+#define FPINF_KEY(name)           FPINF_KEYNUM(name,-1)
+#define FPINF_ITEM(x)             if (fpinf) ODB_fprintf(fpinf, "%s\n", x)
+#define FPINF_NUM(id,val)         if (fpinf) ODB_fprintf(fpinf, "%d %d\n", id, val)
+#define FPINF_KEYSTR(num,str)     if (fpinf) ODB_fprintf(fpinf, "%d,%d %s\n", num, STRLEN(str), str)
+#define FPINF_NUMITEM_TYPE_VAR_MEM_TABLE(num, ptype, pvar, pmem, ptable, poslen) \
+if (fpinf) \
+ pmem ? ODB_fprintf(fpinf, "%d %s:%s.%s@%s\t%s 0\n", \
+                    num, ptype, pvar, pmem, ptable, poslen ? poslen : "0 0") \
+      : ODB_fprintf(fpinf, "%d %s:%s@%s\t%s 0\n"   , \
+                    num, ptype, pvar      , ptable, poslen ? poslen : "0 0")
+#define FPINF_NUMITEM_TYPE_LINK_VAR_TABLE(num, ptype, plink, pvar, ptable) \
+if (fpinf) ODB_fprintf(fpinf, "%d %s:%s(%s)@%s\t0 0 0\n", num, ptype, #plink, pvar, ptable)
+#define FPINF_ITEMFLP(x,val)      if (fpinf) ODB_fprintf(fpinf, "%s %.14g\n", x, val)
+#define FPINF_NICKNAME(num,x)     if (fpinf) ODB_fprintf(fpinf, "%d %s\n", num, x)
+#define FPINF_NUMITEM(num,x,poslen,offset) \
+if (fpinf) { int _sign = GetSign(offset); const char *_tmp = offset; \
+  ODB_fprintf(fpinf, "%d %s\t%s %s%s\n", \
+	      num, x, \
+	      poslen ? poslen : "0 0", \
+              (_sign < 0) ? "-" : "", \
+	      _tmp ? _tmp+ABS(_sign) : "0"); }
+#define FPINF_NUMITEM_WT(num,x,wt)if (fpinf) ODB_fprintf(fpinf, "%d %s %.6f\n", num, x, wt)
+#define FPINF_FMT2(fmt, x1, x2)   if (fpinf) ODB_fprintf(fpinf, fmt, x1, x2)
+#define FPINF_KEYEND(name)        if (fpinf) ODB_fprintf(fpinf, "/end %s\n", #name)
+#define FPINF_LINK(child_id, child, parent_id, \
+                   parent_or_offset, kind_of_link_or_length, \
+                   offset_parent_id, offset_parent_name) \
+if (fpinf) ODB_fprintf(fpinf, "%d %s %d %s %s %d %s\n", \
+		       child_id, child, parent_id, parent_or_offset, kind_of_link_or_length,\
+                       offset_parent_id, offset_parent_name)
+
+#define NL(n)  { if (cfp) { int l; for(l=0; l<(n); l++) fprintf(cfp,"\n"); }}
+#define TAB(n) { if (cfp) { int l; for(l=0; l<(n); l++) fprintf(cfp,"  "); }}
+#define LBDQ(n){ if (cfp) { TAB(1); fprintf(cfp,"\""); TAB(n); }}
+#define LB(n)  { if (cfp) { TAB(1); fprintf(cfp,"{\""); TAB(n); }}
+#define RB(n)  { if (cfp) { int l, lmax=(n); for(l=1; l<=lmax; l++) { \
+	            fprintf(cfp,"\"},"); NL(1); if (l<lmax) LB(0); } }}
+#define RBDQ(n){ if (cfp) { int l, lmax=(n); for(l=1; l<=lmax; l++) { \
+	            fprintf(cfp,"\","); NL(1); if (l<lmax) LBDQ(0); } }}
+#define WR(s)  { if (cfp) { fprintf(cfp,"%s",s); }}
+#define WRCOMMA(s)  { if (cfp) { WR(s); fprintf(cfp,", "); }}
+#define LP     { if (cfp) { fprintf(cfp,"("); }}
+#define RP     { if (cfp) { fprintf(cfp,")"); }}
+
+#define PrtAggrFlag(x) \
+  TAB(1); ODB_fprintf(cfp,"P->aggr_func_flag[%d] = %s; /* '%s' */\n",i,#x,pview->tag[i]); ++numaggr
+
+#define POOLNO "POOLNO"
+
+#define PREFETCH_CODE(ntabs, what, fplink) \
+{ \
+  for (i=0; i<nfrom; i++) { \
+    if (i < nfrom - 1) { \
+      Boolean link_found = 0; \
+      char *snext = pview->from[i+1]->table->name; \
+      char *snext_sharedlinkname = snext; \
+      char *sthis = NULL; \
+      for (j=0; j<=i; j++) { \
+	ODB_Table *t = pview->from[j]; \
+	if (t->link) { \
+	  int l; \
+	  for (l=0; l<t->nlink; l++) { \
+	    char *s = t->link[l]->table->name; \
+	    link_found = strequ(s, snext); \
+	    if (link_found) { \
+	      sthis = t->table->name; \
+              if (t->sharedlink[l]) snext_sharedlinkname = t->sharedlinkname[l]; \
+	      goto what##_prefetch_break; \
+	    } \
+	  } /* for (l=0; l<t->nlink; l++) */ \
+	} /* if (t->link) */ \
+      } /* for (j=0; j<=i; j++) */ \
+    what##_prefetch_break: \
+      if (link_found) { \
+	TAB(ntabs); \
+	ODB_fprintf(cfp,"%s *P%s_off = UseDSlong(P->T_%s, %s, %s, P->T_%s->LINKOFFSET(%s));\n", \
+		LINKOFFSETTYPE, snext, sthis, \
+		odb_label,LINKOFFSETTYPE,sthis,snext_sharedlinkname); \
+	TAB(ntabs); \
+	ODB_fprintf(cfp,"%s *P%s_len = UseDSlong(P->T_%s, %s, %s, P->T_%s->LINKLEN(%s));\n", \
+		LINKLENTYPE, snext, sthis, \
+		odb_label,LINKLENTYPE,sthis,snext_sharedlinkname); \
+        if (fplink && fplink == fpinf) { \
+	  int flag = 1; \
+	  FPINF_NUMITEM_TYPE_LINK_VAR_TABLE(flag, LINKOFFSETTYPE, LINKOFFSET, snext_sharedlinkname, sthis); \
+	  FPINF_NUMITEM_TYPE_LINK_VAR_TABLE(flag, LINKLENTYPE, LINKLEN, snext_sharedlinkname, sthis); \
+	} \
+      } \
+    } /* if (i < nfrom - 1) */ \
+  } /* for (i=0; i<nfrom; i++) */ \
+}
+
+#define CONDCODE(cfp_io,rc) \
+rc = 0; \
+(void) tmp_symbols(cfp_io, pcond, done, i, 1+i+2, nfrom_start); \
+if (i < maxfrom) { \
+  double dval = 0; \
+  int evalok = (optlevel > 0) ? ODB_evaluate(pcond, &dval) : 0; \
+  int count = 0; \
+  if (optlevel > 0 && !evalok) { \
+    /* Perform optimization */ \
+    for (j=0; j<andlen; j++) { \
+      if (andlist[j].maxfrom == i) { \
+	ODB_Tree *expr = andlist[j].expr; \
+             if (count == 0) { TAB(1+i+2); ODB_fprintf(cfp_io,"int cond%d = ",i); } \
+	else if (count  > 0) { NL(1); TAB(6); ODB_fprintf(cfp_io,"&& "); } \
+	dump_c(cfp_io,lineno,expr); \
+	count++; \
+      } \
+    } /* for (j=0; j<andlen; j++) */ \
+  } \
+  if (count > 0) { \
+    ODB_fprintf(cfp_io,";\n"); \
+    TAB(1+i+2); ODB_fprintf(cfp_io,"if (cond%d == 0) continue;\n",i); \
+    rc = count; \
+  } else if (evalok) { \
+    if (dval == 0) { TAB(1+i+2); ODB_fprintf(cfp_io,"continue; /* Always false */\n"); } \
+    rc = -1; \
+  } \
+} \
+else if (i == maxfrom) { \
+  double dval = 0; \
+  int evalok = (optlevel > 0) ? ODB_evaluate(pcond, &dval) : 0; \
+  int count = 0; \
+  if (optlevel > 0 && !evalok) { \
+    /* Perform optimization */ \
+    for (j=0; j<andlen; j++) { \
+      if (andlist[j].maxfrom == i) { \
+	ODB_Tree *expr = andlist[j].expr; \
+	     if (count == 0) { TAB(1+i+2); ODB_fprintf(cfp_io,"int cond%d = ",i); } \
+	else if (count > 0) { NL(1); TAB(6); ODB_fprintf(cfp_io,"&& "); } \
+	dump_c(cfp_io,lineno,expr); \
+	count++; \
+      } \
+    } /* for (j=0; j<andlen; j++) */ \
+  } \
+  else if (!evalok) { \
+    dump_c(cfp_io,lineno,pcond); \
+  } \
+  if (count > 0) { \
+    ODB_fprintf(cfp_io,";\n"); \
+    TAB(1+i+2); ODB_fprintf(cfp_io,"if (cond%d != 0)\n",i); \
+    rc = count; \
+  } else if (evalok) { \
+    if (dval == 0) { TAB(1+i+2); ODB_fprintf(cfp_io,"continue; /* Always false */\n"); } \
+    rc = -1; \
+  } \
+  TAB(1+i+2); ODB_fprintf(cfp_io,"{ /* if-block start */\n"); \
+  oneif++; \
+}
+
+#define NTYPES 1
+static const int ntypes = NTYPES;
+static char *Key[NTYPES]         = { "d"       };
+static char *ExtType[NTYPES]     = { "double"  };
+static char *KeyInfo[NTYPES]     = { "REAL(8)" };
+
+PRIVATE void
+TagStrip(FILE *cfp, int ntabs, const char *tag, const char *endstr)
+{
+  const char *tag_delim = ODB_tag_delim;
+  if (tag_delim && tag && cfp && cfp != fpdevnull) {
+    const char dblquote = '"';
+    const char backslash = '\\';
+    Boolean need_endquote = 0;
+    const char *p = tag;
+    int cnt = 0;
+    while (*p) {
+      if (cnt == 0) {
+	NL(1);
+	TAB(ntabs);
+	fputc(dblquote, cfp); /* Opening quote */
+	need_endquote = 1;
+      }
+      if (*p == dblquote) fputc(backslash, cfp);
+      fputc(*p, cfp);
+      ++cnt;
+      if (*p == *tag_delim && cnt >= linelen_threshold) {
+	fputc(dblquote, cfp); /* Closing quote */
+	need_endquote = 0;
+	cnt = 0;
+      }
+      ++p;
+    }
+    if (need_endquote) fputc(dblquote, cfp); /* Closing quote */
+    if (endstr) ODB_fprintf(cfp, "%s", endstr);
+  }
+}
+
+PRIVATE void
+vector_loop(FILE *cfp, Boolean on)
+{
+  /*
+  if (cfp && on) {
+    NL(1);
+    ODB_fprintf(cfp,"#ifdef VPP\n");
+    ODB_fprintf(cfp,"#pragma loop noalias\n");
+    ODB_fprintf(cfp,"#pragma loop novrec\n");
+    ODB_fprintf(cfp,"#pragma loop vector\n");
+    ODB_fprintf(cfp,"#elif defined(NECSX)\n");
+    ODB_fprintf(cfp,"#pragma cdir nodep\n");
+    ODB_fprintf(cfp,"#endif\n");
+  }
+  */
+}
+
+PRIVATE void
+set_optlevel(FILE *cfp, int opt)
+{
+  /*
+  if (cfp && opt >= 0) {
+    NL(1);
+    ODB_fprintf(cfp,"#ifdef RS6K\n");
+    ODB_fprintf(cfp,"#pragma options optimize=%d\n",opt);
+    ODB_fprintf(cfp,"#endif\n");
+    NL(1);
+  }
+  */
+}
+
+PRIVATE char *
+dblquotes(const char *s)
+{
+  char *p = NULL;
+  if (s) {
+    char *c;
+    int len = 2*strlen(s) + 1;
+    ALLOC(p,len);
+    c = p;
+    while (*s) {
+      if (*s == '"') *c++ = '\\';
+      *c++ = *s++;
+    }
+    *c = '\0';
+  }
+  return p ? p : STRDUP("");
+}
+
+PRIVATE void
+free_tmpsym(Boolean all)
+{
+  if (tmpsym) {
+    int j;
+    for (j=0; j<ntmpsym; j++) {
+      FREE(tmpsym[j]);
+    }
+    if (all) FREE(tmpsym);
+    ntmpsym = 0;
+  }
+}
+
+
+PUBLIC void
+process_one_tables(FILE *cfp, const char *start, const char *end)
+{
+  ODB_linklist *list = manage_linklist(FUNC_LINKLIST_START,NULL,NULL,0);
+  const char *p = one_tables;
+  if (!list && p) {
+    char tmp_delim = *p++;
+    char delim[2];
+    char *saved = STRDUP(p);
+    char *s = saved;
+    char *token = NULL;
+    delim[0] = tmp_delim;
+    delim[1] = '\0';
+    token = strtok(s,delim);
+    while (token) {
+      char *t = STRDUP(token);
+      char *onelooper = strchr(t,'=');
+      char *align = strchr(t,'@');
+      if (onelooper) {
+	*onelooper++ = '\0'; /* sets end of string t implicitly to '\0' */
+	if (ODB_lookup_table(onelooper,NULL) &&
+	    !manage_linklist(FUNC_LINKLIST_QUERY,t,onelooper,1)) {
+	  (void) manage_linklist(FUNC_LINKLIST_ADD,t,onelooper,1);
+	}
+      }
+      else if (align) {
+	*align++ = '\0'; /* sets end of string t implicitly to '\0' */
+	if (ODB_lookup_table(align,NULL) &&
+	    !manage_linklist(FUNC_LINKLIST_QUERY,t,align,2)) {
+	  (void) manage_linklist(FUNC_LINKLIST_ADD,t,align,2);
+	}
+      }
+      FREE(t);
+      token = strtok(NULL,delim);
+    }
+    FREE(saved);
+    list = manage_linklist(FUNC_LINKLIST_START,NULL,NULL,0);
+  }
+  if (list && cfp) {
+    ODB_linklist *plinklist = list;
+    while (plinklist) {
+      if (plinklist->n_rhs > 0) {
+	if (start) ODB_fprintf(cfp,"%s",start);
+	if (plinklist->type == 1) {
+	  ODB_fprintf(cfp,"-1%s=",plinklist->lhs);
+	}
+	else if (plinklist->type == 2) {
+	  ODB_fprintf(cfp,"-A%s=",plinklist->lhs);
+	}
+	if (plinklist->n_rhs > 1) ODB_fprintf(cfp,"(");
+	{ /* Loop over all rhs-(table)names */
+	  struct _rhs_t *first_rhs = plinklist->rhs;
+	  while (first_rhs) {
+	    ODB_fprintf(cfp,"%s",first_rhs->name);
+	    if (first_rhs != plinklist->last_rhs) ODB_fprintf(cfp,",");
+	    first_rhs = first_rhs->next;
+	  } /* while (first_rhs) */
+	}
+	if (plinklist->n_rhs > 1) ODB_fprintf(cfp,")");
+	if (end) ODB_fprintf(cfp,"%s",end);
+      }
+      plinklist = plinklist->next;
+    } /* while (plinklist) */
+  } /* if (list && cfp) */
+}
+
+
+PRIVATE	int
+is_master(const char *master, const char *slave)
+{ /* This is not completely right ;-( .. but practically not used at all */
+  int rc = 0;
+  if (master && slave) {
+    /* Precedence over ALIGN-table (=2) testing */
+    /* "master at slave" */
+    if (manage_linklist(FUNC_LINKLIST_QUERY,master,slave,2))
+      rc = 1; /* master is a master against the given slave */
+  }
+  return rc;
+}
+
+
+PRIVATE int
+onegrep(const char *master, const char *slave, int lineno)
+{
+  int icase = 0;
+  if (master && slave) {
+    int match = 0;
+    ODB_Table *pm = ODB_lookup_table(master,NULL);
+    ODB_Table *ps = ODB_lookup_table(slave,NULL);
+    int m_tableno = pm ? pm->tableno : -1;
+    int s_tableno = ps ? ps->tableno : -1;
+
+    match = (pm && ps && ps->linkslavemask[m_tableno]);
+
+    /* Precedence over ALIGN-table (=2) testing */
+    if (match) {
+      if ((ps->linkslavemask[m_tableno] & 2) == 2) icase = 2;
+      else if ((ps->linkslavemask[m_tableno] & 1) == 1) icase = 1;
+      else match = 0;
+    }
+
+    if (!match) {
+      /* Swap master & slave with each other so that the table order doesn't matter */
+      match = (ps && pm && pm->linkslavemask[s_tableno]);
+      if (match) {
+	if ((pm->linkslavemask[s_tableno] & 2) == 2) icase = 2;
+	else if ((pm->linkslavemask[s_tableno] & 1) == 1) icase = 1;
+	else match = 0;
+      }
+    }
+
+    if (verbose) fprintf(stderr,"onegrep(%s,%s,#%d) = %d : match = %d\n",master,slave,lineno,icase,match);
+  }
+  return icase;
+}
+
+PUBLIC char *
+ODB_get_sharedlinkname(const char *slave, const char *target)
+{
+  char *master = NULL;
+  if (target && slave) {
+    char *p;
+    int len = strlen(slave) + 2;
+    ALLOC(p,len);
+
+    /* locate "&slave" */
+    sprintf(p,"&%s",slave);
+    master = in_extlist1(p,target);
+    FREE(p);
+  }
+  return master;
+}
+
+PRIVATE int
+get_PKmethod(const char *type, char **ftype, char **datatype, char **ctype)
+{
+  int method = 0;
+
+  if (strequ(type,"pk2real")) {
+    method = 2;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk3real")) {
+    method = 3; /* Method#3 now fixed (13/12/2000) */
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"string")) {
+    method = 3; /* Method#3 now fixed (13/12/2000) */
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("STRING");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk4real")) {
+    method = 4;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk5real")) {
+    method = 5;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk9real")) {
+    method = 9;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk2int")) {
+    method = 2;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk3int")) {
+    method = 3;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk4int")) {
+    method = 4;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk5int")) {
+    method = 5;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk1int")) {
+    method = 1;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"yyyymmdd")) {
+    method = 1;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("YYYYMMDD");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"hhmmss")) {
+    method = 1;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("HHMMSS");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,BITFIELD)) {
+    /* method = 3; Used to be 9 before 16/10/2000; SS */
+    /* method = 9; Back to 9 since pcma_3 has failed ; SS 29/11/2000 */
+    method = 1; /* Brand new method since 13/12/2000 */
+    /* if (ftype) *ftype = STRDUP("UINT"); -- commented out on 29/05/2002 by SS */
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("BITFIELD");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"linkoffset_t")) {
+    method = 1;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("LINKOFFSET");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"linklen_t")) {
+    method = 1;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("LINKLEN");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk9int")) {
+    method = 9;
+    if (ftype)    *ftype = STRDUP("INT");
+    if (datatype) *datatype = STRDUP("INT4");
+    if (ctype)    *ctype = STRDUP("int");
+  }
+  else if (strequ(type,"pk11real")) {
+    method = 11;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk12real")) {
+    method = 12;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk13real")) {
+    method = 13;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk14real")) {
+    method = 14;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk15real")) {
+    method = 15;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk16real")) {
+    method = 16;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk17real")) {
+    method = 17;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk18real")) {
+    method = 18;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk19real")) {
+    method = 19;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk21real")) {
+    method = 21;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk22real")) {
+    method = 22;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk23real")) {
+    method = 23;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk24real")) {
+    method = 24;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk25real")) {
+    method = 25;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk26real")) {
+    method = 26;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk27real")) {
+    method = 27;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk28real")) {
+    method = 28;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk29real")) {
+    method = 29;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk31real")) {
+    method = 31;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk32real")) {
+    method = 32;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk33real")) {
+    method = 33;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk34real")) {
+    method = 34;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk35real")) {
+    method = 35;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk36real")) {
+    method = 36;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk37real")) {
+    method = 37;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk38real")) {
+    method = 38;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else if (strequ(type,"pk39real")) {
+    method = 39;
+    if (ftype)    *ftype = STRDUP("DBL");
+    if (datatype) *datatype = STRDUP("REAL8");
+    if (ctype)    *ctype = STRDUP("double");
+  }
+  else {
+    method = 0;
+    if (ftype) *ftype = STRDUP(type);
+    if (datatype) {
+      if (strequ(type,"double")) *datatype = STRDUP("REAL8");
+      else if (strequ(type,"float")) *datatype = STRDUP("REAL4");
+      else if (strequ(type,"int")) *datatype = STRDUP("INT4");
+      else if (strequ(type,"uint")) *datatype = STRDUP("UINT4");
+      else if (strequ(type,"char")) *datatype = STRDUP("INT1");
+      else if (strequ(type,"uchar")) *datatype = STRDUP("UINT1");
+      else if (strequ(type,"short")) *datatype = STRDUP("INT2");
+      else if (strequ(type,"ushort")) *datatype = STRDUP("UINT2");
+      else if (strequ(type,"bufr")) *datatype = STRDUP("BUFR");
+      else if (strequ(type,"grib")) *datatype = STRDUP("GRIB");
+      else if (strequ(type,"real4")) *datatype = STRDUP("REAL4");
+      else if (strequ(type,"real8")) *datatype = STRDUP("REAL8");
+      else if (strequ(type,"real")) *datatype = STRDUP("REAL8");
+      else if (strequ(type,"integer1")) *datatype = STRDUP("INT1");
+      else if (strequ(type,"integer2")) *datatype = STRDUP("INT2");
+      else if (strequ(type,"integer4")) *datatype = STRDUP("INT4");
+      else if (strequ(type,"integer8")) *datatype = STRDUP("INT8");
+      else if (strequ(type,"longlong")) *datatype = STRDUP("INT8");
+      else if (strequ(type,"ulonglong")) *datatype = STRDUP("UINT8");
+      else *datatype = STRDUP("UNDEF");
+    }
+    if (ctype) {
+      if (strequ(type,"double")) *ctype = STRDUP("double");
+      else if (strequ(type,"float")) *ctype = STRDUP("float");
+      else if (strequ(type,"int")) *ctype = STRDUP("int");
+      else if (strequ(type,"uint")) *ctype = STRDUP("unsigned int");
+      else if (strequ(type,"char")) *ctype = STRDUP("char");
+      else if (strequ(type,"uchar")) *ctype = STRDUP("unsigned char");
+      else if (strequ(type,"short")) *ctype = STRDUP("short int");
+      else if (strequ(type,"ushort")) *ctype = STRDUP("unsigned short int");
+      else if (strequ(type,"bufr")) *ctype = STRDUP("bufr");
+      else if (strequ(type,"grib")) *ctype = STRDUP("grib");
+      else if (strequ(type,"real4")) *ctype = STRDUP("float");
+      else if (strequ(type,"real8")) *ctype = STRDUP("double");
+      else if (strequ(type,"real")) *ctype = STRDUP("double");
+      else if (strequ(type,"integer1")) *ctype = STRDUP("char");
+      else if (strequ(type,"integer2")) *ctype = STRDUP("short int");
+      else if (strequ(type,"integer4")) *ctype = STRDUP("int");
+      else if (strequ(type,"integer8")) *ctype = STRDUP("long long int");
+      else if (strequ(type,"longlong")) *ctype = STRDUP("long long int");
+      else if (strequ(type,"ulonglong")) *ctype = STRDUP("unsigned long long int");
+      else *ctype = STRDUP("undefined_ctype");
+    }
+  }
+
+  return method;
+}
+
+
+PRIVATE char *
+get_typedef(const char *type, const char *name, const char *ptr)
+{
+  char *s = NULL;
+  const char *p = ptr ? ptr : "";
+
+  if (strnequ(type,"bit",3)) {
+    char *t = "unsigned";
+    int nbits = atoi(type+3);
+    ALLOC(s,strlen(t) + strlen(name) + 20);
+    sprintf(s,"%s %s : %d",t,name,nbits);
+  }
+  else {
+    ALLOC(s,strlen(type) + strlen(name) + strlen(p) + 2);
+    sprintf(s,"%s %s%s",type,p,name);
+  }
+
+  return s;
+}
+
+
+PRIVATE char *
+get_typename(ODB_Type *ptype)
+{
+  char *tyname;
+  if (ptype->bitstream) {
+    tyname = BITFIELD;
+  }
+  else if (ptype->nsym == 1 && ptype->no_members) {
+    tyname = ptype->sym[0]->name;
+  }
+  else {
+    tyname = ptype->type->name;
+  }
+  return tyname;
+}
+	      
+
+PRIVATE int
+assign_USD_symbols(FILE *cfp, 
+		   ODB_Tree *pnode, 
+		   const int numtabs, 
+		   const int phase,
+		   const char *name,
+		   const char *viewname)
+{
+  int rc = 0;
+  if (!has_USD_symbols) return rc;
+
+  if (pnode) {
+    int what = pnode->what;
+    
+    switch (what) {
+    case ODB_WHERE_SYMBOL:
+      break;
+
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+	  ODB_Tree *expr = match->expr;
+	  rc += assign_USD_symbols(cfp, expr, numtabs, phase, name, viewname);
+	} /* for (j=0; j<nummatch; j++) */
+      }
+      break;
+
+    case ODB_USDNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *s = psym->name;
+	double value = psym->dval;
+	uint flag = psym->flag;
+	uint done = DONE_SYM(flag, phase);
+	
+	if (/* cfp && */ (phase >= 1 && phase <= 3) && !done) {
+	  if (phase == 1) { /* Declare local USD-variable */
+	    TAB(numtabs);
+	    if (IS_POOLNO(s)) {/* '$#' or '$pool#' */
+	      ODB_fprintf(cfp,"double lc_USD_%s = P->PoolNo; /* A fixed value */\n", POOLNO);
+	    }
+	    else if (!IS_USDHASH(s)) {
+	      ODB_fprintf(cfp,"double lc_USD_%s = 0;\n",s+1);
+	    }
+	    else if (IS_USDHASH(s)) {
+	      char *sh = STRDUP(s);
+	      int sh_len = STRLEN(sh);
+	      char *dot = strchr(sh,'.');
+	      if (dot) *dot = 'D'; /* IS_USDDOTHASH(s) */
+	      sh[sh_len-1] = '\0'; /* replace '#' with '\0' */
+	      ODB_fprintf(cfp,"double lc_USDHASH_%s = 0;\n",sh+1);
+	      FREE(sh);
+	    }
+	  }
+	  else if (phase == 2) { /* Get the most recent value of the USD-variable */
+	    if (!IS_POOLNO(s)) {
+	      if (!IS_USDHASH(s)) {
+		TAB(numtabs);
+		if (name) {
+		  ODB_fprintf(cfp,
+			      "ODBMAC_ADDR_TRIGGER(%s, %s, %s, %s%s%s);\n",
+			      odb_label,name,s+1,
+			      viewname ? "\"" : "", 
+			      viewname ? viewname : "NULL", viewname ? "\"" : "");
+		}
+		else { /* !name */
+		  ODB_fprintf(cfp,
+			      "ODBMAC_LC_GETVAL(%s, %s, %s%s%s);\n",
+			      odb_label,s+1,
+			      viewname ? "\"" : "", 
+			      viewname ? viewname : "NULL", viewname ? "\"" : "");
+		}
+	      }
+	      else if (IS_USDHASH(s)) {
+		char *eq = NULL;
+		if (IS_(ROWNUM,s)) eq = "tmpcount+1";
+		if (IS_(UNIQNUM,s)) eq = "ODB_put_one_control_word(tmpcount, P->PoolNo)";
+		else if (IS_(NROWS,s)) eq = "P->Nrows";
+		else if (IS_(NCOLS,s)) eq = "P->Ncols";
+		else if (IS_(COLNUM,s)) eq = "0"; /* Don't know the column ? */
+		else if (IS_USDDOTHASH(s)) eq = "0";
+		if (eq) {
+		  char *sh = STRDUP(s);
+		  int sh_len = STRLEN(sh);
+		  char *dot = strchr(sh,'.');
+		  if (dot) *dot = 'D'; /* IS_USDDOTHASH(s) */
+		  sh[sh_len-1] = '\0'; /* replace '#' with '\0' */
+		  TAB(numtabs);
+		  ODB_fprintf(cfp,"lc_USDHASH_%s = %s;\n",sh+1,eq);
+		  FREE(sh);
+		}
+	      }
+	    } /* if (!IS_POOLNO(s)) */
+	  }
+	  else if (phase == 3) { /* Add variable to the known variable list */
+	    if (!IS_POOLNO(s) && !IS_USDHASH(s)) {
+	      TAB(numtabs);
+	      ODB_fprintf(cfp,"Pool->add_var(\"%s\", \"%s\", \"%s\", it, USD_%s_%s);\n",
+			  odb_label, s, viewname ? viewname : "???", s+1, odb_label);
+	    }
+	    add_list(s);
+	    FPINF_ITEMFLP(s, value);
+	  }
+	  
+	  SET_SYM(psym->flag, phase);
+	}
+	else if (phase == 4) { /* $-symbol found in WHERE */
+	  SET_SYM(psym->flag, 4);
+	}
+	else if (phase == 5) { /* $-symbol found in SELECT-expression */
+	  SET_SYM(psym->flag, 5);
+	}
+	else if (phase == 0) { /* Reset phase flags to zero */
+	  RESET_SYM(psym->flag, 1);
+	  RESET_SYM(psym->flag, 2);
+	  RESET_SYM(psym->flag, 3);
+	}
+      }
+      rc = 1;
+      break;
+      
+    case ODB_COND:
+      {
+	int j, numargs = pnode->argc;
+	for (j=0; j<numargs; j++) 
+	  rc += assign_USD_symbols(cfp, pnode->argv[j], numtabs, phase, name, viewname);
+      }
+      break;
+
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      {
+	int j, numargs = pnode->argc - 1;
+	for (j=1; j<=numargs; j++) 
+	  rc += assign_USD_symbols(cfp, pnode->argv[j], numtabs, phase, name, viewname);
+      }
+      break;
+
+    case ODB_FILE:
+      {
+	rc += assign_USD_symbols(cfp, pnode->argv[2], numtabs, phase, name, viewname);
+      }
+      break;
+      
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_EQ:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_NE:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      rc += assign_USD_symbols(cfp, pnode->argv[0], numtabs, phase, name, viewname);
+      rc += assign_USD_symbols(cfp, pnode->argv[1], numtabs, phase, name, viewname);
+      break;
+      
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      rc += assign_USD_symbols(cfp, pnode->argv[0], numtabs, phase, name, viewname);
+      break;
+      
+    default:
+      rc = 0;
+      break;
+    } /* switch (what) */
+  } /* if (pnode) */
+
+  return rc;
+}
+
+
+PRIVATE int
+tmp_symbols(FILE *cfp, ODB_Tree *pnode, Boolean done[], 
+	    int level, int numtabs, int nfrom_start)
+{
+  int rc = 0;
+
+  if (pnode) {
+    int what = pnode->what;
+
+    switch (what) {
+    case ODB_WHERE_SYMBOL:
+      {
+	char *s = pnode->argv[0];
+	char *ptype = NULL;
+	char *pvar = NULL;
+	char *pmember = NULL;
+	char *ptable = NULL;
+	int ifrom, isym;
+
+	(void) ODB_split(s, &ptype, &pvar, &pmember, &ptable, NULL);
+	ifrom = atoi(pmember) - nfrom_start;
+
+	if (ifrom == level) {
+	  isym = atoi(pvar);
+	  if (!done[isym]) {
+	    int idx = -1;
+	    int j;
+	    int n = ntmpsym;
+	    int len = strlen(ptype) + strlen(ptable) + 100;
+	    char *s = NULL;
+	    char *ps;
+
+	    ALLOC(s,len);
+	    snprintf(s,len,"%d = %s(K%d)",isym,ptable,ifrom);
+	    ps = strchr(s,'=');
+
+	    if (ps) {
+	      for (j=0; j<n; j++) {
+		/* Check if already declared */
+		char *c = tmpsym[j];
+		char *pc = strchr(c,'=');
+		if (pc) {
+		  if (strequ(ps,pc)) {
+		    idx = j;
+		    break;
+		  }
+		}
+	      } /* for (j=0; j<n; j++) */
+	    }
+	    
+	    TAB(numtabs);
+	    if (idx == -1) {
+	      n = ntmpsym;
+	      tmpsym[n] = s;
+	      ntmpsym++;
+	      ODB_fprintf(cfp,"%s tmp%s",ptype,s);
+	      ODB_fprintf(cfp,";\n");
+	    }
+	    else {
+	      char *c = STRDUP(tmpsym[idx]);
+	      char *p = strchr(c,'=');
+	      n = 0;
+	      if (p) {
+		*p = '\0';
+		n = atoi(c);
+	      }
+	      ODB_fprintf(cfp,"%s tmp%d = tmp%d;\n",ptype,isym,n);
+	      FREE(c);
+	      FREE(s);
+	    }
+
+	    done[isym] = 1;
+	  }
+	}
+
+	FREE(ptype);
+	FREE(pvar);
+	FREE(pmember);
+	FREE(ptable);
+      }
+      break;
+
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+	  ODB_Tree *expr = match->expr;
+	  rc += tmp_symbols(cfp, expr, done, level, numtabs, nfrom_start);
+	} /* for (j=0; j<nummatch; j++) */
+      }
+      break;
+
+    case ODB_COND:
+      {
+	int j, numargs = pnode->argc;
+	for (j=0; j<numargs; j++) {
+	  rc += tmp_symbols(cfp, pnode->argv[j], done, level, numtabs, nfrom_start);
+	}
+      }
+      break;
+
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      {
+	int j, numargs = pnode->argc - 1;
+	for (j=1; j<=numargs; j++) {
+	  rc += tmp_symbols(cfp, pnode->argv[j], done, level, numtabs, nfrom_start);
+	}
+      }
+      break;
+
+    case ODB_FILE:
+      {
+	rc += tmp_symbols(cfp, pnode->argv[2], done, level, numtabs, nfrom_start);
+      }
+      break;
+
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_EQ:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_NE:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      rc += tmp_symbols(cfp, pnode->argv[0], done, level, numtabs, nfrom_start);
+      rc += tmp_symbols(cfp, pnode->argv[1], done, level, numtabs, nfrom_start);
+      break;
+
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      rc += tmp_symbols(cfp, pnode->argv[0], done, level, numtabs, nfrom_start);
+      break;
+
+    default:
+      rc = 0;
+      break;
+    } /* switch (what) */
+  }
+
+  return rc;
+}
+
+
+#define CHECK_LENOFS(pvar) { \
+const int linklen =  8; /* strlen("LINKLEN(") */ \
+const int linkofs = 11; /* strlen("LINKOFFSET(") */ \
+if (strnequ(pvar,"LINKLEN(",linklen)) { \
+  char *p = strchr(pvar,')'); \
+  if (p) *p = '\0'; \
+  p = STRDUP(pvar+linklen); \
+  FREE(pvar); \
+  ALLOC(pvar,strlen(p)+10); \
+  sprintf(pvar,"%s.len",p); \
+  FREE(p); \
+} \
+else if (strnequ(pvar,"LINKOFFSET(",linkofs)) { \
+  char *p = strchr(pvar,')'); \
+  if (p) *p = '\0'; \
+  p = STRDUP(pvar+linkofs); \
+  FREE(pvar); \
+  ALLOC(pvar,strlen(p)+10); \
+  sprintf(pvar,"%s.offset",p); \
+  FREE(p); \
+} }
+
+
+PRIVATE void
+where_cond(FILE *cfp, const ODB_Tree *pnode)
+{
+  if (cfp && pnode) {
+    int what = pnode->what;
+
+    switch (what) {
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	ODB_fprintf(cfp,"MATCH(");
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+	  ODB_Tree *expr = match->expr;
+	  ODB_fprintf(cfp,"%s",(j>0) ? "," : ",");
+	  where_cond(cfp, expr);
+	} /* for (j=0; j<nummatch; j++) */
+	ODB_fprintf(cfp,")");
+      }
+      break;
+
+    case ODB_FUNC:
+      {
+	int j, jstart, numargs = pnode->argc - 1;
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	ODB_fprintf(cfp,"%s(",name);
+	jstart = 1;
+	for (j=jstart; j<=numargs; j++) {
+	  where_cond(cfp, pnode->argv[j]);
+	  ODB_fprintf(cfp,"%s",(j==numargs) ? ")" : ","); 
+	}
+      }
+      break;
+
+    case ODB_FILE:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	char *filename = dblquotes(pnode->argv[1]);
+	if (strequ(name,"InFile")) {
+	  where_cond(cfp, pnode->argv[2]);
+	  ODB_fprintf(cfp," IN FILE ('%s')",filename);
+	}
+	else if (strequ(name,"NotInFile")) {
+	  where_cond(cfp, pnode->argv[2]);
+	  ODB_fprintf(cfp," NOT IN FILE ('%s')",filename);
+	}
+	FREE(filename);
+      }
+      break;
+
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_NE:
+    case ODB_EQ:
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      LP;
+      where_cond(cfp, pnode->argv[0]);
+      ODB_fprintf(cfp,"%s ",ODB_keymap(what));
+      if (what == ODB_AND || what == ODB_OR) {
+	RB(1); LB(3);
+      }
+      where_cond(cfp, pnode->argv[1]);
+      RP;
+      break;
+
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      LP;
+      ODB_fprintf(cfp,"%s",ODB_keymap(what));
+      where_cond(cfp, pnode->argv[0]);
+      RP;
+      break;
+
+    case ODB_NUMBER:
+      {
+	double dval = pnode->dval;
+	ODB_fprintf(cfp,"%.14g ", dval);
+      }
+      break;
+
+    case ODB_WHERE_SYMBOL:
+      {
+	char *tag = pnode->argv[2];
+	char *s = strchr(tag,':');
+	char *name = s ? STRDUP(s+1) : STRDUP(tag);
+	if (s) CHECK_LENOFS(name);
+	ODB_fprintf(cfp,"%s ", name);
+	FREE(name);
+      }
+      break;
+
+    case ODB_NAME:
+    case ODB_HASHNAME:
+    case ODB_USDNAME:
+    case ODB_BSNUM:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	ODB_fprintf(cfp,"%s ", name);
+      }
+      break;
+
+    case ODB_STRING:
+    case ODB_WC_STRING:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->dname;
+	ODB_fprintf(cfp,"'%s' ", name);
+      }
+      break;
+
+    default:
+      break;
+    } /* switch (what) */
+  }
+}
+
+
+#define PROCESS_SPLIT(x,append) \
+char *pvar=NULL, *pmember=NULL, *ptable=NULL; \
+char *a = append?append:", "; \
+ODB_split(v->tag[x],NULL,&pvar,&pmember,&ptable,NULL); \
+if (pmember) {\
+  ODB_fprintf(cfp,"%s.%s@%s%s",pvar,pmember,ptable,a); \
+} \
+else         { \
+  CHECK_LENOFS(pvar); \
+  ODB_fprintf(cfp,"%s@%s%s",pvar,ptable,a); \
+} \
+FREE(pvar); FREE(pmember); FREE(ptable);
+
+PRIVATE void
+write_sql_old(FILE *cfp, ODB_View *v, int start_bit)
+{
+  /* May become obsolete (used only if the new version fails) */
+  const int step = 2;
+  int j;
+
+  if (start_bit) {
+    NL(1);
+    ODB_fprintf(cfp,"static const char *Sql[] = {\n");
+  }
+
+  {
+    ODB_Symbol *psym;
+    for (psym = ODB_start_symbol(); psym != NULL; psym = psym->next) {
+      if (psym->kind == ODB_USDNAME) {
+	uint done = (DONE_SYM(psym->flag, 4) || DONE_SYM(psym->flag, 5));
+	if (done) {  /* write only if found in WHERE-statement or SELECT-expression */
+	  char *s = psym->name;
+	  if (!IS_POOLNO(s) && !IS_USDHASH(s)) {
+	    /* Prevent echo'ing '$#' i.e. poolno */
+	    LB(0);
+	    if (psym->dname) {
+	      ODB_fprintf(cfp,"SET %s = '%s';",s,psym->dname);
+	    }
+	    else {
+	      ODB_fprintf(cfp,"SET %s = %.14g;",s,psym->dval);
+	    }
+	    RB(1);
+	  }
+	}
+      } /* if (psym->kind == ODB_USDNAME) */
+    }
+  }
+
+  LB(0); RB(1);
+
+  LB(0); ODB_fprintf(cfp,"CREATE VIEW %s AS",v->view->name); RB(1);
+
+  LB(0); 
+  ODB_fprintf(cfp,"SELECT%s",v->select_distinct ? " UNIQUE" : "");
+  RB(1);
+
+  for (j=0; j<v->nselect; j++) {
+    if (j==0 || j%step == 0) LB(2);
+    if (v->tag[j]) {
+      PROCESS_SPLIT(j,NULL);
+    }
+    else {
+      WRCOMMA(v->select[j]->name);
+    }
+    if (j==v->nselect-1 || (j+1)%step == 0) RB(1);
+  }
+
+  if (v->nuniqueby > 0 && !v->select_distinct) {
+    LB(0); ODB_fprintf(cfp,"UNIQUEBY"); RB(1);
+    LB(2);
+    for (j=0; j<v->nuniqueby; j++) {
+      int k = (v->nselect_all + v->nwhere - v->nuniqueby) + j;
+      if (v->tag[k]) {
+	PROCESS_SPLIT(k,NULL);
+      }
+      else {
+	WRCOMMA(v->uniqueby[j]->name);
+      }
+    }
+    RB(1);
+  }
+
+  LB(0); ODB_fprintf(cfp,"FROM"); RB(1);
+  LB(2);
+  for (j=0; j<v->nfrom; j++) {
+    WRCOMMA(v->from[j]->table->name);
+  }
+  RB(1);
+
+  if (v->cond) {
+    ODB_Tree *pcond = v->cond;
+    int what = pcond->what;
+    LB(0); ODB_fprintf(cfp,"WHERE"); RB(1);
+    if (what == ODB_AND) {
+      /* Strip off the compiler generated call to the function Unique() */
+      ODB_Tree *left = pcond->argv[0];
+      ODB_Tree *right = pcond->argv[1];
+      if (right->what == ODB_FUNC) {
+	ODB_Symbol *psym = right->argv[0];
+	char *name = psym->name;
+	if (strequ(name,"Unique")) pcond = left;
+      }
+    }
+    LB(3); where_cond(cfp,pcond); RB(1);
+  }
+
+  if (v->norderby > 0) {
+    LB(0); ODB_fprintf(cfp,"ORDERBY"); RB(1);
+    LB(2);
+    for (j=0; j<v->norderby; j++) {
+      int i = v->mkeys ? ABS(v->mkeys[j]) : 0;
+      if (i >= 1 && i <= v->nselect) {
+	char *sign = (v->mkeys[j] > 0) ? NULL : " DESC, ";
+	i--;
+	if (v->tag[i]) {
+	  PROCESS_SPLIT(i,sign);
+	}
+	else {
+	  WRCOMMA(v->select[i]->name);
+	}
+      }
+      else {
+	WRCOMMA(v->orderby[j]->name);
+      }
+    }
+    RB(1);
+  }
+
+  LB(0); ODB_fprintf(cfp,";"); RB(2);
+  TAB(1); ODB_fprintf(cfp,"NULL\n};\n");
+  NL(1);
+}
+
+PRIVATE void
+write_sql(FILE *cfp, ODB_View *v, int start_bit) 
+{
+  /* New version; takes original SQL-file from disk (if possible) */
+  extern char *odb_source;
+
+  if (start_bit) {
+    NL(1);
+    ODB_fprintf(cfp,"static const char *Sql[] = {\n");
+  }
+
+  if (ODB_copyfile(cfp, odb_source, "  \"", "\",", 1, 1) <= 0) {
+    write_sql_old(cfp, v, 0);
+  }
+  else {
+    LBDQ(0); ODB_fprintf(cfp,";"); RBDQ(2);
+    TAB(1); ODB_fprintf(cfp,"NULL\n};\n");
+    NL(1);   
+  }
+}
+
+PRIVATE void
+write_sql_for_info() 
+{
+  if (fpinf) {
+    extern char *odb_source;
+    FPINF_KEY(sql_query);
+    (void) ODB_copyfile(fpinf, odb_source, "  ", "", 0, 1);
+    FPINF_KEYEND(sql_query);
+  }
+}
+
+
+
+PRIVATE void
+write_macros(FILE *cfp) 
+{ /* Write macros (#defines) */
+  ODB_View *pview;
+  
+  init_list(NULL);
+  
+  for (pview = ODB_start_view(); pview != NULL; pview = pview->next) {
+    int nselect = pview->nselect;
+    int nselect_all = pview->nselect_all;
+    int nwhere = pview->nwhere;
+    int nall = nselect_all + nwhere;
+    int norderby = pview->norderby;
+    int nselsym = pview->nselsym;
+    int j, k;
+
+    for (j=nselect_all; j<nall; j++) {
+      char *p;
+      int plen;
+
+      if (IS_HASH(pview->where[j-(nselect_all)]->name)) continue;
+      if (IS_DOLLAR(pview->where[j-(nselect_all)]->name)) continue;
+      if (IS_BSNUM(pview->where[j-(nselect_all)]->name)) continue;
+      
+      plen = strlen(pview->def_put[j]) + strlen(pview->alias_put[j]) + 80;
+      ALLOC(p, plen);
+      snprintf(p, plen, "#define %s(i) %s", pview->def_put[j], pview->alias_put[j]);
+      if (!in_list(p)) {
+	add_list(p);
+	ODB_fprintf(cfp,"%s /* '%s' */\n", p, pview->tag[j]);
+      }
+      FREE(p);
+    }
+    
+    k = 0;
+    for (j=nselect_all+nwhere+norderby; j<nselect_all+nwhere+norderby+nselsym; j++, k++) {
+      char *p;
+      int plen;
+
+      if (IS_HASH(pview->selsym[k]->name)) continue;
+      if (IS_DOLLAR(pview->selsym[k]->name)) continue;
+      if (IS_BSNUM(pview->selsym[k]->name)) continue;
+      
+      plen = strlen(pview->def_put[j]) + strlen(pview->alias_put[j]) + 80;
+      ALLOC(p, plen);
+      sprintf(p, "#define %s(i) %s", pview->def_put[j], pview->alias_put[j]);
+      if (!in_list(p)) {
+	add_list(p);
+	ODB_fprintf(cfp,"%s /* '%s' */\n", p, pview->tag[j]);
+      }
+      FREE(p);
+    }
+  }
+  
+  destroy_list();
+}
+
+
+PRIVATE void
+write_hollerith(FILE *cfp)
+{
+  /* Hollerith symbols (if any) */
+  extern int ODB_hollerith_strings;
+  int nhs = ODB_hollerith_strings;
+
+  FPINF_KEYNUM(strings,nhs);
+  if (nhs > 0) {
+    ODB_Symbol *psym;
+    int j = 0;
+    NL(1);
+    for (psym = ODB_start_symbol(); psym != NULL; psym = psym->next) {
+      if (psym->kind == ODB_STRING || psym->kind == ODB_WC_STRING) {
+	ODB_fprintf(cfp, "#define %s \"%s\" /* [%d] */\n",psym->name,psym->sorig,j);
+	FPINF_KEYSTR(j,psym->sorig);
+	j++;
+      } /* if (psym->kind == ODB_STRING || psym->kind == ODB_WC_STRING) */
+    }
+    NL(1);
+  } /* if (nhs > 0) */
+  FPINF_KEYEND(strings);
+}
+
+
+PRIVATE int
+write_setsymbols(FILE *cfp, const char *prefix, Boolean is_a_view)
+{
+  int count = 0;
+  /* Write SET-symbols */
+  ODB_Symbol *psym;
+
+  for (psym = ODB_start_symbol(); psym != NULL; psym = psym->next) {
+    if (psym->kind == ODB_USDNAME) {
+      char *s = psym->name;
+      uint do_write = is_a_view ? /* write only if found in WHERE-statement or SELECT-expression */
+	(DONE_SYM(psym->flag, 4) || DONE_SYM(psym->flag, 5)) : 
+	1;                      /* Otherwise write always */
+      if (s && do_write && !IS_POOLNO(s) && !IS_USDHASH(s)) {
+	char *tmp;
+	const char *theprefix;
+	ALLOC(tmp, strlen(s+1) + 5);
+	sprintf(tmp, "USD_%s", s+1);
+	
+	has_USD_symbols = 1;
+	count++;
+	
+	if (is_a_view && psym->only_view) {
+	  theprefix = "PRIVATE";
+	}
+	else {
+	  theprefix = prefix;
+	}
+	
+	if (strequ(theprefix, "extern")) {
+	  ODB_fprintf(cfp,"%s double %s_%s; /* %s */\n",
+		      theprefix, tmp, odb_label, s);
+	}
+	else {
+	  ODB_fprintf(cfp,"%s double %s_%s = %.14g; /* %s */\n",
+		      theprefix, tmp, odb_label, psym->dval, s);
+	}
+
+	FREE(tmp);
+      } /* if (do_write) */
+    }
+  }
+  if (has_USD_symbols) NL(1);
+  return count;
+}
+
+PUBLIC Boolean
+ODB_IsSimpleExpr(const ODB_Tree *pnode, Boolean funcs_are_simple)
+{
+  Boolean is_simple = 0;
+  if (pnode) {
+    int what = pnode->what;
+    switch (what) {
+    case ODB_NUMBER:
+    case ODB_NAME:
+    case ODB_HASHNAME:
+    case ODB_USDNAME:
+      is_simple = 1;
+      break;
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      is_simple = funcs_are_simple;
+      break;
+    default:
+      is_simple = 0;
+      break;
+    }
+  }
+  return is_simple;
+}
+
+PUBLIC char *
+dump_s(char *in, ODB_Tree *pnode, int flag, Boolean *subexpr_is_aggrfunc)
+{
+  char *s = NULL;
+  int len = STRLEN(in);
+  Boolean Master = subexpr_is_aggrfunc ? 1 : 0;
+  static int aggrfunc_count = 0;
+
+  if (Master) aggrfunc_count = 0;
+
+  if (pnode) {
+    int what = pnode->what;
+
+    switch (what) {
+
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	int slen = len + 1;
+	ALLOC(s,slen);
+	*s = '\0';
+	if (in) strcat(s,in);
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+	  ODB_Tree *expr = match->expr;
+	  char *formula = dump_s(NULL,expr,flag,NULL);
+	  slen += STRLEN(formula) + 20;
+	  REALLOC(s,slen);
+	  if (j>0) strcat(s,",");
+	  strcat(s,"'");
+	  strcat(s,formula);
+	  strcat(s,"'");
+	  FREE(formula);
+	} /* for (j=0; j<nummatch; j++) */
+      }
+      break;
+
+    case ODB_COND:
+      { /* left ? middle : right */
+	ODB_Tree *left   = pnode->argv[0]; char *lhs = dump_s(NULL,left,flag,NULL);
+	ODB_Tree *middle = pnode->argv[1]; char *mid = dump_s(NULL,middle,flag,NULL);
+	ODB_Tree *right  = pnode->argv[2]; char *rhs = dump_s(NULL,right,flag,NULL);
+	int slen = len + strlen(lhs) + strlen(mid) + strlen(rhs) + 30;
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s(%s?%s:%s)",in?in:"",lhs,mid,rhs);
+	FREE(lhs);
+	FREE(mid);
+	FREE(rhs);
+      }
+      break;
+
+    case ODB_EQ:
+    case ODB_NE:
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      {
+	Boolean lhs_simple = ODB_IsSimpleExpr(pnode->argv[0],1);
+	char *lhs = dump_s(NULL,pnode->argv[0],flag,NULL);
+	int lenlhs = STRLEN(lhs);
+	Boolean rhs_simple = ODB_IsSimpleExpr(pnode->argv[1],1);
+	char *rhs = dump_s(NULL,pnode->argv[1],flag,NULL);
+	char *op = ODB_keymap(what);
+	char *blank = "";
+	char *newline = blank;
+	int slen = len + strlen(lhs) + strlen(op) + strlen(rhs) + 20;
+	if (flag == 1 && lenlhs > linelen_threshold) {
+	  /* if no newlines yet, add a newline */
+	  /* if since last newline > linelen_threshold, add a newline */
+	  char *pnl = strrchr(lhs,'\n');
+	  if (!pnl || lhs + lenlhs - pnl > linelen_threshold) newline = "\n";
+	}
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s%s%s%s%s%s%s%s%s%s",
+		         in?in:"",
+		           lhs_simple ? "" : "(",
+		             lhs,
+		               lhs_simple ? "" : ")",
+		                 blank,
+		                   op,
+		                     newline,
+		                       rhs_simple ? "" : "(",
+		                         rhs,
+		                           rhs_simple ? "" : ")"
+		 );
+	FREE(lhs);
+	FREE(rhs);
+      }
+      break;
+
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      {
+	Boolean lhs_simple = ODB_IsSimpleExpr(pnode->argv[0],1);
+	char *lhs = dump_s(NULL,pnode->argv[0],flag,NULL);
+	char *op = ODB_keymap(what);
+	int slen = len + strlen(op) + strlen(lhs) + 10;
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s%s%s%s%s",in?in:"",op,
+		 lhs_simple ? "" : "(",
+		 lhs,
+		 lhs_simple ? "" : ")"
+		 );
+	FREE(lhs);
+      }
+      break;
+
+    case ODB_NUMBER:
+      {
+	int slen = len + 40 + 1;
+	ALLOC(s,slen);
+	if (flag == 1) {
+	  snprintf(s,slen,"%s((double)%.14g)",in?in:"",pnode->dval);
+	}
+	else {
+	  snprintf(s,slen,"%s%.14g",in?in:"",pnode->dval);
+	}
+      }
+      break;
+
+    case ODB_NAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	int slen = len + strlen(psym->name) + 20;
+	char *expanded = (flag == 1) ? ODB_expand_sym(psym,"F(i)",NULL,NULL) : NULL;
+	slen += STRLEN(expanded);
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s%s",in?in:"",expanded?expanded:psym->name);
+	FREE(expanded);
+      }
+      break;
+ 
+    case ODB_STRING:
+    case ODB_WC_STRING:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = dblquotes(psym->name);
+	int slen = len + strlen(name) + 20;
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s '%s'",in?in:"",name);
+	FREE(name);
+      }
+      break;
+ 
+    case ODB_BSNUM:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	int slen = len + strlen(psym->name) + 20;
+	ALLOC(s,slen);
+	snprintf(s,slen,"%s%s",in?in:"",psym->name);
+      }
+      break;
+
+    case ODB_HASHNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	int slen = len + strlen(psym->name+1) + ((flag == 1) ? strlen("_ROWIDX") : 0) + 2;
+	ALLOC(s,slen);
+	if (flag == 1) {
+	  snprintf(s,slen,"%s%s_ROWIDX",in?in:"",psym->name+1);
+	}
+	else {
+	  snprintf(s,slen,"%s%s",in?in:"",psym->name);
+	}
+      }
+      break;
+
+    case ODB_USDNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	int slen = len + 
+	  (((flag == 1) && IS_POOLNO(name)) ? strlen(POOLNO) : strlen(name+1)) + 
+	  ((flag == 1) ? strlen("lc_USDHASH_") : 0) + 2;
+	ALLOC(s,slen);
+	if (flag == 1) {
+	  if (IS_USDDOTHASH(name)) {
+	    char *sh = STRDUP(name);
+	    int sh_len = STRLEN(sh);
+	    char *dot = strchr(sh,'.');
+	    if (dot) *dot = 'D'; /* IS_USDDOTHASH(s) */
+	    sh[sh_len-1] = '\0'; /* replace '#' with '\0' */
+	    snprintf(s,slen,"%slc_USDHASH_%s",in?in:"",sh+1);
+	    FREE(sh);
+	  }
+	  else {
+	    snprintf(s,slen,"%slc_USD_%s",in?in:"",IS_POOLNO(name) ? POOLNO : name+1);
+	  }
+	}
+	else {
+	  snprintf(s,slen,"%s%s",in?in:"",name);
+	}
+	has_USD_symbols = 1;
+      }
+      break;
+
+    case ODB_FUNCAGGR:
+      if (!Master) aggrfunc_count++;
+      /* no "break;" i.e. fall through purposely */
+
+    case ODB_FUNC:
+      {
+	ODB_Symbol *pfunc = pnode->argv[0];
+	int j, numargs = pnode->argc - 1;
+	struct { char *s; } *args = NULL;
+	int jstart;
+	int slen = len + ((flag == 1) ? strlen("Func_") : 0) + 1 + strlen(pfunc->name) + 3;
+	switch (flag) {
+	case 2:
+	  jstart = (pnode->joffset > 0) ? 2 : 1;
+	  break;
+	case 3:
+	  jstart = 1 + pnode->joffset;
+	  break;
+	default:
+	  jstart = 1;
+	  break;
+	}
+	if (numargs > 0) {
+	  ALLOC(args,numargs);
+	  for (j=jstart; j<=numargs; j++) {
+	    ODB_Tree *arg = pnode->argv[j];
+	    char *x = dump_s(NULL,arg,flag,NULL);
+	    slen += STRLEN(x);
+	    if (j<numargs) slen += 1;
+	    args[j-1].s = x;
+	  }
+	}
+	ALLOC(s,slen);
+	if (flag == 1) {
+	  snprintf(s,slen,"%sFunc_%s%s(",
+		   in?in:"",
+		   (what == ODB_FUNCAGGR) ? "_" : "", /* prepend underscore with aggregate funcs */
+		   pfunc->name);
+	}
+	else {
+	  snprintf(s,slen,"%s%s%s(",
+		   in?in:"",
+		   (what == ODB_FUNCAGGR) ? "_" : "", /* prepend underscore with aggregate funcs */
+		   pfunc->name);
+	}
+	if (numargs > 0) {
+	  for (j=jstart; j<=numargs; j++) {
+	    char *x = args[j-1].s;
+	    strcat(s,x);
+	    if (j<numargs) strcat(s,",");
+	    FREE(x);
+	  }
+	  FREE(args);
+	}
+	strcat(s,")");
+      }
+      break;
+
+    default:
+      if (in) {
+	SETMSG3("Unsupported expression after '%s' : Key '%s' (%d) not implemented in this context\n",
+		in, ODB_keymap(what), what);
+      }
+      else {
+	SETMSG2("Unsupported expression : Key '%s' (%d) not implemented in this context\n",
+		ODB_keymap(what), what);
+      }
+      YYerror(msg);
+      break;
+    }
+  }
+  FREE(in);
+
+  if (Master && subexpr_is_aggrfunc) {
+    *subexpr_is_aggrfunc = (aggrfunc_count > 0) ? 1 : 0;
+    aggrfunc_count = 0;
+  }
+
+  return s;
+}
+
+PUBLIC void 
+dump_c(FILE *cfp, int lineno, ODB_Tree *pnode)
+{
+  ODB_lineno = lineno;
+
+  if (pnode) {
+    int what = pnode->what;
+
+    switch (what) {
+
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+#if 0
+	  char *formula = match->formula; /* We don't need this, actually */
+	  ODB_Symbol *psym = match->symexpr->argv[0]; /* This is formula's S2D_<number>-massagee!! */
+	  if (j>0) ODB_fprintf(cfp, ", ");
+	  ODB_fprintf(cfp, "EvalMe(%s)", psym->name);
+#else
+	  ODB_Tree *expr = match->expr;
+	  if (j>0) ODB_fprintf(cfp, ", ");
+	  ODB_fprintf(cfp, "EvalMe(");
+	  dump_c(cfp,lineno,expr);
+	  ODB_fprintf(cfp, ")");
+#endif
+	} /* for (j=0; j<nummatch; j++) */
+      }
+      break;
+
+    case ODB_EQ:
+    case ODB_NE:
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      ODB_fprintf(cfp,"(");
+      dump_c(cfp,lineno,pnode->argv[0]);
+      ODB_fprintf(cfp," %s ",ODB_keymap(what));
+      if (info_dump < 2 && (what == ODB_AND || what == ODB_OR)) {
+	int tabs = (!info_dump) ? 6 : 1;
+	NL(1); TAB(tabs);
+      }
+      dump_c(cfp,lineno,pnode->argv[1]);
+      ODB_fprintf(cfp,")");
+      break;
+
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      ODB_fprintf(cfp,"(");
+      ODB_fprintf(cfp,"%s",ODB_keymap(what));
+      dump_c(cfp,lineno,pnode->argv[0]);
+      ODB_fprintf(cfp,")");
+      break;
+
+    case ODB_NUMBER:
+      if (!info_dump) {
+	ODB_fprintf(cfp,"((double)%.14g)",pnode->dval);
+      }
+      else {
+	ODB_fprintf(cfp,"%.14g",pnode->dval);
+      }
+      break;
+
+    case ODB_STRING:
+    case ODB_WC_STRING:
+    case ODB_NAME:
+    case ODB_BSNUM:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	ODB_fprintf(cfp,"%s",psym->name);
+      }
+      break;
+
+    case ODB_HASHNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	if (!info_dump) {
+	  ODB_fprintf(cfp,"%s_ROW",psym->name+1);
+	}
+	else {
+	  ODB_fprintf(cfp,"%s",psym->name);
+	}
+      }
+      break;
+
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      {
+	ODB_Symbol *pfunc = pnode->argv[0];
+	int j, numargs = pnode->argc - 1;
+	int jstart = 1;
+	ODB_fprintf(cfp,"%s%s%s(",
+		    info_dump ? "" : "Func_",
+		    (what == ODB_FUNCAGGR) ? "_" : "",
+		    pfunc->name);
+	if (ddl_piped && pnode->joffset > 0) jstart = 2;
+	for (j=jstart; j<=numargs; j++) {
+	  ODB_Tree *arg = pnode->argv[j];
+	  dump_c(cfp,lineno,arg);
+	  if (j<numargs) ODB_fprintf(cfp,", ");
+	}
+	ODB_fprintf(cfp,")");
+      }
+      break;
+
+    case ODB_FILE:
+      {
+	ODB_Symbol *pfunc = pnode->argv[0];
+	char *filename = dblquotes(pnode->argv[1]);
+	ODB_Tree *arg = pnode->argv[2];
+	ODB_fprintf(cfp,"%s%s(\"%s\",",info_dump ? "" : "Func_",pfunc->name,filename);
+	dump_c(cfp,lineno,arg);
+	ODB_fprintf(cfp,")");
+	FREE(filename);
+      }
+      break;
+
+    case ODB_USDNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *s = psym->name;
+	if (!info_dump) {
+	  if (IS_USDDOTHASH(s)) {
+	    char *sh = STRDUP(s);
+	    int sh_len = STRLEN(sh);
+	    char *dot = strchr(sh,'.');
+	    if (dot) *dot = 'D'; /* IS_USDDOTHASH(s) */
+	    sh[sh_len-1] = '\0'; /* replace '#' with '\0' */
+	    ODB_fprintf(cfp,"lc_USDHASH_%s",sh+1);
+	    FREE(sh);
+	  }
+	  else {
+	    ODB_fprintf(cfp,"lc_USD_%s",IS_POOLNO(s) ? POOLNO : s+1);
+	  }
+	}
+	else {
+	  ODB_fprintf(cfp,"%s", s);
+	}
+	has_USD_symbols = 1;
+      }
+      break;
+
+    case ODB_WHERE_SYMBOL:
+      {
+	if (!info_dump) {
+	  char *s = pnode->argv[0];
+	  char *pvar = NULL;
+	  int isym;
+	  (void) ODB_split(s, NULL, &pvar, NULL, NULL, NULL);
+	  isym = atoi(pvar);
+	  ODB_fprintf(cfp,"tmp%d",isym);
+	  FREE(pvar);
+	}
+	else {
+	  char *tag = pnode->argv[2];
+	  char *s = strchr(tag,':');
+	  char *name = s ? STRDUP(s+1) : STRDUP(tag);
+	  /* if (s) CHECK_LENOFS(name); */
+	  ODB_fprintf(cfp,"%s", name);
+	  FREE(name);
+	}
+      }
+      break;
+
+    case ODB_SET:
+      break;
+
+    case ODB_TYPE:
+      {
+	ODB_Type *ptype = pnode->argv[0];
+
+	if (ptype) {
+	  /* typedef for TYPE */
+	  int nsym = ptype->nsym;
+	  Boolean processed = ptype->processed;
+
+	  if (nsym > 0 && !processed) {
+	    char *name = ptype->type->name;
+
+	    ODB_fprintf(cfp,"/* *************** TYPE \"%s\" *************** */\n",name);
+	    if (nsym == 1 && ptype->no_members) {
+	      int i = 0;
+	      ODB_fprintf(cfp,
+		      "\n/* typedef %s %s; */\n",
+		      ptype->sym[i]->name, ptype->member[i]->name);
+	      ODB_fprintf(cfp,
+		      "#define %s %s\n",
+		      ptype->member[i]->name, ptype->sym[i]->name);
+	    }
+	    else {
+	      int i;
+	      ODB_fprintf(cfp,"\n/* typedef struct {\n");
+	      for (i=0; i<nsym; i++) {
+		char *s = 
+		  get_typedef(ptype->sym[i]->name, 
+			      ptype->member[i]->name, NULL);
+		TAB(1); ODB_fprintf(cfp,"%s;\n",s);
+		FREE(s);
+	      }
+	      ODB_fprintf(cfp,"} %s; */\n",name);
+	    }
+	    NL(1);
+
+	    ptype->processed = 1;
+	    ODB_fprintf(cfp,"/* *************** End of TYPE \"%s\" *************** */\n",name);
+	  }
+	}
+      }
+      break;
+
+    case ODB_TABLE:
+      {
+	ODB_Table *ptable = pnode->argv[0];
+
+	ODB_pushFILE(fptable);
+
+	if (ptable) {
+	  char *typetag = NULL;
+	  char *nametag = NULL;
+	  char *exttypetag = NULL;
+	  char *extnametag = NULL;
+	  int typetag_len = 0;
+	  int nametag_len = 0;
+	  int exttypetag_len = 0;
+	  int extnametag_len = 0;
+	  int nsym = ptable->nsym;
+	  int nmem = 0;
+
+	  if (nsym > 0) {
+	    char *name = ptable->table->name;
+	    Boolean dummy_table = is_dummy_table(name);
+	    int i, j;
+	    int ntypes_table = ntypes;
+	    Boolean typemask[NTYPES];
+
+	    typemask[0] = 1;
+
+	    if (verbose)
+	      fprintf(stderr,"genc: Processing TABLE='%s' (dummy_table status %d) ...\n",
+		      name, (int)dummy_table);
+
+	    if (fptable != fpdevnull) {
+	      char *p, *dofunc;
+	      int len;
+	      
+	      len = strlen(odb_label) + strlen(name) + 4;
+	      ALLOC(dofunc, len);
+	      sprintf(dofunc,"%s_T_%s", odb_label, name);
+
+	      len = strlen(dofunc) + 3;
+	      ALLOC(p, len);
+	      sprintf(p, "%s.c", dofunc);
+
+	      if (ABS(filtered_info) < 2) {
+		fptable = FOPEN(p, "w");
+	      }
+	      else {
+		fptable = NULL;
+	      }
+	      FREE(p);
+
+	      ALLOC(flist, 1);
+	      flist->filename = STRDUP(dofunc);
+	      flist->create_so = 0;
+	      flist->next = NULL;
+	      if (!flist_start) {
+		flist_start = flist;
+	      }
+	      else {
+		flist_last->next = flist;
+	      }
+	      flist_last = flist;
+
+	      FREE(dofunc);
+	    }
+
+	    cfp = fptable;
+
+	    ODB_fprintf(cfp,"#undef ODB_MAINCODE\n");
+	    ODB_fprintf(cfp,"#undef IS_a_VIEW\n");
+	    ODB_fprintf(cfp,"#define IS_a_TABLE_%s 1\n",name);
+	    /* set_optlevel(cfp, 2); */
+	    set_optlevel(cfp, 0);
+	    ODB_fprintf(cfp,"#include \"%s.h\"\n",odb_label);
+	    NL(1);
+
+	    ODB_pushFILE(cfp);
+	    cfp = fphdr;
+
+	    /* typedef for TABLE */
+
+	    ODB_fprintf(cfp,"#if defined(IS_a_TABLE_%s) || defined(ODB_MAINCODE) || defined(IS_a_VIEW)\n",name);
+	    NL(1);
+	    ODB_fprintf(cfp,
+			"/* *************** TABLE \"%s\" : "
+			"appearance order#%d, hierarchy rank# %d, weight = %.6f *************** */\n",
+			name, ptable->tableno, ptable->rank, ptable->wt);
+	    ODB_fprintf(cfp,"\ntypedef struct {\n");
+	    TAB(1); ODB_fprintf(cfp,"int Handle;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PoolNo;\n");
+	    TAB(1); ODB_fprintf(cfp,"ODB_Funcs *Funcs;\n");
+	    TAB(1); ODB_fprintf(cfp,"boolean Is_loaded;\n");
+	    TAB(1); ODB_fprintf(cfp,"boolean Is_new;\n");
+	    TAB(1); ODB_fprintf(cfp,"boolean Swapped_out;\n");
+	    TAB(1); ODB_fprintf(cfp,"boolean Byteswap;\n");
+	    TAB(1); ODB_fprintf(cfp,"int IO_method;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Created[2];\n");
+	    TAB(1); ODB_fprintf(cfp,"int LastUpdated[2];\n");
+	    TAB(1); ODB_fprintf(cfp,"int Ncols;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Nrows;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Nalloc;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Numreqs;\n");
+
+	    if (!dummy_table) {
+	      for (i=0; i<nsym; i++) {
+		ODB_Type *ptype = ptable->type[i];
+		char *tyname = get_typename(ptype);
+		char *symname = ptable->sym[i]->name;
+		char *s = get_typedef(tyname, symname, NULL);
+		
+		if (ptype->bitstream) {
+		  char *p = strchr(s,' ');
+		  if (p) *p = ',';
+		  TAB(1);
+		  ODB_fprintf(cfp,
+			      "DeclareDS(%s); /* Alias bit stream -typedef \"%s\" */\n",
+			      s,tyname);
+		}
+		else {
+		  char *p = strchr(s,' ');
+		  if (p) *p = ',';
+		  TAB(1);
+		  ODB_fprintf(cfp, "DeclareDS(%s);\n", s);
+		}
+
+		FREE(s);
+		
+	      } /* for (i=0; i<nsym; i++) */
+	    } /* if (!dummy_table) */
+
+	    ODB_fprintf(cfp,"} TABLE_%s;\n",name);
+	    NL(1);
+	    ODB_fprintf(cfp,
+		    "#endif /* defined(IS_a_TABLE_%s) || defined(ODB_MAINCODE)  || defined(IS_a_VIEW) */\n",
+		    name);
+	    NL(1);
+
+	    /* Tags for TABLE */
+
+	    nametag = STRDUP(ODB_tag_delim);
+	    nametag_len = 2;
+	    typetag = STRDUP(ODB_tag_delim);
+	    typetag_len = 2;
+	    extnametag = STRDUP(ODB_tag_delim);
+	    extnametag_len = 2;
+	    exttypetag = STRDUP(ODB_tag_delim);
+	    exttypetag_len = 2;
+
+	    ODB_fprintf(cfp,"#if !defined(ODB_MAINCODE) && defined(IS_a_TABLE_%s)\n",name);
+	    ODB_fprintf(cfp,"extern const ODB_Tags *%s_Set_T_%s_TAG(int *ntag_out, int *nmem_out);\n",odb_label,name);
+	    ODB_fprintf(cfp,"extern const ODB_PrepTags *%s_Set_T_%s_PREPTAG(int *npreptag_out);\n",odb_label,name);
+	    ODB_fprintf(cfp,"#elif defined(ODB_MAINCODE)\n");
+	    ODB_fprintf(cfp,"PRIVATE const ODB_Tags *%s_T_%s_TAG = NULL;\n",odb_label,name);
+	    ODB_fprintf(cfp,"PRIVATE const ODB_PrepTags *%s_T_%s_PREPTAG = NULL;\n",odb_label,name);
+	    ODB_fprintf(cfp,"PRIVATE int %s_nT_%s_TAG = 0;\n",odb_label,name);
+	    ODB_fprintf(cfp,"PRIVATE int %s_nT_%s_PREPTAG = 0;\n",odb_label,name);
+	    ODB_fprintf(cfp,"PRIVATE int %s_nT_%s_MEM = 0;\n",odb_label,name);
+
+	    ODB_fprintf(cfp,"PUBLIC const ODB_Tags *\n%s_Set_T_%s_TAG(int *ntag_out, int *nmem_out)\n",odb_label,name);
+	    ODB_fprintf(cfp,"{\n");
+
+	    if (!dummy_table) {
+	      nmem = 0;
+	      TAB(1); ODB_fprintf(cfp,"if (!%s_T_%s_TAG) {\n", odb_label,name);
+	      TAB(2); ODB_fprintf(cfp,"int ntag = %d;\n", nsym);
+	      TAB(2); ODB_fprintf(cfp,"ODB_Tags *T = NULL;\n");
+	      TAB(2); ODB_fprintf(cfp,"CALLOC(T, ntag);\n");
+	      
+	      for (i=0; i<nsym; i++) {
+		ODB_Type *ptype = ptable->type[i];
+		char *tyname = get_typename(ptype);
+		char *symname = ptable->sym[i]->name;
+		int ksym = ptype->nsym;
+		ODB_Symbol **member = ptype->member;
+		
+		TAB(2);
+		ODB_fprintf(cfp,
+			    "{ static char s[] = \"%s:%s@%s\"; T[%d].name = s; }\n",
+			    tyname,symname,name,i);
+	      
+		nametag_len += strlen(symname) + 1 + strlen(name) + 1;
+		REALLOC(nametag, nametag_len);
+		strcat(nametag,symname);
+		strcat(nametag,"@");
+		strcat(nametag,name);
+		strcat(nametag,ODB_tag_delim);
+		
+		typetag_len += strlen(tyname) + 1;
+		REALLOC(typetag, typetag_len);
+		strcat(typetag,tyname);
+		strcat(typetag,ODB_tag_delim);
+
+		if (ksym > 1) {
+		  int ii;
+		  TAB(2);
+		  ODB_fprintf(cfp,
+			      "T[%d].nmem = %d;\n",
+			      i,ksym);
+
+		  ODB_fprintf(cfp,
+			      "ALLOC(T[%d].memb, %d);\n",i,ksym);
+		  nmem += ksym;
+		  for (ii=0; ii<ksym; ii++) {
+		    char *member_name = member[ii]->name;
+		    int nbits = ptype->len[ii];
+		    char cbits[3];
+		    TAB(3);
+		    ODB_fprintf(cfp,
+				"{ static char s[] = \"%s %d\"; T[%d].memb[%d] = s; }\n",
+				member_name, nbits, i, ii);
+		    
+		    extnametag_len += strlen(symname) + 1 + strlen(member_name) + 1 + strlen(name) + 1;
+		    REALLOC(extnametag, extnametag_len);
+		    strcat(extnametag,symname);
+		    strcat(extnametag,".");
+		    strcat(extnametag,member_name);
+		    strcat(extnametag,"@");
+		    strcat(extnametag,name);
+		    strcat(extnametag,ODB_tag_delim);
+		    
+		    exttypetag_len += strlen("bit") + 2 + 1; /* The "2" since MAXBITS is always < 100 */
+		    REALLOC(exttypetag, exttypetag_len);
+		    strcat(exttypetag,"bit");
+		    snprintf(cbits,sizeof(cbits),"%d",nbits);
+		    strcat(exttypetag,cbits);
+		    strcat(exttypetag,ODB_tag_delim);
+		  } /* for (ii=0; ii<ksym; ii++) */
+		}
+	      } /* for (i=0; i<nsym; i++) */
+	      TAB(2); ODB_fprintf(cfp,"%s_T_%s_TAG = T;\n",odb_label,name);
+	      TAB(2); ODB_fprintf(cfp,"%s_nT_%s_TAG = ntag;\n",odb_label,name);
+	      TAB(2); ODB_fprintf(cfp,"%s_nT_%s_MEM = %d;\n",odb_label,name,nmem);
+	  
+	      TAB(1); ODB_fprintf(cfp,"}\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"if (ntag_out) *ntag_out = %s_nT_%s_TAG;\n",odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"if (nmem_out) *nmem_out = %s_nT_%s_MEM;\n",odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"return %s_T_%s_TAG;\n}\n",odb_label,name);
+	    
+	    if (nmem > 0) {
+	      char *p = NULL;
+	      extnametag_len += nametag_len - 1;
+	      p = STRDUP(extnametag+1); /* All, but the first ODB_tag_delim */
+	      FREE(extnametag);
+	      ALLOC(extnametag,extnametag_len);
+	      strcpy(extnametag,nametag);
+	      strcat(extnametag,p);
+	      FREE(p);
+	      exttypetag_len += typetag_len - 1;
+	      p = STRDUP(exttypetag+1); /* All, but the first ODB_tag_delim */
+	      FREE(exttypetag);
+	      ALLOC(exttypetag,exttypetag_len);
+	      strcpy(exttypetag,typetag);
+	      strcat(exttypetag,p);
+	      FREE(p);
+	    }
+	    
+	    ODB_fprintf(cfp,"PUBLIC const ODB_PrepTags *\n%s_Set_T_%s_PREPTAG(int *npreptag_out)\n",odb_label,name);
+	    ODB_fprintf(cfp,"{\n");
+	    if (!dummy_table) {
+	      TAB(1); ODB_fprintf(cfp,"if (!%s_T_%s_PREPTAG) {\n", odb_label,name);
+	      TAB(2); ODB_fprintf(cfp,"int npreptag = %d;\n", (nmem > 0) ? 4 : 2);
+	      TAB(2); ODB_fprintf(cfp,"ODB_PrepTags *T = NULL;\n");
+	      TAB(2); ODB_fprintf(cfp,"ALLOC(T, npreptag);\n");
+	      if (nmem > 0) {
+		TAB(2); ODB_fprintf(cfp,"T[0].tagtype = preptag_name;\n");
+		TAB(2); ODB_fprintf(cfp,"T[0].longname_len = %d;\n",strlen(nametag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,nametag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[0].longname = s; }\n");
+
+		TAB(2); ODB_fprintf(cfp,"T[1].tagtype = preptag_type;\n");
+		TAB(2); ODB_fprintf(cfp,"T[1].longname_len = %d;\n",strlen(typetag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,typetag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[1].longname = s; }\n");
+
+		TAB(2); ODB_fprintf(cfp,"T[2].tagtype = preptag_extname;\n");
+		TAB(2); ODB_fprintf(cfp,"T[2].longname_len = %d;\n",strlen(extnametag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,extnametag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[2].longname = s; }\n");
+
+		TAB(2); ODB_fprintf(cfp,"T[3].tagtype = preptag_exttype;\n");
+		TAB(2); ODB_fprintf(cfp,"T[3].longname_len = %d;\n",strlen(exttypetag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,exttypetag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[3].longname = s; }\n");
+	      }
+	      else {
+		TAB(2); ODB_fprintf(cfp,"T[0].tagtype = (preptag_name | preptag_extname);\n");
+		TAB(2); ODB_fprintf(cfp,"T[0].longname_len = %d;\n",strlen(nametag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,nametag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[0].longname = s; }\n");
+
+		TAB(2); ODB_fprintf(cfp,"T[1].tagtype = (preptag_type | preptag_exttype);\n");
+		TAB(2); ODB_fprintf(cfp,"T[1].longname_len = %d;\n",strlen(typetag));
+		TAB(2); ODB_fprintf(cfp,"{ static char s[] =");
+		TagStrip(cfp,3,typetag,";\n");
+		TAB(3); ODB_fprintf(cfp,"T[1].longname = s; }\n");
+	      }
+	      TAB(2); ODB_fprintf(cfp,"%s_T_%s_PREPTAG = T;\n",odb_label,name);
+	      TAB(2); ODB_fprintf(cfp,"%s_nT_%s_PREPTAG = npreptag;\n",odb_label,name);
+	      TAB(1); ODB_fprintf(cfp,"}\n");
+	    }
+	    TAB(1); ODB_fprintf(cfp,"if (npreptag_out) *npreptag_out = %s_nT_%s_PREPTAG;\n",odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"return %s_T_%s_PREPTAG;\n}\n",odb_label,name);
+
+	    ODB_fprintf(cfp,"#endif\n");
+	    NL(1);
+	    
+	    FREE(nametag);
+	    FREE(typetag);
+	    FREE(extnametag);
+	    FREE(exttypetag);
+
+	    ODB_fprintf(cfp,"#if defined(ODB_MAINCODE)\n");
+	    NL(1);
+
+	    cfp = ODB_popFILE();
+
+	    (void) write_setsymbols(cfp, "extern", 0);
+	    NL(1);
+
+	    /* CANCEL function for TABLE : removed */
+	
+	    /* 
+	    ODB_fprintf(fphdr,"extern void %s_Ccl_T_%s(void *T);\n",odb_label,name);
+	    ODB_fprintf(cfp,"PUBLIC void\n%s_Ccl_T_%s(void *T)\n{ }\n",odb_label,name);
+	    NL(1);
+	    */
+
+
+	    /* PACK function for TABLE */
+	    
+	    ODB_fprintf(fphdr,"extern int %s_Pack_T_%s(void *T);\n",odb_label,name);
+	    ODB_fprintf(cfp,"PUBLIC int\n%s_Pack_T_%s(void *T)\n{\n",odb_label,name);
+	    if (!dummy_table) {
+	      TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+	      TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	      TAB(1); ODB_fprintf(cfp,"Packed_DS *PDS;\n");
+	      TAB(1); ODB_fprintf(cfp,"if (P->Is_loaded) {\n");
+	      for (i=0; i<nsym; i++) {
+		ODB_Type *ptype = ptable->type[i];
+		char *tyname = get_typename(ptype);
+		char *symname = ptable->sym[i]->name;
+		TAB(2); 
+		ODB_fprintf(cfp,"PDS = PackDS(P, %s, %s, %s); ",odb_label,tyname,symname);
+		ODB_fprintf(cfp,"CHECK_PDS_ERROR(%d);\n",i+1);
+	      }
+	      TAB(1); ODB_fprintf(cfp,"}\n");
+	      TAB(1); ODB_fprintf(cfp,"return Nbytes;\n");
+	    }
+	    else {
+	      TAB(1); ODB_fprintf(cfp,"return 0;\n");
+	    }
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    /* UNPACK function for TABLE */
+	    
+	    ODB_fprintf(fphdr,"extern int %s_Unpack_T_%s(void *T);\n",odb_label,name);
+	    ODB_fprintf(cfp,"PUBLIC int\n%s_Unpack_T_%s(void *T)\n{\n",odb_label,name);
+	    if (!dummy_table) {
+	      TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+	      TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	      TAB(1); ODB_fprintf(cfp,"if (P->Is_loaded) {\n");
+	      for (i=0; i<nsym; i++) {
+		ODB_Type *ptype = ptable->type[i];
+		char *tyname = get_typename(ptype);
+		char *symname = ptable->sym[i]->name;
+		TAB(2); ODB_fprintf(cfp,"UseDS(P, %s, %s, %s); Nbytes += BYTESIZE(P->%s.d);\n",
+				    odb_label,tyname,symname,symname);
+	      }
+	      TAB(1); ODB_fprintf(cfp,"}\n");
+	      TAB(1); ODB_fprintf(cfp,"return Nbytes;\n");
+	    }
+	    else {
+	      TAB(1); ODB_fprintf(cfp,"return 0;\n");
+	    }
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    /* SELECT function for TABLE */
+	    
+	    ODB_fprintf(fphdr,"extern int %s_Sel_T_%s(void *T, ODB_PE_Info *PEinfo, int phase, void *feedback);\n",
+		    odb_label,name);
+	    ODB_fprintf(cfp,"PUBLIC int\n%s_Sel_T_%s(void *T, ODB_PE_Info *PEinfo, int phase, void *feedback)\n{\n",
+		    odb_label,name);
+	    if (!dummy_table) {
+	      TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	      TAB(1); ODB_fprintf(cfp,"ODBMAC_TABLE_DELAYED_LOAD(%s);\n",name);
+	      TAB(1); ODB_fprintf(cfp,"return P->Nrows;\n");
+	    }
+	    else {
+	      TAB(1); ODB_fprintf(cfp,"return 0;\n");
+	    }
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    for (j=0; j<ntypes_table; j++) {
+	      char *pKey = Key[j];
+	      char *pExtType = ExtType[j];
+	      
+	      if (!typemask[j]) continue;
+
+	      /* GET function for TABLE */
+
+	      init_list(NULL);
+	      
+	      for (i=0; i<nsym; i++) {
+		char *p;
+		ODB_Type *ptype = ptable->type[i];
+		char *type = get_typename(ptype);
+		
+		ALLOC(p, strlen(type) + 3);
+		sprintf(p, "/%s/", type);
+		
+		if (!in_list(p)) {
+		  add_list(p);
+		  vector_loop(cfp, 0);
+		}
+		
+		FREE(p);
+	      } /* for (i=0; i<nsym; i++) */
+	      NL(1);
+	      
+	      ODB_fprintf(fphdr,"PreGetTable(%s, %s, %s, %s);\n", odb_label, pKey, pExtType, name);
+	      ODB_fprintf(cfp,"PreGetTable(%s, %s, %s, %s)\n", odb_label, pKey, pExtType, name);
+	      
+	      if (!dummy_table) {
+		for (i=0; i<nsym; i++) {
+		  char *s = ptable->sym[i]->name;
+		  ODB_Type *ptype = ptable->type[i];
+		  char *type = get_typename(ptype);
+		  char *datatype = NULL;
+		  (void)get_PKmethod(type,NULL,&datatype,NULL);
+		  
+		  TAB(1);
+		  ODB_fprintf(cfp,
+			      "Call_CopyGet_TABLE(%s, %s, %d, %s, %s, D, %s, Count, DATATYPE_%s);\n",
+			      odb_label, pKey, i+1, name, type, s, datatype);
+		  FREE(datatype);
+		}
+	      }
+
+	      ODB_fprintf(cfp,"PostGetTable(%s, %s, %s)\n", pKey, pExtType, name);
+	      NL(1);
+	      
+	      /* PUT function for TABLE */
+	      
+	      init_list(NULL);
+	      
+	      for (i=0; i<nsym; i++) {
+		char *p;
+		/* char *s = ptable->sym[i]->name; */
+		ODB_Type *ptype = ptable->type[i];
+		char *type = get_typename(ptype);
+		
+		ALLOC(p, strlen(type) + 3);
+		sprintf(p, "/%s/", type);
+		
+		if (!in_list(p)) {
+		  add_list(p);
+		  vector_loop(cfp, 0);
+		}
+		
+		FREE(p);
+	      }
+	      NL(1);
+
+	      ODB_fprintf(fphdr,"PrePutTable(%s, %s, %s, %s);\n", odb_label, pKey, pExtType, name);
+	      ODB_fprintf(cfp,"PrePutTable(%s, %s, %s, %s)\n", odb_label, pKey, pExtType, name);
+	      
+	      if (!dummy_table) {
+		for (i=0; i<nsym; i++) {
+		  char *s = ptable->sym[i]->name;
+		  ODB_Type *ptype = ptable->type[i];
+		  char *type = get_typename(ptype);
+		  char *datatype = NULL;
+		  (void)get_PKmethod(type,NULL,&datatype,NULL);
+		  
+		  TAB(1);
+		  ODB_fprintf(cfp,
+			      "Call_CopyPut_TABLE(%s, %s, %d, %s, %s, %s, D, Count, DATATYPE_%s);\n",
+			      odb_label, pKey, i+1, name, type, s, datatype);
+		  FREE(datatype);
+		}
+	      }
+
+	      ODB_fprintf(cfp,"PostPutTable(%s, %s, %s)\n", pKey, pExtType, name);
+	      NL(1);
+	    } /* for (j=0; j<ntypes_table; j++) */
+	    
+	    /* Load function for TABLE */
+
+	    ODB_fprintf(fphdr,"PreLoadTable(%s, %s);\n",odb_label,name);
+	    ODB_fprintf(cfp,"PreLoadTable(%s, %s);\n",odb_label,name);
+
+	    if (!dummy_table) {
+	      for (i=0; i<nsym; i++) {
+		char *s = ptable->sym[i]->name;
+		ODB_Type *ptype = ptable->type[i];
+		char *type = get_typename(ptype);
+		char *datatype = NULL;
+		(void)get_PKmethod(type,NULL,&datatype,NULL);
+		TAB(1); 
+		ODB_fprintf(cfp,
+			    "Call_Read_DS(%s, fp_idx, filename, Nbytes, %s, DATATYPE_%s, %s);\n",
+			    odb_label, type, datatype, s);
+		FREE(datatype);
+	      }
+	    }
+
+	    ODB_fprintf(cfp,"PostLoadTable(%s)\n",name);
+	    NL(1);
+
+	    /* Store function for TABLE */
+
+	    ODB_fprintf(fphdr,"PreStoreTable(%s, %s);\n",odb_label,name);
+	    ODB_fprintf(cfp,"PreStoreTable(%s, %s);\n",odb_label,name);
+
+	    if (!dummy_table) {
+	      for (i=0; i<nsym; i++) {
+		char *s = ptable->sym[i]->name;
+		ODB_Type *ptype = ptable->type[i];
+		char *type = get_typename(ptype);
+		char *datatype = NULL;
+		(void)get_PKmethod(type,NULL,&datatype,NULL);
+		TAB(1); 
+		ODB_fprintf(cfp,
+			    "Call_Write_DS(%s, fp_idx, filename, Nbytes, %s, DATATYPE_%s, %s);\n",
+			    odb_label, type, datatype, s);
+		FREE(datatype);
+	      }
+	    }
+
+	    ODB_fprintf(cfp,"PostStoreTable(%s)\n",name);
+	    NL(1);
+
+	    /* Dimension function for TABLE */
+
+	    ODB_fprintf(cfp,"DefineLookupTable(%s)\n",name);
+	    NL(1);
+
+	    ODB_fprintf(fphdr,
+		    "extern void %s_Dim_T_%s(void *T, int *Nrows, int *Ncols, ",
+		    odb_label,name);
+	    ODB_fprintf(cfp,
+		    "PUBLIC void\n%s_Dim_T_%s(void *T, int *Nrows, int *Ncols,\n",
+		    odb_label,name);
+	    TAB(1);
+	    ODB_fprintf(fphdr,"int *Nrowoffset, int ProcID);\n");
+	    ODB_fprintf(cfp,"int *Nrowoffset, int ProcID)\n{\n");
+
+	    TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"Call_LookupTable(%s, P, Nrows, Ncols);\n",name);
+	    TAB(1); ODB_fprintf(cfp,"if (Nrowoffset) *Nrowoffset = 0;\n");
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    /* Removing from memory / swapping out a TABLE */
+
+	    ODB_fprintf(fphdr,
+		    "extern void %s_Swapout_T_%s(void *T);\n",
+		    odb_label,name);
+	    ODB_fprintf(cfp,
+		    "PUBLIC void\n%s_Swapout_T_%s(void *T)\n{\n",
+		    odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Count = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PoolNo = P->PoolNo;\n");
+	    TAB(1); ODB_fprintf(cfp,"FILE *do_trace = NULL;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"if (P->Swapped_out || !P->Is_loaded) return;\n");
+	    TAB(1); ODB_fprintf(cfp,"do_trace = ODB_trace_fp();\n");
+
+	    if (!dummy_table) {
+	      for (i=0; i<nsym; i++) {
+		char *s = ptable->sym[i]->name;
+		TAB(1); ODB_fprintf(cfp,"FreeDS(P, %s, Nbytes, Count);\n",s);
+	      } /* for (i=0; i<nsym; i++) */
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"P->Nrows = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Nalloc = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Is_loaded = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Swapped_out = P->Is_new ? 0 : 1;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SWAPOUT(%s,%d);\n",name,nsym);
+
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    /* Remove function for TABLE */
+
+	    ODB_fprintf(cfp,"DefineRemoveTable(%s, %s)\n", odb_label, name);
+	    NL(1);
+
+	    /* TABLE SQL : A dummy */
+
+	    ODB_fprintf(fphdr, "extern int %s_Sql_T_%s(",odb_label,name);
+	    ODB_fprintf(fphdr, "FILE *fp, int mode, ");
+	    ODB_fprintf(fphdr, "const char *prefix, const char *postfix, char **sqlout);\n");
+
+	    ODB_fprintf(cfp, "PUBLIC int\n%s_Sql_T_%s(",odb_label,name);
+	    ODB_fprintf(cfp, "FILE *fp, int mode, const char *prefix, const char *postfix, char **sqlout) ");
+	    ODB_fprintf(cfp, "{ ODBMAC_TABLESQL(); }\n");
+	    NL(1);
+
+	    /* Sorting keys for TABLE : removed */
+
+	    /*
+	    ODB_fprintf(fphdr,
+		    "extern int *%s_SortKeys_T_%s(void *V, int *NSortKeys);\n",
+		    odb_label,name);
+	    ODB_fprintf(cfp,
+		    "PUBLIC int *\n%s_SortKeys_T_%s(void *V, int *NSortKeys)\n{\n",
+		    odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"if (NSortKeys) *NSortKeys = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"return NULL;\n");
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+	    */
+
+	    /* Initialization function for TABLE */
+
+	    ODB_fprintf(fphdr,
+		    "extern void *%s_Init_T_%s(void *T, ODB_Pool *Pool, int Is_new, int IO_method, int it, int dummy);\n",
+		    odb_label,name);
+	    ODB_fprintf(cfp,
+		    "PUBLIC void *\n%s_Init_T_%s(void *T, ODB_Pool *Pool, int Is_new, int IO_method, int it, int dummy)\n{\n",
+		    odb_label,name);
+	    TAB(1); ODB_fprintf(cfp,"TABLE_%s *P = T;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int PoolNo = Pool->poolno;\n");
+	    TAB(1); ODB_fprintf(cfp,"ODB_Funcs *pf;\n");
+	    TAB(1); ODB_fprintf(cfp,"static ODB_CommonFuncs *pfcom = NULL; /* Shared between pools & threads */\n");
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(%s_Init_T_%s);\n",odb_label,name);
+	    }
+	    TAB(1); ODB_fprintf(cfp,"if (!P) ALLOC(P, 1);\n");
+	    TAB(1); ODB_fprintf(cfp,"PreInitTable(P, %d);\n",nsym);
+
+	    if (!dummy_table) {
+	      for (i=0; i<nsym; i++) {
+		char *s = ptable->sym[i]->name;
+		ODB_Type *ptype = ptable->type[i];
+		char *type = get_typename(ptype);
+		char *datatype = NULL;
+		int pmethod = get_PKmethod(type,NULL,&datatype,NULL);
+		
+		TAB(1); 
+		ODB_fprintf(cfp,"InitDS(%s, DATATYPE_%s, %s, %s, %d);\n",type, datatype, s, name, pmethod);
+		FREE(datatype);
+	      } /* for (i=0; i<nsym; i++) */
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"if (!pfcom) { /* Initialize once only */\n");
+	    TAB(2); ODB_fprintf(cfp,"CALLOC(pfcom,1);\n");
+
+	    TAB(2); ODB_fprintf(cfp,"{ static char s[] = \"@%s\"; pfcom->name = s; }\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->is_table = 1;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->is_considered = 0;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ntables = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ncols = %d;\n",nsym);
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->tableno = %d;\n",ptable->tableno);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->rank = %d;\n",ptable->rank);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->wt = %.6f;\n",ptable->wt);
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->tags = %s_Set_T_%s_TAG(&pfcom->ntag, &pfcom->nmem);\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->preptags = %s_Set_T_%s_PREPTAG(&pfcom->npreptag);\n",odb_label,name);
+	    
+	    TAB(2); ODB_fprintf(cfp,"pfcom->Info = NULL;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->create_index = 0;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->init = %s_Init_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->swapout = %s_Swapout_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->dim = %s_Dim_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->sortkeys = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->update_info = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->aggr_info = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->getindex = NULL; /* N/A */\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->putindex = NULL; /* N/A */\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->select = %s_Sel_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->remove = %s_Remove_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->peinfo = NULL; /* N/A */\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->cancel = NULL;\n");
+
+	    for (j=0; j<ntypes; j++) {
+	      char *pKey = Key[j];
+	      char *pKeyInfo = KeyInfo[j];
+
+	      if (!dummy_table && typemask[j]) {
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sget = %s_%sGet_T_%s; /* %s dbmgr */\n", 
+				pKey, odb_label, pKey, name, pKeyInfo);
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sput = %s_%sPut_T_%s; /* %s dbmgr */\n", 
+				pKey, odb_label, pKey, name, pKeyInfo);
+	      }
+	      else {
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sget = NULL; /* no %s dbmgr allowed */\n", 
+				pKey, pKeyInfo);
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sput = NULL; /* no %s dbmgr allowed */\n", 
+				pKey, pKeyInfo);
+	      }
+	    }
+	    
+	    TAB(2); ODB_fprintf(cfp,"pfcom->load = %s_Load_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->store = %s_Store_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->pack = %s_Pack_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->unpack = %s_Unpack_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->sql = %s_Sql_T_%s;\n",odb_label,name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ncols_aux = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->colaux = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->has_select_distinct = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->has_usddothash = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"} /* if (!pfcom) */\n");
+
+	    TAB(1); ODB_fprintf(cfp,"ALLOC(pf, 1);\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->it = it;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->data = P;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->Res = NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->tmp = NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->pool = Pool;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->common = pfcom;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->next = NULL;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"P->Funcs = pf;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Handle = P->Funcs->pool->handle;\n");
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(0);\n");
+	    }
+	    TAB(1); ODB_fprintf(cfp,"return P;\n");
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    ODB_fprintf(fphdr,"\n");
+	    ODB_fprintf(fphdr,"#endif /* defined(ODB_MAINCODE) */\n");
+	    ODB_fprintf(fphdr,"\n");
+
+	    ODB_fprintf(cfp,"/* *************** End of TABLE \"%s\" *************** */\n",name);
+
+	    if (cfp != fpdevnull) FCLOSE(cfp);
+	  } /* if (nsym > 0) */
+	} /* if (ptable) */
+
+	fptable = ODB_popFILE();
+      }
+      break;
+
+    case ODB_VIEW:
+      {
+	ODB_View *pview = pnode->argv[0];
+
+	ODB_pushFILE(cfp);
+
+	if (pview) {
+	  int nfrom_start = pview->nfrom_start; /* deferred implementation */
+	  int nfrom = pview->nfrom;
+
+	  if (nfrom >= 0) {
+	    int i, j;
+	    int ntypes_view = ntypes;
+	    int typemask[NTYPES];
+	    char **consider_tables = NULL;
+	    char *name = pview->view->name;
+	    ODB_Tree *pcond = pview->cond;
+	    int nselect = pview->nselect;
+	    int nselect_all = pview->nselect_all;
+	    int nwhere = pview->nwhere;
+	    int norderby = pview->norderby;
+	    int nuniqueby = pview->nuniqueby;
+	    int nall = nselect_all + nwhere;
+	    int ncols_aux = 0;
+	    int nselsym = pview->nselsym;
+	    int maxfrom = pview->maxfrom;
+	    int oneif = 0;
+	    int has_link = 0;
+	    int linkless = 0;
+	    Boolean *done = NULL;
+	    Boolean *orphan = NULL;
+	    FILE *fpview = NULL;
+	    char *dofunc = NULL;
+	    int pcond_USD_symbols = 0;
+	    int selsym_USD_symbols = 0;
+	    int count_USD_symbols = 0;
+	    ODB_AndList *andlist = pview->andlist;
+	    int andlen = pview->andlen;
+	    struct {
+	      int len;
+	      int i;
+	      int protected;
+	      int level_plus_one;
+	    } *subloop = NULL;
+	    int *close_bracket = NULL;
+	    char **inlined_len = NULL;
+	    int numsg = 0;
+	    char *typetag = NULL;
+	    char *nametag = NULL;
+	    int typetag_len = 0;
+	    int nametag_len = 0;
+	    int numands = 0;
+	    int nwhere_dupl = 0;
+	    ODB_Symbol *sym_maxcount = ODB_lookup(ODB_USDNAME, usd_maxcount, NULL);
+
+	    typemask[0] = 1;
+
+	    if (verbose) 
+	      fprintf(stderr,"genc: Processing VIEW='%s' ...\n",name);
+
+	    if (!pcond) {
+	      extern ODB_Tree *YACC_dummy_cond; /* from yacc.y */
+	      pcond = pview->cond = YACC_dummy_cond;
+	    }
+
+	    if (!pcond) {
+	      SETMSG1("*** Internal error: Unexpected empty WHERE-condition in view '%s'",
+		      name);
+	      YYerror(msg);
+	    }
+
+	    if (!sym_maxcount) {
+	      /* ODBTk's $__maxcount__ has not been assigned -> assign it with mdi = ABS(RMDI) */
+	      sym_maxcount = ODB_new_symbol(ODB_USDNAME, usd_maxcount);
+	      sym_maxcount->dval = mdi;
+	    }
+
+	    pcond_USD_symbols = assign_USD_symbols(NULL, pcond, 0, 4, NULL, name);
+
+	    CALLOC(tmpsym, nall);
+
+	    {
+	      char *p;
+	      int len;
+	      
+	      len = strlen(name) + strlen(odb_label) + 2;
+	      ALLOC(dofunc, len);
+	      snprintf(dofunc, len, "%s_%s", odb_label, name);
+
+	      len = strlen(dofunc) + 3;
+	      ALLOC(p, len);
+	      snprintf(p, len, "%s.c", dofunc);
+
+	      if (ABS(filtered_info) < 2) {
+		fpview = FOPEN(p, "w");
+	      }
+	      else {
+		fpview = NULL;
+	      }
+	      FREE(p);
+
+	      if (ABS(filtered_info) > 0) {
+		if (filtered_info < 0) {
+		  len = strlen(dofunc) + 6;
+		  ALLOC(p, len);
+		  snprintf(p, len, "%s.info", dofunc);
+		}
+		else {
+		  p = STRDUP("stdout");
+		}
+		fpinf = FOPEN(p, "w");
+		FPINF_MAGIC();
+		FPINF_KEYLINE(database, pview->db->dbname);
+		FPINF_KEYLINE(srcpath, pview->db->srcpath);
+		FPINF_KEYLINE(datapath, pview->db->datapath);
+		FPINF_KEYLINE(idxpath, pview->db->idxpath);
+		FPINF_KEYLINE(poolmask, pview->db->poolmask);
+		FPINF_KEYLINE(viewname, name);
+		FPINF_KEYLINE(has_select_distinct, pview->select_distinct ? "1" : "0");
+		FPINF_KEYLINE(has_count_star, pview->has_count_star ? "1" : "0");
+		FPINF_KEYLINE(has_aggrfuncs, pview->select_aggr_flag ? "1" : "0");
+		FPINF_KEYLINE(has_thin, pview->has_thin ? "1" : "0");
+		if (filtered_info < 0) ODB_fprintf(stdout,"%s\n",name);
+		FREE(p);
+	      }
+	      else {
+		fpinf = NULL;
+	      }
+
+	      ALLOC(flist, 1);
+	      flist->filename = STRDUP(dofunc);
+	      flist->create_so = 1;
+	      flist->next = NULL;
+	      if (!flist_start) {
+		flist_start = flist;
+	      }
+	      else {
+		flist_last->next = flist;
+	      }
+	      flist_last = flist;
+	    }
+
+	    cfp = fpview;
+
+	    ODB_fprintf(cfp,"#define IS_a_VIEW 1\n");
+
+	    ODB_fprintf(cfp,"/* Compilation options used :\n%s",ARGH);
+	    process_one_tables(cfp, "\n\t ","");
+	    ODB_fprintf(cfp,"\n\n*/\n\n");
+
+	    /* set_optlevel(cfp, 2); */
+	    set_optlevel(cfp, 0);
+	    ODB_fprintf(cfp,"#include \"%s.h\"\n",odb_label);
+	    NL(1);
+
+	    write_sql(cfp, pview, 1);
+	    NL(1);
+	
+	    write_sql_for_info();
+
+	    /* Echo ODB_CONSIDER_TABLES */
+	    ODB_fprintf(cfp,"\n#define ODB_CONSIDER_TABLES \"/");
+	    CALLOC(consider_tables, nfrom);
+	    for (i=0; i<nfrom; i++) {
+	      const char *s = pview->from[i]->table->name;
+	      ODB_fprintf(cfp,"%s/",s);
+	      consider_tables[i] = STRDUP(s);
+	    }
+	    ODB_fprintf(cfp,"%s\"\n", (nfrom > 0) ? "" : "/");
+	    NL(1);
+	    
+	    FPINF_KEYNUM(from, nfrom);
+	    for (i=0; i<nfrom; i++) {
+	      const char *s = pview->from[i]->table->name;
+	      double wt = pview->from[i]->wt;
+	      FPINF_NUMITEM_WT(i,s,wt);
+	    }
+	    FPINF_KEYEND(from);
+
+	    write_macros(cfp);
+	    NL(1);
+
+	    write_hollerith(cfp);
+	    NL(1);
+
+	    /* Count no. of (distinct) dollar-variables in SELECT-expression(s) */
+      
+	    selsym_USD_symbols = 0;
+	    if (pview->sel) {
+	      for (i=0; i<nselect; i++) {
+		if (pview->is_formula[i]) {
+		  ODB_Tree *expr = pview->sel[i]->expr;
+		  selsym_USD_symbols += assign_USD_symbols(NULL, expr, 0, 5, NULL, name);
+		}
+	      } /* for (i=0; i<nselect; i++) */
+	    }
+
+	    count_USD_symbols = write_setsymbols(cfp, "extern", 1);
+	    NL(1);
+
+	    /* Calculate the total number of auxiliary columns (ncols_aux) needed */
+
+	    ncols_aux = 0;
+	    if (pview->sel) {
+	      for (i=0; i<nselect; i++) {
+		if (pview->is_formula[i]) {
+		  uint flag = pview->sel[i]->aggr_flag;
+		  if (flag != ODB_AGGR_NONE) ncols_aux += pview->sel[i]->ncols_aux;
+		}
+	      } /* for (i=0; i<nselect; i++) */
+	    }
+	    pview->ncols_aux = ncols_aux;
+
+	    /* The special HASH-symbols to enable row number (#) access */
+	    ODB_fprintf(cfp,"#if !defined(K0_lo_var) && !defined(K0_lo_const)\n");
+	    ODB_fprintf(cfp,"#define K0_lo 0\n");
+	    ODB_fprintf(cfp,"#endif\n");
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      /* The meaning of the little advertised '#tblname' changed on 19/01/2004 by SS
+		 to denote absolute rowid of table '@tblname', foreach at pool;
+		 It used to denote relative rowid i.e. absolute - minus link_offset;
+		 If you had used '#tblname' before, you may now have to change it and
+		 calculate relativeness yourself by '#tblname - tblname.offset at parent + 1' */
+	      /* ODB_fprintf(cfp,"#define %s_ROW ((double)((K%d - K%d_lo) + 1))\n",s,i,i); */
+	      ODB_fprintf(cfp,"#define %s_ROW ((double)(K%d + 1))\n",s,i);
+	      if (pview->has_formulas) {
+		ODB_fprintf(cfp,"#define %s_ROWIDX ((double)(P->Index_%s[i] + 1))\n",s,s);
+	      }
+	    }
+	    NL(1);
+
+	    ALLOC(done, nall);
+	    ZEROIT(done, 0, nall);
+
+	    /* typedef for VIEW */
+
+	    ODB_fprintf(cfp,"/* *************** VIEW \"%s\" *************** */\n",name);
+	    ODB_fprintf(cfp,"\ntypedef struct {\n");
+	    TAB(1); ODB_fprintf(cfp,"int Handle;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PoolNo;\n");
+	    TAB(1); ODB_fprintf(cfp,"ODB_Funcs *Funcs;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Ncols;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Nrows;\n");
+	    TAB(1); ODB_fprintf(cfp,"int  USD_symbols;\n");
+	    TAB(1); ODB_fprintf(cfp,"int  Replicate_PE;\n");
+	    TAB(1); ODB_fprintf(cfp,"int  Npes;\n");
+	    TAB(1); ODB_fprintf(cfp,"int *NrowVec;\n");
+	    TAB(1); ODB_fprintf(cfp,"int *NrowOffset;\n");
+	    TAB(1); ODB_fprintf(cfp,"int  NSortKeys;\n");
+	    if (pview->norderby > 0) {
+	      TAB(1); ODB_fprintf(cfp,"int  SortKeys[%d];\n",pview->norderby);
+	    }
+	    else {
+	      TAB(1); ODB_fprintf(cfp,"int *SortKeys;\n");
+	    }
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      TAB(1); 
+	      if ((pview->active[i] & 0x1) == 0x1) {
+		ODB_fprintf(cfp,"ODBMAC_VIEW_TABLEDECL_WITH_INDEX(%s);\n",s);
+	      }
+	      else {
+		ODB_fprintf(cfp,"ODBMAC_VIEW_TABLEDECL_NO_INDEX(%s);\n",s);
+	      }
+	    }
+	    TAB(1); ODB_fprintf(cfp,"uint can_UPDATE[RNDUP_DIV(%d,MAXBITS)];\n",nselect+ncols_aux);
+	    if (pview->select_aggr_flag) {
+	      TAB(1); ODB_fprintf(cfp,"int aggr_func_flag[%d];\n",nselect+ncols_aux);
+	      TAB(1); ODB_fprintf(cfp,"int numaggr;\n");
+	      TAB(1); ODB_fprintf(cfp,"Boolean all_aggr;\n");
+	    }
+
+	    ODB_fprintf(cfp,"} VIEW_%s;\n",name);
+	    NL(1);
+
+	    /* Setup master-slave relationship of ALIGNed items -- if merge_table_indices */
+
+	    if (merge_table_indices) {
+	      for (i=0; i<nfrom; i++) {
+		/* Loop over "slaves" */
+		if ((pview->active[i] & 0x1) == 0x1) {
+		  char *slave = pview->from[i]->table->name;
+		  for (j=0; j<nfrom; j++) {
+		    /* Loop over ALL the "master" candidates : pick the first one */
+		    if ((pview->active[j] & 0x1) == 0x1) {
+		      char *master = pview->from[j]->table->name;
+		      if (is_master(master,slave)) {
+			pview->merged_with[i] = STRDUP(master); /* Yesh, index IS indeed 'i' !! */
+			break; /* First found; quit loop "for (j=0; j<i; j++)" */
+		      }
+		    } /* if ((pview->active[j] & 0x1) == 0x1) */
+		  } /* for (j=0; j<i; j++) */
+		} /* if ((pview->active[i] & 0x1) == 0x1) */
+	      } /* for (i=0; i<nfrom; i++) */
+	    } /* if (merge_table_indices) */
+
+	    /* Tags for VIEW */
+	    
+	    {
+	      /* Check # of duplicates in WHERE first */
+	      nwhere_dupl = 0;
+	      init_list(NULL);
+	      for (i=nselect_all; i<nselect_all+nwhere; i++) {
+		const char *p =  pview->tag[i] ? pview->tag[i] : pview->where[i-(nselect_all)]->name;
+		if (!in_list(p)) add_list(p); else nwhere_dupl++;
+	      }
+	      destroy_list();
+	    }
+
+	    ODB_fprintf(cfp,"PRIVATE int nV_%s_TAG = %d;\n",
+		    name,nselect+ncols_aux+nselsym+nwhere-nwhere_dupl+norderby+nuniqueby);
+	    ODB_fprintf(cfp,"PRIVATE int nV_%s_MEM = 0;\n",name);
+	    NL(1);
+
+	    nametag = STRDUP(ODB_tag_delim);
+	    nametag_len = 2;
+	    typetag = STRDUP(ODB_tag_delim);
+	    typetag_len = 2;
+
+	    ODB_fprintf(cfp,"PRIVATE const ODB_Tags V_%s_TAG[%d] = {\n",
+		    name,nselect+ncols_aux+nselsym+nwhere-nwhere_dupl+norderby+nuniqueby);
+
+	    /* Record the current ODB_maxcols() for use by ORDERBY ABS-sorting */
+	    if (fpinf) ODB_fprintf(fpinf, "\n/maxcols=%d\n", ODB_maxcols());
+
+	    TAB(1); ODB_fprintf(cfp,"/* === SELECT-symbols (count = %d) === */\n", nselect);
+	    FPINF_KEY(select); /* Don't know the total length */
+	    for (i=0; i<nselect; i++) {
+	      int flag = 0;
+	      const char *ptag = pview->tag[i];
+	      const char *poslen = pview->poslen[i];
+	      char *ptype = NULL;
+	      char *pvar = NULL;
+	      char *pmem = NULL;
+	      char *ptable = NULL;
+	      char *poffset = NULL;
+	      const ODB_Symbol *nicksym = (pview->sel && pview->sel[i]) ? pview->sel[i]->nicksym : NULL;
+	      char *nickname = HAS_NICKNAME(nicksym) ? nicksym->name : NULL;
+	      Boolean nickname_allocated = 0;
+	      Boolean is_usddothash = 0;
+
+	      if (pview->sel && pview->sel[i] && pview->sel[i]->formula) {
+		const char *f1 = pview->sel[i]->formula+1;
+		is_usddothash = IS_USDDOTHASH(f1);
+	      }
+
+	      if (nickname && !pview->is_formula[i]) {
+		/* Make sure we are not dealing with 
+		   linklen_t:LINKLEN(child_table)@parent_table or
+		   linkoffset_t:LINKOFFSET(child_table)@parent_table */
+		char *atag = STRDUP(ptag);
+		char *acolon = strchr(atag,':');
+		if (acolon) {
+		  char *alink = acolon + 1;
+		  char *aat = strchr(alink,'@');
+		  if (aat) {
+		    char *atype = atag;
+		    *acolon = '\0';
+		    if ((strequ(atype,LINKLENTYPE) && strnequ(alink,"LINKLEN(",8)) ||
+			(strequ(atype,LINKOFFSETTYPE) && strnequ(alink,"LINKOFFSET(",11))) {
+		      nickname = NULL;
+		    }
+		  }
+		}
+		FREE(atag);
+	      }
+
+	      if (nickname) {
+		char *pnick = STRDUP(nickname);
+		char *pat = strrchr(pnick,'@');
+		char *pcolon = strchr(pnick,':');
+		if ((pcolon && !pat) || (pcolon && pat && pcolon < pat)) {
+		  char *datatype = NULL;
+		  char *test_type = pnick;
+		  *pcolon++ = '\0';
+		  (void)get_PKmethod(test_type, NULL, &datatype, NULL);
+		  if (!strequ(datatype,"UNDEF")) {
+		    /* This is a known (pre-defined) datatype */
+		    ptype = STRDUP(test_type);
+		    nickname = STRDUP(pcolon);
+		    nickname_allocated = 1;
+		  }
+		  FREE(datatype);
+		}
+		FREE(pnick);
+	      }
+
+	      if (pview->is_formula[i]) {
+		if (!ptype) ptype = STRDUP("Formula");
+		ptable = STRDUP("Formula");
+	      }
+	      else {
+		(void) ODB_split(ptag, ptype ? NULL : &ptype, &pvar, &pmem, &ptable, &poffset);
+	      }
+
+	      if (nickname) {
+		int pnlen;
+		char *pnick = nickname_allocated ? nickname : STRDUP(nickname);
+		char *pat = strrchr(pnick,'@');
+		Boolean valid_chars = 1;
+		if (pat) {
+		  /* Check that all the following chars are valid chars for a table */
+		  const char *c = pat;
+		  valid_chars = (STRLEN(c) > 1) ? 1 : 0;
+		  while ( valid_chars && *++c ) {
+		    if (!IS_VARCHAR(c)) valid_chars = 0;
+		  }
+		}
+		if (pat && valid_chars) {
+		  *pat++ = '\0';
+		  pnlen = strlen(pnick) + 1 + strlen(pat) + 1;
+		}
+		else {
+		  pnlen = strlen(pnick) + 1 + strlen(ptable) + 1;
+		}
+		ALLOC(pvar,pnlen);
+		snprintf(pvar,pnlen,"%s@%s",pnick,(pat && valid_chars) ? pat : ptable);
+		FREE(pnick);
+	      }
+	      else if (pview->is_formula[i]) {
+		const char *pcolon = strchr(ptag,':');
+		if (pcolon) { ++pcolon; pvar = STRDUP(pcolon); }
+		else { pvar = STRDUP("<unknown>"); }
+	      }
+
+	      if (nickname || pview->is_formula[i]) {
+		nametag_len += strlen(pvar) + 1;
+		REALLOC(nametag, nametag_len);
+		strcat(nametag, pvar);
+		strcat(nametag,ODB_tag_delim);
+		if (pview->is_formula[i]) {
+		  flag = pview->sel[i]->aggr_flag ? 4 : 2;
+		  if (!pview->sel[i]->formula_out) {
+		    /* This seems to happen, where the query is table-less */
+		    ODB_Tree *expr = pview->sel[i]->expr;
+		    pview->sel[i]->formula_out = dump_s(NULL,expr,ddl_piped ? 2 : 0,NULL);
+		  }
+		  FPINF_NUMITEM(flag, pview->sel[i]->formula_out, NULL, NULL);
+		}
+		else {
+		  flag = 1;
+		}
+	      }
+	      else if (pmem) {
+		nametag_len += strlen(pvar) + 1 + strlen(pmem) + 1 + strlen(ptable) + 1;
+		REALLOC(nametag, nametag_len);
+		strcat(nametag,pvar);
+		strcat(nametag,".");
+		strcat(nametag,pmem);
+		strcat(nametag,"@");
+		strcat(nametag,ptable);
+		strcat(nametag,ODB_tag_delim);
+		flag = 1;
+	      }
+	      else {
+		nametag_len += strlen(pvar) + 1 + strlen(ptable) + 1;
+		REALLOC(nametag, nametag_len);
+		strcat(nametag,pvar);
+		strcat(nametag,"@");
+		strcat(nametag,ptable);
+		strcat(nametag,ODB_tag_delim);
+		flag = 1;
+	      }
+	      
+	      typetag_len += strlen(ptype) + 1;
+	      REALLOC(typetag, typetag_len);
+	      strcat(typetag, ptype);
+	      strcat(typetag,ODB_tag_delim);
+
+	      TAB(1); ODB_fprintf(cfp,"{ \"%s\", %d, 0, NULL } ,\n", ptag, 
+				  is_usddothash ? 1 : 0);
+	      if (flag == 1) FPINF_NUMITEM(flag, ptag, poslen, poffset);
+	      FREE(pvar);
+	      FREE(pmem);
+	      FREE(ptable);
+	      FREE(ptype);
+	      FREE(poffset);
+	    } /* for (i=0; i<nselect; i++) */
+
+	    {
+	      const int flag = 8; /* Auxiliary aggregate column */
+	      TAB(1); ODB_fprintf(cfp,"/* === Symbols for auxiliary columns (count = %d) === */\n",ncols_aux);
+	      for (i=0; i<ncols_aux; i++) {
+		TAB(1);
+		ODB_fprintf(cfp,"{ \"Formula:ColAux_%d at Formula\", 0, 0, NULL },\n",i+1);
+		FPINF_FMT2("%d %d\t0 0 0\n", flag, i+1); /* Output an auxiliary column# >= 1 */
+	      }
+	    }
+
+	    { 
+	      const int flag = 0; /* Possibly not a pure column, but part of a formula or formulas */
+	      int k = 0;
+	      TAB(1); ODB_fprintf(cfp,"/* === Symbols in SELECT-expressions (count = %d) === */\n",nselsym);
+	      for (i=nselect_all+nwhere+norderby; i<nselect_all+nwhere+norderby+nselsym; i++, k++) {
+		TAB(1); ODB_fprintf(cfp,"{ \"%s\", 0, 0, NULL },\n",
+				    pview->tag[i] ? pview->tag[i] : pview->selsym[k]->name);
+		FPINF_NUMITEM(flag, 
+			      pview->tag[i] ? pview->tag[i] : pview->selsym[k]->name, 
+			      pview->poslen[i], pview->offset[i]);
+	      }
+	    }
+
+	    FPINF_KEYEND(select);
+
+	    if (fpinf) {
+	      FPINF_KEY(nickname); /* We don't know how many symbols have nickname; maybe none */
+	      for (i=0; i<nselect; i++) {
+		const ODB_Symbol *nicksym = (pview->sel && pview->sel[i]) ? pview->sel[i]->nicksym : NULL;
+		const char *nickname = HAS_NICKNAME(nicksym) ? nicksym->name : NULL;
+		if (nickname) {
+		  FPINF_NICKNAME(i, nickname);
+		}
+	      }
+	      FPINF_KEYEND(nickname);
+	    } /* if (fpinf) */
+
+	    {
+	      TAB(1); ODB_fprintf(cfp,"/* === WHERE-symbols (count = %d) === */\n",nwhere-nwhere_dupl);
+	      init_list(NULL);
+	      FPINF_KEYNUM(wheresym,nwhere-nwhere_dupl);
+	      for (i=nselect_all; i<nselect_all+nwhere; i++) {
+		const char *p =  pview->tag[i] ? pview->tag[i] : pview->where[i-(nselect_all)]->name;
+		if (!in_list(p)) {
+		  add_list(p);
+		  TAB(1); ODB_fprintf(cfp,"{ \"%s\", 0, 0, NULL },\n", p);
+		  if (pview->tag[i]) {
+		    FPINF_NUMITEM(1, pview->tag[i], pview->poslen[i], pview->offset[i]);
+		  }
+		  else {
+		    FPINF_NUMITEM(0, pview->where[i-(nselect_all)]->name, NULL, NULL); 
+		  }
+		} /* if (!in_list(p)) */
+	      }
+	      destroy_list();
+	      FPINF_KEYEND(wheresym);
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"/* === ORDERBY-symbols (count = %d) === */\n",norderby);
+	    FPINF_KEYNUM(orderby,norderby);
+	    for (i=nselect_all+nwhere; i<nselect_all+nwhere+norderby; i++) {
+	      TAB(1); ODB_fprintf(cfp,"{ \"%s\", 0, %d, NULL },\n",
+				  pview->tag[i],
+				  pview->mkeys[i-(nselect_all+nwhere)]);
+	      FPINF_NUMITEM(pview->mkeys[i-(nselect_all+nwhere)], 
+			    pview->tag[i], pview->poslen[i], pview->offset[i]);
+	    }
+	    FPINF_KEYEND(orderby);
+
+	    TAB(1); ODB_fprintf(cfp,"/* === UNIQUEBY-symbols (count = %d) === */\n",nuniqueby);
+	    FPINF_KEYNUM(uniqueby,nuniqueby);
+	    for (i=0; i<nuniqueby; i++) {
+	      int k = (nselect_all + nwhere - nuniqueby) + i;
+	      const int flag = 1;
+	      char *ptag = pview->tag[k];
+	      char *poslen = pview->poslen[k];
+	      char *ptype = NULL;
+	      char *pvar = NULL;
+	      char *pmem = NULL;
+	      char *ptable = NULL;
+
+	      (void) ODB_split(ptag, &ptype, &pvar, &pmem, &ptable, NULL);
+
+	      TAB(1); 
+	      if (pmem) {
+		ODB_fprintf(cfp,"{ \"%s:%s.%s@%s\", 0, 0, NULL } ,\n",
+			    ptype, pvar, pmem, ptable);
+		FPINF_NUMITEM_TYPE_VAR_MEM_TABLE(flag, ptype, pvar, pmem, ptable, poslen);
+	      }
+	      else {
+		ODB_fprintf(cfp,"{ \"%s:%s@%s\", 0, 0, NULL } ,\n",
+			    ptype, pvar, ptable);
+		FPINF_NUMITEM_TYPE_VAR_MEM_TABLE(flag, ptype, pvar, NULL, ptable, poslen);
+	      }
+	      FREE(ptype);
+	      FREE(pvar);
+	      FREE(pmem);
+	      FREE(ptable);
+	    }
+	    FPINF_KEYEND(uniqueby);
+	    ODB_fprintf(cfp,"};\n");
+	    NL(1);
+
+	    if (fpinf && pcond) { /* WHERE-cond to info-file */
+	      int lineno = ODB_lineno;
+	      FILE *save_cfp = cfp;
+
+	      cfp = fpinf;
+	      info_dump = 1;
+
+	      FPINF_KEYNUM(wherecond,1);
+	      TAB(1);
+	      dump_c(cfp, lineno, pcond);
+	      NL(1);
+	      FPINF_KEYEND(wherecond);
+
+	      if (andlist && nfrom > 0) {
+		/* Don't generate this for table-less queries */
+		int ja;
+		info_dump = 2;
+		for (ja=0; ja<andlen; ja++) {
+		  FPINF_KEYNUM(wherecond_and,andlist[ja].maxfrom);
+		  TAB(1);
+		  dump_c(cfp, lineno, andlist[ja].expr);
+		  NL(1);
+		  FPINF_KEYEND(wherecond_and);
+		}
+	      }
+
+	      info_dump = 0;
+	      cfp = save_cfp;
+	      ODB_lineno = lineno;
+	    } /* if (fpinf && pcond) */
+
+	    ODB_fprintf(cfp,"PRIVATE int nV_%s_PREPTAG = 3;\n",name);
+	    ODB_fprintf(cfp,"PRIVATE const ODB_PrepTags V_%s_PREPTAG[3] = {\n",name);
+	    TAB(1); ODB_fprintf(cfp,"/* Prepared tags for faster codb_getnames() */\n");
+	    TAB(1); ODB_fprintf(cfp,"{ (preptag_name | preptag_extname), %d,",strlen(nametag));
+	    TagStrip(cfp,2,nametag," },\n");
+	    TAB(1); ODB_fprintf(cfp,"{ (preptag_type | preptag_exttype), %d,",strlen(typetag));
+	    TagStrip(cfp,2,typetag," },\n");
+	    { /* A more robust list of tables that belong to the view */
+	      char *tbltag = NULL;
+	      int len = 2;
+	      tbltag = STRDUP(ODB_tag_delim);
+	      for (i=0; i<nfrom; i++) {
+		len += strlen(consider_tables[i]) + 2;
+		REALLOC(tbltag, len);
+		strcat(tbltag,"@");
+		strcat(tbltag,consider_tables[i]);
+		strcat(tbltag,ODB_tag_delim);
+		FREE(consider_tables[i]);
+	      }
+	      FREE(consider_tables);
+	      TAB(1); ODB_fprintf(cfp,"{  preptag_tblname, %d,", strlen(tbltag));
+	      TagStrip(cfp,2,tbltag," },\n");
+	      FREE(tbltag);
+	    }
+	    ODB_fprintf(cfp,"};\n");
+	    NL(1);
+
+	    FREE(nametag);
+	    FREE(typetag);
+
+	    /* CANCEL function for VIEW */
+	    
+	    ODB_fprintf(cfp,"PRIVATE void\nCcl_V_%s(void *T)\n{\n",name);
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_CCL_V_PRE(%s);\n",name);
+
+	    for (i=0; i<nfrom; i++) {
+	      if ((pview->active[i] & 0x1) == 0x1) { 
+		char *s = pview->from[i]->table->name;
+		TAB(1); ODB_fprintf(cfp,"FREEINDEX(%s);\n",s); 
+	      }
+	    }
+
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    /* SELECT function */
+
+	    /* SELECT (Pre) : Gather the size of the set */
+
+	    ODB_fprintf(cfp,"PRIVATE int\nPrS_V_%s(FILE *do_trace,\n", name);
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P, int it, ODB_PE_Info *PEinfo",name);
+
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      ODB_fprintf(cfp,"\n");
+	      TAB(1);
+	      ODB_fprintf(cfp,"/* TABLE '%s' */ , int N%d, unsigned int BmapIdx%d[]",
+			  s,i,i);
+	    }
+
+	    init_list(NULL);
+	    ZEROIT(done, 0, nall);
+
+	    for (i=nselect_all; i<nall; i++) {
+	      char *call_arg = pview->call_arg[i];
+	      char *pvar;
+	      char *ptype;
+	      char *p;
+	      int plen;
+
+	      if (!call_arg) continue;
+
+	      (void) ODB_split(call_arg, &ptype, &pvar, NULL, NULL, NULL);
+	      
+	      plen = strlen(ptype) + strlen(pvar) + 10;
+	      ALLOC(p, plen);
+	      snprintf(p, plen, "%s %s[]", ptype, pvar);
+
+	      if (!in_list(p)) {
+		add_list(p);
+		ODB_fprintf(cfp,",\n");
+		TAB(1); ODB_fprintf(cfp,"const %s",p);
+		done[i] = 1;
+	      }
+
+	      FREE(p);
+	      FREE(pvar);
+	      FREE(ptype);
+	    }
+
+	    destroy_list();
+
+	    ODB_fprintf(cfp,")\n{\n",name);
+
+	    (void) assign_USD_symbols(NULL, pcond, 0, 0, NULL, name); /* Reset flags */
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 1, 1, NULL, name);
+	    }
+
+	    TAB(1); 
+	    ODB_fprintf(cfp,
+			"double *Addr = (PEinfo && P->USD_symbols > 0) ? PEinfo->addr : NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PE, PEstart = 1;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PEend = PEinfo ? PEinfo->npes : PEstart;\n");
+	    TAB(1); ODB_fprintf(cfp,"int NPEs = PEend - PEstart + 1;\n");
+
+	    if (nfrom > 0) {
+	      TAB(1); ODB_fprintf(cfp,"int K0;\n");
+	      ODB_fprintf(cfp,"#if defined(K0_lo_var)\n");
+	      TAB(1); ODB_fprintf(cfp,"int K0_lo =  0;\n");
+	      ODB_fprintf(cfp,"#elif defined(K0_lo_const)\n");
+	      TAB(1); ODB_fprintf(cfp,"const int K0_lo =  0;\n");
+	      ODB_fprintf(cfp,"#endif\n");
+	      TAB(1); ODB_fprintf(cfp,"int K0_hi = N0;\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"int Count = 0;\n");
+
+	    FPINF_KEY(prefetch);
+	    PREFETCH_CODE(1,PRE,fpinf); /* Prefetch possible OFFSETs & LENGTHs */
+	    FPINF_KEYEND(prefetch);
+	    
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(PrS_V_%s);\n", name);
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_PEINFO_SETUP();\n");
+
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 1, 2, NULL, name);
+	    }
+
+#ifdef REMOVE_COMPLAINTS
+	    TAB(1); ODB_fprintf(cfp,"NPEs=NPEs;   /* Removes some compiler complaints */\n");
+#endif
+	    TAB(1); ODB_fprintf(cfp,"for (PE=PEstart; PE<=PEend; PE++) {\n");
+	    TAB(2); ODB_fprintf(cfp,"int tmpcount = 0;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"if (Addr) {\n");
+	    TAB(3); ODB_fprintf(cfp,"boolean Addr_trigger = 0;\n");
+	    TAB(3); ODB_fprintf(cfp,"*Addr = PE;\n");
+	    (void) assign_USD_symbols(NULL, pcond, 0, 0, NULL, name); /* Reset flags */
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 3, 2, "PEinfo->varname", name);
+	    }
+	    TAB(3); ODB_fprintf(cfp,"if (!Addr_trigger) Addr = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"}\n");
+
+	    TAB(2); ODB_fprintf(cfp,"ODBMAC_PEINFO_SKIP();\n");
+
+	    ZEROIT(done, 0, nall);
+
+	    CALLOC(subloop, nfrom);
+	    CALLOC(close_bracket, nfrom);
+	    CALLOC(inlined_len, nfrom);
+	    CALLOC(orphan, nfrom);
+	    
+	    oneif = 0;
+	    has_link = 0;
+	    linkless = 0;
+
+	    FPINF_KEYNUM(links,nfrom);
+	    for (i=0; i<nfrom; i++) {
+	      numands = 0;
+	      
+	      if (i < nfrom - 1 || (i == nfrom - 1 && maxfrom == i)) {
+		TAB(1+i+1+oneif); 
+		if (subloop[i].len == 1) { /* The ONE-looper via '-1' */
+		  int im1 = subloop[i].i;
+		  ODB_fprintf(cfp,
+			      "K%d = K%d_lo; { "
+			      "/* TABLE '%s' (due to ONELOOPER with '%s') : weight = %.6f */\n",
+			      i,i,
+			      pview->from[i]->table->name,
+			      pview->from[im1]->table->name,
+			      pview->from[i]->wt);
+		  FPINF_LINK(i,pview->from[i]->table->name,im1,
+			     pview->from[im1]->table->name,"1",
+			     im1, pview->from[im1]->table->name);
+		}
+		else if (subloop[i].len == 2) { /* ALIGN-table via '-A' */
+		  int im1 = subloop[i].i;
+		  if (orphan[i]) {
+		    ODB_fprintf(cfp,
+				"K%d = K%d; { "
+				"/* Orphan TABLE '%s' (due to ALIGN with '%s') : weight = %.6f */\n",
+				i,im1,
+				pview->from[i]->table->name,
+				pview->from[im1]->table->name,
+				pview->from[i]->wt);
+		    FPINF_LINK(i,pview->from[i]->table->name,im1,
+			       pview->from[im1]->table->name,"=",
+			       -1, "0");
+		  }
+		  else {
+		    int offset_parent_id = subloop[i].level_plus_one - 1;
+		    const char *offset_parent_name = (offset_parent_id >= 0) ?
+		      pview->from[offset_parent_id]->table->name : "0";
+		    ODB_fprintf(cfp,
+				"K%d = K%d_lo + (K%d - K%d_lo); { "
+				"/* TABLE '%s' (due to ALIGN with '%s') : weight = %.6f */\n",
+				i,i,im1,im1,
+				pview->from[i]->table->name,
+				pview->from[im1]->table->name,
+				pview->from[i]->wt);
+		    FPINF_LINK(i,pview->from[i]->table->name,im1,
+			       pview->from[im1]->table->name,"A",
+			       offset_parent_id, offset_parent_name);
+		  }
+		}
+		else {
+		  int offset_parent_id = subloop[i].level_plus_one - 1;
+		  const char *offset_parent_name = (offset_parent_id >= 0) ?
+		    pview->from[offset_parent_id]->table->name : "0";
+		  int im1 = (i == 0) ? -1 : subloop[i].i;
+		  ODB_fprintf(cfp,
+			      "for (K%d=K%d_lo; K%d<K%d_hi; K%d++) { "
+			      "/* TABLE '%s' : weight = %.6f */\n",
+			      i,i,i,i,i,pview->from[i]->table->name,pview->from[i]->wt);
+		  if (im1 >= 0) {
+		    const char *ckind = NULL;
+		    if (subloop[i].len == 1) ckind = "1";
+		    else if (subloop[i].len == 2) ckind = orphan[i] ? "=" : "A";
+		    else ckind = "N";
+		    FPINF_LINK(i,pview->from[i]->table->name,im1,
+			       pview->from[im1]->table->name,ckind,
+			       offset_parent_id, offset_parent_name);
+		  }
+		  else {
+		    FPINF_LINK(i,pview->from[i]->table->name,im1,
+			       "0","N",
+			       offset_parent_id, offset_parent_name);
+		  }
+		}
+	      }
+	      else if (i == nfrom - 1 && nfrom > 1 && !has_link) {
+		TAB(1+i+1+oneif); 
+		ODB_fprintf(cfp,
+			    "for (K%d=K%d_lo; K%d<K%d_hi; K%d++) { "
+			    "/* Linkless TABLE '%s' : weight = %.6f */\n",
+			    i,i,i,i,i,pview->from[i]->table->name,pview->from[i]->wt);
+		FPINF_LINK(i,pview->from[i]->table->name,-1,
+			   "0","N",
+			   -1, "0");
+		linkless = 1;
+	      }
+	      else {
+		int offset_parent_id = subloop[i].level_plus_one - 1;
+		const char *offset_parent_name = (offset_parent_id >= 0) ?
+		  pview->from[offset_parent_id]->table->name : "0";
+		int im1 = (i == 0) ? -1 : subloop[i].i;
+		if (im1 >= 0) {
+		  const char *ckind = NULL;
+		  if (subloop[i].len == 1) ckind = "1";
+		  else if (subloop[i].len == 2) ckind = orphan[i] ? "=" : "A";
+		  else ckind = "N";
+		  FPINF_LINK(i,pview->from[i]->table->name,im1,
+			     pview->from[im1]->table->name,ckind,
+			     offset_parent_id, offset_parent_name);
+		}
+		else {
+		  FPINF_LINK(i,pview->from[i]->table->name,im1,
+			     "0","N",
+			     offset_parent_id, offset_parent_name);
+		}
+	      }
+	      subloop[i].protected = 1;
+	      
+	      if (i < nfrom - 1) {
+		Boolean link_found = 0;
+		char *snext = pview->from[i+1]->table->name;
+		char *sthis = NULL;
+		int level = -1;
+		
+		for (j=i; j>=0; j--) {
+		  ODB_Table *t = pview->from[j];
+		  if (t->link) {
+		    int l;
+		    for (l=0; l<t->nlink; l++) {
+		      char *s = t->link[l]->table->name;
+		      link_found = strequ(s, snext);
+		      if (link_found) {
+			sthis = pview->from[j]->table->name;
+			level = j;
+			goto PRE_break;
+		      }
+		    } /* for (l=0; l<t->nlink; l++) */
+		  } /* if (t->link) */
+		} /* for (j=i; j>=0; j--) */
+		
+	      PRE_break:
+		has_link = 0;
+		
+		if (!link_found) {
+		  int ii = i+1;
+
+		  /* Search for ALIGNs only */
+		  sthis = pview->from[i]->table->name;
+		  for (j=i+1; j<nfrom; j++) { /* Forward */
+		    if (!subloop[j].protected) {
+		      char *ssnext = pview->from[j]->table->name;
+		      int align = onegrep(sthis, ssnext,__LINE__);
+		      if (align == 2) {
+			subloop[j].len = align;
+			subloop[j].i = i;
+			has_link = 1;
+			snext = ssnext;
+			ii = j;
+			break;
+		      }
+		    } /* if (!subloop[j].protected) */
+		  } /* for (j=i+1; j<nfrom; j++) */
+
+		  if (!has_link) {
+		    /* Do "earlier" tables contain any ALIGN-ments ? */
+		    for (j=i-1; j>=0; j--) { /* Backward */
+		      if (!subloop[j].protected) {
+			char *ssnext = pview->from[j]->table->name;
+			int align = onegrep(sthis, ssnext,__LINE__);
+			if (align == 2) {
+			  subloop[j].len = align;
+			  subloop[j].i = i;
+			  has_link = 1;
+			  snext = ssnext;
+			  ii = j;
+			  break;
+			}
+		      } /* if (!subloop[j].protected) */
+		    } /* for (j=i-1; j>=0; j--) */
+		  }
+
+		  ii = i + 1; /* Reset back to i + 1 */
+		  orphan[ii] = 1;
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_lo = 0;\n",ii);
+		  /* TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_len = 1;\n",ii); */
+		  inlined_len[ii] = STRDUP("1");
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_hi = N%d;\n",ii,ii);
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d;\n",ii);
+		}
+		else {
+		  int ii = i+1;
+		  int test = onegrep(sthis, snext,__LINE__);
+		  has_link = 1; /* some sort of LINK found anyway */
+		  if (test == 0) {
+		    /* Search for ALIGNs only */
+		    sthis = pview->from[i]->table->name;
+		    for (j=i+1; j<nfrom; j++) { /* Forward */
+		      if (!subloop[j].protected) {
+		        char *ssnext = pview->from[j]->table->name;
+			int align = onegrep(sthis, ssnext,__LINE__);
+			if (align == 2) {
+			  subloop[j].len = align;
+			  subloop[j].i = i;
+			  /* snext = ssnext; */
+			  ii = j;
+			  break;
+			}
+		      } /* if (!subloop[j].protected) */
+		    } /* for (j=i+1; j<nfrom; j++) */
+		  }
+		  else if (!subloop[ii].protected) {
+		    subloop[ii].len = test;
+		    subloop[ii].i = level;
+		  } /* if (test == 0) else ... */
+		  ii = i + 1; /* Reset back to i + 1 */
+		  
+		  /*
+		    TAB(1+i+2+oneif); 
+		    ODB_fprintf(cfp,"int K%d_len = P%s_len[K%d];\n",ii,snext,level);
+		  */
+		  
+		  ALLOC(inlined_len[ii],strlen(snext) + 30);
+		  sprintf(inlined_len[ii],"P%s_len[K%d]",snext,level);
+		  
+		  if (pview->safeGuard) {
+		    TAB(1+i+2+oneif);
+		    ODB_fprintf(cfp,"if (%s > 0) { /* safeGuard#%d */\n",inlined_len[ii],++numsg);
+		    close_bracket[i] = 1+i+2+oneif;
+		  }
+		  
+		  TAB(1+i+2+oneif);
+		  ODB_fprintf(cfp,"int K%d_lo = P%s_off[K%d];\n",ii,snext,level);
+		  subloop[ii].level_plus_one = level + 1;
+		  
+		  if (subloop[ii].len == 0) {
+		    if (!subloop[ii].protected) {
+		      subloop[ii].i = level;
+		      subloop[ii].protected = 1;
+		    }
+		    TAB(1+i+2+oneif); 
+		    ODB_fprintf(cfp,"int K%d_hi = K%d_lo + %s;\n",
+				ii,ii,inlined_len[ii]);
+		  }
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d;\n",ii);
+		}
+	      } /* if (i < nfrom - 1) */
+	      
+	      CONDCODE(cfp,numands);
+	    } /*  for (i=0; i<nfrom; i++) */
+
+	    if (nfrom > 0) {
+	      i = nfrom-1;
+	      if (numands == 0 && subloop[i].len == 0) {
+		TAB(1+nfrom+oneif); 
+		ODB_fprintf(cfp,"tmpcount += %s; /* TABLE '%s' : weight = %.6f */\n",
+			    inlined_len[i],
+			    pview->from[i]->table->name,pview->from[i]->wt);
+	      }
+	      else {
+		TAB(1+nfrom+2+oneif); 
+		ODB_fprintf(cfp,"tmpcount++; /* TABLE '%s' : weight = %.6f */\n",
+			    pview->from[i]->table->name,pview->from[i]->wt);
+	      }
+	      if (linkless && nfrom > 1 && !has_link) { /* i is now nfrom-1 */
+		TAB(1+i+1+oneif); 
+		ODB_fprintf(cfp,"} /* Linkless TABLE '%s' */\n",pview->from[i]->table->name);
+		linkless = 0;
+	      }
+	    }
+	    else {
+	      i = 0;
+	      TAB(1+i+1); ODB_fprintf(cfp,"{ /* FROM-less WHERE statement (if any) */\n");
+	      CONDCODE(cfp,numands);
+	      TAB(1+i+3); ODB_fprintf(cfp,"tmpcount++;\n");
+	      TAB(1+i+2); ODB_fprintf(cfp,"} /* if-block end */\n"); \
+	      TAB(1+i+1); ODB_fprintf(cfp,"}\n");
+	    }
+	    
+	    for (i=nfrom-1; i>=0; i--) {
+	      if (pcond && (i == maxfrom)) {
+		oneif--;
+		TAB(1+i+2);
+		ODB_fprintf(cfp,"} /* if-block end */\n");
+	      }
+	      
+	      if (pview->safeGuard && close_bracket[i]) {
+		int ii = i + 1; /* Reset back to i + 1 */
+		int tabs = close_bracket[i];
+		TAB(tabs); 
+		ODB_fprintf(cfp,"} /* end safeGuard#%d : if (%s > 0) ... */\n",numsg--,inlined_len[ii]);
+		close_bracket[i] = 0;
+	      }
+	      
+	      if (i < nfrom - 1 || (numands > 0 || numands == -1)) {
+		TAB(1+i+1+oneif);
+		ODB_fprintf(cfp,"} /* TABLE '%s' */\n", pview->from[i]->table->name);
+	      }
+	    } /* for (i=nfrom-1; i>=0; i--) */
+	  
+	    TAB(2); ODB_fprintf(cfp,"ODBMAC_PEINFO_UPDATE_COUNTS();\n");
+	    TAB(2); ODB_fprintf(cfp,"Count += tmpcount;\n");
+	    TAB(1); ODB_fprintf(cfp,"} /* for (PE=PEstart; PE<=PEend; PE++) */\n");
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_PEINFO_COPY();\n");
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(Count);\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"return Count;\n}\n");
+	    NL(1);
+
+	    /* SELECT (post) : Fill indices */
+
+	    free_tmpsym(0);
+	    
+	    ODB_fprintf(cfp,"PRIVATE int\nPoS_V_%s(FILE *do_trace,\n", name);
+	    TAB(1); ODB_fprintf(cfp,"const VIEW_%s *P, int it, ODB_PE_Info *PEinfo",name);
+
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      ODB_fprintf(cfp,"\n");
+	      TAB(1); 
+	      ODB_fprintf(cfp,"/* TABLE '%s' */ , int N%d, const unsigned int BmapIdx%d[]",
+			  s,i,i);
+	      if ((pview->active[i] & 0x1) == 0x1) {
+		ODB_fprintf(cfp,", int Index_%s[]", s);
+	      }
+	    }
+
+	    init_list(NULL);
+	    ZEROIT(done, 0, nall);
+
+	    for (i=nselect_all; i<nall; i++) {
+	      char *call_arg = pview->call_arg[i];
+	      char *pvar;
+	      char *ptype;
+	      char *p;
+	      int plen;
+
+	      if (!call_arg) continue;
+
+	      (void) ODB_split(call_arg, &ptype, &pvar, NULL, NULL, NULL);
+	      
+	      plen = strlen(ptype) + strlen(pvar) + 10;
+	      ALLOC(p, plen);
+	      sprintf(p, "%s %s[]", ptype, pvar);
+
+	      if (!in_list(p)) {
+		add_list(p);
+		ODB_fprintf(cfp,",\n");
+		TAB(1); ODB_fprintf(cfp,"const %s",p);
+		done[i] = 1;
+	      }
+
+	      FREE(p);
+	      FREE(pvar);
+	      FREE(ptype);
+	    }
+
+	    destroy_list();
+
+	    ODB_fprintf(cfp,")\n{\n",name);
+
+	    (void) assign_USD_symbols(NULL, pcond, 0, 0, NULL, name); /* Reset flags */
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 1, 1, NULL, name);
+	    }
+	    TAB(1); 
+	    ODB_fprintf(cfp,
+		    "double *Addr = (PEinfo && P->USD_symbols > 0) ? PEinfo->addr : NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PE, PEstart = 1;\n");
+	    TAB(1); ODB_fprintf(cfp,"int PEend = PEinfo ? PEinfo->npes : PEstart;\n");
+	    TAB(1); ODB_fprintf(cfp,"int NPEs = PEend - PEstart + 1;\n");
+
+	    if (nfrom > 0) {
+	      TAB(1); ODB_fprintf(cfp,"int K0;\n");
+	      ODB_fprintf(cfp,"#if defined(K0_lo_var)\n");
+	      TAB(1); ODB_fprintf(cfp,"int K0_lo = 0;\n");
+	      ODB_fprintf(cfp,"#elif defined(K0_lo_const)\n");
+	      TAB(1); ODB_fprintf(cfp,"const int K0_lo = 0;\n");
+	      ODB_fprintf(cfp,"#endif\n");
+	      TAB(1); ODB_fprintf(cfp,"int K0_hi = N0;\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"int Count = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int tmpcount = 0;\n");
+	    PREFETCH_CODE(1,POST,NULL); /* Prefetch possible OFFSETs & LENGTHs */
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(PoS_V_%s);\n", name);
+	    }
+
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 1, 2, NULL, name);
+	    }
+
+#ifdef REMOVE_COMPLAINTS
+	    TAB(1); ODB_fprintf(cfp,"Count=Count; /* Removes some compiler complaints */\n");
+	    TAB(1); ODB_fprintf(cfp,"NPEs=NPEs;   /* Removes some compiler complaints */\n");
+#endif
+	    TAB(1); ODB_fprintf(cfp,"for (PE=PEstart; PE<=PEend; PE++) {\n");
+	    TAB(2); ODB_fprintf(cfp,"if (Addr) {\n");
+	    TAB(3); ODB_fprintf(cfp,"boolean Addr_trigger = 0;\n");
+	    TAB(3); ODB_fprintf(cfp,"*Addr = PE;\n");
+	    (void) assign_USD_symbols(NULL, pcond, 0, 0, NULL, name); /* Reset flags */
+	    if (pcond_USD_symbols > 0) {
+	      (void) assign_USD_symbols(cfp, pcond, 3, 2, "PEinfo->varname", name);
+	    }
+	    TAB(3); ODB_fprintf(cfp,"if (!Addr_trigger) Addr = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"}\n");
+	    TAB(2); ODB_fprintf(cfp,"ODBMAC_PEINFO_BREAKLOOP();\n");
+
+	    ZEROIT(done, 0, nall);
+
+	    oneif = 0;
+
+	    for (i=0; i<nfrom; i++) {
+	      numands = 0;
+
+	      /* if (i < nfrom - 1 || (i == nfrom - 1 && maxfrom == i)) */ {
+		TAB(1+i+1+oneif); 
+		if (i > 0 && subloop[i].len == 1) { /* The ONE-looper via '-1' */
+		  int im1 = subloop[i].i;
+		  ODB_fprintf(cfp,
+			      "K%d = K%d_lo; { "
+			      "/* TABLE '%s' (due to ONELOOPER with '%s') : weight = %.6f */\n",
+			      i,i,
+			      pview->from[i]->table->name,
+			      pview->from[im1]->table->name,
+			      pview->from[i]->wt);
+		}
+		else if (i > 0 && subloop[i].len == 2) { /* ALIGN-table via '-A' */
+		  int im1 = subloop[i].i;
+		  if (orphan[i]) {
+		    ODB_fprintf(cfp,
+				"K%d = K%d; { "
+				"/* Orphan TABLE '%s' (due to ALIGN with '%s') : weight = %.6f */\n",
+				i,im1,
+				pview->from[i]->table->name,
+				pview->from[im1]->table->name,
+				pview->from[i]->wt);
+		  }
+		  else {
+		    ODB_fprintf(cfp,
+				"K%d = K%d_lo + (K%d - K%d_lo); { "
+				"/* TABLE '%s' (due to ALIGN with '%s') : weight = %.6f */\n",
+				i,i,im1,im1,
+				pview->from[i]->table->name,
+				pview->from[im1]->table->name,
+				pview->from[i]->wt);
+		  }
+		}
+		else {
+		  ODB_fprintf(cfp,
+			      "for (K%d=K%d_lo; K%d<K%d_hi; K%d++) { "
+			      "/* TABLE '%s' : weight = %.6f */\n",
+			      i,i,i,i,i,pview->from[i]->table->name,pview->from[i]->wt);
+		}
+	      }
+
+	      if (i < nfrom - 1) {
+		Boolean link_found = 0;
+		char *snext = pview->from[i+1]->table->name;
+		/* char *sthis = NULL; */
+		int level = -1;
+		
+		for (j=i; j>=0; j--) {
+		  ODB_Table *t = pview->from[j];
+		  if (t->link) {
+		    int l;
+		    for (l=0; l<t->nlink; l++) {
+		      char *s = t->link[l]->table->name;
+		      link_found = strequ(s, snext);
+		      if (link_found) {
+			/* sthis = pview->from[j]->table->name; */
+			level = j;
+			goto POST_break;
+		      }
+		    } /* for (l=0; l<t->nlink; l++) */
+		  } /* if (t->link) */
+		} /* for (j=i; j>=0; j--) */
+
+	      POST_break:
+		
+		if (!link_found) {
+		  int ii = i + 1; /* Reset back to i + 1 */
+		  orphan[ii] = 1;
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_lo = 0;\n",ii);
+		  /* TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_len = 1;\n",ii); */
+		  inlined_len[ii] = STRDUP("1");
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d_hi = N%d;\n",ii,ii);
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d = K%d_lo;\n",ii,ii);
+		}
+		else {
+		  int ii = i + 1; /* Reset back to i + 1 */
+		  /*
+		  TAB(1+i+2+oneif); 
+		  ODB_fprintf(cfp,"int K%d_len = P%s_len[K%d];\n",ii,snext,level);
+		  */
+
+		  ALLOC(inlined_len[ii],strlen(snext) + 30);
+		  sprintf(inlined_len[ii],"P%s_len[K%d]",snext,level);
+
+		  if (pview->safeGuard) {
+		    TAB(1+i+2+oneif);
+		    ODB_fprintf(cfp,"if (%s > 0) { /* safeGuard#%d */\n",inlined_len[ii],++numsg);
+		    close_bracket[i] = 1+i+2+oneif;
+		  }
+
+		  TAB(1+i+2+oneif);
+		  ODB_fprintf(cfp,"int K%d_lo = P%s_off[K%d];\n",ii,snext,level);
+
+		  if (subloop[ii].len == 0) {
+		    if (!subloop[ii].protected) {
+		      subloop[ii].i = level;
+		      subloop[ii].protected = 1;
+		    }
+		    TAB(1+i+2+oneif); 
+		    ODB_fprintf(cfp,"int K%d_hi = K%d_lo + %s;\n",
+				ii,ii,inlined_len[ii]);
+		  }
+		  TAB(1+i+2+oneif); ODB_fprintf(cfp,"int K%d = K%d_lo;\n",ii,ii);
+		}
+	      } /* if (i < nfrom - 1) */
+	      
+	      CONDCODE(cfp,numands);
+	    } /* for (i=0; i<nfrom; i++) */
+	    FPINF_KEYEND(links);
+	    
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if ((pview->active[i] & 0x1) == 0x1) {
+		TAB(1+nfrom+2); 
+		ODB_fprintf(cfp,"Index_%s[tmpcount] = K%d;\n", s, i);
+	      }
+	    } /* for (i=0; i<nfrom; i++) */
+
+	    if (nfrom > 0) {
+	      TAB(1+nfrom+2);
+	      ODB_fprintf(cfp,"tmpcount++;\n");
+	    }
+	    else {
+	      i = 0;
+	      TAB(1+i+1); ODB_fprintf(cfp,"{ /* FROM-less WHERE statement (if any) */\n");
+	      CONDCODE(cfp,numands);
+	      TAB(1+i+3); ODB_fprintf(cfp,"tmpcount++;\n");
+	      TAB(1+i+2); ODB_fprintf(cfp,"} /* if-block end */\n"); \
+	      TAB(1+i+1); ODB_fprintf(cfp,"}\n");
+	    }
+	    
+	    for (i=nfrom-1; i>=0; i--) {
+	      if (pcond && (i == maxfrom)) {
+		oneif--;
+		TAB(1+i+2);
+		ODB_fprintf(cfp,"} /* if-block end */\n");
+	      }
+
+	      if (pview->safeGuard && close_bracket[i]) {
+		int ii = i + 1; /* Reset back to i + 1 */
+		int tabs = 1+i+2;
+		TAB(tabs); ODB_fprintf(cfp,"} /* end safeGuard#%d : if (%s > 0) ... */\n",numsg--,inlined_len[ii]);
+		close_bracket[i] = 0;
+	      }
+
+	      /* if (i < nfrom - 1 || (numands > 0 || numands == -1)) */ {
+		TAB(1+i+1+oneif); 
+		ODB_fprintf(cfp,"} /* TABLE '%s' */\n", pview->from[i]->table->name);
+	      }
+	    } /* for (i=nfrom-1; i>=0; i--) */
+
+	    TAB(1); ODB_fprintf(cfp,"} /* for (PE=PEstart; PE<=PEend; PE++) */\n");
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(tmpcount);\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"return tmpcount;\n}\n");
+	    NL(1);
+
+	    free_tmpsym(1);
+	    
+	    FREE(subloop);
+	    FREE(close_bracket);
+	    for (i=0; i<nfrom; i++) {
+	      if (inlined_len[i]) FREE(inlined_len[i]);
+	    }
+	    FREE(inlined_len);
+	    FREE(orphan);
+
+	    /* SELECT : The parent SELECT-function for a view */
+
+	    ODB_fprintf(cfp,
+		    "PRIVATE int\nSel_V_%s(void *V, ODB_PE_Info *PEinfo, int phase, void *feedback)\n{\n",
+		    name);
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int CountPrS = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int CountPoS = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_SETUP(%s, \"",name);
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      ODB_fprintf(cfp,"%s%s",s,(i==nfrom-1) ? "" : ",");
+	    }
+	    ODB_fprintf(cfp,"\");\n");
+	    TAB(1); ODB_fprintf(cfp,"int it = get_thread_id_();\n");
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(Sel_V_%s);\n", name);
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_PEINFO_SELVIEW_SETUP();\n");
+
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if ((pview->active[i] & 0x1) == 0x1) { TAB(1); ODB_fprintf(cfp,"FREEINDEX(%s);\n", s); }
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_PRE();\n");
+
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      TAB(1); ODB_fprintf(cfp,"ODBMAC_VIEW_DELAYED_LOAD(%s);\n",s);
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_0();\n");
+
+	    /*
+	    TAB(1); ODB_fprintf(cfp,"P->MaxRows = ");
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if (i>0 && nfrom > 2) { NL(1); TAB(2); }
+	      if (i>0)              { ODB_fprintf(cfp,"* "); }
+	      ODB_fprintf(cfp,"P->T_%s->Nrows%s",s,(i<nfrom-1) ? "" : ";\n");
+	    }
+	    NL(1);
+	    */
+
+	    if (nuniqueby > 0) {
+	      TAB(1); ODB_fprintf(cfp,"codb_hash_set_lock_();\n");
+	      TAB(1); ODB_fprintf(cfp,"codb_hash_init_();\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_1();\n");
+
+	    {
+	      const int tabinc = 1;
+	      int nvars = 0;
+
+	      TAB(tabinc); ODB_fprintf(cfp,"{ /* Start of pre- & post-select block */\n");
+
+	      init_list(NULL);
+	      ZEROIT(done, 0, nall);
+	      
+	      for (i=nselect_all; i<nall; i++) {
+		char *tag = pview->tag[i];
+		char *ptype;
+		char *pvar;
+		char *ptable;
+		char *p;
+		int plen;
+		
+		if (!tag) continue;
+		
+		(void) ODB_split(tag, &ptype, &pvar, NULL, &ptable, NULL);
+		
+		plen = strlen(pvar) + strlen(ptable) + 10;
+		ALLOC(p, plen);
+		snprintf(p, plen, "P->T_%s->%s", ptable, pvar);
+		
+		if (!in_list(p)) {
+		  add_list(p);
+		  TAB(tabinc+1); 
+		  ODB_fprintf(cfp,"const %s *TmpVec_%d = ",ptype,i);
+		  ODB_fprintf(cfp,"UseDSlong(P->T_%s, %s, %s, %s);\n", ptable, odb_label, ptype, p);
+		  done[i] = 1;
+		  nvars++;
+		}
+
+		FREE(p);
+		FREE(ptype);
+		FREE(pvar);
+		FREE(ptable);
+	      }
+
+	      destroy_list();
+	      
+	      for (i=0; i<nfrom; i++) {
+		char *s = pview->from[i]->table->name;
+		TAB(tabinc+1); ODB_fprintf(cfp,"ALLOCBITMAPINDEX(%s);\n",s);
+	      }
+
+	      if (pview->has_thin) {
+		TAB(tabinc+1); ODB_fprintf(cfp,"codb_thin_reset_(&it);\n");
+	      }
+
+	      TAB(tabinc+1); ODB_fprintf(cfp,"CountPrS = PrS_V_%s(do_trace, P, it, PEinfo",name);
+	      
+	      for (i=0; i<nfrom; i++) {
+		char *s = pview->from[i]->table->name;
+		ODB_fprintf(cfp,"\n",s);
+		TAB(tabinc+2); ODB_fprintf(cfp,", P->T_%s->Nrows, P->BitmapIndex_%s",s,s);
+	      }
+
+	      if (nvars > 0) {
+		for (i=nselect_all; i<nall; i++) {
+		  if (done[i]) {
+		    ODB_fprintf(cfp,",\n");
+		    TAB(tabinc+2); ODB_fprintf(cfp,"TmpVec_%d",i);
+		  }
+		}
+	      }
+	      
+	      ODB_fprintf(cfp,");\n");
+	      
+	      TAB(tabinc+1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_POST();\n");
+	      
+	      if (!merge_table_indices) {
+		for (i=0; i<nfrom; i++) {
+		  char *s = pview->from[i]->table->name;
+		  if ((pview->active[i] & 0x1) == 0x1) { 
+		    TAB(tabinc+1); 
+		    ODB_fprintf(cfp, "ALLOCINDEX(%s, CountPrS);\n", s); 
+		  }
+		} /* for (i=0; i<nfrom; i++) */
+	      }
+	      else {
+		/* In index allocation take into account the merging of 
+		   certain ALIGNed (or -A) table indices */
+		
+		TAB(tabinc+1); ODB_fprintf(cfp,"/* Index merge requested via '-O3 -m' options */\n");
+		
+		/* Masters first */
+		for (i=0; i<nfrom; i++) {
+		  char *master = pview->from[i]->table->name;
+		  if ((pview->active[i] & 0x1) == 0x1 && !pview->merged_with[i]) { 
+		    TAB(tabinc+1); 
+		    ODB_fprintf(cfp, "ALLOC(P->Index_%s, CountPrS); P->Allocated_%s = 1;\n", 
+				master, master); 
+		  }
+		} /* for (i=0; i<nfrom; i++) */
+		
+		/* Slaves last */
+		for (i=0; i<nfrom; i++) {
+		  char *master = pview->from[i]->table->name;
+		  if ((pview->active[i] & 0x1) == 0x1 && pview->merged_with[i]) { 
+		    char *slave = pview->merged_with[i];
+		    TAB(tabinc+1); 
+		    ODB_fprintf(cfp, "P->Index_%s = P->Index_%s; P->Allocated_%s = 0;\n", 
+				master, slave, master); 
+		  }
+		} /* for (i=0; i<nfrom; i++) */
+	      }
+
+	      if (nuniqueby > 0) {
+		TAB(tabinc+1); ODB_fprintf(cfp,"codb_hash_reset_();\n");
+	      }
+
+	      TAB(tabinc+1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_2();\n");
+	      
+	      TAB(tabinc+1); ODB_fprintf(cfp,"if (CountPrS > 0) {\n");
+	      if (pview->has_thin) {
+		TAB(tabinc+2); ODB_fprintf(cfp,"codb_thin_reset_(&it);\n");
+	      }
+	      TAB(tabinc+2); ODB_fprintf(cfp,"CountPoS = PoS_V_%s(do_trace, P, it, PEinfo",name);
+	      
+	      for (i=0; i<nfrom; i++) {
+		char *s = pview->from[i]->table->name;
+		ODB_fprintf(cfp,"\n");
+		TAB(tabinc+3); ODB_fprintf(cfp,", P->T_%s->Nrows, P->BitmapIndex_%s",s,s);
+		if ((pview->active[i] & 0x1) == 0x1) {
+		  ODB_fprintf(cfp,", P->Index_%s",s);
+		}
+	      }
+	      
+	      if (nvars > 0) {
+		for (i=nselect_all; i<nall; i++) {
+		  if (done[i]) {
+		    ODB_fprintf(cfp,",\n");
+		    TAB(tabinc+3); ODB_fprintf(cfp,"TmpVec_%d",i);
+		  }
+		}
+	      }
+	      
+	      ODB_fprintf(cfp,"); }\n");
+	      TAB(tabinc+1); ODB_fprintf(cfp,"else { CountPoS = CountPrS; }\n");
+
+	      for (i=0; i<nfrom; i++) {
+		char *s = pview->from[i]->table->name;
+		TAB(tabinc+1); ODB_fprintf(cfp,"FREEBITMAPINDEX(%s);\n",s);
+	      }
+
+	      TAB(tabinc); ODB_fprintf(cfp,"} /* End of pre-& post-select block */\n");
+	    }
+
+	    if (nuniqueby > 0) {
+	      TAB(1); ODB_fprintf(cfp,"codb_hash_init_();\n");
+	      TAB(1); ODB_fprintf(cfp,"codb_hash_unset_lock_();\n");
+	    }
+	    
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_TRACE_SELVIEW_LAST();\n");
+	    TAB(1); ODB_fprintf(cfp,"ODBMAC_ERRMSG_SELVIEW(%s);\n",name);
+	    
+	    {
+	      int cnt, ntbl = 0;
+	      for (i=0; i<nfrom; i++) {
+		if ((pview->active[i] & 0x1) == 0x1) ntbl++;
+	      }
+	      TAB(1); 
+	      ODB_fprintf(cfp,"ODB_debug_print_index(stdout, \"%s\", P->PoolNo, CountPrS, %d",
+			  name, ntbl);
+	      cnt = 0;
+	      for (i=0; i<nfrom; i++) {
+		char *s = pview->from[i]->table->name;
+		if ((pview->active[i] & 0x1) == 0x1) {
+		  ODB_fprintf(cfp,"\n");
+		  TAB(4); 
+		  ODB_fprintf(cfp,", \"%s\", P->Index_%s, P->T_%s, P->T_%s->Nrows",
+			      s, s, s, s);
+		  ++cnt;
+		}
+	      }
+	      ODB_fprintf(cfp,");\n");
+	    }
+	    TAB(1); ODB_fprintf(cfp,"P->Nrows = CountPrS;\n");
+
+	    if (pview->has_thin) {
+	      TAB(1); ODB_fprintf(cfp,"codb_thin_reset_(&it);\n");
+	    }
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(CountPrS);\n");
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"return CountPrS;\n");
+	    ODB_fprintf(cfp,"}\n");
+	    NL(1);
+
+	    for (j=0; j<ntypes_view; j++) {
+	      char *pKey = Key[j];
+	      char *pExtType = ExtType[j];
+
+	      if (!typemask[j]) continue;
+
+	      ODB_fprintf(cfp,"PRIVATE int\n%sGet_V_%s(void *V, %s D[],\n",
+		      pKey, name, pExtType);
+	      TAB(1); ODB_fprintf(cfp,"int LdimD, int Nrows, int Ncols,\n");
+	      TAB(1); ODB_fprintf(cfp,"int ProcID, const int Flag[], int row_offset)\n{\n");
+
+	      TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	      TAB(1); ODB_fprintf(cfp,"int Count = MIN(Nrows, P->Nrows);\n");
+	      TAB(1); ODB_fprintf(cfp,"int K1 = 0, K2 = Count;\n");
+	      TAB(1); ODB_fprintf(cfp,"int Npes = P->Npes;\n");
+	      if (pview->has_formulas) {
+		TAB(1); ODB_fprintf(cfp,"int ii, it = get_thread_id_();\n");
+		TAB(1); ODB_fprintf(cfp,"Formula *tmp = NULL;\n");
+	      }
+	      TAB(1); ODB_fprintf(cfp,"FILE *do_trace = ODB_trace_fp();\n");
+
+	      if (insert_drhook) {
+	        TAB(1); ODB_fprintf(cfp,"DRHOOK_START(%sGet_V_%s);\n", pKey, name);
+	      }
+
+	      TAB(1); ODB_fprintf(cfp,"ODBMAC_PEINFO_OFFSET();\n");
+
+	      if (pview->sel) {
+		int kaux = pview->nselect;
+		int k = 0;
+		int ioffset = nselect_all+nwhere+norderby;
+		for (i=0; i<nselect; i++) {
+		  if (pview->is_formula[i]) {
+		    int ksave = k;
+		    int naux, ns = 0, ne = pview->sel[i]->ncols_aux;
+		    for (naux=ns; naux <= ne; naux++) {
+		      Boolean need_i = 0;
+		      int ii = (naux == ns) ? i : kaux++;
+		      TAB(1); ODB_fprintf(cfp,"if (FLAG_FETCH(Flag[%d])) { /* column#%d */\n",ii,ii+1);
+		      TAB(2); ODB_fprintf(cfp,"/* Formula: '%s' */\n",pview->sel[i]->formula+1);
+		      if (pview->sel[i]->ncols_aux > 0) {
+			TAB(2); ODB_fprintf(cfp,"const int ArgNo = %d;\n",1+naux);
+		      }
+		      { /* Start of dollar & column variables */
+			int jj;
+			k = ksave;
+			init_list(NULL);
+			for (jj=0; jj<pview->sel[i]->nsym; jj++, k++) {
+			  char *s = pview->sel[i]->sym[jj]->name;
+			  char *call_arg = pview->call_arg[ioffset+k];
+			  if (IS_HASH(s)) { need_i = 1; continue; }
+			  if (in_list(s)) continue;
+			  if (IS_DOLLAR(s)) {
+			    if (IS_POOLNO(s)) {
+			      TAB(2); 
+			      ODB_fprintf(cfp,
+					  "double lc_USD_%s = P->PoolNo; "
+					  "/* A fixed value */\n", POOLNO);
+			    }
+			    else if (!IS_USDHASH(s)) {
+			      TAB(2); 
+			      ODB_fprintf(cfp,
+					  "double ODBMAC_LC_GETVAL(%s, %s, %c%s%c); /* '%s' */\n",
+					  odb_label,s+1,'"',name,'"',s);
+			    }
+			    else if (IS_USDHASH(s)) {
+			      /* These are NOT all correct ; 
+				 they need to be dynamic/loop variable depended etc. */
+			      char *eq = NULL;
+			      if (IS_(ROWNUM,s)) eq = "0";
+			      if (IS_(UNIQNUM,s)) eq = "ODB_put_one_control_word(0, P->PoolNo)";
+			      else if (IS_(NROWS,s)) eq = "P->Nrows";
+			      else if (IS_(NCOLS,s)) eq = "P->Ncols";
+			      else if (IS_(COLNUM,s)) eq = "0"; /* Don't know the column ? */
+			      else if (IS_USDDOTHASH(s)) eq = "0"; 
+			      if (eq) {
+				char *sh = STRDUP(s);
+				int sh_len = STRLEN(sh);
+				char *dot = strchr(sh,'.');
+				if (dot) *dot = 'D'; /* IS_USDDOTHASH(s) */
+				sh[sh_len-1] = '\0'; /* replace '#' with '\0' */
+				TAB(2);
+				ODB_fprintf(cfp,
+					    "double lc_USDHASH_%s = %s; /* Not correct */\n",
+					    sh+1,eq);
+				FREE(sh);
+			      }
+			    }
+			    add_list(s);
+			  }
+			  else if (STRLEN(call_arg) > 0) {
+			    char *pcolon = strchr(call_arg,':');
+			    char *atag = pview->tag[ioffset+k];
+			    if (pcolon && in_list(pcolon)) continue;
+			    if (pcolon && atag) {
+			      char *p = NULL;
+			      int plen;
+			      char *ptype = NULL;
+			      char *pvar = NULL;
+			      char *ptable = NULL;
+			      (void) ODB_split(atag, &ptype, &pvar, NULL, &ptable, NULL);
+			      TAB(2); ODB_fprintf(cfp,"const %s *%s = ",ptype,pcolon+1);
+			      plen = strlen(pvar) + strlen(ptable) + 10;
+			      ALLOC(p, plen);
+			      snprintf(p, plen, "P->T_%s->%s", ptable, pvar);
+			      ODB_fprintf(cfp,"UseDSlong(P->T_%s, %s, %s, %s);\n", 
+					  ptable, odb_label, ptype, p);
+			      FREE(p);
+			      FREE(ptype);
+			      FREE(pvar);
+			      FREE(ptable);
+			      need_i = 1;
+			      add_list(pcolon);
+			    }
+			  }
+			}
+			destroy_list();
+		      } /* End of dollar & column variables */
+		      TAB(2); ODB_fprintf(cfp,"tmp = &D[%d*LdimD];\n",ii);
+		      TAB(2); ODB_fprintf(cfp,"for (ii=K1; ii<K2; ii++) {\n");
+		      if (need_i) {
+			TAB(3); ODB_fprintf(cfp,"int i = ii + row_offset;\n");
+		      }
+		      TAB(3); ODB_fprintf(cfp,"tmp[ii] =");
+		      {
+			char *f1 =  dump_s(NULL,pview->sel[i]->expr,1,NULL);
+			int f1len = STRLEN(f1);
+			if (f1len < linelen_threshold) {
+			  ODB_fprintf(cfp," %s;\n",f1);
+			}
+			else {
+			  char *p1 = f1;
+			  ODB_fprintf(cfp,"\n");
+			  TAB(4);
+			  while ( *p1 ) {
+			    ODB_fprintf(cfp,"%c",*p1);
+			    if (*p1 == '\n') TAB(4);
+			    p1++;
+			  }
+			  ODB_fprintf(cfp,";\n");
+			}
+			FREE(f1);
+		      }
+		      TAB(2); ODB_fprintf(cfp,"} /* for (ii=K1; ii<K2; ii++) */\n");
+		      TAB(1); ODB_fprintf(cfp,"} /* if (FLAG_FETCH(Flag[%d])) -- column#%d */\n",ii,ii+1);
+		    } /* for (naux=ns; naux <= ne; naux++) */
+		  }
+		  else {
+		    int ifrom = pview->table_index[i];
+		    ODB_Table *from = pview->from[ifrom];
+		    char *tname = from->table->name;
+		    char *tag = pview->tag[i];
+		    /* char *define = pview->def_get[i]; */
+		    char *alias_get = pview->alias_get[i];
+		    char *ptype = NULL;
+		    char *pvar = NULL;
+		    char *datatype = NULL;
+		    int pos = 0, len = 0;
+		    char *p = NULL;
+		    
+		    (void) ODB_split(tag, &ptype, &pvar, NULL, NULL, NULL);
+		    (void) get_PKmethod(ptype,NULL,&datatype,NULL);
+		    
+		    p = strstr(alias_get, "_BITS(");
+		    if (p && strequ(ptype,BITFIELD)) {
+		      /* Read pos & len from ", %d, %d)" */
+		      char *psave = STRDUP(alias_get);
+		      char *comma = strrchr(psave, ','); /* The last comma */
+		      if (comma) {
+			len = atoi(comma+1);
+			*comma = '\0';
+			comma = strrchr(psave, ','); /* 2nd last comma */
+			if (comma) pos = atoi(comma+1);
+		      }
+		      FREE(psave);
+		    }
+		
+		    TAB(1); 
+		    ODB_fprintf(cfp,
+				"Call_GatherGet_VIEW(%s, %s, %d, %s, %s, K1, K2, %s, D, %s, DATATYPE_%s, %d, %d);\n",
+				odb_label, pKey, i+1, name, ptype, tname, pvar,
+				datatype, pos, len);
+		    
+		    FREE(pvar);
+		    FREE(ptype);
+		    FREE(datatype);
+		  } /* if (pview->is_formula[i]) ...  else ... */
+		} /* for (i=0; i<nselect; i++) */
+	      }
+
+	      if (insert_drhook) {
+		TAB(1); ODB_fprintf(cfp,"DRHOOK_END(K2-K1);\n");
+	      }
+
+	      TAB(1); ODB_fprintf(cfp,"return K2-K1;\n");
+	      ODB_fprintf(cfp,"}\n");
+	      NL(1);	    
+
+	      if (!pview->all_readonly) {
+		ODB_fprintf(cfp,"PRIVATE int\n%sPut_V_%s(void *V, const %s D[],\n",
+			pKey, name, pExtType);
+		TAB(1); ODB_fprintf(cfp,"int LdimD, int Nrows, int Ncols,\n");
+		TAB(1); ODB_fprintf(cfp,"int ProcID, const int Flag[])\n{\n");
+		
+		TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+		TAB(1); ODB_fprintf(cfp,"int Count = MIN(Nrows, P->Nrows);\n");
+		TAB(1); ODB_fprintf(cfp,"int K1 = 0, K2 = Count;\n");
+		TAB(1); ODB_fprintf(cfp,"int Npes = P->Npes;\n");
+		TAB(1); ODB_fprintf(cfp,"FILE *do_trace = ODB_trace_fp();\n");
+
+		if (insert_drhook) {
+	          TAB(1); ODB_fprintf(cfp,"DRHOOK_START(%sPut_V_%s);\n", pKey, name);
+		}
+
+		TAB(1); ODB_fprintf(cfp,"ODBMAC_PEINFO_OFFSET();\n");
+		
+		for (i=0; i<nselect; i++) {
+		  if (!pview->readonly[i]) {
+		    int ifrom = pview->table_index[i];
+		    ODB_Table *from = pview->from[ifrom];
+		    char *tname = from->table->name;
+		    char *tag = pview->tag[i];
+		    /* char *define = pview->def_put[i]; */
+		    char *alias_put = pview->alias_put[i];
+		    char *ptype = NULL;
+		    char *pvar = NULL;
+		    char *datatype = NULL;
+		    int pos = 0, len = 0;
+		    char *p = NULL;
+
+		    (void) ODB_split(tag, &ptype, &pvar, NULL, NULL,NULL);
+		    (void) get_PKmethod(ptype,NULL,&datatype,NULL);
+
+		    p = strstr(alias_put, "_BITS(");
+		    if (p && strequ(ptype,BITFIELD)) {
+		      /* Read pos & len from ", %d, %d)" */
+		      char *psave = STRDUP(alias_put);
+		      char *comma = strrchr(psave, ','); /* The last comma */
+		      if (comma) {
+			len = atoi(comma+1);
+			*comma = '\0';
+			comma = strrchr(psave, ','); /* 2nd last comma */
+			if (comma) pos = atoi(comma+1);
+		      }
+		      FREE(psave);
+		    }
+
+		    TAB(1); 
+		    ODB_fprintf(cfp,
+		      "Call_ScatterPut_VIEW(%s, %s, %d, %s, %s, K1, K2, %s, %s, D, DATATYPE_%s, %d, %d);\n",
+				odb_label, pKey, i+1, name, ptype, tname, pvar,
+				datatype, pos, len);
+		    
+		    FREE(pvar);
+		    FREE(ptype);
+		  }
+		} /* for (i=0; i<nselect; i++) */
+		
+		if (insert_drhook) {
+		  TAB(1); ODB_fprintf(cfp,"DRHOOK_END(K2-K1);\n");
+		}
+
+		TAB(1); ODB_fprintf(cfp,"return K2-K1;\n}\n");
+		NL(1);
+	      } /* if (!pview->all_readonly) */
+	    }/* for (j=0; j<ntypes_view; j++) */
+
+	    /* Dimension function for VIEW */
+
+	    ODB_fprintf(cfp,"PRIVATE void\nDim_V_%s(",name);
+	    ODB_fprintf(cfp,"void *V, int *Nrows, int *Ncols, int *Nrowoffset, int ProcID) ");
+	    ODB_fprintf(cfp,"{ ODBMAC_DIM(%s); }\n",name);
+	    NL(1);
+
+	    /* Removing and deallocating VIEW (the same as cancel (Ccl_V_) for views) */
+
+	    ODB_fprintf(cfp,"#define Swapout_V_%s Ccl_V_%s\n",name, name);
+	    NL(1);
+
+	    /* VIEW SQL */
+
+	    ODB_fprintf(cfp, "PRIVATE int\nSql_V_%s(", name);
+	    ODB_fprintf(cfp, "FILE *fp, int mode, const char *prefix, const char *postfix, char **sqlout) ");
+	    ODB_fprintf(cfp, "{ ODBMAC_VIEWSQL(); }\n");
+	    NL(1);
+
+	    /* VIEW colaux */
+
+	    {
+	      int kaux = pview->nselect;
+	      int Ncols_tot = kaux + ncols_aux;
+	      FPINF_KEYNUM(colaux, Ncols_tot);
+	      if (ncols_aux >= 0) {
+		int *colaux = NULL;
+		CALLOC(colaux, Ncols_tot);
+		ODB_fprintf(cfp,"PRIVATE int\nColAux_V_%s(",name);
+		ODB_fprintf(cfp,"void *V, int colaux[], int colaux_len)\n{\n");
+		for (i=0; i<nselect; i++) {
+		  if (pview->is_formula[i]) {
+		    uint flag = pview->sel[i]->aggr_flag;
+		    if (pview->sel[i]->ncols_aux > 0) {
+		      int naux, ns = 0, ne = pview->sel[i]->ncols_aux;
+		      int ii = i;
+		      for (naux=ns; naux < ne; naux++) {
+			colaux[ii] = kaux+1; /* Fortran-index */
+			ii = kaux++;
+		      }
+		    }
+		    else {
+		      colaux[i] = i+1; /* Fortran-index */
+		    }
+		  }
+		  else {
+		    colaux[i] = i+1; /* Fortran-index */
+		  }
+		}
+		TAB(1); ODB_fprintf(cfp,"int filled = 0;\n");
+		TAB(1); ODB_fprintf(cfp,"static const int ColAux_len = %d;\n",Ncols_tot);
+		TAB(1); ODB_fprintf(cfp,"static const int ColAux[%d] = ",Ncols_tot);
+		for (i=0; i<Ncols_tot; i++) {
+		  ODB_fprintf(cfp,"%s%d",(i>0) ? "," : "{",colaux[i]);
+		  FPINF_NUM(i, colaux[i]);
+		}
+		ODB_fprintf(cfp,"};\n");
+		TAB(1); ODB_fprintf(cfp,"ODBMAC_COPY_COLAUX(%s);\n",name);
+		TAB(1); ODB_fprintf(cfp,"return filled;\n");
+		ODB_fprintf(cfp,"}\n");
+		NL(1);
+		FREE(colaux);
+	      }
+	      FPINF_KEYEND(colaux);
+	    }
+
+	    /* Sorting keys */
+
+	    ODB_fprintf(cfp,
+			"PRIVATE int *\nSortKeys_V_%s(void *V, int *NSortKeys) { ODBMAC_SORTKEYS(%s); }\n",
+			name, name);
+	    NL(1);
+
+	    /* Inquire update status per column of SQL */
+
+	    ODB_fprintf(cfp,
+		    "PRIVATE int \nUpdateInfo_V_%s(void *V, const int ncols, int can_UPDATE[]) ",
+		    name);
+	    ODB_fprintf(cfp,"{ ODBMAC_UPDATEINFO(%s); }\n",name);
+	    NL(1);
+
+	    /* Aggregate funcs in use ? */
+
+	    if (pview->select_aggr_flag) {
+	      ODB_fprintf(cfp,
+			  "PRIVATE int \nAggrInfo_V_%s(void *V, const int ncols, int aggr_func_flag[]) ",
+			  name);
+	      ODB_fprintf(cfp,"{ ODBMAC_AGGRINFO(%s); }\n",name);
+	      NL(1);
+	    }
+
+	    /* Get indices */
+
+	    ODB_fprintf(cfp,
+		    "PRIVATE int *\nGetIndex_V_%s(void *V, const char *Table, int *Nidx)\n{\n",
+		    name);
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int Dummy = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"int *Nlen = Nidx ? Nidx : &Dummy;\n");
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if ((pview->active[i] & 0x1) == 0x1) { 
+		TAB(1); ODB_fprintf(cfp,"ODBMAC_GETINDEX(%s);\n",s);
+	      }
+	    }
+	    TAB(1); ODB_fprintf(cfp,"return NULL;\n}\n");
+	    NL(1);
+
+	    ODB_fprintf(cfp,
+		    "PRIVATE int\nPutIndex_V_%s(void *V, const char *Table, int Nidx, int idx[], int by_address)\n{\n",
+		    name);
+	    TAB(1); ODB_fprintf(cfp,"/* *** Warning: This is a VERY DANGEROUS routine -- if misused !!! */\n");
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int rc = 0;\n");
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if ((pview->active[i] & 0x1) == 0x1) { 
+		TAB(1); ODB_fprintf(cfp,"ODBMAC_PUTINDEX(%s);\n",s);
+	      }
+	    }
+	    TAB(1); ODB_fprintf(cfp,"return rc;\n}\n");
+	    NL(1);
+
+	    /* PE-info */
+
+	    ODB_fprintf(cfp,"PRIVATE void\nPEinfo_V_%s(void *V, ODB_PE_Info *PEinfo) ",name);
+	    ODB_fprintf(cfp,"{ ODBMAC_PEINFO_INIT(%s); }\n",name);
+	    NL(1);
+
+	    /* Initialization function for VIEW (table pointers are resolved at Create_Pool) */
+
+	    ODB_fprintf(cfp,
+		    "PRIVATE void *\nInit_V_%s(void *V, ODB_Pool *Pool, int Dummy1, int Dummy2, int it, int add_vars)\n{\n",
+		    name);
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"int PoolNo = Pool->poolno;\n");
+	    TAB(1); ODB_fprintf(cfp,"ODB_Funcs *pf;\n");
+	    TAB(1); ODB_fprintf(cfp,"static ODB_CommonFuncs *pfcom = NULL; /* Shared between pools & threads */\n");
+
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(Init_V_%s);\n",name);
+	    }
+	    TAB(1); ODB_fprintf(cfp,"if (!P) ALLOC(P, 1);\n");
+
+	    TAB(1); ODB_fprintf(cfp,"P->PoolNo = PoolNo;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Ncols = %d;\n",nselect+ncols_aux);
+	    TAB(1); ODB_fprintf(cfp,"P->Nrows = 0;\n");
+	    /* TAB(1); ODB_fprintf(cfp,"P->MaxRows = 0;\n"); */
+
+	    TAB(1); ODB_fprintf(cfp,"P->USD_symbols = %d; /* In SELECT = %d ; In WHERE = %d */\n",
+				count_USD_symbols,selsym_USD_symbols,pcond_USD_symbols);
+
+	    TAB(1); ODB_fprintf(cfp,"P->Replicate_PE = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Npes = 0;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->NrowVec = NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->NrowOffset = NULL;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"P->NSortKeys = %d;\n",pview->norderby);
+	    if (pview->norderby > 0) {
+	      for (i=0; i<pview->norderby; i++) {
+		TAB(1); 
+		ODB_fprintf(cfp,"P->SortKeys[%d] = %d;\n",
+			i,pview->mkeys[i]);
+	      }
+	    }
+	    else {
+	      TAB(1); ODB_fprintf(cfp,"P->SortKeys = NULL;\n");
+	    }
+
+	    TAB(1);  
+	    ODB_fprintf(cfp,
+			"/* Initially all bits set to 0, which corresponds to read-only -mode for all */\n");
+
+	    TAB(1);  
+	    ODB_fprintf(cfp,
+			"memset(P->can_UPDATE, 0, sizeof(P->can_UPDATE));\n");
+
+	    for (i=0; i<nselect; i++) {
+	      TAB(1);
+	      if (pview->readonly[i]) {
+		ODB_fprintf(cfp,"ODBIT_unset(P->can_UPDATE, P->Ncols, MAXBITS, %d, %d); /* %s */\n", 
+			    i, i, pview->tag[i]);
+	      }
+	      else {
+		ODB_fprintf(cfp,"ODBIT_set(P->can_UPDATE, P->Ncols, MAXBITS, %d, %d);   /* %s */\n", 
+			    i, i, pview->tag[i]);
+	      }
+	    }
+
+	    if (pview->select_aggr_flag) {
+	      int numaggr = 0;
+	      TAB(1); ODB_fprintf(cfp,"/* Aggregate function flags */\n");
+	      TAB(1); ODB_fprintf(cfp,"memset(P->aggr_func_flag, 0, sizeof(P->aggr_func_flag));\n");
+	      for (i=0; i<nselect; i++) {
+		if (pview->is_formula[i]) {
+		  uint flag = pview->sel[i]->aggr_flag;
+		  switch (flag) {
+		  case ODB_AGGR_COUNT :          PrtAggrFlag(ODB_AGGR_COUNT); break;
+		  case ODB_AGGR_COUNT_DISTINCT:  PrtAggrFlag(ODB_AGGR_COUNT_DISTINCT); break;
+		  case ODB_AGGR_BCOUNT :         PrtAggrFlag(ODB_AGGR_BCOUNT); break;
+		  case ODB_AGGR_BCOUNT_DISTINCT: PrtAggrFlag(ODB_AGGR_BCOUNT_DISTINCT); break;
+		  case ODB_AGGR_MIN :            PrtAggrFlag(ODB_AGGR_MIN); break;
+		  case ODB_AGGR_MAX :            PrtAggrFlag(ODB_AGGR_MAX); break;
+		  case ODB_AGGR_SUM :            PrtAggrFlag(ODB_AGGR_SUM); break;
+		  case ODB_AGGR_SUM_DISTINCT:    PrtAggrFlag(ODB_AGGR_SUM_DISTINCT); break;
+		  case ODB_AGGR_AVG :            PrtAggrFlag(ODB_AGGR_AVG); break;
+		  case ODB_AGGR_AVG_DISTINCT:    PrtAggrFlag(ODB_AGGR_AVG_DISTINCT); break;
+		  case ODB_AGGR_MEDIAN :         PrtAggrFlag(ODB_AGGR_MEDIAN); break;
+		  case ODB_AGGR_MEDIAN_DISTINCT: PrtAggrFlag(ODB_AGGR_MEDIAN_DISTINCT); break;
+		  case ODB_AGGR_STDEV :          PrtAggrFlag(ODB_AGGR_STDEV); break;
+		  case ODB_AGGR_STDEV_DISTINCT:  PrtAggrFlag(ODB_AGGR_STDEV_DISTINCT); break;
+		  case ODB_AGGR_VAR :            PrtAggrFlag(ODB_AGGR_VAR); break;
+		  case ODB_AGGR_VAR_DISTINCT:    PrtAggrFlag(ODB_AGGR_VAR_DISTINCT); break;
+		  case ODB_AGGR_RMS :            PrtAggrFlag(ODB_AGGR_RMS); break;
+		  case ODB_AGGR_RMS_DISTINCT:    PrtAggrFlag(ODB_AGGR_RMS_DISTINCT); break;
+		  case ODB_AGGR_DOTP :           PrtAggrFlag(ODB_AGGR_DOTP); break;
+		  case ODB_AGGR_DOTP_DISTINCT:   PrtAggrFlag(ODB_AGGR_DOTP_DISTINCT); break;
+		  case ODB_AGGR_NORM :           PrtAggrFlag(ODB_AGGR_NORM); break;
+		  case ODB_AGGR_NORM_DISTINCT:   PrtAggrFlag(ODB_AGGR_NORM_DISTINCT); break;
+		  case ODB_AGGR_COVAR :          PrtAggrFlag(ODB_AGGR_COVAR); break;
+		  case ODB_AGGR_CORR :           PrtAggrFlag(ODB_AGGR_CORR); break;
+		  case ODB_AGGR_LINREGR_A :      PrtAggrFlag(ODB_AGGR_LINREGR_A); break;
+		  case ODB_AGGR_LINREGR_B :      PrtAggrFlag(ODB_AGGR_LINREGR_B); break;
+		  case ODB_AGGR_MINLOC :         PrtAggrFlag(ODB_AGGR_MINLOC); break;
+		  case ODB_AGGR_MAXLOC :         PrtAggrFlag(ODB_AGGR_MAXLOC); break;
+		  case ODB_AGGR_DENSITY :        PrtAggrFlag(ODB_AGGR_DENSITY); break;
+		  default: break;
+		  }
+		}
+	      } /* for (i=0; i<nselect; i++) */
+
+	      /* For now: Auxiliary columns -- despite aggregate-func related -- are ignored */
+
+	      TAB(1); ODB_fprintf(cfp,"P->numaggr = %d;\n", numaggr);
+	      TAB(1); ODB_fprintf(cfp,"P->all_aggr = %d;\n", 
+				  (numaggr == nselect) ? 1 : 0); /* 1 if all columns aggregate funcs */
+	    } /* if (pview->select_aggr_flag) */
+
+	    TAB(1); ODB_fprintf(cfp,"{\n");
+	    TAB(2); ODB_fprintf(cfp,"ODB_Pool *p = Pool;\n");
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      TAB(2); ODB_fprintf(cfp,"ODBMAC_ASSIGN_TABLEDATA(%s);\n",s);
+	    }
+	    TAB(1); ODB_fprintf(cfp,"}\n");
+	    
+	    for (i=0; i<nfrom; i++) {
+	      char *s = pview->from[i]->table->name;
+	      if ((pview->active[i] & 0x1) == 0x1) { 
+		TAB(1); ODB_fprintf(cfp,"NULLIFY_INDEX(%s);\n",s);
+	      }
+	    }
+
+	    TAB(1); ODB_fprintf(cfp,"if (!pfcom) { /* Initialize once only */\n");
+	    TAB(2); ODB_fprintf(cfp,"CALLOC(pfcom,1);\n");
+
+	    TAB(2); ODB_fprintf(cfp,"{ static char s[] = \"%s\"; pfcom->name = s; }\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->is_table = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->is_considered = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ntables = %d;\n",nfrom);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ncols = P->Ncols;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->tableno = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->rank = 0;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->wt = 0;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->tags = V_%s_TAG;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->preptags = V_%s_PREPTAG;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ntag = nV_%s_TAG;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->npreptag = nV_%s_PREPTAG;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->nmem = nV_%s_MEM;\n",name);
+	    
+	    TAB(2); ODB_fprintf(cfp,"pfcom->Info = NULL;\n");
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->create_index = %d;\n", pview->create_index);
+
+	    if (fpinf) {
+	      ODB_fprintf(fpinf, "\n/create_index=%d\n", pview->create_index);
+	      ODB_fprintf(fpinf, "\n/binary_index=%d\n", pview->binary_index ? 1 : 0);
+	      if (pview->create_index <= 0) {
+		ODB_fprintf(fpinf, "\n/use_indices=%d\n",pview->use_indices ? 1 : 0);
+		ODB_fprintf(fpinf, "\n/use_index_name=%s\n",pview->use_index_name);
+	      }
+	    }
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->init = Init_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->swapout = Swapout_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->dim = Dim_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->sortkeys = SortKeys_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->update_info = UpdateInfo_V_%s;\n",name);
+	    TAB(2);
+	    if (pview->select_aggr_flag) {
+	      ODB_fprintf(cfp,"pfcom->aggr_info = AggrInfo_V_%s;\n",name);
+	    }
+	    else {
+	      ODB_fprintf(cfp,"pfcom->aggr_info = NULL;\n");
+	    }
+	    TAB(2); ODB_fprintf(cfp,"pfcom->getindex = GetIndex_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->putindex = PutIndex_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->peinfo = PEinfo_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->select = Sel_V_%s;\n",name);
+	    TAB(2); ODB_fprintf(cfp,"pfcom->remove = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->cancel = Ccl_V_%s;\n",name);
+
+	    for (j=0; j<ntypes; j++) {
+	      char *pKey = Key[j];
+	      if (typemask[j]) {
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sget = %sGet_V_%s;\n", 
+				    pKey, pKey, name);
+		if (pview->all_readonly) {
+		  TAB(2); ODB_fprintf(cfp,"pfcom->%sput = NULL; /* All view entries read-only */\n", 
+				      pKey);
+		}
+		else {
+		  TAB(2); ODB_fprintf(cfp,"pfcom->%sput = %sPut_V_%s;\n", 
+				      pKey, pKey, name);
+		}
+	      }
+	      else {
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sget = NULL; /* no dbmgr allowed for this type */\n", 
+				    pKey);
+		TAB(2); ODB_fprintf(cfp,"pfcom->%sput = NULL; /* no dbmgr allowed for this type */\n", 
+				    pKey);
+	      }
+	    }
+	    
+	    TAB(2); ODB_fprintf(cfp,"pfcom->load = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->store = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->pack = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->unpack = NULL;\n");
+	    TAB(2); ODB_fprintf(cfp,"pfcom->sql = Sql_V_%s;\n",name);
+
+	    TAB(2); ODB_fprintf(cfp,"pfcom->ncols_aux = %d;\n",ncols_aux);
+	    if (ncols_aux >= 0) {
+	      TAB(2); ODB_fprintf(cfp,"pfcom->colaux = ColAux_V_%s;\n",name);
+	    }
+	    else {
+	      TAB(2); ODB_fprintf(cfp,"pfcom->colaux = NULL;\n");
+	    }
+
+	    TAB(2);
+	    if (pview->select_distinct && nuniqueby > 0) {
+	      ODB_fprintf(cfp,"pfcom->has_select_distinct = %d; /* SELECT DISTINCT ... */\n",
+			  -nuniqueby);
+	    }
+	    else if (nuniqueby > 0) {
+	      ODB_fprintf(cfp,"pfcom->has_select_distinct = %d; /* SELECT ... UNIQUEBY ... */\n",
+			  nuniqueby);
+	    }
+	    else if (nfrom == 0) {
+	      ODB_fprintf(cfp,"pfcom->has_select_distinct = 1; /* No active tables */\n");
+	    }
+	    else {
+	      ODB_fprintf(cfp,"pfcom->has_select_distinct = 0;\n");
+	    }
+	    TAB(2); ODB_fprintf(cfp,"pfcom->has_usddothash = %d;\n",pview->usddothash ? 1 : 0);
+	    TAB(1); ODB_fprintf(cfp,"} /* if (!pfcom) */\n");
+
+	    TAB(1); ODB_fprintf(cfp,"ALLOC(pf, 1);\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->it = it;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->data = P;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->Res = NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->tmp = NULL;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->pool = Pool;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->common = pfcom;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf->next = NULL;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"P->Funcs = pf;\n");
+	    TAB(1); ODB_fprintf(cfp,"P->Handle = P->Funcs->pool->handle;\n");
+
+	    TAB(1); ODB_fprintf(cfp,"if (add_vars) {\n");
+	    
+	    (void) assign_USD_symbols(NULL, pcond, 0, 0, NULL, name); /* Reset flags */
+
+	    if (has_USD_symbols > 0) {
+	      /* Set-symbols */
+	      ODB_Symbol *psym;
+
+	      init_list(NULL);
+	      FPINF_KEY(set);
+
+	      if (pcond_USD_symbols > 0) {
+		/* Give priority to WHERE-symbols over the other symbols */
+		(void) assign_USD_symbols(cfp, pcond, 2, 3, name, name);
+	      } /* if (pcond_USD_symbols > 0) */
+	      
+	      if (selsym_USD_symbols > 0) {
+		/* Also give priority to SELECT-expression -symbols over the other symbols */
+		for (i=0; i<nselect; i++) {
+		  if (pview->sel[i] && pview->sel[i]->expr) {
+		    ODB_Tree *expr = pview->sel[i]->expr;
+		    (void) assign_USD_symbols(cfp, expr, 2, 3, name, name);
+		  }
+		} /* for (i=0; i<nselect; i++) */
+	      } /* if (selsym_USD_symbols > 0) */
+
+	      for (psym = ODB_start_symbol(); psym != NULL; psym = psym->next) {
+		if (psym->kind == ODB_USDNAME && psym->only_view) {
+		  if (DONE_SYM(psym->flag, 4) || DONE_SYM(psym->flag, 5)) {
+		    char *s = psym->name;
+		    double value = psym->dval;
+		    if (!in_list(s)) {
+		      if (!IS_POOLNO(s) && !IS_USDHASH(s)) {
+			TAB(2);
+			ODB_fprintf(cfp,"Pool->add_var(\"%s\", \"%s\", \"%s\", it, USD_%s_%s);\n",
+				    odb_label, s, name ? name : "???", s+1, odb_label);
+		      }
+		      add_list(s);
+		      FPINF_ITEMFLP(s, value);
+		    }
+		  } /* if (DONE_SYM(psym->flag, 4) || DONE_SYM(psym->flag, 5)) */
+		}
+		if (psym->kind == ODB_USDNAME) {
+		  RESET_SYM(psym->flag, 4); /* Reset for subsequent uses */
+		  RESET_SYM(psym->flag, 5); /* Reset for subsequent uses */
+		}
+	      }
+
+	      destroy_list();
+	      /* Make sure ODBTk's $__maxcount__ gets there, too */
+	      FPINF_ITEMFLP(sym_maxcount->name, sym_maxcount->dval);
+	      FPINF_KEYEND(set);
+	    } /* if (has_USD_symbols > 0) */
+	      
+	    TAB(1);  ODB_fprintf(cfp,"} /* if (add_vars) */\n");
+	    
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(0);\n");
+	    }
+	    TAB(1); ODB_fprintf(cfp,"return P;\n}\n");
+	    NL(1);
+
+	    ODB_fprintf(cfp,"/* *************** End of VIEW \"%s\" *************** */\n",name);
+	    NL(1);
+
+	    FREE(done);
+
+	    ODB_fprintf(cfp,
+		    "PUBLIC ODB_Funcs *\nAnchor2%s(void *V, ODB_Pool *pool, int *nviews, int it, int add_vars)\n{\n",
+		    dofunc);
+	    TAB(1); ODB_fprintf(cfp,"VIEW_%s *P = V;\n",name);
+	    TAB(1); ODB_fprintf(cfp,"ODB_Funcs *pf;\n");
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_START(Anchor2%s);\n",dofunc);
+	    }
+	    TAB(1); ODB_fprintf(cfp,"if (!P) P = Init_V_%s(NULL, pool, -1, -1, it, add_vars);\n",name);
+	    TAB(1); ODB_fprintf(cfp,"if (nviews) *nviews = 1;\n");
+	    TAB(1); ODB_fprintf(cfp,"pf = P->Funcs;\n");
+	    if (insert_drhook) {
+	      TAB(1); ODB_fprintf(cfp,"DRHOOK_END(0);\n");
+	    }
+	    TAB(1); ODB_fprintf(cfp,"return pf;\n");
+	    ODB_fprintf(cfp,"}\n");
+
+	    FREE(dofunc);
+
+	    FCLOSE(fpview);
+	    FCLOSE(fpinf);
+	  } /* if (nfrom >= 0) */
+	} /* if (pview) */ 
+
+	cfp = ODB_popFILE();
+      }
+      break;
+
+    default:
+      SETMSG3("DDL-source line#%d: Key '%s' (%d) not implemented\n",
+	      lineno, ODB_keymap(what), what);
+      YYerror(msg);
+      break;
+    } /* switch (what) */
+  }
+}
+
+
+
+PUBLIC ODB_Filelist *
+genc(Boolean views_only)
+{
+  FILE *cfp = NULL;
+
+  {
+    char *p;
+    int len;
+
+    len = strlen(odb_label);
+
+    if (views_only) {
+      fphdr = fpdevnull;
+      fptable = fpdevnull;
+    }
+    else {
+      ALLOC(p, len + 5);
+      sprintf(p, "%s.h", odb_label);
+      if (ABS(filtered_info) < 2) {
+	fphdr = FOPEN(p, "w");
+      }
+      else {
+	fphdr = NULL;
+      }
+      FREE(p);
+
+      ALLOC(p, len + 3);
+      sprintf(p, "%s.c", odb_label);
+      if (ABS(filtered_info) < 2) {
+	fptable = FOPEN(p, "w");
+      }
+      else {
+	fptable = NULL;
+      }
+      FREE(p);
+    }
+  }
+  
+  cfp = fphdr;
+
+  if (!views_only) { /* Part#1 */
+    char *odb_h = strrchr(ODB_H,'/');
+    if (odb_h) odb_h++; else odb_h = ODB_H;
+
+    ODB_fprintf(cfp,"#ifndef ODB_GENCODE\n");
+    ODB_fprintf(cfp,"#define ODB_GENCODE 1\n");
+    ODB_fprintf(cfp,"#endif\n");
+    NL(1);
+
+    {
+      int numeric = 0;
+      const char *vstr = codb_versions_(NULL, NULL, &numeric, NULL);
+      ODB_fprintf(cfp,"\n/* Software revision : %s (%d) */\n", vstr, numeric);
+    }
+    NL(1);
+
+#ifdef INLINE_ODB_H
+    ODB_fprintf(cfp,"#ifdef ODB_H\n");
+    ODB_fprintf(cfp,"#include \"%s\"\n",odb_h);
+    ODB_fprintf(cfp,"#else\n");
+    NL(1);
+    ODB_fprintf(cfp,"/* Start of include '%s' */\n",ODB_H);
+    NL(1);
+    {
+      if (ODB_copyfile(cfp, ODB_H, NULL, NULL, 0, 1) <= 0) {
+	SETMSG1("Problems with master include file '%s'",ODB_H);
+	YYerror(msg);
+      }
+    }
+    NL(1);
+    ODB_fprintf(cfp,"/* End of include '%s' */\n",ODB_H);
+    NL(1);
+    ODB_fprintf(cfp,"#endif /* ifdef ODB_H */\n");
+#else
+    ODB_fprintf(cfp,"#include \"%s\"\n",odb_h);
+#endif
+    {
+      const char odb_macros_h[] = "odb_macros.h";
+      ODB_fprintf(cfp,"#include \"%s\"\n",odb_macros_h);
+    }
+    if (insert_drhook) {
+      const char cdrhook_h[] = "cdrhook.h";
+      ODB_fprintf(cfp,"#include \"%s\"\n",cdrhook_h);
+    }
+    NL(1);
+
+    ODB_fprintf(cfp,"#define ODB_LABEL    \"%s\"\n",odb_label);
+    NL(1);
+
+    ODB_fprintf(cfp,"\n/* Compilation options used :\n%s",ARGH);
+    process_one_tables(cfp, "\n\t ","");
+    ODB_fprintf(cfp,"\n\n*/\n");
+    NL(1);
+    
+    /* Table hierarchy */
+    if (table_hier && ODB_ntables > 0) {
+      int j;
+      int len = 10;
+      ODB_fprintf(cfp,
+		  "/* ----- Table hierarchy (= the default scanning order) : # of tables = %d\n",
+		  ODB_ntables);
+      NL(1);
+      for (j=0; j<ODB_ntables; j++) {
+	ODB_Table *ptable = table_hier[j];
+	int len_t = strlen(ptable->table->name);
+	len = MAX(len, len_t);
+      }
+      TAB(1);
+      ODB_fprintf(cfp,"%10s    %*s : %10s   %s\n",
+		  "Rank#", len, "Table", "Order#", "Weight");
+      TAB(1);
+      ODB_fprintf(cfp,"%10s    %*s : %10s   %s\n",
+		  "-----", len, "-----", "------", "------");
+      for (j=0; j<ODB_ntables; j++) {
+	ODB_Table *ptable = table_hier[j];
+	TAB(1);
+	ODB_fprintf(cfp,"%10d    %*s : %10d   %.6f\n",
+		    ptable->rank, len, ptable->table->name,
+		    ptable->tableno, ptable->wt);
+      }
+      NL(1);
+      ODB_fprintf(cfp,"   ----- End of table hierarchy ----- */\n"); 
+      NL(1);
+    } /* if (table_hier && ODB_ntables > 0) */
+
+    /* One common function to print flags-file */
+
+    ODB_fprintf(cfp,"PUBLIC void %s_print_flags_file(void);\n",odb_label);
+    NL(1);
+
+    ODB_fprintf(cfp,"#if defined(ODB_MAINCODE)\n");
+    NL(1);
+    (void) write_setsymbols(cfp, "PUBLIC", 0);
+    ODB_fprintf(cfp,"#endif /* defined(ODB_MAINCODE) */\n");
+    NL(1);
+
+    /* Just in case there are no views, which would have invoked ... */
+    ODB_link_massage();
+
+    /* Write alias types only */
+    {
+      ODB_Cmd *pcmd;
+      for (pcmd = ODB_start_cmd(); pcmd != NULL; pcmd = pcmd->next) {
+	ODB_Tree *pnode = pcmd->node;
+	if (pnode) {
+	  if (pnode->what == ODB_TYPE) {
+	    dump_c(cfp, pcmd->lineno, pcmd->node);
+	    NL(1);
+	  }
+	} /* if (pnode) */
+      } /* for (pcmd = ODB_start_cmd(); pcmd != NULL; pcmd = pcmd->next) */
+    }
+    
+    /* Create data structures */
+    {
+      ODB_Table *ptable;
+      Boolean done_INT = 0;
+      Boolean done_UINT = 0;
+      Boolean done_DBL = 0;
+      
+      init_list(NULL);
+      
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	int j, nsym = ptable->nsym;
+	
+	for (j=0; j<nsym; j++) {
+	  char *p;
+	  ODB_Type *ptype = ptable->type[j];
+	  /* ODB_Symbol *psym = ptable->sym[j]; */
+	  char *type = get_typename(ptype);
+	  
+	  ALLOC(p, strlen(type) + 3);
+	  sprintf(p, "/%s/", type);
+	  
+	  if (!in_list(p)) {
+	    char *ftype = NULL;
+	    int pmethod = get_PKmethod(type, &ftype, NULL,NULL);
+	    
+	    add_list(p);
+	    ODB_fprintf(cfp,"DefineDS(%s);\n",type);
+	    
+	    if (pmethod == 0) {
+	      ODB_fprintf(cfp,"DS_DummyPacks(%s, %s, %s)\n",odb_label,ftype,type);
+	    }
+	    else {
+	      if      (!done_INT  && strequ(ftype,"INT")) {
+		ODB_fprintf(cfp,"#define %s_pack_%s ODB_pack_%s\n",odb_label,ftype,ftype);
+		ODB_fprintf(cfp,"#define %s_unpack_%s ODB_unpack_%s\n",odb_label,ftype,ftype);
+		done_INT = 1;
+	      }
+	      else if (!done_UINT && strequ(ftype,"UINT")) {
+		ODB_fprintf(cfp,"#define %s_pack_%s ODB_pack_%s\n",odb_label,ftype,ftype);
+		ODB_fprintf(cfp,"#define %s_unpack_%s ODB_unpack_%s\n",odb_label,ftype,ftype);
+		done_UINT = 1;
+	      }
+	      else if (!done_DBL  && strequ(ftype,"DBL")) {
+		ODB_fprintf(cfp,"#define %s_pack_%s ODB_pack_%s\n",odb_label,ftype,ftype);
+		ODB_fprintf(cfp,"#define %s_unpack_%s ODB_unpack_%s\n",odb_label,ftype,ftype);
+		done_DBL = 1;
+	      }
+	    }
+	    ODB_fprintf(cfp,"DS_Unpacking(%s, %s, %s)\n", odb_label, ftype, type); 
+	    ODB_fprintf(cfp,"DS_Packing(%s, %s, %s)\n", odb_label, ftype, type); 
+	    NL(1);
+	    
+	    FREE(ftype);
+	  }
+	  
+	  FREE(p);
+	} /* for (j=0; j<nsym; j++) */
+      }
+      
+      destroy_list();
+    }
+    NL(1);
+  }  /* if (!views_only) { -- Part#1 */
+
+  /* Write statements (type, table, view etc. defs) */
+  
+  cfp = fptable;
+    
+  ODB_fprintf(cfp,"#define ODB_MAINCODE 1\n");
+  NL(1);
+  set_optlevel(cfp, 0);
+  ODB_fprintf(cfp,"#include \"%s.h\"\n",odb_label);
+  NL(1);
+
+  {
+    ODB_Cmd *pcmd;
+    for (pcmd = ODB_start_cmd(); pcmd != NULL; pcmd = pcmd->next) {
+      dump_c(cfp, pcmd->lineno, pcmd->node);
+    }
+  }
+
+  if (!views_only) { /* Part#2 */
+    /* Write the "odb_label" specific information */
+
+    /* Printing of flags-file */
+
+    ODB_fprintf(cfp,
+	    "PUBLIC void \n%s_print_flags_file(void)\n{\n", odb_label);
+    TAB(1); ODB_fprintf(cfp,"int rc = 0, io = -1;\n");
+    TAB(1); ODB_fprintf(cfp,"FILE *fp = NULL;\n");
+    TAB(1); 
+    ODB_fprintf(cfp,
+	    "cma_open_(&io, \"%s.flags\", \"w\", &rc, strlen(\"%s.flags\"), strlen(\"w\"));\n",
+	    odb_label, odb_label);
+    TAB(1); ODB_fprintf(cfp, "if (rc != 1) return; /* multi-bin file ==> forget flags-file */\n");
+    TAB(1); ODB_fprintf(cfp, "fp = CMA_get_fp(&io);\n");
+    TAB(1); ODB_fprintf(cfp, "if (!fp) return; /* pointer NULL ==> forget the flags-file ;-( */\n");
+    if (!reset_align_issued) {
+      /* grep for lines starting with "-A" */
+      if (ODB_grepfile(cfp, "^-A",
+		       "$ODB_COMPILER_FLAGS", 
+		       "  fprintf(fp,\"%s\\n\",\"", "\");", 1, 0) < 0) { 
+	/* < 0, not <= 0 to allow file '/dev/null' in $ODB_COMPILER_FLAGS */
+	char *env = getenv("ODB_COMPILER_FLAGS");
+	SETMSG1("Problems accessing $ODB_COMPILER_FLAGS-file '%s'", env ? env : "");
+	YYerror(msg);
+      }
+    }
+    if (!reset_onelooper_issued) {
+      /* grep for lines starting with "-1" */
+      if (ODB_grepfile(cfp, "^-1",
+		       "$ODB_COMPILER_FLAGS", 
+		       "  fprintf(fp,\"%s\\n\",\"", "\");", 1, 0) < 0) { 
+	/* < 0, not <= 0 to allow file '/dev/null' in $ODB_COMPILER_FLAGS */
+	char *env = getenv("ODB_COMPILER_FLAGS");
+	SETMSG1("Problems accessing $ODB_COMPILER_FLAGS-file '%s'", env ? env : "");
+	YYerror(msg);
+      }
+    }
+    if (one_tables) {
+      process_one_tables(cfp,"  fprintf(fp,\"","\\n\");\n");
+    }
+    TAB(1); ODB_fprintf(cfp, "cma_close_(&io, &rc);\n}\n");
+    NL(1);
+
+    /* Add funcs */
+    
+    ODB_fprintf(cfp,
+		"PRIVATE int \nCreate_Funcs(ODB_Pool *pool, int is_new, int io_method, int it)\n{\n");
+    TAB(1); ODB_fprintf(cfp,"int nfuncs = 0;\n");
+    TAB(1); ODB_fprintf(cfp,"static int first_time = 1;\n");
+    {
+      ODB_Table *ptable;
+      int num_tables = 0;
+      int id = 0;
+      
+      /* Create caching info about TableIsConsidered */
+
+      id = 0;
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	++id;
+      }
+      num_tables = id;
+      TAB(1); ODB_fprintf(cfp,"static int IsConsidered[%d];\n",num_tables);
+
+      if (insert_drhook) {
+	TAB(1); ODB_fprintf(cfp,"DRHOOK_START(Create_Funcs);\n");
+      }
+
+      TAB(1); ODB_fprintf(cfp,"if (first_time) {\n");
+      id = 0;
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	char *name = ptable->table->name;
+	TAB(2); ODB_fprintf(cfp,"ODBMAC_INIT_IsConsidered(%s, %d);\n",name,id++);
+      }
+      TAB(2); ODB_fprintf(cfp,"first_time = 0;\n");
+      TAB(1); ODB_fprintf(cfp,"} /* if (first_time) */\n");
+
+      /* Declare tables and setup, alloc & add table funcs (all in one go) */
+
+      id = 0;
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	char *name = ptable->table->name;
+	Boolean dummy_table = is_dummy_table(name);
+	TAB(1); ODB_fprintf(cfp,"ODBMAC_CREATE_TABLE(%s, %s, %d, %d);\n",
+			    odb_label,name,id++,
+			    dummy_table ? 0 : 1);
+      } /* for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) */
+    
+      if (insert_drhook) {
+	TAB(1); ODB_fprintf(cfp,"DRHOOK_END(0);\n");
+      }
+    }
+
+    TAB(1); ODB_fprintf(cfp,"return nfuncs;\n}\n");
+    NL(1);
+
+    /* Establish the data "load" and "store" -functions for the pool */
+    
+    /* Load */
+    
+    {
+      ODB_Table *ptable;
+     
+      ODB_fprintf(cfp,"PRIVATE int\nLoad_Pool(ODB_Pool *P, int io_method)\n{\n");
+      TAB(1); ODB_fprintf(cfp,"int rc = 0;\n");
+      TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+      TAB(1); ODB_fprintf(cfp,"ODB_Funcs *pf = P->funcs;\n");
+      TAB(1); ODB_fprintf(cfp,"if (io_method != 5) {\n");
+      
+      /* Read tables */
+      
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	char *s = ptable->table->name;
+	TAB(2); ODB_fprintf(cfp, "Call_TABLE_Load(%s, pf, 1);\n", s);
+      }
+
+      TAB(1); ODB_fprintf(cfp,"} /* if (io_method != 5) */\n");
+      TAB(1); ODB_fprintf(cfp,"return (rc < 0) ? rc : Nbytes;\n}\n");
+      NL(1);
+    }
+  
+    /* Store */
+    
+    {
+      ODB_Table *ptable;
+      
+      ODB_fprintf(cfp,"PRIVATE int\nStore_Pool(const ODB_Pool *P, int io_method)\n{\n");
+      if (readonly_mode) {
+	TAB(1); ODB_fprintf(cfp,"/* Data layout was compiled under Read/Only mode (-r option or ODB_READONLY=1) */\n");
+	TAB(1); ODB_fprintf(cfp,"return 0;\n}\n");
+      }
+      else {
+	TAB(1); ODB_fprintf(cfp,"int rc = 0;\n");
+	TAB(1); ODB_fprintf(cfp,"int Nbytes = 0;\n");
+	TAB(1); ODB_fprintf(cfp,"ODB_Funcs *pf = P->funcs;\n");
+	TAB(1); ODB_fprintf(cfp,"if (io_method != 5) {\n");
+	
+	/* Write tables */
+	
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  char *s = ptable->table->name;
+	  TAB(2); ODB_fprintf(cfp, "Call_TABLE_Store(%s, pf, 1);\n",s);
+	}
+
+	TAB(1); ODB_fprintf(cfp,"} /* if (io_method != 5) */\n");
+	TAB(1); ODB_fprintf(cfp,"return (rc < 0) ? rc : Nbytes;\n}\n");
+      }
+
+      NL(1);
+    }
+  }  /* if (!views_only) { -- Part#2 */
+
+  if (fphdr != fpdevnull) FCLOSE(fphdr);
+
+  if (views_only) {
+    if (fptable != fpdevnull) FCLOSE(fptable);
+    goto finish;
+  }
+
+  /* Anchor-function to bind the database dynamically with
+     its create, load and store functions */
+
+  cfp = fptable;
+
+  ODB_fprintf(cfp,
+	  "PUBLIC ODB_Funcs *\nAnchor2%s(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars)\n{\n",
+	  odb_label);
+  TAB(1); ODB_fprintf(cfp,"ODB_Anchor_Funcs *func = V;\n");
+  TAB(1); ODB_fprintf(cfp,"ODB_Pool *p = pool;\n");
+  if (insert_drhook) {
+    TAB(1); ODB_fprintf(cfp,"DRHOOK_START(Anchor2%s);\n",odb_label);
+  }
+  TAB(1); 
+  ODB_fprintf(cfp,
+	      "/* A special case : ntables not a NULL => return no. of tables */\n");
+  TAB(1); ODB_fprintf(cfp,"if (ntables) {\n");
+  /* Fixed no. of TABLEs for this definition */
+  {
+    int ntables = 0;
+    ODB_Table *ptable;
+    
+    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+      ntables++;
+    }
+    TAB(2); ODB_fprintf(cfp,"*ntables = %d;\n",ntables);
+  }
+
+  TAB(2); ODB_fprintf(cfp,"goto finish;\n");
+  TAB(1); ODB_fprintf(cfp,"}\n");
+
+  TAB(1); ODB_fprintf(cfp,"func->create_funcs = Create_Funcs;\n");
+  TAB(1); ODB_fprintf(cfp,"func->load         = Load_Pool;\n");
+  TAB(1); ODB_fprintf(cfp,"func->store        = Store_Pool;\n");
+
+  /* Set-symbols */
+  TAB(1); ODB_fprintf(cfp,"if (add_vars) {\n");
+  {
+    ODB_Symbol *psym;
+    for (psym = ODB_start_symbol(); psym != NULL; psym = psym->next) {
+      if (psym->kind == ODB_USDNAME) {
+	char *s = psym->name;
+	if (!IS_POOLNO(s) && !IS_USDHASH(s)) {
+	  char *tmp;
+	  ALLOC(tmp, strlen(s+1) + 5);
+	  sprintf(tmp, "USD_%s", s+1);
+	  TAB(2); ODB_fprintf(cfp,
+			      "p->add_var(p->dbname, \"%s\", NULL, it, %s_%s);\n",
+			      s, tmp, odb_label);
+	  FREE(tmp);
+	}
+      }
+    }
+  }
+  TAB(1);  ODB_fprintf(cfp,"} /* if (add_vars) */\n");
+      
+  TAB(1); ODB_fprintf(cfp,"finish:\n");
+  if (insert_drhook) {
+    TAB(1); ODB_fprintf(cfp,"DRHOOK_END(0);\n");
+  }
+  TAB(1); ODB_fprintf(cfp,"return NULL;\n}\n");
+
+  if (fptable != fpdevnull) FCLOSE(fptable);
+
+
+ finish:
+
+  if (!views_only && (filtered_info == 0 || filtered_info == -1)) {
+
+    /* Create setup file for subsequent uses */
+
+    extern char *IOresolve_env(const char *str); /* from libioassign.a */
+    ODB_Table *ptable;
+    char *setup_file = getenv("ODB_SETUP_FILE");
+    char *params, *maxproc;
+    char *odb_ld, *odb_libs;
+    char *shell;
+    Boolean opened = 0;
+    FILE *fp = stderr;
+    
+    if (setup_file) {
+      char *file = IOresolve_env(setup_file);
+      fp = strequ(file,"/dev/null") ? NULL : FOPEN(file, "w");
+      if (!fp) {
+	if (!strequ(file,"/dev/null")) PERROR(file);
+      }
+      else {
+	fprintf(stderr,"Creating ODB setup-file '%s' ...\n",file);
+	opened = 1;
+      }
+      FREE(file);
+    }
+
+    odb_ld = getenv("ODB_LD");
+    odb_ld = odb_ld ? STRDUP(odb_ld) : STRDUP("");
+
+    odb_libs = getenv("ODB_LIBS");
+    odb_libs = odb_libs ? STRDUP(odb_libs) : STRDUP("");
+
+    shell = getenv("ODB_SETUP_SHELL");
+    if (!shell) shell = getenv("SHELL");
+    shell = shell ? STRDUP(shell) : STRDUP("/bin/ksh");
+   
+    ODB_fprintf(fp,"#!%s\n",shell);
+    if (strstr(shell,"/ksh") || strstr(shell,"/bash")) {
+      ODB_fprintf(fp,"%sexport ODB_LD=\"%s\"\n",
+	      strlen(odb_ld) > 0 ? "" : "# ",
+	      odb_ld);
+      ODB_fprintf(fp,"%sexport ODB_LIBS=\"%s\"\n",
+	      strlen(odb_libs) > 0 ? "" : "# ",
+	      odb_libs);
+    }
+    else if (strstr(shell,"/sh")) {
+      ODB_fprintf(fp,"%sODB_LD=\"%s\"; export ODB_LD\n",
+	      strlen(odb_ld) > 0 ? "" : "# ",
+	      odb_ld);
+      ODB_fprintf(fp,"%sODB_LIBS=\"%s\"; export ODB_LIBS\n",
+	      strlen(odb_libs) > 0 ? "" : "# ",
+	      odb_libs);
+    }
+    else {
+      ODB_fprintf(fp,"%ssetenv ODB_LD \"%s\"\n",
+	      strlen(odb_ld) > 0 ? "" : "# ",
+	      odb_ld);
+      ODB_fprintf(fp,"%ssetenv ODB_LIBS \"%s\"\n",
+	      strlen(odb_libs) > 0 ? "" : "# ",
+	      odb_libs);
+    }
+
+    params = getenv("ODB_IOASSIGN_PARAMS");
+    params = params ? STRDUP(params) : STRDUP("");
+
+    /* Value for the following variable doesn't matter anymore (since 30R2 onwards) */
+    maxproc = getenv("ODB_IOASSIGN_MAXPROC");
+    maxproc = maxproc ? STRDUP(maxproc) : STRDUP("64");
+
+    ODB_fprintf(fp,
+	    "ioassign -s -a \\$ODB_SRCPATH_%s/%s.dd %s\n",
+	    odb_label,odb_label,odb_label);
+
+    ODB_fprintf(fp,
+	    "ioassign -s -a \\$ODB_SRCPATH_%s/%s.sch %s.sch\n",
+	    odb_label,odb_label,odb_label);
+
+    ODB_fprintf(fp,
+	    "ioassign -s %s -a \\$ODB_SRCPATH_%s/%s.iomap %s.iomap\n",
+	    params, odb_label,odb_label,odb_label);
+
+    ODB_fprintf(fp,
+	    "ioassign -s -a \\$ODB_SRCPATH_%s/%s.flags %s.flags\n",
+	    odb_label,odb_label,odb_label);
+
+    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+      char *s = ptable->table->name;
+
+      ODB_fprintf(fp,
+	      "ioassign -s %s -a \\$ODB_SRCPATH_%s/dca/%s.dca %s.%s.dca\n",
+	      params,
+	      odb_label, s,
+	      odb_label, s);
+    }
+
+    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+      char *s = ptable->table->name;
+
+      ODB_fprintf(fp,
+	      "ioassign -s -n %s %s -a \\$ODB_DATAPATH_%s/%%d/%s %s.%s.%%d\n",
+	      maxproc, params,
+	      odb_label, s,
+	      odb_label, s);
+    }
+
+    if (opened) FCLOSE(fp);
+
+    ALLOC(flist, 1);
+    flist->filename = STRDUP(odb_label);
+    flist->create_so = 1;
+    flist->next = NULL;
+    if (!flist_start) {
+      flist_start = flist;
+    }
+    else {
+      flist_last->next = flist;
+    }
+    flist_last = flist;
+
+    FREE(odb_ld);
+    FREE(odb_libs);
+    FREE(shell);
+    FREE(params);
+    FREE(maxproc);
+  }
+
+  if (genstatic == 1) {
+    ODB_View *pview;
+    char *pstatic, *p;
+    FILE *cfp;
+    int viewlen = 0;
+    extern int Ccompile_Sstatic_stubb;
+    
+    int len = strlen(odb_label);
+
+    ALLOC(p, len + 9);
+    sprintf(p,"%s_Sstatic", odb_label);
+
+    if (Ccompile_Sstatic_stubb) {
+      ALLOC(flist, 1);
+      flist->filename = STRDUP(p);
+      flist->create_so = 0;
+      flist->next = NULL;
+      if (!flist_start) {
+	flist_start = flist;
+      }
+      else {
+	flist_last->next = flist;
+      }
+      flist_last = flist;
+    }
+
+    ALLOC(pstatic, strlen(p) + 3);
+    sprintf(pstatic,"%s.c", p);
+
+    if (incremental) {
+      if (is_regular_file_(pstatic)) {
+	char *newname = NULL;
+	ALLOC(newname, strlen(pstatic) + 5);
+	sprintf(newname,"%s.old",pstatic);
+	if (rename_file_(pstatic,newname) != 0) {
+	  incremental = 0; /* Rename failed, but we don't want to abort */
+	}
+	FREE(newname);
+      }
+      else {
+	incremental = 0;
+      }
+    }
+
+    if (ABS(filtered_info) < 2) {
+      cfp = FOPEN(pstatic, "w");
+    }
+    else {
+      cfp = NULL;
+    }
+    FREE(p);
+
+    ODB_fprintf(cfp,"#define ODB_GENCODE 0\n");
+    
+    set_optlevel(cfp, 0);
+    ODB_fprintf(cfp,"#include \"%s.h\"\n",odb_label);
+
+    NL(1);
+
+    ODB_fprintf(cfp,"PUBLIC void %s_static_init() {\n",odb_label);
+    ODB_fprintf(cfp,"ODB_ANCHOR(%s);\n",odb_label);
+
+    viewlen = 0;
+    for (pview = ODB_start_view(); pview != NULL; pview = pview->next) {
+      char *name = pview->view->name;
+      ODB_fprintf(cfp,"ODB_ANCHOR_VIEW(%s, %s );\n",odb_label,name);
+      viewlen += strlen(name) + 1;
+    }
+
+    if (incremental && viewlen > 0 && ABS(filtered_info) < 2) {
+      /* Strip away those views that were just recompiled */
+      char *cmd = NULL;
+      char *delim = "(";
+      FCLOSE(cfp);
+      viewlen += 2 * strlen(pstatic) + 256;
+      ALLOC(cmd, viewlen);
+
+      if (verbose) {
+	sprintf(cmd,"ls -l %s.old",pstatic);
+        fprintf(stderr,"## Executing: %s\n",cmd);
+	(void)system(cmd);
+      }
+
+      if (verbose) {
+	sprintf(cmd,"wc -l %s.old",pstatic);
+	fprintf(stderr,"## Executing: %s\n",cmd);
+	(void)system(cmd);
+      }
+
+      sprintf(cmd,"egrep ODB_ANCHOR_VIEW %s.old | egrep -v ' ",pstatic);
+      for (pview = ODB_start_view(); pview != NULL; pview = pview->next) {
+	char *name = pview->view->name;
+	strcat(cmd,delim);
+	strcat(cmd,name);
+	delim = "|";
+      }
+      delim = ") ' >> ";
+      strcat(cmd,delim);
+      strcat(cmd,pstatic);
+      if (verbose) fprintf(stderr,"## Executing\n\t%s\n",cmd);
+      (void)system(cmd);
+      FREE(cmd);
+      {
+	extern char *IOresolve_env(const char *str); /* from libioassign.a */
+	char *pfile = IOresolve_env(pstatic);
+	cfp = FOPEN(pfile,"a");
+	ODB_fprintf(cfp,"}\n");
+	FCLOSE(cfp);
+	FREE(pfile);
+      }
+    }
+    else {
+      ODB_fprintf(cfp,"}\n");
+      FCLOSE(cfp);
+    }
+
+    FREE(pstatic);
+  }
+
+  return flist_start;
+}
diff --git a/odb/src/compiler/lex.l b/odb/src/compiler/lex.l
new file mode 100644
index 0000000..5c4cbba
--- /dev/null
+++ b/odb/src/compiler/lex.l
@@ -0,0 +1,1127 @@
+%{ 
+
+/* Important:
+   If compiling with flex, please *DO COMPILE* with lex-compatibility option
+   "-l" in order to get effect of %array instead of %pointer i.e. 
+   extern char yytext[] instead of extern char *yytext !! ;-(
+ */
+
+#include "defs.h" 
+
+#if defined(YYLMAX)
+#undef YYLMAX
+#define YYLMAX 65536
+#endif
+
+extern FILE *fpsrc;
+extern int optlevel;
+extern Boolean verbose;
+extern int include_nesting;
+extern FILE *yyin;
+extern char *odb_source;
+extern int ODB_lineno;
+
+int LEX_convflag = 0;
+double LEX_unconv_value = 0;
+
+int LEX_in_where = 0;
+int LEX_auto_usd_count = 0;
+
+int LEX_create_index = 0;
+Boolean LEX_binary_index = false;
+
+PRIVATE Boolean in_comment = 0;
+
+#define ZEROSTR  "\0"
+#define DBLSLASH "// "
+
+#define SRC(s) { if (fpsrc) { fprintf(fpsrc,"%s%s ",s,yytext); } }
+#define ZSRC   SRC(ZEROSTR)
+#define NEWLINE  { if (fpsrc) { fprintf(fpsrc,"\n%s",in_comment ? DBLSLASH : ZEROSTR); } }
+
+PUBLIC  int ODB_lineno = 1;
+
+PRIVATE int first_time = 1;
+
+#define NSTATE_STACK_DEPTH 32
+PRIVATE int state[NSTATE_STACK_DEPTH] = { 0 };
+PRIVATE int *p_state = state;
+
+#ifdef FLEX_SCANNER
+/* Specific to flex scanner */
+#define MAX_INCLUDE_DEPTH NSTATE_STACK_DEPTH
+PRIVATE YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+PRIVATE int include_stack_ptr = 0;
+#endif
+
+/* Protos only here */
+
+PRIVATE void LEX_next_state(int next);
+PUBLIC void LEX_prev_state();
+PRIVATE void LEX_all_states(FILE *fp);
+PUBLIC void LEX_print_state(FILE *fp);
+PUBLIC FILE *LEX_open_include(const char *filename);
+PUBLIC void LEX_close_include();
+PUBLIC double Atof(char *s);
+
+%}
+
+%p 30000
+%a 15000
+%n 5000
+%e 7000
+%o 8000
+%k 2500
+
+%s LEX_NORMAL
+%s LEX_INCLUDE
+%s LEX_SET
+%s LEX_TYPE
+%s LEX_TABLE
+%s LEX_VIEW
+%s LEX_FROM
+%s LEX_ORDERBY
+%s LEX_EXCLUDED_BY_IFDEF
+%s LEX_ALIGN
+%s LEX_USING
+
+Number	((([0-9]+)|([0-9]*\.([0-9]+)?))([eEdD][-+]?[0-9]+)?)
+Name	[_ at A-Za-z]([@\._A-Za-z0-9]*)([#][_]?[0-9]+)?
+USDName	[$](([_A-Za-z0-9]+\.[_A-Za-z0-9]+[#])|([_A-Za-z0-9]*([#])?))
+HASHName [#][_A-Za-z0-9]+
+BSnum   [\\][0-9]+
+String	((\"[^"\n]*\")|(\'[^'\n]*\')|(\{[^\}\n]*\}))
+OptLevel [ \t]*[/][/][ \t]*[\@]OPT[ \t]*=[ \t]*[0-9]*[ \t]*[\n]
+Comment  (([/][/].*)|([-][-][ \t]).*)[\n]
+Define  [#][ \t]*define[ \t]+[_A-Za-z0-9]*[ \t]*[0-9]*[ \t]*[\n]
+Undef   [#][ \t]*undef[ \t]+[_A-Za-z0-9]*[ \t]*[0-9]*[ \t]*[\n]
+Ifdef   [#][ \t]*ifdef[ \t]+[_A-Za-z0-9]*[ \t]*[\n]
+Ifndef  [#][ \t]*ifndef[ \t]+[_A-Za-z0-9]*[ \t]*[\n]
+Endif   [#][ \t]*endif[ \t]*.*[\n]
+Include ([#][ \t]*include)|(INCLUDE)|(include)
+
+%%
+
+%{
+	if (first_time) {
+   	  /* LEX_all_states(stderr); */
+	  LEX_next_state(LEX_NORMAL);
+	  first_time = 0;
+	}
+
+%}
+
+\n		{ ODB_lineno++; NEWLINE; }
+
+^[ \t]*\n	{ ODB_lineno++; }
+
+[ \t]+	;
+
+^{Ifdef}	{
+			double value = ODB_get_define(yytext);
+			ODB_lineno++; 
+			if (value == 0) {
+				LEX_next_state(LEX_EXCLUDED_BY_IFDEF);
+				/* if (verbose) fprintf(stderr,"==> Entering %s",yytext); */
+			}
+			/* if (fpsrc) fprintf(fpsrc,"// %s",yytext); */
+		}
+
+^{Ifndef}	{
+			double value = ODB_get_define(yytext);
+			ODB_lineno++; 
+			if (value != 0) {
+				LEX_next_state(LEX_EXCLUDED_BY_IFDEF);
+				/* if (verbose) fprintf(stderr,"==> Entering %s",yytext); */
+			}
+			/* if (fpsrc) fprintf(fpsrc,"// %s",yytext); */
+		}
+
+^{Endif}	{
+			/* if (fpsrc) fprintf(fpsrc,"// %s",yytext); */
+			ODB_lineno++; 
+			if (*p_state == LEX_EXCLUDED_BY_IFDEF) {
+				/* if (verbose) fprintf(stderr,"==> Leaving %s",yytext); */
+				LEX_prev_state();
+			}
+		}
+
+<LEX_EXCLUDED_BY_IFDEF>.*[\n] {
+			/* if (fpsrc) fprintf(fpsrc,"//!!! %s",yytext); */
+			ODB_lineno++; 
+		}
+
+^{Define}	{ 
+			char *p = strstr(yytext, "#define");
+			if (p) {
+			  p += 7;
+			  ODB_put_define(p,1);
+			}
+			ODB_lineno++; 
+		}
+
+^{Undef}	{ 
+			char *p = strstr(yytext, "#undef");
+			if (p) {
+			  p += 6;
+			  ODB_put_define(p,0);
+			}
+			ODB_lineno++; 
+		}
+
+";"		{ 
+		  Boolean do_newline = 1;
+		  if (	 *p_state == LEX_SET
+		      || *p_state == LEX_TYPE
+		      || *p_state == LEX_TABLE
+		      || *p_state == LEX_VIEW
+		      || *p_state == LEX_FROM
+		      || *p_state == LEX_ORDERBY
+		      || *p_state == LEX_ALIGN
+		      || *p_state == LEX_USING
+		      ) 
+		  { 
+			if (*p_state == LEX_SET) do_newline = 0;
+			LEX_prev_state();
+			if (*p_state == LEX_VIEW) LEX_prev_state();
+		  } 
+		  if (fpsrc) { 
+			ZSRC; 
+			if (do_newline) NEWLINE;
+			in_comment = 0; 
+		  }
+		  LEX_in_where = 0;
+		  return ODB_SEMICOLON;
+		}
+
+
+^{OptLevel}	{ 
+			char *p = strchr(yytext, '=');
+			if (p) optlevel = atoi(p+1);
+			optlevel = MAX(0,optlevel);
+			if (verbose) {
+			   fprintf(stderr,
+				"*** Warning: Optlevel = %d\n",optlevel);
+			}
+			ODB_lineno++; 
+		}
+
+{Comment}	{ 
+			if (fpsrc) fprintf(fpsrc,"%s%s",yytext,
+					   in_comment ? DBLSLASH : ZEROSTR);
+			ODB_lineno++; 
+		}
+
+<LEX_NORMAL>^{Include} {
+	LEX_next_state(LEX_INCLUDE);
+	/* LEX_print_state(stderr); */
+	SRC(DBLSLASH);
+	in_comment = 1;
+	return ODB_INCLUDE; }
+
+<LEX_NORMAL>SET |
+<LEX_NORMAL>set {
+	LEX_next_state(LEX_SET);
+	ZSRC;
+	return ODB_SET; }
+
+READONLY	|
+readonly	{ ZSRC; return ODB_READONLY; }
+
+READ_ONLY	|
+read_only	{ ZSRC; return ODB_READONLY; }
+
+READ[ \t]*ONLY	|
+read[ \t]*only	{ ZSRC; return ODB_READONLY; }
+
+UPDATED		|
+updated		{ ZSRC; return ODB_UPDATED; }
+
+UPDATABLE	|
+updatable	{ ZSRC; return ODB_UPDATED; }
+
+<LEX_NORMAL>USING |
+<LEX_NORMAL>using |
+<LEX_NORMAL>USE   |
+<LEX_NORMAL>use   {
+  LEX_next_state(LEX_USING);
+  ZSRC; return ODB_USING; }
+
+<LEX_NORMAL>DATABASE |
+<LEX_NORMAL>database |
+<LEX_USING>DATABASE  |
+<LEX_USING>database  { ZSRC; return ODB_DATABASE; }
+
+<LEX_NORMAL>SRCPATH |
+<LEX_NORMAL>srcpath |
+<LEX_USING>SRCPATH  |
+<LEX_USING>srcpath  { ZSRC; return ODB_SRCPATH; }
+
+<LEX_NORMAL>DATAPATH |
+<LEX_NORMAL>datapath |
+<LEX_USING>DATAPATH  |
+<LEX_USING>datapath  { ZSRC; return ODB_DATAPATH; }
+
+<LEX_NORMAL>IDXPATH |
+<LEX_NORMAL>idxpath |
+<LEX_USING>IDXPATH  |
+<LEX_USING>idxpath  { ZSRC; return ODB_IDXPATH; }
+
+<LEX_NORMAL>POOLMASK |
+<LEX_NORMAL>poolmask |
+<LEX_USING>POOLMASK  |
+<LEX_USING>poolmask  { ZSRC; return ODB_POOLMASK; }
+
+<LEX_NORMAL>INDEX |
+<LEX_NORMAL>index |
+<LEX_USING>INDEX  |
+<LEX_USING>index  { ZSRC; LEX_binary_index = false; return ODB_INDEX; }
+
+<LEX_NORMAL>TEXT[ \t]*INDEX |
+<LEX_NORMAL>TEXT[ \t]*index |
+<LEX_NORMAL>text[ \t]*INDEX |
+<LEX_NORMAL>text[ \t]*index |
+<LEX_USING>TEXT[ \t]*INDEX  |
+<LEX_USING>TEXT[ \t]*index  |
+<LEX_USING>text[ \t]*INDEX  |
+<LEX_USING>text[ \t]*index  { ZSRC; LEX_binary_index = false; return ODB_INDEX; }
+
+<LEX_NORMAL>BINARY[ \t]*INDEX |
+<LEX_NORMAL>BINARY[ \t]*index |
+<LEX_NORMAL>binary[ \t]*INDEX |
+<LEX_NORMAL>binary[ \t]*index |
+<LEX_USING>BINARY[ \t]*INDEX  |
+<LEX_USING>BINARY[ \t]*index  |
+<LEX_USING>binary[ \t]*INDEX  |
+<LEX_USING>binary[ \t]*index  { ZSRC; LEX_binary_index = true; return ODB_INDEX; }
+
+<LEX_NORMAL>NO[ \t]*INDEX |
+<LEX_NORMAL>NO[ \t]*index |
+<LEX_NORMAL>no[ \t]*index |
+<LEX_NORMAL>no[ \t]*INDEX { ZSRC; return ODB_NOINDEX; }
+
+<LEX_NORMAL>REORDER |
+<LEX_NORMAL>reorder { ZSRC; return ODB_REORDER; }
+
+<LEX_NORMAL>NO[ \t]*REORDER |
+<LEX_NORMAL>NO[ \t]*reorder |
+<LEX_NORMAL>no[ \t]*reorder |
+<LEX_NORMAL>no[ \t]*REORDER { ZSRC; return ODB_NOREORDER; }
+
+<LEX_NORMAL>INSERT |
+<LEX_NORMAL>insert { ZSRC; return ODB_INSERT; }
+
+<LEX_NORMAL>NO[ \t]*INSERT |
+<LEX_NORMAL>NO[ \t]*insert |
+<LEX_NORMAL>no[ \t]*insert |
+<LEX_NORMAL>no[ \t]*INSERT { ZSRC; return ODB_NOINSERT; }
+
+<LEX_NORMAL>SAFE[ \t]*GUARD |
+<LEX_NORMAL>SAFE[ \t]*guard |
+<LEX_NORMAL>safe[ \t]*GUARD |
+<LEX_NORMAL>safe[ \t]*guard { ZSRC; return ODB_SAFEGUARD; }
+
+<LEX_NORMAL>NO[ \t]*SAFE[ \t]*GUARD |
+<LEX_NORMAL>NO[ \t]*SAFE[ \t]*guard |
+<LEX_NORMAL>NO[ \t]*safe[ \t]*GUARD |
+<LEX_NORMAL>NO[ \t]*safe[ \t]*guard { ZSRC; return ODB_NOSAFEGUARD; }
+
+<LEX_NORMAL>no[ \t]*SAFE[ \t]*GUARD |
+<LEX_NORMAL>no[ \t]*SAFE[ \t]*guard |
+<LEX_NORMAL>no[ \t]*safe[ \t]*GUARD |
+<LEX_NORMAL>no[ \t]*safe[ \t]*guard { ZSRC; return ODB_NOSAFEGUARD; }
+
+<LEX_NORMAL>RESET	|
+<LEX_NORMAL>reset	{
+  LEX_next_state(LEX_ALIGN);
+  ZSRC; return ODB_RESET; }
+
+<LEX_NORMAL>ALIGN	|
+<LEX_NORMAL>align	{ 
+  LEX_next_state(LEX_ALIGN);
+  ZSRC; return ODB_ALIGN; }
+
+<LEX_ALIGN>ALIGN	|
+<LEX_ALIGN>align	{ 
+  ZSRC; return ODB_ALIGN; }
+
+<LEX_NORMAL>ONELOOPER	|
+<LEX_NORMAL>onelooper	{ 
+  LEX_next_state(LEX_ALIGN);
+  ZSRC; return ODB_ONELOOPER; }
+
+<LEX_ALIGN>ONELOOPER	|
+<LEX_ALIGN>onelooper	{ 
+  ZSRC; return ODB_ONELOOPER; }
+
+<LEX_NORMAL>SHAREDLINK	|
+<LEX_NORMAL>sharedlink	{ 
+  LEX_next_state(LEX_ALIGN);
+  ZSRC; return ODB_SHAREDLINK; }
+
+<LEX_ALIGN>SHAREDLINK	|
+<LEX_ALIGN>sharedlink	{ 
+  ZSRC; return ODB_SHAREDLINK; }
+
+<LEX_NORMAL>CREATE[ \t]*TYPE |
+<LEX_NORMAL>CREATE[ \t]*type |
+<LEX_NORMAL>create[ \t]*TYPE |
+<LEX_NORMAL>create[ \t]*type |
+<LEX_NORMAL>typedef	       |
+<LEX_NORMAL>TYPEDEF	       {
+	LEX_next_state(LEX_TYPE);
+	ZSRC;
+	return ODB_TYPE; }
+
+<LEX_NORMAL>CREATE[ \t]*TABLE |
+<LEX_NORMAL>CREATE[ \t]*table |
+<LEX_NORMAL>create[ \t]*TABLE |
+<LEX_NORMAL>create[ \t]*table {
+	LEX_next_state(LEX_TABLE);
+	ZSRC;
+	return ODB_TABLE; }
+
+<LEX_TABLE>TYPE[ \t]*OF |
+<LEX_TABLE>TYPE[ \t]*of |
+<LEX_TABLE>type[ \t]*of |
+<LEX_TABLE>type[ \t]*OF { 
+		 ZSRC;
+		 return ODB_TYPEOF;  }
+
+<LEX_NORMAL>CREATE[ \t]*VIEW |
+<LEX_NORMAL>CREATE[ \t]*view |
+<LEX_NORMAL>create[ \t]*VIEW |
+<LEX_NORMAL>create[ \t]*view {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	return ODB_VIEW; }
+
+<LEX_NORMAL>DROP[ \t]*INDEX |
+<LEX_NORMAL>DROP[ \t]*index |
+<LEX_NORMAL>drop[ \t]*INDEX |
+<LEX_NORMAL>drop[ \t]*index {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	LEX_create_index = -1; /* DROP INDEX [a quick hack] */
+	return ODB_DROPINDEX; }
+
+<LEX_NORMAL>CREATE[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*index |
+<LEX_NORMAL>create[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*index {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	LEX_create_index = 1; /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+	return ODB_CREATEINDEX; }
+
+<LEX_NORMAL>CREATE[ \t]*UNIQUE[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*UNIQUE[ \t]*index |
+<LEX_NORMAL>create[ \t]*UNIQUE[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*UNIQUE[ \t]*index |
+<LEX_NORMAL>CREATE[ \t]*unique[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*unique[ \t]*index |
+<LEX_NORMAL>create[ \t]*unique[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*unique[ \t]*index {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	LEX_create_index = 1; /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+	return ODB_CREATEINDEX; }
+
+<LEX_NORMAL>CREATE[ \t]*DISTINCT[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*DISTINCT[ \t]*index |
+<LEX_NORMAL>create[ \t]*DISTINCT[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*DISTINCT[ \t]*index |
+<LEX_NORMAL>CREATE[ \t]*distinct[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*distinct[ \t]*index |
+<LEX_NORMAL>create[ \t]*distinct[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*distinct[ \t]*index {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	LEX_create_index = 1; /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+	return ODB_CREATEINDEX; }
+
+<LEX_NORMAL>CREATE[ \t]*BITMAP[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*BITMAP[ \t]*index |
+<LEX_NORMAL>create[ \t]*BITMAP[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*BITMAP[ \t]*index |
+<LEX_NORMAL>CREATE[ \t]*bitmap[ \t]*INDEX |
+<LEX_NORMAL>CREATE[ \t]*bitmap[ \t]*index |
+<LEX_NORMAL>create[ \t]*bitmap[ \t]*INDEX |
+<LEX_NORMAL>create[ \t]*bitmap[ \t]*index {
+	LEX_next_state(LEX_VIEW);
+	SRC(DBLSLASH);
+	in_comment = 1;
+	LEX_create_index = 2; /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+	return ODB_CREATEINDEX; }
+
+<LEX_VIEW>"("[ \t]*SELECT |
+<LEX_VIEW>"("[ \t]*select { ZSRC; return ODB_SELECT; /* sub-query */ }
+
+<LEX_VIEW>QUERY[ \t]*"(" |
+<LEX_VIEW>query[ \t]*"(" { ZSRC; return ODB_QUERY; /* sub-query */ }
+
+<LEX_VIEW>MATCH[ \t]*"(" |
+<LEX_VIEW>match[ \t]*"(" { ZSRC; return ODB_MATCH; /* match-keyword */ }
+
+<LEX_NORMAL>RETURN |
+<LEX_NORMAL>return |
+<LEX_NORMAL>QUIT |
+<LEX_NORMAL>quit |
+<LEX_NORMAL>EXIT |
+<LEX_NORMAL>exit { SRC(DBLSLASH); return ODB_EXIT; }
+
+<LEX_NORMAL>SELECT[ \t]*UNIQUE    |
+<LEX_NORMAL>SELECT[ \t]*unique    |
+<LEX_NORMAL>select[ \t]*unique    |
+<LEX_NORMAL>select[ \t]*UNIQUE    |
+<LEX_NORMAL>SELECT[ \t]*DISTINCT  |
+<LEX_NORMAL>SELECT[ \t]*distinct  |
+<LEX_NORMAL>select[ \t]*distinct  |
+<LEX_NORMAL>select[ \t]*DISTINCT  { 
+	LEX_next_state(LEX_VIEW);			
+	ZSRC; 
+	return ODB_SELECT_DISTINCT; }
+
+<LEX_VIEW>SELECT[ \t]*UNIQUE	  |
+<LEX_VIEW>SELECT[ \t]*unique	  |
+<LEX_VIEW>select[ \t]*unique	  |
+<LEX_VIEW>select[ \t]*UNIQUE	  |
+<LEX_VIEW>SELECT[ \t]*DISTINCT  |
+<LEX_VIEW>SELECT[ \t]*distinct  |
+<LEX_VIEW>select[ \t]*distinct  |
+<LEX_VIEW>select[ \t]*DISTINCT  { 
+	ZSRC; 
+	return ODB_SELECT_DISTINCT; }
+
+<LEX_NORMAL>SELECT[ \t]*ALL	|
+<LEX_NORMAL>select[ \t]*all	|
+<LEX_NORMAL>select[ \t]*ALL	|
+<LEX_NORMAL>SELECT[ \t]*all	|
+<LEX_NORMAL>SELECT		|
+<LEX_NORMAL>select		{
+	LEX_next_state(LEX_VIEW);			
+	ZSRC; 
+	return ODB_SELECT_ALL; }
+
+<LEX_VIEW>SELECT[ \t]*ALL	|
+<LEX_VIEW>select[ \t]*all	|
+<LEX_VIEW>select[ \t]*ALL	|
+<LEX_VIEW>SELECT[ \t]*all	|
+<LEX_VIEW>SELECT		|
+<LEX_VIEW>select		{
+	ZSRC; 
+	return ODB_SELECT_ALL; }
+
+<LEX_VIEW>FROM			|
+<LEX_VIEW>from			{ 
+	LEX_next_state(LEX_FROM);			
+	ZSRC;
+	return ODB_FROM; }
+
+<LEX_VIEW>ON			|
+<LEX_VIEW>on			{ 
+  /* Later: Build safeguards here against using 'ON table' elsewhere than with CREATE [UNIQUE|BITMAP] INDEX */
+	LEX_next_state(LEX_FROM);			
+	ZSRC;
+	return ODB_ON; }
+
+<LEX_FROM>WHERE			|
+<LEX_FROM>where			{ 
+	LEX_prev_state(); /* back to LEX_VIEW */
+	LEX_in_where = 1;
+	LEX_auto_usd_count = 0;
+        ZSRC; 
+	return ODB_WHERE; }
+
+<LEX_VIEW>WHERE			|
+<LEX_VIEW>where			{ 
+	LEX_in_where = 1;
+	LEX_auto_usd_count = 0;
+        ZSRC; 
+	return ODB_WHERE; }
+
+<LEX_VIEW>UNIQUE[ \t]*BY	|
+<LEX_VIEW>UNIQUE[ \t]*by	|
+<LEX_VIEW>unique[ \t]*by	|
+<LEX_VIEW>unique[ \t]*BY	{ ZSRC; return ODB_UNIQUEBY; }
+
+<LEX_VIEW>DISTINCT[ \t]*BY	|
+<LEX_VIEW>DISTINCT[ \t]*by	|
+<LEX_VIEW>distinct[ \t]*by	|
+<LEX_VIEW>distinct[ \t]*BY	{ ZSRC; return ODB_UNIQUEBY; }
+
+<LEX_VIEW>DISTINCT              |
+<LEX_VIEW>distinct              |
+<LEX_VIEW>UNIQUE                |
+<LEX_VIEW>unique                {
+	ZSRC; 
+	return ODB_DISTINCT;    }
+
+<LEX_VIEW>ORDER[ \t]*BY	|
+<LEX_VIEW>ORDER[ \t]*by	|
+<LEX_VIEW>order[ \t]*by	|
+<LEX_VIEW>order[ \t]*BY	|
+<LEX_VIEW>SORT[ \t]*BY	|
+<LEX_VIEW>SORT[ \t]*by	|
+<LEX_VIEW>sort[ \t]*by  	|
+<LEX_VIEW>sort[ \t]*BY  	{ 
+	LEX_next_state(LEX_ORDERBY);			
+        ZSRC;
+	return ODB_ORDERBY; }
+
+<LEX_FROM>ORDER[ \t]*BY	|
+<LEX_FROM>ORDER[ \t]*by	|
+<LEX_FROM>order[ \t]*by	|
+<LEX_FROM>order[ \t]*BY	|
+<LEX_FROM>SORT[ \t]*BY	|
+<LEX_FROM>SORT[ \t]*by	|
+<LEX_FROM>sort[ \t]*by  	|
+<LEX_FROM>sort[ \t]*BY  	{ 
+	LEX_prev_state(); /* back to LEX_VIEW */
+	LEX_next_state(LEX_ORDERBY);			
+        ZSRC;
+	return ODB_ORDERBY; }
+
+<LEX_VIEW>AND			| 
+<LEX_VIEW>and			| 
+<LEX_VIEW>"&&"			{ ZSRC; return ODB_AND; }
+
+<LEX_VIEW>"|"			{ ZSRC; return ODB_NORM; }
+
+<LEX_VIEW>OR			| 
+<LEX_VIEW>or			| 
+<LEX_VIEW>"||"			{ ZSRC; return ODB_OR; }
+
+<LEX_VIEW>BETWEEN		|
+<LEX_VIEW>between		{ ZSRC; return ODB_BETWEEN; }
+
+<LEX_VIEW>"!~"		|
+<LEX_VIEW>NOT[ \t]*LIKE	|
+<LEX_VIEW>NOT[ \t]*like	|
+<LEX_VIEW>not[ \t]*LIKE	|
+<LEX_VIEW>not[ \t]*like	{ ZSRC; return ODB_NOTLIKE; }
+
+<LEX_VIEW>"=~"			|
+<LEX_VIEW>LIKE			|
+<LEX_VIEW>like			{ ZSRC; return ODB_LIKE; }
+
+<LEX_VIEW>NOT[ \t]*RLIKE	|
+<LEX_VIEW>NOT[ \t]*rlike	|
+<LEX_VIEW>not[ \t]*RLIKE	|
+<LEX_VIEW>not[ \t]*rlike	{ ZSRC; return ODB_NOTLIKE; }
+
+<LEX_VIEW>RLIKE			|
+<LEX_VIEW>rlike			{ ZSRC; return ODB_LIKE; }
+
+<LEX_VIEW>NEAR[ \t]*"("		|
+<LEX_VIEW>near[ \t]*"("		{ ZSRC; return ODB_NEAR; }
+
+<LEX_VIEW>INSIDE[ \t]*"("	|
+<LEX_VIEW>inside[ \t]*"("	{ ZSRC; return ODB_INSIDE; }
+
+<LEX_VIEW>IN[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>in[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>IN[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>in[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>INSIDE[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>inside[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>INSIDE[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>inside[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>POLYGON[ \t]*"("		|
+<LEX_VIEW>polygon[ \t]*"("		{ ZSRC; return ODB_INSIDE_POLYGON; }
+
+<LEX_VIEW>NOT[ \t]*INSIDE[ \t]*"(" |
+<LEX_VIEW>not[ \t]*inside[ \t]*"(" |
+<LEX_VIEW>NOT[ \t]*inside[ \t]*"(" |
+<LEX_VIEW>not[ \t]*INSIDE[ \t]*"(" |
+<LEX_VIEW>"!"[ \t]*INSIDE[ \t]*"(" |
+<LEX_VIEW>"!"[ \t]*inside[ \t]*"(" |
+<LEX_VIEW>OUTSIDE[ \t]*"("	   |
+<LEX_VIEW>outside[ \t]*"("	   { ZSRC; return ODB_OUTSIDE; }
+
+<LEX_VIEW>NOT[ \t]*IN[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*in[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*IN[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*in[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>not[ \t]*IN[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>not[ \t]*in[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>not[ \t]*IN[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>not[ \t]*in[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*INSIDE[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*inside[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*INSIDE[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*inside[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>not[ \t]*INSIDE[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>not[ \t]*inside[ \t]*POLYGON[ \t]*"("	|
+<LEX_VIEW>not[ \t]*INSIDE[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>not[ \t]*inside[ \t]*polygon[ \t]*"("	|
+<LEX_VIEW>NOT[ \t]*POLYGON[ \t]*"(" |
+<LEX_VIEW>not[ \t]*polygon[ \t]*"(" |
+<LEX_VIEW>NOT[ \t]*polygon[ \t]*"(" |
+<LEX_VIEW>not[ \t]*POLYGON[ \t]*"(" |
+<LEX_VIEW>OUTSIDE[ \t]*POLYGON[ \t]*"(" |
+<LEX_VIEW>outside[ \t]*polygon[ \t]*"(" |
+<LEX_VIEW>OUTSIDE[ \t]*polygon[ \t]*"(" |
+<LEX_VIEW>outside[ \t]*POLYGON[ \t]*"(" |
+<LEX_VIEW>"!"[ \t]*POLYGON[ \t]*"(" |
+<LEX_VIEW>"!"[ \t]*polygon[ \t]*"(" { ZSRC; return ODB_OUTSIDE_POLYGON; }
+
+<LEX_VIEW>"<=>"			{ ZSRC; return ODB_CMP; }
+
+<LEX_VIEW>"="[ \t]*{String}  |
+<LEX_VIEW>"=="[ \t]*{String} |
+<LEX_VIEW>"<>"[ \t]*{String} |
+<LEX_VIEW>"!="[ \t]*{String} |
+<LEX_VIEW>"/="[ \t]*{String} {
+  /* Either "string" or 'string' or {string}' */
+  char quote = 0;
+  char *p = yytext;
+  char *oper = NULL;
+  ZSRC; 
+  while (*p) {
+    if (*p == '"' || *p == '\'' || *p == '{') {
+      quote = *p;
+      if (quote == '{') quote = '}';
+      break;
+    }
+    ++p;
+  }
+  yylval.str = STRDUP(p); /* Open quote included; will be replaced with char '1' or '0' */
+  {
+    char *close_quote = strchr(yylval.str+1,quote);    
+    if (!close_quote) {
+      YYerror("Unterminated string");
+    } else {
+      *close_quote = '\0'; /* remove close quote */
+      *p = '\0';
+      oper = STRDUP(yytext);
+      p = strchr(oper,' ');
+      if (!p) p = strchr(oper,'\t');
+      if (p) *p = '\0';
+      if (strequ(oper,"==") || strequ(oper,"=")) *yylval.str = '1';
+      else *yylval.str = '0';
+    }
+  }
+  return ODB_EQNE_STRING;
+}
+
+<LEX_VIEW>"<>"		| 
+<LEX_VIEW>"!="		|
+<LEX_VIEW>"/="		{ ZSRC; return ODB_NE; }
+
+<LEX_VIEW>"="		|
+<LEX_VIEW>"=="		{ ZSRC; return ODB_EQ; }
+
+<LEX_VIEW>">"		{ ZSRC; return ODB_GT; }
+<LEX_VIEW>"<"		{ ZSRC; return ODB_LT; }
+<LEX_VIEW>">="		{ ZSRC; return ODB_GE; }
+<LEX_VIEW>"<="		{ ZSRC; return ODB_LE; }
+
+<LEX_VIEW>NOT[ \t]*IN[ \t]*FILE	|
+<LEX_VIEW>NOT[ \t]*in[ \t]*FILE	|
+<LEX_VIEW>NOT[ \t]*IN[ \t]*file	|
+<LEX_VIEW>NOT[ \t]*in[ \t]*file	|
+<LEX_VIEW>not[ \t]*IN[ \t]*FILE	|
+<LEX_VIEW>not[ \t]*in[ \t]*FILE	|
+<LEX_VIEW>not[ \t]*IN[ \t]*file	|
+<LEX_VIEW>not[ \t]*in[ \t]*file	|
+<LEX_VIEW>"!"[ \t]*IN[ \t]*FILE	|
+<LEX_VIEW>"!"[ \t]*IN[ \t]*file	|
+<LEX_VIEW>"!"[ \t]*in[ \t]*FILE	|
+<LEX_VIEW>"!"[ \t]*in[ \t]*file	{ ZSRC; return ODB_NOTINFILE; }
+
+<LEX_VIEW>NOT[ \t]*IN |
+<LEX_VIEW>NOT[ \t]*in |
+<LEX_VIEW>not[ \t]*in |
+<LEX_VIEW>not[ \t]*IN |
+<LEX_VIEW>"!"[ \t]*IN	|
+<LEX_VIEW>"!"[ \t]*in	{ ZSRC; return ODB_NOTIN; }
+
+<LEX_VIEW>IN[ \t]*FILE	|
+<LEX_VIEW>IN[ \t]*file	|
+<LEX_VIEW>in[ \t]*FILE	|
+<LEX_VIEW>in[ \t]*file	{ ZSRC; return ODB_INFILE; }
+
+<LEX_VIEW>IN		|
+<LEX_VIEW>in		{ ZSRC; return ODB_IN; }
+
+<LEX_VIEW>"!" |
+<LEX_VIEW>NOT |
+<LEX_VIEW>not	{ ZSRC; return ODB_NOT; }
+
+<LEX_ORDERBY>ASC	|
+<LEX_ORDERBY>asc	{ ZSRC; return ODB_ASC; }
+
+<LEX_ORDERBY>DESC	|
+<LEX_ORDERBY>desc	{ ZSRC; return ODB_DESC; }
+
+<LEX_ORDERBY>ABS	|
+<LEX_ORDERBY>abs	{ ZSRC; return ODB_ABS; }
+
+<LEX_VIEW>IS		|
+<LEX_VIEW>is		{ ZSRC; return ODB_IS; }
+
+<LEX_VIEW>NULL		|
+<LEX_VIEW>null		{ ZSRC; return ODB_NULL; }
+
+<LEX_VIEW>[?]		{ 
+  int rc = LEX_in_where ? ODB_USDNAME : ODB_QMARK;
+  if (LEX_in_where) {
+    ODB_Symbol *psym = NULL;
+    char *auto_usd = NULL;
+    ALLOC(auto_usd,20);
+    sprintf(auto_usd,"$%d",++LEX_auto_usd_count);
+    psym = ODB_lookup(ODB_USDNAME,auto_usd,NULL);
+    if (!psym) {
+      const double auto_value = 0;
+      psym = ODB_new_symbol(ODB_USDNAME,auto_usd);
+      psym->dval = auto_value;
+    }
+    yylval.str = STRDUP(auto_usd);
+    FREE(auto_usd);
+  }
+  ZSRC;
+  return rc;
+}
+
+AS  |
+as  { ZSRC; return ODB_AS; }
+
+":" { ZSRC; return ODB_COLON; }
+
+"[" { ZSRC; return ODB_LB; }
+"]" { ZSRC; return ODB_RB; }
+
+"(" { ZSRC; return ODB_LP; }
+")" { ZSRC; return ODB_RP; }
+
+"," { ZSRC; return ODB_COMMA; }
+
+"**" | 
+"^" { ZSRC; return ODB_POWER; }
+
+"=" { ZSRC; return ODB_EQ; }
+"+" { ZSRC; return ODB_ADD; }
+"-" { ZSRC; return ODB_SUB; }
+
+<LEX_VIEW>".*" { ZSRC; return ODB_DOTP; }
+
+"*" { ZSRC; return ODB_STAR; }
+"/" { ZSRC; return ODB_DIV; }
+"%" { ZSRC; return ODB_MODULO; }
+
+{String}	{ /* Either "string" or 'string' or {string} */
+		  char quote = yytext[0];
+		  if (quote == '{') quote = '}';
+		  ZSRC; 
+		  yylval.str = STRDUP(yytext+1); /* skip open quote */
+		  if (yytext[yyleng-1] != quote) {
+			YYerror("Unterminated string");
+		  } else  
+			yylval.str[yyleng-2] = '\0';  /* remove close quote */
+		  /*
+		  if (strlen(yylval.str) != 8) {
+			YYerror("String length not equal to 8");
+		  }
+		  */
+		  return ODB_STRING;
+		}
+
+{Name}		{ /* A pure symbol (can be a case-sensitive define);
+		     ODB_lowercase will do the STRDUP() as well */
+		  ZSRC; 
+		  yylval.str = ODB_has_define(yytext) ? STRDUP(yytext) : ODB_lowercase(yytext);
+		  return ODB_NAME;
+		}
+
+{USDName}	{ /* A symbol starting with a dollar;  
+		     ODB_lowercase will do the STRDUP() as well */
+		  ZSRC; 
+		  yylval.str = ODB_lowercase(yytext);
+		  return ODB_USDNAME;
+		}
+
+{HASHName}	{ /* A symbol starting with a hash (#);  
+		     ODB_lowercase will do the STRDUP() as well */
+		  ZSRC; 
+		  yylval.str = ODB_lowercase(yytext);
+		  return ODB_HASHNAME;
+		}
+
+<LEX_VIEW>{BSnum} { /* A symbol starting with backslash (\) and followed by an integer number.
+		       Only valid in WHERE-statements (and denotes column# from sub-query outputs) */
+		    ZSRC;
+		    if (LEX_in_where) {
+		      yylval.str = STRDUP(yytext);
+		    }
+		    else {
+		      SETMSG1("Variable '%s' can be used only in WHERE-stmt",yytext);
+		      YYerror(msg);
+		    }
+		    return ODB_BSNUM;
+		  }
+
+{Number}([hH][pP][aA]|[ \t]+[hH][pP][aA][ \t\n]+) { /* Hecto-Pascals to Pascals (hPa) (case doesn't matter) */
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  yylval.dval = 100*Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER; 
+		}
+
+{Number}([mM][bB][aA][rR]|[ \t]+[mM][bB][aA][rR][ \t\n]+) { /* mbar's to Pascals (case doesn't matter) */
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  yylval.dval = 100*Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER; 
+		}
+
+{Number}([wWsS]|[ \t]+[wWsS][ \t\n]+) { /* longitude west or latitude south (case doesn't matter) */
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  yylval.dval = -Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER; 
+		}
+
+{Number}([eEnN]|[ \t]+[eEnN][ \t\n]+) { /* longitude east or latitude north (case doesn't matter) */
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  yylval.dval = +Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER; 
+		}
+
+{Number}(C|[ \t]+C[ \t\n]+)	{ /* Celsius (Capital "C" at the end) */
+		  double celsius;
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  celsius = Atof(yytext);
+		  /* Remember the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 1;
+		  LEX_unconv_value = celsius;
+		  yylval.dval = celsius + ZERO_POINT; /* Value is now in Kelvin */
+		  return ODB_NUMBER; 
+		}
+
+{Number}(F|[ \t]+F[ \t\n]+) { /* Fahrenheit (Capital "F" at the end) */
+		  double fahrenheit, celsius;
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  fahrenheit = Atof(yytext);
+		  /* Remember the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 2;
+		  LEX_unconv_value = fahrenheit;
+		  celsius = ((fahrenheit - 32)*5)/9;
+		  yylval.dval = celsius + ZERO_POINT; /* Value is now in Kelvin */
+		  return ODB_NUMBER; 
+		}
+
+{Number}(K|[ \t]+K[ \t\n]+) { /* Kelvin (Capital "K" at the end) ; 
+		     just for convenience; no conversions performed */
+		  ZSRC; 
+		  yytext[strlen(yytext)-1] = '\0';
+		  yylval.dval = Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER;  /* Value is now in Kelvin */
+		}
+
+{Number}(km|[ \t]+km[ \t\n]+) { /* Kilometres (lowercase "km") */
+		     ZSRC; 
+		     yytext[strlen(yytext)-1] = '\0';
+		     yylval.dval = 1000 * Atof(yytext);
+		     /* Reset the latest conversion (in case of unary-minus) */
+		     LEX_convflag = 0;
+		     LEX_unconv_value = 0;
+		     return ODB_NUMBER;  /* Value is now in metres */
+		   }
+
+{Number}(miles|[ \t]+miles[ \t\n]+) { /* Kilometres (lowercase word "miles") */
+		     ZSRC; 
+		     yytext[strlen(yytext)-1] = '\0';
+		     yylval.dval = ((double)1609.34e0) * Atof(yytext);
+		     /* Reset the latest conversion (in case of unary-minus) */
+		     LEX_convflag = 0;
+		     LEX_unconv_value = 0;
+		     return ODB_NUMBER;  /* Value is now in metres */
+		   }
+
+{Number}	{
+		  ZSRC; 
+		  yylval.dval = Atof(yytext);
+		  /* Reset the latest conversion (in case of unary-minus) */
+		  LEX_convflag = 0;
+		  LEX_unconv_value = 0;
+		  return ODB_NUMBER; 
+		}
+
+.		{ ZSRC; return yytext[0]; }
+
+%%
+
+PRIVATE void
+LEX_next_state(int next) {
+	BEGIN(next); 
+	/* fprintf(stderr,"==> Entering LEX_next_state(%d)\n",next); */
+	*++p_state = next; 
+	LEX_in_where = 0;
+}
+
+PUBLIC void
+LEX_prev_state() {
+	int lstate = *p_state;
+	if (lstate == LEX_INCLUDE && fpsrc) { in_comment = 0; NEWLINE;  }
+	p_state--; 
+	/* fprintf(stderr,"<== Leaving LEX_prev_state(): %d : %d\n",
+	           lstate, *p_state); */
+	LEX_in_where = 0;
+	BEGIN(*p_state); 
+}
+
+PRIVATE void
+LEX_all_states(FILE *fp)
+{
+	fprintf(fp,"*** LEX state numbers:\n");
+	fprintf(fp,"LEX_NORMAL            = %d\n",LEX_NORMAL);
+	fprintf(fp,"LEX_INCLUDE           = %d\n",LEX_INCLUDE);
+	fprintf(fp,"LEX_SET               = %d\n",LEX_SET);
+	fprintf(fp,"LEX_TYPE              = %d\n",LEX_TYPE);
+	fprintf(fp,"LEX_TABLE             = %d\n",LEX_TABLE);
+	fprintf(fp,"LEX_VIEW              = %d\n",LEX_VIEW);
+	fprintf(fp,"LEX_FROM              = %d\n",LEX_FROM);
+	fprintf(fp,"LEX_ORDERBY           = %d\n",LEX_ORDERBY);
+	fprintf(fp,"LEX_EXCLUDED_BY_IFDEF = %d\n",LEX_EXCLUDED_BY_IFDEF);
+}
+
+PUBLIC void 
+LEX_print_state(FILE *fp)
+{
+	int level = 0;
+	int *p = NULL;
+	LEX_all_states(fp);
+	do {
+	  p = &state[level];
+	  fprintf(fp,"LEX-state nesting level#%d : %d\n",level,*p);
+	  level++;
+	} while ( p != p_state && level < NSTATE_STACK_DEPTH );
+}
+
+PUBLIC FILE *
+LEX_open_include(const char *filename)
+{
+  FILE *fp = FOPEN(filename, "r");
+  int lineno = 0;
+
+  if (verbose) fprintf(stderr,"*** Including \"%s\"\n",filename);
+
+  if (!fp) {
+    SETMSG1("Can't open include-file '%s'",filename);
+    YYerror(msg);
+  }
+
+#ifdef FLEX_SCANNER
+  /* Specific to flex scanner */
+  if (include_stack_ptr >= MAX_INCLUDE_DEPTH) {
+    SETMSG1("Includes nested too deeply. Maximum depth = %d",MAX_INCLUDE_DEPTH);
+    YYerror(msg);
+  }
+  include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+#endif
+
+  lineno = ODB_lineno;
+  
+  ODB_pushFILE(yyin);
+  ODB_pushstr(odb_source);
+  ODB_pushi(lineno);
+  
+  yyin = fp;
+  odb_source = STRDUP(filename);
+  ODB_lineno = 1;
+  include_nesting++;
+
+#ifdef FLEX_SCANNER
+  /* Specific to flex scanner */
+  yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+  BEGIN(*p_state);
+#endif
+
+  return fp;
+}
+
+
+PUBLIC void
+LEX_close_include()
+{
+  FILE *tmp = yyin;
+  int lineno = ODB_popi();
+  extern int ODB_lineno;
+  
+  if (verbose) 
+    fprintf(stderr,"*** End of Include with \"%s\"***\n",odb_source);
+    
+  ODB_lineno = lineno;
+  odb_source = ODB_popstr();
+  yyin = ODB_popFILE();
+  
+  FCLOSE(tmp);
+
+  include_nesting--;
+
+#ifdef FLEX_SCANNER
+  /* Specific to flex scanner */
+  if ( --include_stack_ptr < 0 ) {
+    YYerror("Programming error: Include stack underflow");
+  }
+  else {
+    yy_delete_buffer(YY_CURRENT_BUFFER);
+    yy_switch_to_buffer(include_stack[include_stack_ptr]);
+  }
+#endif
+
+  if (verbose) 
+    fprintf(stderr,"*** Proceeding with \"%s\"***\n",odb_source);
+}
+
+
+PUBLIC
+double Atof(char *s) /* Modifies the argument (length unchanged) */
+{
+  double res = 0;
+  if (s) {
+    char *p = s;
+    while (*p) { if (*p == 'd' || *p == 'D') *p = 'e'; ++p; }
+    res = atof(s);
+  }
+  return res;
+}
+
+
+#undef yywrap
+
+PUBLIC 
+int yywrap(void) 
+{
+  int rc = 1; /* No more input to come */
+  if (include_nesting > 0) {
+    LEX_close_include();
+    rc = 0; /* There IS indeed more input to come */
+  } 
+  return rc;
+}
+
diff --git a/odb/src/compiler/list.c b/odb/src/compiler/list.c
new file mode 100644
index 0000000..03c6508
--- /dev/null
+++ b/odb/src/compiler/list.c
@@ -0,0 +1,219 @@
+#include "defs.h"
+
+static const char DELIM = '|';
+
+PRIVATE char *list = NULL;
+
+PUBLIC char *
+get_list()
+{
+  return list;
+}
+
+PUBLIC char
+get_list_delim()
+{
+  return DELIM;
+}
+
+PUBLIC int
+get_list_elemcount()
+{
+  int cnt = -1; /* "-1" since there is one less elements in the list than delimiters */
+  const char *p = list;
+  if (p) {
+    while (*p) {
+      if (*p == DELIM) cnt++;
+      p++;
+    }
+  }
+  return (cnt >= 0) ? cnt : 0;
+}
+
+PUBLIC void
+destroy_list()
+{
+  FREE(list);
+}
+
+
+PUBLIC char *
+init_list(const char *p)
+{
+  destroy_list();
+  if (p) {
+    ALLOC(list, strlen(p) + 3);
+    sprintf(list,"%c%s%c",DELIM,p,DELIM);
+  }
+  else {
+    ALLOC(list,2);
+    list[0] = DELIM;
+    list[1] = '\0';
+  }
+  return list;
+}
+
+
+PUBLIC Boolean 
+in_list(const char *p)
+{
+  Boolean found = 0;
+  if (list && p) {
+    char *token;
+    ALLOC(token, strlen(p) + 3);
+    sprintf(token,"%c%s%c",DELIM,p,DELIM);
+    found = (strstr(list, token) != NULL);
+    FREE(token);
+  }
+  return found;
+}
+
+
+PUBLIC Boolean 
+in_mylist(const char *p, const char *mylist, char delim)
+{
+  Boolean found = 0;
+  if (mylist && p && delim) {
+    char *token;
+    ALLOC(token, strlen(p) + 3);
+    sprintf(token,"%c%s%c",delim,p,delim);
+    found = (strstr(mylist, token) != NULL);
+    FREE(token);
+  }
+  return found;
+}
+
+
+PUBLIC Boolean 
+in_extlist(const char *p, const char *extlist)
+{
+  Boolean found = 0;
+  if (extlist && p) {
+    char *token;
+    ALLOC(token, strlen(p) + 3);
+    sprintf(token,"%c%s%c",DELIM,p,DELIM);
+    found = (strstr(extlist, token) != NULL);
+    FREE(token);
+  }
+  return found;
+}
+
+
+PUBLIC char *
+in_extlist1(const char *p, const char *extlist)
+{
+  char *found = NULL;
+  if (extlist && p) {
+    char *token;
+    char *first;
+    ALLOC(token, strlen(p) + 2);
+    sprintf(token,"%s%c",p,DELIM);
+    first = token;
+    found = strstr(extlist, token);
+    if (found) {
+      char *a;
+      char *f_start = found;
+      char *f_end;
+      while (*--f_start != DELIM);
+      f_start++;
+      a = f_end = STRDUP(f_start);
+      while (*f_end != *first) f_end++;
+      *f_end = '\0';
+      found = STRDUP(a); /* master name directly */
+      FREE(a);
+    }
+    FREE(token);
+  }
+  return found;
+}
+
+
+PUBLIC char *
+add_list(const char *p)
+{
+  if (!list) {
+    list = init_list(p);
+  }
+  else {
+    int lenp = STRLEN(p);
+    if (p && lenp > 0) {
+      char tmp[2];
+      int lenlist = strlen(list);
+      REALLOC(list, lenlist + lenp + 2);
+      strcat(list, p);
+      tmp[0] = DELIM; tmp[1] = '\0';
+      strcat(list, tmp);
+    }
+  }
+  return list;
+}
+
+
+PUBLIC ODB_linklist *
+manage_linklist(int function,
+		const char *lhs, const char *rhs, int type)
+{
+  static ODB_linklist *linklist = NULL;
+  ODB_linklist *retlist = NULL;
+
+  switch (function) {
+  case FUNC_LINKLIST_ADD:
+    if (lhs && rhs) {
+      ODB_linklist *plinklist;
+      if (!linklist) CALLOC(linklist,1); /* Start constructing it now */
+      plinklist = linklist;
+      while (plinklist) {
+	if (plinklist->n_rhs == 0 || 
+	    (plinklist->type == type && strequ(plinklist->lhs,lhs))) {
+	  if (plinklist->n_rhs == 0) { /* An empty slot */
+	    plinklist->type = type;
+	    plinklist->lhs = STRDUP(lhs);
+	    ALLOC(plinklist->rhs,1);
+	    plinklist->last_rhs = plinklist->rhs;
+	  }
+	  else { /* plinklist->type == type && strequ(plinklist->lhs,lhs) */
+	    ALLOC(plinklist->last_rhs->next,1);
+	    plinklist->last_rhs = plinklist->last_rhs->next;
+	  }
+	  plinklist->last_rhs->name = STRDUP(rhs);
+	  plinklist->last_rhs->next = NULL;
+	  plinklist->n_rhs++;
+	  retlist = plinklist;
+	  break;
+	}
+	if (!plinklist->next) CALLOC(plinklist->next,1);
+	plinklist = plinklist->next;
+      } /* while (plinklist) */
+    } /* if (lhs && rhs) */
+    break;
+
+  case FUNC_LINKLIST_START:
+    retlist = linklist;
+    break;
+
+  case FUNC_LINKLIST_QUERY:
+    if (lhs && rhs) {
+      ODB_linklist *plinklist = linklist;
+      while (plinklist) {
+	if (plinklist->n_rhs > 0 && 
+	    plinklist->type == type && strequ(plinklist->lhs,lhs)) {
+	  /* Loop over all rhs-(table)names */
+	  struct _rhs_t *first_rhs = plinklist->rhs;
+	  while (first_rhs) {
+	    if (strequ(first_rhs->name,rhs)) {
+	      retlist = plinklist;
+	      break;
+	    }
+	    first_rhs = first_rhs->next;
+	  } /* while (first_rhs) */
+	  break;
+	}
+	plinklist = plinklist->next;
+      } /* while (plinklist) */
+    } /* if (lhs && rhs) */
+    break;
+
+  } /* switch (function) */
+
+  return retlist;
+}
diff --git a/odb/src/compiler/odb98.c b/odb/src/compiler/odb98.c
new file mode 100644
index 0000000..b1723c0
--- /dev/null
+++ b/odb/src/compiler/odb98.c
@@ -0,0 +1,2121 @@
+#include "defs.h"
+#include "magicwords.h"
+#include "cdrhook.h"
+
+PRIVATE const char vers[] = "v2.12-Feb-2012";
+PRIVATE const char date_str[] = __DATE__;
+PRIVATE const char time_str[] = __TIME__;
+
+PRIVATE char *main_prog = NULL;
+
+#ifdef SGI
+#define SYSTEM_NAME "(Silicon Graphics)"
+#endif
+
+#ifdef VCCPX
+#if defined(VPP5000)
+#define SYSTEM_NAME "(Fujitsu VPP5000 [cross compiler])"
+#else
+#define SYSTEM_NAME "(Fujitsu VPP [cross compiler])"
+#endif
+#elif VPP5000
+#define SYSTEM_NAME "(Fujitsu VPP5000) [native]"
+#elif VPP
+#define SYSTEM_NAME "(Fujitsu VPP) [native]"
+#endif
+
+#if defined(NECSX)
+#define SYSTEM_NAME "(NEC SX series [cross compiler])"
+#endif
+
+#ifdef SUN4
+#define SYSTEM_NAME "(Sun/Solaris)"
+#endif
+
+#ifdef HPPA
+#define SYSTEM_NAME "(HP PA-Risc)"
+#endif
+
+#ifdef LINUX
+#if defined(NECTX)
+#define SYSTEM_NAME "(LINUX/NEC FRONT-END)"
+#elif defined(CYGWIN)
+#define SYSTEM_NAME "(WINDOWS/CYGWIN)"
+#elif defined(SUN4)
+#define SYSTEM_NAME "(Sun/Linux)"
+#elif defined(CRAYXT)
+#define SYSTEM_NAME "(Cray XT)"
+#else
+#define SYSTEM_NAME "(LINUX)"
+#endif
+#endif
+
+#ifdef ALPHA
+#define SYSTEM_NAME "(ALPHA)"
+#endif
+
+#ifdef RS6K
+#define SYSTEM_NAME "(IBM SP RS/6000 AIX)"
+#endif
+
+#ifndef SYSTEM_NAME
+#define SYSTEM_NAME "(Probably Intel or AMD)"
+#endif
+
+PRIVATE char system_name[] = SYSTEM_NAME; 
+
+int pcma_blocksize = 256;
+int pcma_restore_packed = 0;
+
+#define DEVNULL "/dev/null"
+FILE *fpdevnull = NULL;
+
+PRIVATE Boolean traceback_done = 0;
+
+int filtered_info = 0;
+int ddl_piped = 0;
+PRIVATE char *tmp_file = NULL;
+
+PRIVATE char *original_name = NULL;
+PRIVATE Boolean print_help = 0;
+PRIVATE Boolean views_only = 0;
+PRIVATE Boolean create_so = 1;
+PRIVATE Boolean check_syntax_only = 0;
+Boolean debug = 0;
+Boolean verbose = 0;
+PRIVATE Boolean print_version = 0;
+int optlevel = 3; /* this used to be 2 until 2-Mar-2006/SS; now we don't need to specify -O3 anymore */
+int genstatic = 0;
+int incremental = 0;
+int merge_table_indices = 0;
+int use_indices = 1; /* the default can be overridden via 'export ODB_USE_INDICES=0' in ksh */
+int reorder_tables = 1; /* the default can be overridden via 'export ODB_REORDER_TABLES=0' in ksh */
+int insert_tables = 1;  /* the default can be overridden via 'export ODB_INSERT_TABLES=0' in ksh */
+int Ccompile_Sstatic_stubb = 1;
+char *one_tables = NULL;
+int safeGuard = 0; /* the default can be overridden via 'export ODB_SAFEGUARD=1' in ksh */
+Boolean reset_align_issued = 0;
+Boolean reset_onelooper_issued = 0;
+Boolean readonly_mode = 0;
+Boolean insert_drhook = 1;
+int latlon_rad = -1; /* 
+			Assumptions about (lat,lon) [or $ODB_LAT / $ODB_LON]
+			Check value of environment $ODB_LATLON_RAD
+			-1 : Not initialized
+			 1 : (lat,lon) in radians
+			 0 : (lat,lon) in degrees
+			 This has impact on new functions 
+			 lat_degrees & lon_degrees  and
+			 lat_radians & lon_radians
+			 Instead of _radians/_degrees you can use _deg2rad/_rad2deg, too
+		     */
+
+char *bailout_string = NULL;
+int bailout_level = 0; /*
+			 -b               (bailout_level == -1)
+			 -B bailout_level
+
+			 To bail out from incorrect column or table names in SQL
+			 When set to -1 (via use of -B flag or export ODB_BAILOUT=-1, 
+			 bailout ([no]bailout) keyword in SQL), it means that :
+			 (1) Spelling mistakes in SELECT columns result 
+			     in substitution of a column into a formula zero ("0")
+			 (2) Spelling mistakes in formulas in SELECT columns
+			     lead to substitution of (formula) 0 (zero) inplace of a column
+			 (3) Incorrect table name in FROM statement lead to ignore 
+			     that table
+			 (4) Columns in UNIQUEBY are simply ignored
+			 (5) Columns in ORDERBY are ignored as in UNIQUEBY
+			 (6) Column variables in WHERE condition are substituted with zero.
+
+			 If you want other than "0", f.ex. NULL, set also the environment variable
+			 export ODB_BAILOUT_STRING='$mdi' for instance
+
+		       */
+
+PRIVATE Boolean empty_tables = 0;
+PRIVATE char *table_list = NULL;
+PRIVATE int n_table_list = 0;
+PRIVATE char delim_table_list = 0;
+PRIVATE char *sql_query = NULL;
+
+char *ARGH = NULL;
+
+FILE *fpsrc = NULL;
+int include_nesting = 0;
+char *odb_source = NULL;
+char *filter_cmd = NULL;
+char *odb_syspath = NULL;
+char *odb_outpath = NULL;
+char *odb_cc = NULL;
+char *odb_ld = NULL;
+char *odb_libs = NULL;
+char *odb_libs_keep = NULL;
+char *odb_label = NULL;
+
+#ifndef ODB_SYSPATH
+#define ODB_SYSPATH "."
+#endif
+
+PRIVATE void rm()
+{
+  if (tmp_file && is_regular_file_(tmp_file)) remove_file_(tmp_file);
+}
+
+PRIVATE void
+set_signals()
+{
+  static Boolean done = 0;
+  if (!done) {
+    signal(SIGBUS, ODB_sigexit);
+    signal(SIGSEGV, ODB_sigexit);
+    signal(SIGILL, ODB_sigexit);
+#if defined(SIGEMT)
+    signal(SIGEMT, ODB_sigexit);
+#endif
+#if defined(SIGSTKFLT)
+    signal(SIGSTKFLT,ODB_sigexit); /* Stack fault */
+#endif
+    /* signal(SIGFPE, ODB_sigexit); */
+    signal(SIGTRAP, ODB_sigexit);
+    signal(SIGINT, ODB_sigexit);
+    signal(SIGQUIT, ODB_sigexit);
+    signal(SIGTERM, ODB_sigexit);
+    signal(SIGIO, ODB_sigexit);
+    signal(SIGABRT, ODB_sigexit);
+    signal(SIGXCPU, ODB_sigexit);
+    /* signal(SIGCHLD, SIG_IGN); */
+    atexit(rm);
+    done = 1;
+  }
+}
+
+PRIVATE void
+fixenv(const char *name, const char *value)
+{
+  char *env;
+  int len = STRLEN(name) + 1 + STRLEN(value) + 1;
+  ALLOC(env, len);
+  sprintf(env,"%s=%s",name,value);
+  /* fprintf(stderr,"fixenv: %s\n",env); */
+  putenv(env);
+  /* env is purposely NOT freed; space internally allocated & used by char **environ */
+}
+
+
+PRIVATE int   *unit4fp     = NULL;
+PRIVATE char **unit4fp_str = NULL;
+PRIVATE int  unit4fp_len   = 0;
+
+PRIVATE void
+mapfp2unit(FILE *fp, int unit, const char *file)
+{
+  if (fp) {
+    int fno = fileno(fp);
+    if (!unit4fp) {
+      int j;
+#ifdef CRAYXT
+      unit4fp_len = sysconf(_SC_OPEN_MAX);
+#else
+      unit4fp_len = getdtablesize();
+#endif
+      ALLOC(unit4fp, unit4fp_len);
+      ALLOC(unit4fp_str, unit4fp_len);
+      for (j=0; j<unit4fp_len; j++) {
+	unit4fp[j] = -1; /* Means: Not in use */
+	unit4fp_str[j] = NULL;
+      }
+    }
+    if (fno >= 0 && fno < unit4fp_len) {
+      unit4fp[fno] = unit;
+      unit4fp_str[fno] = STRDUP(file);
+    }
+  }
+}
+
+
+PUBLIC void
+cma_prt_stat_(const int *ftn_unit, const int *cma_unit, 
+	      const int *binno, const int *numbins, 
+	      const int *fileno, 
+	      const char *str_open_time,  const char *str_close_time, 
+	      const char *logical_name,   const char *true_name, 
+	      const char *pipecmd,        const char *cmd, 
+	      const int *read_only, const int *packmethod, const int *blocksize, 
+	      const int *numddrs,   const int *lenddrs, 
+	      const int *numobs,    const int *maxreplen,  const int *cmalen, 
+	      const int *filesize,  const int *filepos, const int *blksize,  
+	      const int *bytes,     const int *num_trans, 
+	      const int *readbuf_len, const int *readbuf_is_alloc, 
+	      const int *writebuf_len, const int *writebuf_is_alloc, 
+	      const int *prealloc, const int *extent,   
+	      const int *mrfs_flag, 
+	      const double *walltime,  const double *xfer_speed, 
+	      const double *usercpu,   const double *syscpu,
+	      /* Hidden arguments */
+	      int str_open_time_len,  int str_close_time_len, 
+	      int logical_name_len,   int true_name_len, 
+	      int pipecmd_len,        int cmd_len
+	      )
+{
+  /* A dummy replacement routine to avoid the need to
+     have Fortran I/O library linked into the C-code.
+     This routine might be called from cma_close_(),
+     called by ODB_fclose() */
+  return;
+}
+
+int drhook_lhook = 0; /* dummy; to satisfy externals */
+
+void
+Dr_Hook(const char *name, int option, double *handle, 
+	const char *filename, int sizeinfo,
+	int name_len, int filename_len)
+{ 
+  /* A dummy Dr.Hook -call to satisfy externals */ 
+}
+
+#ifdef RS6K
+PUBLIC void /* Just a dummy ; due to the new RAISE(sig)-macro in privpub.h */
+xl__trbk_() { }
+#endif
+
+#if defined(VPP5000) || defined(VPP)
+
+/* Fujitsu VPP doesn't have snprintf, so we created one */
+/* The same code sits in ifsaux/support/endian.c */
+
+int snprintf(char *str, size_t size, const char *format, ...)
+{
+  int rc;
+  va_list ap;
+  va_start(ap, format);
+  rc = vsprintf(str, format, ap);
+  va_end(ap);
+  return rc;
+}
+
+#endif
+
+/* A dummy in case macro ALLOCA gets used */
+ll_t getstk_() { return 0; }
+
+/* A copy of odb/tools/abor1.c */
+
+void abor1_(const char *s, int slen)
+{
+  if (s && slen > 0 && slen < 1024) {
+    fprintf(stderr,"***Error in abor1_: %*s\n",slen,s);
+  }
+  else {
+    fprintf(stderr,"***Error in abor1_: Aborting ...\n");
+  }
+  raise(SIGABRT);
+  _exit(1); /* Should never end up here */
+}
+
+void abor1fl_(const char *filename, const int *linenum, 
+	      const char *s, 
+	      int filenamelen, int slen)
+{
+  if (filename && filenamelen > 0 && linenum && *linenum > 0) {
+    fprintf(stderr,
+	    "***Error: abor1fl_ has been called at %*s:%d\n",
+	    filenamelen, filename, *linenum);
+  }
+  abor1_(s,slen);
+  _exit(1); /* Should never end up here */
+}
+
+PUBLIC FILE *
+ODB_trace_fp(void)
+{
+  /* A dummy routine to return NULL fp of non-existent tracing file */
+  return NULL;
+}
+
+/* More dummies to patch gaps due to thread safe implementation of CMA I/O */
+PUBLIC void coml_in_parallel_(int *kispar_region) { if (kispar_region) *kispar_region = 0; }
+PUBLIC void coml_init_lockid_with_name_(o_lock_t *mylock, const char *name, int name_len) { }
+PUBLIC void coml_init_lockid_(o_lock_t *mylock) { }
+PUBLIC void coml_set_lockid_(o_lock_t *mylock)  { }
+PUBLIC void coml_unset_lockid_(o_lock_t *mylock) { }
+PUBLIC void coml_test_lockid_(int *is_set, o_lock_t *mylock) { if (is_set) *is_set = 1; }
+PUBLIC int get_thread_id_() { return 1; }
+PUBLIC int get_max_threads_() { return 1; }
+
+PUBLIC int
+ODB_fclose(FILE *fp, const char *srcfile, int srcline)
+{
+  int rc = 0;
+  if (fp && fp == stdin) {
+    /* do nothing */
+  }
+  else if (fp && fp == stdout) {
+    fflush(fp);
+  }
+  else if (fp && fp == stderr) {
+    fflush(fp);
+  }
+  else if (fp) {
+    extern void cma_close_(const int *unit, 
+			   int *retcode);
+    char *str = NULL;
+    int unit = -1;
+    int fno = fileno(fp);
+
+    if (fno >= 0 && fno < unit4fp_len) {
+      unit = unit4fp[fno];
+      if (unit == -1) {
+	/* Presumably not opened via ODB_fopen */
+	rc = fclose(fp);
+	goto finish;
+      }
+      str = STRDUP(unit4fp_str[fno]);
+    }
+
+    if (verbose && str) {
+      fprintf(stderr,
+	      "***Closing file '%s' at (fp=%p, fno=%d, unit=%d) [%s:%d]\n", 
+	      str, fp, fno, unit,
+	      srcfile, srcline);
+    }
+
+    cma_close_(&unit, &rc);
+
+    if (rc != 0) {
+      fprintf(stderr,
+	      "***Error in ODB_fclose(%s:%d): Unable to close file '%s' (fp=%p, fno=%d, unit=%d) : rc=%d\n",
+	      srcfile, srcline,
+	      str?str:"<UNDEFINED>", fp, fno, unit, rc);
+      exit(1);
+    }
+
+    FREE(str);
+    if (fno >= 0 && fno < unit4fp_len) {
+      unit4fp[fno] = -1;
+      FREE(unit4fp_str[fno]);
+    }
+  }
+
+ finish:
+  return rc;
+}
+
+PUBLIC FILE *
+ODB_fopen(const char *file, const char *mode, const char *srcfile, int srcline)
+{
+  FILE *fp = NULL;
+
+  if (strequ(file, "stdin")) {
+    fp = stdin;
+  }
+  else if (strequ(file, "stdout")) {
+    fp = stdout;
+  }
+  else if (strequ(file, "stderr")) {
+    fp = stderr;
+  }
+  else {
+
+    /* Benefit implicitly from ioassign */
+
+    extern void cma_open_(int *unit,
+			  const char *filename,
+			  const char *mode,
+			  int *retcode,
+			  /* Hidden arguments to Fortran-program */
+			  int len_filename,
+			  int len_mode);
+    extern FILE *CMA_get_fp(const int *unit);
+    
+    int unit;
+    int rc;
+    
+    cma_open_(&unit, file, mode, &rc, STRLEN(file), STRLEN(mode));
+    if (rc == 1) fp = CMA_get_fp(&unit);
+    
+    if (!fp) {
+      fprintf(stderr,
+	      "***Error in ODB_fopen(%s:%d): Unable to open '%s', mode='%s' : rc=%d\n",
+	      srcfile, srcline,
+	      file, mode, rc);
+      exit(1);
+    }
+    
+    mapfp2unit(fp, unit, file);
+    
+    if (verbose) {
+      char *str = NULL;
+      int fno = fileno(fp);
+      if (fno >= 0 && fno < unit4fp_len) {
+	unit = unit4fp[fno];
+	str = STRDUP(unit4fp_str[fno]);
+      }
+      if (str) fprintf(stderr,
+		       "***Opened file '%s' at (fp=%p, fno=%d, unit=%d, mode='%s') [%s:%d]\n", 
+		       str, fp, fno, unit, mode,
+		       srcfile, srcline);
+      FREE(str);
+    }
+    
+  }
+  return fp;
+}
+
+PRIVATE void
+write_symbol_map()
+{
+  if (!ddl_piped) {
+    FILE *fpmap;
+    char *map;
+    ALLOC(map, STRLEN(odb_outpath) + STRLEN(original_name) + 20);
+    sprintf(map,"%s/%s.lst",odb_outpath,original_name);
+    if (verbose) fprintf(stderr,"Symbol output goes to file '%s'\n",map);
+    fpmap = FOPEN(map, "w");
+    ODB_print_symbols(fpmap);
+    FCLOSE(fpmap);
+    FREE(map);
+  }
+}
+
+PRIVATE void
+Print_ODB_env()
+{
+  if (verbose) {
+    fprintf(stderr,"ODB_SYSPATH ==> '%s'\n",odb_syspath);
+    fprintf(stderr,"ODB_OUTPATH ==> '%s'\n",odb_outpath ? odb_outpath : "<undefined>");
+    fprintf(stderr,"ODB_CC ==> '%s'\n",odb_cc);
+    fprintf(stderr,"ODB_LD ==> '%s'\n",odb_ld);
+    fprintf(stderr,"ODB_LIBS ==> '%s'\n",odb_libs);
+    fprintf(stderr,"ODB_LIBS_KEEP ==> '%s'\n",odb_libs_keep);
+  }
+}
+
+PRIVATE char *
+transform_label(const char *s)
+{
+  char *new_s = s ? STRDUP(s) : NULL;
+  char *sp = new_s;
+  if (sp) {
+    char *p = STRDUP(sp);
+    char *new_p = p;
+    /* Must start with [a-zA-Z] */
+    if (!((*sp >= 'a' && *sp <= 'z')||
+	  (*sp >= 'A' && *sp <= 'Z'))) 
+      sp++;
+    while (*sp) {
+      /* accepted chars [a-zA-Z0-9] ==> uppercase where applicable */
+      if ((*sp >= 'a' && *sp <= 'z') ||
+	  (*sp >= 'A' && *sp <= 'Z') ||
+	  (*sp >= '0' && *sp <= '9')) {
+	if (islower(*sp)) {
+	  *p++ = toupper(*sp);
+	}
+	else {
+	  *p++ = *sp;
+	}
+      }
+      sp++;
+    }
+    *p = '\0';
+    FREE(new_s);
+    new_s = new_p;
+  }
+  return new_s;
+}
+
+char *
+ODB_uppercase(const char *s)
+{
+  char *new_s = s ? STRDUP(s) : NULL;
+  char *sp = new_s;
+  if (sp) {
+    do {
+      if (islower(*sp)) *sp = toupper(*sp);
+    } while(*++sp);
+  }
+  return new_s;
+}
+
+char *
+ODB_lowercase(const char *s)
+{
+  char *new_s = s ? STRDUP(s) : NULL;
+  char *sp = new_s;
+  if (sp) {
+    do {
+      if (isupper(*sp)) *sp = tolower(*sp);
+    } while(*++sp);
+  }
+  return new_s;
+}
+
+char *
+ODB_capitalize(const char *s)
+{
+  char *new_s = s ? ODB_lowercase(s) : NULL;
+
+  if (new_s) {
+    if (islower(new_s[0])) new_s[0] = toupper(new_s[0]);
+  }
+
+  /* fprintf(stderr,"ODB_capitalize(%s) ==> %s\n",s,new_s); */
+
+  return new_s;
+}
+
+
+PRIVATE void
+ODB_getenv()
+{
+  char *p;
+
+  p = getenv("ODB98_DEBUG");
+  if (p && strequ(p,"1")) debug = 1;
+
+  p = getenv("ODB_SYSPATH");
+  if (p) {
+    odb_syspath = STRDUP(p);
+  }
+  else {
+    odb_syspath = STRDUP(ODB_SYSPATH);
+    fixenv("ODB_SYSPATH", odb_syspath);
+  }
+
+  p = getenv("ODB_OUTPATH");
+  odb_outpath = p ? STRDUP(p) : STRDUP(".");
+  fixenv("ODB_OUTPATH", odb_outpath);
+
+  p = getenv("ODB_CC");
+#ifdef VPP
+  odb_cc = p ? STRDUP(p) : STRDUP("vcc -g -DVPP");
+#else
+  odb_cc = p ? STRDUP(p) : STRDUP("cc -g");
+#endif
+
+  p = getenv("ODB_LD");
+#ifdef VPP
+  /* odb_ld = p ? STRDUP(p) : STRDUP("frt -X9 -Wl,-dy,-G,-Bdynamic"); */
+  odb_ld = p ? STRDUP(p) : STRDUP("ld -dy -G -Bdynamic");
+#else
+  /* odb_ld = p ? STRDUP(p) : STRDUP("f90 -shared"); */
+  odb_ld = p ? STRDUP(p) : STRDUP("ld -shared");
+#endif
+
+  p = getenv("ODB_LIBS");
+  odb_libs = p ? STRDUP(p) : STRDUP("");
+
+  p = getenv("ODB_LIBS_KEEP");
+  odb_libs_keep = p ? STRDUP(p) : STRDUP("0");
+
+  p = getenv("ODB_LABEL");
+  odb_label = p ? transform_label(p) : NULL;
+
+  p = getenv("ODB_READONLY");
+  if (p) readonly_mode = atoi(p);
+
+  p = getenv("ODB_LATLON_RAD");
+  if (p) {
+    latlon_rad = atoi(p);
+    if (latlon_rad != -1 &&
+	latlon_rad !=  0 && 
+	latlon_rad !=  1) latlon_rad = -1; /* i.e. as if undefined */
+  }
+
+  p = getenv("ODB_USE_INDICES");
+  if (p) use_indices = atoi(p);
+
+  p = getenv("ODB_REORDER_TABLES");
+  if (p) reorder_tables = atoi(p);
+
+  p = getenv("ODB_INSERT_TABLES");
+  if (p) insert_tables = atoi(p);
+
+  p = getenv("ODB_SAFEGUARD");
+  if (p) safeGuard = atoi(p);
+
+  p = getenv("ODB_BAILOUT");
+  if (p) bailout_level = atoi(p);
+
+  p = getenv("ODB_BAILOUT_STRING");
+  if (p) bailout_string = STRDUP(p);
+  else bailout_string = STRDUP("0");
+}
+
+
+void 
+odb_warn(char *errormsg, int rc) 
+{ 
+  extern int ODB_ncmds;
+  extern char yytext[];
+
+  if (ODB_ncmds > 0 || STRLEN(yytext) > 0) {
+    extern int ODB_lineno;
+    fprintf(stderr,"*** %s in \"%s\":%d near or before token '%s'\n",
+	    (rc == 0) ? "Warning" : "Error", 
+	    odb_source,ODB_lineno,yytext);
+    if (errormsg) {
+      fprintf(stderr,"%s\n",errormsg);
+    }
+    if (odb_source) {
+      char cmd[256];
+      sprintf(cmd,"head -%d %s | tail -1",ODB_lineno,odb_source);
+      (void)system(cmd);
+      fflush(stdout);
+    }
+
+    /*
+    LEX_print_state(stderr);
+    
+    {
+      extern int include_nesting;
+      fprintf(stderr,"\tinclude_nesting = %d\n",include_nesting);
+    }
+    */
+    
+    write_symbol_map();
+  }
+  else
+    fprintf(stderr,"Input file '%s' contains no statements\n",odb_source);
+
+  /* sleep(5); */
+}
+
+void 
+yyerror(char *errormsg) 
+{
+  odb_warn(errormsg, 1);
+  exit(1);
+}
+
+
+PUBLIC int
+ODB_fprintf(FILE *fp, const char *format, ...)
+{
+  /* The same as fprintf(), but does nothing when fp points to NULL or fpdevnull */
+  if (!fp || fp == fpdevnull) return 0;
+  else {
+    int n;
+    va_list args;
+    va_start(args, format);
+    n = vfprintf(fp, format, args);
+    va_end(args);
+    return n;
+  }
+}
+
+PUBLIC uint
+ODB_hash(int kind, const char *s) /* taken from ioassign_hash.c */
+{
+  static const uint hashsize = 123457U; /* hardcoded for now */
+  uint hashval = kind;
+  for (; *s ;) {
+    hashval = (*s++) + 31U * hashval;
+  }
+  return hashval%hashsize;
+}
+
+PRIVATE char *
+Check_Env(int fixtoo, const char *prefix, const char *dbname, const char *idx)
+{
+  char *env = NULL;
+  if (prefix && dbname) {
+    char *long_env, *short_env;
+    char *long_name = NULL;
+    const char *short_name = prefix;
+    int len;
+
+    len = STRLEN(prefix) + 1 + STRLEN(dbname) + 1;
+    ALLOC(long_name, len);
+    sprintf(long_name,"%s_%s", prefix, dbname);
+    long_env = getenv(long_name);
+
+    if (fixtoo || !long_env) {
+      short_env = getenv(short_name);
+      
+      if (long_env) {
+	if (!short_env) fixenv(short_name, long_env);
+      }
+      else if (short_env) {
+	fixenv(long_name, short_env);
+      }
+      
+      short_env = getenv(short_name);
+      if (!short_env) fixenv(short_name, idx ? idx : ".");
+
+      long_env = getenv(long_name);
+      if (!long_env) fixenv(long_name, idx ? idx : ".");
+
+      env = getenv(long_name);
+      
+      FREE(long_name);
+    }
+    else {
+      env = long_env;
+    }
+  }
+  return env;
+}
+
+PRIVATE void
+Check_Empty_Tables(const char *dbname)
+{
+  FREE(table_list);
+  n_table_list = 0;
+  delim_table_list = 0;
+  if (dbname && empty_tables) {
+    char *ddfile = NULL;
+    int len = STRLEN(dbname) + STRLEN(".dd") + 1;
+    ALLOC(ddfile,len);
+    snprintf(ddfile,len,"%s.dd",dbname);
+    if (!is_regular_file_(ddfile)) {
+      /* This was completely fresh database w/o any data ==> compile all tables */
+      empty_tables = 0;
+      goto finish;
+    }
+    /* Read from Unix-pipe those files i.e. table names, which have got some data
+       and save the list to the 'table_list' */
+    {
+      const char cmd[] = "find [0-9]* -type f -follow -print | perl -pe 's|^.*/||' | sort -u";
+      FILE *fp = popen(cmd,"r");
+      /* fprintf(stderr,"||| cmd='%s' : fp=%p\n",cmd,fp); */
+      if (fp) { /* Success */
+	char line[MAXLINE];
+	char *p;
+	init_list(NULL);
+	while ( (p = fgets(line, MAXLINE, fp)) != NULL ) {
+	  while (isspace(*p)) p++;
+	  if (*p) {
+	    char *nl = strchr(p,'\n');
+	    if (nl) *nl = '\0';
+	    (void) add_list(p);
+	  }
+	  if (feof(fp)) break;
+	}
+	n_table_list = get_list_elemcount();
+	p = get_list();
+	/* fprintf(stderr,"||| n_table_list=%d\n",n_table_list); */
+	table_list = STRDUP(p);
+	/* fprintf(stderr,"||| table_list='%s'\n",table_list); */
+	delim_table_list = get_list_delim();
+	/* fprintf(stderr,"||| delim_table_list=%c\n",delim_table_list); */
+	destroy_list();
+	pclose(fp);
+      }
+      else { /* And error, but ignored ==> compile all tables */
+	empty_tables = 0;
+	goto finish;
+      }
+    }
+  finish:
+    FREE(ddfile);
+    return;
+  }
+  if (!table_list || n_table_list == 0) {
+    empty_tables = 0; /* Did not satisfy boundary conditions ==> compile all tables */
+  }
+  /* fprintf(stderr,"||| empty_tables=%d\n",(int)empty_tables); */
+}
+
+
+PUBLIC Boolean
+is_dummy_table(const char *name)
+{
+  Boolean dummy_table = empty_tables; /* By default no table is considered dummy i.e. as if -z was NOT specified */
+  if (empty_tables) { /* -z was supplied */
+    if (in_mylist(name, table_list, delim_table_list)) dummy_table = 0;
+  }
+  if (dummy_table && verbose) 
+    fprintf(stderr,"**Warning: table '%s' is considered empty --> minimal code generated\n",name);
+  return dummy_table;
+}
+
+
+#define FLAGS "1:A:bB:cCdD:f:F:GhHiI:l:mO:o:q:Q:rRsSU:uvVwz"
+#define USAGE \
+  "Usage: %s\n" \
+  "       [-c (compile_only)]\n" \
+  "       [-C (check syntax of ddl/sql only)]\n" \
+  "       [-d(ebug)] [-h(elp)]\n" \
+  "       [-w (vieWs_only)] [-l odb_label]\n" \
+  "       [-o output_source_path]\n" \
+  "       [-I system_data_path]\n" \
+  "       [-v(erbose)]\n" \
+  "       [-V(ersion)]\n" \
+  "       [-O{0|1|2|3}]\n" \
+  "       [-s] [-i]\n" \
+  "       [-R] [-S]\n" \
+  "       [-D define_string]\n" \
+  "       [-1 master_table=slave_table]\n" \
+  "       [-A master_table=slave_table]\n" \
+  "       [-m(erge_table_indices)]\n" \
+  "       [-G (turn safeGuard-tests in views' C-code back on)]\n" \
+  "       [-f filter_command]\n" \
+  "       [-r (generate read/only-code)]\n" \
+  "       [-H (do *NOT* insert Dr.Hook-calls)] \n" \
+  "       [-z (dummy code for empty tables)]\n" \
+  "       [-F[-]{0|1|2|3}]\n" \
+  "       [-q 'sql_query']\n" \
+  "       [-Q sql_query_file]\n" \
+  "       [-b (to bailout from column/table name spelling mistakes in SQLs)]\n" \
+  "       [-B bailout_level_bitmap]\n" \
+  "       [-u (do not use CREATE INDEX-indices)]\n" \
+  "       {DDL-file | SQL-file(s)}\n"
+
+/* Supported flags:
+
+   -c               ! Compile only i.e. do not create shared objects (.so)
+   -C               ! Check syntax of ddl/sql only, but don't create .o nor .so
+   -d               ! Debug mode  (also activated via export ODB98_DEBUG=1)
+   -h               ! Help me! Prints usage and exits
+   -H               ! Insert Dr.Hook -calls
+   -l odb_label     ! Change the default label otherwise determined from 
+                    !   the DDL-file name or ODB_LABEL. Must contain letters [A-Z]
+   -o source_path   ! Where to place the output files (.h, .c, .o, .so, .ddl_)
+   -w               ! Handle vieWs only
+   -I system_path   ! Location of the ODB system files, like "odb.h" etc.
+   -v               ! More verbose output
+   -V               ! Print version number of the compiler
+   -O [0|1|2|3]     ! Generate optimized C-code (-O3 is the default)
+   -s               ! Generate static stubb (xxx_Sstatic.c)
+   -i               ! Enable incremental update of static stubb (if applicable via -s)
+   -D def_string    ! Define preprocessing key, say -DMETEO_FRANCE in layout/sql
+   -U def_string    ! Undefine preprocessing key, say -UECMWF in layout/sql
+   -1 master=slave  ! The master table (say 'index') that refers to the given slave table
+                    ! (say 'hdr') with constant length of one (in level -O3 only)
+                    ! See also ONELOOPER-stmt in ODB/SQL-language
+   -A master=slave  ! Define align tables, that go in sync-step when selecting data
+                    ! See also ALIGN-stmt in ODB/SQL-language
+   -m               ! To merge table indices in views, if ALIGN or -A was specified
+   -R               ! Do *NOT* perform reordering of TABLEs in FROM-statement
+                    ! Can also be specified/overridden by REORDER/NOREORDER ODB/SQL-stmts
+   -S               ! Suppress C-compilation of static stubb (xxx_Sstatic.c)
+   -G               ! Turn safeGuard-tests in views' C-code back on (default is off)
+   -r               ! Generate read/only-code by default (as if READONLY; was given in SQL)
+   -z               ! Provides dummy routines for non-existent (empty) tables to both
+                    ! reduce compilation time and and size of object library.
+                    ! "Emptyness" is checked by the odb98.x compile by help of command
+                    ! 'find [0-9]* -type f -follow -print | xargs -n1 basename | sort -u'
+                    ! (However we are using substantially faster perl-version instead of xargs)
+   -F[-][0|1|2|3]   ! Provides filtered compilation information for use by generic select 
+                    ! (goes to file <dbname>_<viewname>.info)
+                    ! Level 0 : No info created at all (the default)
+                    ! Level 1 : Standard info created (implemented)
+                    ! Level 2 : As Level 1, but no C-code is created (<dbname>.ddl_ will be created)
+                    ! Level 3 : As Level 2, but more extensive information about layout is also written
+                    ! Level >= 2 implies also -O3 -C i.e. optlevel=3 and no compilation of non-existent C-code
+                    ! If you DO NOT employ the negative (-) sign, then the I/O is ...
+                    !    ... to/from stdout/stdin i.e. unix pipes are ok
+   -q 'sql_query'   ! Supply SQL-query via command line string; only one query possible
+                    ! View name by default "myview", but an attempt to search 'create view' is also made
+                    ! Implies -w. Useful when "piping" the .ddl_ i.e. with -F2 option
+   -Q sql_query_file! The same as -q 'sql_query', but the "sql_query" is read from the file "sql_query_file"
+                    ! This option was made available for long queries (Unix shell cmd line limit problems)
+   -b               ! See discussion above ; search backwards for "bailout_level"
+   -B bailout_level ! To supply specific OR'red bitmap as bailout_level
+   -u               ! Opt out from using CREATE INDEX-indices (same as export ODB_USE_INDICES=0)
+
+  Typically for tables :  odb98.x dbase.ddl
+            for view(s):  odb98.x -w -l dbase myview.sql
+            for view(s):  odb98.x -w -l dbase myview1.sql myview2.sql
+	    no .so-file:  odb98.x -c -w -l dbase myview.sql
+
+  In addition defaults may be read from $ODB_COMPILER_FLAGS (if present)
+  If not present, then set to "/dev/null", otherwise odb98.x may hang forever (29-Jun-2006/SS)
+
+ */
+
+PRIVATE char **
+get_default_args(int *numargs, int *errflg)
+{
+  /* Use purposely fopen & fclose (rather than FOPEN & FCLOSE)
+     to prevent from using CMAIO & IOASSIGN routines,
+     since environment variables they may access are not
+     defined at this early stage */
+
+  char **args = NULL;
+  int nargs = 0;
+  char *env = getenv("ODB_COMPILER_FLAGS");
+
+  if (!env) {
+    if (debug) fprintf(stderr,"get_default_args: ODB_COMPILER_FLAGS not set; assuming '/dev/null'\n");
+    /* To prevent further hanging */
+    fixenv("ODB_COMPILER_FLAGS", "/dev/null");
+    env = getenv("ODB_COMPILER_FLAGS");
+  }
+
+  if (debug) fprintf(stderr,"get_default_args: ODB_COMPILER_FLAGS=%s\n",env?env:NIL);
+
+  if (env) {
+    FILE *fp = fopen(env,"r");
+    if (fp) {
+      char *p;
+      char line[MAXLINE];
+
+      while ( (p = fgets(line, MAXLINE, fp)) != NULL ) {
+	while (isspace(*p)) p++;
+	if (*p == '-') nargs++;
+      }
+
+      if (debug) fprintf(stderr,"get_default_args: no. of args = %d\n",nargs);
+
+      if (nargs > 0) {
+	int j = 0;
+	CALLOC(args, nargs);
+	rewind(fp);
+	while ( (p = fgets(line, MAXLINE, fp)) != NULL ) {
+	  while (isspace(*p)) p++;
+	  if (*p == '-') {
+	    char *nl = strchr(p,'\n');
+	    if (nl) *nl = '\0';
+	    args[j++] = STRDUP(p);
+	  }
+	}
+      } /* if (nargs > 0) */
+
+      fclose(fp);
+
+      if (debug) {
+	int j;
+	for (j=0; j<nargs; j++) {
+	  fprintf(stderr,"get_default_args: args[%d] = '%s'\n",j,args[j]);
+	}
+      }
+    }
+    else {
+      fprintf(stderr,"***Error: Unable to open file behind the ODB_COMPILER_FLAGS=%s\n",env);
+      (*errflg)++;
+    } /* if (fp) ... else ... */
+  }
+
+  if (numargs) *numargs = nargs;
+  return args;
+}
+
+
+PRIVATE Boolean
+scan_include(FILE *fp, const char *target)
+{
+  Boolean has_include = 0;
+  char *p;
+  char line[MAXLINE];
+  while ( (p = fgets(line, MAXLINE, fp)) != NULL ) {
+    while ( *p == ' ' || *p == '\t' ) p++;
+    if (strnequ(p,"INCLUDE ",8) || 
+	strnequ(p,"INCLUDE\t",8) ||
+	strnequ(p,"#include ",9) ||
+	strnequ(p,"#include\t",9)) {
+      char *s;
+      int slen = STRLEN(target) + 5;
+      ALLOC(s,slen);
+      sprintf(s,"%s.ddl",target);
+      has_include = (strstr(s,p+8) != NULL);
+      FREE(s);
+      if (has_include) break;
+    }
+    else if (strnequ(p,"CREATE",6) || strnequ(p,"VIEW",4)) {
+      has_include = 0;
+      break;
+    }
+  }
+  FREWIND(fp);
+  return has_include;
+}
+
+
+PUBLIC int
+ODB_addrel(const char *p, char separ)
+{
+  int rc = 0;
+  char *start = STRDUP(p);
+  char *s_in = start;
+  char *buf = STRDUP(s_in);
+  char *s_out = buf;
+  char *master = NULL;
+  char **slaves = NULL;
+  int j, nslaves = 0;
+  char *s;
+
+  while (*s_in) {
+    if (*s_in != ' ' && *s_in != '\t' &&
+	*s_in != '(' && *s_in != ')') {
+      *s_out++ = *s_in++;
+    }
+    else
+      s_in++;
+  }
+  *s_out = '\0';
+
+  s = strchr(buf,separ);
+  if (s) {
+    char *token;
+    char *saved = NULL;
+    master = STRDUP(buf);
+    s = strchr(master,separ);
+    *s = '\0';
+    saved = STRDUP(s+1);
+    token = strtok(s+1,",");
+    while (token) { /* Count no. slaves */
+      char *t = STRDUP(token);
+      token = strtok(NULL,",");
+      nslaves++;
+      FREE(t);
+    }
+    if (nslaves > 0) {
+      CALLOC(slaves, nslaves);
+      token = strtok(saved,",");
+      j = 0;
+      while (token) { /* Count no. slaves */
+	slaves[j++] = STRDUP(token);
+	token = strtok(NULL,",");
+      }
+      rc = 0;
+      /* for (j=-1; j<nslaves-1; j++) */ {
+	int k;
+	j = -1;
+	/* if (j >= 0) master = STRDUP(slaves[j]); */
+	for (k=j+1; k<nslaves; k++) {
+	  char *x;
+	  int xlen = STRLEN(master) + 1 + STRLEN(slaves[k]) + 1;
+	  ALLOC(x,xlen);
+	  sprintf(x,"%s%c%s",master,separ,slaves[k]);
+	  add_list(x);
+	  FREE(x);
+	  rc++;
+	} /* for (k=j+1; k<nslaves; k++) */
+	FREE(master);
+      } /* for (j=-1; j<nslaves; j++) */
+    } /* if (nslaves > 0) */
+    FREE(saved);
+  }
+    
+  FREE(start);
+  FREE(buf);
+  FREE(master);
+  for (j=0; j<nslaves; j++) {
+    FREE(slaves[j]);
+  }
+  FREE(slaves);
+  
+  /* rc = ((nslaves + 1) * nslaves)/2; */ /* This many pairs formed */
+  return rc;
+}
+
+
+PRIVATE void Compile(const char *cmd, int retry)
+{
+  if (retry > 0) {
+    fprintf(stderr,"## Compilation [retry%d]: %s\n",retry,cmd);
+  }
+  else if (verbose) {
+    fprintf(stderr,"## Compilation: %s\n",cmd);
+  }
+  else {
+    fprintf(stderr,"%s\n",cmd);
+  }
+  (void)system(cmd);
+}
+
+
+PRIVATE void WriteQuery(FILE *fp, const char *s)
+{
+  if (fp && s) {
+    char quote = 0;
+    Boolean comment = 0;
+    while (*s) {
+      char ch = *s++;
+      if (isspace(ch) || isprint(ch)) {
+	ODB_fprintf(fp, "%c", ch);
+        if (!comment && (ch == '/' || ch == '-') && ch == *s) comment = 1;
+        else if (comment && ch == '\n') comment = 0;
+	if (quote && quote == ch) quote = 0;
+	else if (!quote) {
+	  if (!comment && ch == ';') ODB_fprintf(fp,"\n");
+	  else if (ch == '\'' || ch == '"') quote = ch;
+	}
+      }
+    }
+    ODB_fprintf(fp, " ;\n");
+  }
+}
+
+PRIVATE char *Slurp(const char *path)
+{
+  extern int IOgetsize(const char *path, int *filesize, int *blksize);
+  int filesize = 0;
+  int rc = IOgetsize(path, &filesize, NULL);
+  char *s = NULL;
+  if (rc == 0 && filesize > 0) {
+    FILE *fp = fopen(path,"r");
+    if (fp) {
+      ALLOC(s, filesize+20);
+      rc = fread(s, sizeof(*s), filesize, fp); /* slurp!! */
+      if (rc == filesize) { /* Success */
+	s[filesize] = '\0'; 
+	strcat(s," ;\n");
+      }
+      else FREE(s); /* Failure */
+      fclose(fp);
+    }
+  }
+  if (!s) {
+    fprintf(stderr,"***Error: Unable to inline non-existent (or empty) ODB/SQL-file '%s'\n",
+	    path ? path : NIL);
+    RAISE(SIGABRT);
+    _exit(1);
+  }
+  return s;
+}
+
+int
+main(int cmdline_argc, char *cmdline_argv[])
+{
+  char *p;
+  extern FILE *yyin;
+  int c;
+  int errflg = 0;
+  int one_count = 0;
+  extern char *optarg;
+  extern int optind;
+  char *Pwd = "";
+  char *fpsrc_file = NULL;
+  int argc = 0;
+  char **argv = NULL;
+  int def_argc = 0;
+  char **def_argv = NULL;
+  int k,j;
+
+  main_prog = cmdline_argv[0];
+
+  (void) ODB_std_mem_alloc(1); /* Always enforce standard memory alloc
+				  since some yacc/lex malloc()'s are out
+				  of our control */
+
+  fixenv("IOASSIGN_INCORE","0"); /* Make sure no incore IOASSIGN gets used */
+
+  {
+    int argh_len = 1 + cmdline_argc;
+    for (j=0; j<cmdline_argc; j++) argh_len += STRLEN(cmdline_argv[j]) + 10;
+    argh_len *= 2;
+    ALLOC(ARGH, argh_len);
+  }
+  ARGH[0] = '\0';
+
+  set_signals();
+
+  ODB_getenv();
+
+  def_argv = get_default_args(&def_argc, &errflg);
+  argc = def_argc + cmdline_argc;
+
+/*
+  fprintf(stderr,"main: def_argc=%d, cmdline_argc=%d, argc=%d, errflg=%d\n",
+	  def_argc, cmdline_argc, argc, errflg);
+*/
+
+  CALLOC(argv,argc+1);
+
+  k = 0;
+  if (cmdline_argc > 0) argv[k++] = cmdline_argv[0];
+
+  if (def_argc > 0) {
+    for (j=0; j<def_argc; j++) {
+      argv[k++] = def_argv[j];
+    }
+  }
+
+  if (cmdline_argc > 1) {
+    for (j=1; j<cmdline_argc; j++) {
+      argv[k++] = cmdline_argv[j];
+    }
+  }
+
+  argv[k] = NULL;
+
+/*
+  {
+    int j;
+    fprintf(stderr,"main: argc = %d\n",argc);
+    for (j=0; j<argc; j++) {
+      fprintf(stderr,"main: argv[%d] = '%s'\n",j,argv[j] ? argv[j] : NIL);
+    }
+  }
+*/
+
+  init_list(NULL);
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case '1': /* ONE-looper */
+      p = optarg;
+      if (!strchr(p,'=')) {
+	fprintf(stderr,
+		"*** Error: Invalid master-to-slave table relation in flag '-1%s'\n",
+		p);
+	errflg++;
+      }
+      else {
+	one_count += ODB_addrel(p,'=');
+      }
+      /* -- delayed until process_one_tables() finished --
+      strcat(ARGH,"\n\t -1");
+      strcat(ARGH,p);
+      */
+      break;
+    case 'A': /* ALIGNed table(s) */
+      p = optarg;
+      if (!strchr(p,'=')) {
+	fprintf(stderr,
+		"*** Error: Invalid master-to-slave table relation in flag '-A%s'\n",
+		p);
+	errflg++;
+      }
+      else {
+	char *s  = STRDUP(p);
+	char *ps = strchr(s,'=');
+	if (ps) *ps = '@';
+	one_count += ODB_addrel(s,'@');
+	FREE(s);
+      }
+      /* -- delayed until process_one_tables() finished --
+      strcat(ARGH,"\n\t -A");
+      strcat(ARGH,p);
+      */
+      break;
+    case 'b':
+      bailout_level = -1;
+      strcat(ARGH,"\n\t -b");
+      break;
+    case 'B':
+      bailout_level = atoi(optarg);
+      strcat(ARGH,"\n\t -B");
+      strcat(ARGH,optarg);
+      break;
+    case 'c':
+      create_so = 0;
+      strcat(ARGH,"\n\t -c");
+      break;
+    case 'C':
+      create_so = 0;
+      check_syntax_only = 1;
+      strcat(ARGH,"\n\t -C");
+      break;
+    case 'd':
+      debug = 1;
+      strcat(ARGH,"\n\t -d");
+      break;
+    case 'f':
+      filter_cmd = STRDUP(optarg);
+      strcat(ARGH,"\n\t -f");
+      strcat(ARGH,filter_cmd);
+      break;
+    case 'F':
+      filtered_info = atoi(optarg);
+      {
+	const char *p = strchr(optarg,'.');
+	if (ABS(filtered_info) <= 3 && !p) {
+	  strcat(ARGH,"\n\t -F");
+	  if (ABS(filtered_info) >= 2) {
+	    strcat(ARGH,optarg);
+	    optlevel = 3;
+	    strcat(ARGH,"\n\t -O3");
+	    genstatic = -1; /* prevents "-s" having any effect */
+	    create_so = 0;
+	    check_syntax_only = 1;
+	    strcat(ARGH,"\n\t -C");
+	  }
+	  ddl_piped = (filtered_info > 0) ? 1 : 0;
+	}
+	else { /* Not a valid level */
+	  filtered_info = 0;
+	}
+      }
+      break;
+    case 'G':
+      safeGuard = 1;
+      strcat(ARGH,"\n\t -G");
+      break;
+    case '?':
+    case 'h':
+      print_help = 1;
+      break;
+    case 'H':
+      insert_drhook = 0; /* Note the reversed meaning (04-Feb-2006) */
+      strcat(ARGH,"\n\t -H");
+      break;
+    case 'i':
+      incremental = 1;
+      strcat(ARGH,"\n\t -i");
+      break;
+    case 'I':
+      FREE(odb_syspath);
+      odb_syspath = STRDUP(optarg);
+      fixenv("ODB_SYSPATH", odb_syspath);
+      strcat(ARGH,"\n\t -I");
+      strcat(ARGH,odb_syspath);
+      break;
+    case 'l':
+      FREE(odb_label);
+      odb_label = transform_label(optarg);
+      strcat(ARGH,"\n\t -l");
+      strcat(ARGH,odb_label);
+      /* break; */
+      /* Let purposely "fall through" to also enable -Ddatabase_name !! */
+      optarg = odb_label;
+    case 'D':
+      ODB_put_define(optarg,1);
+      strcat(ARGH,"\n\t -D");
+      strcat(ARGH,optarg);
+      break;
+    case 'U':
+      ODB_put_define(optarg,0);
+      strcat(ARGH,"\n\t -U");
+      strcat(ARGH,optarg);
+      break;
+    case 'm':
+      merge_table_indices = 1;
+      break;
+    case 'O':
+      optlevel = atoi(optarg);
+      if (optlevel >= 0) {
+	strcat(ARGH,"\n\t -O");
+	strcat(ARGH,optarg);
+      }
+      optlevel = MAX(0,optlevel);
+      break;
+    case 'o':
+      FREE(odb_outpath);
+      odb_outpath = STRDUP(optarg);
+      fixenv("ODB_OUTPATH", odb_outpath);
+      strcat(ARGH,"\n\t -o");
+      strcat(ARGH,odb_outpath);
+      break;
+    case 'q':
+      views_only = 1;
+      strcat(ARGH,"\n\t -w");
+      FREE(sql_query);
+      sql_query = STRDUP(optarg);
+      strcat(ARGH,"\n\t -q'");
+      strcat(ARGH,sql_query);
+      strcat(ARGH,"'");
+      break;
+    case 'Q':
+      views_only = 1;
+      strcat(ARGH,"\n\t -w");
+      FREE(sql_query);
+      sql_query = Slurp(optarg);
+      strcat(ARGH,"\n\t -Q");
+      strcat(ARGH,optarg);
+      break;
+    case 'r':
+      readonly_mode = 1;
+      strcat(ARGH,"\n\t -r");
+      break;
+    case 'R':
+      reorder_tables = 0;
+      strcat(ARGH,"\n\t -R");
+      break;
+    case 's':
+      if (genstatic == 0) {
+	genstatic = 1;
+	strcat(ARGH,"\n\t -s");
+      }
+      break;
+    case 'S':
+      Ccompile_Sstatic_stubb = 0;
+      strcat(ARGH,"\n\t -S");
+      break;
+    case 'u':
+      use_indices = 0;
+      strcat(ARGH,"\n\t -u");
+      break;
+    case 'v':
+      verbose = 1;
+      strcat(ARGH,"\n\t -v");
+      break;
+    case 'V':
+      print_version = 1;
+      strcat(ARGH,"\n\t -V");
+      break;
+    case 'w':
+      views_only = 1;
+      strcat(ARGH,"\n\t -w");
+      break;
+    case 'z':
+      empty_tables = 1;
+      strcat(ARGH,"\n\t -z");
+      break;
+    default:
+      errflg++;
+      break;
+    }
+  }
+
+  if (one_count > 0) {
+    char *plist = add_list(NULL);
+    if (plist && optlevel >= 3) one_tables = STRDUP(plist);
+  }
+
+  destroy_list();
+
+  /* if (one_count == 0 || optlevel < 3) merge_table_indices = 0; */
+  if (optlevel < 3) merge_table_indices = 0;
+  if (merge_table_indices) strcat(ARGH,"\n\t -m");
+
+  if (verbose) {
+    Pwd = "\npwd;";
+  }
+
+  if (print_version) {
+    fprintf(stderr,"ECMWF ODB/SQL Compiler, Revision %s [%s], %s, %s   %s\n",
+	    vers, codb_versions_(NULL, NULL, NULL, NULL),
+	    date_str, time_str,
+	    system_name);
+    fprintf(stderr,"Copyright (c) 1998-2008 ECMWF. All Rights Reserved. ");
+    fprintf(stderr,"Contact your ODB representative\n");
+  }
+
+  if (print_help) {
+    fprintf(stderr,USAGE,argv[0]);
+    exit(errflg);
+  }
+
+  if (argc - 1 == optind) {
+    char *arg = STRDUP(argv[argc-1]);
+    char *pslash = strrchr(arg, '/');
+    char *dir = NULL;
+    if (pslash) {
+      *pslash = '\0';
+      dir = arg;
+      if (verbose) fprintf(stderr,"*** Changing dir to '%s'\n", dir);
+      if (chdir(dir) != 0) { /* Error */
+	PERROR(dir);
+	errflg++;
+      }
+      odb_source = STRDUP(pslash+1);
+    }
+    else {
+      odb_source = STRDUP(arg);
+    }
+    if (!errflg && sql_query) {
+      /* Ignore IOASSIGN, even if available */
+      fixenv("IOASSIGN","/dev/null");
+    }
+    if (!errflg && sql_query) {
+      FILE *fp_in = NULL;
+      FILE *fp_out = NULL;
+      char *env = getenv("TMPDIR");
+      char *viewname = getenv("ODB98_VIEWNAME");
+      if (viewname) {
+	char *ODBSQL_tmp_file = 
+	  env ? "$TMPDIR/%s.sql" : "./%s.sql";
+	int len = STRLEN(ODBSQL_tmp_file) + STRLEN(viewname) + 1;
+	ALLOC(tmp_file,len);
+	snprintf(tmp_file,len,ODBSQL_tmp_file,viewname);
+      }
+      else {
+	char *ODBSQL_tmp_file = 
+	  env ? "$TMPDIR/myview_%d.sql" : "./myview_%d.sql";
+	int len = STRLEN(ODBSQL_tmp_file) + 20;
+	int pid = (int)getpid();
+	ALLOC(tmp_file,len);
+	snprintf(tmp_file,len,ODBSQL_tmp_file,pid);
+      }
+      fp_out = FOPEN(tmp_file,"w");
+      WriteQuery(fp_out, sql_query);
+      FCLOSE(fp_out);
+      if (verbose) fprintf(stderr,"*** tmp_file='%s' created\n", tmp_file);
+      if (verbose) fprintf(stderr,"*** Treating file '%s' as stdin\n", odb_source);
+      /* if (stdin) fclose(stdin); */
+      /* stdin = FOPEN(odb_source, "r"); */
+      fp_in = freopen(odb_source, "r", stdin);
+      if (!fp_in || fp_in != stdin) {
+	PERROR(odb_source);
+	errflg++;
+      }
+      else {
+	ddl_piped++;
+	if (!odb_label) {
+	  char *pdot = strchr(odb_source,'.');
+	  if (pdot) *pdot = '\0';
+	  odb_label = transform_label(odb_source);
+	}
+	FREE(odb_source);
+	odb_source = STRDUP(tmp_file);
+      }
+    }
+    FREE(arg);
+  }
+  else if (argc > optind || sql_query) {
+    /* More than one file supplied or -q -option (or -Q) to supply the query was given */
+    FILE *fp_out = NULL;
+    char *env = getenv("TMPDIR");
+    char *viewname = getenv("ODB98_VIEWNAME");
+    if (viewname) {
+      char *ODBSQL_tmp_file = 
+	env ? "$TMPDIR/%s.sql" : "./%s.sql";
+      int len = STRLEN(ODBSQL_tmp_file) + STRLEN(viewname) + 1;
+      ALLOC(tmp_file,len);
+      snprintf(tmp_file,len,ODBSQL_tmp_file,viewname);
+    }
+    else {
+      char *ODBSQL_tmp_file = 
+	env ? "$TMPDIR/myview_%d.sql" : "./myview_%d.sql";
+      int len = STRLEN(ODBSQL_tmp_file) + 20;
+      int pid = (int)getpid();
+      ALLOC(tmp_file,len);
+      snprintf(tmp_file,len,ODBSQL_tmp_file,pid);
+    }
+    fp_out = FOPEN(tmp_file,"w");
+    if (sql_query) {
+      WriteQuery(fp_out, sql_query);
+    }
+    else {
+      for ( ; optind < argc; optind++) {
+	char *sqlfile = argv[optind];
+	/* fprintf(fp_out,"#include \"%s\"\n",sqlfile); */
+	if (ODB_copyfile(fp_out, sqlfile, NULL, NULL, 0, 1) <= 0) {
+	  fprintf(stderr,
+		  "***Error: Problems including SQL-file='%s' into tmp_file='%s'\n", 
+		  sqlfile, tmp_file);
+	  exit(1);
+	}
+      } /* for ( ; optind < argc; optind++) */
+    }
+    FCLOSE(fp_out);
+    if (verbose) fprintf(stderr,"*** tmp_file='%s' created\n", tmp_file);
+    odb_source = STRDUP(tmp_file);
+  }
+
+  if (filter_cmd) { /* Not tested */
+    /* Apply CPP + PERL filtering (or some other filterings)
+       Reason: Enable more relaxed input of KEYWORDs (say, in lowercase) */
+    char *cmd;
+    char *newfile;
+    ALLOC(newfile,STRLEN(odb_source) + 100);
+    sprintf(newfile,"%s__%d",odb_source,getpid());
+    ALLOC(cmd,STRLEN(filter_cmd) + STRLEN(odb_source) + STRLEN(newfile) + 10);
+    sprintf(cmd,"%s < %s > %s", filter_cmd, odb_source, newfile);
+    (void)system(cmd);
+    if (tmp_file) remove_file_(tmp_file);
+    tmp_file = STRDUP(newfile);
+    FREE(newfile);
+    FREE(odb_source);
+    odb_source = STRDUP(tmp_file);
+  }
+
+  if (odb_source) {
+    int len;
+    if (verbose) fprintf(stderr,"*** Input file = '%s'\n",odb_source);
+    p = strrchr(odb_source,'/');
+    if (!odb_label) {
+      char *xp = p ? ODB_uppercase(p+1) : ODB_uppercase(odb_source);
+      char *c  = strchr(xp,'.');
+      if (c) *c = '\0';
+      odb_label = transform_label(xp);
+      FREE(xp);
+    }
+    if (!odb_outpath) {
+      char *a = p ? STRDUP(odb_source) : NULL;
+      char *b = a ? strrchr(a,'/') : NULL;
+      if (b) *b = '\0'; 
+      odb_outpath = p ? STRDUP(a) : STRDUP(".");
+      FREE(a);
+    }
+    original_name = p ? STRDUP(p+1) : STRDUP(odb_source);
+    {
+      char *c = strchr(original_name,'.');
+      if (c) *c = '\0';
+    }
+
+    /* check for "ddl_" suffix ; do not allow such file for input */
+    len = STRLEN(odb_source);
+    if (len >= 5) {
+      if (strequ(&odb_source[len-5], ".ddl_")) {
+	fprintf(stderr, 
+		"***Error: Direct compilation of 'ddl_' file '%s' is forbidden\n",
+		odb_source);
+	errflg++;
+      }
+    }
+  }
+  else {
+    errflg++;
+  }
+
+  if (errflg) {
+    fprintf(stderr,USAGE,argv[0]);
+    exit(errflg);
+  }
+
+  Print_ODB_env();
+
+  p = strchr(odb_label,'.');
+  if (p) *p = '\0';
+  ALLOC(p, STRLEN(odb_label) + 3);
+  sprintf(p, "%s.c", odb_label);
+
+  /* Make sure env-variable ODB_SRCPATH_<dbname>/ODB_SRCPATH is available */
+  Check_Env(1, "ODB_SRCPATH", odb_label, NULL);
+
+  /* Make sure env-variable ODB_DATAPATH_<dbname>/ODB_DATAPATH is available */
+  Check_Env(1, "ODB_DATAPATH", odb_label, NULL);
+
+  /* Make sure env-variable ODB_IDXPATH_<dbname>/ODB_IDXPATH is available */
+  Check_Env(1, "ODB_IDXPATH", odb_label, "./idx");
+
+  Check_Empty_Tables(odb_label); /* Only applicable, if "-z" option was supplied */
+
+  /* fpdevnull = FOPEN(DEVNULL, "w"); */
+  fpdevnull = NULL; /* NULL is accepted, since we use our own ODB_fprintf(), not fprinf() */
+
+  if (verbose) fprintf(stderr,"*** Output source path = '%s'\n",odb_outpath);
+
+  if (ddl_piped) {
+    /* .ddl_ -file read/written from/to stdin/stdout */
+    fpsrc_file = views_only ? STRDUP("stdin") : STRDUP("stdout");
+  }
+  else {
+    int len = STRLEN(odb_outpath) + STRLEN(odb_label) + 7 + 1;
+    ALLOC(fpsrc_file, len);
+    snprintf(fpsrc_file, len, "%s/%s.ddl_", odb_outpath, odb_label);
+  }
+
+  yyin = FOPEN(odb_source,"r");
+
+  if (views_only) {
+    fpsrc = NULL; /* Since we are not writing anything out */
+    if (!scan_include(yyin, odb_label)) {
+      extern FILE *LEX_open_include(const char *filename);
+
+      if (!ddl_piped) {
+	if (!is_regular_file_(fpsrc_file)) {
+	  /* Trying "odb_syspath" instead of "odb_outpath" */
+	  int len = STRLEN(odb_syspath) + STRLEN(odb_label) + 7 + 1;
+	  FREE(fpsrc_file);
+	  ALLOC(fpsrc_file, len);
+	  snprintf(fpsrc_file, len, "%s/%s.ddl_", odb_syspath, odb_label);
+	}
+      }
+
+      (void) LEX_open_include(fpsrc_file);
+    }
+  }
+  else {
+    fpsrc = FOPEN(fpsrc_file, "w");
+  }
+
+  { /* Set defaults */
+    /* from yacc.y */
+    extern char *YACC_current_dbname;
+    extern char *YACC_current_srcpath;
+    extern char *YACC_current_datapath;
+    extern char *YACC_current_idxpath;
+    extern char *YACC_current_poolmask;
+    char *env;
+
+    YACC_current_dbname = STRDUP(odb_label);
+
+    env = Check_Env(0, "ODB_SRCPATH", odb_label, NULL);
+    YACC_current_srcpath = STRDUP(env);
+
+    env = Check_Env(0, "ODB_DATAPATH", odb_label, NULL);
+    YACC_current_datapath = STRDUP(env);
+
+    env = Check_Env(0, "ODB_IDXPATH", odb_label, "./idx");
+    YACC_current_idxpath = STRDUP(env);
+
+    env = getenv("ODB_PERMANENT_POOLMASK");
+    if (!env) env = "-1";
+    YACC_current_poolmask = STRDUP(env);
+  }
+
+  if (yyin) { 
+    while(!feof(yyin)) {
+      int success = yyparse();
+      Boolean done = (success != 0);
+      if (done) break;
+    } /* while(!feof(yyin)) */
+
+    FCLOSE(yyin);
+  }
+  else {
+    PERROR(odb_source);
+    errflg++;
+  }
+
+  FREE(fpsrc_file);
+
+  if (!errflg) {
+    if (fpsrc) {
+      fprintf(fpsrc,";\n");
+      FCLOSE(fpsrc);
+      fpsrc = NULL;
+    }
+    ODB_link_massage();
+  }
+
+  /* Change directory to ODB_OUTPATH for output files */
+
+  if (!errflg) {
+    char pold[4096]; 
+    getcwd(pold, sizeof(pold));
+    if (chdir(odb_outpath) == -1) {
+      PERROR(odb_outpath);
+      errflg++;
+    }
+    else {
+      if (verbose) {
+	char pnew[4096];
+	getcwd(pnew, sizeof(pnew));
+	if (verbose) fprintf(stderr,"==> Working directory: '%s' --> '%s'\n",pold,pnew);
+      }
+    }
+  }
+
+  if (debug) {
+    write_symbol_map();
+  }
+
+  /* Generate C-file(s) and compile */
+
+  if (!errflg) {
+    ODB_Filelist *flist = genc(views_only);
+    ODB_Filelist *x = flist;
+    int count = 0;
+    char *dbase_object = NULL;
+    char *table_obj_stack = NULL;
+
+    if (check_syntax_only) goto out_of_compile;
+
+    if (!x) {
+      fprintf(stderr,"*** No files to compile ***\n");
+      errflg++;
+    }
+    else {
+      while (x) {
+	count++;
+	/*
+	   fprintf(stderr,"Count#%d: filename=%s, create_so=%d\n",
+	   count, x->filename, (int)x->create_so);
+	   */
+	x = x->next;
+      }
+    }
+
+    if (views_only) {
+      char *dso_file = NULL;
+      Boolean found = 0;
+      ALLOC(dbase_object, STRLEN(odb_label) + 4);
+      sprintf(dbase_object,"%s.so",odb_label);
+      found = is_regular_file_(dbase_object);
+      if (!found) {
+	char *rldpath = getenv("ODB_RLDPATH");
+	if (verbose && create_so) {
+	  fprintf(stderr,
+		  "*** Warning: Not located '%s'\n",
+		  dbase_object);
+	}
+	if (rldpath) {
+	  char *token = strtok(rldpath,":");
+	  while (!found && token) {
+	    char *t = STRDUP(token);
+	    char *tcolon = strchr(t,':');
+	    if (tcolon) *tcolon = '\0';
+	    ALLOC(dso_file, STRLEN(t) + STRLEN(odb_label) + 5);
+	    sprintf(dso_file,"%s/%s.so",t,odb_label);
+	    FREE(t);
+	    found = is_regular_file_(dso_file);
+	    if (!found) {
+	      if (verbose && create_so) {
+		fprintf(stderr,
+			"*** Warning: Not located '%s'\n",
+			dso_file);
+	      }
+	    } /* if (!found) */
+	    if (!found) FREE(dso_file);
+	    token = strtok(NULL,":");
+	  }
+	} /* if (rldpath) */
+	if (found) {
+	  FREE(dbase_object);
+	  dbase_object = STRDUP(dso_file);
+	}
+      } /* if (!found) */
+      if (create_so) {
+	if (!found) {
+	  fprintf(stderr,
+		  "***Error: Database shareable object '%s' not located\n",
+		  dbase_object);
+	  errflg++;
+	}
+	else {
+	  fprintf(stderr,
+		  "Using database shareable object from '%s'\n",
+		  dbase_object);
+	}
+      } /* if (create_so) */
+    }
+    else {
+      dbase_object = STRDUP("");
+    }
+
+    while (flist) {
+      char *cmd;
+      char *file = flist->filename;
+      char *c_file, *o_file, *so_file;
+
+      ALLOC(c_file, STRLEN(file) + 3);
+      sprintf(c_file, "%s.c", file);
+
+      ALLOC(o_file, STRLEN(file) + 3);
+      sprintf(o_file, "%s.o", file);
+
+      ALLOC(so_file, STRLEN(file) + 4);
+      sprintf(so_file, "%s.so", file);
+
+      /* if (verbose) */ fprintf(stderr,"Compiling '%s' ...\n",c_file);
+
+      ALLOC(cmd, 
+	    STRLEN(Pwd) + STRLEN(o_file) + 
+	    STRLEN(odb_cc) + STRLEN(odb_syspath) + STRLEN(c_file) + 
+	    500);
+
+      sprintf(cmd,
+	      "%s/bin/rm -f %s;\n%s -c -I %s %s",
+	      Pwd, o_file, 
+	      odb_cc, odb_syspath, c_file);
+
+      Compile(cmd,0);
+
+      if (!is_regular_file_(o_file)) {
+	Boolean problem = 1;
+	/* Try to recover from unknown problems (especially with VPP700 cross compilation) */
+	/* Re-try #1 */
+	sprintf(cmd,
+		"%s/bin/rm -f %s;export TMPDIR=.;\n%s -c -I %s -DK0_lo_const %s",
+		Pwd, o_file, 
+		odb_cc, odb_syspath, c_file);
+	Compile(cmd,1);
+
+	if (is_regular_file_(o_file)) 
+	  problem = 0; /* Problem cleared */
+	else {
+	  /* Re-try #2 */
+	  sprintf(cmd,
+		  "%s/bin/rm -f %s;export TMPDIR=.;\n%s -c -I %s -DK0_lo_var %s",
+		  Pwd, o_file, 
+		  odb_cc, odb_syspath, c_file);
+	  Compile(cmd,2);
+	  if (is_regular_file_(o_file)) 
+	    problem = 0; /* Problem cleared */
+	}
+
+	if (problem) { /* A genuine problem ... sigh !! */
+	  fprintf(stderr,"***Error: C-compilation failed for '%s'\n",c_file);
+	  PERROR(o_file);
+	  errflg++;
+	}
+      }
+
+      FREE(cmd);
+
+      if (!errflg && create_so && flist->create_so) {
+	char *dobj = NULL;
+
+	if (STRLEN(dbase_object) == 0) {
+	  FREE(dbase_object);
+	  ALLOC(dbase_object, STRLEN(odb_label) + 4);
+	  sprintf(dbase_object,"%s.so",odb_label);
+	}
+
+	if (strequ(so_file,dbase_object)) {
+	  dobj = table_obj_stack ? STRDUP(table_obj_stack) : STRDUP("");
+	}
+	else {
+	  dobj = STRDUP(dbase_object);
+	}
+
+	ALLOC(cmd, 
+	      STRLEN(so_file) + 
+	      STRLEN(odb_ld) + STRLEN(o_file) + 
+	      STRLEN(so_file) + STRLEN(odb_libs) +
+	      STRLEN(dobj) +
+	      50);
+
+	sprintf(cmd,"\n\t%s\n\t/bin/rm -f %s;\n\t%s %s %s -o %s %s",
+		Pwd, so_file, 
+		odb_ld, o_file, dobj, so_file, odb_libs);
+
+	FREE(dobj);
+
+	if (verbose) fprintf(stderr,"## DSO creation: %s\n",cmd);
+	(void)system(cmd);
+	FREE(cmd);
+	
+	if (!is_regular_file_(so_file)) {
+	  fprintf(stderr,
+		  "***Error: Unable to create shareable object from '%s'\n",
+		  o_file);
+	  PERROR(so_file);
+	  errflg++;
+	}
+      } /* if (create_so && flist->create_so) */
+
+      if (!errflg && create_so && !flist->create_so && o_file) {
+	char *s = NULL;
+	int slen = STRLEN(o_file) + 1;
+	if (table_obj_stack) slen += STRLEN(table_obj_stack) + 1;
+	ALLOC(s,slen);
+	if (table_obj_stack) {
+	  sprintf(s,"%s %s",table_obj_stack,o_file);
+	  FREE(table_obj_stack);
+	} else {
+	  strcpy(s,o_file);
+	}
+	table_obj_stack = s;
+	if (verbose) fprintf(stderr,"Table object stack : '%s'\n",table_obj_stack);
+      }
+
+      FREE(c_file);
+      FREE(o_file);
+      FREE(so_file);
+
+      flist = flist->next;
+    } /* while (flist) */
+
+    FREE(dbase_object);
+    FREE(table_obj_stack);
+  } /* if (!errflg) */
+
+ out_of_compile: ;
+
+  FCLOSE(fpdevnull);
+
+  if (!debug && errflg) {
+    write_symbol_map();
+  }
+
+  FREE(original_name);
+
+  /* if (errflg == 0) remove_file_(tmp_file); */
+  exit(errflg);
+
+  return errflg;
+}
+
+/* Error trapping */
+
+/* Note: there was a #define exit ODB_exit in defs.h ; so all exit()'s call this */
+#undef exit
+/* Now reverted back to normal exit() */
+
+#if defined(SGI) || defined(VCCPX)
+PUBLIC void 
+errtra_()
+{
+  char cmd[1024];
+  static char def[] = "/usr/bin/echo where | /usr/bin/dbx -c /dev/null -p";
+  char *x = getenv("ODB_ERRTRA_CMD");
+  Boolean x_given = 0;
+  if (!x) x = def;
+  else x_given = 1;
+  sprintf(cmd,"%s %d",x,getpid());
+  if (x_given) fprintf(stderr,"\nerrtra_(): Executing '%s' ...\n",cmd);
+  fflush(stderr);
+  fflush(stdout);
+  (void)system(cmd);
+  fflush(stderr);
+  fflush(stdout);
+}
+#endif
+
+PUBLIC void
+ODB_exit(int status)
+{ 
+#if defined(SGI) || defined(VPPCX)
+  if (status != 0) errtra_();
+#endif
+  if (status != 0) fprintf(stderr,"***Error: Exiting with status = %d\n",status);
+  /* else fprintf(stderr,"\nExiting with status = %d\n",status); */
+  if (status != 0) {
+    extern int gdb_trbk();
+    extern FILE *fpinf;
+    FILE *fp = NULL;
+    if (fpinf) fp = fpinf;
+    else if (ddl_piped || ABS(filtered_info) != 0) fp = stdout;
+    ODB_fprintf(fp, "\n/error_code=%d\n", status);
+    if (!traceback_done) {
+      if (!gdb_trbk()) { }
+      /* else if (!dbx_tbrk();) { } ... to-be-done */
+      traceback_done = 1;
+    }
+  }
+  exit(status);
+}
+
+/* GNU-debugger traceback */
+
+#if !defined(GNUDEBUGGER)
+#define GNUDEBUGGER /usr/bin/gdb
+#endif
+
+#define PRETOSTR(x) #x
+#define TOSTR(x) PRETOSTR(x)
+
+PUBLIC
+int gdb_trbk()
+{
+  int invoked = 0;
+  char *gdb = getenv("GNUDEBUGGER");
+  /* fprintf(stderr,"[1] gdb_trbk(): gdb = '%s'\n",gdb ? gdb : NIL); */
+  if (!gdb) gdb = "1";
+  /* fprintf(stderr,"[2] gdb_trbk(): gdb = '%s' (exe=%s)\n",gdb ? gdb : NIL, TOSTR(GNUDEBUGGER)); */
+  if (gdb && (access(TOSTR(GNUDEBUGGER),X_OK) != 0)) gdb = NULL;
+  /* fprintf(stderr,"[3] gdb_trbk(): gdb = '%s'\n",gdb ? gdb : NIL); */
+  if (gdb && 
+      (strequ(gdb,"1")    || 
+       strequ(gdb,"true") || 
+       strequ(gdb,"TRUE"))) {
+    char gdbcmd[65536];
+    pid_t pid = getpid();
+    const char *a_out = main_prog ? main_prog : "./odb98.x";
+    fprintf(stderr,
+	    "[gdb_trbk] : Invoking %s ...\n",
+	    TOSTR(GNUDEBUGGER));
+    snprintf(gdbcmd,sizeof(gdbcmd),
+	     "set +e; /bin/echo '"
+	     "set watchdog 1\n"
+	     "set confirm off\n"
+	     "set pagination off\n"
+	     "set print elements 16\n"
+	     "set print repeats 3\n"
+	     "set print sevenbit-strings on\n"
+	     "where\n"
+	     "quit\n' > ./gdb_trbk.%d ; "
+	     "%s -x ./gdb_trbk.%d -q -n -f -batch %s %d < /dev/null ; "
+	     "/bin/rm -f ./gdb_trbk.%d"
+	     , pid
+	     , TOSTR(GNUDEBUGGER), pid, a_out, pid
+	     , pid);
+    
+    /* fprintf(stderr,"%s\n",gdbcmd); */
+    fflush(NULL);
+    (void)system(gdbcmd);
+    fflush(NULL);
+    invoked = 1;
+  }
+  return invoked;
+}
+
+PUBLIC void
+ODB_sigexit(int signum)
+{
+  fprintf(stderr,"***Error: Received signal#%d\n",signum);
+  if (!gdb_trbk()) { }
+  /* else if (!dbx_tbrk();) { } ... to-be-done */
+  traceback_done = 1;
+  ODB_exit(signum);
+}
+
diff --git a/odb/src/compiler/regex.c b/odb/src/compiler/regex.c
new file mode 100644
index 0000000..195bf92
--- /dev/null
+++ b/odb/src/compiler/regex.c
@@ -0,0 +1,101 @@
+#include "defs.h"
+
+/* See also lib/wildcard.c */
+
+#if defined(LINUX) || defined(SUN4) || defined(RS6K)
+/* Watch for this; This GNU-thing may now be okay for other systems, too */
+#include <regex.h>
+#define REGEX_DEF(p)      regex_t p
+#define REGCMP(p,pattern) status = regcomp(&p,pattern,REG_EXTENDED | REG_NOSUB)
+#define REGEX(p,s)        status = regexec(&p,s,0,NULL,0)
+#define REGFREE(p)        regfree(&p)
+#else
+#include <libgen.h>
+#define REGEX_DEF(p)      char *p
+#define REGCMP(p,pattern) p = regcmp(pattern,NULL), status = (p ? 0 : 1)
+#define REGEX(p,s)        status = (regex(p,s) ? 0 : 1)
+#define REGFREE(p)
+#endif
+
+PUBLIC int 
+ODB_regex(const char *s, ODB_Table **from, const int *from_attr, int nfrom)
+{
+  int count = 0;
+  int len;
+  char *rex = NULL;
+  int status;
+  REGEX_DEF(p);
+  
+  Boolean neg = 0;
+  Boolean ignore_case = 0;
+
+  if (*s == '/') {
+    rex = STRDUP(s+1);
+  }
+  else if (strnequ(s,"!/",2) || strnequ(s,"~/",2)) {
+    rex = STRDUP(s+2);
+    neg = 1;
+  }
+  else {
+    return 0;
+  }
+
+  len = STRLEN(rex);
+  ignore_case = (len > 3 && strncaseequ(&rex[len-2],"/i",2)); 
+
+  {
+    char *ptmp = strrchr(rex,'/');
+    if (ptmp) *ptmp = '\0';
+  }
+
+  if (ignore_case) {
+    char *c = ODB_lowercase(rex);
+    FREE(rex);
+    rex = c;
+  }
+
+  REGCMP(p, rex);
+
+  if (status == 0) {
+    int j;
+    /* fprintf(stderr,"$$$ regex-analyzing '%s'; nfrom=%d\n",s,nfrom); */
+    for (j=0; j<nfrom; j++) {
+      ODB_Table *pfrom = from[j];
+      int flag = from_attr[j];
+      /* Ignore auto-inserted tables, since these were not tables that user intended to have */
+      if ((flag & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) continue;
+      if (pfrom && pfrom->expname) {
+	int k;
+	for (k=0; k<pfrom->nsym; k++) {
+	  char *c = ignore_case ? 
+	    ODB_lowercase(pfrom->expname[k]) : STRDUP(pfrom->expname[k]);
+	  REGEX(p, c);
+	  FREE(c);
+	  if ((!neg && status==0) || (neg && status!=0)) {
+	    char *pvar = strchr(pfrom->expname[k],':');
+	    if (pvar) {
+	      char *var = STRDUP(pvar + 1);
+	      ODB_pushstr(var);
+	      count++;
+	      /*
+	      fprintf(stderr,"\t$$$ table='%s': match#%d for '%s'\n",pfrom->table->name,count,var);
+	      {
+		int kk;
+		for (kk=0; kk<pfrom->nsym; kk++) {
+		  fprintf(stderr,"\t  >>> '%s': col#%d = '%s'\n",pfrom->table->name,kk+1,pfrom->expname[kk]);
+		}
+	      }
+	      */
+	    }
+	  } /* if ((!neg && status==0) || (neg && status!=0)) */
+	} /* for (k=0; k<pfrom->nsym; k++) */
+      } /* if (pfrom && pfrom->expname) */
+    } /* for (j=0; j<nfrom; j++) */
+  }
+  
+  REGFREE(p);
+
+  FREE(rex);
+
+  return count;
+}
diff --git a/odb/src/compiler/tree.c b/odb/src/compiler/tree.c
new file mode 100644
index 0000000..d6288b3
--- /dev/null
+++ b/odb/src/compiler/tree.c
@@ -0,0 +1,6005 @@
+
+/* tree.c */
+
+#include "defs.h"
+#include "magicwords.h"
+#include "pcma_extern.h"
+
+extern Boolean verbose;
+extern int safeGuard;
+extern int LEX_in_where;
+
+extern int bailout_level;
+extern char *bailout_string;
+extern int ddl_piped;
+extern Boolean debug;
+
+PUBLIC  Boolean ODB_tables_done = 0;
+
+PUBLIC  Boolean ODB_in_tabledef = 0;
+PUBLIC  Boolean has_USD_symbols = 0;
+PUBLIC  Boolean has_OFFSET_func = 0;
+
+PUBLIC  Boolean has_count_star = 0;
+PUBLIC  Boolean has_usddothash = 0;
+PUBLIC  Boolean no_from_stmt = 0;
+
+PUBLIC int ODB_nsymbols = 0;
+PUBLIC int ODB_nUSDsymbols = 0;
+PUBLIC int ODB_nHASHsymbols = 0;
+PUBLIC int ODB_nBSNUMsymbols = 0;
+PUBLIC int ODB_ntypes = 0;
+PUBLIC int ODB_ntables = 0;
+PUBLIC int ODB_nviews = 0;
+PUBLIC int ODB_nnodes = 0;
+PUBLIC int ODB_hollerith_strings = 0;
+PUBLIC Boolean ODB_has_links = 0;
+
+
+/* Used in ODB_link_massage() */
+
+typedef struct cmptable_t {
+  double wt;
+  ODB_Table *p;
+} Cmptable_t;
+
+PRIVATE int cmptable(const Cmptable_t *a, const Cmptable_t *b) {
+  if      ( a->wt < b->wt ) return -1;
+  else if ( a->wt > b->wt ) return  1;
+  else			    return  0;
+}
+
+/* Used in ODB_reorder_tables() */
+
+typedef struct cmpfromtable_t {
+  double wt;
+  int rank;
+  int flag;
+} Cmpfromtable_t;
+
+PRIVATE int cmpfromtable(const Cmpfromtable_t *a, const Cmpfromtable_t *b) {
+  if      ( a->wt < b->wt ) return -1;
+  else if ( a->wt > b->wt ) return  1;
+  else			    return  0;
+}
+
+PRIVATE ODB_Tree *first_oper      = NULL;
+PRIVATE ODB_Tree *last_oper = NULL;
+
+PRIVATE ODB_Symbol *first_symbol      = NULL;
+PRIVATE ODB_Symbol *last_symbol = NULL;
+
+PRIVATE ODB_Type *first_type      = NULL;
+PRIVATE ODB_Type *last_type = NULL;
+
+PRIVATE ODB_Table *first_table      = NULL;
+PRIVATE ODB_Table *last_table = NULL;
+
+PUBLIC ODB_Table **table_hier = NULL;
+
+PRIVATE ODB_View *first_view      = NULL;
+PRIVATE ODB_View *last_view = NULL;
+
+/* Registered functions */
+
+static double ftrunc(double x); /* As in funcs.h included later in this file */
+
+static
+double lldegrees(double d)
+{
+  extern int latlon_rad;
+  if (latlon_rad != 0) d = R2D(d);
+  /* if (d > 180) d -= 360; */
+  return d;
+}
+
+static
+double llradians(double d)
+{
+  extern int latlon_rad;
+  if (latlon_rad != 1) d = D2R(d);
+  /* if (d > pi) d -= 2*pi; */
+  return d;
+}
+
+static double dint(double d); /* from funcs.h */
+
+static
+double timestamp(double indate, double intime)
+{ /* Merge "YYYYMMDD" and "HHMMSS" into "YYYYMMDDHHMMSS" */
+  double outstamp = RMDI; /* Missing data indicator : here indicates error */
+  if (indate >= 0 && indate <= INT_MAX &&
+      intime >= 0 && intime <= 240000) {
+    long long int lldate = (long long int)indate;
+    long long int lltime = (long long int)intime;
+    long long int tstamp = lldate * 1000000ll + lltime;
+    outstamp = tstamp;
+    outstamp = dint(outstamp);
+  }
+  return outstamp;
+}
+
+
+static
+double basetime(double indate, double intime)
+{ /* Merge "YYYYMMDD" and "HHMMSS" into "YYYYMMDDHH" */
+  double outstamp = RMDI; /* Missing data indicator : here indicates error */
+  if (indate >= 0 && indate <= INT_MAX &&
+      intime >= 0 && intime <= 240000) {
+    long long int lldate = (long long int)indate;
+    long long int lltime = (long long int)intime;
+    long long int tstamp = lldate * 1000000ll + (lltime/10000ll);
+    outstamp = tstamp;
+    outstamp = dint(outstamp);
+  }
+  return outstamp;
+}
+
+
+static
+int boxid(double x, double deltax, double xmin, double xmax,
+	  int wrap_around_ok)
+{
+  int id = NMDI;
+  if (deltax < 0) deltax = -deltax;
+  if (deltax != 0 && xmin < xmax) {
+    double xspan = xmax - xmin;
+    int n = (int)(xspan/deltax);
+    id = (int)((x - xmin)/deltax);
+    if (id < 0 || id >= n) {
+      if (wrap_around_ok) {
+	if (id < 0) id = n-1;
+	else if (id >= n) id = 0;
+      }
+      else {
+	if (id < 0) id = 0;
+	else if (id >= n) id = n-1;
+      }
+    }
+  }
+  return id;
+}
+
+static
+double box(double x, double deltax, double xmin, double xmax,
+	   int wrap_around_ok)
+{
+  double value = RMDI;
+  if (deltax < 0) deltax = -deltax;
+  if (deltax != 0 && xmin < xmax) {
+    int id = boxid(x,deltax,xmin,xmax,wrap_around_ok);
+    value = xmin + id * deltax + 0.5 * deltax;
+  }
+  return value;
+}
+
+static
+double boxid_lat(double lat, double deltalat)
+{
+  const double latmax = 90;
+  return boxid(lat,deltalat,-latmax,+latmax,0);
+}
+
+static
+double boxlat(double lat, double deltalat)
+{
+  const double latmax = 90;
+  return box(lat,deltalat,-latmax,+latmax,0);
+}
+
+static
+double boxid_lon(double lon, double deltalon)
+{
+  const double lonmax = 180;
+  return boxid(lon,deltalon,-lonmax,+lonmax,1);
+}
+
+static
+double boxlon(double lon, double deltalon)
+{
+  const double lonmax = 180;
+  return box(lon,deltalon,-lonmax,+lonmax,1);
+}
+
+#include "funcs.h"
+
+typedef struct _kw_t {
+  char *name;
+  int   token_def;
+} kw_t;
+
+static int Nkw = 0;
+
+PRIVATE kw_t 
+keyword[] = {
+  "number", ODB_NUMBER,
+  "symref", ODB_NAME,
+  "$symref", ODB_USDNAME,
+  "#symref", ODB_HASHNAME,
+  "\\bsnum", ODB_BSNUM,
+  "nickname", ODB_NICKNAME,
+  "arrname", ODB_ARRNAME,
+  "hollerith", ODB_STRING,
+  "wildcard", ODB_WC_STRING,
+  "LIKE", ODB_LIKE,
+  "NOTLIKE", ODB_NOTLIKE,
+  "==", ODB_EQ,
+  "+", ODB_ADD,
+  "-", ODB_SUB,
+  "*", ODB_STAR,
+  "/", ODB_DIV,
+  "", ODB_UNARY_PLUS,
+  "-", ODB_UNARY_MINUS,
+  "||", ODB_OR,
+  "&&", ODB_AND,
+  "!", ODB_NOT,
+  ">", ODB_GT,
+  ">=", ODB_GE,
+  "<", ODB_LT,
+  "<=", ODB_LE,
+  "!=", ODB_NE,
+  "<=>", ODB_CMP,
+  "set", ODB_SET,
+  "typeref", ODB_TYPE,
+  "tableref", ODB_TABLE,
+  "viewref", ODB_VIEW,
+  "function", ODB_FUNC,
+  "string_function", ODB_STRFUNC,
+  "inside_function", ODB_INSIDE,
+  "inside_polygon_function", ODB_INSIDE_POLYGON,
+  "near_function", ODB_NEAR,
+  "str1_function", ODB_STRFUNC1,
+  "aggregate_function", ODB_FUNCAGGR,
+  "where_symbol",ODB_WHERE_SYMBOL,
+  "query",ODB_QUERY,
+  "match_function",ODB_MATCH,
+  "?", ODB_QMARK,
+  ":", ODB_COLON,
+  "|", ODB_NORM,
+  NULL
+};
+
+
+PRIVATE int
+cmpstr_kw(const void *A, const void *B)
+{
+  const kw_t *a = A;
+  const kw_t *b = B;
+  if      ( a->token_def < b->token_def ) return -1;
+  else if ( a->token_def > b->token_def ) return  1;
+  else			                  return  0;
+}
+
+
+PUBLIC char *
+ODB_keymap(int what)
+{
+  if (Nkw == 0) { /* Very first time only */
+    const kw_t *pkw = keyword;
+    while (pkw->name) {
+      Nkw++;
+      pkw++;
+    }
+    qsort(keyword, Nkw, sizeof(kw_t), cmpstr_kw);
+  } /* if (Nkw == 0) */
+  {
+    static char unknown[] = "<unknown>";
+    kw_t *pkw = NULL;
+    kw_t key;
+    key.token_def = what;
+    pkw = bsearch(&key, keyword, Nkw, sizeof(kw_t), cmpstr_kw);
+    return pkw ? pkw->name : unknown;
+  }
+}
+
+PUBLIC ODB_Tree *
+ODB_start_oper() { return first_oper; }
+
+PUBLIC ODB_Symbol *
+ODB_start_symbol() { return first_symbol; }
+
+PUBLIC ODB_Type *
+ODB_start_type() { return first_type; }
+
+PUBLIC ODB_Table *
+ODB_start_table() { return first_table; }
+
+PUBLIC ODB_View *
+ODB_start_view() { return first_view; }
+
+PUBLIC char *
+ODB_extract(const char *in, int left_delim, int right_delim)
+{
+  char *rc = NULL;
+  if (in) {
+    char *p = STRDUP(in);
+    int lenp = strlen(p);
+    char *pleft = 
+      BETWEEN(left_delim,0,255) ? strchr(p, left_delim) : p - 1;
+    rc = STRDUP(in);
+    if (pleft) {
+      char *pright = NULL;
+      pleft++;
+      pright = 
+	BETWEEN(right_delim,0,255) ? strchr(pleft, right_delim) : &p[lenp];
+      if (pright) {
+	*pright = '\0';
+	FREE(rc);
+	rc = STRDUP(pleft);
+      }
+    } /* if (pleft) */
+    FREE(p);
+  }
+
+  /*
+  if (rc) fprintf(stderr,
+		  "ODB_extract: from='%s' with delims %c and %c gives '%s'\n",
+		  in, left_delim, right_delim, rc);
+		  */
+
+  return rc;
+}
+
+
+PRIVATE int
+cmpstr_funcs(const void *A, const void *B)
+{
+  const funcs_t *a = A;
+  const funcs_t *b = B;
+  return strcmp(a->name, b->name);
+}
+
+
+PRIVATE const funcs_t *
+get_func(const char *name)
+{
+  if (NfuncS == 0) { /* Very first time only */
+    const funcs_t *pf = Func;
+    while (pf->name) {
+      NfuncS++;
+      pf++;
+    }
+    qsort(Func, NfuncS, sizeof(funcs_t), cmpstr_funcs);
+  } /* if (NfuncS == 0) */
+
+  {
+    funcs_t *pf = NULL;
+    funcs_t key;
+    key.name = (char *)name;
+    pf = bsearch(&key, Func, NfuncS, sizeof(funcs_t), cmpstr_funcs);
+    if (pf) return pf;
+  }
+  /* Ending up here ? ==> Error */
+  SETMSG1("Unrecognized function '%s'",name);
+  YYerror(msg);
+  return NULL;
+}
+
+
+PRIVATE const funcs_t *
+check_func(const char *name, int numargs, 
+	   const int *min_numargs, const int *max_numargs)
+{
+  const funcs_t *pf = get_func(name);
+  if (pf) {
+    if (pf->numargs == -1) { /* Variable no. of arguments */
+      Boolean will_abort = 0;
+      if (min_numargs && (numargs < *min_numargs)) {
+	SETMSG3("Incorrect no. of args (%d) passed to the function '%s'. Expecting at least %d.",
+		numargs,name,*min_numargs);
+	YYwarn(1,msg); /* "1" to get "*** Error" message printed ; no abort yet */
+	will_abort = 1;
+      }
+      if (max_numargs && (numargs > *max_numargs)) {
+	SETMSG3("Incorrect no. of args (%d) passed to the function '%s'. Expecting no more than %d.",
+		numargs,name,*max_numargs);
+	YYwarn(1,msg); /* "1" to get "*** Error" message printed ; no abort yet */
+	will_abort = 1;
+      }
+      if (will_abort) exit(1);
+      return pf;
+    }
+    if (pf->numargs == numargs) return pf;
+    SETMSG3("Incorrect no. of args (%d) passed to the function '%s'. Expecting %d.",
+	    numargs,name,pf->numargs);
+    YYerror(msg);
+  } /* if (pf) */
+  /* Ending up here ? ==> Error */
+  SETMSG1("Unrecognized function '%s'",name);
+  YYerror(msg);
+  return NULL;
+}
+
+
+PRIVATE char *
+symref(const ODB_Symbol *p)
+{
+  char *s, *name = NULL;
+  int len = 20;
+  if (p) {
+    if (p->name) {
+      name = p->name;
+      len += strlen(name);
+    }
+  }
+  ALLOC(s, len);
+  snprintf(s,len,"[%p,'%s']",p,name ? name : NIL);
+  return s;
+}
+
+
+PUBLIC void
+ODB_print_symbols(FILE *fp)
+{
+  int j;
+  if (!fp) fp = stderr;
+
+  fprintf(fp,"*** ODB_print_symbols() ***\n");
+
+  fprintf(fp,"\tNo. of symbols = %d : kind = ODB_NAME = %d\n",
+	  ODB_nsymbols, ODB_NAME);
+  fprintf(fp,"\tNo. of $-symbols = %d : kind = ODB_USDNAME = %d\n",
+	  ODB_nUSDsymbols, ODB_USDNAME);
+  fprintf(fp,"\tNo. of #-symbols = %d : kind = ODB_HASHNAME = %d\n",
+	  ODB_nHASHsymbols, ODB_HASHNAME);
+  fprintf(fp,"\tNo. of \\-symbols = %d : kind = ODB_BSNUM = %d\n",
+	  ODB_nBSNUMsymbols, ODB_BSNUM);
+  fprintf(fp,"\tNo. of holleriths = %d : kind = ODB_STRING = %d\n",
+	  ODB_hollerith_strings, ODB_STRING);
+  fprintf(fp,"\tNo. of types   = %d : kind = ODB_TYPE = %d\n",
+	  ODB_ntypes, ODB_TYPE);
+  fprintf(fp,"\tNo. of tables  = %d : kind = ODB_TABLE = %d\n",
+	  ODB_ntables, ODB_TABLE);
+  fprintf(fp,"\tNo. of views   = %d : kind = ODB_VIEW = %d\n",
+	  ODB_nviews, ODB_VIEW);
+
+  { /* Symbol table */
+    ODB_Symbol *p = ODB_start_symbol();
+    for (; p != NULL; p = p->next) {
+      fprintf(fp,"symref=%p: name='%s', kind=(%d,%s), dval=%g, dname='%s', flag=0x%x\n",
+	      p, p->name?p->name:NIL, 
+	      p->kind, ODB_keymap(p->kind),
+	      p->dval, p->dname ? p->dname : NIL,
+	      p->flag);
+    }
+  }
+
+  { /* Type definitions */
+    ODB_Type *p = ODB_start_type();
+    for (; p != NULL; p = p->next) {
+      char *s = symref(p->type);
+      fprintf(fp,"typeref=%p: symref=%s, nsym=%d, no_members=%d, bitstream=%d\n",
+	      p, s, p->nsym, (int)p->no_members, (int)p->bitstream);
+      FREE(s);
+
+      if (p->nsym > 0) {
+	fprintf(fp,"  : symrefs & members=\n");
+	for (j=0; j<p->nsym; j++) {
+	  s = symref(p->sym[j]);
+	  fprintf(fp,"\t%s",s);
+	  FREE(s);
+	  s = symref(p->member[j]);
+	  fprintf(fp," & %s",s);
+	  FREE(s);
+	  if (p->bitstream) {
+	    fprintf(fp," : bit (pos=%d,len=%d)",p->pos[j],p->len[j]);
+	  }
+	  fprintf(fp,"\n");
+	}
+      } /* if (p->nsym > 0) */
+
+    }
+  }
+
+  { /* Table definitions */
+    ODB_Table *p = ODB_start_table();
+    for (; p != NULL; p = p->next) {
+      char *s = symref(p->table);
+      fprintf(fp,"tableref=%p: symref=%s, nsym=%d\n",
+	      p, s, p->nsym);
+      FREE(s);
+
+      if (p->nsym > 0) {
+	char **expname = p->expname;
+	fprintf(fp,"  : typerefs & symrefs=\n");
+	for (j=0; j<p->nsym; j++) {
+	  ODB_Type *type = p->type[j];
+	  int linkmode;
+	  s = symref(type ? type->type : NULL);
+	  fprintf(fp,"\t%p : %s",type,s);
+	  FREE(s);
+	  if (expname) {
+	    s = expname[j] ? expname[j] : NULL;
+	    fprintf(fp," & expname='%s'",s?s:NIL);
+	  }
+	  s = symref(p->sym[j]);
+	  linkmode = p->linkmode[j];
+	  fprintf(fp," & %s & linkmode = %d\n",s,linkmode);
+	  FREE(s);
+	}
+      } /* if (p->nsym > 0) */
+
+      if (p->nlink > 0) {
+	int nlink = p->nlink; 
+	fprintf(fp,"  : nlink=%d\n",nlink);
+	for (j=0; j<nlink; j++) {
+	  char *s = p->linkname[j];
+	  fprintf(fp,"\tlink#%d, linkname='%s' ",j,s?s:NIL);
+	  if (p->link[j]) {
+	    s = symref(p->link[j]->table);
+	    fprintf(fp,": tableref=%p, symref=%s\n",
+		    p->link[j],s);
+	    FREE(s);
+	  }
+	  else {
+	   fprintf(fp,": tableref=UNDEFINED\n"); 
+	  }
+	}
+      } /* if (p->nlink > 0) */
+
+    }
+  }
+
+  { /* View definitions */
+    ODB_View *p = ODB_start_view();
+    for (; p != NULL; p = p->next) {
+      char *s = symref(p->view);
+      fprintf(fp,"viewref=%p: symref=%s\n",p, s);
+      FREE(s);
+      fprintf(fp,"  : nselect=%d, nselect_all=%d, nfrom=%d, nwhere=%d, norderby=%d",
+	      p->nselect, p->nselect_all, p->nfrom, p->nwhere, p->norderby);
+      fprintf(fp,", WHERE-code is %s",
+	      p->cond ? "present" : "NOT present");
+      if (p->cond) fprintf(fp," at %p",p->cond);
+
+      if (p->nselect > 0) {
+	fprintf(fp,"  : symrefs(SELECT)=\n");
+	for (j=0; j<p->nselect; j++) {
+	  s = symref(p->select[j]);
+	  fprintf(fp,"\t%s",s);
+	  FREE(s);
+	  if (p->table_index) {
+	    fprintf(fp," : tid = %d", p->table_index[j]);
+	  }
+	  if (p->tag) {
+	    fprintf(fp," : tag = '%s'",p->tag[j] ? p->tag[j] : NIL);
+	  }
+	  if (p->call_arg) {
+	    fprintf(fp," : arg = '%s'",p->call_arg[j] ? p->call_arg[j] : NIL);
+	  }
+	  if (p->def_put && p->alias_put) {
+	    fprintf(fp,"\n\t  : #define %s(d,i) %s",
+		    p->def_put[j], p->alias_put[j]);
+	  }
+	  if (p->def_get && p->alias_get) {
+	    fprintf(fp,"\n\t  : #define %s(d,i) %s",
+		    p->def_get[j], p->alias_get[j]);
+	  }
+	  fprintf(fp,"\n");
+	}
+      } /* if (p->nselect > 0) */
+
+      if (p->nfrom > 0) {
+	fprintf(fp,"  : tablerefs(FROM)=\n");
+	for (j=0; j<p->nfrom; j++) {
+	  ODB_Table *table = p->from[j];
+	  s = symref(table ? table->table : NULL);
+	  fprintf(fp,"\t%p : %s\n",table,s);
+	  FREE(s);
+	}
+      } /* if (p->nfrom > 0) */
+
+      if (p->nwhere > 0) {
+	int k;
+	fprintf(fp,"  : symrefs(WHERE)=\n");
+	for (j=0, k=p->nselect_all; j<p->nwhere; j++, k++) {
+	  s = symref(p->where[j]);
+	  fprintf(fp,"\t%s",s);
+	  FREE(s);
+	  if (p->table_index) {
+	    fprintf(fp," : table_index = %d", p->table_index[k]);
+	  }
+	  if (p->tag) {
+	    fprintf(fp," : tag = '%s'",p->tag[k] ? p->tag[k] : NIL);
+	  }
+	  if (p->def_put && p->alias_put) {
+	    fprintf(fp,"\n\t  : #define %s(i,d) %s",
+		    p->def_put[k]   ? p->def_put[k]   : NIL, 
+		    p->alias_put[k] ? p->alias_put[k] : NIL);
+	  }
+	  if (p->def_get && p->alias_get) {
+	    fprintf(fp,"\n\t  : #define %s(i,d) %s",
+		    p->def_get[k]   ? p->def_get[k]   : NIL,
+		    p->alias_get[k] ? p->alias_get[k] : NIL);
+	  }
+	  fprintf(fp,"\n");
+	}
+      } /* if (p->nwhere > 0) */
+
+      if (p->norderby > 0) {
+	int k;
+	fprintf(fp,"  : symrefs(ORDERBY)=\n");
+	for (j=0, k=p->nselect_all+p->nwhere; j<p->norderby; j++, k++) {
+	  int key = p->mkeys[j];
+	  s = symref(p->orderby[j]);
+	  fprintf(fp,"\t%s : sorting key#%d",s,key);
+	  FREE(s);
+	  if (p->tag) {
+	    fprintf(fp," : tag = '%s'",p->tag[k] ? p->tag[k] : NIL);
+	  }
+	  fprintf(fp,"\n");
+	}
+      } /* if (p->norderby > 0) */
+
+    }
+  }
+
+  fprintf(fp,"*** End of ODB_print_symbols() ***\n");
+}
+
+PRIVATE ODB_dbcred *AssignDBCred()
+{
+  /* from yacc.y */
+  extern char *YACC_current_dbname;
+  extern char *YACC_current_srcpath;
+  extern char *YACC_current_datapath;
+  extern char *YACC_current_idxpath;
+  extern char *YACC_current_poolmask;
+  ODB_dbcred *p = NULL;
+  CALLOC(p, 1);
+  p->dbname   = STRDUP(YACC_current_dbname);
+  p->srcpath  = STRDUP(YACC_current_srcpath);
+  p->datapath = STRDUP(YACC_current_datapath);
+  p->idxpath  = STRDUP(YACC_current_idxpath);
+  p->poolmask = STRDUP(YACC_current_poolmask);
+  return p;
+}
+
+
+PRIVATE char *
+hash_massage(const char *s)
+{
+  char *p;
+  int len = strlen(s) + 2;
+  ALLOC(p, len);
+  snprintf(p,len,"#%s",s);
+  return p;
+}
+
+PRIVATE char *
+s2d_join(const char *s, int count)
+{
+  char *p;
+  int len = strlen(s) + 2;
+  ALLOC(p,len);
+  snprintf(p,len,"%s%d",s,count);
+  return p;
+}
+
+PRIVATE char *
+s2d_massage(const char *s, int kind)
+{
+  char *psm, *sm;
+
+  if (kind == ODB_STRING) {
+    /* Leading blank removal */
+    while (*s) {
+      if (*s != ' ') break;
+      s++;
+    }
+  }
+
+  {
+    int len = S2DLEN + strlen(s) + 1;
+    ALLOC(sm, len);
+    snprintf(sm,len,"%s%s",S2D,s);
+  }
+
+  if (kind == ODB_STRING) {
+    psm = sm + S2DLEN;
+    while (*psm) {
+      /* Replace non-printables with a question mark */
+      if (!isprint(*psm)) *psm = '?';
+      psm++;
+    }
+  }
+
+  return sm;
+}
+
+PRIVATE double
+s2d(const char *s, int kind)
+{
+  const int ns = sizeof(double);
+  union {
+    double dval;
+    char   s[sizeof(double)+1];
+  } u;
+  int len = strlen(s);
+
+  memset(u.s,' ',ns);
+
+  if (len < ns && kind == ODB_STRING) {
+    /* Right justify */
+    int offset = ns - len;
+    strncpy(&u.s[offset],s,len);
+  }
+  else {
+    strncpy(u.s, s, ns);
+  }
+  u.s[ns] = '\0';
+
+  /* fprintf(stderr,"s2d: in='%s', out='%s'\n",s,u.s); */
+
+  return u.dval;
+}
+
+
+PRIVATE char *
+d2s(double d)
+{
+  const int ns = sizeof(double);
+  union {
+    double dval;
+    char   s[sizeof(double)+1];
+  } u;
+  u.dval = d;
+  u.s[ns] = '\0';
+  return STRDUP(u.s);
+}
+
+
+PUBLIC Boolean
+ODB_is_oper(void *p)
+{
+  Boolean is_oper = 0;
+  if (p) {
+    ODB_Tree *ptest = p;
+    ODB_Tree *pnode = ODB_start_oper();
+    for (; pnode != NULL; pnode = pnode->next) {
+      if (pnode == ptest) {
+	is_oper = 1;
+	break;
+      }
+    }
+  }
+  return is_oper;
+}
+
+
+PUBLIC Boolean
+ODB_is_symbol(void *p)
+{
+  Boolean is_symbol = 0;
+  if (p) {
+    ODB_Symbol *ptest = p;
+    ODB_Symbol *psym = ODB_start_symbol();
+    for (; psym != NULL; psym = psym->next) {
+      if (psym == ptest) {
+	is_symbol = 1;
+	break;
+      }
+    }
+  }
+  return is_symbol;
+}
+
+
+PUBLIC ODB_Symbol *
+ODB_lookup(int kind, const char *name, ODB_Symbol *start_symbol)
+{
+  if (name) {
+    ODB_Symbol *psym = start_symbol ? start_symbol : ODB_start_symbol();
+    if (verbose) fprintf(stderr,
+			 "ODB_lookup: kind=(%d,%s), name='%s'\n",
+			 kind, ODB_keymap(kind), name);
+    if (kind == ODB_STRING || kind == ODB_WC_STRING) {
+      for (; psym != NULL; psym = psym->next) {
+	if (psym->kind == kind && psym->dname) {
+	  char *s = s2d_massage(name, kind);
+	  if (strequ(psym->dname, &s[S2DLEN])) {
+	    FREE(s);
+	    return psym;
+	  }
+	  FREE(s);
+	}
+      }
+    }
+    else if (LEX_in_where && kind == ODB_USDNAME && IS_USDDOTHASH(name)) {
+      /* Disallow use of "$<parent_tblname>.<child_tblname>#" in WHERE-stmt */
+      SETMSG1("It is forbidden to use '$parent.child#' -variable (now '%s') in WHERE-statement",name);
+      YYwarn(1,msg); /* Warn only ,but will most likely abort later due to this */
+      return NULL; 
+    }
+    else { /* Speeded up lookup */
+      uint hash = ODB_hash(kind, name);
+      for (; psym != NULL; psym = psym->next) {
+	if (psym->hash == hash && psym->kind == kind && strequ(psym->name, name)) return psym;
+      }
+    }
+  }
+  return NULL; /* No symbol found */
+}
+
+PUBLIC ODB_Type *
+ODB_lookup_type(const char *name, ODB_Type *start_type)
+{
+  ODB_Type *ptype = start_type ? start_type : ODB_start_type();
+
+  for (; ptype != NULL; ptype = ptype->next) {
+    ODB_Symbol *psym = ptype->type;
+    if (strequ(psym->name, name)) return ptype;
+  }
+
+  return NULL; /* No type found */
+}
+
+PUBLIC ODB_Table *
+ODB_lookup_table(const char *name, ODB_Table *start_table)
+{
+  ODB_Table *ptable = start_table ? start_table : ODB_start_table();
+  uint hash = ODB_hash(ODB_TABLE, name);
+  for (; ptable != NULL; ptable = ptable->next) {
+    ODB_Symbol *psym = ptable->table;
+    if (psym->hash == hash && strequ(psym->name, name)) return ptable;
+  }
+
+  return NULL; /* No table found */
+}
+
+
+PUBLIC Boolean
+ODB_in_table(int kind, const char *name, const ODB_Table *ptable, int *index)
+{
+  /* "name" can be a (a) string "#table_name"
+                     (b) column entry name, when kind = ODB_NAME
+		     (c) column type name, when kind = ODB_TYPE
+  */
+  Boolean in_table = 0;
+
+  if (index) *index = -1; /* Not found (or a HASH-symbol) */
+
+  if (name && ptable) {
+    if (IS_HASH(name)) {
+      char *p = hash_massage(ptable->table->name);
+      in_table = strequ(p,name);
+      FREE(p);
+    }
+    else {
+      int j, nsym = ptable->nsym;
+      for (j=0; j<nsym; j++) {
+	ODB_Symbol *psym = (kind == ODB_TYPE) ? ptable->type[j]->type : ptable->sym[j];
+	if (psym && strequ(psym->name, name)) {
+	  if (index) *index = j;
+	  in_table = 1;
+	  break;
+	}
+      } /* for (j=0; j<nsym; j++) */
+    }
+  }
+
+  return in_table;
+}
+
+
+PUBLIC Boolean
+ODB_in_type(const char *name, const ODB_Type *ptype, int *index)
+{
+  Boolean in_type = 0;
+
+  if (index) *index = -1; /* Not found */
+
+  if (name && ptype) {
+    int j, nsym = ptype->nsym;
+
+    for (j=0; j<nsym; j++) {
+      ODB_Symbol *psym = ptype->member[j];
+      if (strequ(psym->name, name)) {
+	if (index) *index = j;
+	in_type = 1;
+	break;
+      }
+    } /* for (j=0; j<nsym; j++) */
+  }
+
+  return in_type;
+}
+
+
+PUBLIC ODB_View *
+ODB_lookup_view(const char *name, ODB_View *start_view)
+{
+  ODB_View *pview = start_view ? start_view : ODB_start_view();
+
+  for (; pview != NULL; pview = pview->next) {
+    ODB_Symbol *psym = pview->view;
+    if (strequ(psym->name, name)) return pview;
+  }
+
+  return NULL; /* No type found */
+}
+
+
+PUBLIC ODB_Symbol *
+ODB_new_symbol(int kind, const char *s)
+{
+  ODB_Symbol *psym = ODB_lookup(kind, s, NULL);
+
+  if (!psym) {
+    Boolean okay = 0;
+    okay |= (kind == ODB_NAME);
+    okay |= (kind == ODB_NICKNAME);
+    okay |= (kind == ODB_STRING);
+    okay |= (kind == ODB_WC_STRING);
+    okay |= (ODB_in_tabledef && (kind == ODB_TYPE));
+    okay |= (ODB_in_tabledef && (kind == ODB_USDNAME));
+
+    if (!okay) {
+      if (strchr(s, '@') || strchr(s, '.')) {
+	SETMSG3("Symbol '%s' of kind=(%d,%s) cannot contain \"@\" or \".\"",
+		s, kind, ODB_keymap(kind));
+	YYerror(msg);
+      }
+    }
+
+    if (verbose) fprintf(stderr,
+			 "ODB_new_symbol: kind=(%d,%s), name='%s'\n",
+			 kind, ODB_keymap(kind), s);
+
+    CALLOC(psym, 1);
+
+    if (first_symbol)  
+      last_symbol->next = psym;
+    else 
+      first_symbol = psym;
+    last_symbol = psym;
+
+    psym->kind = kind;
+
+    if (kind == ODB_STRING || kind == ODB_WC_STRING) {
+      char *sm = s2d_massage(s, kind);
+      psym->name = s2d_join(S2D,ODB_hollerith_strings);
+      psym->dname = STRDUP(&sm[S2DLEN]);
+      psym->dval = s2d(psym->dname, kind);
+      psym->sorig = STRDUP(s);
+      FREE(sm);
+    }
+    else if (kind == ODB_HASHNAME) {
+      psym->name = hash_massage(s+1);
+      psym->dname = NULL;
+      psym->dval = 0;
+      psym->sorig = NULL;
+    }
+    else {
+      psym->name = STRDUP(s);
+      psym->dname = NULL;
+      psym->dval = 0;
+      psym->sorig = NULL;
+    }
+    psym->hash = ODB_hash(psym->kind, psym->name);
+
+    psym->flag = 0;
+    psym->only_view = 0;
+    psym->next = NULL;
+
+    if (kind == ODB_USDNAME || IS_DOLLAR(s)) {
+      has_USD_symbols = 1;
+      ODB_nUSDsymbols++;
+      psym->only_view = (ODB_tables_done || ODB_ntables > 0);
+    }
+    else if (kind == ODB_STRING || kind == ODB_WC_STRING)
+      ODB_hollerith_strings++;
+    else if (kind == ODB_HASHNAME)
+      ODB_nHASHsymbols++;
+    else if (kind == ODB_BSNUM)
+      ODB_nBSNUMsymbols++;
+    else 
+      ODB_nsymbols++;
+  }
+
+  return psym;
+}
+
+
+PUBLIC ODB_Symbol *
+ODB_symbol_copy(ODB_Symbol *psym)
+{
+  ODB_Symbol *p = psym ? ODB_new_symbol(psym->kind, psym->name) : NULL;
+  return p;
+}
+
+
+PUBLIC ODB_Type *
+ODB_new_type(const char *s, Boolean reuse_okay)
+{
+  ODB_Type *ptype = ODB_lookup_type(s, NULL);
+
+  if (ptype && !reuse_okay) {
+    SETMSG1("An attempt to redefine an existing type '%s'",s);
+    YYerror(msg);
+  }
+
+  if (!ptype) {
+    ODB_Symbol *psym = ODB_new_symbol(ODB_TYPE, s);
+
+    ALLOC(ptype, 1);
+    
+    if (first_type)  
+      last_type->next = ptype;
+    else 
+      first_type = ptype;
+    last_type = ptype;
+    
+    ptype->type = psym;
+    ptype->nsym = 0;
+    ptype->sym  = NULL;
+    ptype->member = NULL;
+    
+    ptype->bitstream = 0;
+    ptype->no_members = 0;
+    ptype->processed = 0;
+    ptype->pos = NULL;
+    ptype->len = NULL;
+    
+    ptype->next = NULL;
+
+    ODB_ntypes++;
+  }    
+
+  return ptype;
+}
+
+PUBLIC ODB_Table *
+ODB_copy_table(const ODB_Table *from, const char *name)
+{
+  ODB_Table *p = ODB_lookup_table(name, NULL);
+
+  if (p && name) {
+    ODB_Table *ptable = ODB_start_table();
+    ODB_Table *prev = NULL;
+    
+    for (; ptable != NULL; ptable = ptable->next) {
+      if (ptable == p) {
+	/* The "ptable" becomes obsolete and will be replaced by the "new" */
+	ODB_Table *new;
+	ALLOC(new, 1);
+	/* Copy "from" to "new" ; as-is */
+	memcpy(new, from, sizeof(*new));
+	/*
+	  fprintf(stderr,
+		"$$$ copy_table: from=('%s' at %p), to='%s' <i.e. '%s' at %p>\n",
+		from->table->name, from,
+		name,
+		ptable->table->name, ptable);
+	*/
+	/* .. but retain some old entries */
+	new->table = ptable->table;
+	new->tableno = ptable->tableno;
+	new->rank = ptable->rank;
+	new->wt = ptable->wt;
+	/* correct expanded names */
+	{
+	  int nsym = new->nsym;
+	  int j;
+	  ALLOC(new->expname, nsym);
+	  for (j=0; j<nsym; j++) {
+	    char *x;
+	    char *oldname = STRDUP(from->expname[j]);
+	    x = strchr(oldname,'@');
+	    if (x) {
+	      char *newname;
+	      int newlen;
+	      *++x = '\0';
+	      newlen = strlen(oldname) + strlen(name) + 1;
+	      ALLOC(newname, newlen);
+	      snprintf(newname,newlen,"%s%s",oldname,name);
+	      new->expname[j] = newname;
+	    }
+	    else {
+	      new->expname[j] = STRDUP(oldname);
+	    }
+	    FREE(oldname);
+	  } /* for (j=0; j<nsym; j++) */
+	}
+	/* Don't forget to update the chain */
+	new->next = ptable->next;
+	if (prev) prev->next = new;
+	if (ptable == first_table) first_table = new;
+	if (ptable == last_table)  last_table = new;
+	p = new;
+	break;
+      }
+      prev = ptable;
+    } /* for (; ptable != NULL; ptable = ptable->next) */
+  } /* if (p) */
+
+  return p;
+}
+
+PUBLIC ODB_Table *
+ODB_new_table(const char *s, Boolean reuse_okay)
+{
+  ODB_Table *ptable = ODB_lookup_table(s, NULL);
+
+  if (ptable && !reuse_okay) {
+    SETMSG1("An attempt to redefine an existing table '%s'",s);
+    YYerror(msg);
+  }
+
+  if (ODB_tables_done) {
+    SETMSG1("No more table defs allowed after view defs. Occured at table '%s'",s);
+    YYerror(msg);
+  }
+
+  if (!ptable) {
+    ODB_Symbol *psym = ODB_new_symbol(ODB_TABLE, s);
+
+    ALLOC(ptable, 1);
+
+    if (first_table)  
+      last_table->next = ptable;
+    else 
+      first_table = ptable;
+    last_table = ptable;
+
+    ptable->table = psym;
+    ptable->tableno = ODB_ntables++;
+    ptable->rank = ptable->tableno; /* the default in absence of a better value so far */
+    ptable->nsym = 0;
+    ptable->wt = 0;
+    ptable->type = NULL;
+    ptable->sym  = NULL;
+    ptable->expname = NULL;
+    ptable->linkslavemask = NULL;
+    ptable->nlink = 0;
+    ptable->link  = NULL;
+    ptable->sharedlink = NULL;
+    ptable->sharedlinkname = NULL;
+    ptable->any_sharedlinks = 0;
+
+    ptable->db = AssignDBCred();
+
+    ptable->next = NULL;
+  }    
+
+  return ptable;
+}
+
+PUBLIC const char *
+ODB_NickName(int colnum)
+{
+  /* The default nickname for each SQL-column : 
+     un-addressable  "<a><number>" where <a> is ARTIFICIAL_NICKCHAR = \a in defs.h */
+  static char s[20];
+  snprintf(s,sizeof(s),"%c%d",ARTIFICIAL_NICKCHAR,colnum);
+  return s;
+}
+
+PUBLIC ODB_View *
+ODB_new_view(const char *s, Boolean reuse_okay)
+{
+  extern int use_indices;
+  extern char *use_index_name;
+  extern int reorder_tables;
+  extern int insert_tables;
+  extern Boolean LEX_binary_index;
+  ODB_View *pview = ODB_lookup_view(s, NULL);
+
+  if (pview && !reuse_okay) {
+    SETMSG1("An attempt to redefine an existing view '%s'",s);
+    YYerror(msg);
+  }
+
+  if (!pview) {
+    ODB_Symbol *psym = ODB_new_symbol(ODB_VIEW, s);
+
+    CALLOC(pview, 1);
+
+    if (first_view)  
+      last_view->next = pview;
+    else 
+      first_view = pview;
+    last_view = pview;
+
+    pview->view    = psym;
+
+    pview->db = AssignDBCred();
+
+    pview->create_index = 0;
+    pview->binary_index = LEX_binary_index;
+
+    pview->nselect = 0;
+    pview->nselect_all = 0;
+    pview->select  = NULL;
+
+    pview->sel = NULL;
+    pview->is_formula = NULL;
+    pview->has_formulas = 0;
+    pview->nselsym = 0;
+    pview->selsym = NULL;
+
+    pview->ncols_aux = 0;
+
+    pview->select_distinct = 0;
+    pview->usddothash = 0;
+    pview->use_indices = use_indices;
+    pview->use_index_name = use_index_name ? STRDUP(use_index_name) : STRDUP("*");
+    pview->reorder_tables = reorder_tables;
+    pview->insert_tables = insert_tables;
+    pview->has_count_star = 0;
+    pview->safeGuard = 0;
+
+    pview->select_aggr_flag = ODB_AGGR_NONE;
+
+    pview->no_from_stmt = 0;
+    pview->nfrom_start = 0;
+    pview->nfrom   = 0;
+    pview->from    = NULL;
+    pview->from_attr = NULL;
+    pview->maxfrom = INT_MAX;
+    pview->active  = NULL;
+    pview->merged_with = NULL;
+
+    pview->nwhere  = 0;
+    pview->where   = NULL;
+
+    pview->nuniqueby = 0;
+    pview->uniqueby = NULL;
+
+    pview->has_thin = 0;
+
+    pview->norderby = 0;
+    pview->orderby = NULL;
+    pview->mkeys = NULL;
+
+    pview->table_index = NULL;
+    pview->tag = NULL;
+
+    pview->call_arg = NULL;
+
+    pview->def_put = NULL;
+    pview->alias_put = NULL;
+
+    pview->def_get = NULL;
+    pview->alias_get = NULL;
+
+    pview->poslen = NULL;
+
+    pview->cond = NULL;
+    pview->andlist = NULL;
+    pview->andlen = 0;
+
+    pview->next = NULL;
+
+    ODB_nviews++;
+  }    
+
+  return pview;
+}
+
+PUBLIC int
+ODB_remove_duplicates(SymbolParam_t *in, 
+		      int  *table_index,
+		      char **tag,
+		      char **call_arg,
+		      char **def_put,
+		      char **alias_put,
+		      char **def_get,
+		      char **alias_get,
+		      char **poslen,
+		      char **offset)
+{
+  int ndrem = 0;
+  if (in) {
+    int j;
+    int nsym = in->nsym;
+
+    init_list(NULL);
+    for (j=0; j<nsym; j++) {
+      char *s = tag ? tag[j] : in->sym[j]->name;
+      char *p;
+      int len = strlen(s) + 3;
+      ALLOC(p, len);
+      snprintf(p, len, "/%s/", s);
+      if (!in_list(p)) {
+	add_list(p);
+	in->sym[ndrem] = in->sym[j];
+	in->readonly[ndrem] = in->readonly[j];
+	if (in->sel) in->sel[ndrem] = in->sel[j];
+	if (table_index) table_index[ndrem] = table_index[j];
+	if (tag) tag[ndrem] = STRDUP(tag[j]);
+	if (call_arg) call_arg[ndrem] = STRDUP(call_arg[j]);
+	if (def_put) def_put[ndrem] = STRDUP(def_put[j]);
+	if (alias_put) alias_put[ndrem] = STRDUP(alias_put[j]);
+	if (def_get) def_get[ndrem] = STRDUP(def_get[j]);
+	if (alias_get) alias_get[ndrem] = STRDUP(alias_get[j]);
+	if (poslen) poslen[ndrem] = STRDUP(poslen[j]);
+	if (offset) offset[ndrem] = STRDUP(offset[j]);
+	ndrem++;
+      }
+      FREE(p);
+    } /* for (j=0; j<nsym; j++) */
+    destroy_list();
+
+    if (table_index) {
+      for (j=ndrem; j<nsym; j++) {
+	table_index[j] = RMDI;
+      } /* for (j=ndrem; j<nsym; j++) */
+    } /* if (table_index) */
+
+    in->nsym = ndrem;
+  }
+  return ndrem;
+}
+
+
+PUBLIC Boolean 
+ODB_dupl_symbols(ODB_Symbol **psym, int nsym, Boolean extract)
+{
+  Boolean dupl_exist = 0;
+  int dupl_count = 0;
+  int j;
+
+  init_list(NULL);
+
+  if (extract) {
+    for (j=0; j<nsym; j++) {
+      char *name = psym[j]->name;
+      if (!strnequ(name,"LINKLEN(",8)) {
+	char *s = ODB_extract(name,'(',')');
+	char *p;
+	int len = strlen(s) + 3;
+
+	ALLOC(p, len);
+	snprintf(p, len, "/%s/", s);
+	
+	if (!in_list(p)) {
+	  add_list(p);
+	  FREE(p);
+	}
+	else {
+	  FREE(p);
+	  dupl_count++;
+	}
+
+	FREE(s);
+      }
+    } /* for (j=0; j<nsym; j++) */
+  }
+  else {
+    for (j=0; j<nsym; j++) {
+      char *s = psym[j]->name;
+      char *p;
+      int len = strlen(s) + 3;
+
+      ALLOC(p, len);
+      snprintf(p, len, "/%s/", s);
+      
+      if (!in_list(p)) {
+	add_list(p);
+	FREE(p);
+      }
+      else {
+	FREE(p);
+	dupl_count++;
+      }
+    } /* for (j=0; j<nsym; j++) */
+  }
+
+  destroy_list();
+
+  dupl_exist = (dupl_count > 0);
+
+  return dupl_exist;
+}
+
+
+PUBLIC void
+ODB_link_massage()
+{
+  if (!ODB_tables_done) {
+    /* Resolve any outstanding links to the other tables */
+
+    ODB_Table *ptable;
+    Boolean on_error = 0;
+    ODB_Table **all_tables = NULL;
+
+    if (debug) {
+      int j = 0;
+      CALLOC(all_tables, ODB_ntables);
+      for (ptable = ODB_start_table() ; ptable != NULL; ptable = ptable->next) {
+	all_tables[j++] = ptable;
+      }
+    }
+    
+    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+      int nlink = ptable->nlink;
+
+      CALLOC(ptable->linkslavemask,ODB_ntables);
+      
+      if (nlink > 0) {
+	int j;
+	char *tablename = ptable->table->name;
+
+	ODB_has_links = 1;
+	
+	for (j=0; j<nlink; j++) {
+	  char *xx = ptable->linkname[j];
+	  char *yy = ptable->sharedlinkname[j];
+	  /* fprintf(stderr,"ODB_link_massage(): <%s> : j/nlink=%d,%d : xx='%s', yy='%s'\n",
+		  tablename, j,nlink, xx, yy); */
+	  if (!ptable->link[j]) {
+	    char *linkname = ptable->linkname[j];
+	    ODB_Table *p = ODB_lookup_table(linkname, NULL);
+	    if (!p) {
+	      fprintf(stderr,
+		      "Unable to establish a link from table '%s' to the undefined table '%s'\n",
+		      tablename, linkname);
+	      on_error = 1;
+	    }
+	    ptable->link[j] = p;
+	  } /* if (!ptable->link[j]) */
+
+	  /* Shareable links (if any) */
+	  if (ptable->sharedlinkname[j] && !ptable->sharedlink[j]) {
+	    char *linkname = ptable->sharedlinkname[j];
+	    ODB_Table *p = ODB_lookup_table(linkname, NULL);
+	    if (!p) {
+	      fprintf(stderr,
+		      "Unable to establish shareable link from table '%s' to a non-existent table '%s'\n",
+		      tablename, linkname);
+	      on_error = 1;
+	    }
+	    ptable->sharedlink[j] = p;
+	  } /* Shareable links (if any) */
+	} /* for (j=0; j<nlink; j++) */
+      } /* if (nlink > 0) */
+    } /* for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) */
+    
+    if (on_error) YYerror("Table linking failed");
+
+    process_one_tables(NULL,NULL,NULL);
+
+    { 
+      /* 
+	 Assign weights for use by FROM-stmt based on how the links span 
+         Fill in the linkslavemask, too 
+      */
+
+      ODB_linklist *list = manage_linklist(FUNC_LINKLIST_START,NULL,NULL,0);
+      int j;
+      const double delta_link = 1;
+      const double delta_align = 1;
+      const double delta_onelooper = 1;
+
+      for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	int nlink = ptable->nlink;
+	if (nlink > 0) {
+	  int jtbl = ptable->tableno;
+	  for (j=0; j<nlink; j++) {
+	    ODB_Table *p = ptable->link[j];
+	    p->linkslavemask[jtbl] = 4; /* Is behind a link */
+	    p->wt += delta_link; /* Increase weight by delta for direct links (on slave-side only) */
+	  } /* for (j=0; j<nlink; j++) */
+	} /* if (nlink > 0) */
+      }
+
+      if (debug) {
+	int j;
+	fprintf(stderr,"Initial weights :\n");
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  fprintf(stderr,"[%d] ptable->table->name = '%s' : initial weight = %.6f\n",
+		  ptable->tableno, ptable->table->name, ptable->wt);
+	  for (j=0; j<ODB_ntables; j++) {
+	    fprintf(stderr," %s=%d",
+		    all_tables[j]->table->name,
+		    (int)ptable->linkslavemask[j]);
+	  }
+	  fprintf(stderr,"\n");
+	}
+      }
+
+      if (list) { /* Indirect LINKs (via ALIGN/ONELOOPER) */
+	ODB_Table **ptcache = NULL;
+	CALLOC(ptcache,ODB_ntables);
+
+	if (debug) fprintf(stderr,
+			   "ptcache(ODB_ntables=%d) : Indirect LINKs (via ALIGN/ONELOOPER) : list=%p\n",
+			   ODB_ntables, list);
+
+	while (list) {
+	  if (debug) fprintf(stderr,
+			     "list : n_rhs=%d, lhs=%s, type=%d (only #1, ONELOOPER or #2, ALIGN considered)\n",
+			     list->n_rhs, list->lhs ? list->lhs : NIL, list->type);
+	  if (list->n_rhs > 0 && 
+	      (list->type == 1 || list->type == 2)) {
+	    int n = 0;
+
+	    { /* Calculate n (= count of existing tables) and 
+		 fill ptcache (= participating & existing tables) */
+	      struct _rhs_t *first_rhs = list->rhs;
+	      ptable = ODB_lookup_table(list->lhs, NULL);
+	      if (ptable) ptcache[n++] = ptable;
+	      while (first_rhs) {
+		ptable = ODB_lookup_table(first_rhs->name, NULL);
+		if (ptable) ptcache[n++] = ptable;
+		first_rhs = first_rhs->next;
+	      } /* while (first_rhs) */
+	    }
+
+	    if (debug) fprintf(stderr, "\tptcache(n=%d)\n",n);
+
+	    if (n > 1) {
+	      int j1, j2, jtbl;
+	      if (list->type == 2) { /* ALIGN'ed (or -A) tables */
+		/* 
+		   Add delta-weight to BOTH tables' weights, but make sure
+		   you do this only once, since there maybe redundant
+		   -A or ALIGN-statements for a subset of tables; like
+		   -Aa=(b,c,d)
+		   -Ab=(c,d)
+		*/
+		for (j1=0; j1<n; j1++) {
+		  ptable = ptcache[j1];
+		  jtbl = ptable->tableno;
+		  for (j2=j1+1; j2<n; j2++) {
+		    ODB_Table *p = ptcache[j2];
+		    int jj = p->tableno;
+		    if ((ptable->linkslavemask[jj] & list->type) != list->type) { /* "master" */
+		      ptable->wt += delta_align;
+		      ptable->linkslavemask[jj] |= list->type; /* No more updates for this */
+		    }
+		    if ((p->linkslavemask[jtbl] & list->type) != list->type) { /* "slave" */
+		      p->wt += delta_align;
+		      p->linkslavemask[jtbl] |= list->type; /* No more updates for this */
+		    }
+		  } /* for (j2=j1+1; j2<n; j2++) */
+		} /* for (j1=0; j1<n; j1++) */
+	      }
+	      else if (list->type == 1) { /* ONELOOPER's (or -1) tables */
+		/*
+		  Add delta-weight to slave-table only and also make sure
+		  this is done only once (the reason is the same as with ALIGN).
+		  Also add delta-weight only if master & slave have a true "LINK-manship"
+		  i.e. linktype[] & 4 at slave is equal to 4
+		*/
+		for (j1=0; j1<n; j1++) {
+		  ptable = ptcache[j1];
+		  jtbl = ptable->tableno;
+		  for (j2=j1+1; j2<n; j2++) {
+		    ODB_Table *p = ptcache[j2];
+		    int jj = p->tableno;
+		    if ((ptable->linkslavemask[jj] & list->type) != list->type) {
+		      if ((ptable->linkslavemask[jj] & 4) == 4) { /* I'm a slave */
+			ptable->wt += delta_onelooper;
+			ptable->linkslavemask[jj] |= list->type; /* No more updates for this */
+		      }
+		    }
+		    if ((p->linkslavemask[jtbl] & list->type) != list->type) {
+		      if ((p->linkslavemask[jtbl] & 4) == 4) { /* I'm a slave */
+			p->wt += delta_onelooper;
+			p->linkslavemask[jtbl] |= list->type; /* No more updates for this */
+		      }
+		    }
+		  } /* for (j2=j1+1; j2<n; j2++) */
+		} /* for (j1=0; j1<n; j1++) */
+	      } /* if (list->type == 2) ... else if (list->type == 1) ... */
+	    } /* if (n > 1) */
+	  } /* if (list->n_rhs > 0 && ... */
+	  list = list->next;
+	} /* while (list) */
+	FREE(ptcache);
+      } /* if (list) */
+
+      if (debug) {
+	int j;
+	fprintf(stderr,"Intermediate, stage#2 weights :\n");
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  fprintf(stderr,"[%d] ptable->table->name = '%s' : intermed. weight = %.6f : mask=\n",
+		  ptable->tableno, ptable->table->name, ptable->wt);
+	  for (j=0; j<ODB_ntables; j++) {
+	    fprintf(stderr," %s=%d",
+		    all_tables[j]->table->name,
+		    (int)ptable->linkslavemask[j]);
+	  }
+	  fprintf(stderr,"\n");
+	}
+      }
+
+      /* Now make sure that ALIGNed tables have themselves the same weight
+	 Iterate until convergence (as in "final order" below) */
+      {
+	int changed;
+	int iter = 0;
+	const int maxiter = 2 * ODB_ntables;
+	ODB_linklist *saved_list = manage_linklist(FUNC_LINKLIST_START,NULL,NULL,0);
+	ODB_Table **ptcache = NULL;
+	CALLOC(ptcache,ODB_ntables);
+
+	if (debug) fprintf(stderr,
+			   "ptcache(ODB_ntables=%d) : Iterate until convergence : saved_list=%p\n",
+			   ODB_ntables, saved_list);
+	do {
+	  changed = 0;
+	  list = saved_list;
+	  while (list) {
+	    if (debug) fprintf(stderr,
+			       "list : n_rhs=%d, lhs=%s, type=%d (only #2, ALIGN considered)\n",
+			       list->n_rhs, list->lhs ? list->lhs : NIL, list->type);
+	    if (list->n_rhs > 0 && 
+		list->type == 2) { /* 2 --> consider ALIGNed (or -A) tables only */
+	      int n = 0;
+	      
+	      { /* Calculate n (= count of existing tables) and 
+		   fill ptcache (= participating & existing tables) */
+		struct _rhs_t *first_rhs = list->rhs;
+		ptable = ODB_lookup_table(list->lhs, NULL);
+		if (ptable) ptcache[n++] = ptable;
+		while (first_rhs) {
+		  ptable = ODB_lookup_table(first_rhs->name, NULL);
+		  if (ptable) ptcache[n++] = ptable;
+		  first_rhs = first_rhs->next;
+		} /* while (first_rhs) */
+	      }
+	      
+	      if (debug) fprintf(stderr, "\tptcache(n=%d)\n",n);
+
+	      if (n > 1) {
+		int jtbl;
+		double maxwt = 0; /* Puts tables lower in the hierarchy */
+		for (jtbl=0; jtbl<n; jtbl++) {
+		  ODB_Table *p = ptcache[jtbl];
+		  maxwt = MAX(maxwt,p->wt);
+		} /* for (jtbl=0; jtbl<n; jtbl++) */
+		for (jtbl=0; jtbl<n; jtbl++) {
+		  ODB_Table *p = ptcache[jtbl];
+		  if (p->wt != maxwt) {
+		    p->wt = maxwt;
+		    changed++;
+		  }
+		} /* for (jtbl=0; jtbl<n; jtbl++) */
+	      } /* if (n > 1) */
+	    } /* if (list->n_rhs > 0 && ... */
+	    list = list->next;
+	  } /* while (list) */
+	} while (changed && ++iter < maxiter);
+
+	FREE(ptcache);
+
+	if (changed && iter >= maxiter) { /* Abort */
+	  SETMSG1("Cannot resolve ALIGNed tables' ordering in %d iterations. Check for possible table-recursion",iter);
+	  YYerror(msg);
+	}
+      }
+
+      if (debug) {
+	int j;
+	fprintf(stderr,"Intermediate, stage#2 weights :\n");
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  fprintf(stderr,"[%d] ptable->table->name = '%s' : intermed. weight = %.6f : mask=\n",
+		  ptable->tableno, ptable->table->name, ptable->wt);
+	  for (j=0; j<ODB_ntables; j++) {
+	    fprintf(stderr," %s=%d",
+		    all_tables[j]->table->name,
+		    (int)ptable->linkslavemask[j]);
+	  }
+	  fprintf(stderr,"\n");
+	}
+      }
+
+      /* The semi-final order : a tie-breaker
+	 Add "seed" to weight from initial table ordering (1 millionth)
+       */
+
+      {
+	const double eps = 0.000001;
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  ptable->wt += eps * ptable->tableno;
+	}
+      }
+
+      /* The final order : 
+	 Adjust weights so that master (parent) table can never have 
+	 larger weight than the slave (child) table.
+	 This examination and alteration goes on over the genuine links only.
+	 As result, the smaller the weight, the higher in the hierarchy
+	 the FROM-table ends up being placed.
+      */
+
+      {
+	const double eps = 0.001;
+	int changed;
+	int iter = 0;
+	const int maxiter = 2 * ODB_ntables;
+	do {
+	  changed = 0;
+	  for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	    int nlink = ptable->nlink;
+	    if (nlink > 0) { /* Check only genuine links (for now) */
+	      double parent_wt = ptable->wt;
+	      for (j=0; j<nlink; j++) {
+		ODB_Table *p = ptable->link[j];
+		if (p->wt <= parent_wt) {
+		  /* child receives parent weight 
+		     (+ epsilon to make it really bigger i.e. lower in the hierarchy) */
+		  p->wt = parent_wt + eps;
+		  changed++;
+		}
+	      } /* for (j=0; j<nlink; j++) */
+	    } /* if (nlink > 0) */
+	  }
+	} while (changed && ++iter < maxiter);
+
+	if (changed && iter >= maxiter) { /* Abort */
+	  SETMSG1("Cannot resolve table ordering in %d iterations. Check for possible table-recursion",iter);
+	  YYerror(msg);
+	}
+      }
+
+      { /* Calculate rank order number in the hierarchy */
+	int j;
+	Cmptable_t *cmp = NULL;
+	ALLOC(cmp, ODB_ntables);
+	for (ptable = ODB_start_table(), j=0; ptable != NULL; ptable = ptable->next, j++) {
+	  cmp[j].wt = ptable->wt;
+	  cmp[j].p  = ptable;
+	}
+	qsort(cmp, ODB_ntables, sizeof(*cmp), 
+	      (int (*)(const void *, const void *))cmptable);
+	ALLOC(table_hier, ODB_ntables);
+	for (j=0; j<ODB_ntables; j++) {
+	  table_hier[j] = cmp[j].p;
+	  cmp[j].p->rank = j;
+	}
+	FREE(cmp);
+      }
+
+      if (debug) {
+	int j;
+	fprintf(stderr,"Final weights & rank :\n");
+	for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	  fprintf(stderr,"[%d] [rank=%d] ptable->table->name = '%s' : final weight = %.6f, mask=\n",
+		  ptable->tableno, ptable->rank, ptable->table->name, ptable->wt);
+	  for (j=0; j<ODB_ntables; j++) {
+	    fprintf(stderr," %s=%d",
+		    all_tables[j]->table->name,
+		    (int)ptable->linkslavemask[j]);
+	  }
+	  fprintf(stderr,"\n");
+	}
+      }
+    }
+
+    FREE(all_tables);
+
+    ODB_tables_done = 1;
+  }
+}
+
+
+/* === PRIVATE routines === */
+
+PUBLIC int GetSign(const char *poffset)
+{
+  int sign = 0;
+  if (poffset && !strequ(poffset,"0")) {
+    if (*poffset == '-' || *poffset == '_') sign = -1;
+    else if (*poffset == '+') sign = +1;
+  }
+  return sign;
+}
+
+
+PRIVATE char *ZZtop(const char *poffset, int sign) {
+  char *zz = NULL;
+  if (poffset && !strequ(poffset, "0")) {
+    int len = 3 + STRLEN(poffset) + 1;
+    ALLOC(zz, len);
+    snprintf(zz, len, "_Z%s%s",
+	     (sign < 0) ? "_" : "",
+	     poffset+ABS(sign));
+  }
+  else
+    zz = STRDUP("");
+  return zz;
+}
+
+PRIVATE char *TheWho(const char *poffset, int sign) {
+  char *zz = NULL;
+  if (poffset && !strequ(poffset, "0")) {
+    int len = 1 + STRLEN(poffset) + 1;
+    ALLOC(zz, len);
+    snprintf(zz, len, "%s%s",
+	     sign ? "" : "+",
+	     poffset+ABS(sign));
+  }
+  else
+    zz = STRDUP("");
+  return zz;
+}
+
+PRIVATE char *GreenDay(const char *poffset) {
+  char *zz = NULL;
+  if (poffset && !strequ(poffset, "0")) {
+    int len = STRLEN(ODB_OFFSET_CHAR) + STRLEN(poffset) + 1;
+    ALLOC(zz, len);
+    snprintf(zz, len, "%s%s",
+	     ODB_OFFSET_CHAR, poffset);
+  }
+  else
+    zz = STRDUP("");
+  return zz;
+}
+
+PRIVATE ODB_Tree *
+new_node(int what)
+{
+  ODB_Tree *pnode;
+
+  CALLOC(pnode, 1);
+
+  if (first_oper)  
+    last_oper->next = pnode;
+  else 
+    first_oper = pnode;
+  last_oper = pnode;
+
+  pnode->what    = what;
+  pnode->dval    = 0;
+  pnode->argc    = 0;
+  pnode->argv    = NULL;
+  pnode->level   = -1;
+  pnode->joffset = 0;
+  pnode->next    = NULL;
+
+  ODB_nnodes++;
+
+  return pnode;
+}
+
+
+PUBLIC ODB_Tree *
+ODB_oper_copy(ODB_Tree *expr, Boolean recursive)
+{
+  ODB_Tree *pnode = NULL;
+  if (expr) {
+    pnode = new_node(expr->what);
+    pnode->dval    = expr->dval;
+    pnode->argc    = expr->argc;
+    pnode->level   = expr->level;
+    if (pnode->argc > 0) {
+      int j, n = pnode->argc;
+      ALLOC(pnode->argv, n);
+      for (j=0; j<n; j++) {
+	void *p = expr->argv[j];
+	if (ODB_is_symbol(p)) {
+	  pnode->argv[j] = ODB_symbol_copy(p);
+	}
+	else if (ODB_is_oper(p)) {
+	  pnode->argv[j] = recursive ? ODB_oper_copy(expr->argv[j],1) : expr->argv[j];
+	}
+	else { /* Something else : do not copy */
+	  pnode->argv[j] = expr->argv[j];
+	}
+      }
+    }
+    else {
+      pnode->argv = NULL;
+    }
+  }
+  return pnode;
+}
+
+typedef struct Alias_Type_t {
+  char *true_type;
+  char *your_type;
+  struct Alias_Type_t *next;
+} AliasType;
+
+PRIVATE AliasType *alias_type_start = NULL;
+PRIVATE AliasType *alias_type = NULL;
+
+PRIVATE Boolean
+add_alias(const char *true_type, const char *your_type)
+{
+  Boolean already_there = 0;
+  AliasType *p;
+
+  for (p = alias_type_start; p != NULL; p = p->next) {
+    if (strequ(p->your_type, your_type)) {
+      already_there = 1;
+      break;
+    }
+  }
+
+  if (!already_there) {
+    ALLOC(p, 1);
+
+    if (!alias_type_start) {
+      /* Get started */
+      alias_type_start = p;
+      alias_type_start->true_type = NULL;
+      alias_type_start->your_type = NULL;
+      alias_type_start->next      = NULL;
+    }
+
+    /* Add it */
+    p->true_type = STRDUP(true_type);
+    p->your_type = STRDUP(your_type);
+    p->next      = NULL;
+    if (alias_type) alias_type->next = p;
+    alias_type = p;
+  }
+
+  return already_there;
+}
+
+PRIVATE const char *
+getalias(const char *your_type)
+{
+  const char *true_type = your_type;
+  AliasType *p;
+
+  for (p = alias_type_start; p != NULL; p = p->next) {
+    if (strequ(p->your_type, your_type)) {
+      true_type = p->true_type;
+      break;
+    }
+  }
+  return true_type;
+}
+
+
+PUBLIC int 
+ODB_evaluate(ODB_Tree *pnode, double *dval)
+     /* For compile-time expression evalution only */
+{
+  int irc = 0;
+
+  *dval = 0;
+
+  if (pnode) {
+    switch (pnode->what) {
+
+    case ODB_NUMBER:
+      *dval = pnode->dval;
+      irc = 1;
+      break;
+
+    case ODB_USDNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	if (!IS_POOLNO(name)) { /* Applicable to non-$# only */
+	  *dval = psym->dval; /* current (compile-time) value of $-variable */
+	  irc = 1;
+	}
+      }
+      break;
+
+    case ODB_ADD: 
+    case ODB_SUB: 
+    case ODB_STAR: 
+    case ODB_DIV: 
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+      {
+	double arg[2];
+	int i, numargs = MIN(pnode->argc,2);
+
+	if (numargs <= 0) {
+	  SETMSG1("Zero number of args for operation '%s'",ODB_keymap(pnode->what));
+	  YYerror(msg);
+	  break;
+	}
+
+	irc = 1;
+	for (i=0; i<numargs; i++) {
+	  irc *= ODB_evaluate(pnode->argv[i], &arg[i]);
+	}
+
+	if (!irc) break;
+
+	switch (pnode->what) {
+	case ODB_ADD: 
+	  *dval = arg[0] + arg[1];
+	  break;
+	case ODB_SUB: 
+	  *dval = arg[0] - arg[1];
+	  break;
+	case ODB_STAR: 
+	  *dval = arg[0] * arg[1];
+	  break;
+	case ODB_DIV: 
+	  {
+	    if (arg[1] != 0) 
+	      *dval = arg[0] / arg[1];
+	    else {
+	      SETMSG0("Division by zero");
+	      YYerror(msg);
+	    }
+	  }
+	  break;
+
+	case ODB_UNARY_PLUS:
+	  *dval = arg[0];
+	  break;
+
+	case ODB_UNARY_MINUS:
+	  *dval = -arg[0];
+	  break;
+
+	} /* switch (pnode->what) [inner] */
+      }
+      break;
+
+    case ODB_FUNC:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *fname = psym->name;
+	const funcs_t *f = get_func(fname);
+	if (f && f->u.compile_time) {
+	  int joffset = (f->numargs < 0) ? f->joffset : 0;
+	  int i, numargs = pnode->argc - 1 - joffset;
+	  Boolean arg_to_radians = (f->deg2rad > 0 && ((f->deg2rad & 0x1) == 0x1)) ? 1 : 0;
+	  double *arg = NULL;
+	  ALLOC(arg, numargs);
+	  irc = 1;
+	  for (i=0; i<numargs; i++) {
+	    irc *= ODB_evaluate(pnode->argv[1+joffset+i], &arg[i]);
+	    if (irc && arg_to_radians) arg[i] = D2R(arg[i]);
+	    else if (irc && f->deg2rad < 0 && ABS(f->deg2rad) != i+1) { /* [hack] */
+	      arg[i] = D2R(arg[i]);
+	    }
+
+	  }
+	  if (irc) { /* Still ok --> now call the function itself */
+	    double res = 0;
+	    Boolean funcresult_to_degrees = (f->deg2rad > 0 && ((f->deg2rad & 0x2) == 0x2)) ? 1 : 0;
+	    if (joffset == 0) {
+	      if (f->numargs < 0) {
+		res = f->u.vararg(numargs, arg); /* Whatever these functions might be */
+	      }
+	      else {
+		switch (numargs) {
+		case 0: res = f->u.zeroarg (); break;
+		case 1: res = f->u.onearg  (arg[0]); break;
+		case 2: res = f->u.twoarg  (arg[0], arg[1]); break;
+		case 3: res = f->u.threearg(arg[0], arg[1], arg[2]); break;
+		case 4: res = f->u.fourarg (arg[0], arg[1], arg[2], arg[3]); break;
+		case 5: res = f->u.fivearg (arg[0], arg[1], arg[2], arg[3], arg[4]); break;
+		case 6: res = f->u.sixarg  (arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); break;
+		default: res = f->u.vararg (numargs, arg); break;
+		}
+	      }
+	    }
+	    else if (joffset == 1) { /* Usually min/max function */
+	      res = f->u.vararg(numargs, arg); /* Note: Here "numargs" could even be 1 !! */
+	    }
+	    else { /* After all the hassle, cannot evaluate, since unrecognized joffset */
+	      irc = 0;
+	    }
+
+	    if (irc && funcresult_to_degrees) res = R2D(res);
+	    if (irc) *dval = res;
+	  }
+	  FREE(arg);
+	}
+	else {
+	  irc = 0; /* not an evaluable function */
+	}
+      }
+      break;
+
+    case ODB_NAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *dname = psym->name;
+        irc = ODB_has_define(dname);
+        if (irc) *dval = ODB_get_define(dname);
+      }
+      break;
+
+    } /* switch (pnode->what) [outer] */
+  } /* if (pnode) */
+
+  return irc;
+}
+
+PRIVATE double 
+dval_assign(double *dval) { return *dval; }
+
+PRIVATE int
+ival_assign(int *ival) { return *ival; }
+
+PUBLIC Boolean
+ODB_split(const char *s, char **type, char **var, char **member, char **table, char **offset)
+{
+  Boolean rc = 0;
+  char *p = STRDUP(s);
+  char *pcolon = strchr(p, ':');
+  char *pdot = IS_USDDOTHASH(p) ? NULL : strchr(p, '.');
+  char *pat  = strchr(p, '@');
+  char *ptype, *pvar, *pmember, *ptable;
+  char *poffset = GET_OFFSET(p);
+  if (poffset) ++poffset;
+
+  if (type)   *type   = NULL;
+  if (var)    *var    = NULL;
+  if (member) *member = NULL;
+  if (table)  *table  = NULL;
+  if (offset) *offset = NULL;
+
+  if (pdot && pat) {
+    if (pat < pdot) {
+      SETMSG1("An '@'-sign precedes a '.'-sign in SELECT/WHERE/ORDERBY-symbol '%s'\n",s);
+      PRTMSG(msg);
+      rc = 1;
+      goto finish;
+    }
+  }
+
+  ptype = pcolon ? p : NULL;
+  pvar = pcolon ? pcolon + 1 : p;
+  if (pcolon) *pcolon = '\0';
+  ptable = pat ? pat + 1 : NULL;
+  if (ptable && poffset) {
+    char *offset_char = GET_OFFSET(ptable);
+    if (offset_char) *offset_char = '\0';
+  }
+  else if (pvar && poffset) {
+    char *offset_char = GET_OFFSET(pvar);
+    if (offset_char) *offset_char = '\0';
+  }
+  if (pat) *pat = '\0';
+  pmember = pdot ? pdot + 1 : NULL;
+  if (pdot) *pdot = '\0';
+
+  if (ptable) {
+    char *pbrL = strchr(ptable,'[');
+    char *pbrR = pbrL ? strchr(ptable,']') : NULL;
+
+    if (pbrR - pbrL > 0) {
+      char *x1, *x2;
+      int len = (pbrL - ptable) + (pbrR - pbrL) + 1;
+      char *ptable_actual = NULL;
+      ALLOC(ptable_actual, len);
+      x1 = ptable;
+      x2 = ptable_actual;
+      while (*x1 && x1 < pbrL) {
+	*x2++ = *x1++;
+      }
+      *x2++ = '_';
+      x1++;
+      while (*x1 && x1 < pbrR) {
+	*x2++ = *x1++;
+      }
+      *x2++ = '\0';
+      ptable = STRDUP(ptable_actual);
+      FREE(ptable_actual);
+    } /* if (pbrR - pbrL > 0) */
+  }
+
+  if (type)   *type   = ptype   ? STRDUP(ptype)   : NULL;
+  if (var)    *var    = STRDUP(pvar);
+  if (member) *member = pmember ? STRDUP(pmember) : NULL;
+  if (table)  *table  = ptable  ? STRDUP(ptable)  : NULL;
+  if (offset) *offset = poffset ? STRDUP(poffset) : STRDUP("0");
+
+ finish:
+
+  FREE(p);
+  return rc;
+}
+
+
+PRIVATE char *
+join(int icase, const char *var, const char *member, 
+     const ODB_Table *t, const ODB_Type *type,
+     Boolean is_where, Boolean is_selectexpr, 
+     const ODB_Symbol *psym, const char *offset)
+{
+  char *p = NULL;
+  
+  if (!IS_HASH(var)) {
+    const char *poffset = offset ? offset : "0";
+    int sign = 0;
+    int len = 100;
+    char *table = t ? t->table->name : NULL;
+    Boolean bitstream = type ? type->bitstream : 0;
+    char *typename = "undefined";
+    Boolean not_valid_char = 0;
+    int j;
+    const char *c;
+    char *xvar = NULL;
+    
+    ALLOC(xvar, strlen(var) + 1);
+    c = var;
+    j = 0;
+    while ( *c ) {
+      if (IS_VARCHAR(c)) xvar[j++] = *c;
+      else not_valid_char = 1;
+      c++;
+    }
+    xvar[j] = '\0';
+    
+    if (xvar) len += strlen(xvar);
+    if (member) len += strlen(member);
+    if (table) len += strlen(table);
+    if (type) {
+      typename = bitstream ? BITFIELD : type->type->name;
+    }
+    if (typename) len += strlen(typename);
+    len += strlen(poffset) + 10;
+    sign = GetSign(poffset);
+
+    ALLOC(p, len);
+    *p = '\0';
+
+    switch (icase) {
+    case -1: /* def_put */
+      {
+	if (is_selectexpr) { /* Must be consistent with ODB_expand_sym */
+	  FREE(p);
+	  p = ODB_expand_sym(psym, "F", table, poffset);
+	}
+	else {
+	  char *ptable = ODB_uppercase(table);
+	  char *pvar = not_valid_char ? STRDUP(xvar) : ODB_capitalize(xvar);
+	  char *pmember = member ? ODB_capitalize(member) : STRDUP("all");
+	  char *zz = ZZtop(poffset, sign);
+
+	  snprintf(p, len, "%s%s_%s_%s_%s", ptable, zz,
+		   pvar, pmember, 
+		   is_where ? "EXPR" : "PUT");
+	  
+	  FREE(zz);
+	  FREE(pmember);
+	  FREE(pvar);
+	  FREE(ptable);
+	}
+      }
+      break;
+      
+    case -2: /* alias_put */
+      {
+	char *zz = TheWho(poffset, sign);
+	if (bitstream && member) {
+	  int index = -1;
+	  Boolean member_present = ODB_in_type(member, type, &index);
+	  
+	  if (is_where) {
+	    snprintf(p, len, "GET_BITS(T_%sX%s[i%s], %d, %d)", 
+		     table, xvar, 
+		     zz,
+		     type->pos[index], type->len[index]);
+	  }
+	  else if (is_selectexpr) {
+	    snprintf(p, len, "GET_BITS(T_%sX%s[P->Index_%s[i%s]], %d, %d)", 
+		     table, xvar, table, 
+		     zz,
+		     type->pos[index], type->len[index]);
+	  }
+	  else {
+	    snprintf(p, len, "PUT_BITS(T_%sX%s[i%s], d, %d, %d)", 
+		     table, xvar,
+		     zz,
+		     type->pos[index], type->len[index]);
+	  }
+	}
+	else {
+	  if (is_where) {
+	    if (member) 
+	      snprintf(p, len, "T_%sX%s[i%s].%s", table, xvar, 
+		       zz, member);
+	    else
+	      snprintf(p, len, "T_%sX%s[i%s]", table, xvar,
+		       zz);
+	  }
+	  else if (is_selectexpr) {
+	    if (member) 
+	      snprintf(p, len, "T_%sX%s[P->Index_%s[i%s]].%s", table, xvar, table, 
+		       zz, member);
+	    else
+	      snprintf(p, len, "T_%sX%s[P->Index_%s[i%s]]", table, xvar, table,
+		       zz);
+	  }
+	  else {
+	    if (member) 
+	      snprintf(p, len, "T_%sX%s[i%s].%s = d", table, xvar, 
+		       zz, member);
+	    else
+	      snprintf(p, len, "T_%sX%s[i%s] = d", table, xvar,
+		       zz);
+	  }
+	}
+	FREE(zz);
+      }
+      break;
+      
+    case 0: /* Tag */
+      {
+	char *zz = GreenDay(poffset);
+	if (member)
+	  snprintf(p, len, "%s:%s.%s@%s%s", 
+		  typename, var, member, table, zz);
+	else {
+	  const char *actual_type = getalias(typename);
+	  snprintf(p, len, "%s:%s@%s%s", actual_type, var, table, zz);
+	}
+	FREE(zz);
+      }
+      break;
+      
+    case 1: /* def_get */
+      {
+	char *ptable = ODB_uppercase(table);
+	char *pvar = not_valid_char ? STRDUP(xvar) : ODB_capitalize(xvar);
+	char *pmember = member ? ODB_capitalize(member) : NULL;
+	char *zz = ZZtop(poffset, sign);
+	
+	if (pmember) 
+	  snprintf(p, len, "%s%s_%s_%s_GET", ptable, zz,
+		   pvar, pmember);
+	else
+	  snprintf(p, len, "%s%s_%s_all_GET", ptable, zz,
+		   pvar);
+
+	FREE(zz);
+	FREE(pmember);
+	FREE(pvar);
+	FREE(ptable);
+      }
+      break;
+      
+    case 2: /* alias_get */
+      {
+	char *zz = TheWho(poffset, sign);
+	if (bitstream && member) {
+	  int index = -1;
+	  Boolean member_present = ODB_in_type(member, type, &index);
+	  
+	  snprintf(p, len, "d = GET_BITS(T_%sX%s[i%s], %d, %d)", 
+		   table, xvar, 
+		   zz,
+		   type->pos[index], type->len[index]);
+	}
+	else {
+	  if (member) 
+	    snprintf(p, len, "d = T_%sX%s[i%s].%s", table, xvar, zz, member);
+	  else
+	    snprintf(p, len, "d = T_%sX%s[i%s]", table, xvar, zz);
+	}
+	break;
+	FREE(zz);
+      }
+      
+    case 3: /* call_arg */
+      {
+	char *zz = ZZtop(poffset, sign);
+	snprintf(p, len, "%s:T_%sX%s", typename, table, xvar);
+	FREE(zz);
+      }
+      break;
+
+    case 4: /* poslen */
+      if (bitstream && member) {
+	int index = -1;
+	Boolean member_present = ODB_in_type(member, type, &index);
+	snprintf(p, len, "%d %d", type->pos[index], type->len[index]);
+      }
+      else {
+	snprintf(p, len, "0 0");
+      }
+      break;
+      
+    }
+    
+    FREE(xvar);
+  }
+
+  return p;
+}
+
+
+/* === PUBLIC routines === */
+
+
+PUBLIC char *
+ODB_expand_sym(const ODB_Symbol *psym, const char *suffix, 
+	       const char *table, const char *offset)
+{
+  char *s = NULL;
+  if (psym) { 
+    int slen = 40;
+    char *pvar = NULL;
+    char *pmember = NULL;
+    char *ptable = NULL;
+    char *poffset = NULL;
+    int sign = 0;
+    (void) ODB_split(psym->name, NULL, &pvar, &pmember, &ptable, &poffset);
+    if (!ptable && table) ptable = STRDUP(table);
+    if (ptable) {
+      char *p = ptable;
+      while (*p) { if (islower(*p)) *p = toupper(*p); p++; }
+    }
+    else {
+      ptable = STRDUP("no_table");
+    }
+    if (!poffset && offset) poffset = STRDUP(offset);
+    if (!poffset) poffset = STRDUP("0");
+    sign = GetSign(poffset);
+
+    if (pvar) {
+      int in_bracket = 0;
+      char *p = pvar;
+      char *newpvar = STRDUP(pvar);
+      char *newp = newpvar;
+      while (*p) { 
+	if (!in_bracket && islower(*p)) *newp++ = toupper(*p);
+	else if (IS_VARCHAR(p)) *newp++ = *p;
+	else if (*p == '(') in_bracket++;
+	else if (*p == ')') in_bracket--;
+	p++;
+      }
+      *newp = '\0';
+      FREE(pvar);
+      pvar = STRDUP(newpvar);
+    }
+    else {
+      pvar = STRDUP("no_var");
+    }
+    if (pmember) {
+      char *p = pmember;
+      while (*p) { if (islower(*p)) *p = toupper(*p); p++; }
+    }
+    else {
+      pmember = STRDUP("all");
+    }
+    {
+      char *zz = ZZtop(poffset, sign);
+      slen += STRLEN(ptable) + STRLEN(zz) + STRLEN(pvar) + STRLEN(pmember) + STRLEN(suffix);
+      ALLOC(s,slen);
+      snprintf(s,slen,"%s%s_%s_%s%s%s",
+	       ptable,zz,
+	       pvar,pmember,
+	       suffix ? "_" : "",
+	       suffix ? suffix : "");
+      FREE(zz);
+    }
+
+    FREE(pvar);
+    FREE(pmember);
+    FREE(ptable);
+    FREE(poffset);
+  }
+  return s;
+}
+
+
+PRIVATE ODB_Stack *stack = NULL;
+
+PRIVATE int stack_debug = 0;
+PRIVATE int stack_first_time = 1;
+
+PRIVATE void check_stack_debug()
+{
+  if (stack_first_time) {
+    char *env = getenv("ODB_STACK_DEBUG");
+    if (env) stack_debug = atoi(env);
+    stack_first_time = 0;
+  }
+}
+
+PRIVATE void stack_error(const char *errmsg)
+{
+  fprintf(stderr,"***Stack handling error: %s\n",errmsg);
+  fprintf(stderr,"\tFor more info: Please re-run the compilation with -v option and ODB_STACK_DEBUG=1\n");
+  raise(SIGABRT);
+  exit(1);
+}
+
+#define POPSTACK(x,f) \
+ODB_Stack *this = NULL; \
+if (stack) { \
+  x = stack->u.x; \
+  f = stack->flag; \
+  this = stack; \
+  stack = stack->prev; \
+} \
+FREE(this);
+
+PUBLIC char *
+ODB_popstr()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    char *s = NULL;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x1;
+    POPSTACK(s,flag);
+    if (stack_debug) {
+      fprintf(stderr,
+	      "<<< ODB_popstr() = %p ('%s') : flag=0x%x, flag_expected=0x%x\n",
+	      s?s:NULL,s?s:"(nil)",flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popstr(): flag != flag_expected");
+    return s;
+  }
+}
+
+PUBLIC int
+ODB_popi()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    int i = 0;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x2;
+    POPSTACK(i,flag);
+    if (stack_debug) {
+      fprintf(stderr,"<<< ODB_popi() = %d : flag=0x%x, flag_expected=0x%x\n",i,flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popi(): flag != flag_expected");
+    return i;
+  }
+}
+
+PUBLIC ODB_Tree *
+ODB_popexpr()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    ODB_Tree *expr = NULL;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x4;
+    POPSTACK(expr,flag);
+    if (stack_debug) {
+      fprintf(stderr,
+	      "<<< ODB_popexpr() = %p : flag=0x%x, flag_expected=0x%x\n",
+	      expr?expr:NULL,flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popexpr(): flag != flag_expected");
+    return expr;
+  }
+}
+
+PUBLIC FILE *
+ODB_popFILE()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    FILE *fp = NULL;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x8;
+    POPSTACK(fp,flag);
+    if (stack_debug) {
+      fprintf(stderr,
+	      "<<< ODB_popFILE() = %p : flag=0x%x, flag_expected=0x%x\n",
+	      fp?fp:NULL,flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popFILE(): flag != flag_expected");
+    return fp;
+  }
+}
+
+PUBLIC ODB_Symbol *
+ODB_popSYMBOL()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    ODB_Symbol *psym = NULL;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x10;
+    POPSTACK(psym,flag);
+    if (stack_debug) {
+      fprintf(stderr,
+	      "<<< ODB_popSYMBOL() = %p : flag=0x%x, flag_expected=0x%x\n",
+	      psym?psym:NULL,flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popSYMBOL(): flag != flag_expected");
+    return psym;
+  }
+}
+
+PUBLIC ODB_SelectExpr *
+ODB_popSELECTEXPR()
+{
+  if (stack_first_time) check_stack_debug();
+  {
+    ODB_SelectExpr *sel = NULL;
+    unsigned int flag = 0;
+    const unsigned int flag_expected = 0x20;
+    POPSTACK(sel,flag);
+    if (stack_debug) {
+      fprintf(stderr,
+	      "<<< ODB_popSELECTEXPR() = %p : flag=0x%x, flag_expected=0x%x\n",
+	      sel?sel:NULL,flag,flag_expected);
+    }
+    if (flag != flag_expected) stack_error("ODB_popSELECTEXPR(): flag != flag_expected");
+    return sel;
+  }
+}
+
+#define PUSHSTACK(x,f) \
+{ \
+  ODB_Stack *prev = NULL; \
+  ODB_Stack *this = stack; \
+  if (this) { \
+    prev = this; \
+    ALLOC(this->next,1); \
+    this = this->next; \
+  } \
+  else { \
+    ALLOC(this,1); \
+  } \
+  this->u.x = x; \
+  this->flag = f; \
+  this->prev = prev; \
+  this->next = NULL; \
+  stack = this; \
+}
+
+PUBLIC void 
+ODB_pushstr(char *s)
+{
+  const unsigned int flag = 0x1;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushstr(%p) '%s'\n",s?s:NULL,s?s:"(nil)");
+  }
+  PUSHSTACK(s,flag);
+}
+
+PUBLIC void 
+ODB_pushi(int i)
+{
+  const unsigned int flag = 0x2;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushi(%d)\n",i);
+  }
+  PUSHSTACK(i,flag);
+}
+
+PUBLIC void 
+ODB_pushexpr(ODB_Tree *expr)
+{
+  const unsigned int flag = 0x4;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushexpr(%p)\n",expr?expr:NULL);
+  }
+  PUSHSTACK(expr,flag);
+}
+
+PUBLIC void 
+ODB_pushFILE(FILE *fp)
+{
+  const unsigned int flag = 0x8;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushFILE(%p)\n",fp?fp:NULL);
+  }
+  PUSHSTACK(fp,flag);
+}
+
+PUBLIC void 
+ODB_pushSYMBOL(ODB_Symbol *psym)
+{
+  const unsigned int flag = 0x10;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushSYMBOL(%p)\n",psym?psym:NULL);
+  }
+  PUSHSTACK(psym,flag);
+}
+
+PUBLIC void 
+ODB_pushSELECTEXPR(ODB_SelectExpr *sel)
+{
+  const unsigned int flag = 0x20;
+  if (stack_first_time) check_stack_debug();
+  if (stack_debug) {
+    fprintf(stderr,">>> ODB_pushSELECTEXPR(%p)\n",sel?sel:NULL);
+  }
+  PUSHSTACK(sel,flag);
+}
+
+#define VERBOSE_REORDER_PRINT() \
+	char *s = pview->from[j]->table->name; \
+	int flag = pview->from_attr[j]; \
+	int tblno = pview->from[j]->tableno; \
+	int rank = pview->from[j]->rank; \
+	int i, nlink = pview->from[j]->nlink; \
+	fprintf(stderr,"[%d] = %s [flag=0x%x:tbl#%d:rank=%d] : # of links = %d ",j,s,flag,tblno,rank,nlink); \
+	for (i=0; i<nlink; i++) { \
+	  char *linktablename = pview->from[j]->link[i]->table->name; /* vow !! */ \
+	  int itstblno = pview->from[j]->link[i]->tableno; \
+	  int itsrank = pview->from[j]->link[i]->rank; \
+	  fprintf(stderr,"%s%s<tbl#%d:rank=%d>",(i>0) ? "," : "\n(",linktablename,itstblno,itsrank); \
+	}  \
+	fprintf(stderr,"%s\n",(nlink > 0) ? ")" :"")
+
+
+PUBLIC int
+ODB_reorder_tables(ODB_View *pview)
+{
+  int nfrom = pview ? pview->nfrom : 0;
+  if (pview && nfrom >= 1) {
+    int j;
+    const char *vname = pview->view->name;
+
+    if (verbose) {
+      fprintf(stderr,
+	      "ODB_reorder_tables(): Reordering FROM-tables in view '%s'\n",vname);
+    }
+
+    if (verbose) {
+      fprintf(stderr,"ODB_reorder_tables(): ** Old sequence -->\n");
+      for (j=0; j<nfrom; j++) {
+	VERBOSE_REORDER_PRINT();
+      }
+    } /* if (verbose) */
+
+    if (nfrom > 1) {
+      int *newflag = NULL;
+      ODB_Table **newfrom = NULL;
+      Cmpfromtable_t *cmp = NULL;
+
+      ALLOC(cmp, nfrom);
+
+      for (j=0; j<nfrom; j++) {
+	char *s = pview->from[j]->table->name;
+	ODB_Table *ptable = ODB_lookup_table(s, NULL);
+	if (verbose) {
+	  fprintf(stderr,"ODB_reorder_tables(): [%d] table=%s : wt=%.6f\n",j,s,ptable->wt);
+	}
+	cmp[j].wt = ptable->wt;
+	cmp[j].rank = j;
+	cmp[j].flag = pview->from_attr[j];
+      }
+
+      qsort(cmp, nfrom, sizeof(*cmp), 
+	    (int (*)(const  void *, const void *))cmpfromtable);
+
+      ALLOC(newflag, nfrom);
+      ALLOC(newfrom, nfrom);
+      for (j=0; j<nfrom; j++) {
+	newflag[j] = cmp[j].flag;
+	newfrom[j] = pview->from[cmp[j].rank];
+      }
+
+      FREE(pview->from_attr);
+      pview->from_attr = newflag;
+      FREE(pview->from);
+      pview->from = newfrom;
+
+      FREE(cmp);
+    } /* if (nfrom > 1) */
+
+    if (verbose) {
+      fprintf(stderr,"ODB_reorder_tables(): ** New sequence -->\n");
+      for (j=0; j<nfrom; j++) {
+	VERBOSE_REORDER_PRINT();
+      }
+      for (j=0; j<nfrom; j++) {
+	char *s = pview->from[j]->table->name;
+	ODB_Table *ptable = ODB_lookup_table(s, NULL);
+	fprintf(stderr,"ODB_reorder_tables()> [%d] table=%s : wt=%.6f\n",j,s,ptable->wt);
+      }
+    } /* if (verbose) */
+
+  } /* if (pview && nfrom >= 1) */
+  return nfrom;
+}
+
+
+PRIVATE int
+Unroll_Links(ODB_Table **from, int nfrom, Boolean touched[])
+{
+  int j, rc = 0;
+  for (j=0; j<nfrom; j++) {
+    ODB_Table *ptable = from[j];
+    int tblno = ptable->tableno;
+    if (!touched[tblno]) { /* Avoids infinite loop when recursive links between tables */
+      touched[tblno] = 1;
+      rc++;
+      rc += Unroll_Links(ptable->link, ptable->nlink, touched);
+    }
+  }
+  return rc;
+}
+
+PUBLIC int
+ODB_insert_tables(ODB_View *pview)
+{
+  int nfrom = pview ? pview->nfrom : 0;
+  if (pview && nfrom > 1) {
+    int saved_nfrom = nfrom;
+    int n_touched, tblno, j;
+    ODB_Table **newfrom = NULL; /* new from-list */
+    int newlen = 0;
+    int lenstr = ODB_ntables;
+    int more, total_more = 0;
+    ODB_Table **all_tables = NULL; /* All tables; original order */
+    int *picked = NULL; /* 0 = if not picked, 1 = if already picked, 2 = if inserted */
+    Boolean *touched = NULL; /* True if table in unrolled "hierarchy-path" */
+    ODB_Table *ptable = NULL; 
+
+    CALLOC(all_tables, ODB_ntables);
+    j = 0;
+    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+      if (verbose) {
+	tblno = ptable->tableno;
+	fprintf(stderr,">>all_tables[%d] = '%s' : tableno = %d\n", 
+		j, ptable->table->name, tblno);
+      }
+      lenstr += STRLEN(ptable->table->name);
+      all_tables[j++] = ptable;
+    }
+
+    CALLOC(newfrom, ODB_ntables);
+    CALLOC(picked, ODB_ntables);
+    for (j=0; j<nfrom; j++) {
+      ptable = pview->from[j];
+      tblno = ptable->tableno;
+      picked[tblno] = 1;
+      newfrom[j] = ptable;
+    }
+    newlen = nfrom;
+    
+    CALLOC(touched, ODB_ntables);
+    n_touched = Unroll_Links(pview->from, nfrom, touched); /* Could this be an infinite loop ? */
+    if (verbose) {
+      fprintf(stderr,"n_touched = %d\n", n_touched);
+      for (j=0; j<ODB_ntables; j++) {
+	if (touched[j]) {
+	  ptable = all_tables[j];
+	  fprintf(stderr,"[%d] : '%s'\n", j, ptable->table->name);
+	}
+      }
+    }
+
+    do {
+      more = 0;
+      for (j=0; j<nfrom; j++) {
+	int i;
+        ptable = newfrom[j];
+	for (i=0; i<ODB_ntables; i++) {
+	  if (!picked[i] && touched[i] && ptable->linkslavemask[i]) {
+	    /* insert this table */
+	    picked[i] = 2;
+	    ODB_pushi(i);
+	    more++;
+	    total_more++;
+	  }
+	}
+      }
+      if (more > 0) {
+	for (j=more-1; j>=0; j--) {
+	  int i = ODB_popi();
+	  newfrom[newlen++] = all_tables[i];
+	}
+	nfrom = newlen;
+      }
+    } while (more > 0);
+
+    if (verbose) {
+      fprintf(stderr,"--> New picked-list\n");
+      for (j=0; j<ODB_ntables; j++) {
+	if (picked[j]) {
+	  ptable = all_tables[j];
+	  fprintf(stderr,"###[%d] : '%s' : picked=%d\n", j, ptable->table->name,picked[j]);
+	}
+      }
+    }
+
+    FREE(all_tables);
+    FREE(touched);
+    FREE(picked);
+
+    FREE(pview->from);
+    pview->from = newfrom;
+    pview->nfrom = nfrom;
+
+    if (total_more > 0) { /* Update from_attr -flags */
+      int *newflag = NULL;
+      ALLOC(newflag, nfrom);
+      for (j=0; j<saved_nfrom; j++) {
+	newflag[j] = pview->from_attr[j];
+      }
+      for (j=saved_nfrom; j<nfrom; j++) {
+	newflag[j] = ODB_FROM_ATTR_INSERT;
+      }
+      FREE(pview->from_attr);
+      pview->from_attr = newflag;
+    }
+
+    if (verbose && total_more > 0) { /* Report the change */
+      char *oldfromlist = NULL;
+      char *newfromlist = NULL;
+      ALLOC(oldfromlist, lenstr); *oldfromlist = '\0';
+      ALLOC(newfromlist, lenstr); *newfromlist = '\0';
+      more = 0;
+      for (j=0; j<saved_nfrom; j++) {
+	ptable = pview->from[j];
+	if (j > 0) strcat(oldfromlist,",");
+	strcat(oldfromlist,ptable->table->name);
+      }
+      more = 0;
+      for (j=0; j<nfrom; j++) {
+	ptable = pview->from[j];
+	if (more++ > 0) strcat(newfromlist,",");
+	strcat(newfromlist,ptable->table->name);
+      }
+      SETMSG2("Potentially missing tables inserted to FROM-statement\n"
+	      "  before '%s' and\n  after '%s'\n",
+	      oldfromlist, newfromlist);
+      PRTMSG(msg);
+      FREE(oldfromlist);
+      FREE(newfromlist);
+    } /* if (verbose && total_more > 0) */
+  } /* if (pview && nfrom > 1) */
+  return nfrom;
+}
+
+
+PUBLIC int
+ODB_pick_tables(int nfrom)
+{
+  int flag = ODB_FROM_ATTR_AUTO;
+  int count = 0;
+  no_from_stmt = 0;
+  if (nfrom <= 0) {
+    ODB_Table *ptable = ODB_start_table();
+    for ( ; ptable != NULL; ptable = ptable->next) {
+      ODB_pushstr(ptable->table->name);
+      ODB_pushi(flag);
+      count++;
+    }
+    if (nfrom == -2) no_from_stmt = 1; /* FROM-less SELECT */
+  }
+  else {
+    int j;
+    char **fromlist = NULL;
+    ALLOC(fromlist, nfrom);
+    /* Empty stack first */
+    for (j=nfrom-1; j>=0; j--) {
+      char *s = ODB_popstr(); /* a character string from the stack */
+      fromlist[j] = s;
+    }
+    /* Redo the stack + add the flag */
+    flag = ODB_FROM_ATTR_USER;
+    for (j=0; j<nfrom; j++) {
+      char *s = fromlist[j];
+      ODB_pushstr(s);
+      ODB_pushi(flag);
+      count++;
+    }
+    FREE(fromlist);
+  }
+  return count;
+}
+
+PUBLIC int
+ODB_pick_symbols(ODB_Table **from, const int *from_attr, int nfrom)
+{
+  int count = 0;
+
+  if (from && nfrom > 0) {
+    int i;
+    for (i=0; i<nfrom; i++) {
+      if ((from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) {
+	/* Skip this table if table was auto-inserted */
+	continue;
+      }
+      else {
+	ODB_Table *ptable = from[i];
+	char *tname = ptable->table->name;
+	int tname_len = strlen(tname);
+	int j, nsym = ptable->nsym;
+	
+	for (j=0; j<nsym; j++) {
+	  ODB_Symbol *psym = ptable->sym[j];
+	  if (psym) {
+	    char *symname = psym->name;
+	    char *s;
+	    int len = strlen(symname) + tname_len + 2;
+	    ALLOC(s, len);
+	    snprintf(s, len, "%s@%s", symname, tname);
+	    ODB_pushstr(s);
+	    count++;
+	  }
+	} /* for (j=0; j<nsym; j++) */
+      }
+    } /* for (i=0; i<nfrom; i++) */
+  }
+
+  return count;
+}
+
+
+PRIVATE Boolean
+check_string2(Boolean is_error, char **tag, const ODB_Tree *p1, const ODB_Tree *p2)
+{
+  /* Check that if a string expression is present, then
+     the counterpart argument (or expr) must be either
+     another string expression or an ODB_NAME with a correct
+     datatype ("string") */
+
+  Boolean on_error = 0;
+  char *name = NULL;
+
+  if (p1) {
+    Boolean is_string = (p1->what == ODB_STRING ||
+			 p1->what == ODB_WC_STRING);
+
+    if (p2) {
+      is_string |= (p2->what == ODB_STRING ||
+		    p2->what == ODB_WC_STRING);
+
+      if (is_string) {
+	Boolean in_business = 
+	  (
+	   ((p1->what == ODB_STRING || p1->what == ODB_WC_STRING)
+	    && p2->what == ODB_WHERE_SYMBOL) ||
+	   ((p2->what == ODB_STRING || p2->what == ODB_WC_STRING)
+	    && p1->what == ODB_WHERE_SYMBOL));
+
+	if (in_business) {
+	  char *swhere     = (p1->what == ODB_WHERE_SYMBOL) ? p1->argv[0] : p2->argv[0];
+	  char *ptype = NULL;
+	  char *pvar = NULL;
+	  char *ptable = NULL;
+	  int isym;
+	  ODB_Symbol *psym = (p1->what == ODB_STRING || p1->what == ODB_WC_STRING) 
+	    ? p1->argv[0] : p2->argv[0];
+
+	  (void) ODB_split(swhere, NULL, &pvar, NULL, NULL, NULL);
+	  isym = atoi(pvar); /* Order no. of a view symbol */
+	  
+	  (void) ODB_split(tag[isym], &ptype, &pvar, NULL, &ptable, NULL);
+
+	  if (!strequ(ptype,STRING)) {
+	    SETMSG4("Can't compare non-string symbol '%s' (type='%s', table='%s') against string symbol '%s'",
+		    pvar, ptype, ptable, psym->name);
+	    YYerror(msg);
+	  }
+
+	  FREE(ptype);
+	  FREE(pvar);
+	  FREE(ptable);
+	}
+
+      } /* if (is_string) */
+    }
+  }
+    
+  if (on_error && is_error) {
+    SETMSG1("Cannot compare a non-string variable '%s' against a string expression",
+	    name);
+    YYerror(msg);
+  }
+
+  return on_error;
+}
+
+
+PUBLIC int
+ODB_trace_symbols(ODB_Tree *pnode, ODB_Tracesym *t, Boolean is_selectexpr)
+{
+  int rc = 0;
+
+  if (pnode) {
+    int what = pnode->what;
+
+    switch (what) {
+    case ODB_WHERE_SYMBOL:
+      if (t) {
+	if (t->flag == 0) {
+	  t->next++;
+	  rc = 1; /* Already resolved, but must be accounted for */
+	}
+	else if (t->flag == 2) {
+	  t->maxfrom = MAX(t->maxfrom, pnode->level);
+	}
+      }
+      break;
+      
+    case ODB_NAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+
+	if (t) {
+	  if (t->flag == 0) {
+	    int j = t->next++;
+	    int ifrom = t->table_index[j];
+	    char *tag = t->tag[j];
+	    char *s = t->where[j];
+	    int len = strlen(s) + 50;
+	    char *p;
+	    
+	    t->maxfrom = MAX(t->maxfrom, ifrom);
+	    
+	    ALLOC(p, len);
+	    snprintf(p, len, "double:%d.%d@%s", j, ifrom, s);
+	    
+	    {
+	      int numargs = 3;
+	      void **tmp;
+	      ALLOC(tmp, numargs);
+	      tmp[0] = p;
+	      tmp[1] = psym;
+	      tmp[2] = tag;
+	      pnode->argc = numargs;
+	      FREE(pnode->argv);
+	      pnode->argv = tmp;
+	    }
+
+	    pnode->level = ifrom;
+	    pnode->what = ODB_WHERE_SYMBOL;
+	  }
+	  else if (t->flag == 2) {
+	    t->maxfrom = MAX(t->maxfrom, pnode->level);
+	  }
+	}
+	else if (!t) {
+	  ODB_pushstr(name);
+	}
+      }
+      rc = 1;
+      break;
+
+    case ODB_HASHNAME:
+      {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+
+	if (t) {
+	  if (t->flag == 0) {
+	    int j = t->next++;
+	    int ifrom = t->table_index[j];
+	    /* fprintf(stderr,"TRACE_SYMBOLS: HASHNAME='%s' --> ifrom=%d\n",name,ifrom); */
+	    t->maxfrom = MAX(t->maxfrom, ifrom);
+	    pnode->level = ifrom;
+	  }
+	  else if (t->flag == 2) {
+	    t->maxfrom = MAX(t->maxfrom, pnode->level);
+	  }
+	}
+	else if (!t) {
+	  ODB_pushstr(name);
+	}
+      }
+      rc = 1;
+      break;
+
+    case ODB_BSNUM:
+      rc = 0;
+      break;
+
+    case ODB_USDNAME:
+      if (is_selectexpr && !t) {
+	ODB_Symbol *psym = pnode->argv[0];
+	char *name = psym->name;
+	ODB_pushstr(name);
+	rc = 1;
+      }
+      else {
+	rc = 0;
+      }
+      break;
+
+    case ODB_COND:
+      {
+	int j, numargs = pnode->argc;
+	for (j=0; j<numargs; j++) 
+	  rc += ODB_trace_symbols(pnode->argv[j], t, is_selectexpr);
+      }
+      break;
+
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      {
+	int j, numargs = pnode->argc - 1;
+
+	if (t) {
+	  ODB_Symbol *psym = pnode->argv[0];
+	  char *name = psym->name;
+	  if (t->flag == 0) {
+	    t->has_maxcount |= strequ(name,"maxcount");
+	    t->has_Unique |= strequ(name,"Unique");
+	    t->has_thin |= strequ(name,"thin");
+	  }
+	  else if (t->flag == 2) {
+	    t->has_maxcount |= strequ(name,"maxcount");
+	    t->has_Unique |= strequ(name,"Unique");
+	    t->maxfrom = MAX(t->maxfrom, pnode->level);
+	  }
+	}
+
+	for (j=1; j<=numargs; j++) 
+	  rc += ODB_trace_symbols(pnode->argv[j], t, is_selectexpr);
+      }
+      break;
+
+    case ODB_FILE:
+      {
+	int numargs = pnode->argc - 1;
+
+	if (t) {
+	  if (t->flag == 0) {
+	    /* t->has_infile = 1; */
+	  }
+	  else if (t->flag == 2) {
+	    /* t->has_infile = 1; */
+	    t->maxfrom = MAX(t->maxfrom, pnode->level);
+	  }
+	}
+
+	rc += ODB_trace_symbols(pnode->argv[2], t, is_selectexpr);
+      }
+      break;
+
+    case ODB_NE:
+    case ODB_EQ:
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      rc += ODB_trace_symbols(pnode->argv[0], t, is_selectexpr);
+      rc += ODB_trace_symbols(pnode->argv[1], t, is_selectexpr);
+      break;
+
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      rc += ODB_trace_symbols(pnode->argv[0], t, is_selectexpr);
+      break;
+
+    case ODB_MATCH:
+      {
+	int j, nummatch = pnode->argc; /* Ought to be 1 */
+	for (j=0; j<nummatch; j++) {
+	  ODB_Match_t *match = pnode->argv[j];
+	  rc += ODB_trace_symbols(match->expr, t, is_selectexpr);
+	}
+      }
+      break;
+  
+    default:
+      rc = 0;
+      break;
+    } /* switch (what) */
+  }
+
+  return rc;
+}
+
+
+PRIVATE char *Voffset(const char *poffset)
+{
+  char *s = NULL;
+  if (poffset && !strequ(poffset,"0")) {
+    s = STRDUP(poffset);
+    if (*s == '_') *s = '-';
+  }
+  else
+    s = STRDUP("0");
+  return s;
+}
+
+
+#define PROCESS(SYMBOL, symbol, nsymbol, ifrom, in_flag, is_where, is_selectexpr, is_select) \
+for (j=0; j<nsymbol; j++) { \
+  Boolean is_select_formula = (is_select && v->is_formula && v->is_formula[j]) ? 1 : 0; \
+  if (!is_select_formula) { \
+   ODB_Symbol *psym = v->symbol[j]; \
+   const char *s = psym->name; \
+   Boolean found = 0; \
+   char *pvar = NULL; \
+   char *pmember = NULL; \
+   char *ptable = NULL; \
+   char *poffset = NULL; \
+   if (ODB_split(s, NULL, &pvar, &pmember, &ptable, &poffset) == 0) { \
+    int index = -1; \
+    found = ODB_in_table(ODB_NAME, pvar, t, &index); \
+    if (found && ptable) found = strequ(tname, ptable); \
+    if (found && pmember && index >= 0) { \
+      ODB_Type *type = t->type[index]; \
+      Boolean member_present = ODB_in_type(pmember, type, NULL); \
+      if (!member_present) { \
+	char *tyname = type->type->name; \
+	SETMSG3("Member '%s' is not present in type '%s' (variable '%s')\n", \
+		pmember, tyname, pvar); \
+	PRTMSG(msg); \
+	SETMSG2("  Error occurred while processing table '%s' in view '%s'\n", \
+		tname, vname); \
+	PRTMSG(msg); \
+	error_count++; \
+      } \
+    } /* if (found && pmember) */ \
+    if (found) { \
+      ODB_Type *type = (index >= 0) ? t->type[index] : NULL; \
+      v->table_index[k] = ifrom; \
+      v->tag[k] = join(0, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->call_arg[k] = join(3, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->def_put[k] = join(-1, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->alias_put[k] = join(-2, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->def_get[k] = join(1, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->alias_get[k] = join(2, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->poslen[k] = join(4, pvar, pmember, t, type, is_where, is_selectexpr, psym, poffset); \
+      v->offset[k] = Voffset(poffset); \
+    } \
+   } \
+   else { \
+    SETMSG3("Invalid %s-symbol '%s' encountered in view '%s'\n", \
+	    SYMBOL, s, vname);  \
+    PRTMSG(msg);  \
+    error_count++; \
+   } \
+   if (found) { refsym[k]++; reftab[ifrom] = 1; } \
+   FREE(pvar); \
+   FREE(pmember); \
+   FREE(ptable); \
+   FREE(poffset); \
+  } \
+  in_flag[k++] = 1; \
+} /* for (j=0; j<nsymbol; j++) */
+
+
+PRIVATE Boolean
+check_string(Boolean is_error, int what, const ODB_Tree *p1, const ODB_Tree *p2)
+{
+  /* A string can only be part of the ODB_EQ or ODB_NE or ODB_LIKE or ODB_NOTLIKE
+     expressions, and can only appear in either LHS or RHS of the full expression.
+     Furthermore if ODB_EQ/ODB_NE expr, then the other side of the
+     expr must be an ODB_NAME */
+
+  Boolean on_error = 0;
+
+  if (p1) {
+    Boolean is_string = (p1->what == ODB_STRING || p1->what == ODB_WC_STRING);
+
+    if (p2) {
+      is_string |= (p2->what == ODB_STRING || p2->what == ODB_WC_STRING);
+
+      if (is_string) {
+	on_error = ((what != ODB_EQ) && (what != ODB_NE) && 
+		    (what != ODB_LIKE) && (what != ODB_NOTLIKE));
+	if (!on_error) {
+	  on_error = !(
+		       ((p1->what == ODB_STRING || p1->what == ODB_WC_STRING)
+			&& 
+			(p2->what == ODB_STRING || p2->what == ODB_NAME))
+		       ||
+		       ((p2->what == ODB_STRING || p2->what == ODB_WC_STRING)
+			 && 
+			(p1->what == ODB_STRING || p1->what == ODB_NAME)));
+	}
+      } /* if (is_string) */
+    }
+    else {
+      /* No second parameter ==> a unary operation or so */
+      on_error = is_string; /* No unary operations available for ODB_STRING */
+    }
+  }
+    
+  if (on_error && is_error) {
+    SETMSG0("Invalid presence of a string expression");
+    YYerror(msg);
+  }
+
+  return on_error;
+}
+
+
+PRIVATE int
+remap_expr_symbols(ODB_Tree *pnode, int nsym, ODB_Symbol **psym, 
+		   char **tag, ODB_Symbol **psym_updated)
+{
+  int rc = 0;
+  static int stklen = 0;
+  Boolean Master = 0;
+
+  if (tag && psym && nsym > 0) {
+    int j;
+    for (j=nsym-1; j>=0; j--) {
+      if (tag[j] && psym[j]) {
+	char *atag = tag[j];
+	char *name = psym[j]->name;
+	if (IS_HASH(name)) continue;
+	if (IS_DOLLAR(name)) continue;
+	/* fprintf(stderr,"remap_expr_symbols: pushing symbol[%d] = '%s' to stack\n",j,psym[j]->name); */
+	ODB_pushSYMBOL(psym[j]);
+	/* fprintf(stderr,"remap_expr_symbols: pushing tag[%d] = '%s' to stack\n",j,atag); */
+	ODB_pushstr(atag);
+	ODB_pushi(j);
+	stklen++;
+      }
+    }
+    Master = 1;
+  }
+
+  if (pnode && stklen > 0) {
+    int what = pnode->what;
+    
+    switch (what) {
+      
+    case ODB_EQ:
+    case ODB_NE:
+    case ODB_GT:
+    case ODB_GE:
+    case ODB_LE:
+    case ODB_LT:
+    case ODB_AND:
+    case ODB_OR:
+    case ODB_ADD:
+    case ODB_SUB:
+    case ODB_STAR:
+    case ODB_DIV:
+      rc += remap_expr_symbols(pnode->argv[0], 0, NULL, NULL, psym_updated);
+      rc += remap_expr_symbols(pnode->argv[1], 0, NULL, NULL, psym_updated);
+      break;
+      
+    case ODB_UNARY_PLUS:
+    case ODB_UNARY_MINUS:
+    case ODB_NOT:
+      rc += remap_expr_symbols(pnode->argv[0], 0, NULL, NULL, psym_updated);
+      break;
+      
+    case ODB_NAME:
+      { /* Note the reverse order of these 'pops' */
+	int j = ODB_popi();
+	char *atag = ODB_popstr();
+	ODB_Symbol *psym = ODB_popSYMBOL();
+	ODB_Symbol *newsym = NULL;
+	char *pcolon = strchr(atag,':');
+	if (pcolon) {
+	  pcolon++;
+	  if (!strequ(psym->name,pcolon)) {
+	    newsym = ODB_new_symbol(ODB_NAME, pcolon);
+	    if (psym_updated) psym_updated[j] = newsym;
+	  }
+	}
+	pnode->argv[0] = newsym ? newsym : psym; /* Changed the symbol pointer !! */
+	rc++;
+	stklen--;
+      }
+      break;
+
+    case ODB_COND:
+      {
+	int j, numargs = pnode->argc;
+	for (j=0; j<numargs; j++) {
+	  rc += remap_expr_symbols(pnode->argv[j], 0, NULL, NULL, psym_updated);
+	}
+      }
+      break;
+      
+    case ODB_FUNC:
+    case ODB_FUNCAGGR:
+      {
+	int j, numargs = pnode->argc - 1;
+	if (numargs > 0) {
+	  for (j=1; j<=numargs; j++) {
+	    rc += remap_expr_symbols(pnode->argv[j], 0, NULL, NULL, psym_updated);
+	  }
+	}
+      }
+      break;
+
+    case ODB_NUMBER:
+      /* Do nothing ? */
+      break;
+      
+    default:
+      fprintf(stderr,
+	      "***Warning in remap_expr_symbols() :"
+	      "what = %d alias '%s' : Should be here ?\n", what, ODB_keymap(what));
+      break;
+    } /* switch (what) */
+  } /* if (pnode && stklen > 0) */
+
+  if (Master && stklen != 0) {
+    SETMSG1("A serious programming error in remap_expr_symbols(): stklen != 0 (stklen=%d)",stklen);
+    YYerror(msg);
+  }
+
+  return rc;
+}
+
+PUBLIC int
+ODB_setup_selectexpr(ODB_View *pview, int k, int j)
+{
+  int rc = 0;
+  if (pview && pview->sel && k >= 0 && j >= 0) {
+    int nselect_all = pview->nselect_all;
+    int nwhere = pview->nwhere;
+    int norderby = pview->norderby;
+    int i = nselect_all+nwhere+norderby + k;
+    int n = remap_expr_symbols(pview->sel[j]->expr, 
+			       pview->sel[j]->nsym, pview->sel[j]->sym, &pview->tag[i],
+			       pview->sel[j]->sym);
+    rc = pview->sel[j]->nsym;
+  }
+  return rc;
+}
+
+PUBLIC uint
+ODB_which_aggr(const ODB_Tree *pnode, int *ncols_aux)
+{
+  int Ncols_aux = 0;
+  uint aggr_flag = ODB_AGGR_NONE;
+  if (pnode && pnode->what == ODB_FUNCAGGR) {
+    const ODB_Symbol *psym = pnode->argv[0];
+    const char *name = psym->name;
+    if (strequ(name,"min")) aggr_flag = ODB_AGGR_MIN;
+    else if (strequ(name,"max")) aggr_flag = ODB_AGGR_MAX;
+    else if (strequ(name,"density")) aggr_flag = ODB_AGGR_DENSITY;
+    else if (strequ(name,"sum")) aggr_flag = ODB_AGGR_SUM;
+    else if (strequ(name,"sum_distinct")) aggr_flag = ODB_AGGR_SUM_DISTINCT;
+    else if (strequ(name,"avg")) aggr_flag = ODB_AGGR_AVG;
+    else if (strequ(name,"avg_distinct")) aggr_flag = ODB_AGGR_AVG_DISTINCT;
+    else if (strequ(name,"median")) aggr_flag = ODB_AGGR_MEDIAN;
+    else if (strequ(name,"median_distinct")) aggr_flag = ODB_AGGR_MEDIAN_DISTINCT;
+    else if (strequ(name,"stdev")) aggr_flag = ODB_AGGR_STDEV;
+    else if (strequ(name,"stdev_distinct")) aggr_flag = ODB_AGGR_STDEV_DISTINCT;
+    else if (strequ(name,"var")) aggr_flag = ODB_AGGR_VAR;
+    else if (strequ(name,"var_distinct")) aggr_flag = ODB_AGGR_VAR_DISTINCT;
+    else if (strequ(name,"rms")) aggr_flag = ODB_AGGR_RMS;
+    else if (strequ(name,"rms_distinct")) aggr_flag = ODB_AGGR_RMS_DISTINCT;
+    else if (strequ(name,"count")) aggr_flag = ODB_AGGR_COUNT;
+    else if (strequ(name,"count_distinct")) aggr_flag = ODB_AGGR_COUNT_DISTINCT;
+    else if (strequ(name,"bcount")) aggr_flag = ODB_AGGR_BCOUNT;
+    else if (strequ(name,"bcount_distinct")) aggr_flag = ODB_AGGR_BCOUNT_DISTINCT;
+    else if (strequ(name,"dotp")) aggr_flag = ODB_AGGR_DOTP;
+    else if (strequ(name,"dotp_distinct")) aggr_flag = ODB_AGGR_DOTP_DISTINCT;
+    else if (strequ(name,"norm")) aggr_flag = ODB_AGGR_NORM;
+    else if (strequ(name,"norm_distinct")) aggr_flag = ODB_AGGR_NORM_DISTINCT;
+    else if (strequ(name,"covar")) { aggr_flag = ODB_AGGR_COVAR; Ncols_aux = 1; }
+    else if (strequ(name,"corr")) { aggr_flag = ODB_AGGR_CORR; Ncols_aux = 1; }
+    else if (strequ(name,"linregr_a")) { aggr_flag = ODB_AGGR_LINREGR_A; Ncols_aux = 1; }
+    else if (strequ(name,"linregr_b")) { aggr_flag = ODB_AGGR_LINREGR_B; Ncols_aux = 1; }
+    else if (strequ(name,"minloc")) { aggr_flag = ODB_AGGR_MINLOC; Ncols_aux = 1; }
+    else if (strequ(name,"maxloc")) { aggr_flag = ODB_AGGR_MAXLOC; Ncols_aux = 1; }
+  }
+  if (ncols_aux) *ncols_aux = Ncols_aux;
+  return aggr_flag;
+}
+
+PUBLIC int
+ODB_RemoveDuplicateTables(ODB_View *v)
+{
+  int new_nfrom = v ? v->nfrom : 0;
+  if (new_nfrom > 0) {
+    ODB_Table **from = NULL;
+    int *from_attr = NULL;
+    int i, nfrom = new_nfrom;
+    int *refcount = NULL;
+    CALLOC(refcount, ODB_ntables);
+    for (i=0; i<nfrom; i++) {
+      const char *tblname = v->from[i]->table->name;
+      ODB_Table *t = ODB_lookup_table(tblname, NULL);
+      int num = t->tableno;
+      if (num >= 0 && num < ODB_ntables) refcount[num]++;
+    }
+    CALLOC(from, nfrom);
+    CALLOC(from_attr, nfrom);
+    new_nfrom = 0;
+    for (i=0; i<nfrom; i++) {
+      const char *tblname = v->from[i]->table->name;
+      ODB_Table *t = ODB_lookup_table(tblname, NULL);
+      int num = t->tableno;
+      if (num >= 0 && num < ODB_ntables && refcount[num] >= 1) {
+	int flag = v->from_attr[i];
+	from[new_nfrom] = v->from[i];
+	from_attr[new_nfrom] = v->from_attr[i];
+	new_nfrom++;
+	refcount[num] = 0;
+      }
+    }
+    FREE(refcount);
+    v->from = from;
+    v->nfrom = new_nfrom;
+  }
+  return new_nfrom;
+}
+
+
+PUBLIC ODB_Tree *
+ODB_oper(int what, void *p1, void *p2, void *p3, void *p4,
+	 const char *filename, int lineno)
+{		
+  ODB_Tree *pnode = new_node(what);
+
+  if (debug) {
+    fprintf(stderr,
+	    "%p = ODB_oper(what=%d i.e. %s [called from %s:%d], p1=%p, p2=%p, p3=%p, p4=%p)\n",
+	    pnode, what, ODB_keymap(what), filename, lineno, p1, p2, p3, p4);
+  }
+
+  switch (what) {
+
+  case ODB_MATCH:
+    {
+      ODB_Match_t *match = p1;
+      int nummatch = 1;
+      pnode->argc = nummatch;
+      ALLOC(pnode->argv, nummatch);
+      pnode->argv[0] = match;
+    }
+    break;
+
+  case ODB_NUMBER:
+    pnode->dval = dval_assign(p1);  /* "p1" used to be a ptr to yylval.dval */
+    break;
+
+  case ODB_ARRNAME:
+    {
+      int j, nsym = ival_assign(p1);  /* "p1" is the number of symbols */
+      what = pnode->what = ODB_NAME; /* Renamed */
+      pnode->argc = nsym;
+      ALLOC(pnode->argv,nsym);
+      /* fprintf(stderr,"ODB_ARRNAME: argc = %d\n",nsym); */
+      for (j=nsym-1; j>=0; j--) {
+	char *s = ODB_popstr();
+	ODB_Symbol *psym = ODB_new_symbol(what, s);
+	pnode->argv[j] = psym;
+	/* fprintf(stderr,"ODB_ARRNAME: argv[%d] -> '%s'\n",j,s); */
+      }
+    }
+    break;
+
+  case ODB_USDNAME:
+    {
+      char *pname = p1;
+      ODB_Symbol *psym = ODB_lookup(ODB_USDNAME,pname,NULL);
+      if (!psym) {
+	SETMSG1("Attempt to use undefined SET-variable '%s'",pname);
+	YYerror(msg);
+      }
+    }
+
+    /* no break; fall through */
+  case ODB_HASHNAME:
+  case ODB_NAME:
+  case ODB_BSNUM:
+  case ODB_STRING:
+  case ODB_WC_STRING:
+    {
+      ODB_Symbol *psym = ODB_new_symbol(what, p1);
+      pnode->argc = 1;
+      ALLOC(pnode->argv,1);
+      pnode->argv[0] = psym;
+    }
+    break;
+
+  case ODB_COND:
+    /* x ? y : z */
+    {
+      int numargs = 3;
+      pnode->argc = numargs;
+      ALLOC(pnode->argv,numargs);
+      pnode->argv[0] = p1;
+      pnode->argv[1] = p2;
+      pnode->argv[2] = p3;
+    }
+    break;
+
+  case ODB_IN:
+    /* 
+       target IN ( a, b, c, ... ) 
+
+         is converted to 
+
+       ((target == a) || (target == b) || (target == c) || ...)
+     */
+    {
+      ODB_Tree *target = p1;
+      int j, numargs = p2 ? ival_assign(p2) : 0;
+      ODB_Tree **args = NULL;
+      CALLOC(args, numargs);
+      for (j=numargs-1; j>=0; j--) {
+	ODB_Tree *expr = ODB_popexpr();
+	args[j] = ODBOPER2(ODB_EQ,target,expr);
+      }
+      if (numargs == 1) {
+	pnode = args[0]; /* i.e. just simply "target == a" */
+      }
+      else { /* numargs > 1 */
+	ODB_Tree *chain = NULL;
+	pnode->argc = 2;
+	ALLOC(pnode->argv,2);
+	pnode->argv[0] = args[0];  /* left expr : "target == a" */
+	chain = args[1];
+	for (j=2; j<numargs; j++) {
+	  chain = ODBOPER2(ODB_OR,chain,args[j]);
+	}
+	pnode->argv[1] = chain;  /* right expr : "((target == b) || (target == c) || ...)" */
+	pnode->what = ODB_OR;    /* we end up with : left || right */
+      }
+      FREE(args);
+    }
+    break;
+
+  case ODB_NOTIN:
+    /* 
+       target NOT IN ( a, b, c, ... ) 
+
+         is converted to 
+
+       ((target != a) && (target != b) && (target != c) && ...)
+     */
+    {
+      ODB_Tree *target = p1;
+      int j, numargs = p2 ? ival_assign(p2) : 0;
+      ODB_Tree **args = NULL;
+      CALLOC(args, numargs);
+      for (j=numargs-1; j>=0; j--) {
+	ODB_Tree *expr = ODB_popexpr();
+	args[j] = ODBOPER2(ODB_NE,target,expr);
+      }
+      if (numargs == 1) {
+	pnode = args[0]; /* i.e. just simply "target != a" */
+      }
+      else { /* numargs > 1 */
+	ODB_Tree *chain = NULL;
+	pnode->argc = 2;
+	ALLOC(pnode->argv,2);
+	pnode->argv[0] = args[0];  /* left expr : "target != a" */
+	chain = args[1];
+	for (j=2; j<numargs; j++) {
+	  chain = ODBOPER2(ODB_AND,chain,args[j]);
+	}
+	pnode->argv[1] = chain;  /* right expr : "((target != b) && (target != c) && ...)" */
+	pnode->what = ODB_AND;   /* we end up with : left && right */
+      }
+      FREE(args);
+    }
+    break;
+
+  case ODB_QUERY:
+    {
+      int j, numargs = p4 ? ival_assign(p4) : 0;
+      char *fname = (numargs > 0) ? "SubQuery" : "RunOnceQuery";
+      char *poolmask = p1 ? p1 : "-1";
+      ODB_Tree *poolmask_expr = ODBOPER1(ODB_STRING, poolmask);
+      char *db = p2 ? p2 : "";
+      ODB_Tree *db_expr = ODBOPER1(ODB_STRING, db);
+      char *query = p3;
+      ODB_Tree *query_expr = ODBOPER1(ODB_STRING, query);
+      double make_sort_unique = 1;
+      ODB_Tree *make_sort_unique_expr =  ODBOPER1(ODB_NUMBER, &make_sort_unique);
+      ODB_Tree **tmpargv = NULL;
+      if (numargs > 0) {
+	ALLOC(tmpargv, numargs);
+	for (j=numargs-1; j>=0; j--) {
+	  tmpargv[j] = ODB_popexpr();
+	}
+      }
+      ODB_pushexpr(poolmask_expr);
+      ODB_pushexpr(db_expr);
+      ODB_pushexpr(query_expr);
+      ODB_pushexpr(make_sort_unique_expr);
+      if (numargs > 0) {
+	for (j=0; j<numargs; j++) ODB_pushexpr(tmpargv[j]);
+	/* FREE(tmpargv); */
+      }
+      if (debug) {
+	fprintf(stderr,"what=ODB_QUERY (%d) near end ; fname='%s' :\n",what,fname);
+	fprintf(stderr,"p1 = %p : poolmask = %s\n",p1,poolmask);
+	fprintf(stderr,"p2 = %p : db = '%s'\n",p2,db);
+	fprintf(stderr,"p3 = %p : query = '%s'\n",p3,query?query:NIL);
+	fprintf(stderr,"make_sort_unique = %d\n",(int)make_sort_unique);
+	fprintf(stderr,"p4 = %p : numargs = %d (numargs+4 = %d)\n",p4,numargs,numargs+4);
+      }
+      numargs += 4;
+      pnode = ODBOPER2(ODB_FUNC, fname, &numargs); /* changed pnode !!!! */
+    }
+    break;
+
+  case ODB_STRFUNC1:
+    {
+      /* 
+	 lat or latitude("helsinki");
+	 lon or longitude("stockholm");
+	 alt or altitude("paris");
+      */
+      char *fname = p1;
+      char *place = p2;
+    back_here:
+      if (strequ(fname,"latitude")   || strequ(fname,"lat")  ||
+	  strequ(fname,"longitude")  || strequ(fname,"lon")  ||
+	  strequ(fname,"altitude")   || strequ(fname,"alt")  || 
+	  strequ(fname,"population") || strequ(fname,"popul") || strequ(fname,"pop")) {
+	int nargs = 1;
+	ODB_Tree *arg1 = ODBOPER1(ODB_STRING,place);
+	char f[4];
+	strncpy(f,fname,3); /* Retain just the first 3 letterz */
+	f[3] = '\0';
+	ODB_pushexpr(arg1);
+	pnode = ODBOPER2(ODB_FUNC, f, &nargs); /* changed pnode !!!! */
+      }
+      else if (strequ(fname,"elevation")  || strequ(fname,"elev")) {
+	fname = "alt";
+	goto back_here;
+      }
+      else {
+	SETMSG2("Unrecognized string function %s(\"%s\")",fname,place);
+	YYerror(msg);
+      }
+    }
+    break;
+
+  case ODB_INSIDE:
+  case ODB_INSIDE_POLYGON:
+  case ODB_NEAR:
+    {
+      /* 
+	 For example:
+	   inside("finland",lat,lon) [returns 1 if inside, 0 otherwise]
+	 or
+	   polygon("/polygon/filename", lat, lon) [returns 1 if inside polygon, 0 otherwise]
+	 or
+	   near("helsinki",lat,lon) [returns distance in meters]
+
+	 You can also leave out the (lat,lon); 
+	 they will be assumed "lat at hdr" and "lon at hdr"
+
+	 These functions also don't need degrees(lat),degrees(lon)
+	 as it is done internally (note also that noawadays degrees() := lldegrees())
+      */
+      ODB_Tree *region = p1; /* code for the region or place name */
+      ODB_Tree *lat = p2;
+      ODB_Tree *lon = p3;
+      char *fname = (what == ODB_INSIDE) ? "Inside" : 
+	((what == ODB_INSIDE_POLYGON) ? "InPolygon" : "Near");
+      int nargs = 3;
+      ODB_pushexpr(region);
+      ODB_pushexpr(lat);
+      ODB_pushexpr(lon);
+      pnode = ODBOPER2(ODB_FUNC, fname, &nargs); /* changed pnode !!!! */
+    }
+    break;
+
+  case ODB_STRFUNC:
+    {
+      /* lhs OPER "str", where OPER ODB_{EQ,LIKE} */
+      /* This becomes a vararg function --> {strequal|wildcard}(nargs,str,nargs-1 ARRNAMEs) */
+      ODB_Tree *lhs = p1; /* code for ODB_ARRNAME (renamed to ODB_NAME) */
+      int nsym = lhs->argc;
+      ODB_Tree *str = p2; /* code for ODB_STRING or ODB_WC_STRING */
+      int oper = ival_assign(p3);
+      char *fname = (oper == ODB_EQ) ? "StrEqual" : "WildCard";
+      int j, nargs = 1 + nsym;
+      ODB_pushexpr(str);
+      for (j=0; j<nsym; j++) {
+	ODB_Symbol *psym = lhs->argv[j];
+	ODB_Tree *expr = ODBOPER1(ODB_NAME, psym->name);
+	ODB_pushexpr(expr);
+      }
+      pnode = ODBOPER2(ODB_FUNC, fname, &nargs); /* changed pnode !!!! */
+    }
+    break;
+
+  case ODB_FUNC:
+    {
+      char *fname = p1;
+      Boolean free_fname = 0;
+      int j, numargs = p2 ? ival_assign(p2) : 0;
+      Boolean has_distinct = p3 ? ival_assign(p3) : 0;
+      Boolean distinct_allowed = 0;
+      ODB_Match_t *match = (p4 && strequ(fname, "InQuery")) ? p4 : NULL;
+      int nummatch = 0;
+      int joffset = 0;
+      Boolean is_thin = 0;
+      Boolean is_varargs = 0;
+      Boolean is_offset = 0;
+      int key = 0;
+      int keylen = 0;
+      const int onearg = 1;
+      const funcs_t *f = NULL;
+
+      /* check first if this is LINKOFFSET or LINKLEN -case 
+	 and numargs == 1 and the "onlys" arg-expression is ODB_NAME : if true then
+	 LINKOFFSET(xxx[@table]) will be changed to xxx.offset[@table]
+	 LINKLEN(xxx[@table]) will be changed to xxx.len[@table]
+	 the [@table] is optional and could be either blank or @table
+      */
+
+      if (numargs == 1 && (strequ(fname,"linklen") || strequ(fname,"linkoffset"))) {
+	Boolean linklen = strequ(fname,"linklen") ? 1 : 0;
+	ODB_Tree *expr = ODB_popexpr();
+	if (expr && expr->what == ODB_NAME && expr->argv) { /* still cool !! */
+	  ODB_Symbol *psym = expr->argv[0];
+	  char *s = psym->name;
+	  char *pvar = NULL;
+	  char *pmember = NULL;
+	  char *ptable = NULL;
+	  (void) ODB_split(s, NULL, &pvar, &pmember, &ptable, NULL);
+	  if (pvar && !pmember) {
+	    char *snew;
+	    int slen = strlen(pvar) + STRLEN(ptable) + 20;
+	    ALLOC(snew, slen);
+	    snprintf(snew,slen,"%s.%s%s%s",
+		     pvar,
+		     linklen ? "len" : "offset",
+		     ptable ? "@" : "",
+		     ptable ? ptable : "");
+	    FREE(pvar);
+	    FREE(pmember);
+	    FREE(ptable);
+	    pnode = ODBOPER1(ODB_NAME, snew);
+	    break; /* changed pnode !!!! */
+	  }
+	  FREE(pvar);
+	  FREE(pmember);
+	  FREE(ptable);
+	}
+	/* No success --> push the last expression back to stack */
+	ODB_pushexpr(expr);
+      }
+
+      /* check if count(expression), in which case turn it to bcount-function
+	 (boolean count), which is similar to Fortran90's count(logical_expression) function */
+
+      if (numargs == 1 && strequ(fname,"count")) {
+	ODB_Tree *expr = ODB_popexpr();
+	if (!ODB_IsSimpleExpr(expr,0)) fname = "bcount"; /* now a boolean counter */
+	ODB_pushexpr(expr); /* restore expression stack */
+      }
+
+      if (strequ(fname,"atan") && numargs == 2) {
+	/* Means atan2(arg1,arg2) */
+	fname = "atan2";
+      }
+      else if (strequ(fname,"degrees") || strequ(fname,"rad2deg")) {
+	fname = "degrees";
+      }
+      else if (strequ(fname,"radians") || strequ(fname,"deg2rad")) {
+	fname = "radians";
+      }
+      else if (strequ(fname,"lldegrees") || strequ(fname,"ll_degrees") ||
+	       strequ(fname,"lldeg")) {
+	fname = "lldegrees";
+      }
+      else if (strequ(fname,"latdegrees") || strequ(fname,"latrad2deg") ||
+	       strequ(fname,"lat_degrees") || strequ(fname,"lat_rad2deg")) {
+	fname = "lldegrees";
+      }
+      else if (strequ(fname,"londegrees") || strequ(fname,"lonrad2deg") ||
+	       strequ(fname,"lon_degrees") || strequ(fname,"lon_rad2deg")) {
+	fname = "lldegrees";
+      }
+      else if (strequ(fname,"llradians") || strequ(fname,"ll_radians") ||
+	       strequ(fname,"llrad")) {
+	fname = "llradians";
+      }
+      else if (strequ(fname,"latradians") || strequ(fname,"latdeg2rad") ||
+	       strequ(fname,"lat_radians") || strequ(fname,"lat_deg2rad")) {
+	fname = "llradians";
+      }
+      else if (strequ(fname,"lonradians") || strequ(fname,"londeg2rad") ||
+	       strequ(fname,"lon_radians") || strequ(fname,"lon_deg2rad")) {
+	fname = "llradians";
+      }
+      else if (strequ(fname,"invector")) {
+	fname = "in_vector";
+      }
+      else if (strequ(fname,"minval")) {
+	fname = "min";
+      }
+      else if (strequ(fname,"maxval")) {
+	fname = "max";
+      }
+      else if (strequ(fname,"cov") || strequ(fname,"covariance") ||
+	       strequ(fname,"covarians")) {
+	fname = "covar";
+      }
+      else if (strequ(fname,"correlation") || strequ(fname,"correl")) {
+	fname = "corr";
+      }
+      else if (strequ(fname,"lina") || strequ(fname,"linregra") || 
+	       strequ(fname,"linrega") || strequ(fname,"linreg_a")) {
+	fname = "linregr_a";
+      }
+      else if (strequ(fname,"linb") || strequ(fname,"linregrb") || 
+	       strequ(fname,"linregb") || strequ(fname,"linreg_b")) {
+	fname = "linregr_b";
+      }
+      else if (strequ(fname,"std") || strequ(fname,"stddev")) {
+	fname = "stdev";
+      }
+      else if (strequ(fname,"variance") || strequ(fname,"varians")) {
+	fname = "var";
+      }
+      else if (strequ(fname,"average") || strequ(fname,"mean")) {
+	fname = "avg";
+      }
+      else if (strequ(fname,"rand")) {
+	fname = "random";
+      }
+      else if (strequ(fname,"datenow")) {
+	fname = "date_now";
+      }
+      else if (strequ(fname,"timenow")) {
+	fname = "time_now";
+      }
+      else if (strequ(fname, "thinn") ||
+	       strequ(fname, "thinned") || strequ(fname, "thinning")) {
+	fname = "thin";
+      }
+      else if (strequ(fname, "celsius")) {
+	fname = "k2c";
+      }
+      else if (strequ(fname, "fahrenheit")) {
+	fname = "k2f";
+      }
+      else if (strequ(fname, "dotproduct") || 
+	       strequ(fname, "dot_product") ||
+	       strequ(fname, "dot_prod")) {
+	fname = "dotp";
+      }
+      else if (strequ(fname, "timestamp")) {
+	fname = "tstamp";
+      }
+      else if (strequ(fname, "time_angle")) {
+	fname = "ta";
+      }
+      else if (strequ(fname, "hour_angle")) {
+	fname = "ha";
+      }
+      else if (strequ(fname, "daynum")) {
+	fname = "datenum";
+      }
+      else if (strequ(fname, "solar_declination") || strequ(fname, "solar_declination_angle")) {
+	fname = "sda";
+      }
+      else if (strequ(fname, "solar_elevation") || strequ(fname, "solar_elevation_angle") ||
+	       strequ(fname, "solar_altitude") || strequ(fname, "solar_altitude_angle")) {
+	fname = "sela";
+      }
+      else if (strequ(fname, "solar_zenith") || strequ(fname, "solar_zenith_angle")) {
+	fname = "sza";
+      }
+      else if (strequ(fname, "solar_azimuth") || strequ(fname, "solar_azimuth_angle")) {
+	fname = "saza";
+      }
+
+      if (strequ(fname,"count")) {
+	if (numargs == 0 && !has_distinct) { /* count(*) or just count() */
+	  /* note: count(distinct *) not possible due to yacc.y grammar defs, however
+	     count(distinct) is possible and thus must not be accepted */
+	  double one = 1;
+	  ODB_Tree *expr = ODBOPER1(ODB_NUMBER,&one);
+	  ODB_pushexpr(expr);
+	  numargs = 1;
+	  /* Need to flag presence of count(*) to trigger failure in case of "No active tables" */
+	  /* Happens with 'SELECT count(*) FROM hdr', which should have been either
+	     'SELECT count(#hdr) FROM hdr' or 'SELECT count(lat) FROM hdr' */
+	  has_count_star = 1; /* will be reset back to 0 (false) after ODBOPER(ODB_VIEW,...) in yacc.y */
+	}
+	if (numargs == 1) { 
+	  pnode->what = ODB_FUNCAGGR;
+	  distinct_allowed = has_distinct;
+	  f = NULL;
+	}
+	else {
+	  f = check_func(fname, numargs, NULL, NULL);
+	}
+      }
+      else if (strequ(fname,"sum")   || strequ(fname,"avg") || strequ(fname,"median")  ||
+	       strequ(fname,"stdev") || strequ(fname,"rms") || strequ(fname,"density") ||
+	       strequ(fname,"var")   || strequ(fname,"bcount") ) {
+	if (numargs == 1) { 
+	  pnode->what = ODB_FUNCAGGR;
+	  distinct_allowed = has_distinct;
+	  f = NULL;
+	}
+	else {
+	  f = check_func(fname, numargs, NULL, NULL);
+	}
+      }
+      else if (strequ(fname,"dotp") || strequ(fname,"norm")) {
+	if (numargs == 2) { 
+	  pnode->what = ODB_FUNCAGGR;
+	  distinct_allowed = has_distinct;
+	  f = NULL;
+	}
+	else {
+	  f = check_func(fname, numargs, NULL, NULL);
+	}
+      }
+      else if (strequ(fname,"corr") || strequ(fname,"covar")  ||
+	       strequ(fname,"linregr_a") || strequ(fname,"linregr_b") ||
+	       strequ(fname,"minloc") || strequ(fname,"maxloc")) {
+	if (numargs == 2) { 
+	  pnode->what = ODB_FUNCAGGR;
+	  f = NULL;
+	}
+	else {
+	  f = check_func(fname, numargs, NULL, NULL);
+	}
+      }
+      else if (strequ(fname,"min") || strequ(fname,"max")) {
+	if (numargs == 1) { 
+	  pnode->what = ODB_FUNCAGGR;
+	  /* fname = strequ(fname,"min") ? "Min" : "Max"; */
+	  f = NULL;
+	}
+	else {
+	  /* Allocate more space for one hidden arg (which is # of actual args) */
+	  f = check_func(fname, numargs, &onearg, NULL); /* Requires at least 1 argument */
+	  is_varargs = 1;
+	}
+      }
+      else if (strequ(fname, "InQuery")) {
+	const int fivearg = 5;
+	f = check_func(fname, numargs, &fivearg, NULL); /* Requires at least 5 arguments */
+	if (match) nummatch = 1; /* Just for clarify; not used for anything here */
+	is_varargs = 1;
+      }
+      else if (strequ(fname, "cksum")) {
+	f = check_func(fname, numargs, NULL, NULL); /* Requires no args */
+	is_varargs = 1;
+      }
+      else if (strequ(fname, "StrEqual") || strequ(fname, "WildCard")) {
+	const int twoarg = 2;
+	f = check_func(fname, numargs, &twoarg, NULL); /* Requires 2 or more args */
+	is_varargs = 1;
+      }
+      else if (strequ(fname, "SubQuery") || strequ(fname, "RunOnceQuery")) {
+	const int fourarg = 4;
+	f = check_func(fname, numargs, &fourarg, NULL); /* Requires 4 or more args */
+	is_varargs = 1;
+      }
+      else if (strequ(fname, "thin")) {
+	/* Allocate more space for the two first,hidden, args {key,n} */
+	/* The following separates multiple occurences of the same thin()-functions */
+	static int thincnt = 0; 
+	++thincnt;
+	is_thin = 1;
+	key = ODB_cksum32((const char *)&thincnt, sizeof(thincnt), key);
+	keylen += sizeof(thincnt);
+	f = check_func(fname, numargs, &onearg, NULL); /* Require at least 1 argument */
+      }
+      else if (strequ(fname, "offset")) {
+	/* offset()-function : 2 args of which
+	   the 1st one must be column at table, but
+	   the 2nd one must be an evaluable (constant) expression
+	*/
+	is_offset = 1;
+	has_OFFSET_func = 1;
+	f = check_func(fname, numargs, NULL, NULL);
+      }
+      else {
+	f = check_func(fname, numargs, NULL, NULL);
+      }
+
+      if (f) joffset = f->joffset;
+
+      if (distinct_allowed) {
+	int plen = strlen(fname) + strlen("_distinct") + 1;
+	char *p;
+	ALLOC(p,plen);
+	snprintf(p,plen,"%s_distinct",fname);
+	fname = p;
+	free_fname = 1;
+	f = check_func(fname, numargs, NULL, NULL);
+      }
+
+      pnode->joffset = joffset;
+      pnode->argc = 1 + joffset + numargs;
+      ALLOC(pnode->argv,pnode->argc);
+      pnode->argv[0] = ODB_new_symbol(what, fname); /* function name */
+      if (free_fname) FREE(fname);
+
+      /* Flush the expression stack */
+
+      srand(numargs);
+      for (j=numargs; j>=1; j--) {
+	ODB_Tree *addr = ODB_popexpr();
+	pnode->argv[joffset+j] = addr;
+
+	if (is_thin) {
+	  if (addr && addr->argc > 0) {
+	    double random_number = (double)rand()/(double)RAND_MAX;
+	    double number = random_number;
+	    switch (addr->what) {
+	    case ODB_FUNC:
+	      number = addr->argc;
+	      key = ODB_cksum32((const char *)&number, sizeof(number), key);
+	      keylen += sizeof(number);
+	      /* fall through */
+	    case ODB_BSNUM:
+	    case ODB_NAME:
+	    case ODB_USDNAME:
+	    case ODB_HASHNAME:
+	    case ODB_STRING:
+	    case ODB_WC_STRING:
+	      {
+		const ODB_Symbol *psym = addr->argv[0];
+		const char *s = psym ? psym->name : NULL;
+		int slen = STRLEN(s);
+		if (slen > 0) {
+		  key = ODB_cksum32(s, slen, key);
+		  keylen += slen;
+		}
+		else { /* A fallback */
+		  number = random_number;
+		  key = ODB_cksum32((const char *)&number, sizeof(number), key);
+		  keylen += sizeof(number);
+		}
+	      }
+	      break;
+	    case ODB_NUMBER:
+	      number = addr->dval;
+	      /* fall through */
+	    default:
+	      key = ODB_cksum32((const char *)&number, sizeof(number), key);
+	      keylen += sizeof(number);
+	      break;
+	    } /* switch (addr->what) */
+	  }
+	}
+      } /* for (j=numargs; j>=1; j--) */
+
+      if (is_thin) { /* thinning function */
+	double d1, d2;
+	d1 = numargs + 1; /* The number of actual args/expressions after this arg "n" */
+	pnode->argv[1] = ODBOPER1(ODB_NUMBER,&d1);
+	key = ODB_pp_cksum32(keylen, key);
+	d2 = key;
+	pnode->argv[2] = ODBOPER1(ODB_NUMBER,&d2);
+      }
+      else if (is_offset) { /* offset(expr_1, expr_2) -function */
+	int error_count = 0;
+	ODB_Tree *expr_1 = pnode->argv[1];
+	ODB_Tree *expr_2 = pnode->argv[2];
+	double offset = 0;
+	{
+	  /* The 1st arg must be ODB_NAME */
+	  if (expr_1->what != ODB_NAME) {
+            error_count++;
+	    SETMSG1("The 1st argument in offset()-function must be a column name (ODB_NAME). Was %s",
+		    ODB_keymap(expr_1->what));
+	    YYwarn(error_count, msg); /* No abort yet */
+	  }
+	}
+        {
+          /* 2nd arg must be a constant expression (i.e. evaluable) */
+          int irc = ODB_evaluate(expr_2,&offset);
+          if (!irc) {
+            error_count++;
+            SETMSG1("The 2nd argument in offset()-function must be a constant expression. Was %s",
+                    ODB_keymap(expr_2->what));
+            YYwarn(error_count, msg); /* No abort yet */
+          }
+	  if (error_count == 0) {
+	    /* Replace the result of evaluation with a constant number */
+	    expr_2->dval = offset;
+	    expr_2->what = ODB_NUMBER;
+	  }
+        }
+        if (error_count > 0) {
+          SETMSG0("Invalid argument(s) in offset()-function");
+          YYerror(msg);
+        }
+	/* Finally : Turn this pnode into a ODB_NAME, with offset appended
+	   into the name itself with OFFSET_CHAR as a separator */
+	{
+	  int ioffset = (offset >= -INT_MAX && offset <= INT_MAX) ? (int)offset : 0;
+	  ODB_Symbol *psym = expr_1->argv[0];
+	  char *name = psym->name;
+	  char *newname = NULL;
+	  if (ioffset != 0) {
+	    int len = STRLEN(name) + 30;
+	    ALLOC(newname,len);
+	    snprintf(newname,len,"%s%s%s%d",
+		     name,ODB_OFFSET_CHAR,
+		     (ioffset > 0) ? "" : "_",
+		     ABS(ioffset));
+	  }
+	  else {
+	    newname = STRDUP(name);
+	  }
+	  pnode = ODBOPER1(ODB_NAME,newname);
+	}
+      }
+      else if (is_varargs) { /* variable no. of args */
+	double nargs = numargs;
+	pnode->argv[1] = ODBOPER1(ODB_NUMBER,&nargs);
+      }
+    }
+    break;
+
+  case ODB_FILE:
+    {
+      ODB_Symbol *pfunc = ODB_new_symbol(what, p1); /* function name */
+      int numargs = 2;
+
+      (void) check_func(pfunc->name, numargs, NULL, NULL);
+
+      pnode->argc = numargs + 1;
+      ALLOC(pnode->argv,pnode->argc);
+      pnode->argv[0] = pfunc;
+      pnode->argv[1] = p2; /* filename */
+      pnode->argv[2] = p3; /* expression */
+    }
+    break;
+
+  case ODB_EQ:
+  case ODB_ADD:
+  case ODB_SUB:
+  case ODB_STAR:
+  case ODB_DIV:
+  case ODB_GT:
+  case ODB_GE:
+  case ODB_LE:
+  case ODB_LT:
+  case ODB_NE:
+  case ODB_AND:
+  case ODB_OR:
+    check_string(1,what,p1,p2);
+    pnode->argc = 2;
+    ALLOC(pnode->argv,2);
+    pnode->argv[0] = p1;   /* left expr */
+    pnode->argv[1] = p2;  /* right expr */
+    break;
+
+  case ODB_UNARY_PLUS: 
+  case ODB_UNARY_MINUS: 
+  case ODB_NOT: 
+    check_string(1,what,p1,NULL);
+    pnode->argc = 1;
+    ALLOC(pnode->argv,1);
+    pnode->argv[0] = p1;   /* unary expr */
+    break;
+
+  case ODB_GTGT:
+  case ODB_GTGE:
+  case ODB_GEGE:
+  case ODB_GEGT:
+  case ODB_LTLT:
+  case ODB_LTLE:
+  case ODB_LELE:
+  case ODB_LELT:
+    {
+      int XX = what / ODB_SCALE;
+      int YY = what % ODB_SCALE;
+      pnode->argc = 2;
+      ALLOC(pnode->argv,2);
+      what = pnode->what = ODB_AND;   /* Switch 'what' to ODB_AND */
+      pnode->argv[0] = ODBOPER2(XX, p1, p2);  /* left & middle expr */
+      pnode->argv[1] = ODBOPER2(YY, p2, p3);  /* middle & right expr */
+    }
+    break;   
+
+  case ODB_SET:
+    {
+      ODB_Symbol *psym = p1;
+      ODB_Tree *expr = p2;
+      Boolean is_string = check_string(0, what, expr, NULL);
+      if (!is_string) {
+	double dval = 0;
+	int irc = ODB_evaluate(expr, &dval);
+	
+	if (irc) psym->dval = dval;
+	
+	pnode->argc = 1;
+	ALLOC(pnode->argv,1);
+	pnode->argv[0] = psym;
+      }
+      else {
+	if (expr->what == ODB_STRING && expr->argc == 1) {
+	  ODB_Symbol *psym1 = expr->argv[0];
+	  double dval = s2d(psym1->name, expr->what);
+	  char *str = d2s(dval);
+	  ODB_Symbol *psym2 = ODB_new_symbol(expr->what, str);
+	  pnode->argc = 1;
+	  ALLOC(pnode->argv,1);
+	  pnode->argv[0] = psym2;
+	  FREE(str);
+	}
+	else {
+	  SETMSG1("Invalid expression in SET-variable '%s' declaration",psym->name);
+	  YYerror(msg);
+	}
+      }
+    }
+    break;
+
+  case ODB_TYPE:
+    pnode->argc = 1;
+    ALLOC(pnode->argv,1);
+    pnode->argv[0] = p1;
+    
+    if (p1) {
+      ODB_Type *type = p1;
+      char *tyname = type->type->name;
+      int nsym = ival_assign(p2);
+      int j, bitcount;
+      
+      /* Note overallocation for use by UNUSED if applicable */
+
+      type->nsym = nsym;
+      ALLOC(type->sym, nsym + 1);
+      ALLOC(type->member, nsym + 1);
+      
+      for (j=nsym-1; j>=0; j--) {
+	char *s;
+	s = ODB_popstr(); /* member name from stack */
+	type->member[j] = ODB_lookup(ODB_NAME, s, NULL);
+	s = ODB_popstr(); /* type string from stack */
+	type->sym[j] = ODB_lookup(ODB_TYPE, s, NULL);
+      }
+
+      type->no_members = (nsym == 1 && strequ(type->member[0]->name,EMPTY_MEMBER));
+
+      if (type->no_members) {
+	Boolean already_in_list;
+
+	type->member[0] = ODB_lookup(ODB_TYPE, tyname, NULL);
+	already_in_list = add_alias(type->sym[0]->name, type->member[0]->name);
+
+	if (already_in_list) {
+	  SETMSG2("Attempt to supersede already defined type '%s' with '%s'",
+		  type->member[0]->name, type->sym[0]->name);
+	  YYerror(msg);
+	}
+      }
+      
+      /* Check if solely a bit stream */
+
+      ALLOC(type->pos, nsym + 1);
+      ALLOC(type->len, nsym + 1);
+
+      for (j=0; j<nsym; j++) {
+	type->pos[j] = 0;
+	type->len[j] = 0;
+      }
+
+      type->bitstream = (!type->no_members);
+      bitcount = 0;
+
+      if (type->bitstream) {
+	for (j=0; j<nsym; j++) {
+	  char *s = type->sym[j]->name;
+	  
+	  if (strnequ(s,"bit",3)) {
+	    int nbits = atoi(s+3);
+	    type->pos[j] = bitcount;
+	    type->len[j] = nbits;
+	    bitcount += nbits;
+	  }
+	  else {
+	    type->bitstream = 0;
+	    break;
+	  }
+	} /* for (j=0; j<nsym; j++) */
+      }
+
+      if (type->bitstream) {
+	if (bitcount > MAXBITS) {
+	  SETMSG2("Exceeded maximum no. of bits (%d) allowed per data struct in type '%s'",
+		  MAXBITS, tyname);
+	  YYerror(msg);
+	}
+
+#ifdef EXCLUDE_THIS
+	if (bitcount < MAXBITS) {
+	  /* Allocate an extra field called UNUSED */
+
+	  int nbits = MAXBITS - bitcount;
+	  /* char unused[] = UNUSED; */
+	  char pbit[10];
+	  snprintf(pbit,sizeof(pbit),"bit%d",nbits);
+
+	  type->member[nsym] = ODB_new_symbol(ODB_NAME, UNUSED);
+	  type->sym[nsym] = ODB_new_symbol(ODB_TYPE, pbit);
+	  type->pos[nsym] = bitcount;
+	  type->len[nsym] = nbits;
+
+	  type->nsym = ++nsym;
+
+	  bitcount += nbits; /* Now this should equal to MAXBITS */
+	}
+#endif
+
+      } /* if (type->bitstream) */
+    }
+    break;
+
+  case ODB_TABLE:
+    pnode->argc = 1;
+    ALLOC(pnode->argv,1);
+    pnode->argv[0] = p1;
+    break;
+
+  case ODB_VIEW:
+    pnode->argc = 1;
+    ALLOC(pnode->argv,1);
+    pnode->argv[0] = p1;
+    
+    if (p1) {
+      ODB_View *v = p1;
+      char *vname = v->view->name;
+      int nselect = v->nselect;
+      int nselect_all = v->nselect_all;
+      int nfrom   = v->nfrom;
+      int nwhere  = v->nwhere;
+      int norderby = v->norderby;
+      int nselsym = v->nselsym;
+      int nsym = nselect_all + nwhere + norderby + nselsym;
+      int *refsym = NULL;
+      int i, j, k;
+      int error_count = 0;
+      int prtsyms = 0;
+      Boolean redundant_tables = (v->create_index >= 0) ? 1 : 0;
+      Boolean *in_select = NULL;
+      Boolean *in_where = NULL;
+      Boolean *in_orderby = NULL;
+      Boolean *in_selsym = NULL;
+      
+      v->has_count_star = has_count_star;
+      v->safeGuard = safeGuard;
+
+      ODB_link_massage();
+
+      nfrom = ODB_RemoveDuplicateTables(v);
+      
+      CALLOC(in_select, nsym);
+      CALLOC(in_where, nsym);
+      CALLOC(in_orderby, nsym);
+      CALLOC(in_selsym, nsym);
+
+      ALLOC(v->table_index, nsym);
+      for (k=0; k<nsym; k++) v->table_index[k] = RMDI;
+
+      CALLOC(v->tag, nsym);
+      CALLOC(v->call_arg, nsym);
+      CALLOC(v->def_get, nsym);
+      CALLOC(v->alias_get, nsym);
+      CALLOC(v->def_put, nsym);
+      CALLOC(v->alias_put, nsym);
+      CALLOC(v->poslen, nsym);
+      CALLOC(v->offset, nsym);
+      
+      while (redundant_tables) {
+	Boolean *reftab = NULL;
+	ODB_Table **from = NULL;
+	int *from_attr = NULL;
+	int new_nfrom = 0;
+
+	ALLOC(reftab, nfrom);
+	ALLOC(from, nfrom);
+	ALLOC(from_attr, nfrom);
+	
+	CALLOC(refsym, nsym);
+
+	for (i=0; i<nfrom; i++) {
+	  ODB_Table *t = v->from[i];
+	  char *tname = t->table->name;
+	  int nlink = t->nlink;
+	  
+	  /* We must accept traversal over all FROM-tables if count(*) was present ;
+	     However, do NOT accept those tables which were auto-inserted by the program 
+	     (see INSERT; or ODB_INSERT_TABLES) */
+
+	  reftab[i] =
+	    (((v->from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) || 
+	     (!v->has_count_star)) ? 0 : 1;
+	  
+	  k = 0;
+	  PROCESS("SELECT", select, nselect, i, in_select, 0, 0, 1);
+	  
+	  k = nselect_all;
+	  PROCESS("WHERE", where, nwhere, i, in_where, 1, 0, 0);
+
+	  k = nselect_all + nwhere;
+	  PROCESS("ORDERBY", orderby, norderby, i, in_orderby, 0, 0, 0);
+
+	  k = nselect_all + nwhere + norderby;
+	  PROCESS("SELECTEXPR", selsym, nselsym, i, in_selsym, 0, 1, 0);
+
+	  if (!reftab[i] && nlink > 0) {
+	    /* Check if LINKs to any tables that follow are found */
+	    int jj;
+	    for (jj=0; jj<nlink && !reftab[i]; jj++) {
+	      char *linkname = t->linkname[jj];
+	      int ii;
+	      for (ii=i+1; ii<nfrom && !reftab[i]; ii++) {
+		ODB_Table *tii = v->from[ii];
+		char *tiiname = tii->table->name;
+		reftab[i] = strequ(tiiname, linkname);
+	      } /* for (ii=i+1; ii<nfrom && !reftab[i]; ii++) */
+	    } /* for (jj=0; jj<nlink && !reftab[i]; jj++) */
+	  }
+	} /* for (i=0; i<nfrom; i++) */
+
+	redundant_tables = 0;
+	new_nfrom = 0;
+
+	for (i=0; i<nfrom; i++) {
+	  int flag = v->from_attr[i];
+	  if (reftab[i]) {
+	    from[new_nfrom] = v->from[i];
+	    from_attr[new_nfrom] = v->from_attr[i];
+	    new_nfrom++;
+	  } 
+	  else {
+	    ODB_Table *t = v->from[i];
+	    char *tname = t->table->name;
+	    if ((flag & ODB_FROM_ATTR_INSERT) != ODB_FROM_ATTR_INSERT) {
+	      /* Report only those tables which compiler has *not* inserted itself */
+	      if (!v->no_from_stmt) { /* Assume FROM-stmt was indeed present */
+	        SETMSG3("Table '%s' is not referenced in view '%s' [0x%x]\n", tname, vname,flag);
+	        PRTMSG(msg);
+	      }
+	    }
+	    redundant_tables = 1;
+	  }
+	}
+
+	if (nfrom == 0) {
+	  SETMSG1("No active tables in view '%s'\n",vname);
+	  PRTMSG(msg); /* Changed from error to warning */
+	  v->nfrom = 0;
+	  redundant_tables = 0;
+	}
+	else if (redundant_tables) {
+	  for (i=0; i<new_nfrom; i++) {
+	    v->from[i] = from[i];
+	    v->from_attr[i] = from_attr[i];
+	  }
+	  nfrom = v->nfrom = new_nfrom;
+	  FREE(refsym);
+	}
+
+	FREE(from);
+	FREE(reftab);
+      } /* while (redundant_tables) */
+      
+      for (k=0; k<nsym; k++) {
+	int count = refsym[k];
+	
+	if (count != 1) {
+	  char *w;
+	  ODB_Symbol *psym = NULL;
+	  char *name;
+	  Boolean is_error = 0;
+	  Boolean is_where = 0;
+	  Boolean is_selsym = 0;
+	  Boolean is_formula = 0;
+	  
+	  if (in_select[k]) {
+	    w = "SELECT";
+	    psym = v->select[k];
+	    is_formula = (v->is_formula && v->is_formula[k]);
+	  }
+	  else if (in_where[k]) {
+	    w = "WHERE";
+	    psym = v->where[k-(nselect_all)];
+	    is_where = 1;
+	  }
+	  else if (in_orderby[k]) {
+	    w = "ORDERBY";
+	    psym = v->orderby[k-(nselect_all+nwhere)];
+	    is_formula = IS_FORMULA(psym->name);
+	  }
+	  else if (in_selsym[k]) {
+	    w = "SELECTEXPR";
+	    psym = v->selsym[k-(nselect_all+nwhere+norderby)];
+	    is_selsym = 1;
+	  }
+	  else {
+	    psym = NULL; /* Impossible ? */
+	  }
+
+	  name = psym ? psym->name : NULL;
+
+	  if (!name) {
+	    SETMSG2("No active table for empty %s-variable in view '%s'\n",
+		    w, vname);
+	    is_error = 1;
+	  }
+	  else if ((is_where || is_selsym)  && (IS_DOLLAR(name) || IS_HASH(name))) {
+	    is_error = 0;
+	  }
+	  else if (count < 1 && !is_formula) {
+	    SETMSG3("No active table for %s-variable '%s' in view '%s'\n",
+		    w, name, vname);
+	    is_error = 1;
+	  }
+	  else if (count > 1) {
+	    SETMSG3("%s-variable '%s' specified more than once in view '%s'\n",
+		    w, name, vname);
+	    is_error = 1;
+	  }
+
+	  if (is_error) {
+	    PRTMSG(msg);
+	    error_count++;
+	    ++prtsyms;
+	  }
+	}
+      }
+      
+      if (error_count == 0) { 
+	/* Re-assign SELECT/WHERE/ORDERBY-variables to the exact symbol entries */
+	
+	for (k=0; k<nsym; k++) {
+	  ODB_Symbol *psym = NULL;
+	  char *s;
+	  char *pvar = NULL;
+	  Boolean is_formula = 0;
+
+	  if (in_select[k]) {
+	    psym = v->select[k];
+	    is_formula = (v->is_formula && v->is_formula[k]);
+	  }
+	  else if (in_where[k]) {
+	    psym = v->where[k-(nselect_all)];
+	  }
+	  else if (in_orderby[k]) {
+	    psym = v->orderby[k-(nselect_all+nwhere)];
+	    is_formula = IS_FORMULA(psym->name);
+	  }
+	  else if (in_selsym[k]) {
+	    psym = v->selsym[k-(nselect_all+nwhere+norderby)];
+	  }
+
+	  s = psym->name;
+
+	  if (IS_HASH(s)) {
+	    pvar = STRDUP(s);
+	    psym = ODB_lookup(ODB_HASHNAME, pvar, NULL);
+	  }
+	  else if (is_formula) {
+	    if (in_select[k]) {
+	      psym = ODB_lookup(ODB_NAME, v->sel[k]->formula, NULL);
+	    }
+	  }
+	  else {
+	    (void) ODB_split(s, NULL, &pvar, NULL, NULL, NULL);
+	    psym = ODB_lookup(ODB_NAME, pvar, NULL);
+	  }
+
+	  if (!psym) {
+	    if (pvar) {
+	      SETMSG3("Undefined symbol '%s' (now as '%s') in view '%s'\n",s,pvar,vname);
+	    }
+	    else {
+	      SETMSG2("Undefined symbol '%s' in view '%s'\n",s,vname);
+	    }
+	    PRTMSG(msg);
+	    error_count++;
+	    ++prtsyms;
+	  }
+
+	  if (in_select[k]) {
+	    v->select[k] = psym;
+	  }
+	  else if (in_where[k]) {
+	    v->where[k-(nselect_all)] = psym;
+	  }
+	  else if (in_orderby[k]) {
+	    v->orderby[k-(nselect_all+nwhere)] = psym;
+	  }
+	  else if (in_selsym[k]) {
+	    v->selsym[k-(nselect_all+nwhere+norderby)] = psym;
+	  }
+
+	  FREE(pvar);
+	} /* for (k=0; k<nsym; k++) */
+	
+      }
+      
+      FREE(refsym);
+
+      
+      if (error_count == 0) {
+	/* Check for duplicate symbols in SELECT */
+
+	Boolean dupl_exist = 1;
+	int n = nselect_all;
+
+	while (dupl_exist) {
+	  ODB_Symbol **seltag;
+
+	  ALLOC(seltag, n);
+
+	  for (k=0; k<n; k++) {
+	    ODB_Symbol *psym;
+	    ALLOC(psym, 1);
+	    if (!v->tag[k] && v->is_formula && v->is_formula[k]) {
+	      int taglen = strlen("Formula:") + strlen(v->sel[k]->formula) + 1 + strlen("Formula") + 1;
+	      ALLOC(v->tag[k], taglen);
+	      snprintf(v->tag[k], taglen, "Formula:%s at Formula", 
+		       /* In the next +1 since the first item is formula_char 
+			  (see yacc.y; search for first_char) */
+		       v->sel[k]->formula+1);
+	    }
+	    psym->name = v->tag[k];
+	    /* fprintf(stderr,"k=%d :  v->tag[k] = '%s'\n",k, v->tag[k]); */
+	    seltag[k] = psym;
+	  }
+
+	  dupl_exist = ODB_dupl_symbols(seltag, n, 0);
+
+	  /*
+	  if (dupl_exist) {
+	    for (k=0; k<n; k++) {
+	      fprintf(stderr,"k=%d: '%s' ('%s')\n",k,seltag[k]->name,v->select[k]->name);
+	    }
+	  }
+	  */
+	  
+	  for (k=0; k<n; k++) {
+	    FREE(seltag[k]);
+	  }
+	  FREE(seltag);
+
+	  if (dupl_exist) {
+	    SymbolParam_t *sp;
+
+	    ALLOC(sp,1);
+	    sp->nsym = n;
+	    sp->sym = v->select;
+	    sp->readonly = v->readonly;
+	    sp->sel = v->sel;
+
+	    SETMSG1("Duplicate SELECT-variables encountered in the view '%s' => removing\n", 
+		    vname);
+	    PRTMSG(msg);
+	    
+	    
+	    /* error_count++; */
+	    
+	    n = ODB_remove_duplicates(sp,
+				      v->table_index,
+				      v->tag,
+				      v->call_arg,
+				      v->def_put,
+				      v->alias_put,
+				      v->def_get,
+				      v->alias_get,
+				      v->poslen,
+				      v->offset);
+	  }
+	} /* while (dupl_exist) */
+
+	v->nselect = n;
+      }
+
+      if (error_count == 0 && norderby > 0) {
+	/* Check for duplicate symbols in ORDERBY */
+
+	ODB_Symbol **seltag;
+	Boolean dupl_exist;
+
+	ALLOC(seltag, norderby);
+	for (k=0; k<norderby; k++) {
+	  int kk = k + (nselect_all + nwhere);
+	  ODB_Symbol *psym = v->orderby[k];
+	  if (!v->tag[kk] && IS_FORMULA(psym->name)) {
+	    int taglen = strlen("Formula:") + strlen(psym->name) + 1 + strlen("Formula") + 1;
+	    ALLOC(v->tag[kk], taglen);
+	    snprintf(v->tag[kk], taglen, "Formula:%s at Formula", 
+		     /* In the next +1 since the first item is formula_char 
+			(see yacc.y; search for first_char) */
+		     psym->name+1);
+	  }
+	  ALLOC(psym, 1);
+	  psym->name = v->tag[kk];
+	  seltag[k] = psym;
+	}
+
+	dupl_exist = ODB_dupl_symbols(seltag, norderby, 0);
+
+	if (dupl_exist) {
+	  for (k=0; k<norderby; k++) {
+	    fprintf(stderr,"k=%d: '%s'\n",k,seltag[k]->name);
+	  }
+
+	  SETMSG1("Duplicate ORDERBY-variables encountered in the view '%s'\n", vname);
+	  PRTMSG(msg);
+
+	  error_count++;
+	  ++prtsyms;
+	}
+
+	for (k=0; k<norderby; k++) {
+	  FREE(seltag[k]);
+	}
+	FREE(seltag);
+      }
+
+      FREE(in_select);
+      FREE(in_where);
+      FREE(in_orderby);
+      FREE(in_selsym);
+      
+      if (error_count > 0) {
+	if (prtsyms) ODB_print_symbols(NULL);
+	YYerror("Syntax error");
+      }
+    }
+    break;
+
+  default:
+    SETMSG2("Operation '%s' (%d) not supported/implemented",ODB_keymap(what),what);
+    YYerror(msg);
+    break;
+  }
+
+  return pnode;
+}
+
+
+PUBLIC ODB_Symbol **
+ODB_resolve_relations(const char *label,
+		      int bailout_key,
+		      SymbolParam_t *inout,
+		      const char *vname,
+		      ODB_Table **table, 
+		      const int *from_attr,
+		      int ntable,
+		      ODB_Symbol **sym, 
+		      int *sign,
+		      int nsym,
+		      Boolean allow_dollar,
+		      Boolean allow_hash,
+		      int *nsym_out,
+		      int **sign_out)
+{
+  ODB_Symbol **newsym = NULL;
+  Boolean has_symbol_param = (inout != NULL);
+  Boolean may_have_select_expr = (has_symbol_param && inout->sel);
+  int on_error = 0;
+  Boolean has_sign = (sign != NULL && sign_out != NULL);
+  int linkmode_1 = 1;
+  int linkmode_2 = 2;
+  int ReadOnly = 1;
+  int *refcount = NULL;
+  int *linkmode = NULL;
+  int i,j;
+  int more_than_one;
+  int less_than_one;
+  int zero = 0;
+  int redo = 0;
+
+#if 0
+  fprintf(stderr,"ODB_resolve_relations('%s')\n",label);
+#endif
+
+  *nsym_out = 0;
+
+  ALLOC(refcount, nsym);
+  ALLOC(linkmode, nsym);
+
+ re_do:
+  redo = 0;
+
+  for (j=0; j<nsym; j++) {
+    char *s = sym[j]->name;
+    char *pvar = NULL;
+    char *pmember = NULL;
+    char *ptable = NULL;
+    char *poffset = NULL;
+    char *xpvar = NULL;
+    Boolean is_hash = IS_HASH(s);
+    Boolean linkoffset = 0;
+    Boolean linklen = 0;
+    Boolean is_formula = 
+      (IS_FORMULA(s) ||
+       (may_have_select_expr && inout->sel[j] && inout->sel[j]->formula));
+
+#if 0
+    fprintf(stderr,"ODB_resolve_relations(A): name[%d]='%s' : is_formula = %d\n",
+	    j,s,(int)is_formula);
+#endif
+
+    refcount[j] = 0;
+    linkmode[j] = 0;
+
+    if (is_formula) continue; /* skip formulas */
+
+    if (!allow_hash && is_hash) {
+      fprintf(stderr,
+	      "Hash symbols ('%s') cannot be present in %s-clause; view '%s'\n",
+	      s, label, vname);
+      on_error++;
+      continue;
+    }
+
+    if (allow_dollar && IS_DOLLAR(s)) continue;
+
+    if (is_hash) {
+      pvar = STRDUP(s);
+      ptable = STRDUP(s+1);
+    }
+    else {
+      (void) ODB_split(s, NULL, &pvar, &pmember, &ptable, &poffset);
+    }
+
+    if (pmember) {
+      if (strequ(pmember,"off") || strequ(pmember,"offset")) {
+	int len = strlen(pvar) + 20;
+	ALLOC(xpvar, len);
+	snprintf(xpvar,len,"LINKOFFSET(%s)",pvar);
+	linkoffset = 1;
+      }
+      else if (strequ(pmember,"len") || strequ(pmember,"length")) {
+	int len = strlen(pvar) + 20;
+	ALLOC(xpvar, len);
+	snprintf(xpvar,len,"LINKLEN(%s)",pvar);
+	linklen = 1;
+      }
+    }
+
+    for (i=0; i<ntable; i++) {
+      extern char *one_tables;
+      ODB_Table *t = table[i];
+      char *tname = t->table->name;
+      int index = -1;
+      Boolean found = 0;
+      Boolean retry = 0;
+
+      /* Ignore searches from automatically inserted tables, since they
+	 were not considered by the user in the first place */
+      if ((from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) continue;
+
+    retry_again:
+      index = -1;
+      found = ODB_in_table(ODB_NAME, pvar, t, &index);
+
+      if (found && ptable) found = strequ(tname, ptable);
+
+      if (!found) {
+	/* No progress; Try with links if applicable ... */
+
+	if (t->nlink > 0 && pmember && xpvar) {
+	  found = ODB_in_table(ODB_NAME, xpvar, t, &index);
+
+	  if (found && ptable) found = strequ(tname, ptable);
+	  if (found) found = (t->linkmode[index] > 0);
+	} /* if (t->nlink > 0 && ... */
+      } /* if (!found) */
+
+      if (!found && one_tables && t->any_sharedlinks && !retry) {
+	/* Still no progress; Try sharedlinks if applicable ... */
+	char *x = xpvar ? ODB_extract(xpvar, '(',')') : STRDUP(pvar);
+	char *y = strchr(x,'.');
+	retry = 1;
+	if (!y) {
+	  char *master = ODB_get_sharedlinkname(x, one_tables);
+	  FREE(x);
+	  if (master) {
+	    char *new_s;
+	    int len_new_s = 0;
+	    int len_master = strlen(master);
+	    FREE(pvar);
+	    if (linkoffset || linklen) {
+	      ALLOC(pvar,len_master+20);
+	      sprintf(pvar,"%s.%s",master,linkoffset?"offset":"length");
+	      FREE(xpvar);
+	      ALLOC(xpvar, len_master + 20);
+	      sprintf(xpvar,"%s(%s)",linkoffset?"LINKOFFSET":"LINKLEN",master);
+	    }
+	    else {
+	      ALLOC(pvar,len_master+1);
+	      sprintf(pvar,"%s",master);
+	    }
+	    len_new_s += strlen(pvar);
+	    if (ptable)  len_new_s += strlen(ptable) + 1;
+	    if (poffset) len_new_s += strlen(poffset) + 1;
+	    ++len_new_s;
+	    ALLOC(new_s, len_new_s);
+	    if (poffset && !strequ(poffset,"0")) {
+	      int sign = GetSign(poffset);
+	      snprintf(new_s, len_new_s, "%s%s%s%s%s%s",
+		       pvar, 
+		       ptable  ? "@" : "", 
+		       ptable  ? ptable  : "",
+		       ODB_OFFSET_CHAR,
+		       (sign < 0) ? "_" : "",
+		       poffset+ABS(sign)
+		       );
+	    }
+	    else {
+	      snprintf(new_s, len_new_s, "%s%s%s",
+		       pvar, 
+		       ptable  ? "@" : "", 
+		       ptable  ? ptable  : "");
+	    }
+	    sym[j] = ODB_new_symbol(ODB_NAME, new_s); /* change sym[j] !!!! */
+	    FREE(new_s);
+	    FREE(master);
+	    goto retry_again;
+	  }
+	}
+	FREE(x);
+      }
+
+      if (found) {
+	refcount[j]++;
+	linkmode[j] = (index >= 0) ? t->linkmode[index] : 0;
+	/*
+	{
+	  char *typename = (index >= 0) ? t->type[index]->type->name : NIL;
+	  int klinkmode = (index >= 0) ? t->linkmode[index] : -1;
+	  fprintf(stderr,"resolve(j=%d,i=%d): refcount=%d, linkmode=%d",
+		  j,i,refcount[j],linkmode[j]);
+	  fprintf(stderr,
+		  ", pvar='%s', xpvar='%s', pmember='%s', ptable='%s', index=%d, type='%s', linkmode=%d\n",
+		  pvar, xpvar ? xpvar : NIL, pmember ? pmember : NIL,
+		  ptable ? ptable : NIL, index, typename, klinkmode);
+	}
+	*/
+      }
+    } /* for (i=0; i<ntable; i++) */
+
+    FREE(xpvar);
+    FREE(pvar);
+    FREE(pmember);
+    FREE(ptable);
+    FREE(poffset);
+  } /* for (j=0; j<nsym; j++) */
+
+  /* Check if any "refcount[]" greater than one.
+     That means ambiguous tables found i.e.
+     a symbol can be present in more than one table.
+     This is an error. */
+
+  more_than_one = 0;
+  for (j=0; j<nsym; j++) {
+    char *s = sym[j]->name;
+    Boolean is_formula = 
+      (IS_FORMULA(s) ||
+       (may_have_select_expr && inout->sel[j] && inout->sel[j]->formula));
+    if (is_formula) continue; /* skip formulas */
+    more_than_one |= (refcount[j] > 1);
+  }
+
+  if (more_than_one) {
+    on_error++;
+
+    for (j=0; j<nsym; j++) {
+      if (refcount[j] > 1) {
+	char *s = sym[j]->name;
+	fprintf(stderr,"Ambiguous %s-symbol '%s' encountered in view '%s'. ",
+		label, s, vname);
+	fprintf(stderr,"Related to more than one FROM-table.\n");
+      }
+    } /* for (j=0; j<nsym; j++) */
+  }
+
+  /* Check if any "refcount[]" equal to zero.
+     That may be mean that one of LINKOFFSET or LINKLEN 
+     or even both is present.
+     Alternatively it means that a symbol is not present 
+     in any given table, which is an error (except of course
+     when a $-symbol is in concern in the WHERE-part) */
+
+  less_than_one = 0;
+  for (j=0; j<nsym; j++) {
+    char *s = sym[j]->name;
+    Boolean is_formula = 
+      (IS_FORMULA(s) ||
+       (may_have_select_expr && inout->sel[j] && inout->sel[j]->formula));
+    if (is_formula) continue; /* skip formulas */
+    if (allow_dollar && IS_DOLLAR(s)) continue; /* Disregard, if dollar */
+    less_than_one |= (refcount[j] < 1);
+  }
+
+  /* Check if any links are present in the given tables */
+      
+  if (!on_error) {
+    if (less_than_one) {
+      int links_present = 0;
+
+      for (i=0; i<ntable; i++) {
+	ODB_Table *t = table[i];
+	/* Ignore searches from automatically inserted tables, since they
+	   were not considered by the user in the first place */
+	if ((from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) continue;
+	links_present |= (t->nlink > 0);
+	if (links_present) break;
+      }
+
+      if (!links_present) {
+	/* No reason to search for LINKLEN or so */
+	int add = 0;
+	/* Display message(s) */
+	for (j=0; j<nsym; j++) {
+	  char *s = sym[j]->name;
+	  Boolean is_formula = 
+	    (IS_FORMULA(s) ||
+	     (may_have_select_expr && inout->sel[j] && inout->sel[j]->formula));
+	  if (is_formula) continue; /* skip formulas */
+	  if (allow_dollar && IS_DOLLAR(s)) continue; /* Disregard, if dollar */
+	  if (refcount[j] < 1) {
+	    int an_error = 0;
+	    SETMSG3("Table reference count < 1 for column#%d in %s : '%s'",j+1,label,s);
+	    if (bailout_level == 0 || 
+		( (bailout_level & bailout_key) != bailout_key) ||
+		STRLEN(bailout_string) == 0) {
+	      an_error++;
+	      add++;
+	    }
+	    else {
+	      /* Make it a (simple) formula according to BAILOUT_STRING;
+		 We support (a) A number, like "0" for zero
+		            (b) A dollar variable, like "$mdi" */
+	      ODB_Tree *expr = NULL;
+	      s = bailout_string;
+	      while (isspace(*s)) s++;
+	      if (ODB_is_integer(s)) {
+		int numba = atoi(s);
+		expr = ODBOPER1(ODB_NUMBER,&numba);
+	      }
+	      else if (ODB_is_dollar(s)) {
+		if (allow_dollar && bailout_key == ODB_BAILOUT_WHERE) {
+		  ODB_Symbol *psym = ODB_new_symbol(ODB_USDNAME, s);
+		  sym[j] = psym;
+		  redo++;
+		  continue;
+		}
+		else {
+		  expr = ODBOPER1(ODB_USDNAME,s);
+		}
+	      }
+	      if (expr) {
+		char *first_char = STRDUP(FORMULA_CHAR); /* first_char free'd inside the dump_s */
+		char *formula = dump_s(first_char,expr,ddl_piped ? 2 : 0,NULL);
+		ODB_Symbol *psym = ODB_new_symbol(ODB_NAME, formula);
+		sym[j] = psym;
+		if (may_have_select_expr) {
+		  int nsym;
+		  char *f1 = dump_s(NULL,expr,3,NULL);
+		  ODB_Symbol *nick = ODB_new_symbol(ODB_NICKNAME, f1);
+		  inout->sel[j]->nicksym = nick;
+		  inout->sel[j]->expr = expr;
+		  inout->sel[j]->aggr_flag = ODB_AGGR_NONE;
+		  inout->sel[j]->formula = formula;
+		  inout->sel[j]->formula_out = NULL;
+		  inout->sel[j]->ncols_aux = 0;
+		  inout->sel[j]->nsym = nsym = ODB_trace_symbols(expr,NULL,1);
+		  if (nsym > 0) {
+		    ALLOC(inout->sel[j]->sym, nsym);
+		    for (j=nsym-1; j>=0; j--) {
+		      char *s = ODB_popstr();
+		      /* The following symbol may still have "@"'s or "."'s [if ODB_NAME] */
+		      int what = IS_HASH(s) ? ODB_HASHNAME : (IS_DOLLAR(s) ? ODB_USDNAME : ODB_NAME);
+		      inout->sel[j]->sym[j] = ODB_new_symbol(what, s);
+		    }
+		  }
+		  else { /* No symbols; just scalars (or functions) etc. */
+		    inout->sel[j]->nsym = 0;
+		    inout->sel[j]->sym = NULL;
+		  }
+		  if (inout->readonly) inout->readonly[j] = 1; /* Always unconditionally R/O */
+		  redo++;
+		}
+	      }
+	      else { /* An error after all ;-( */
+		an_error++;
+		add++;
+	      }
+	    }
+	    YYwarn(an_error,msg);
+	  } /* if (refcount[j] < 1) */
+	} /* for (j=0; j<nsym; j++) */
+	if (add) on_error++; /* Truly an error i.e. no bail outs possible */
+      } /* if (!links_present) */
+    } /* if (less_than_one) */
+  }
+
+  if (!on_error && redo) goto re_do;
+
+  /* Search tables for a matching LINKOFFSET/LINKLEN or name.offset/name.len 
+     Expand partial names */
+
+  if (!on_error) {
+    int count = 0;
+
+    for (j=0; j<nsym; j++) {
+      Boolean is_readonly = (has_symbol_param && inout->readonly[j]);
+      char *s = sym[j]->name;
+      char *pvar = NULL;
+      char *pmember = NULL;
+      char *ptable = NULL;
+      char *poffset = NULL;
+      Boolean is_hash = IS_HASH(s);
+      Boolean is_formula = 
+	(IS_FORMULA(s) ||
+	 (may_have_select_expr && inout->sel[j] && inout->sel[j]->formula));
+      ODB_SelectExpr *sel = may_have_select_expr ? inout->sel[j] : NULL;
+
+#if 0
+      fprintf(stderr,"ODB_resolve_relations(B): name[%d]='%s'\n",j,s);
+#endif
+
+      ODB_pushi(has_sign ? sign[j] : zero);
+
+      if (is_formula) {
+	ODB_pushi(linkmode[j]);
+	ODB_pushstr(s);
+	ODB_pushi(ReadOnly);
+	ODB_pushSELECTEXPR(sel);
+	count++;
+	continue; /* next j */
+      }
+
+      if (refcount[j] == 1 || 
+	  (allow_dollar && IS_DOLLAR(s))) {
+	char *st = s;
+	ODB_pushi(linkmode[j]);
+
+	if (!(allow_dollar && IS_DOLLAR(s))) {
+	  if (is_hash) {
+	    pvar = STRDUP(s);
+	    ptable = STRDUP(s+1);
+	  }
+	  else {
+	    (void) ODB_split(s, NULL, &pvar, &pmember, &ptable, &poffset);
+	  }
+	  if (!ptable) {
+	    char *xtable = NULL;
+	    for (i=0; i<ntable; i++) {
+	      ODB_Table *t = table[i];
+	      char *tname = t->table->name;
+	      Boolean found = 0;
+	      /* Ignore searches from automatically inserted tables, since they
+		 were not considered by the user in the first place */
+	      if ((from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) continue;
+	      found = ODB_in_table(ODB_NAME, pvar, t, NULL);
+	      if (found) { /* The only occurence, since refcount[j] == 1 is checked */
+		int len = strlen(pvar) + STRLEN(pmember) + strlen(tname) + 10;
+		len += STRLEN(poffset);
+		ALLOC(st, len);
+		if (poffset && !strequ(poffset,"0")) {
+		  int sign = GetSign(poffset);
+		  sprintf(st, "%s%s%s@%s%s%s%s", 
+			  pvar, 
+			  pmember ? "." : "", 
+			  pmember ? pmember : "",
+			  tname,
+			  ODB_OFFSET_CHAR, 
+			  (sign < 0) ? "_" : "",
+			  poffset+ABS(sign)
+			  );
+		}
+		else {
+		  sprintf(st, "%s%s%s@%s", 
+			  pvar, 
+			  pmember ? "." : "", 
+			  pmember ? pmember : "",
+			  tname);
+		}
+		break;
+	      }
+	    } /* for (i=0; i<ntable; i++) */
+	    FREE(xtable);
+	  }
+	  FREE(pvar);
+	  FREE(pmember);
+	  FREE(ptable);
+	  FREE(poffset);
+	}
+
+	ODB_pushstr(st);
+	ODB_pushi(is_readonly ? ReadOnly : zero);
+	ODB_pushSELECTEXPR(sel);
+	count++;
+	continue; /* next j */
+      }
+
+      if (is_hash) {
+	pvar = STRDUP(s);
+	ptable = STRDUP(s+1);
+      }
+      else {
+	(void) ODB_split(s, NULL, &pvar, &pmember, &ptable, &poffset);
+      }
+      
+      if (!ptable) {
+	char *xtable = NULL;
+	char *xpvar = NULL;
+
+	ALLOC(xpvar, strlen(pvar) + 20);
+	sprintf(xpvar,"LINKOFFSET(%s)",pvar);
+
+	refcount[j] = 0;
+
+	for (i=0; i<ntable; i++) {
+	  ODB_Table *t = table[i];
+	  char *tname = t->table->name;
+	  Boolean found = 0;
+	  /* Ignore searches from automatically inserted tables, since they
+	     were not considered by the user in the first place */
+	  if ((from_attr[i] & ODB_FROM_ATTR_INSERT) == ODB_FROM_ATTR_INSERT) continue;
+	  found = ODB_in_table(ODB_NAME, xpvar, t, NULL);
+	  if (found && ptable) found = strequ(tname, ptable);
+	  if (found) refcount[j]++;
+	  if (found && !xtable && refcount[j] == 1) xtable = STRDUP(tname);
+	} /* for (i=0; i<ntable; i++) */
+
+	if (refcount[j] == 1) {
+	  /* Bingo ! */
+	  char *soffset = NULL;
+	  char *slen = NULL;
+	  char *zz = GreenDay(poffset);
+
+	  ODB_pushi(linkmode_1);
+	  if (xtable) {
+	    int len = strlen(xpvar) + strlen(xtable) + STRLEN(zz) + 10;
+	    ALLOC(soffset, len);
+	    snprintf(soffset, len, "%s@%s%s", xpvar,xtable,zz);
+	  }
+	  else {
+	    soffset = STRDUP(xpvar);
+	  }
+	  ODB_pushstr(soffset);
+	  ODB_pushi(is_readonly ? ReadOnly : zero);
+	  ODB_pushSELECTEXPR(sel);
+
+	  if (xtable) {
+	    int len = strlen(pvar) + strlen(xtable) + STRLEN(zz) + 20;
+	    ALLOC(slen, len);
+	    snprintf(slen,len,"LINKLEN(%s)@%s%s",pvar,xtable,zz);
+	  }
+	  else {
+	    int len = strlen(pvar) + STRLEN(zz) + 20;
+	    ALLOC(slen, len);
+	    snprintf(slen,len,"LINKLEN(%s)%ss",pvar,zz);
+	  }
+
+	  FREE(zz);
+
+	  ODB_pushi(has_sign ? sign[j] : zero);
+	  ODB_pushi(linkmode_2);
+	  ODB_pushstr(slen);
+	  ODB_pushi(is_readonly ? ReadOnly : zero);
+	  ODB_pushSELECTEXPR(sel); /* This is a bit wrong, since linkoffset already got this "sel" */
+
+	  count += 2;
+	}
+	else {
+	  /* No luck */	
+	  SETMSG2("Variable '%s' is not uniquely found from any FROM-tables; view '%s'",
+		  s, vname);
+	  on_error++;
+	  YYwarn(on_error, msg);
+	}
+
+	FREE(xpvar);
+	FREE(xtable);
+      }
+      else {
+	SETMSG3("Error in variable '%s', view '%s'. No such table '%s' in FROM-list",
+		s, vname, ptable);
+	on_error++;
+	YYwarn(on_error, msg);
+      }
+      
+      FREE(pvar);
+      FREE(pmember);
+      FREE(ptable);
+      FREE(poffset);
+    } /* for (j=0; j<nsym; j++) */
+
+    if (!on_error) {
+      SymbolParam_t *out = NULL;
+      ALLOC(newsym, count);
+      if (has_sign) ALLOC(*sign_out, count);
+      if (has_symbol_param) {
+	CALLOC(out, 1);
+	out->nsym = count;
+	CALLOC(out->sym, count);
+	CALLOC(out->readonly, count);
+	CALLOC(out->sel, count);
+      }
+
+      *nsym_out = count;
+
+      for (j=count-1; j>=0; j--) {
+	ODB_SelectExpr *sel = ODB_popSELECTEXPR();
+	int dummy = ODB_popi(); /* this is the readonly guy if applicable */
+	char *s = ODB_popstr();
+	Boolean is_hash = IS_HASH(s);
+	int  lnmode = ODB_popi();
+	int  key = ODB_popi();
+
+	if (has_sign) (*sign_out)[j] = key;
+
+	if (lnmode == 0) {
+	  newsym[j] = ODB_new_symbol(is_hash ? ODB_HASHNAME : ODB_NAME, s);
+	}
+	else if (lnmode == 1) {
+	  char *tname = strrchr(s,'@');
+	  char *x = ODB_extract(s,'(',')');
+	  char *y = strchr(x,'.');
+	  if (y) *y = '\0';
+	  if (!tname) tname = "";
+	  ALLOC(y, strlen(x) + strlen(tname) + 20);
+	  sprintf(y,"LINKOFFSET(%s)%s",x,tname);
+	  newsym[j] = ODB_new_symbol(ODB_NAME, y);
+	  FREE(x);
+	}
+	else if (lnmode == 2) {
+	  char *tname = strrchr(s,'@');
+	  char *x = ODB_extract(s,'(',')');
+	  char *y = strchr(x,'.');
+	  if (y) *y = '\0';
+	  if (!tname) tname = "";
+	  ALLOC(y, strlen(x) + strlen(tname) + 20);
+	  sprintf(y,"LINKLEN(%s)%s",x,tname);
+	  newsym[j] = ODB_new_symbol(ODB_NAME, y);
+	  FREE(x);
+	}
+	if (has_symbol_param) {
+	  out->sym[j] = newsym[j];
+	  out->readonly[j] = dummy;
+	  out->sel[j] = sel;
+	}
+      } /* for (j=count-1; j>=0; j--) */
+
+      if (has_symbol_param) {
+	int jj;
+	/* fprintf(stderr,"<before> inout->nsym = %d\n",inout->nsym); 
+	for (jj=0; jj<inout->nsym; jj++) {
+	  fprintf(stderr,"@%d: '%s', readonly=%d\n",
+		  jj,inout->sym[jj]->name,inout->readonly[jj]);
+	}
+	*/
+	inout->nsym = out->nsym;
+	inout->sym = out->sym;
+	inout->readonly = out->readonly;
+	inout->sel = out->sel;
+	/*
+	fprintf(stderr,"<afterr> inout->nsym = %d\n",inout->nsym);
+	for (jj=0; jj<inout->nsym; jj++) {
+	  fprintf(stderr,"@%d: '%s', readonly=%d\n",
+		  jj,inout->sym[jj]->name,inout->readonly[jj]);
+	}
+	*/
+      }
+    } /* if (!on_error) */
+  }
+  
+  /* Errors ? */
+
+  if (on_error) {
+    SETMSG3("Error in building table-to-%s-symbol relations in view '%s' (err. count = %d)",
+	    label, vname, on_error);
+    YYerror(msg);
+  }
+
+  /*
+  if (newsym) {
+    int count = *nsym_out;
+    for (j=0; j<count; j++) {
+      fprintf(stderr,"resolve(%s, %s): %d : symref=%s\n",
+	      vname,label,j,symref(newsym[j]));
+    }
+  }
+  */
+
+  FREE(refcount);
+  FREE(linkmode);
+
+  return newsym;
+}
+
+
+Boolean
+ODB_matchup_sym(Boolean report_error,
+		const char *target_label,
+		ODB_Symbol **target,
+		int ntarget,
+		const char *with_label,
+		ODB_Symbol **with,
+		int nwith,
+		int *key)
+{
+  int i, j, errcnt = 0;
+  Boolean has_key = (key != NULL);
+
+  for (j=0; j<ntarget; j++) {
+    char *st = target[j]->name;
+    Boolean found = 0;
+
+    for (i=0; i<nwith; i++) {
+      char *sw = with[i]->name;
+      if (strequ(st,sw)) {
+	found = 1;
+	/* if (has_key) key[j] = key[j] * (i + 1); */
+	if (has_key) {
+	  int maxcols = ODB_maxcols();
+	  if (ABS(key[j]) != maxcols) {
+	    key[j] = key[j] * (i + 1);
+	  }
+	  else if (key[j] ==  maxcols) { /* ABS-sorting, ascending */
+	    key[j] =  maxcols + i + 1;
+	  }
+	  else if (key[j] == -maxcols) { /* ABS-sorting, descending */
+	    key[j] = -(maxcols + i + 1);
+	  }
+	}
+	break;
+      }
+    } /* for (i=0; i<nwith; i++) */
+
+    if (!found) {
+      if (report_error) {
+	fprintf(stderr,
+		"%s-variable '%s' is not specified in the %s-list\n",
+		target_label, st, with_label);
+      }
+      if (has_key) key[j] = 0;
+      errcnt++;
+    }
+  } /* for (j=0; j<ntarget; j++) */
+
+  if (report_error && errcnt > 0) {
+    fprintf(stderr,"%s-variables:\n",target_label);
+    for (j=0; j<ntarget; j++) {
+      char *st = target[j]->name;
+      fprintf(stderr,"\t%d:\t%s\n",j,st);
+    }
+    fprintf(stderr,"%s-variables:\n",with_label);
+    for (i=0; i<nwith; i++) {
+      char *sw = with[i]->name;
+      fprintf(stderr,"\t%d:\t%s\n",i,sw);
+    }
+  } /* if (report_error && errcnt > 0) */
+
+  return (errcnt > 0);
+}
+
+
+int
+ODB_wildcard(const char *s,
+	     ODB_Table **from,
+	     const int *from_attr,
+	     int nfrom)
+{
+  int j, count = 0;
+  Boolean found;
+  int table_idx = -1;
+  int name_idx = -1;
+  char *pvar = NULL;
+  char *pmember = NULL;
+  char *ptable = NULL;
+
+  (void) ODB_split(s, NULL, &pvar, &pmember, &ptable, NULL);
+
+  if (!ptable) {
+    SETMSG1("Table not speficied in SELECT-wildcard definition '%s'",s);
+    YYerror(msg);
+  }
+  else {
+    /* Cross-check that the ptable is a valid one */
+    found = 0;
+    for (j=0; j<nfrom; j++) {
+      found = strequ(ptable,from[j]->table->name);
+      if (found) {
+	table_idx = j;
+	break;
+      }
+    }
+    if (!found) {
+      SETMSG2("Invalid table name '%s' in SELECT-wildcard definition '%s'",
+	      ptable,s);
+      YYerror(msg);
+    }
+  }
+
+  if (!pvar) {
+    SETMSG1("Variable name not speficied in SELECT-wildcard definition '%s'",s);
+    YYerror(msg);
+  }
+  
+  if (!pmember) {
+    /* A Bitfield member is NOT to be scanned */
+    if (!strequ(pvar,"*")) {
+      SETMSG1("Invalid SELECT-wildcard definition '%s'. Use '*@table'",s);
+      YYerror(msg);
+    }
+    /* All okay */
+    count = from[table_idx]->nsym;
+    for (j=0; j<count; j++) {
+      char *p = from[table_idx]->sym[j]->name;
+      char *c;
+      ALLOC(c, strlen(p) + 1 + strlen(ptable) + 1);
+      sprintf(c,"%s@%s",p,ptable);
+      ODB_pushstr(c);
+    }
+  }
+  else {
+    /* Bitfield members are to be scanned */
+    if (!strequ(pmember,"*")) {
+      SETMSG1("Invalid SELECT-wildcard definition '%s'. Use 'name.*@table'",s);
+      YYerror(msg);
+    }
+    /* Cross-check that the pvar exists in the ptable i.e. from[table_idx] */
+    found = 0;
+    for (j=0; j<from[table_idx]->nsym; j++) {
+      found = strequ(pvar, from[table_idx]->sym[j]->name);
+      if (found) {
+	name_idx = j;
+	break;
+      }
+    }
+    if (!found) {
+      SETMSG3("Error in SELECT-wildcard '%s': Variable '%s' is not present in table '%s'",
+	      s, pvar, ptable);
+      YYerror(msg);
+    }
+    /* Make sure it is a Bitfield */
+    if (!from[table_idx]->type[name_idx]->bitstream) {
+      SETMSG2("Error in SELECT-wildcard '%s': Variable '%s' is not a bitfield",s,pvar);
+      YYerror(msg);
+    }
+    /* All okay */
+    count = from[table_idx]->type[name_idx]->nsym;
+    for (j=0; j<count; j++) {
+      char *p = from[table_idx]->type[name_idx]->member[j]->name;
+      char *c;
+      ALLOC(c, strlen(pvar) + 1 + strlen(p) + 1 + strlen(ptable) + 1);
+      sprintf(c,"%s.%s@%s",pvar,p,ptable);
+      ODB_pushstr(c);
+    }
+  }
+  
+
+  FREE(pvar);
+  FREE(pmember);
+  FREE(ptable);
+
+  return count;
+}
+
+
+PUBLIC Boolean
+ODB_is_integer(const char *s)
+{
+  Boolean is_integer = 0;
+  if (s && (isdigit(*s) || (*s == '+') || (*s == '-'))) {
+    double d = atof(s);
+    double flr = floor(d);
+    is_integer = (d == flr && flr >= -INT_MAX && flr <= INT_MAX);
+  }
+  /*
+  fprintf(stderr,
+	  "ODB_is_integer('%s'): is_integer = %d\n",
+	  s ? s : NIL,(int)is_integer);
+  */
+  return is_integer;
+}
+
+
+PUBLIC Boolean
+ODB_is_dollar(const char *s)
+{
+  Boolean is_dollar = 0;
+  if (IS_DOLLAR(s)) {
+    int ok = 1;
+    while (*++s && ok) {
+      char c = *s;
+      if (isalnum(c) || c == '_') continue; /* still ok */
+      ok = 0;
+      break;
+    }
+    is_dollar = ok ? 1 : 0;
+  }
+  return is_dollar;
+}
+
+
+
+PRIVATE void
+Form_AND_expr(ODB_View *pview, ODB_Tree *pcond)
+{
+  if (pcond) {
+    int what = pcond->what;
+    if (what == ODB_AND) {
+      ODB_Tree *left = pcond->argv[0];
+      ODB_Tree *right = pcond->argv[1];
+
+      if (left && left->what != ODB_AND) {
+	ODB_pushexpr(left);
+	pview->andlen++;
+      } 
+      else {
+	Form_AND_expr(pview, left);
+      }
+
+      if (right && right->what != ODB_AND) {
+	ODB_pushexpr(right);
+	pview->andlen++;
+      }
+      else {
+	Form_AND_expr(pview, right);
+      }
+    } /* if (what == ODB_AND) */
+  }
+}
+
+
+PUBLIC void
+ODB_setup_where(ODB_View *pview)
+{
+  int j, nfrom;
+  ODB_Tracesym t;
+  
+  t.flag = 0;
+  t.next = pview->nselect_all;
+  t.maxfrom = 0;
+  t.table_index = pview->table_index;
+  t.where = pview->def_put;
+  t.tag = pview->tag;
+  t.has_maxcount = 0;
+  t.has_Unique = 0;
+  t.has_thin = 0;
+  
+  (void) ODB_trace_symbols(pview->cond, &t, 0);
+  
+  nfrom =  pview->nfrom;
+
+  /* Check if the special maxcount() function was referred to */
+  if (t.has_maxcount) t.maxfrom = nfrom - 1;
+  pview->maxfrom = t.maxfrom;
+
+  /* Check if thin-function was referred to */
+  pview->has_thin = t.has_thin;
+  
+  /* fprintf(stderr,"ODB_VIEW(%s): maxfrom = %d\n",name,maxfrom); */
+  
+  /* Check "string"'s */
+  
+  t.flag = 1;
+  t.next = pview->nselect_all;
+  t.maxfrom = 0;
+  t.table_index = pview->table_index;
+  t.where = pview->def_put;
+  t.tag = pview->tag;
+  t.has_maxcount = 0;
+  t.has_Unique = 0;
+  t.has_thin = 0;
+  
+  (void) ODB_trace_symbols(pview->cond, &t, 0);
+
+  /* Active TABLEs */
+
+  CALLOC(pview->active, nfrom);
+  for (j=0; j<pview->nselect; j++) {
+    int tidx = pview->table_index[j];
+    if (tidx >= 0 && tidx < nfrom) pview->active[tidx] |= 0x1;
+  }
+
+  if (pview->nselsym > 0) { /* Right place ? */
+    int nselect_all = pview->nselect_all;
+    int nwhere = pview->nwhere;
+    int norderby = pview->norderby;
+    int nselsym = pview->nselsym;
+    for (j=nselect_all+nwhere+norderby; j<nselect_all+nwhere+norderby+nselsym; j++) {
+      int tidx = pview->table_index[j];
+      if (tidx >= 0 && tidx < nfrom) pview->active[tidx] |= 0x1;
+    }
+  }
+
+  /* Prepare for merged table indices */
+
+  CALLOC(pview->merged_with, nfrom);
+  for (j=0; j<pview->nselect; j++) {
+    int tidx = pview->table_index[j];
+    if (tidx >= 0 && tidx < nfrom) pview->merged_with[tidx] = NULL;
+  } /* for (j=0; j<pview->nselect; j++) */
+
+  /* Form the AND-expression list */
+
+  pview->andlen = 0;
+  FREE(pview->andlist);
+
+  if (pview->cond) {
+    Boolean *has_Unique;
+
+    Form_AND_expr(pview, pview->cond);
+    
+    if (pview->andlen == 0) {
+      ODB_pushexpr(pview->cond);
+      pview->andlen = 1;
+    }
+    
+    ALLOC(pview->andlist, pview->andlen);
+    ALLOC(has_Unique, pview->andlen);
+    
+    for (j=pview->andlen-1; j>=0; j--) {
+      ODB_Tree *expr = ODB_popexpr();
+      pview->andlist[j].expr = expr;
+      t.flag = 2;
+      t.next = 0;
+      t.maxfrom = 0;
+      t.table_index = NULL;
+      t.where = NULL;
+      t.tag = NULL;
+      t.has_maxcount = 0;
+      t.has_Unique = 0;
+      t.has_thin = 0;
+      
+      (void) ODB_trace_symbols(expr, &t, 0);
+      
+      if (t.has_maxcount) t.maxfrom = nfrom - 1;
+      has_Unique[j] = t.has_Unique;
+      
+      pview->andlist[j].maxfrom = t.maxfrom;
+    }
+
+    /* Unhoist the Unique() AND-expr to the most inner loop (i.e. pview->maxfrom) */
+    for (j=0; j<pview->andlen; j++) {
+      if (has_Unique[j]) pview->andlist[j].maxfrom = pview->maxfrom;
+    }
+
+    FREE(has_Unique);
+
+#if 0
+    fprintf(stderr,"*** DEBUG print from ODB_setup_where ***\n");
+    fprintf(stderr,"View='%s' : No. of AND-expressions = %d\n",
+	    pview->view->name,pview->andlen);
+    for (j=0; j<pview->andlen; j++) {
+      ODB_Tree *expr = pview->andlist[j].expr;
+      fprintf(stderr,"\t(%d) : addr=%p : maxfrom = %d (nfrom-1=%d, Views maxfrom=%d)\n",
+	      j,
+	      expr, pview->andlist[j].maxfrom,
+	      nfrom - 1, pview->maxfrom);
+      dump_c(stderr, 0, expr);
+      fprintf(stderr,"\n");
+    }
+    fprintf(stderr,"*** End of DEBUG print ***\n");
+#endif
+  }
+}
+
+
+PUBLIC Boolean
+ODB_fixconv(ODB_Tree *pnode)
+{
+  Boolean fixed = 0;
+  extern int LEX_convflag;
+  extern double LEX_unconv_value;
+  if (LEX_convflag) {
+    if (pnode->what == ODB_NUMBER) {
+      double dval = pnode->dval;
+      switch (LEX_convflag) {
+      case 1: /* Celsius */
+	dval = c2k(-LEX_unconv_value);
+	fixed = 1;
+	break;
+      case 2: /* Fahrenheit */
+	dval = f2k(-LEX_unconv_value);
+	fixed = 1;
+	break;
+      }
+      pnode->dval = dval;
+    }
+    LEX_convflag = 0;
+    LEX_unconv_value = 0;
+  }
+  else if (pnode->what == ODB_NUMBER) {
+    pnode->dval = -pnode->dval; /* Unary minus */
+    fixed = 1;
+  }
+  return fixed;
+}
diff --git a/odb/src/compiler/yacc.y b/odb/src/compiler/yacc.y
new file mode 100644
index 0000000..8a65de1
--- /dev/null
+++ b/odb/src/compiler/yacc.y
@@ -0,0 +1,3302 @@
+%{
+#define THIS_IS_YACC_FILE
+#include "defs.h"
+#include "pcma_extern.h"
+
+#undef yywrap
+
+#define ODBURO_EMPTY 0x1
+#define ODBREADONLY  0x2
+#define ODBUPDATED   0x4
+#define ODBAS        0x8
+
+#define ODB_LAT "lat at hdr"
+#define ODB_LON "lon at hdr"
+
+extern int yywrap();
+extern void LEX_prev_state();
+extern Boolean verbose;
+extern int use_indices;
+extern int reorder_tables;
+extern int insert_tables;
+extern int safeGuard;
+extern FILE *LEX_open_include(const char *filename);
+extern int ODB_maxcols();
+
+extern Boolean readonly_mode;
+extern Boolean has_count_star;
+extern Boolean has_usddothash;
+extern Boolean no_from_stmt;
+extern int ddl_piped;
+extern int LEX_convflag;
+extern double LEX_unconv_value;
+extern int LEX_create_index;
+extern int bailout_level;
+extern char *bailout_string;
+
+PRIVATE const char YACC_any_index[] = "*";
+PUBLIC char *use_index_name = NULL;
+
+PRIVATE Boolean YACC_select_distinct = 0;
+
+PRIVATE int tmp_view_num = 0;
+
+PRIVATE const int YACC_MinusOne = -1;
+PRIVATE const int YACC_PlusOne  =  1;
+PRIVATE double YACC_IncOne = 1;
+PRIVATE	double YACC_TruE = 1;
+PRIVATE int YACC_distinct = 1;
+
+PUBLIC ODB_Tree *YACC_dummy_cond = NULL;
+
+PUBLIC char *YACC_current_dbname = NULL;
+PUBLIC char *YACC_current_srcpath = NULL;
+PUBLIC char *YACC_current_datapath = NULL;
+PUBLIC char *YACC_current_idxpath = NULL;
+PUBLIC char *YACC_current_poolmask = NULL;
+
+PRIVATE char *YACC_join(unsigned int code, const char *s2)
+{
+  int len = STRLEN(s2) + 20;
+  char *s = NULL;
+  ALLOC(s, len);
+  snprintf(s,len,"%u%s",code,s2);
+  return s;
+}
+
+PRIVATE char *YACC_join_by_expr(const char *s, int odb_name,
+	const ODB_Tree *exprlat, const ODB_Tree *exprlon)
+{
+  unsigned int code = 0;
+  unsigned int j;
+  for (j=1; j<=2; j++) {
+    const ODB_Tree *expr = (j==1) ? exprlat : exprlon;
+    if (expr) {
+      const char *compare_with = (j==1) ? ODB_LAT : ODB_LON;
+      int what = expr->what;
+      if (what == odb_name) {
+        ODB_Symbol *psym = expr->argv[0];
+	char *name = psym->name;
+	if (strequ(name, compare_with)) code |= j;
+      }
+    }
+  } /* for (j=1; j<=2; j++) */
+  /* The rational behind the "code"
+     When a bit (1st or 2nd or both) are set, then 1st argument or 2nd argument or 
+     both, respectively, will be subject to ODB_lldegrees() in ODB_inside/inpolygon/near functions.
+
+     This complicated matter is needed to avoid applying ODB_lldegrees() twice per argument:
+     once when entering, and once when in ODB_inside/inpolygon/near functions.
+
+     After this for example the following works ok and should give the same results:
+     WHERE inside("finland")
+     WHERE inside("finland",lat,lon)
+     WHERE inside("finland",degrees(lat),degrees(lon))
+     WHERE inside("finland",degrees(lat),lon)
+     WHERE inside("finland",lat,degrees(lon))
+
+     The code (values 0,1,2 or 3) will be prepended in front of supplied string argument
+     and stripped away in ODB_inside/inpolygon/near functions to extract the code.
+   */
+  return YACC_join(code, s);
+}
+
+/* We do not accept the following table names */
+
+#define N_INVTABNAM  12
+
+PRIVATE const char *invalid_table_names[N_INVTABNAM] = {
+	"core", /* Unix core-file */
+	        /* The following are specific to Windows/CYGWIN-based databases 
+		   See more : http://support.microsoft.com/?id=74496 */
+	"con",  /* Keyboard and display */
+	"prn",  /* System list device, usually a parallel port */
+	"aux",  /* Auxiliary device, usually a serial port */
+	"nul",  /* Bit-bucket device */
+	"com1", /* First serial communications port */
+	"com2", /* Second serial communications port */
+	"com3", /* Third serial communications port */
+	"com4", /* Fourth serial communications port */
+	"lpt1", /* First parallel printer port */
+	"lpt2", /* Second parallel printer port */
+	"lpt3"  /* Third parallel printer port */
+};
+
+#define DEF_USDHASH(s, a_value) \
+ pname = s; \
+ value = a_value; \
+ { \
+   ODB_Tree *expr = ODBOPER1(ODB_NUMBER,&value); \
+   ODB_Tree *p; \
+   name = ODB_new_symbol(ODB_USDNAME,pname); \
+   p = ODBOPER2(ODB_SET, name, expr); \
+   (void) ODB_new_cmd(p); \
+ }
+
+#define DEF_USDDOTHASH(parent_tblname, child_tblname) \
+ { \
+   /* Create r/o variable "$<parent_tblname>.<child_tblname>#" to \
+      denote dynamic length between two tables during SQL-query. \
+      After this you can do the following: \
+      SELECT lat,lon,$hdr.body# AS "body.len",press,obsvalue \
+      FROM hdr,body WHERE press < 100; */ \
+   ODB_Symbol *name; \
+   char *pname; \
+   int len = STRLEN(parent_tblname) + STRLEN(child_tblname) + 4; \
+   ALLOC(pname, len); \
+   snprintf(pname, len, "$%s.%s#", parent_tblname, child_tblname); \
+   name = ODB_new_symbol(ODB_USDNAME,pname); \
+   FREE(pname); \
+   { \
+     double value = 0; \
+     ODB_Tree *expr = ODBOPER1(ODB_NUMBER,&value); \
+     ODB_Tree *ptree = ODBOPER2(ODB_SET, name, expr); \
+     (void) ODB_new_cmd(ptree); \
+   } \
+ }
+
+%}
+
+%union {
+  double         dval;
+  int            numargs;
+  int	         id;
+  int	         sign;
+  char	         onechar;
+  char          *str;
+  ODB_Symbol    *sym;
+  ODB_Type      *type;
+  Tabledef_t    *table;
+  Viewdef_t     *view;
+  Selectdef_t   *select;
+  ODB_Tree      *node;
+  ODB_Cmd       *cmd;
+  ODB_Arridx    *arridx;
+  ODB_SelAttr_t *attr;
+  ODB_Match_t   *match;
+};
+
+%token <dval> ODB_NUMBER
+%token <str>  ODB_NAME ODB_USDNAME ODB_HASHNAME ODB_BSNUM
+%token <str>  ODB_STRING ODB_WC_STRING ODB_FILE ODB_EQNE_STRING
+%token <id>   ODB_INSIDE ODB_OUTSIDE
+%token <id>   ODB_INSIDE_POLYGON ODB_OUTSIDE_POLYGON
+
+%type  <cmd>     stmt stmtlist
+%type  <node>    expr cond pred where selexpr num_expr selpred formula query
+%type  <node>    opt_inc opt_selinc strcmpre inside selinside near selnear strfunc1
+%type  <node>	 other_siders other_near
+%type  <numargs> as star arrname
+%type  <numargs> decllist fromlist uniqlist sortlist arglist alignlist selarglist num_arglist
+%type  <numargs> decl from uniqueby orderby arrsort opt_arglist
+%type  <numargs> exprlist
+%type  <numargs> opt_ontable ontable indexcols indexlist indexname
+%type  <match>   matchfunc
+%type  <str>     name USDname extUSDname HASHname BSnum type string opt_table_name 
+%type  <str>     filename opt_idxname idxname dbcred
+%type  <id>	 opt_sel_param is_null_or_is_not_null opt_as_nickname in_notin opt_using
+%type  <id>	 eqne like_notlike infile_notinfile
+%type  <id>      insiders outsiders
+%type  <attr>    select2
+%type  <type>    typedef
+%type  <table>   tabledef
+%type  <view>    viewdef indexdef dropindex
+%type  <dval>    number const_expr
+%type  <arridx>  arrindex
+%type  <onechar> align
+%type  <select>  select sellist selname
+%type  <sign>    opt_ascdesc ascdesc
+
+%token ODB_FUNC ODB_FUNCAGGR ODB_STRFUNC ODB_NEAR
+%token ODB_STRFUNC1 ODB_QUERY
+%token ODB_INCLUDE
+%token ODB_SET
+%token ODB_TYPE
+%token ODB_TABLE
+%token ODB_VIEW ODB_SELECT ODB_FROM ODB_WHERE ODB_UNIQUEBY ODB_ORDERBY
+%token ODB_CREATEINDEX ODB_ON ODB_DROPINDEX
+%token ODB_SEMICOLON ODB_COMMA
+%token ODB_LP ODB_RP
+%token ODB_LB ODB_RB
+%token ODB_EXIT ODB_BETWEEN
+%token ODB_WHERE_SYMBOL
+%token ODB_ASC ODB_DESC ODB_ABS
+%token ODB_ALIGN ODB_ONELOOPER ODB_SHAREDLINK ODB_RESET
+%token ODB_LIKE ODB_NOTLIKE
+%token ODB_IS ODB_NULL
+%token ODB_SELECT_DISTINCT ODB_SELECT_ALL
+%token ODB_AS ODB_READONLY ODB_UPDATED
+%token ODB_REORDER ODB_NOREORDER
+%token ODB_INDEX ODB_NOINDEX
+%token ODB_SAFEGUARD ODB_NOSAFEGUARD
+%token ODB_INSERT ODB_NOINSERT
+%token ODB_TYPEOF
+%token ODB_ARRNAME ODB_NICKNAME
+%token ODB_DISTINCT
+%token ODB_COND ODB_NORM
+%token ODB_USING
+%token ODB_DATABASE ODB_SRCPATH ODB_DATAPATH ODB_IDXPATH ODB_POOLMASK
+%token ODB_MATCH
+
+%left  ODB_OR
+%left  ODB_AND
+%left  ODB_IN ODB_NOTIN
+%left  ODB_INFILE ODB_NOTINFILE
+%left  ODB_NE ODB_EQ ODB_CMP
+%left  ODB_GE ODB_LE ODB_GT ODB_LT
+%left  ODB_DOTP
+%left  ODB_ADD ODB_SUB
+%left  ODB_STAR ODB_DIV ODB_MODULO
+%left  ODB_UNARY_MINUS ODB_UNARY_PLUS ODB_NOT
+%right ODB_POWER
+%right ODB_QMARK ODB_COLON
+
+%start odbsql
+
+%%
+
+odbsql  : { /* a hack to get "$mdi" always defined */
+	    char *pname = "$mdi";
+	    double value = ABS(RMDI);
+	    ODB_Symbol *name = ODB_lookup(ODB_USDNAME,pname,NULL);
+	    if (!name) {
+	      ODB_Tree *expr = ODBOPER1(ODB_NUMBER,&value);
+	      ODB_Tree *p;
+	      name = ODB_new_symbol(ODB_USDNAME,pname);
+	      p = ODBOPER2(ODB_SET, name, expr);
+	      (void) ODB_new_cmd(p); 
+	    }
+	    /* For internal use only; None of the following cannot be redefined by the user */
+	    /* Install '$#' which defines the current pool number in order to
+	       reference it from SELECT-expressions or WHERE-stmt */
+	    DEF_USDHASH("$#", 0);
+	    /* Install also other $-variables that end with '#'.
+	       Note also that _POOLNO i.e. '$pool#' is an alias to '$#' */
+	    DEF_USDHASH(_POOLNO, 0);
+	    DEF_USDHASH(_NPOOLS, 0);
+	    DEF_USDHASH(_NTABLES, 0);
+	    DEF_USDHASH(_UNIQNUM, 0);
+	    DEF_USDHASH(_ROWNUM, 0);
+	    DEF_USDHASH(_COLNUM, 0);
+	    DEF_USDHASH(_NROWS, 0);
+	    DEF_USDHASH(_NCOLS, 0);
+	    { /* Initialize the dummy WHERE-condition */
+	      if (!YACC_dummy_cond) YACC_dummy_cond = ODBOPER1(ODB_NUMBER,&YACC_TruE);
+	    }	    
+	} stmtlist
+	;
+
+stmtlist: stmt				{ $$ = $1; }
+	| stmtlist ODB_SEMICOLON stmt	{ $$ = $1; }
+	| error				{ yyclearin; yyerrok; }
+	;
+
+stmt	: /* empty */			{ $$ = NULL; }
+	| ODB_INCLUDE filename {
+		char *filename = STRDUP($2);
+		(void) LEX_open_include(filename);
+
+		/* Help LEX to bail out from the INCLUDE-block */
+		LEX_prev_state(); 
+
+		return 0;
+	}
+	| ODB_EXIT { return 1; }
+	| ODB_READONLY	{ readonly_mode = 1; }
+	| ODB_UPDATED	{ readonly_mode = 0; }
+	| opt_using ODB_INDEX as opt_idxname { 
+	  const char *idxname = $4 ? $4 : YACC_any_index;
+	  use_index_name = STRDUP(idxname); 
+	  use_indices = 1;
+	}
+	| opt_using ODB_DATABASE as dbcred {
+	  char *s = $4;
+	  while(isspace(*s)) ++s;
+	  {
+	    char *cred = STRDUP(s);
+	    char *last_slash = strchr(cred, '/');
+	    char *basename = last_slash ? last_slash+1 : cred;
+	    char *dot = strchr(basename,'.');
+	    char *dirname;
+	    if (last_slash) *last_slash = '\0';
+	    dirname = (STRLEN(cred) > 0) ? cred : ".";
+	    FREE(YACC_current_srcpath);
+	    YACC_current_srcpath = STRDUP(dirname);
+	    FREE(YACC_current_datapath);
+	    YACC_current_datapath = STRDUP(dirname);
+	    FREE(YACC_current_dbname);
+	    if (dot) *dot = '\0';
+	    YACC_current_dbname = ODB_uppercase(basename);
+	    FREE(cred);
+	  }
+	}
+	| opt_using ODB_SRCPATH as dbcred {
+	  char *s = $4;
+	  while(isspace(*s)) ++s;
+	  {
+	    char *cred = STRDUP(s);
+	    FREE(YACC_current_srcpath);
+	    YACC_current_srcpath = cred;
+	  }
+	}
+	| opt_using ODB_DATAPATH as dbcred {
+	  char *s = $4;
+	  while(isspace(*s)) ++s;
+	  {
+	    char *cred = STRDUP(s);
+	    FREE(YACC_current_datapath);
+	    YACC_current_datapath = cred;
+	  }
+	}
+	| opt_using ODB_IDXPATH as dbcred {
+	  char *s = $4;
+	  while(isspace(*s)) ++s;
+	  {
+	    char *cred = STRDUP(s);
+	    FREE(YACC_current_idxpath);
+	    YACC_current_idxpath = cred;
+	  }
+	}
+	| opt_using ODB_POOLMASK as dbcred {
+	  char *s = $4;
+	  while(isspace(*s)) ++s;
+	  {
+	    char *cred = STRDUP(s);
+	    FREE(YACC_current_poolmask);
+	    YACC_current_poolmask = cred;
+	  }
+	}
+	| ODB_NOINDEX	{ use_indices = 0; FREE(use_index_name); }
+	| ODB_REORDER	{ reorder_tables = 1; }
+	| ODB_NOREORDER	{ reorder_tables = 0; }
+	| ODB_INSERT	{ insert_tables = 1; }
+	| ODB_NOINSERT	{ insert_tables = 0; }
+	| ODB_SAFEGUARD	  { safeGuard = 1; }
+	| ODB_NOSAFEGUARD { safeGuard = 0; }
+	| ODB_SET extUSDname ODB_EQ expr {
+		char *pname = $2;
+		ODB_Symbol *name;
+		/* Prevent user from redefining the '$#' variable */
+		if (strequ(pname,"$#")) {
+		  SETMSG0("Pool number ($#-variable) cannot be re-defined by the user");
+		  YYerror(msg);
+		}
+		/* Prevent redefinition of *ANY* variables starting with '$' and
+		   ending with '#'. These are for internal use only */
+		if (IS_USDHASH(pname)) {
+		  SETMSG1("Illegal '%s': it is forbidden to redefine $-variables ending with '#'",pname);
+		  YYerror(msg);
+		}
+		name = ODB_lookup(ODB_USDNAME,pname,NULL);
+		if (!name) {
+		  ODB_Tree *expr = $4;
+		  ODB_Tree *p;
+
+		  name = ODB_new_symbol(ODB_USDNAME,pname);
+		  p = ODBOPER2(ODB_SET, name, expr);
+
+		  $$ = ODB_new_cmd(p); 
+		}
+		else {
+		  double oldvalue = name->dval;
+		  double newvalue = 0;
+		  if (!(ODB_evaluate($4,&newvalue) && newvalue == oldvalue)) {
+		    SETMSG2("Variable '%s' was already set ; previous value (%.20g) retained\n",
+		           pname, oldvalue);
+		    YYwarn(0,msg);
+		  }
+		}
+	}
+	| ODB_RESET align {
+		extern char *one_tables;
+		char c = $2;
+		if (one_tables) {
+		  char *p = one_tables;
+		  while (*p) { if (*p == c) *p = '#'; p++; }
+		}
+		if (c == '=') {
+		  extern Boolean reset_align_issued;
+		  reset_align_issued = 1;
+		}
+		else if (c == '@') {
+		  extern Boolean reset_onelooper_issued;
+		  reset_onelooper_issued = 1;
+		}
+	}
+	| align ODB_LP alignlist ODB_RP {
+		char key = $1;
+		int nsym = $3;
+		extern char *one_tables;
+		extern int optlevel;
+		extern Boolean ODB_tables_done; /* defined in tree.c */
+		if (ODB_tables_done) {
+		  SETMSG0("ALIGN/ONELOOPER/SHAREDLINK statements must be situated in data definition layout (ddl)\n");
+		  YYerror(msg);
+		}
+		else if (key == '&') { /* Shareable link; regardless of optimization level */
+		  char c = key;
+		  int j;
+		  char *master;
+		  char *tmp_one_tables = NULL;
+		  char **list;
+  		  ALLOC(list, nsym);
+		  for (j=nsym-1; j>=0; j--) {
+		    list[j] = ODB_popstr();
+		  }
+		  master = STRDUP(list[0]);
+		  if (one_tables) {
+		    int len;
+		    tmp_one_tables = STRDUP(one_tables+1);
+		    len = strlen(tmp_one_tables);
+		    tmp_one_tables[len-1] = '\0';
+		    FREE(one_tables);
+		  }
+		  init_list(tmp_one_tables);
+		  for (j=1; j<nsym; j++) {
+		    int nelem, len_all;
+		    char *all;
+		    len_all = strlen(master) + 1 + strlen(list[j]) + 1;
+		    ALLOC(all, len_all);
+		    sprintf(all,"%s%c%s",master,c,list[j]);
+		    nelem = ODB_addrel(all,c);
+		    FREE(all);
+		  }
+		  {
+		    char *plist = add_list(NULL);
+		    if (plist) one_tables = STRDUP(plist);
+		  }
+		  destroy_list();
+		  FREE(list);
+		  FREE(master);
+		}
+		else if (nsym >= 2 && optlevel >=3) {
+		  char c = key;
+		  int j, nelem;
+		  char *master;
+		  char *tmp_one_tables = NULL;
+		  char **list;
+		  int len_all;
+		  char *all;
+  		  ALLOC(list, nsym);
+		  for (j=nsym-1; j>=0; j--) {
+		    list[j] = ODB_popstr();
+		  }
+		  master = STRDUP(list[0]);
+		  if (one_tables) {
+		    int len;
+		    tmp_one_tables = STRDUP(one_tables+1);
+		    len = strlen(tmp_one_tables);
+		    tmp_one_tables[len-1] = '\0';
+		    FREE(one_tables);
+		  }
+		  init_list(tmp_one_tables);
+		  len_all = strlen(master) + 1 + 1;
+		  for (j=1; j<nsym; j++) {
+		    len_all += strlen(list[j]) + 1;
+		  }
+		  len_all += 1;
+		  ALLOC(all, len_all);
+		  sprintf(all,"%s%c(",master,c);
+		  for (j=1; j<nsym; j++) {
+		   strcat(all,list[j]);
+		   strcat(all,(j<nsym-1) ? "," : ")");
+		  }
+		  nelem = ODB_addrel(all,c);
+		  {
+		    char *plist = add_list(NULL);
+		    if (plist) one_tables = STRDUP(plist);
+		  }
+		  destroy_list();
+		  FREE(list);
+		  FREE(master);
+		  FREE(all);
+		}
+	} 
+	| typedef ODB_LP decllist ODB_RP {
+		int nsym = $3;
+		ODB_Type *type = $1;
+		ODB_Tree *p;
+		p = ODBOPER2(ODB_TYPE, type, &nsym);
+		$$ = ODB_new_cmd(p); 
+	}
+	| typedef name {
+		int nsym = 1;
+		ODB_Type *type = $1;
+		char *empty_member = STRDUP(EMPTY_MEMBER);
+		ODB_Tree *p;
+
+		(void) ODB_new_type($2, 1);
+		(void) ODB_new_symbol(ODB_NAME, empty_member);
+
+		ODB_pushstr($2);         /* type string to stack */
+		ODB_pushstr(empty_member);  /* member name string to stack */
+
+		p = ODBOPER2(ODB_TYPE, type, &nsym);
+
+		$$ = ODB_new_cmd(p); 
+	}
+	| tabledef ODB_LP decllist ODB_RP { 
+	  extern Boolean ODB_in_tabledef;
+	  ODB_Cmd *pcmd = NULL;
+	  Tabledef_t *list = $1;
+	  int nt = list->num_tables, jlist = 0;
+	  {
+		int j, k, nsym = $3, ksym, nsym_actual = 0;
+		ODB_Table *table = list->tables[jlist];
+		char *tname = table ? table->table->name : NIL;
+		ODB_Tree *p;
+		Boolean dupl_exist;
+		ODB_Symbol **psym;
+		ODB_Type **ptype;
+		int *linkmode;
+		int nlink = 0;
+
+		ALLOC(ptype, 2 * nsym);
+		ALLOC(psym, 2 * nsym);
+		ALLOC(linkmode, 2 * nsym);
+
+		ksym = 2*nsym - 1;
+		for (j=nsym-1; j>=0; j--) {
+		  char *s;
+		  ODB_Type *type;
+		  char *typename;
+
+		  s = ODB_popstr(); /* name string from stack */
+		  psym[ksym]  = ODB_lookup(ODB_NAME, s, NULL);
+
+		  s = ODB_popstr(); /* type string from stack */
+		  ptype[ksym] = ODB_lookup_type(s, NULL);
+
+		  type = ptype[ksym];
+		  typename = type->type->name;
+
+		  if (*typename == '@') { 
+		    /* We have a link; adjust entries; note reverse order */
+		    char *len, *offset;
+
+		    linkmode[ksym  ] = 2; /* Length */
+		    linkmode[ksym-1] = 1; /* Offset */
+		    nlink++;
+
+		    ALLOC(len, strlen(psym[ksym]->name) + 30);
+		    sprintf(len, "LINKLEN(%s)",psym[ksym]->name);
+
+		    ALLOC(offset, strlen(psym[ksym]->name) + 30);
+		    sprintf(offset, "LINKOFFSET(%s)",psym[ksym]->name);
+
+		    psym[ksym] = ODB_new_symbol(ODB_NAME, len);
+		    psym[ksym-1] = ODB_new_symbol(ODB_NAME, offset);
+
+		    FREE(offset);
+		    FREE(len);
+
+		    ptype[ksym] = ODB_new_type(LINKLENTYPE, 1);
+		    ptype[ksym-1] = ODB_new_type(LINKOFFSETTYPE, 1);
+		    nsym_actual += 2;
+		  }
+		  else {
+		    linkmode[ksym] = linkmode[ksym-1] = 0; /* Not a link */
+		    psym[ksym-1]  = NULL;
+		    ptype[ksym-1] = NULL;
+		    nsym_actual++;
+		  }
+		  ksym -= 2;
+		}
+
+		table->nsym = nsym_actual;
+		ALLOC(table->type, nsym_actual);
+		ALLOC(table->sym, nsym_actual);
+		ALLOC(table->linkmode, nsym_actual);
+		
+		ksym = 2 * nsym;
+		j = 0;
+		for (k=0; k<ksym; k++) {
+		  if (ptype[k] && psym[k]) {
+		    table->type[j] = ptype[k];
+		    table->sym[j] = psym[k];
+		    table->linkmode[j] = linkmode[k];
+		    j++;
+		  }
+		  k++;
+		  if (ptype[k] && psym[k]) {
+		    table->type[j] = ptype[k];
+		    table->sym[j] = psym[k];
+		    table->linkmode[j] = linkmode[k];
+		    j++;
+		  }
+		}
+
+		nsym = nsym_actual;
+		
+		table->nlink = nlink;
+		ALLOC(table->link, nlink);
+		ALLOC(table->linkname, nlink);
+		ALLOC(table->sharedlink, nlink);
+		ALLOC(table->sharedlinkname, nlink);
+
+		if (nlink > 0) {
+		  Boolean *sharedlink_mask;
+		  int num_sharedlink = 0;
+		  CALLOC(sharedlink_mask, nsym);
+		  k = 0;
+		  for (j=0; j<nsym; j++) {
+		    if (table->linkmode[j] == 1) { /* LINK-offset */
+		      extern char *one_tables;
+		      char *p = ODB_extract(table->sym[j]->name,'(',')');
+		      ODB_Table *link_table = ODB_lookup_table(p,NULL);
+		      table->link[k] = link_table; /* Can still point to a NULL */
+		      table->linkname[k] = p; /* ... just in case the link[k] was a NULL */
+		      table->sharedlink[k] = NULL; /* ... for the moment; may change */
+		      table->sharedlinkname[k] = ODB_get_sharedlinkname(p, one_tables);
+		      if (table->sharedlinkname[k]) {
+			table->sharedlinkname[k] = STRDUP(table->sharedlinkname[k]);
+		        num_sharedlink++;
+			sharedlink_mask[j]   = 1; /* link-offset */
+			sharedlink_mask[j+1] = 1; /* link-length */
+		      }
+		      k++;
+		      DEF_USDDOTHASH(tname, p);
+		    } /* if (table->linkmode[j] == 1) */
+		  }
+		  if (num_sharedlink > 0) {
+		    /* Remove shared link from symbol list of this table */
+		    ODB_Type **shl_type;
+		    ODB_Symbol **shl_sym;
+		    int *shl_linkmode;
+	            nsym_actual = nsym - 2 * num_sharedlink; /* "2" is for offset & length */
+		    ALLOC(shl_type, nsym_actual);
+		    ALLOC(shl_sym, nsym_actual);
+		    ALLOC(shl_linkmode, nsym_actual);
+		    k = 0;
+		    for (j=0; j<nsym; j++) {
+			if (sharedlink_mask[j]) continue;
+			shl_type[k] = table->type[j];
+			shl_sym[k] = table->sym[j];
+			shl_linkmode[k] = table->linkmode[j];
+			k++;
+		    }
+		    FREE(table->type);     table->type = shl_type;
+		    FREE(table->sym);      table->sym = shl_sym;
+		    FREE(table->linkmode); table->linkmode = shl_linkmode;
+		    table->nsym = nsym = nsym_actual; /* no. of symbols reset again */
+		    table->any_sharedlinks = 1;
+		  }
+		  FREE(sharedlink_mask);
+		} /* if (nlink > 0) */
+
+		FREE(linkmode);
+
+		dupl_exist = ODB_dupl_symbols(table->sym, nsym, 1);
+
+		if (dupl_exist) {
+		  SETMSG1("Duplicate variables encountered in the table '%s'\n", tname);
+		  YYerror(msg);
+		}
+
+		ALLOC(table->expname, nsym);
+		for (j=0; j<nsym; j++) {
+		  char *s = NULL;
+		  int slen = 3;
+		  Boolean bitstream = table->type[j]->bitstream;
+		  slen += strlen(bitstream ? BITFIELD : table->type[j]->type->name);
+		  slen += strlen(table->sym[j]->name);
+		  slen += strlen(table->table->name);
+		  ALLOC(s, slen);
+		  sprintf(s,"%s:%s@%s",
+			bitstream ? BITFIELD : table->type[j]->type->name,
+			table->sym[j]->name,
+			table->table->name);
+		  table->expname[j] = s;
+		}
+
+		p = ODBOPER1(ODB_TABLE, table);
+
+		pcmd = ODB_new_cmd(p);
+	  }
+	  if (nt > 1) {
+	    for (jlist=1; jlist<nt; jlist++) {
+		ODB_Tree *p;
+		ODB_Table *table0 = list->tables[0];
+		ODB_Table *table = list->tables[jlist];
+		char *tname = table ? table->table->name : NIL;
+		table = list->tables[jlist] = ODB_copy_table(table0, tname);
+		p = ODBOPER1(ODB_TABLE, table);
+		pcmd = ODB_new_cmd(p);
+	    }
+	  }
+	  $$ = pcmd;
+	  ODB_in_tabledef = 0;
+	}
+	| dropindex opt_ontable {
+	  ODB_Cmd *pcmd = NULL;
+	  Viewdef_t *list = $1;
+	  int nt = list->num_views, jlist = 0;
+	  ODB_link_massage();
+	  if (nt > 1) {
+	    ODB_View *view = list->views[0];
+	    char *vname = STRDUP(view->view->name);
+	    char *vp = strrchr(vname,'_');
+	    if (!vp) vp = vname; else *vp = '\0';
+	    SETMSG1("The array syntax '%s[<low>:<high>]' in name definition not supported with CREATE INDEX",vp);
+	    YYerror(msg);
+	  }
+	  {
+	    int j;
+	    int error = 0;
+	    int nfrom = $2;
+	    int nselect = 0;
+	    ODB_View *view = list->views[jlist];
+	    char *vname = view->view->name;
+	    view->cond = NULL;
+	    view->create_index = LEX_create_index;
+
+	    if (nfrom > 0) {
+	      view->no_from_stmt = no_from_stmt = 0;
+	      view->nfrom = nfrom;
+	      ALLOC(view->from, nfrom);
+	      ALLOC(view->from_attr, nfrom);
+	      for (j=nfrom-1; j>=0; j--) {
+		int flag = ODB_popi(); /* from-attribute */
+		char *s = ODB_popstr(); /* a character string from the stack */
+		ODB_Table *ptable = ODB_lookup_table(s, NULL);
+		if (!ptable) {
+		  SETMSG4("Undefined table '%s' in DROP INDEX %s ON %s (from_attr=0x%x)\n",
+			  s,vname,s,flag);
+		  error++;
+		  YYwarn(error,msg);
+		}
+		view->from_attr[j] = flag;
+		view->from[j] = ptable;
+	      }
+
+	      ALLOC(view->active, 1);
+	      view->active[0] = 1;
+	    }
+
+	    if (error) { 
+	      SETMSG1("Syntax error in DROP INDEX '%s' [ON table(s)] definition",vname);
+	      YYerror(msg);
+	    }
+
+	    {
+	      ODB_Tree *p = ODBOPER1(ODB_VIEW, view);
+	      pcmd = ODB_new_cmd(p);
+	    }
+	  }
+	  $$ = pcmd;
+	  LEX_create_index = 0;
+	}
+	| indexdef ontable indexcols where {
+	  ODB_Cmd *pcmd = NULL;
+	  Viewdef_t *list = $1;
+	  int nt = list->num_views, jlist = 0;
+	  int nfrom = $2; /* must be 1 */
+	  ODB_link_massage();
+	  if (nfrom != 1) {
+	    SETMSG0("Currently exactly one 'tablename' needed in 'CREATE INDEX name ON tablename' ...");
+	    YYerror(msg);
+	  }
+	  if (nt > 1) {
+	    ODB_View *view = list->views[0];
+	    char *vname = STRDUP(view->view->name);
+	    char *vp = strrchr(vname,'_');
+	    if (!vp) vp = vname; else *vp = '\0';
+	    SETMSG1("The array syntax '%s[<low>:<high>]' in name definition not supported with CREATE INDEX",vp);
+	    YYerror(msg);
+	  }
+	  {
+	    int j;
+	    int nselect = $3; /* ncols (could be == 0) */ 
+	    ODB_Tree *cond = $4;
+	    int nwhere = ODB_trace_symbols(cond, NULL, 0);
+	    ODB_View *view = list->views[jlist];
+	    char *vname = view->view->name;
+	    int error = 0;
+	    Boolean relate_where  = (nwhere > 0);
+	    Boolean relate_select = (nselect > 0);
+	    ODB_Symbol **pwhere= NULL;
+	    ODB_Symbol **pselect=NULL;
+
+	    /* Reverse processing order : WHERE, COLUMNS, ON TABLE */
+
+	    /* === WHERE === */
+	    ALLOC(pwhere, nwhere);
+	    for (j=nwhere-1; j>=0; j--) {
+	      char *s = ODB_popstr(); /* a character string from the stack */
+	      /* The following symbol may still have "@"'s or "."'s [if ODB_NAME] */
+	      int what = IS_HASH(s) ? ODB_HASHNAME : 
+		  (IS_DOLLAR(s) ? ODB_USDNAME : (IS_BSNUM(s) ? ODB_BSNUM : ODB_NAME));
+	      pwhere[j] = ODB_new_symbol(what, s);
+	    }
+
+	    /* "select" COLUMNS */
+	    ALLOC(pselect, nselect);
+	    view->nselect = nselect;
+	    view->nselect_all = nselect;
+	    view->all_readonly = 1;
+	    ALLOC(view->readonly, nselect);
+	    CALLOC(view->is_formula, nselect);
+	    for (j=nselect-1; j>=0; j--) {
+	      char *s = ODB_popstr(); /* a character string from the stack */
+	      pselect[j] = ODB_new_symbol(ODB_NAME, s);
+	      view->readonly[j] = 1;
+	    }
+	    view->select = pselect;
+
+	    /* "from" TABLE */
+
+	    if (nfrom != 1) error++;
+
+	    view->no_from_stmt = no_from_stmt = 0;
+	    view->nfrom = nfrom;
+	    ALLOC(view->from, nfrom);
+	    ALLOC(view->from_attr, nfrom);
+
+	    for (j=nfrom-1; j>=0; j--) {
+	      int flag = ODB_popi(); /* from-attribute */
+	      char *s = ODB_popstr(); /* a character string from the stack */
+	      ODB_Table *ptable = ODB_lookup_table(s, NULL);
+	      if (!ptable) {
+		SETMSG3("Undefined table '%s' in CREATE INDEX '%s' (from_attr=0x%x)\n",s,vname,flag);
+		error++;
+		YYwarn(error,msg);
+	      }
+	      view->from_attr[j] = flag;
+	      view->from[j] = ptable;
+	    }
+
+	    ALLOC(view->active, 1);
+	    view->active[0] = 1;
+
+	    /* === Check SELECT relations === */
+	    
+	    if (!error && relate_select) {
+	      int count = 0;
+	      SymbolParam_t *inout;
+	      
+	      /*** SELECT ***/
+	      
+	      ALLOC(inout, 1);
+	      inout->nsym = nselect;
+	      inout->sym = pselect;
+	      inout->readonly = view->readonly;
+	      inout->sel = NULL;
+
+	      (void)ODB_resolve_relations("SELECT", ODB_BAILOUT_SELECT, inout, 
+      		       vname, view->from, view->from_attr, nfrom, pselect, NULL, nselect, 
+					  0, 0,
+					  &count, NULL);
+
+	      FREE(pselect);
+
+	      relate_select = 0;
+
+	      /* === Remove duplicates (if any) === */
+
+	      nselect = ODB_remove_duplicates(inout, 
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL,
+					      NULL);
+	      
+	      view->nselect_all = nselect;
+	      view->nselect = nselect;
+	      view->select = pselect = inout->sym;
+	      view->readonly = inout->readonly;
+
+	      if (nselect > MAXBITS) {
+		SETMSG1("Only up to %d columns allowed in CREATE INDEX ... ON TABLE ( columns )",MAXBITS);
+		error++;
+		YYwarn(error,msg);
+	      }
+
+	      FREE(inout);
+	    }
+	    
+	    if (!error && relate_where) {
+	      /*** WHERE ***/
+	      int count = 0;
+
+	      view->where = 
+		ODB_resolve_relations("WHERE", ODB_BAILOUT_WHERE, NULL, 
+		   vname, view->from, view->from_attr, nfrom, pwhere, NULL, nwhere, 
+				      1, 1,
+				      &count, NULL);
+	      view->nwhere = nwhere = count;
+	      relate_where = 0;
+	    }
+
+	    if (!error && !cond && nselect == 0) {
+	      /* Make sure the user DOES supply columns and/or WHERE-condition,
+		 but does not leave out BOTH !! */
+	      SETMSG0("Either column(s) or WHERE-condition must be present in CREATE INDEX ... ON TABLE ( columns ) WHERE cond");
+	      error++;
+	      YYwarn(error,msg);
+	    }
+
+	    if (error) { 
+	      SETMSG1("Syntax error in CREATE INDEX '%s' definition",vname);
+	      YYerror(msg);
+	    }
+
+	    /* The rest */
+
+	    view->active[0] = 1;
+	    view->cond = cond;
+
+	    view->create_index = LEX_create_index;
+
+	    {
+	      ODB_Tree *p = ODBOPER1(ODB_VIEW, view);
+	      /* Setup WHERE-symbols and check string comparisons in WHERE */
+	      ODB_setup_where(view);
+	      pcmd = ODB_new_cmd(p);
+	    }
+	  }
+	  $$ = pcmd;
+	  LEX_create_index = 0;
+	}
+	| viewdef select uniqueby from where orderby {
+	  /* New: if orderby is present, then push its symbols to select-list, too,
+	          in case they were missing => the following becomes possible:
+
+		  select a,b,c from t orderby d
+
+		  as it is in fact the same as
+
+		  select a,b,c,d from t orderby d !! 
+
+		  Note: This technique doesn't work if a sorting column number is given, i.e.
+		  the following doesn't make sense:
+
+		  select a,b,c, from t orderby 4
+
+		  But the following is still legal:
+
+		  select a,b,c from t orderby 3
+
+		  since column#3 i.e. c is already present in select
+		  */
+	  ODB_Cmd *pcmd = NULL;
+	  Viewdef_t *list = $1;
+	  int nt = list->num_views, jlist = 0;
+	  ODB_link_massage();
+	  if (nt > 1) {
+	    ODB_View *view = list->views[0];
+	    char *vname = STRDUP(view->view->name);
+	    char *vp = strrchr(vname,'_');
+	    if (!vp) vp = vname; else *vp = '\0';
+	    SETMSG1("The array syntax '%s[<low>:<high>]' in name definition not supported with CREATE VIEW",vp);
+	    YYerror(msg);
+	  }
+	  {
+		int j;
+		Selectdef_t *sdef = $2;
+		int nselect = sdef->nselect;
+		Boolean *readonly = sdef->readonly;
+		int nfrom = $4;
+		int norderby = $6;
+		int nuniqueby = $3;
+		ODB_Tree *cond = $5;
+		int nwhere = ODB_trace_symbols(cond, NULL, 0);
+		int iwhere = nwhere;
+		ODB_View *view = list->views[jlist];
+		char *vname = view->view->name;
+		ODB_Tree *p;
+		int error = 0;
+		Boolean relate_where  = (nwhere > 0);
+		Boolean relate_orderby = (norderby > 0 || norderby == -1);
+		Boolean relate_select = 1;
+		Boolean has_wildcard = 0;
+		Boolean has_regex = 0;
+		Boolean has_number_orderby = 0;
+		Boolean has_number_uniqueby = 0;
+		int *sign = NULL;
+		ODB_Symbol **pwhere= NULL;
+		ODB_Symbol **porderby=NULL;
+		ODB_Symbol **puniqueby=NULL;
+		ODB_Symbol **pselect=NULL;
+		Boolean *p_readonly=NULL;
+		int more_from_orderby = 0;
+		char **from_orderby = NULL;
+		ODB_SelectExpr **p_sel = NULL;
+		Boolean maybe_sd = 0; /* maybe a SELECT DISTINCT ? */
+
+		/* Note the reverse(-ish) processing order :
+		   {WHERE,ORDERBY,FROM,UNIQUEBY,SELECT} */
+
+		/* === WHERE === */
+
+		ALLOC(pwhere, nwhere);
+
+		for (j=nwhere-1; j>=0; j--) {
+		  char *s = ODB_popstr(); /* a character string from the stack */
+		  /* The following symbol may still have "@"'s or "."'s [if ODB_NAME] */
+		  int what = IS_HASH(s) ? ODB_HASHNAME : 
+		      (IS_DOLLAR(s) ? ODB_USDNAME : (IS_BSNUM(s) ? ODB_BSNUM : ODB_NAME));
+		  pwhere[j] = ODB_new_symbol(what, s);
+		}
+
+		/* === ORDERBY === */
+
+		if (norderby > 0) {
+		  ALLOC(from_orderby, norderby);
+		  ALLOC(porderby, norderby);
+		  ALLOC(sign, norderby);
+		}
+		more_from_orderby = 0;
+
+		for (j=norderby-1; j>=0; j--) {
+		  char *s = ODB_popstr();     /* a character string from the stack */
+		  int  xsign = ODB_popi(); /* the sign : +1 or -1 or 9999 (=ABS) */
+		  sign[j] = xsign;
+		  /* The following symbol may still have "@"'s or "."'s */
+		  porderby[j] = ODB_new_symbol(ODB_NAME, s);
+		  if (ODB_is_integer(s)) {
+		    has_number_orderby = 1;
+		  }
+		  else {
+		    from_orderby[more_from_orderby++] = s;
+		  }
+		}
+		
+		/*
+		fprintf(stderr,"more_from_orderby is now = %d\n",more_from_orderby);
+		fprintf(stderr,"norderby = %d\n",norderby);
+		*/
+
+		/* === FROM === */
+
+		view->nfrom = nfrom;
+		ALLOC(view->from_attr, nfrom);
+		ALLOC(view->from, nfrom);
+
+		{
+		  int new_nfrom = 0;
+		  for (j=nfrom-1; j>=0; j--) {
+		    int flag = ODB_popi(); /* from-attribute */
+		    char *s = ODB_popstr(); /* a character string from the stack */
+		    ODB_Table *ptable = ODB_lookup_table(s, NULL);
+		    if (!ptable) {
+		      SETMSG3("Undefined table '%s' in view '%s' (from_attr=0x%x)\n",s,vname,flag);
+		      if (bailout_level == 0 || 
+			  ( (bailout_level & ODB_BAILOUT_FROM) != ODB_BAILOUT_FROM) ) error++;
+		      YYwarn(error,msg);
+		    }
+		    else {
+		      new_nfrom++;
+		    }
+		    view->from_attr[j] = flag;
+		    view->from[j] = ptable;
+		  } /* for (j=nfrom-1; j>=0; j--) */
+		  
+		  if (!error && new_nfrom < nfrom) {
+		    /* We are here due to bailout_level NOT being == 0 (which is the default) */
+		    ODB_Table **from;
+		    int *from_attr;
+		    int jj = 0;
+		    ALLOC(from, new_nfrom);
+		    ALLOC(from_attr, new_nfrom);
+		    for (j=0; j<nfrom; j++) {
+		      int flag = view->from_attr[j];
+		      ODB_Table *ptable = view->from[j];
+		      if (ptable) {
+			jj++;
+			from_attr[jj] = flag;
+			from[jj] = ptable;
+		      }
+		    } /* for (j=0; j<nfrom; j++) */
+		    FREE(view->from);
+		    FREE(view->from_attr);
+		    view->from = from;
+		    view->from_attr = from_attr;
+		    view->nfrom = nfrom = new_nfrom;
+		    if (nfrom == 0) {
+		      /* 
+			 Could this be a problem ?
+			 FROM bad_table1,bad_table2 gets converted into FROM * ???
+		      */
+		      no_from_stmt = 1;
+		    }
+		  }
+		}
+
+		view->no_from_stmt = no_from_stmt;
+
+		if (!YACC_select_distinct &&
+		    no_from_stmt &&
+		    norderby == 0 && 
+		    nselect > 0 &&
+		    nuniqueby == 0) maybe_sd = 1;
+
+		/* == Remove duplicate FROM-tables == */
+
+		if (!no_from_stmt) {
+		  nfrom = ODB_RemoveDuplicateTables(view);
+		}
+
+		/* == Insert missing FROM-tables == */
+
+		if (view->insert_tables) { 
+		  /* 'INSERT' keyword is used (is the default [see also env ODB_INSERT_TABLES]) */
+		  nfrom = ODB_insert_tables(view);
+		}
+		else {
+		  /* don't perform insertion */
+		  if (verbose) 
+			fprintf(stderr,
+				"yacc: Insertion of missing tables to FROM-stmt bypassed in view '%s'\n",vname);
+		} /* if (view->insert_tables) */
+
+		/* == Reorder FROM-tables == */
+		
+		if (view->reorder_tables) { 
+		  /* 'REORDER' keyword used/active (the default [see also env ODB_REORDER_TABLES]) */
+		  (void) ODB_reorder_tables(view);
+		}
+		else {
+		  /* don't perform reordering */
+		  if (verbose) 
+			fprintf(stderr,
+				"yacc: Reordering of FROM-tables bypassed in view '%s'\n",vname);
+		} /* if (view->reorder_tables) */
+
+		nfrom = view->nfrom;
+
+		/* === UNIQUEBY === */
+
+		if (nuniqueby != 0 && YACC_select_distinct) {
+		  SETMSG3("The keywords in '%s' and '%s' have to be mutually exclusive in view '%s'\n",
+			  "SELECT UNIQUE", "UNIQUE BY", vname);
+		  error++;
+		  YYwarn(error,msg);
+		}
+
+		if (!YACC_select_distinct) {
+		  if (nuniqueby < 0) {
+		    nuniqueby = ODB_pick_symbols(view->from, view->from_attr, nfrom);
+		  }
+		  ALLOC(puniqueby, nuniqueby);
+		  for (j=nuniqueby-1; j>=0; j--) {
+		    char *s = ODB_popstr(); /* a character string from the stack */
+		    /* The following symbol may still have "@"'s or "."'s */
+		    puniqueby[j] = ODB_new_symbol(ODB_NAME, s); 
+		    has_number_uniqueby |= ODB_is_integer(s);
+		  }
+		}
+
+		/* === SELECT === */
+
+		if (nselect < 0) { /* Means : 'SELECT *' */
+		  int j;
+		  Boolean readonly_flag = sdef->readonly[0];
+		  sdef->nselect = nselect = 
+		    ODB_pick_symbols(view->from, view->from_attr, nfrom) + more_from_orderby;
+		  ALLOC(sdef->select_items, nselect);
+		  FREE(sdef->readonly);
+		  ALLOC(sdef->readonly, nselect);
+		  for (j=more_from_orderby-1; j>=0 ; j--) {
+		    char *s = from_orderby[j];
+		    ODB_pushstr(s);
+		  }
+		  for (j=nselect-1; j>=0; j--) {
+		    char *s = ODB_popstr();
+		    sdef->select_items[j] = s;
+		    sdef->readonly[j] = readonly_flag;
+		  }
+		  readonly = sdef->readonly;
+		  if (more_from_orderby == 0) {
+		    relate_select = 0; /* Symbol relations to the tables are now fully resolved */
+		  }
+		}
+		else if (more_from_orderby > 0) {
+		  /* expand "sdef" with items from orderby */
+		  int j, jj;
+		  Selectdef_t *new_sdef = NULL;
+		  CALLOC(new_sdef,1);
+		  /* fprintf(stderr,"<begin>nselect=%d\n",nselect); */
+		  nselect += more_from_orderby;
+		  /* fprintf(stderr,"<end>nselect=%d\n",nselect); */
+		  new_sdef->nselect = nselect;
+		  ALLOC(new_sdef->select_items, nselect);
+		  ALLOC(new_sdef->readonly, nselect);
+		  CALLOC(new_sdef->sel, nselect);
+		  new_sdef->next = NULL;
+		  new_sdef->nselect = nselect;
+		  for (j=0; j<sdef->nselect; j++) {
+		    new_sdef->select_items[j] = sdef->select_items[j];
+		    new_sdef->readonly[j] = sdef->readonly[j];
+		    if (sdef->sel) new_sdef->sel[j] = sdef->sel[j];
+		  }
+		  jj = more_from_orderby;
+		  for (j=sdef->nselect; j<new_sdef->nselect; j++) {
+		    new_sdef->select_items[j] = from_orderby[--jj];
+		    new_sdef->readonly[j] = readonly_mode;
+		  }
+		  readonly = new_sdef->readonly;
+		  FREE(sdef->select_items);
+		  FREE(sdef->readonly);
+		  FREE(sdef->sel);
+		  FREE(sdef);
+		  sdef = new_sdef;
+		}
+
+		FREE(from_orderby);
+
+		ALLOC(pselect, nselect);
+		ALLOC(p_readonly, nselect);
+		CALLOC(p_sel, nselect);
+
+		for (j=0; j<nselect; j++) {
+		  char *s = STRDUP(sdef->select_items[j]);
+		  int slen = strlen(s);
+		  /* The following symbol may still have "@"'s or "."'s */
+		  pselect[j] = ODB_new_symbol(ODB_NAME, s); 
+		  p_readonly[j] = readonly[j];
+		  if (sdef->sel) p_sel[j] = &sdef->sel[j];
+		  if (IS_REGEX(s, slen)) {
+			has_regex = 1;
+		  }
+		  else if (IS_WILDCARD(s)) {
+			has_wildcard = 1;
+		  }
+		  /*
+		  fprintf(stderr,
+		             "$#@ sdef->select_items[%d] = '%s' (readonly=%d, wildcard=%d/%d, regex=%d/%d)\n",
+			     j,s,p_readonly[j],IS_WILDCARD(s),has_wildcard,IS_REGEX(s, slen),has_regex); */
+		}
+
+		/* Expand partial wildcards ('*@table' or 'var.*@table') in SELECT */
+
+		if (has_regex || has_wildcard) {
+		  int errcnt = 0;
+		  int i, count = 0;
+		  int *p_count;
+		  CALLOC(p_count, nselect);
+		  for (j=0; j<nselect; j++) {
+		    ODB_Symbol *psym = pselect[j];
+		    char *s = psym->name;
+		    int slen = strlen(s);
+		    if (IS_REGEX(s, slen)) {
+		      /* fprintf(stderr,"$$$ IS_REGEX: pselect[%d]->name = '%s'\n",j,s); */
+		      p_count[j] = ODB_regex(s, view->from, view->from_attr, nfrom);
+		      if (p_count[j] <= 0) {
+		        SETMSG2("Regular expression '%s' in SELECT-clause (column#%d) did not match any columns",
+			s,j+1);
+			++errcnt;
+			YYwarn(errcnt,msg); /* Do not abort -- yet */
+		      }
+		    }
+		    else if (IS_WILDCARD(s)) {
+		      /* fprintf(stderr,"$$$ IS_WILDCARD: pselect[%d]->name = '%s'\n",j,s); */
+		      s = ODB_lowercase(psym->name);
+		      /* ODB_wildcard will fail inside if no matches found */
+		      p_count[j] = ODB_wildcard(s, view->from, view->from_attr, nfrom);
+		      FREE(s);
+		    }
+		    else {
+		      /* fprintf(stderr,"$$$ regular: pselect[%d]->name = '%s'\n",j,s); */
+		      ODB_pushstr(s);
+		      p_count[j] = 1;
+		    }
+		    count += p_count[j];
+	            /* fprintf(stderr,"===>p_count[%d] = %d\n",j,p_count[j]); */
+		  } /* for (j=0; j<nselect; j++) */
+
+		  if (errcnt > 0) ODB_exit(errcnt);
+
+		  /* fprintf(stderr,"### nselect=%d => count=%d\n",nselect,count); */
+
+		  {		  
+		    ODB_SelectExpr **p_sel_expanded;
+		    Boolean *p_readonly_expanded;
+		    CALLOC(p_sel_expanded, count);
+		    ALLOC(p_readonly_expanded, count);
+		    i = count;
+		    for (j=nselect-1; j>=0; j--) {
+		      int k;
+		      for (k=0; k<p_count[j]; k++) {
+		        --i;
+		        p_readonly_expanded[i] = p_readonly[j];
+		        p_sel_expanded[i] = p_sel[j];
+		      } /* for (k=0; k<p_count[j]; k++) */
+		    } /* for (j=nselect-1; j>=0; j--) */
+  		    FREE(p_readonly);
+		    p_readonly = p_readonly_expanded;
+		    FREE(p_sel);
+		    p_sel = p_sel_expanded;
+		  }
+
+		  FREE(pselect);
+		  nselect = count;
+
+		  ALLOC(pselect, nselect);
+
+		  for (j=nselect-1; j>=0; j--) {
+		    char *s = ODB_popstr(); /* a character string from the stack */
+		    /* The following symbol may still have "@"'s or "."'s */
+		    /* fprintf(stderr,"$$$ from stack %d = '%s' (readonly=%d)\n",j,s,p_readonly[j]); */
+		    pselect[j] = ODB_new_symbol(ODB_NAME, s); 
+		  }
+
+		} /* if (has_regex || has_wildcard) */
+
+		/* === Check SELECT relations === */
+
+		if (relate_select) {
+		  int count = 0;
+		  SymbolParam_t *inout;
+
+		  /*** SELECT ***/
+
+		  ALLOC(inout, 1);
+		  inout->nsym = nselect;
+		  inout->sym = pselect;
+		  inout->readonly = p_readonly;
+		  inout->sel = p_sel;
+
+		  (void)ODB_resolve_relations("SELECT", ODB_BAILOUT_SELECT, inout, 
+			vname, view->from, view->from_attr, nfrom, pselect, NULL, nselect, 
+			0, 0,
+			&count, NULL);
+
+		  FREE(pselect);
+		  FREE(p_readonly);
+
+		  relate_select = 0;
+
+		  /* === Remove duplicates (if any) === */
+
+		  nselect = ODB_remove_duplicates(inout, 
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL,
+						  NULL);
+
+		  pselect = inout->sym;
+		  p_readonly = inout->readonly;
+		  p_sel = inout->sel;
+
+		  FREE(inout);
+		}
+
+		view->nselect_all = nselect;
+		view->nselect = nselect;
+		view->select = pselect;
+		view->readonly = p_readonly;
+
+		view->all_readonly = 0;
+		for (j=0; j<nselect; j++) {
+		  view->all_readonly += view->readonly[j];
+	          /* fprintf(stderr,"$$$ select col#%d = '%s'\n",j,view->select[j]->name); */
+		}
+		view->all_readonly = (view->all_readonly == nselect);
+
+		if (nselect == 0) {
+		  SETMSG1("Empty SELECT-clause in view '%s'",vname);
+		  YYerror(msg);
+		}
+
+		/* Find symbol references in select expressions/formulas */
+
+		view->sel = p_sel;
+		CALLOC(view->is_formula, nselect);
+		view->nselsym = 0;
+		view->selsym = NULL;
+		for (j=0; j<nselect; j++) {
+		  if (view->sel && view->sel[j] && view->sel[j]->formula) {
+		    /*** SELECT expression (for each column separately) ***/
+		    ODB_Tree *expr = view->sel[j]->expr;
+		    char *formula = view->sel[j]->formula;
+		    int count = 0;
+		    ODB_Symbol **psym = view->sel[j]->sym;
+		    int nsym = view->sel[j]->nsym;
+		    /* fprintf(stderr,"SELECTEXPR[col#%d:%s]< nsym=%d\n",j+1,formula,nsym); */
+		    psym = view->sel[j]->sym = 
+			  ODB_resolve_relations("SELECTEXPR", ODB_BAILOUT_SELECTEXPR, NULL, 
+			  vname, view->from, view->from_attr, nfrom, psym, NULL, nsym, 
+			  1, 1,
+			  &count, NULL);
+		    /* fprintf(stderr,"SELECTEXPR[col#%d:%s]> nsym=%d\n",j+1,formula,count); */
+		    if (nsym != count) {
+		      SETMSG1("Tried to access the whole link-word (= 2 columns) in your SELECT-expression '%s' ?",
+		      formula+1);
+		      YYwarn(1,msg);
+		      SETMSG2("A serious programming error after ODB_resolve_relations(SELECTEXPR): nsym=%d != count=%d",
+		              nsym, count);
+		      YYerror(msg); /* Fails on this */
+		    }
+		    view->nselsym += count;
+		    view->is_formula[j] = 1;
+
+		    if (maybe_sd) {
+		      /* Still in SELECT DISTINCT -route ? */
+		      ODB_Tree *expr = view->sel[j]->expr;
+		      double numba = 0;
+		      int irc = ODB_evaluate(expr,&numba);
+		      if (!irc) maybe_sd = 0;
+		    }
+		  }
+		  else
+		    maybe_sd = 0;
+		}
+
+		if (maybe_sd) YACC_select_distinct = 1;
+
+		if (view->nselsym > 0) {
+		  int k, nselsym = view->nselsym;
+		  CALLOC(view->selsym, nselsym);
+		  for (j=0, k=0; j<nselect; j++) {
+		    if (view->is_formula[j] && view->sel[j]->nsym > 0) {
+		      int kk, nsym = view->sel[j]->nsym;
+		      for (kk=0; kk<nsym; kk++) {
+		        view->selsym[k+kk] = view->sel[j]->sym[kk];
+		      }
+		      k += nsym;
+		    }
+		  }
+		}
+
+		/* Take UNIQUEBY elements from the SELECT-list directly */
+
+		if (YACC_select_distinct) {
+		  nuniqueby = nselect;
+		  ALLOC(puniqueby, nuniqueby);
+		  for (j=0; j<nuniqueby; j++) {
+		    puniqueby[j] = ODB_symbol_copy(pselect[j]);
+		  }		  
+		  view->select_distinct = 1;
+		}
+
+		/* === Adjust UNIQUEBY references, if integers were found === */
+		/* Not applicable to SELECT DISTINCT, since an integer is also an expression */
+
+		if (has_number_uniqueby && !YACC_select_distinct) {
+		  for (j=0; j<nuniqueby; j++) {
+		    char *s = puniqueby[j]->name;
+		    if (ODB_is_integer(s)) {
+			int val = atoi(s);
+			if (val >= 1 && val <= view->nselect) {
+			  puniqueby[j] = view->select[val-1];
+			}
+			else {
+			  SETMSG2("No such SELECT-column#%d. UNIQUEBY out of bounds in view '%s'",
+				 val, vname);
+			  YYerror(msg); 
+			}
+		    } /* if (ODB_is_integer(s)) */
+		  }
+		}
+
+		/* === Append UNIQUEBY variables to the WHERE-condition === */
+
+		if (nuniqueby > 0) {
+		  double Dnuniqueby = nuniqueby;
+		  int numargs = 1 + nuniqueby;
+		  ODB_Tree *func, *expr;
+
+		  /*** Add expression with AND ***/
+
+		  expr = ODBOPER1(ODB_NUMBER,&Dnuniqueby);
+		  ODB_pushexpr(expr);
+
+		  if (YACC_select_distinct) {
+		    /* "puniqueby[j]->name" can be a formula */
+		    for (j=0; j<nuniqueby; j++) {
+		      /* Note: right now 'nuniqueby == nselect' */
+		      char *s = puniqueby[j]->name;
+		      if (view->is_formula[j]) {
+			expr = ODB_oper_copy(view->sel[j]->expr, 1);
+		      }
+		      else {
+		        expr = ODBOPER1(ODB_NAME,puniqueby[j]->name);
+		      }
+		      ODB_pushexpr(expr);
+		    }
+		  }
+		  else {
+		    for (j=0; j<nuniqueby; j++) {
+		      expr = ODBOPER1(ODB_NAME,puniqueby[j]->name);
+		      ODB_pushexpr(expr);
+		    }
+		  }
+		  func = ODBOPER2(ODB_FUNC,"Unique",&numargs);
+
+		  if (cond)  cond = ODBOPER2(ODB_AND,cond,func);
+		  else       cond = func;
+
+		  /*** Re-create list of WHERE-symbols added by the UNIQUEBY symbols ***/
+
+		  FREE(pwhere);
+		  nwhere = ODB_trace_symbols(cond, NULL, 0);
+		  ALLOC(pwhere, nwhere);
+
+		  for (j=nwhere-1; j>=0; j--) {
+		    char *s = ODB_popstr(); /* a character string from the stack */
+		    /* The following symbol may still have "@"'s or "."'s */
+		    pwhere[j] = ODB_new_symbol(ODB_NAME, s);
+		  }
+
+		  relate_where = 1;
+		}
+
+		/* === Check WHERE relations === */
+
+		if (relate_where) {
+		  /*** WHERE ***/
+		  int count = 0;
+		  view->where = 
+			ODB_resolve_relations("WHERE", ODB_BAILOUT_WHERE, NULL, 
+			vname, view->from, view->from_attr, nfrom, pwhere, NULL, nwhere, 
+			1, 1,
+			&count, NULL);
+
+		  view->nwhere = nwhere = count;
+
+		  relate_where = 0;
+		}
+		else {
+		  view->nwhere = nwhere = 0;
+		  view->where = NULL;
+		}
+
+		/* === Adjust ORDERBY references, if integers were found === */
+
+		if (has_number_orderby) {
+		  for (j=0; j<norderby; j++) {
+		    char *s = porderby[j]->name;
+		    if (ODB_is_integer(s)) {
+			int val = atoi(s);
+			if (val >= 1 && val <= view->nselect) {
+			  porderby[j] = view->select[val-1];
+			}
+			else {
+			  SETMSG2("No such SELECT-column#%d. ORDERBY out of bounds in view '%s'",
+				 val, vname);
+			  YYerror(msg); 
+			}
+		    } /* if (ODB_is_integer(s)) */
+		  }
+		}
+
+		/* === Fill in wildcard ORDERBY relations === */
+
+		if (norderby == -1) {
+		  norderby = view->nselect;
+		  ALLOC(porderby, norderby);
+		  ALLOC(sign, norderby);
+		  for (j=0; j<norderby; j++) {
+		    ODB_Symbol *psym = view->select[j];
+		    char *s = psym->name;
+		    porderby[j] = ODB_new_symbol(ODB_NAME, s);
+		    sign[j] = +1;
+		  }
+		}
+
+		/* === Check ORDERBY relations === */
+
+		if (relate_orderby) {
+		  /*** ORDERBY ***/
+		  int count = 0;
+		  view->orderby = 
+			ODB_resolve_relations("ORDERBY", ODB_BAILOUT_ORDERBY, NULL,
+			vname, view->from, view->from_attr, nfrom, porderby, sign, norderby, 
+			0, 0,
+			&count, &view->mkeys);
+
+		  view->norderby = norderby = count;
+		  relate_orderby = 0;
+
+		  /* Match up ORDER BY-symbols with the specified SELECT-symbols */
+		  error |= ODB_matchup_sym(1,
+				"ORDERBY", view->orderby, view->norderby, 
+				"SELECT", view->select, view->nselect,
+				view->mkeys);
+		}
+		else {
+		  view->norderby = 0;
+		  view->orderby = NULL;
+		  view->mkeys = NULL;
+		}
+
+		if (error) { 
+		  SETMSG1("Syntax error in view '%s' definition",vname);
+		  YYerror(msg);
+		}
+
+		FREE(puniqueby);
+		FREE(pwhere);
+		FREE(porderby);
+		FREE(sign);
+
+		view->cond = cond;
+		view->nuniqueby = nuniqueby;
+
+		/* === Wrap up === */
+
+		has_usddothash = 0;
+		p = ODBOPER1(ODB_VIEW, view);
+		has_count_star = 0;
+
+		/* Get the fully resolved UNIQUEBY symbols from WHERE-symbols */
+		{
+		  int count = view->nwhere - iwhere;
+		  if (count > 0) {
+		    int k = 0;
+		    ALLOC(view->uniqueby, count);
+		    for (j=iwhere; j<nwhere; j++) {
+		      view->uniqueby[k++] = view->where[j];
+		    }
+		    view->nuniqueby = count;
+		  }
+		}
+
+		/* Setup WHERE-symbols and check string comparisons in WHERE */
+		ODB_setup_where(view);
+
+		/* Remap symbols in SELECT-expressions */
+		if (view->nselsym > 0) {
+		  int k=0, nselsym = view->nselsym;
+		  for (j=0; j<nselect; j++) {
+		    if (view->is_formula[j]) {
+		      /*** SELECT expression (for each column separately) ***/
+		      ODB_Tree *expr = view->sel[j]->expr;
+		      char *formula = view->sel[j]->formula;
+		      char *formula_out = NULL;
+		      int count = 0;
+		      ODB_Symbol **psym = view->sel[j]->sym;
+		      int nsym = view->sel[j]->nsym;
+		      k += ODB_setup_selectexpr(view, k, j);
+		      view->sel[j]->formula_out = formula_out = dump_s(NULL,expr,ddl_piped ? 2 : 0,NULL);
+		      /* fprintf(stderr,"SELECTEXPR[col#%d:%s]> nsym=%d\n",j+1,formula_out,nsym); */
+		    }
+		  }
+		  FREE(view->selsym);
+		  /* Redo selsym's */
+		  CALLOC(view->selsym, nselsym);
+		  for (j=0, k=0; j<nselect; j++) {
+		    if (view->is_formula[j] && view->sel[j]->nsym > 0) {
+		      int kk, nsym = view->sel[j]->nsym;
+		      for (kk=0; kk<nsym; kk++) {
+		        ODB_Symbol *psym = view->selsym[k+kk] = view->sel[j]->sym[kk];
+			if (!has_usddothash && psym && psym->name) {
+			  /* Flag presence of "$<parent_table>.<child_table>" -variables in SELECT */
+			  has_usddothash = IS_USDDOTHASH(psym->name) ? 1 : 0;
+			}
+		      } /* for (kk=0; kk<nsym; kk++) */
+		      k += nsym;
+		    }
+		  } /* for (j=0, k=0; j<nselect; j++) */
+		}
+
+		/* Set 'has_formulas' if any SELECT colums involves formulas */
+		if (view->sel) {
+	          for (j=0; j<nselect; j++) {
+		    if (view->is_formula[j]) { view->has_formulas = 1; break; }
+                  }
+		}
+
+		if (view->has_formulas) {
+		  /* Update select aggregate list for each element SELECT-list 
+		     (constant/common for all) */
+		  view->select_aggr_flag = 0;
+		  view->ncols_aux = 0;
+		  for (j=0; j<nselect; j++) {
+		    if (view->is_formula[j]) {
+		      view->select_aggr_flag |= view->sel[j]->aggr_flag;
+		      view->ncols_aux += view->sel[j]->ncols_aux;
+		    }
+		  }
+		}
+
+		view->usddothash = has_usddothash;
+
+		has_usddothash = 0;
+		YACC_select_distinct = 0;
+		LEX_convflag = 0;
+		LEX_unconv_value = 0;
+		pcmd = ODB_new_cmd(p); 
+		if (verbose) 
+			fprintf(stderr,"yacc: VIEW='%s' done.\n",vname);
+	  }
+	  $$ = pcmd;
+	}
+	;
+
+as	: /* empty */	{ $$ = 0; }
+	| ODB_AS	{ $$ = 1; }
+	| ODB_EQ	{ $$ = 2; }
+	| ODB_COLON	{ $$ = 3; }
+	;
+
+typedef	: ODB_TYPE name as { 
+		ODB_Type *type = ODB_new_type($2, 0);
+		$$ = type; 
+	}
+	;
+
+tabledef: ODB_TABLE arrname as {
+		extern Boolean ODB_in_tabledef;
+		int errflg = 0;
+		int jlist;
+		int nt = $2;
+		char **table_name = NULL;
+		Tabledef_t *list;
+		ALLOC(list,1);
+		list->num_tables = nt;
+		ALLOC(list->tables, nt);
+		ODB_in_tabledef = 1;
+		ALLOC(table_name, nt);
+		for (jlist=nt-1; jlist>=0; jlist--) {
+		  table_name[jlist] = ODB_popstr();
+		}
+		/* Check that the table name is NOT called "core" to avoid confusion with Unix core-files */
+		/* ECMWF had one such case in Dec'2005, where tar-command failed (!) on IBM
+		   and produced a core-dump in one of the ODB data directories, which bound to cause
+		   havoc what it comes to autodetecting table names for compilation etc. */
+		/* Now (5-May-2006) we test also against Windows/CYGWIN special files, too */
+		for (jlist=0; jlist<nt; jlist++) {
+		  int jt;
+		  for (jt=0; jt<N_INVTABNAM; jt++) {
+		    const char *pname = invalid_table_names[jt];
+		    if (strequ(table_name[jlist], pname)) {
+		      SETMSG1("ODB/SQL-compiler does not accept table names that are called '%s'.",pname);
+		      errflg++;
+		      YYwarn(errflg,msg);
+		      break; /* for (jt=0; jt<N_INVTABNAM; jt++) */
+		    }
+		  }
+		}
+		if (errflg > 0) { /* Invalid table names encountered */
+		  SETMSG0("Invalid table names encountered");
+		  YYerror(msg);
+		}
+		for (jlist=0; jlist<nt; jlist++) {
+		  list->tables[jlist] = ODB_new_table(table_name[jlist], 0);
+		}
+		FREE(table_name);
+		$$ = list;
+	}
+	;
+
+indexdef : ODB_CREATEINDEX idxname {
+		const int nt = 1;
+		char *idxname = $2;
+		{
+		  Viewdef_t *list;
+		  CALLOC(list,1);
+		  list->num_views = nt;
+		  CALLOC(list->views, nt);
+		  list->views[0] = ODB_new_view(idxname, 0);
+		  $$ = list;
+		}
+	 }
+
+dropindex : ODB_DROPINDEX opt_idxname {
+		const int nt = 1;
+		char *idxname = $2;
+		if (!idxname) idxname = use_index_name;
+		if (!idxname) idxname = STRDUP("*");
+		{
+		  Viewdef_t *list;
+		  CALLOC(list,1);
+		  list->num_views = nt;
+		  CALLOC(list->views, nt);
+		  list->views[0] = ODB_new_view(idxname, 0);
+		  $$ = list;
+		}
+	 }
+	 ;
+
+viewdef	: ODB_VIEW arrname as { 
+		int jlist;
+		int nt = $2;
+		char **view_name = NULL;
+		Viewdef_t *list;
+		ALLOC(list,1);
+		list->num_views = nt;
+		ALLOC(list->views, nt);
+		ALLOC(view_name, nt);
+		for (jlist=nt-1; jlist>=0; jlist--) {
+		  view_name[jlist] = ODB_popstr();
+		}
+		for (jlist=0; jlist<nt; jlist++) {
+		  list->views[jlist] = ODB_new_view(view_name[jlist], 0);
+		  tmp_view_num++;		  
+		}
+		FREE(view_name);
+		$$ = list;
+	}
+	| /* empty */ {
+	        extern char *odb_source;
+	        const int nt = 1;
+	        Viewdef_t *list;
+		char *viewname = NULL;
+		ALLOC(list,1);
+		list->num_views = nt;
+		ALLOC(list->views, nt);
+		if (tmp_view_num > 0 || !odb_source) {
+		  if (!odb_source && tmp_view_num == 0) tmp_view_num++;
+		  ALLOC(viewname,50);
+		  sprintf(viewname,"%s_%d","_tmp",tmp_view_num++);
+		  list->views[0] = ODB_new_view(viewname, 0);
+		}
+		else {
+		  char *p = viewname = ODB_lowercase(odb_source);
+		  char *find = strrchr(viewname,'/');
+		  if (find) p = find + 1;
+		  find = strchr(p,'.');
+		  if (find) *find = '\0';
+		  list->views[0] = ODB_new_view(p, 0);
+		  tmp_view_num++;		  
+		}
+		FREE(viewname);
+		$$ = list;
+	}
+	;
+
+select	: select2 sellist	{ 
+	        ODB_SelAttr_t *attr = $1;
+		Selectdef_t *sdef = NULL;
+		Selectdef_t *p_sdef = $2;
+		int i, n = 0;
+		while (p_sdef) {
+		  n += p_sdef->nselect;
+		  p_sdef = p_sdef->next;
+		}
+		/* fprintf(stderr,">>ODB_SELECT sellist: n=%d\n",n); */
+		CALLOC(sdef, 1);
+		sdef->nselect = n;
+		ALLOC(sdef->select_items, n);
+		ALLOC(sdef->readonly, n);
+		CALLOC(sdef->sel, n);
+		sdef->next = NULL;
+		if (n > 0) {
+		  int chunk = 0;
+		  i = n;
+		  p_sdef = $2;
+		  while (p_sdef) {
+		    int j, nselect = p_sdef->nselect;
+		    ++chunk;
+		    /* fprintf(stderr,"** nselect=%d (chunk#%d)\n",nselect,chunk); */
+		    for (j=nselect-1; j>=0; j--) {
+		      --i;
+		      sdef->select_items[i] = p_sdef->select_items[j];
+		      sdef->readonly[i] = p_sdef->readonly[j];
+		      if (p_sdef->sel) sdef->sel[i] = p_sdef->sel[j];
+		      /* fprintf(stderr,"**** i=%d, j=%d: '%s' [r/o=%d]\n",
+			      i,j,sdef->select_items[i],sdef->readonly[i]); */
+		    }
+		    p_sdef = p_sdef->next;
+		  }
+		}
+		/* fprintf(stderr,"<<ODB_SELECT sellist\n"); */
+		YACC_select_distinct = attr ? attr->distinct : 0;
+		$$ = sdef;
+	}
+	| select2 star opt_sel_param opt_comma { 
+	        ODB_SelAttr_t *attr = $1;
+		int mode = $3;
+		Boolean readonly_flag = 
+		  IS_SET(mode,ODBURO_EMPTY) ? readonly_mode : IS_SET(mode,ODBREADONLY);
+		Selectdef_t *sdef;
+		CALLOC(sdef,1);
+		sdef->nselect = -1;
+		sdef->select_items = NULL;
+		ALLOC(sdef->readonly, 1);
+		sdef->readonly[0] = readonly_flag;
+		sdef->next = NULL;
+		YACC_select_distinct = attr ? attr->distinct : 0;
+		if (IS_SET(mode,ODBAS)) { /* Disregard, but warn */
+		  char *s = ODB_popstr();
+		  SETMSG1("Nickname not applicable in 'SELECT * AS %s'",s);
+		  YYerror(msg);
+		}
+		$$ = sdef;
+	}
+	;
+
+opt_comma : /* empty */
+	  | ODB_COMMA
+	  ;
+
+select2	: ODB_SELECT_DISTINCT { ODB_SelAttr_t *attr; CALLOC(attr,1); attr->distinct = 1; $$ = attr; }
+	| ODB_SELECT_ALL      { $$ = NULL; /* interpreted as distinct=0 */ }
+	;
+
+opt_sel_param 	: opt_as_nickname 		{ $$ = (ODBURO_EMPTY | $1); }
+		| opt_as_nickname ODB_READONLY	{ $$ = (ODBREADONLY  | $1); }
+		| opt_as_nickname ODB_UPDATED	{ $$ = (ODBUPDATED   | $1); }
+		;
+
+opt_as_nickname	: /* empty */ { $$ = 0; }
+	      	| ODB_AS name   { ODB_pushstr($2); $$ = ODBAS; }
+	      	| ODB_AS string { ODB_pushstr($2); $$ = ODBAS; }
+		;
+
+uniqueby: /* empty */			{ $$ = 0; }
+	| ODB_UNIQUEBY uniqlist		{ $$ = $2; }
+	| ODB_UNIQUEBY star		{ $$ = -1; }
+	;
+
+from	: /* empty */			{ $$ = ODB_pick_tables(-2); /* Automatic "pick up" */ }
+	| ODB_FROM star			{ $$ = ODB_pick_tables(-1); /* Automatic "pick up" */}
+	| ODB_FROM fromlist		{ $$ = ODB_pick_tables($2); /* User defined : add attribute */}
+	;
+
+ontable : ODB_ON fromlist { 
+	    int count = ODB_pick_tables($2);
+	    $$ = count;
+          }
+	;
+
+opt_ontable : /* empty */ { $$ =  0; }
+	    | ontable	  { $$ = $1; }
+	    ;
+
+where	: /* empty */			{ $$ = NULL; }
+	| ODB_WHERE cond		{ $$ = $2;   }
+	;
+
+orderby	: /* empty */			{ $$ = 0; }
+	| ODB_ORDERBY sortlist		{ $$ = $2; }
+	| ODB_ORDERBY star		{ $$ = -1; }
+	;
+
+star	: ODB_STAR			{ $$ = -1; }
+	| ODB_LP star ODB_RP		{ $$ = -1; }
+	;
+
+cond	: expr				{ $$ = $1; }
+	| pred				{ $$ = $1; }
+	;
+
+insiders : ODB_INSIDE		{ $$ = ODB_INSIDE; }
+	 | ODB_INSIDE_POLYGON   { $$ = ODB_INSIDE_POLYGON; }
+	 ;
+
+outsiders : ODB_OUTSIDE		{ $$ = ODB_OUTSIDE; }
+	  | ODB_OUTSIDE_POLYGON { $$ = ODB_OUTSIDE_POLYGON; }
+	  ;
+
+other_siders : insiders string opt_comma ODB_RP {
+          int what = $1;
+	  char *s = YACC_join(3,$2);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  ODB_Tree *lat = ODBOPER1(ODB_NAME,ODB_LAT);
+	  ODB_Tree *lon = ODBOPER1(ODB_NAME,ODB_LON);
+	  $$ = ODBOPER3(what, region, lat, lon);
+	}
+	| outsiders string opt_comma ODB_RP {
+	  char *s = YACC_join(3,$2);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  ODB_Tree *lat = ODBOPER1(ODB_NAME,ODB_LAT);
+	  ODB_Tree *lon = ODBOPER1(ODB_NAME,ODB_LON);
+	  int what = ($1 == ODB_OUTSIDE) ? ODB_INSIDE : ODB_INSIDE_POLYGON;
+	  ODB_Tree *tmp = ODBOPER3(what, region, lat, lon);
+	  $$ = ODBOPER1(ODB_NOT, tmp);
+	}
+	;
+
+other_near : ODB_NEAR string opt_comma ODB_RP {
+	  char *s = YACC_join(3,$2);
+	  ODB_Tree *place = ODBOPER1(ODB_STRING,s);
+	  ODB_Tree *lat = ODBOPER1(ODB_NAME,ODB_LAT);
+	  ODB_Tree *lon = ODBOPER1(ODB_NAME,ODB_LON);
+	  $$ = ODBOPER3(ODB_NEAR, place, lat, lon);
+	}
+	;
+
+selinside : insiders string ODB_COMMA selexpr ODB_COMMA selexpr opt_comma ODB_RP {
+          int what = $1;
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  $$ = ODBOPER3(what, region, $4, $6);
+	}
+	| outsiders string ODB_COMMA selexpr ODB_COMMA selexpr opt_comma ODB_RP {
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  int what = ($1 == ODB_OUTSIDE) ? ODB_INSIDE : ODB_INSIDE_POLYGON;
+	  ODB_Tree *tmp = ODBOPER3(what, region, $4, $6);
+	  $$ = ODBOPER1(ODB_NOT, tmp);
+	}
+	| other_siders { $$ = $1; }
+	;
+
+selnear	: ODB_NEAR string ODB_COMMA selexpr ODB_COMMA selexpr opt_comma ODB_RP {
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *place = ODBOPER1(ODB_STRING,s);
+	  $$ = ODBOPER3(ODB_NEAR, place, $4, $6);
+	}
+	| other_near { $$ = $1; }
+	;
+
+inside	: insiders string ODB_COMMA expr ODB_COMMA expr opt_comma ODB_RP {
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  $$ = ODBOPER3($1, region, $4, $6);
+	}
+	| outsiders string ODB_COMMA expr ODB_COMMA expr opt_comma ODB_RP {
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *region = ODBOPER1(ODB_STRING,s);
+	  int what = ($1 == ODB_OUTSIDE) ? ODB_INSIDE : ODB_INSIDE_POLYGON;
+	  ODB_Tree *tmp = ODBOPER3(what, region, $4, $6);
+	  $$ = ODBOPER1(ODB_NOT, tmp);
+	}
+	| other_siders { $$ = $1; }
+	;
+
+near	: ODB_NEAR string ODB_COMMA expr ODB_COMMA expr opt_comma ODB_RP {
+	  char *s = YACC_join_by_expr($2, ODB_NAME, $4, $6);
+	  ODB_Tree *place = ODBOPER1(ODB_STRING,s);
+	  $$ = ODBOPER3(ODB_NEAR, place, $4, $6);
+	}
+	| other_near { $$ = $1; }
+	;
+
+strcmpre: arrname			{ $$ = ODBOPER1(ODB_ARRNAME,&$1); }
+	| arrname ODB_EQNE_STRING	{ /* A serious hack ;-( */
+	    char *s = $2;
+	    int eqne = (*s++ == '1') ? ODB_EQ : ODB_NE;
+	    ODB_Tree *lhs = ODBOPER1(ODB_ARRNAME,&$1);
+	    ODB_Tree *rhs = ODBOPER1(ODB_STRING,s);
+	    int oper = ODB_EQ;
+	    ODB_Tree *t = ODBOPER3(ODB_STRFUNC, lhs, rhs, &oper);
+	    $$ = (eqne == oper) ? t : ODBOPER1(ODB_NOT, t);
+	}	
+	| arrname like_notlike string	{ 
+	    ODB_Tree *lhs = ODBOPER1(ODB_ARRNAME,&$1);
+	    ODB_Tree *rhs = ODBOPER1(ODB_WC_STRING,$3);
+	    int like = $2 ? ODB_LIKE : ODB_NOTLIKE;
+	    int oper = ODB_LIKE;
+	    ODB_Tree *t = ODBOPER3(ODB_STRFUNC, lhs, rhs, &oper);
+	    $$ = (like == oper) ? t : ODBOPER1(ODB_NOT, t);
+	}
+	;
+
+eqne	: ODB_EQ	{ $$ = 1; }
+	| ODB_NE	{ $$ = 0; }
+	;
+
+like_notlike	: ODB_LIKE	{ $$ = 1; }
+		| ODB_NOTLIKE	{ $$ = 0; }
+		;
+
+pred	: ODB_LP pred ODB_RP		{ $$ = $2; }
+	| expr is_null_or_is_not_null		{
+	  int is_what = $2 ? ODB_EQ : ODB_NE;
+	  char *pname = "$mdi";
+	  ODB_Symbol *name = ODB_lookup(ODB_USDNAME,pname,NULL);
+	  double mdi = name ? ABS(name->dval) : ABS(RMDI);
+	  ODB_Tree *arg = $1;
+	  if (is_what == ODB_EQ) {
+	    /* WHERE x is NULL 
+	       will effectively be translated to the following:
+	       WHERE abs(x) = $mdi 
+	     */
+	    int nargs = 1;
+	    ODB_pushexpr(arg);
+	    {
+	      ODB_Tree *lhs = ODBOPER2(ODB_FUNC,"abs",&nargs);
+	      ODB_Tree *rhs = ODBOPER1(ODB_NUMBER,&mdi);
+	      $$ = ODBOPER2(is_what, lhs, rhs);
+	    }
+	  }
+	  else {
+	    /* WHERE x is not NULL 
+	       will effectively be translated to the following:
+	       WHERE x != $mdi && x != -$mdi
+	     */
+	    ODB_Tree *rhspos = ODBOPER1(ODB_NUMBER,&mdi); /* $mdi */
+	    double mdineg = -mdi;
+	    ODB_Tree *rhsneg = ODBOPER1(ODB_NUMBER,&mdineg); /* -$mdi */
+	    ODB_Tree *left  = ODBOPER2(ODB_NE, arg, rhspos); /* x !=  $mdi */
+	    ODB_Tree *right = ODBOPER2(ODB_NE, arg, rhsneg); /* x != -$mdi */
+	    $$ = ODBOPER2(ODB_AND, left, right); /* left AND right */
+	  }
+	}
+	| ODB_NOT cond			{ $$ = ODBOPER1(ODB_NOT,$2); }
+	| cond ODB_AND cond		{ $$ = ODBOPER2(ODB_AND,$1,$3); }
+	| cond ODB_OR cond		{ $$ = ODBOPER2(ODB_OR,$1,$3); }
+	| expr ODB_BETWEEN expr ODB_AND expr { $$ = ODBOPER3(ODB_LELE,$3,$1,$5); }
+	| expr ODB_GT expr		{ $$ = ODBOPER2(ODB_GT,$1,$3); }
+	| expr ODB_GE expr		{ $$ = ODBOPER2(ODB_GE,$1,$3); }
+	| expr eqne expr		{ $$ = ODBOPER2($2 ? ODB_EQ : ODB_NE,$1,$3); }
+	| expr ODB_IS expr		{ $$ = ODBOPER2(ODB_EQ,$1,$3); }
+	| expr ODB_LE expr		{ $$ = ODBOPER2(ODB_LE,$1,$3); }
+	| expr ODB_LT expr		{ $$ = ODBOPER2(ODB_LT,$1,$3); }
+	| expr ODB_CMP expr		{ 
+	  int numargs = 2;
+	  ODB_pushexpr($1); ODB_pushexpr($3);
+	  $$ = ODBOPER2(ODB_FUNC,"cmp",&numargs); 
+	}
+	| expr ODB_IS ODB_NOT expr	{ $$ = ODBOPER2(ODB_NE,$1,$4); }
+	| expr ODB_GT expr ODB_GT expr	{ $$ = ODBOPER3(ODB_GTGT,$1,$3,$5); }
+	| expr ODB_GT expr ODB_GE expr	{ $$ = ODBOPER3(ODB_GTGE,$1,$3,$5); }
+	| expr ODB_GE expr ODB_GE expr	{ $$ = ODBOPER3(ODB_GEGE,$1,$3,$5); }
+	| expr ODB_GE expr ODB_GT expr	{ $$ = ODBOPER3(ODB_GEGT,$1,$3,$5); }
+	| expr ODB_LT expr ODB_LT expr	{ $$ = ODBOPER3(ODB_LTLT,$1,$3,$5); }
+	| expr ODB_LT expr ODB_LE expr	{ $$ = ODBOPER3(ODB_LTLE,$1,$3,$5); }
+	| expr ODB_LE expr ODB_LE expr	{ $$ = ODBOPER3(ODB_LELE,$1,$3,$5); }
+	| expr ODB_LE expr ODB_LT expr	{ $$ = ODBOPER3(ODB_LELT,$1,$3,$5); }
+	| ODB_ALIGN ODB_LP fromlist ODB_RP {
+		int numargs = $3;
+		if (numargs >= 2) {
+		  int j, nequ = numargs - 1;
+		  char **hs;
+		  ODB_Tree **hexpr, **equexpr;
+		  ODB_Tree *target, *andchain;
+		  ALLOC(hs, numargs);
+		  ALLOC(hexpr, numargs);
+		  for (j=numargs-1; j>=0; j--) {
+			char *t = NULL;
+			char *s = ODB_popstr();
+			int len = strlen(s) + 2;
+			ALLOC(t,len);
+			sprintf(t,"#%s",s);
+			hexpr[j] = ODBOPER1(ODB_HASHNAME, t);
+			FREE(t);
+		  }
+		  target = hexpr[0];
+		  ALLOC(equexpr, nequ);
+		  for (j=0; j<nequ; j++) {
+			equexpr[j] = ODBOPER2(ODB_EQ, target, hexpr[j+1]);
+		  }
+		  andchain = equexpr[0];
+		  for (j=1; j<nequ; j++) {
+			andchain = ODBOPER2(ODB_AND, andchain, equexpr[j]);
+		  }
+		  $$ = andchain;
+		}
+		else { /* No args ==> error */
+		  SETMSG0("ALIGN ( )-statement expects at least two arguments.");
+		  YYerror(msg);
+		}
+	}
+	| expr in_notin ODB_LP expr ODB_COLON expr opt_inc ODB_RP {
+	  ODB_Tree *target = $1;
+	  Boolean is_in = $2;
+	  ODB_Tree *begin = $4;
+	  ODB_Tree *end = $6;
+	  ODB_Tree *step = $7;
+	  int j, n = 4;
+	  ODB_Tree **args;
+	  ALLOC(args, n);
+	  args[0] = target;
+	  args[1] = begin;
+	  args[2] = end;
+	  args[3] = step;
+	  for (j=0; j<n; j++) ODB_pushexpr(args[j]);
+	  { 
+	    ODB_Tree *f = ODBOPER2(ODB_FUNC,"InGenList",&n);
+	    $$ = is_in ? f : ODBOPER1(ODB_NOT,f);
+	  }
+	  FREE(args);
+	}
+	| expr in_notin query {
+	  int numexpr = 1;
+	  double dnumexpr = numexpr;
+	  ODB_Tree *numexpr_expr = ODBOPER1(ODB_NUMBER, &dnumexpr);
+	  double dnummatch = 0;
+	  ODB_Tree *nummatch_expr = ODBOPER1(ODB_NUMBER, &dnummatch);
+	  ODB_Tree *expr = $1;
+	  Boolean is_in = $2;
+	  ODB_Tree *query = $3;
+	  ODB_Symbol *query_funcsym = query->argv[0];
+	  char *query_funcname = query_funcsym->name;
+	  double runonce = strequ(query_funcname, "RunOnceQuery") ? 1 : 0;
+	  ODB_Tree *runonce_expr = ODBOPER1(ODB_NUMBER, &runonce);
+	  int numargs = numexpr + 4;
+	  ODB_pushexpr(numexpr_expr);
+	  ODB_pushexpr(nummatch_expr);
+	  ODB_pushexpr(query);
+	  ODB_pushexpr(runonce_expr);
+	  ODB_pushexpr(expr);
+	  { 
+	    ODB_Tree *f = ODBOPER4(ODB_FUNC, "InQuery", &numargs, NULL, NULL);
+	    $$ = is_in ? f : ODBOPER1(ODB_NOT, f);
+	  }
+	}
+	| ODB_MATCH expr ODB_COMMA exprlist opt_comma ODB_RP in_notin query {
+	  int j,numexpr = 1 + $4;
+	  double dnumexpr = numexpr;
+	  ODB_Tree *numexpr_expr = ODBOPER1(ODB_NUMBER, &dnumexpr);
+	  double dnummatch = 0;
+	  ODB_Tree *nummatch_expr = ODBOPER1(ODB_NUMBER, &dnummatch);
+	  ODB_Tree **expr = NULL;
+	  CALLOC(expr, numexpr);
+	  for (j=numexpr-1; j>0; j--) expr[j] = ODB_popexpr();
+	  expr[0] = $2;
+	  {
+	    Boolean is_in = $7;
+	    ODB_Tree *query = $8;
+	    ODB_Symbol *query_funcsym = query->argv[0];
+	    char *query_funcname = query_funcsym->name;
+	    double runonce = strequ(query_funcname, "RunOnceQuery") ? 1 : 0;
+	    ODB_Tree *runonce_expr = ODBOPER1(ODB_NUMBER, &runonce);
+	    double dnumexpr = numexpr;
+	    ODB_Tree *numexpr_expr = ODBOPER1(ODB_NUMBER, &dnumexpr);
+	    int numargs = numexpr + 4;
+	    ODB_pushexpr(numexpr_expr);
+	    ODB_pushexpr(nummatch_expr);
+	    ODB_pushexpr(query);
+	    ODB_pushexpr(runonce_expr);
+	    for (j=0; j<numexpr; j++) ODB_pushexpr(expr[j]);
+	    FREE(expr);
+	    { 
+	      ODB_Tree *f = ODBOPER4(ODB_FUNC, "InQuery", &numargs, NULL, NULL);
+	      $$ = is_in ? f : ODBOPER1(ODB_NOT, f);
+	    }
+	  }
+	}
+	| matchfunc in_notin query {
+	  ODB_Match_t *match = $1;
+	  const char *formula = match->formula;
+	  int nummatch = strchr(formula,'\\') ? 1 : 0; /* If any \<number>'s present ==> nummatch = 1 */
+	  ODB_Tree *match_expr = (nummatch == 1) ? ODBOPER1(ODB_MATCH, match) : match->expr;
+	  {
+	    double dnummatch = nummatch;
+	    ODB_Tree *nummatch_expr = ODBOPER1(ODB_NUMBER, &dnummatch);
+	    Boolean is_in = $2;
+	    ODB_Tree *query = $3;
+	    ODB_Symbol *query_funcsym = query->argv[0];
+	    char *query_funcname = query_funcsym->name;
+	    double runonce = strequ(query_funcname, "RunOnceQuery") ? 1 : 0;
+	    ODB_Tree *runonce_expr = ODBOPER1(ODB_NUMBER, &runonce);
+	    int numexpr = 1;
+	    double dnumexpr = numexpr;
+	    ODB_Tree *numexpr_expr = ODBOPER1(ODB_NUMBER, &dnumexpr);
+	    int numargs = numexpr + 4;
+	    ODB_pushexpr(numexpr_expr);
+	    ODB_pushexpr(nummatch_expr);
+	    ODB_pushexpr(query);
+	    ODB_pushexpr(runonce_expr);
+	    ODB_pushexpr(match_expr);
+	    { 
+	      ODB_Tree *f = ODBOPER4(ODB_FUNC, "InQuery", &numargs, NULL, (nummatch == 1) ? match : NULL);
+	      $$ = is_in ? f : ODBOPER1(ODB_NOT, f);
+	    }
+	  }
+	}
+	| expr in_notin ODB_LP arglist ODB_RP {
+	  Boolean is_in = $2;
+	  int numargs = $4;
+	  if (numargs >= 1) {
+	    ODB_Tree *target = $1;
+	    $$ = ODBOPER2(is_in?ODB_IN:ODB_NOTIN,target,&numargs);
+	  }
+	  else { /* No args ==> warning */
+	    double numba = is_in ? 0 : 1; /* always false/true */
+	    SETMSG1("expression %s ( )-statement expects at least one argument.",
+		    is_in ? "IN" : "NOTIN");
+	    YYwarn(0,msg);
+	    $$ = ODBOPER1(ODB_NUMBER, &numba);
+	  }
+	}
+	| expr infile_notinfile filename {
+	  ODB_Tree *expr = $1;
+	  char *filename = STRDUP($3);
+	  $$ = ODBOPER3(ODB_FILE,$2 ? "InFile" : "NotInFile",filename,expr);
+	}
+	;
+
+infile_notinfile	: ODB_INFILE			{ $$ = 1; }
+			| ODB_NOTINFILE			{ $$ = 0; }
+			;
+
+in_notin: ODB_IN			{ $$ = 1; }
+	| ODB_NOTIN			{ $$ = 0; }
+	;
+
+opt_inc : /* empty */			{ $$ = ODBOPER1(ODB_NUMBER,&YACC_IncOne);  }
+	| ODB_COLON expr		{ $$ = $2; }
+	; 
+
+opt_selinc : /* empty */		{ $$ = ODBOPER1(ODB_NUMBER,&YACC_IncOne);  }
+	| ODB_COLON formula		{ $$ = $2; }
+	; 
+
+filename: ODB_STRING			{ $$ = $1; }
+	| ODB_LP ODB_STRING ODB_RP	{ $$ = $2; }
+	;
+
+uniqlist: /* empty */			{ $$ = 0; }
+	| arrname			{ $$ = $1; }
+	| const_expr			{ 
+		char *s; ALLOC(s,50); sprintf(s,"%.20g",$1); ODB_pushstr(s);
+		$$ = 1;
+	}
+	| uniqlist ODB_COMMA arrname	{ $$ = $1 + $3; }
+	| uniqlist ODB_COMMA const_expr	{ 
+		char *s; ALLOC(s,50); sprintf(s,"%.20g",$3); ODB_pushstr(s);
+		$$ = $1 + 1; 
+	}
+	| uniqlist ODB_COMMA		{ $$ = $1; }
+	;
+
+fromlist: /* empty */			{ $$ = 0; }
+	| arrname			{ $$ = $1; }
+	| fromlist ODB_COMMA arrname	{ $$ = $1 + $3; }
+	| fromlist ODB_COMMA		{ $$ = $1; }
+	;
+
+indexname : name			{ ODB_pushstr($1); $$ = 1; }
+	  ;
+
+indexlist : /* empty */				{ $$ = 0;  }
+	  | indexname				{ $$ = $1; }
+	  | indexlist ODB_COMMA indexname	{ $$ = $1 + $3; }
+	  | indexlist ODB_COMMA			{ $$ = $1; }
+	  ;
+
+indexcols : /* empty */		        { $$ = 0;  }
+	  | ODB_LP indexlist ODB_RP	{ $$ = $2; }
+	  ;
+
+sellist : selname			{ $$ = $1; }
+	| sellist ODB_COMMA selname { 
+		Selectdef_t *sdef = $3;
+		sdef->next = $1;
+		$$ = sdef;
+	}
+	| sellist ODB_COMMA		{ $$ = $1; }
+	;
+
+selname : formula opt_sel_param { 
+                static int colid = 0;
+		int mode = $2;
+		Boolean readonly_flag =
+		  IS_SET(mode,ODBURO_EMPTY) ? readonly_mode : IS_SET(mode,ODBREADONLY);
+		ODB_Tree *expr = $1;
+		Boolean is_name = (expr && expr->what == ODB_NAME);
+		Boolean is_aggr = (expr && expr->what == ODB_FUNCAGGR);
+		Selectdef_t *sdef;
+		int j, n = is_name ? expr->argc : 1;
+		ODB_Symbol *nick = NULL;
+		/* fprintf(stderr,"selexpr opt_sel_param : is_name = %d, n=%d\n",(int)is_name, n); */
+		CALLOC(sdef, 1);
+		sdef->nselect = n;
+		ALLOC(sdef->select_items, n);
+		ALLOC(sdef->readonly, n);
+		CALLOC(sdef->sel, n);
+		if (IS_SET(mode,ODBAS)) { /* Nicknames */
+		  char *s = ODB_popstr();
+		  if (n > 1) { /* not applicable/bad if n > 1 */
+		    SETMSG1("Multiple colnames in 'SELECT arrayname[lo:hi] AS %s' cannot have the same nickname",s);
+		    YYerror(msg); /* Abort */
+		  }
+		  /* Replace possible ODB_tag_delim's with blanks */
+		  {
+		    const char *tag_delim = ODB_tag_delim;
+		    if (tag_delim) {
+		      char *ss = s;
+		      while (*ss) {
+			if (*ss == *tag_delim) *ss = ' ';
+			++ss;
+		      }
+		    }
+		  }
+		  nick = ODB_new_symbol(ODB_NICKNAME, s);
+		  for (j=0; j<n; j++) sdef->sel[j].nicksym = nick;
+		}
+		if (!is_name) {
+		  char *first_char = STRDUP(FORMULA_CHAR); /* first_char free'd inside the dump_s */
+		  Boolean subexpr_is_aggrfunc = 0;
+		  /* Search also subexpression for ODB_FUNCAGGR, since that's disallowed */ 
+		  char *formula = dump_s(first_char,expr,ddl_piped ? 2 : 0,&subexpr_is_aggrfunc);
+		  char *f;
+		  int nsym = 0;
+		  int ncols_aux = 0;
+		  /* filter formula : change xxx_distinct(z) into xxx(distinct z) */
+		  while ( (f = strstr(formula,"_distinct(")) != NULL ) { f[0] = '('; f[9] = ' '; }
+		  /* filter formula : change count(1) into count(*) */
+		  while ( (f = strstr(formula,"count(1)")) != NULL ) { f[6] = '*'; }
+		  sdef->sel[0].expr = expr;
+		  sdef->sel[0].aggr_flag = is_aggr ? ODB_which_aggr(expr, &ncols_aux) : ODB_AGGR_NONE;
+		  sdef->sel[0].formula = formula;
+		  sdef->sel[0].ncols_aux = ncols_aux;
+		  if (subexpr_is_aggrfunc) {
+		    SETMSG1("Sub-expression in SELECT-column '%s' cannot be an aggregate function",
+			    formula+1);
+		    YYerror(msg);
+		  }
+		  sdef->sel[0].nsym = nsym = ODB_trace_symbols(expr,NULL,1);
+		  if (nsym > 0) {
+		    ALLOC(sdef->sel[0].sym, nsym);
+		    for (j=nsym-1; j>=0; j--) {
+		      char *s = ODB_popstr();
+		      /* The following symbol may still have "@"'s or "."'s [if ODB_NAME] */
+		      int what = IS_HASH(s) ? ODB_HASHNAME : 
+			  (IS_DOLLAR(s) ? ODB_USDNAME : (IS_BSNUM(s) ? ODB_BSNUM : ODB_NAME));
+		      sdef->sel[0].sym[j] = ODB_new_symbol(what, s);
+		    }
+		  }
+		  else { /* No symbols; just scalars (or functions) etc. */
+		    sdef->sel[0].nsym = 0;
+		    sdef->sel[0].sym = NULL;
+		  }
+		  if (!nick) {
+		    char *f1 = dump_s(NULL,expr,3,NULL);
+		    /* Skip over "_" if an aggregate function was in concern */
+		    int add = is_aggr ? 1 : 0;
+		    /* filter formula : change xxx_distinct(z) into xxx(distinct z) */
+		    while ( (f = strstr(f1,"_distinct(")) != NULL ) { f[0] = '('; f[9] = ' '; }
+		    /* filter formula : change count(1) into count(*) */
+		    while ( (f = strstr(f1,"count(1)")) != NULL ) { f[6] = '*'; }
+		    nick = ODB_new_symbol(ODB_NICKNAME, f1 + add);
+		    sdef->sel[0].nicksym = nick;
+		  }
+		  sdef->readonly[0] = 1; /* Always unconditionally R/O */
+		  sdef->select_items[0] = formula;
+		}
+		else {
+		  for (j=0; j<n; j++) {
+		    ODB_Symbol *psym = expr->argv[j];
+		    char *s = psym->name;
+		    /* fprintf(stderr,"YACC(from ARRNAME): argv[%d] -> '%s'\n",j,s); */
+		    sdef->select_items[j] = STRDUP(s);
+		    sdef->readonly[j] = readonly_flag;
+		    sdef->sel[j].expr = NULL; /* by default */
+		    sdef->sel[j].nicksym = nick ? nick : psym;
+		  }
+		}
+		sdef->next = NULL;
+		++colid;
+		$$ = sdef;
+	}
+        | string opt_sel_param  {
+                int mode = $2;
+		Boolean readonly_flag =
+		  IS_SET(mode,ODBURO_EMPTY) ? readonly_mode : IS_SET(mode,ODBREADONLY);
+                Selectdef_t *sdef;
+                const int n = 1;
+                CALLOC(sdef, 1);
+                sdef->nselect = n;
+                ALLOC(sdef->select_items, n);
+                ALLOC(sdef->readonly, n);
+                CALLOC(sdef->sel, n);
+                sdef->select_items[0] = STRDUP($1);
+                sdef->readonly[0] = readonly_flag;
+		if (IS_SET(mode,ODBAS)) { /* Nicknames (... but watch for regular expressions ) */
+		  char *s = ODB_popstr();
+		  ODB_Symbol *nick = ODB_new_symbol(ODB_NICKNAME, s);
+		  sdef->sel[0].nicksym = nick;	    
+		}
+		else {
+		  sdef->sel[0].nicksym = ODB_new_symbol(ODB_NICKNAME,ODB_NickName(1));
+		}
+		/* fprintf(stderr,"---> string='%s',  opt_sel_param=%d\n",$1,$2); */
+                sdef->next = NULL;
+                $$ = sdef;
+        }
+	;
+
+number	: ODB_NUMBER		{ $$ = $1; }
+	| USDname		{
+		char *pname = $1;
+		ODB_Symbol *name = ODB_lookup(ODB_USDNAME,pname,NULL);
+		if (!name) {
+		  SETMSG1("Variable '%s' has not been set",pname);
+		  YYerror(msg);
+		}
+		$$ = name->dval;
+	}
+	;
+
+const_expr	: num_expr { /* Must be able to evaluate into a number */
+		  double numba = 0;
+		  int irc = ODB_evaluate($1,&numba);
+		  if (!irc) {
+		     SETMSG0("Unable to evaluate an expression, which was assumed constant");
+		     YYerror(msg);
+		  }
+		  $$ = numba;
+		}
+		;
+
+arrindex: ODB_LB const_expr ODB_RB {
+		double d = $2; double flr = floor(d);
+		ODB_Arridx *a; ALLOC(a,1);
+		if (d != flr || flr > INT_MAX || flr < -INT_MAX) {
+		  SETMSG1("Invalid array index %g",d);
+		  YYerror(msg);
+		}
+		a->low = flr;
+		a->high = flr;
+		a->inc = 1;
+		a->only_low = 0;
+		a->only_high = 1;
+		$$ = a;
+	}
+	|  ODB_LB const_expr ODB_COLON const_expr ODB_RB {
+		double low = $2; double flrlow = floor(low);
+		double high = $4; double flrhigh = floor(high);
+		ODB_Arridx *a; ALLOC(a,1);
+		if (low  != flrlow  || flrlow  > INT_MAX || flrlow  < -INT_MAX ||
+		    high != flrhigh || flrhigh > INT_MAX || flrhigh < -INT_MAX) {
+		  SETMSG2("Invalid array indices %g:%g found",low,high);
+		  YYerror(msg);
+		}
+		a->low = flrlow;
+		a->high = flrhigh;
+		a->inc = (flrhigh >= flrlow) ? 1 : -1;
+		a->only_low = 0;
+		a->only_high = 0;
+		$$ = a;
+	}
+	|  ODB_LB const_expr ODB_COLON const_expr ODB_COLON const_expr ODB_RB {
+		double low = $2; double flrlow = floor(low);
+		double high = $4; double flrhigh = floor(high);
+		double inc = $6; double flrinc = floor(inc);
+		ODB_Arridx *a; ALLOC(a,1);
+		if (low  != flrlow  || flrlow  > INT_MAX || flrlow  < -INT_MAX ||
+		    high != flrhigh || flrhigh > INT_MAX || flrhigh < -INT_MAX ||
+		    inc  != flrinc  || flrinc  > INT_MAX || flrinc  < -INT_MAX ||
+		    flrinc == 0) {
+		  SETMSG3("Invalid array indices %g:%g:%g found",low,high,inc);
+		  YYerror(msg);
+		}
+		a->low = flrlow;
+		a->high = flrhigh;
+		a->inc = flrinc;
+		a->only_low = 0;
+		a->only_high = 0;
+		$$ = a;
+	}
+	;
+
+opt_table_name	:	/* empty */	{ $$ = STRDUP(""); }
+		| name			{ $$ = $1;	   }
+		;
+
+arrname	: name			{ ODB_pushstr($1); $$ = 1; }
+	| name arrindex	opt_table_name {
+		ODB_Arridx *a = $2;
+		int low = a->low, high = a->high, inc = a->inc;
+		int j, count;
+		int namelen = strlen($1) + strlen($3);
+		count = 0;
+		if (low <= high) {
+		  inc = ABS(inc);
+		  for (j=low; j<=high; j+=inc) {
+		    char *s;
+		    ALLOC(s, namelen + 30);
+		    sprintf(s,"%s_%s%d%s",$1,(j<0) ? "_" : "", ABS(j),$3);
+		    ODB_pushstr(s);
+		    count++;
+		  }
+		} else {
+		  inc = ABS(inc);
+		  for (j=low; j>=high; j-=inc) {
+		    char *s;
+		    ALLOC(s, namelen + 30);
+		    sprintf(s,"%s_%s%d%s",$1,(j<0) ? "_" : "", ABS(j), $3);
+		    ODB_pushstr(s);
+		    count++;
+		  }
+		}
+		if (count == 0) {
+		  SETMSG5("An empty array section definition : %s[%d:%d:%d]%s\n",
+			  $1,a->low,a->high,a->inc,$3);
+		  YYerror(msg);
+		}
+		$$ = count;
+	}
+	;
+
+sortlist: /* empty */			{ $$ = 0; }
+	| arrsort			{ $$ = $1; }
+	| sortlist ODB_COMMA arrsort	{ $$ = $1 + $3; }
+	| sortlist ODB_COMMA		{ $$ = $1; }
+	;
+
+arrsort	: arrname opt_ascdesc { 
+		int j, n = $1;
+		char **s; ALLOC(s,n);
+		for (j=n-1; j>=0; j--) s[j] = ODB_popstr();
+		for (j=0; j<n; j++) {
+		  ODB_pushi($2 * YACC_PlusOne);
+		  ODB_pushstr(s[j]); 
+		}
+		FREE(s);
+		$$ = n; 
+	}
+	| ODB_ADD arrname {  
+		int j, n = $2;
+		char **s; ALLOC(s,n);
+		for (j=n-1; j>=0; j--) s[j] = ODB_popstr();
+		for (j=0; j<n; j++) {
+		  ODB_pushi(YACC_PlusOne);
+		  ODB_pushstr(s[j]); 
+		}
+		FREE(s);
+		$$ = n; 
+	}
+	| ODB_SUB arrname {  
+		int j, n = $2;
+		char **s; ALLOC(s,n);
+		for (j=n-1; j>=0; j--) s[j] = ODB_popstr();
+		for (j=0; j<n; j++) {
+		  ODB_pushi(YACC_MinusOne);
+		  ODB_pushstr(s[j]); 
+		}
+		FREE(s);
+		$$ = n; 
+	}
+	| arrname ODB_ABS opt_ascdesc {  
+		int j, n = $1;
+		char **s; ALLOC(s,n);
+		for (j=n-1; j>=0; j--) s[j] = ODB_popstr();
+		for (j=0; j<n; j++) {
+		  ODB_pushi($3 * ODB_maxcols());
+		  ODB_pushstr(s[j]); 
+		}
+		FREE(s);
+		$$ = n; 
+	}
+	| ODB_ABS ODB_LP arrname ODB_RP opt_ascdesc {  
+		int j, n = $3;
+		char **s; ALLOC(s,n);
+		for (j=n-1; j>=0; j--) s[j] = ODB_popstr();
+		for (j=0; j<n; j++) {
+		  ODB_pushi($5 * ODB_maxcols());
+		  ODB_pushstr(s[j]); 
+		}
+		FREE(s);
+		$$ = n; 
+	}
+	| const_expr {
+		double d = $1;
+		char *s; ALLOC(s,50); sprintf(s,"%.20g",ABS(d)); 
+		ODB_pushi((d >= 0) ? YACC_PlusOne : YACC_MinusOne); 
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	| const_expr ODB_ABS {
+		double d = $1;
+		char *s; ALLOC(s,50); sprintf(s,"%.20g",ABS(d)); 
+		ODB_pushi(((d >= 0) ? YACC_PlusOne : YACC_MinusOne) * ODB_maxcols()); 
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	| ODB_ABS ODB_LP const_expr ODB_RP {
+		double d = $3;
+		char *s; ALLOC(s,50); sprintf(s,"%.20g",ABS(d)); 
+		ODB_pushi(((d >= 0) ? YACC_PlusOne : YACC_MinusOne) * ODB_maxcols()); 
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	| const_expr ascdesc {
+		double d = $1;
+		int ad = $2;
+		char *s; 
+		if (d < 0) {
+		  SETMSG2("The value itself (%g) in ORDERBY-list cannot be negative when using %s",
+			  d, (ad == 1) ? "ASC" : "DESC");
+		  YYerror(msg);
+		}
+		ALLOC(s,50); sprintf(s,"%.20g",d); 
+		ODB_pushi((ad == 1) ? YACC_PlusOne : YACC_MinusOne);
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	| const_expr ODB_ABS ascdesc {
+		double d = $1;
+		int ad = $3;
+		char *s; 
+		if (d < 0) {
+		  SETMSG2("The value itself (%g) in ORDERBY-list cannot be negative when using %s",
+			  d, (ad == 1) ? "ASC" : "DESC");
+		  YYerror(msg);
+		}
+		ALLOC(s,50); sprintf(s,"%.20g",d); 
+		ODB_pushi(((ad == 1) ? YACC_PlusOne : YACC_MinusOne) * ODB_maxcols());
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	| ODB_ABS ODB_LP const_expr ODB_RP ascdesc {
+		double d = $3;
+		int ad = $5;
+		char *s; 
+		if (d < 0) {
+		  SETMSG2("The value itself (%g) in ORDERBY-list cannot be negative when using %s",
+			  d, (ad == 1) ? "ASC" : "DESC");
+		  YYerror(msg);
+		}
+		ALLOC(s,50); sprintf(s,"%.20g",d); 
+		ODB_pushi(((ad == 1) ? YACC_PlusOne : YACC_MinusOne) * ODB_maxcols());
+		ODB_pushstr(s);
+		$$ = 1;
+	}
+	;
+
+opt_ascdesc  : /* empty */ { $$ =  1; }
+	     | ascdesc	   { $$ = $1; }	
+	     ;
+
+ascdesc	  : ODB_ASC	   { $$ =  1; }	
+	  | ODB_DESC	   { $$ = -1; }
+	  ;
+
+decllist: /* empty */			{ $$ = 0; }
+	| decl				{ $$ = $1; }
+	| decllist ODB_COMMA decl	{ $$ = $1 + $3; }
+	| decllist ODB_COMMA		{ $$ = $1; }
+	| ODB_LP decllist ODB_RP	{ $$ = $2; }
+	; 
+
+decl	: name type		{
+		ODB_Type   *type = ODB_new_type($2, 1);
+		ODB_Symbol *name = ODB_new_symbol(ODB_NAME, $1);
+		ODB_pushstr($2); /* type string to stack */
+		ODB_pushstr($1); /* member name string to stack */
+		$$ = 1; 
+	}
+	| name arrindex type {
+		ODB_Arridx *a = $2;
+		int low = a->low, high = a->high, inc = a->inc;
+		int j, count;
+		int  namelen = strlen($1);
+		ODB_Type *type = ODB_new_type($3, 1);
+		count = 0;
+		if (a->only_high) { /* A special case */
+		  if (high > 0)      { low =  1; inc =  1; }
+		  else if (high < 0) { low = -1; inc = -1; }
+		  else /* error */   { 
+		    SETMSG2("A zero length type definition with array section : %s %s[0]\n",
+			   $3, $1);
+		    YYerror(msg);
+		  }
+		}
+		if (low <= high) {
+		  inc = ABS(inc);
+		  for (j=low; j<=high; j+=inc) {
+		    char *s;
+		    ALLOC(s, namelen + 30);
+		    sprintf(s,"%s_%s%d",$1,(j<0) ? "_" : "", ABS(j));
+		    (void) ODB_new_symbol(ODB_NAME, s);
+		    ODB_pushstr($3); /* type string to stack */
+		    ODB_pushstr(s);  /* member name string to stack */
+		    count++;
+		  }
+		} else {
+		  inc = ABS(inc);
+		  for (j=low; j>=high; j-=inc) {
+		    char *s;
+		    ALLOC(s, namelen + 30);
+		    sprintf(s,"%s_%s%d",$1,(j<0) ? "_" : "", ABS(j));
+		    (void) ODB_new_symbol(ODB_NAME, s);
+		    ODB_pushstr($3); /* type string to stack */
+		    ODB_pushstr(s);  /* member name string to stack */
+		    count++;
+		  }
+		}
+		if (count == 0) {
+		  SETMSG2("An empty type definition with array section : %s %s[???]\n",
+			  $3, $1);
+		  YYerror(msg);
+		}
+		$$ = count;
+	}
+	;
+
+expr	: ODB_LP expr ODB_RP    { $$ = $2; }
+	| ODB_NUMBER		{ $$ = ODBOPER1(ODB_NUMBER,&$1); }
+        | USDname		{ $$ = ODBOPER1(ODB_USDNAME,$1); }
+	| inside		{ $$ = $1; }
+	| near			{ $$ = $1; }
+	| strcmpre		{ $$ = $1; }
+        | HASHname		{ $$ = ODBOPER1(ODB_HASHNAME,$1); }
+        | BSnum			{ $$ = ODBOPER1(ODB_BSNUM,$1); }
+	| strfunc1		{ $$ = $1; }
+	| name ODB_LP arglist ODB_RP opt_table_name { 
+	  /* looking for possible linkoffset/-len(var)@table_name */
+	  char *tblname = $5;
+	  int tblen = STRLEN(tblname);
+	  int numargs = $3;
+	  if (tblen > 0) {
+	    char *fname = $1;
+	    int errcnt = 0;
+	    if (strequ(fname,"linklen") || strequ(fname,"linkoffset")) {
+	      ODB_Tree *expr = ODB_popexpr();
+	      if (numargs == 1 && expr && expr->what == ODB_NAME && expr->argv) {
+		ODB_Symbol *psym = expr->argv[0];
+		char *s = psym->name;
+		char *snew;
+		int slen = strlen(s) + 1 + tblen + 1;
+		ALLOC(snew, slen);
+		snprintf(snew,slen,"%s%s%s",s,IS_TABLE(tblname) ? "" : "@",tblname);
+		expr = ODBOPER1(ODB_NAME, snew);
+		ODB_pushexpr(expr); /* back to stack */
+	      }
+	      else
+		++errcnt;
+	    }
+	    else
+	      ++errcnt;
+	    if (errcnt > 0) {
+	      SETMSG2("If parent table name is given, then the syntax must be : %s or %s",
+		      "linkoffset(child_table)@parent",
+		      "linklen(child_table)@parent");
+	      YYerror(msg);
+	    }
+	  }
+	  $$ = ODBOPER2(ODB_FUNC,$1,&numargs); 
+        }
+        | expr ODB_ADD expr	{ $$ = ODBOPER2(ODB_ADD,$1,$3); }
+        | expr ODB_SUB expr	{ $$ = ODBOPER2(ODB_SUB,$1,$3); }
+        | expr ODB_STAR expr	{ $$ = ODBOPER2(ODB_STAR,$1,$3); }
+        | expr ODB_DIV expr	{ $$ = ODBOPER2(ODB_DIV,$1,$3); }
+	| expr ODB_MODULO expr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"mod",&numargs); }
+	| expr ODB_POWER expr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"pow",&numargs); }
+	| ODB_ADD expr %prec ODB_UNARY_PLUS  { 
+		$$ = $2;
+	}
+	| ODB_SUB expr %prec ODB_UNARY_MINUS { 
+		if (ODB_fixconv($2)) {
+		  $$ = $2;
+		}
+		else {
+		  $$ = ODBOPER1(ODB_UNARY_MINUS,$2); 
+		}
+	}
+        ;
+
+arglist	: /* empty */		 { $$ = 0; }
+	| cond			 { ODB_pushexpr($1);   $$ = 1; }
+	| arglist ODB_COMMA cond { ODB_pushexpr($3);   $$ = $1 + 1; }
+	;
+
+exprlist: expr			  { ODB_pushexpr($1);   $$ = 1; }
+	| exprlist ODB_COMMA expr { ODB_pushexpr($3);   $$ = $1 + 1; }
+	;
+
+matchfunc : ODB_MATCH cond ODB_RP {
+	    ODB_Match_t *match = NULL;
+	    CALLOC(match, 1);
+	    match->expr = $2;
+	    match->formula = dump_s(NULL,match->expr,0,NULL);
+	    match->symexpr = ODBOPER1(ODB_STRING,match->formula);
+	    $$ = match;
+	  }
+	  ;
+
+num_expr: ODB_LP num_expr ODB_RP    { $$ = $2; }
+	| number		    { $$ = ODBOPER1(ODB_NUMBER,&$1); }
+	| name ODB_LP num_arglist ODB_RP { $$ = ODBOPER2(ODB_FUNC,$1,&$3); }
+        | num_expr ODB_ADD num_expr	{ $$ = ODBOPER2(ODB_ADD,$1,$3); }
+        | num_expr ODB_SUB num_expr	{ $$ = ODBOPER2(ODB_SUB,$1,$3); }
+        | num_expr ODB_STAR num_expr	{ $$ = ODBOPER2(ODB_STAR,$1,$3); }
+        | num_expr ODB_DIV num_expr	{ $$ = ODBOPER2(ODB_DIV,$1,$3); }
+	| num_expr ODB_MODULO num_expr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"mod",&numargs); }
+	| num_expr ODB_POWER num_expr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"pow",&numargs); }
+	| ODB_ADD num_expr %prec ODB_UNARY_PLUS  { 
+		$$ = $2;
+	}
+	| ODB_SUB num_expr %prec ODB_UNARY_MINUS { 
+		if (ODB_fixconv($2)) {
+		  $$ = $2;
+		}
+		else {
+		  $$ = ODBOPER1(ODB_UNARY_MINUS,$2); 
+		}
+	}
+        ;
+
+num_arglist : /* empty */		 { $$ = 0; }
+	| num_expr			 { ODB_pushexpr($1);   $$ = 1; }
+	| num_arglist ODB_COMMA num_expr { ODB_pushexpr($3);   $$ = $1 + 1; }
+	;
+
+formula	: selexpr			{ $$ = $1; }
+	| selpred			{ $$ = $1; }
+	;
+
+selpred	: ODB_LP selpred ODB_RP		{ $$ = $2; }
+	| selexpr is_null_or_is_not_null		{
+		int is_what = $2 ? ODB_EQ : ODB_NE;
+		ODB_Tree *arg = $1;
+		int nargs = 1;
+		ODB_pushexpr(arg);
+		{
+		  ODB_Tree *lhs = ODBOPER2(ODB_FUNC,"abs",&nargs);
+		  char *pname = "$mdi";
+		  ODB_Symbol *name = ODB_lookup(ODB_USDNAME,pname,NULL);
+		  double mdi = name ? ABS(name->dval) : ABS(RMDI);
+		  ODB_Tree *rhs = ODBOPER1(ODB_NUMBER,&mdi);
+		  $$ = ODBOPER2(is_what, lhs, rhs);
+		}
+	}
+	| ODB_NOT formula			{ $$ = ODBOPER1(ODB_NOT,$2); }
+	| formula ODB_AND formula		{ $$ = ODBOPER2(ODB_AND,$1,$3); }
+	| formula ODB_OR formula		{ $$ = ODBOPER2(ODB_OR,$1,$3); }
+	| selexpr ODB_BETWEEN selexpr ODB_AND selexpr { $$ = ODBOPER3(ODB_LELE,$3,$1,$5); }
+	| selexpr ODB_GT selexpr		{ $$ = ODBOPER2(ODB_GT,$1,$3); }
+	| selexpr ODB_GE selexpr		{ $$ = ODBOPER2(ODB_GE,$1,$3); }
+	| selexpr eqne selexpr			{ $$ = ODBOPER2($2 ? ODB_EQ : ODB_NE,$1,$3); }
+	| selexpr ODB_IS selexpr		{ $$ = ODBOPER2(ODB_EQ,$1,$3); }
+	| selexpr ODB_LE selexpr		{ $$ = ODBOPER2(ODB_LE,$1,$3); }
+	| selexpr ODB_LT selexpr		{ $$ = ODBOPER2(ODB_LT,$1,$3); }
+	| selexpr ODB_CMP selexpr		{ 
+	  int numargs = 2;
+	  ODB_pushexpr($1); ODB_pushexpr($3);
+	  $$ = ODBOPER2(ODB_FUNC,"cmp",&numargs); 
+	}
+	| selexpr ODB_IS ODB_NOT selexpr	{ $$ = ODBOPER2(ODB_NE,$1,$4); }
+	| selexpr ODB_GT selexpr ODB_GT selexpr	{ $$ = ODBOPER3(ODB_GTGT,$1,$3,$5); }
+	| selexpr ODB_GT selexpr ODB_GE selexpr	{ $$ = ODBOPER3(ODB_GTGE,$1,$3,$5); }
+	| selexpr ODB_GE selexpr ODB_GE selexpr	{ $$ = ODBOPER3(ODB_GEGE,$1,$3,$5); }
+	| selexpr ODB_GE selexpr ODB_GT selexpr	{ $$ = ODBOPER3(ODB_GEGT,$1,$3,$5); }
+	| selexpr ODB_LT selexpr ODB_LT selexpr	{ $$ = ODBOPER3(ODB_LTLT,$1,$3,$5); }
+	| selexpr ODB_LT selexpr ODB_LE selexpr	{ $$ = ODBOPER3(ODB_LTLE,$1,$3,$5); }
+	| selexpr ODB_LE selexpr ODB_LE selexpr	{ $$ = ODBOPER3(ODB_LELE,$1,$3,$5); }
+	| selexpr ODB_LE selexpr ODB_LT selexpr	{ $$ = ODBOPER3(ODB_LELT,$1,$3,$5); }
+	| selexpr in_notin ODB_LP formula ODB_COLON formula opt_selinc ODB_RP {
+	  ODB_Tree *target = $1;
+	  Boolean is_in = $2;
+	  ODB_Tree *begin = $4;
+	  ODB_Tree *end = $6;
+	  ODB_Tree *step = $7;
+	  int j, n = 4;
+	  ODB_Tree **args;
+	  ALLOC(args, n);
+	  args[0] = target;
+	  args[1] = begin;
+	  args[2] = end;
+	  args[3] = step;
+	  for (j=0; j<n; j++) ODB_pushexpr(args[j]);
+	  {
+	    ODB_Tree *f = ODBOPER2(ODB_FUNC,"InGenList",&n);
+	    $$ = is_in ? f : ODBOPER1(ODB_NOT,f);
+	  }
+	  FREE(args);
+	}
+	| selexpr in_notin ODB_LP selarglist ODB_RP {
+	  Boolean is_in = $2;
+	  int numargs = $4;
+	  if (numargs >= 1) {
+	    ODB_Tree *target = $1;
+	    $$ = ODBOPER2(is_in?ODB_IN:ODB_NOTIN,target,&numargs);
+	  }
+	  else { /* No args ==> warning */
+	    double numba = is_in ? 0 : 1; /* always false/true */
+	    SETMSG1("expression %s ( )-statement expects at least one argument.",
+		    is_in ? "IN" : "NOTIN");
+	    YYwarn(0,msg);
+	    $$ = ODBOPER1(ODB_NUMBER, &numba);
+	  }
+	}
+	| formula ODB_QMARK formula ODB_COLON formula { $$ = ODBOPER3(ODB_COND,$1,$3,$5); }
+	;
+
+strfunc1: name ODB_LP string ODB_RP { $$ = ODBOPER2(ODB_STRFUNC1, $1, $3); }
+	;
+
+selexpr	: ODB_LP selexpr ODB_RP	        { $$ = $2; }
+	| selinside			{ $$ = $1; }
+	| selnear			{ $$ = $1; }
+	| strcmpre			{ $$ = $1; }
+	| strfunc1			{ $$ = $1; }
+	| name ODB_LP selarglist ODB_RP	opt_table_name { 
+	  /* looking for possible linkoffset/-len(var)@table_name */
+	  char *tblname = $5;
+	  int tblen = STRLEN(tblname);
+	  int numargs = $3;
+	  if (tblen > 0) {
+	    char *fname = $1;
+	    int errcnt = 0;
+	    if (strequ(fname,"linklen") || strequ(fname,"linkoffset")) {
+	      ODB_Tree *expr = ODB_popexpr();
+	      if (numargs == 1 && expr && expr->what == ODB_NAME && expr->argv) {
+		ODB_Symbol *psym = expr->argv[0];
+		char *s = psym->name;
+		char *snew;
+		int slen = strlen(s) + 1 + tblen + 1;
+		ALLOC(snew, slen);
+		snprintf(snew,slen,"%s%s%s",s,IS_TABLE(tblname) ? "" : "@",tblname);
+		expr = ODBOPER1(ODB_NAME, snew);
+		ODB_pushexpr(expr); /* back to stack */
+	      }
+	      else
+		++errcnt;
+	    }
+	    else
+	      ++errcnt;
+	    if (errcnt > 0) {
+	      SETMSG2("If parent table name is given, then the syntax must be : %s or %s",
+		      "linkoffset(child_table)@parent",
+		      "linklen(child_table)@parent");
+	      YYerror(msg);
+	    }
+	  }
+	  $$ = ODBOPER2(ODB_FUNC,$1,&numargs); 
+	}
+	| name ODB_LP ODB_DISTINCT selarglist ODB_RP { 
+	    $$ = ODBOPER3(ODB_FUNC,$1,&$4,&YACC_distinct); }
+	| name ODB_LP ODB_STAR ODB_RP   { 
+	    int numargs = 0;
+	    $$ = ODBOPER2(ODB_FUNC,$1,&numargs); }
+        | USDname			{ $$ = ODBOPER1(ODB_USDNAME,$1); }
+        | HASHname			{ $$ = ODBOPER1(ODB_HASHNAME,$1); }
+        | BSnum				{ $$ = ODBOPER1(ODB_BSNUM,$1); }
+        | ODB_NUMBER			{ $$ = ODBOPER1(ODB_NUMBER,&$1); }
+        | selexpr ODB_ADD selexpr	{ $$ = ODBOPER2(ODB_ADD,$1,$3); }
+        | selexpr ODB_SUB selexpr	{ $$ = ODBOPER2(ODB_SUB,$1,$3); }
+        | selexpr ODB_STAR selexpr	{ $$ = ODBOPER2(ODB_STAR,$1,$3); }
+        | selexpr ODB_DIV selexpr	{ $$ = ODBOPER2(ODB_DIV,$1,$3); }
+	| selexpr ODB_MODULO selexpr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"mod",&numargs); }
+	| selexpr ODB_POWER selexpr { 
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"pow",&numargs); }
+	| ODB_ADD selexpr %prec ODB_UNARY_PLUS  { 
+		$$ = $2;
+	}
+	| ODB_SUB selexpr %prec ODB_UNARY_MINUS { 
+		if (ODB_fixconv($2)) {
+		  $$ = $2;
+		}
+		else {
+		  $$ = ODBOPER1(ODB_UNARY_MINUS,$2); 
+		}
+	}
+	| selexpr ODB_DOTP selexpr {
+		int numargs = 2;
+		ODB_pushexpr($1); ODB_pushexpr($3);
+		$$ = ODBOPER2(ODB_FUNC,"dotp",&numargs);
+	}	
+	| ODB_NORM selexpr ODB_NORM { /* | x | i.e. sqrt(dotp(x,x)) */
+		int numargs = 2;
+		ODB_pushexpr($2); ODB_pushexpr($2);
+		$$ = ODBOPER2(ODB_FUNC,"norm",&numargs);
+	}	
+	| ODB_NORM selexpr ODB_COMMA selexpr ODB_NORM { /* | x, y | or i.e. sqrt(x .* x) */
+		int numargs = 2;
+		ODB_pushexpr($2); ODB_pushexpr($4);
+		$$ = ODBOPER2(ODB_FUNC,"norm",&numargs);
+	}	
+        ;
+
+selarglist : /* empty */		 { $$ = 0; }
+	| formula			 { ODB_pushexpr($1);   $$ = 1; }
+	| selarglist ODB_COMMA formula	 { ODB_pushexpr($3);   $$ = $1 + 1; }
+	;
+
+alignlist : /* empty */			{ $$ = 0; }
+	| arrname			{ $$ = $1; }
+	| alignlist ODB_COMMA arrname	{ $$ = $1 + $3; }
+	;
+
+USDname	: ODB_USDNAME		{ $$ = $1; }
+	;
+
+extUSDname : USDname		{ $$ = $1; }
+	   | name		{
+	     char *s = $1;
+	     int slen;
+	     /* Check that no '.' or '@' exist in the "name",
+	        since they are invalid in USDname-proper */
+	     if (strchr(s,'.') || strchr(s,'@')) {
+		SETMSG1("Parameter '%s' cannot contain '.' or '@' characters in this context",s);
+		YYerror(msg);
+	     }
+	     /* Now prepend with a 'dollar'-sign and return */
+	     slen = strlen(s);
+	     ALLOC(s,slen+2);
+	     sprintf(s,"$%s",$1);
+	     $$ = s; 
+	   }
+	;
+
+HASHname: ODB_HASHNAME		{ $$ = $1; }
+	;
+
+BSnum	: ODB_BSNUM		{ $$ = $1; }
+	;
+
+string	: ODB_STRING		{ $$ = $1; }
+	| string ODB_STRING	{
+	  int len = STRLEN($1) + STRLEN($2) + 1;
+	  char *s = NULL;
+	  ALLOC(s, len);
+	  snprintf(s,len,"%s%s",$1,$2);
+	  $$ = s;	  
+	}
+	;
+
+opt_arglist : /* empty */       { $$ =  0; }
+	    | ODB_COMMA	arglist { $$ = $2; }
+	    ;
+
+query	: ODB_SELECT string ODB_RP {
+	  /* Usage f.ex. : obstype IN ( SELECT "distinct obstype FROM hdr" ) */
+	  int len = STRLEN("SELECT ") + STRLEN($2) + 1;
+	  char *poolmask = "-1";
+	  char *db = getenv("ODB98_DBPATH"); /* see odb/scripts/odbsql */
+	  char *query = NULL;
+	  int numargs = 0;
+	  ALLOC(query, len);
+	  snprintf(query,len,"SELECT %s",$2);
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	| ODB_QUERY string opt_arglist ODB_RP {
+	  /* Usage f.ex. : a IN query("set $x=1; select a from t where c = $x") */
+	  char *poolmask = "-1";
+	  char *db = getenv("ODB98_DBPATH"); /* see odb/scripts/odbsql */
+	  char *query = $2;
+	  int numargs = $3;
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	| ODB_QUERY string ODB_COMMA string opt_arglist ODB_RP {
+	  /* Usage f.ex. : codetype IN query("/data/base/XYZ", "select codetype from hdr") */
+	  /*      or     : codetype IN query("1-10,16,20", "select codetype from hdr") */
+	  char *arg2 = $2;
+	  Boolean poolmask_given = (*arg2 == '-' || *arg2 == ',' || isdigit(*arg2)) ? 1 : 0;
+	  char *poolmask = poolmask_given ? arg2 : "-1";
+	  char *db = poolmask_given ? getenv("ODB98_DBPATH") : arg2;
+	  char *query = $4;
+	  int numargs = $5;
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	| ODB_QUERY const_expr ODB_COMMA string ODB_COMMA string opt_arglist ODB_RP {
+	  /* Usage f.ex. : sensor IN query(7, "/data/base/XYZ", "select distinct sensor from hdr") */
+	  char poolmask[80];
+	  double poolno = $2;
+	  char *db = $4;
+	  char *query = $6;
+	  int numargs = $7;
+	  snprintf(poolmask,sizeof(poolmask),"%.0f", poolno);
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	| ODB_QUERY string ODB_COMMA string ODB_COMMA string opt_arglist ODB_RP {
+	  /* Usage f.ex. : sensor IN query("1-10,16,20", "/data/base/XYZ", "select distinct sensor from hdr") */
+	  char *poolmask = $2;
+	  char *db = $4;
+	  char *query = $6;
+	  int numargs = $7;
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	| ODB_QUERY const_expr ODB_COMMA string opt_arglist ODB_RP {
+	  /* Usage f.ex. : a IN query(7, "set $x=1; select a from t where c = $x") */
+	  char poolmask[80];
+	  double poolno = $2;
+	  char *db = getenv("ODB98_DBPATH"); /* see odb/scripts/odbsql */
+	  char *query = $4;
+	  int numargs = $5;
+	  snprintf(poolmask,sizeof(poolmask),"%.0f", poolno);
+	  $$ = ODBOPER4(ODB_QUERY, poolmask, db, query, &numargs);
+	}
+	;
+
+type	: ODB_NAME		{ $$ = $1; }
+	| ODB_TYPEOF ODB_LP name ODB_RP {
+	  char *arg = $3;
+	  char *x = NULL;
+	  char *s = STRDUP(arg);
+	  char *tblname = strchr(s,'@');
+	  ODB_Table *ptable = NULL;
+	  if (tblname) {
+	    *tblname++ = '\0';
+	    ptable = ODB_lookup_table(tblname,NULL);
+	    if (!ptable) {
+	      SETMSG2("Reference to undefined table '%s' in TYPEOF(%s)",tblname,arg);
+	      YYerror(msg);
+	    }
+	    else {
+	      int index = -1;
+	      if (ODB_in_table(ODB_NAME, s, ptable, &index) && index >= 0) {
+	        x = STRDUP(ptable->type[index]->type->name);
+	      }
+	      else {
+	        SETMSG3("Unable to locate item '%s' from table '%s' in TYPEOF(%s)",s,tblname,arg);
+	        YYerror(msg);
+	      }
+	    }
+	  }
+	  if (!ptable) { /* Find table */
+	    int count = 0;
+	    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	      if (ODB_in_table(ODB_NAME, s, ptable, NULL)) count++;
+	    }
+	    if (count == 0) {
+	      SETMSG2("Unable to locate table for item '%s' in TYPEOF(%s)",s,arg);
+	      YYerror(msg);
+	    }
+	    if (count > 1) {
+	      SETMSG3("Item '%s' in TYPEOF(%s) found in %d tables, but must be unambiguous",s,arg,count);
+	      YYerror(msg);
+	    }
+	    for (ptable = ODB_start_table(); ptable != NULL; ptable = ptable->next) {
+	      int index = -1;
+	      if (ODB_in_table(ODB_NAME, s, ptable, &index) && index >= 0) {
+	        x = STRDUP(ptable->type[index]->type->name);
+	        break;
+	      }
+	    }
+	    if (!ptable) {
+	      SETMSG2("Unable to locate table for item '%s' in TYPEOF(%s)",s,arg);
+	      YYerror(msg);
+	    }
+	  }
+	  FREE(s);
+	  if (!x) {
+	    SETMSG1("Cannot resolve item or table in TYPEOF(%s)",arg);
+	    YYerror(msg);
+	  }
+	  $$ = x;
+	}
+	;
+
+name	: ODB_NAME		{ $$ = STRDUP($1); }
+	;
+
+align	: ODB_ALIGN		{ $$ = '@'; }
+	| ODB_ONELOOPER		{ $$ = '='; }
+	| ODB_SHAREDLINK	{ $$ = '&'; }
+	;
+
+is_null_or_is_not_null	: ODB_IS ODB_NULL	  { $$ = 1; }
+			| ODB_IS ODB_NOT ODB_NULL { $$ = 0; }
+			;
+
+idxname : name	      { $$ = $1; }
+	;
+
+opt_idxname : /* empty */ { $$ = NULL; }
+	    | idxname     { $$ = $1; }
+	    | ODB_STAR    { $$ = STRDUP("*"); }
+	    | string      { $$ = $1; /* Already STRDUP'ped in lex.l */ }
+	    ;
+
+opt_using   : /* empty */ { $$ = 0; }
+	    | ODB_USING	  { $$ = 1; }
+	    ;
+
+dbcred : string      { $$ = $1; /* Already STRDUP'ped in lex.l */ }
+       | name	     { $$ = $1; }
+       ;
diff --git a/odb/src/ddl.CCMA/CCMA.ddl b/odb/src/ddl.CCMA/CCMA.ddl
new file mode 100644
index 0000000..d0660f5
--- /dev/null
+++ b/odb/src/ddl.CCMA/CCMA.ddl
@@ -0,0 +1,3 @@
+#define CCMA
+
+#include "cma.h"
diff --git a/odb/src/ddl.CCMA/CCMA.dep b/odb/src/ddl.CCMA/CCMA.dep
new file mode 100644
index 0000000..fe62695
--- /dev/null
+++ b/odb/src/ddl.CCMA/CCMA.dep
@@ -0,0 +1,139 @@
+#-- Last updated:  07-Feb-2000
+
+DDLS=\
+	CCMA.ddl \
+	CMA.inc \
+	mdi.inc \
+	obstype.inc \
+	varno.inc \
+	vertco_type.inc \
+	ppcode.inc \
+	sensor.inc \
+	blacklist.inc
+
+TABLES=\
+	desc \
+	ddrs \
+	index \
+	hdr \
+	sat \
+        reo3 \
+	rtovs \
+	rtovs_slev \
+	rtovs_mlev \
+	rtovs_pred \
+	atovs \
+	atovs_pred \
+	body \
+	errstat \
+	update
+
+VIEWS=\
+	date_time \
+	ddrdata \
+	ecset \
+	getsatid \
+	getsatobid \
+	get_soe_reo3 \
+	matchup_atovs_pred \
+	matchup_body \
+	matchup_gbrad \
+	matchup_hdr \
+	mkglobstab \
+	mkglobstab_atovs \
+	mkglobstab_gpsro \
+	mobhdrca_obsort \
+	obatabs_robhdr \
+	obatabs_robody \
+	obs_boxes \
+	obsortca_auxiliary \
+	obsortca_body \
+	obsortca_errstat \
+	obsortca_hdr \
+	obsortca_hdr2auxiliary_body \
+	obsortca_hdr2body \
+	obsortca_index \
+	obsortca_update \
+	prtgom \
+	robhdr \
+	robhdr_screen \
+	robhdr_tc \
+	robhdrca_obsort \
+	robody \
+	robody_0 \
+	robody_1 \
+	robody_tc \
+	robody_traj \
+	sat_atovs \
+	sat_rtovs \
+	sat_rtovs_mlev \
+	suobarea \
+	suobarea_sat \
+	suobarea_satob \
+	update_ddrs \
+	prtdpst_robhdr \
+	prtdpst_robody \
+	matchup_rtovs_pred \
+	caifc1 \
+        camelo_robhdr \
+        camelo_robody \
+        canaco_robhdr \
+        canaco_robody \
+        cancer_robhdr \
+        cancer_robody \
+        cantik_robhdr \
+        cantik_robody \
+        carcfo \
+        castor \
+        caviso_robhdr \
+        caviso_robody \
+        cavodk_robhdr \
+        cavodk_robody \
+        hop_canari_robhdr \
+        hop_canari_robody \
+	canaco_robhdr_ccma \
+	satbody_radar \
+	sathdr_radar \
+	obsort_hdr2radar_body \
+	obstat_radrefl \
+	obstat_radhure \
+	pertcma \
+	sat_radar \
+	time_numtsl \
+	setup_tovscv \
+	setup_tovscv_cloud_sink \
+	getsatid_resat \
+	hop_canari_conv \
+	robhdr_screen_conv \
+	global_enkf_105 \
+	global_enkf_110 \
+	global_enkf_115 \
+	global_enkf_120 \
+	sugoms \
+	suobarea_scatt \
+	update_hprior_101 \
+	update_hprior_102 \
+	update_hprior_103 \
+	update_hprior_104 \
+	update_hprior_105 \
+	update_hprior_106 \
+	update_hprior_107 \
+	update_hprior_108 \
+	update_hprior_109 \
+	update_hprior_110 \
+	update_hprior_111 \
+	update_hprior_112 \
+	update_hprior_113 \
+	update_hprior_114 \
+	update_hprior_115 \
+	update_hprior_116 \
+	update_hprior_117 \
+	update_hprior_118 \
+	update_hprior_119 \
+	update_hprior_120
+	obsort_gnssro_body \
+	obsort_hdr2gnssro_body \
+	obsort_hdr2scatt_body \
+	matchup_gbrad \
+	matchup_raingg
+
diff --git a/odb/src/ddl.CCMA/CMakeLists.txt b/odb/src/ddl.CCMA/CMakeLists.txt
new file mode 100644
index 0000000..ce82ea7
--- /dev/null
+++ b/odb/src/ddl.CCMA/CMakeLists.txt
@@ -0,0 +1,427 @@
+set(sources
+
+    CCMA.ddl
+
+    aeolus.h
+    allsky.h
+    auxiliary.h
+    body.h
+    cloud_sink.h
+    cma.h
+    collocated_imager_information.h
+    conv.h
+    ensemble.h
+    errstat.h
+    forecast_diagnostic.h
+    gbrad.h
+    gnssro.h
+    hdr.h
+    idx.h
+    limb.h
+    mdi.h
+    modsurf.h
+    obstype.h
+    ppcode.h
+    radar.h
+    radar_station.h
+    radiance.h
+    raingg.h
+    resat.h
+    sat.h
+    satob.h
+    scatt.h
+    sensor.h
+    smos.h
+    ssmi1d.h
+    surfbody_feedback.h
+    type_definitions.h
+    update.h
+    varno.h
+    vertco_type.h
+)
+
+set(views
+
+    adjust_ccma_distribid.sql
+    adjust_seqnos.sql
+    ak_resat_averaging_kernel.sql
+    amv.sql
+    amv2.sql
+    amv_flag.sql
+    amv_flag2.sql
+    caifc1.sql
+    camelo_robhdr.sql
+    camelo_robody.sql
+    canaco_robhdr.sql
+    canaco_robhdr_ccma.sql
+    canaco_robody.sql
+    cancer_robhdr.sql
+    cancer_robody.sql
+    cantik_robhdr.sql
+    cantik_robody.sql
+    carcfo.sql
+    castor.sql
+    caviso_robhdr.sql
+    caviso_robody.sql
+    cavodk_robhdr.sql
+    cavodk_robody.sql
+    conv_hdr.sql
+    data_radar_station.sql
+    date_time.sql
+    ecmwf_matchup_allsky_body.sql
+    ecmwf_matchup_body.sql
+    ecmwf_matchup_gbrad.sql
+    ecmwf_matchup_hdr.sql
+    ecmwf_matchup_raingg.sql
+    ecmwf_matchup_update_1.sql
+    ecmwf_matchup_update_2.sql
+    ecmwf_matchup_update_3.sql
+    ecmwf_matchupsink.sql
+    ecset.sql
+    exp_info_1.sql
+    fc_sens_obs.sql
+    fcq_robhdr_0.sql
+    fcq_robhdr_1.sql
+    fcq_robhdr_2.sql
+    fcq_robody_0.sql
+    fcq_robody_1.sql
+    fcq_robody_2.sql
+    fix_date_and_time.sql
+    fixresatlen.sql
+    gather4poolmask.sql
+    gather4poolmask_counts.sql
+    gbrad_body_rr.sql
+    gbrad_rr.sql
+    get_soe_resat.sql
+    getgbradid.sql
+    getlimbid.sql
+    getsatid.sql
+    getsatid_resat.sql
+    getsatobid.sql
+    getsfcobsid.sql
+    global_enkf_1.sql
+    global_enkf_10.sql
+    global_enkf_100.sql
+    global_enkf_105.sql
+    global_enkf_110.sql
+    global_enkf_115.sql
+    global_enkf_120.sql
+    global_enkf_15.sql
+    global_enkf_2.sql
+    global_enkf_20.sql
+    global_enkf_25.sql
+    global_enkf_3.sql
+    global_enkf_30.sql
+    global_enkf_35.sql
+    global_enkf_4.sql
+    global_enkf_40.sql
+    global_enkf_45.sql
+    global_enkf_5.sql
+    global_enkf_50.sql
+    global_enkf_55.sql
+    global_enkf_60.sql
+    global_enkf_65.sql
+    global_enkf_70.sql
+    global_enkf_75.sql
+    global_enkf_80.sql
+    global_enkf_85.sql
+    global_enkf_90.sql
+    global_enkf_95.sql
+    hop_canari_conv.sql
+    hop_canari_robhdr.sql
+    hop_canari_robody.sql
+    hretr_canari_robody.sql
+    hretr_canari_satbody.sql
+    manda_gene_body.sql
+    manda_gene_hdr.sql
+    manda_laelalo.sql
+    matchup_allsky_body.sql
+    matchup_atovs_pred.sql
+    matchup_body.sql
+    matchup_gbrad.sql
+    matchup_hdr.sql
+    matchup_raingg.sql
+    matchup_sensorlist.sql
+    matchup_update_1.sql
+    matchup_update_10.sql
+    matchup_update_2.sql
+    matchup_update_3.sql
+    matchup_update_4.sql
+    matchup_update_5.sql
+    matchup_update_6.sql
+    matchup_update_7.sql
+    matchup_update_8.sql
+    matchup_update_9.sql
+    matchupsink.sql
+    mkglobstab.sql
+    mkglobstab_gpsro.sql
+    mobhdrca_obsort.sql
+    obatabs_robhdr.sql
+    obs_boxes.sql
+    obsdist.sql
+    obsdist_allsky.sql
+    obsdist_allsky_body.sql
+    obsdist_auxiliary.sql
+    obsdist_auxiliary_body.sql
+    obsdist_body.sql
+    obsdist_errstat.sql
+    obsdist_gbrad.sql
+    obsdist_gbrad_body.sql
+    obsdist_hdr.sql
+    obsdist_hdr2allsky_body.sql
+    obsdist_hdr2auxiliary_body.sql
+    obsdist_hdr2body.sql
+    obsdist_hdr2gbrad_body.sql
+    obsdist_hdr2radar_body.sql
+    obsdist_hdr2radiance_body.sql
+    obsdist_hdr2raingg_body.sql
+    obsdist_hdr2resat_averaging_kernel.sql
+    obsdist_index.sql
+    obsdist_index2hdr.sql
+    obsdist_limb.sql
+    obsdist_modsurf.sql
+    obsdist_poolno.sql
+    obsdist_radar.sql
+    obsdist_radar_body.sql
+    obsdist_radar_station.sql
+    obsdist_radiance.sql
+    obsdist_radiance_body.sql
+    obsdist_raingg.sql
+    obsdist_raingg_body.sql
+    obsdist_resat.sql
+    obsdist_resat_averaging_kernel.sql
+    obsdist_sat.sql
+    obsdist_satob.sql
+    obsdist_update_1.sql
+    obsdist_update_10.sql
+    obsdist_update_2.sql
+    obsdist_update_3.sql
+    obsdist_update_4.sql
+    obsdist_update_5.sql
+    obsdist_update_6.sql
+    obsdist_update_7.sql
+    obsdist_update_8.sql
+    obsdist_update_9.sql
+    obsdist_windows.sql
+    obshor.sql
+    obsort_gnssro_body.sql
+    obsort_hdr2allsky_body.sql
+    obsort_hdr2auxiliary_body.sql
+    obsort_hdr2gbrad_body.sql
+    obsort_hdr2gnssro_body.sql
+    obsort_hdr2radar_body.sql
+    obsort_hdr2raingg_body.sql
+    obsort_hdr2scatt_body.sql
+    obsortca_auxiliary.sql
+    obsortca_body.sql
+    obsortca_errstat.sql
+    obsortca_hdr.sql
+    obsortca_hdr2auxiliary_body.sql
+    obsortca_hdr2body.sql
+    obsortca_index.sql
+    obsortca_update_1.sql
+    obsortca_update_2.sql
+    obsortca_update_3.sql
+    odb_info.sql
+    poolmask_1.sql
+    poolmask_2.sql
+    prtdpst_robhdr.sql
+    prtdpst_robody.sql
+    raingg_body_rr.sql
+    raingg_rr.sql
+    revmatchup_body.sql
+    revmatchup_hdr.sql
+    robhdr.sql
+    robhdr_gbrad_get_rr.sql
+    robhdr_gbrad_put_rr.sql
+    robhdr_grid_distribute.sql
+    robhdr_rad.sql
+    robhdr_raingg_get_rr.sql
+    robhdr_raingg_put_rr.sql
+    robhdr_screen.sql
+    robhdr_screen_conv.sql
+    robhdr_tc.sql
+    robhdrca_obsort.sql
+    robody.sql
+    robody_gbrad_get_rr.sql
+    robody_gbrad_put_rr.sql
+    robody_rad.sql
+    robody_raingg_get_rr.sql
+    robody_raingg_put_rr.sql
+    robody_tc.sql
+    robody_traj.sql
+    sat_aeolus.sql
+    sat_atovs.sql
+    sat_gpsro.sql
+    sat_lrad.sql
+    sat_radar.sql
+    sat_satob.sql
+    sat_ssmi.sql
+    satbody_allsky.sql
+    satbody_atovs.sql
+    satbody_gpsro.sql
+    satbody_radar.sql
+    sathdr_cloud_sink.sql
+    sathdr_radar.sql
+    scatt.sql
+    scatt_flag.sql
+    set_active.sql
+    set_active_smos.sql
+    setup_tovscv.sql
+    setup_tovscv_cloud_sink.sql
+    small.sql
+    stat_obs_1.sql
+    sugoms.sql
+    suobarea.sql
+    suobarea_limb.sql
+    suobarea_sat.sql
+    suobarea_satob.sql
+    suobarea_scatt.sql
+    suobsaddr.sql
+    suobscor_robhdr.sql
+    suobscor_robody.sql
+    suvarbc_robhdr_0.sql
+    suvarbc_robody_0.sql
+    time_info.sql
+    time_numtsl.sql
+    tslot.sql
+    update_desc_1.sql
+    update_desc_2.sql
+    update_enkf_links.sql
+    update_hprior_1.sql
+    update_hprior_10.sql
+    update_hprior_100.sql
+    update_hprior_101.sql
+    update_hprior_102.sql
+    update_hprior_103.sql
+    update_hprior_104.sql
+    update_hprior_105.sql
+    update_hprior_106.sql
+    update_hprior_107.sql
+    update_hprior_108.sql
+    update_hprior_109.sql
+    update_hprior_11.sql
+    update_hprior_110.sql
+    update_hprior_111.sql
+    update_hprior_112.sql
+    update_hprior_113.sql
+    update_hprior_114.sql
+    update_hprior_115.sql
+    update_hprior_116.sql
+    update_hprior_117.sql
+    update_hprior_118.sql
+    update_hprior_119.sql
+    update_hprior_12.sql
+    update_hprior_120.sql
+    update_hprior_13.sql
+    update_hprior_14.sql
+    update_hprior_15.sql
+    update_hprior_16.sql
+    update_hprior_17.sql
+    update_hprior_18.sql
+    update_hprior_19.sql
+    update_hprior_2.sql
+    update_hprior_20.sql
+    update_hprior_21.sql
+    update_hprior_22.sql
+    update_hprior_23.sql
+    update_hprior_24.sql
+    update_hprior_25.sql
+    update_hprior_26.sql
+    update_hprior_27.sql
+    update_hprior_28.sql
+    update_hprior_29.sql
+    update_hprior_3.sql
+    update_hprior_30.sql
+    update_hprior_31.sql
+    update_hprior_32.sql
+    update_hprior_33.sql
+    update_hprior_34.sql
+    update_hprior_35.sql
+    update_hprior_36.sql
+    update_hprior_37.sql
+    update_hprior_38.sql
+    update_hprior_39.sql
+    update_hprior_4.sql
+    update_hprior_40.sql
+    update_hprior_41.sql
+    update_hprior_42.sql
+    update_hprior_43.sql
+    update_hprior_44.sql
+    update_hprior_45.sql
+    update_hprior_46.sql
+    update_hprior_47.sql
+    update_hprior_48.sql
+    update_hprior_49.sql
+    update_hprior_5.sql
+    update_hprior_50.sql
+    update_hprior_51.sql
+    update_hprior_52.sql
+    update_hprior_53.sql
+    update_hprior_54.sql
+    update_hprior_55.sql
+    update_hprior_56.sql
+    update_hprior_57.sql
+    update_hprior_58.sql
+    update_hprior_59.sql
+    update_hprior_6.sql
+    update_hprior_60.sql
+    update_hprior_61.sql
+    update_hprior_62.sql
+    update_hprior_63.sql
+    update_hprior_64.sql
+    update_hprior_65.sql
+    update_hprior_66.sql
+    update_hprior_67.sql
+    update_hprior_68.sql
+    update_hprior_69.sql
+    update_hprior_7.sql
+    update_hprior_70.sql
+    update_hprior_71.sql
+    update_hprior_72.sql
+    update_hprior_73.sql
+    update_hprior_74.sql
+    update_hprior_75.sql
+    update_hprior_76.sql
+    update_hprior_77.sql
+    update_hprior_78.sql
+    update_hprior_79.sql
+    update_hprior_8.sql
+    update_hprior_80.sql
+    update_hprior_81.sql
+    update_hprior_82.sql
+    update_hprior_83.sql
+    update_hprior_84.sql
+    update_hprior_85.sql
+    update_hprior_86.sql
+    update_hprior_87.sql
+    update_hprior_88.sql
+    update_hprior_89.sql
+    update_hprior_9.sql
+    update_hprior_90.sql
+    update_hprior_91.sql
+    update_hprior_92.sql
+    update_hprior_93.sql
+    update_hprior_94.sql
+    update_hprior_95.sql
+    update_hprior_96.sql
+    update_hprior_97.sql
+    update_hprior_98.sql
+    update_hprior_99.sql
+    varbc_allsky_robhdr.sql
+    varbc_allsky_robody.sql
+    varbc_gbrad_robhdr.sql
+    varbc_gbrad_robody.sql
+    varbc_rad_robhdr.sql
+    varbc_rad_robody.sql
+    varbc_setup_robhdr.sql
+    varbc_setup_robody.sql
+    varbc_sfcobs_robhdr.sql
+    varbc_sfcobs_robody.sql
+    varbc_tcwv_robhdr.sql
+    varbc_tcwv_robody.sql
+    varbc_to3_robhdr.sql
+    varbc_to3_robody.sql
+)
+
+odb_add_schema(TARGET CCMA SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_CCMA TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.CCMA/adjust_ccma_distribid.sql b/odb/src/ddl.CCMA/adjust_ccma_distribid.sql
new file mode 120000
index 0000000..dffbea4
--- /dev/null
+++ b/odb/src/ddl.CCMA/adjust_ccma_distribid.sql
@@ -0,0 +1 @@
+../ddl/adjust_ccma_distribid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/adjust_seqnos.sql b/odb/src/ddl.CCMA/adjust_seqnos.sql
new file mode 120000
index 0000000..78d1023
--- /dev/null
+++ b/odb/src/ddl.CCMA/adjust_seqnos.sql
@@ -0,0 +1 @@
+../ddl/adjust_seqnos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/aeolus.h b/odb/src/ddl.CCMA/aeolus.h
new file mode 120000
index 0000000..d9f814d
--- /dev/null
+++ b/odb/src/ddl.CCMA/aeolus.h
@@ -0,0 +1 @@
+../ddl/aeolus.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ak_resat_averaging_kernel.sql b/odb/src/ddl.CCMA/ak_resat_averaging_kernel.sql
new file mode 120000
index 0000000..2860589
--- /dev/null
+++ b/odb/src/ddl.CCMA/ak_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/ak_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/alloc.h b/odb/src/ddl.CCMA/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.CCMA/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/allsky.h b/odb/src/ddl.CCMA/allsky.h
new file mode 120000
index 0000000..0a19265
--- /dev/null
+++ b/odb/src/ddl.CCMA/allsky.h
@@ -0,0 +1 @@
+../ddl/allsky.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/amv.sql b/odb/src/ddl.CCMA/amv.sql
new file mode 120000
index 0000000..37eb366
--- /dev/null
+++ b/odb/src/ddl.CCMA/amv.sql
@@ -0,0 +1 @@
+../ddl/amv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/amv2.sql b/odb/src/ddl.CCMA/amv2.sql
new file mode 120000
index 0000000..84338ea
--- /dev/null
+++ b/odb/src/ddl.CCMA/amv2.sql
@@ -0,0 +1 @@
+../ddl/amv2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/amv_flag.sql b/odb/src/ddl.CCMA/amv_flag.sql
new file mode 120000
index 0000000..b0f5a0e
--- /dev/null
+++ b/odb/src/ddl.CCMA/amv_flag.sql
@@ -0,0 +1 @@
+../ddl/amv_flag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/amv_flag2.sql b/odb/src/ddl.CCMA/amv_flag2.sql
new file mode 120000
index 0000000..de40940
--- /dev/null
+++ b/odb/src/ddl.CCMA/amv_flag2.sql
@@ -0,0 +1 @@
+../ddl/amv_flag2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/auxiliary.h b/odb/src/ddl.CCMA/auxiliary.h
new file mode 120000
index 0000000..8ae1b08
--- /dev/null
+++ b/odb/src/ddl.CCMA/auxiliary.h
@@ -0,0 +1 @@
+../ddl/auxiliary.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/bits.h b/odb/src/ddl.CCMA/bits.h
new file mode 120000
index 0000000..459b52a
--- /dev/null
+++ b/odb/src/ddl.CCMA/bits.h
@@ -0,0 +1 @@
+../ddl/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/body.h b/odb/src/ddl.CCMA/body.h
new file mode 120000
index 0000000..ccd0f32
--- /dev/null
+++ b/odb/src/ddl.CCMA/body.h
@@ -0,0 +1 @@
+../ddl/body.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/caifc1.sql b/odb/src/ddl.CCMA/caifc1.sql
new file mode 120000
index 0000000..9243a2f
--- /dev/null
+++ b/odb/src/ddl.CCMA/caifc1.sql
@@ -0,0 +1 @@
+../ddl/caifc1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/camelo_robhdr.sql b/odb/src/ddl.CCMA/camelo_robhdr.sql
new file mode 120000
index 0000000..a95c3e4
--- /dev/null
+++ b/odb/src/ddl.CCMA/camelo_robhdr.sql
@@ -0,0 +1 @@
+../ddl/camelo_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/camelo_robody.sql b/odb/src/ddl.CCMA/camelo_robody.sql
new file mode 120000
index 0000000..df5c6e7
--- /dev/null
+++ b/odb/src/ddl.CCMA/camelo_robody.sql
@@ -0,0 +1 @@
+../ddl/camelo_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/canaco_robhdr.sql b/odb/src/ddl.CCMA/canaco_robhdr.sql
new file mode 120000
index 0000000..59034bd
--- /dev/null
+++ b/odb/src/ddl.CCMA/canaco_robhdr.sql
@@ -0,0 +1 @@
+../ddl/canaco_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/canaco_robhdr_ccma.sql b/odb/src/ddl.CCMA/canaco_robhdr_ccma.sql
new file mode 120000
index 0000000..8f81e77
--- /dev/null
+++ b/odb/src/ddl.CCMA/canaco_robhdr_ccma.sql
@@ -0,0 +1 @@
+../ddl/canaco_robhdr_ccma.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/canaco_robody.sql b/odb/src/ddl.CCMA/canaco_robody.sql
new file mode 120000
index 0000000..1020ce8
--- /dev/null
+++ b/odb/src/ddl.CCMA/canaco_robody.sql
@@ -0,0 +1 @@
+../ddl/canaco_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cancer_robhdr.sql b/odb/src/ddl.CCMA/cancer_robhdr.sql
new file mode 120000
index 0000000..d218b14
--- /dev/null
+++ b/odb/src/ddl.CCMA/cancer_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cancer_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cancer_robody.sql b/odb/src/ddl.CCMA/cancer_robody.sql
new file mode 120000
index 0000000..8a4f855
--- /dev/null
+++ b/odb/src/ddl.CCMA/cancer_robody.sql
@@ -0,0 +1 @@
+../ddl/cancer_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cantik_robhdr.sql b/odb/src/ddl.CCMA/cantik_robhdr.sql
new file mode 120000
index 0000000..84fe03b
--- /dev/null
+++ b/odb/src/ddl.CCMA/cantik_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cantik_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cantik_robody.sql b/odb/src/ddl.CCMA/cantik_robody.sql
new file mode 120000
index 0000000..7655217
--- /dev/null
+++ b/odb/src/ddl.CCMA/cantik_robody.sql
@@ -0,0 +1 @@
+../ddl/cantik_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/carcfo.sql b/odb/src/ddl.CCMA/carcfo.sql
new file mode 120000
index 0000000..ca7f67e
--- /dev/null
+++ b/odb/src/ddl.CCMA/carcfo.sql
@@ -0,0 +1 @@
+../ddl/carcfo.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/castor.sql b/odb/src/ddl.CCMA/castor.sql
new file mode 120000
index 0000000..4b5ac23
--- /dev/null
+++ b/odb/src/ddl.CCMA/castor.sql
@@ -0,0 +1 @@
+../ddl/castor.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/caviso_robhdr.sql b/odb/src/ddl.CCMA/caviso_robhdr.sql
new file mode 120000
index 0000000..53c7d7e
--- /dev/null
+++ b/odb/src/ddl.CCMA/caviso_robhdr.sql
@@ -0,0 +1 @@
+../ddl/caviso_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/caviso_robody.sql b/odb/src/ddl.CCMA/caviso_robody.sql
new file mode 120000
index 0000000..dcd7bef
--- /dev/null
+++ b/odb/src/ddl.CCMA/caviso_robody.sql
@@ -0,0 +1 @@
+../ddl/caviso_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cavodk_robhdr.sql b/odb/src/ddl.CCMA/cavodk_robhdr.sql
new file mode 120000
index 0000000..9725d5d
--- /dev/null
+++ b/odb/src/ddl.CCMA/cavodk_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cavodk_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cavodk_robody.sql b/odb/src/ddl.CCMA/cavodk_robody.sql
new file mode 120000
index 0000000..2394b44
--- /dev/null
+++ b/odb/src/ddl.CCMA/cavodk_robody.sql
@@ -0,0 +1 @@
+../ddl/cavodk_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cdrhook.h b/odb/src/ddl.CCMA/cdrhook.h
new file mode 120000
index 0000000..8784f89
--- /dev/null
+++ b/odb/src/ddl.CCMA/cdrhook.h
@@ -0,0 +1 @@
+../ddl/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cloud_sink.h b/odb/src/ddl.CCMA/cloud_sink.h
new file mode 120000
index 0000000..3cdc586
--- /dev/null
+++ b/odb/src/ddl.CCMA/cloud_sink.h
@@ -0,0 +1 @@
+../ddl/cloud_sink.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/cma.h b/odb/src/ddl.CCMA/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.CCMA/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/collocated_imager_information.h b/odb/src/ddl.CCMA/collocated_imager_information.h
new file mode 120000
index 0000000..3b061d6
--- /dev/null
+++ b/odb/src/ddl.CCMA/collocated_imager_information.h
@@ -0,0 +1 @@
+../ddl/collocated_imager_information.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/conv.h b/odb/src/ddl.CCMA/conv.h
new file mode 120000
index 0000000..9280d6d
--- /dev/null
+++ b/odb/src/ddl.CCMA/conv.h
@@ -0,0 +1 @@
+../ddl/conv.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/conv_hdr.sql b/odb/src/ddl.CCMA/conv_hdr.sql
new file mode 120000
index 0000000..708dae7
--- /dev/null
+++ b/odb/src/ddl.CCMA/conv_hdr.sql
@@ -0,0 +1 @@
+../ddl/conv_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/data_radar_station.sql b/odb/src/ddl.CCMA/data_radar_station.sql
new file mode 120000
index 0000000..90b082e
--- /dev/null
+++ b/odb/src/ddl.CCMA/data_radar_station.sql
@@ -0,0 +1 @@
+../ddl/data_radar_station.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/date_time.sql b/odb/src/ddl.CCMA/date_time.sql
new file mode 120000
index 0000000..7e66570
--- /dev/null
+++ b/odb/src/ddl.CCMA/date_time.sql
@@ -0,0 +1 @@
+../ddl/date_time.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/dca.h b/odb/src/ddl.CCMA/dca.h
new file mode 120000
index 0000000..005f5d7
--- /dev/null
+++ b/odb/src/ddl.CCMA/dca.h
@@ -0,0 +1 @@
+../ddl/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_allsky_body.sql b/odb/src/ddl.CCMA/ecmwf_matchup_allsky_body.sql
new file mode 120000
index 0000000..ece85d2
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_body.sql b/odb/src/ddl.CCMA/ecmwf_matchup_body.sql
new file mode 120000
index 0000000..b818336
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_body.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_gbrad.sql b/odb/src/ddl.CCMA/ecmwf_matchup_gbrad.sql
new file mode 120000
index 0000000..5173cb9
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_gbrad.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_hdr.sql b/odb/src/ddl.CCMA/ecmwf_matchup_hdr.sql
new file mode 120000
index 0000000..88cc790
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_raingg.sql b/odb/src/ddl.CCMA/ecmwf_matchup_raingg.sql
new file mode 120000
index 0000000..b88e6ae
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_raingg.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_update_1.sql b/odb/src/ddl.CCMA/ecmwf_matchup_update_1.sql
new file mode 120000
index 0000000..3cef54f
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_update_1.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_update_2.sql b/odb/src/ddl.CCMA/ecmwf_matchup_update_2.sql
new file mode 120000
index 0000000..7ceaa64
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_update_2.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchup_update_3.sql b/odb/src/ddl.CCMA/ecmwf_matchup_update_3.sql
new file mode 120000
index 0000000..3c45f49
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchup_update_3.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecmwf_matchupsink.sql b/odb/src/ddl.CCMA/ecmwf_matchupsink.sql
new file mode 120000
index 0000000..ed1a9b7
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecmwf_matchupsink.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchupsink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecset.sql b/odb/src/ddl.CCMA/ecset.sql
new file mode 120000
index 0000000..171c3e1
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecset.sql
@@ -0,0 +1 @@
+../ddl/ecset.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ecstdlib.h b/odb/src/ddl.CCMA/ecstdlib.h
new file mode 120000
index 0000000..32bb85b
--- /dev/null
+++ b/odb/src/ddl.CCMA/ecstdlib.h
@@ -0,0 +1 @@
+../ddl/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ensemble.h b/odb/src/ddl.CCMA/ensemble.h
new file mode 120000
index 0000000..8963a78
--- /dev/null
+++ b/odb/src/ddl.CCMA/ensemble.h
@@ -0,0 +1 @@
+../ddl/ensemble.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/errstat.h b/odb/src/ddl.CCMA/errstat.h
new file mode 120000
index 0000000..217465a
--- /dev/null
+++ b/odb/src/ddl.CCMA/errstat.h
@@ -0,0 +1 @@
+../ddl/errstat.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/exp_info_1.sql b/odb/src/ddl.CCMA/exp_info_1.sql
new file mode 120000
index 0000000..ef6ea5d
--- /dev/null
+++ b/odb/src/ddl.CCMA/exp_info_1.sql
@@ -0,0 +1 @@
+../ddl/exp_info_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fc_sens_obs.sql b/odb/src/ddl.CCMA/fc_sens_obs.sql
new file mode 120000
index 0000000..be8267e
--- /dev/null
+++ b/odb/src/ddl.CCMA/fc_sens_obs.sql
@@ -0,0 +1 @@
+../ddl/fc_sens_obs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robhdr_0.sql b/odb/src/ddl.CCMA/fcq_robhdr_0.sql
new file mode 120000
index 0000000..ac9f59f
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robhdr_0.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robhdr_1.sql b/odb/src/ddl.CCMA/fcq_robhdr_1.sql
new file mode 120000
index 0000000..4066238
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robhdr_2.sql b/odb/src/ddl.CCMA/fcq_robhdr_2.sql
new file mode 120000
index 0000000..35ed6cc
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robody_0.sql b/odb/src/ddl.CCMA/fcq_robody_0.sql
new file mode 120000
index 0000000..ff0fac0
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robody_0.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robody_1.sql b/odb/src/ddl.CCMA/fcq_robody_1.sql
new file mode 120000
index 0000000..1dc87a2
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robody_1.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fcq_robody_2.sql b/odb/src/ddl.CCMA/fcq_robody_2.sql
new file mode 120000
index 0000000..9614780
--- /dev/null
+++ b/odb/src/ddl.CCMA/fcq_robody_2.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fix_date_and_time.sql b/odb/src/ddl.CCMA/fix_date_and_time.sql
new file mode 120000
index 0000000..911c543
--- /dev/null
+++ b/odb/src/ddl.CCMA/fix_date_and_time.sql
@@ -0,0 +1 @@
+../ddl/fix_date_and_time.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/fixresatlen.sql b/odb/src/ddl.CCMA/fixresatlen.sql
new file mode 120000
index 0000000..d3ed207
--- /dev/null
+++ b/odb/src/ddl.CCMA/fixresatlen.sql
@@ -0,0 +1 @@
+../ddl/fixresatlen.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/forecast_diagnostic.h b/odb/src/ddl.CCMA/forecast_diagnostic.h
new file mode 120000
index 0000000..8d17f2d
--- /dev/null
+++ b/odb/src/ddl.CCMA/forecast_diagnostic.h
@@ -0,0 +1 @@
+../ddl/forecast_diagnostic.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/funcs.h b/odb/src/ddl.CCMA/funcs.h
new file mode 120000
index 0000000..e16dc7c
--- /dev/null
+++ b/odb/src/ddl.CCMA/funcs.h
@@ -0,0 +1 @@
+../ddl/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gather4poolmask.sql b/odb/src/ddl.CCMA/gather4poolmask.sql
new file mode 120000
index 0000000..ab32525
--- /dev/null
+++ b/odb/src/ddl.CCMA/gather4poolmask.sql
@@ -0,0 +1 @@
+../ddl/gather4poolmask.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gather4poolmask_counts.sql b/odb/src/ddl.CCMA/gather4poolmask_counts.sql
new file mode 120000
index 0000000..f44cb2c
--- /dev/null
+++ b/odb/src/ddl.CCMA/gather4poolmask_counts.sql
@@ -0,0 +1 @@
+../ddl/gather4poolmask_counts.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gbrad.h b/odb/src/ddl.CCMA/gbrad.h
new file mode 120000
index 0000000..a94ed8e
--- /dev/null
+++ b/odb/src/ddl.CCMA/gbrad.h
@@ -0,0 +1 @@
+../ddl/gbrad.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gbrad_body_rr.sql b/odb/src/ddl.CCMA/gbrad_body_rr.sql
new file mode 120000
index 0000000..177d585
--- /dev/null
+++ b/odb/src/ddl.CCMA/gbrad_body_rr.sql
@@ -0,0 +1 @@
+../ddl/gbrad_body_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gbrad_rr.sql b/odb/src/ddl.CCMA/gbrad_rr.sql
new file mode 120000
index 0000000..d1c0f67
--- /dev/null
+++ b/odb/src/ddl.CCMA/gbrad_rr.sql
@@ -0,0 +1 @@
+../ddl/gbrad_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/get_soe_resat.sql b/odb/src/ddl.CCMA/get_soe_resat.sql
new file mode 120000
index 0000000..a288979
--- /dev/null
+++ b/odb/src/ddl.CCMA/get_soe_resat.sql
@@ -0,0 +1 @@
+../ddl/get_soe_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getgbradid.sql b/odb/src/ddl.CCMA/getgbradid.sql
new file mode 120000
index 0000000..c9a9862
--- /dev/null
+++ b/odb/src/ddl.CCMA/getgbradid.sql
@@ -0,0 +1 @@
+../ddl/getgbradid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getlimbid.sql b/odb/src/ddl.CCMA/getlimbid.sql
new file mode 120000
index 0000000..6db0e04
--- /dev/null
+++ b/odb/src/ddl.CCMA/getlimbid.sql
@@ -0,0 +1 @@
+../ddl/getlimbid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getsatid.sql b/odb/src/ddl.CCMA/getsatid.sql
new file mode 120000
index 0000000..d806462
--- /dev/null
+++ b/odb/src/ddl.CCMA/getsatid.sql
@@ -0,0 +1 @@
+../ddl/getsatid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getsatid_resat.sql b/odb/src/ddl.CCMA/getsatid_resat.sql
new file mode 120000
index 0000000..596c1d9
--- /dev/null
+++ b/odb/src/ddl.CCMA/getsatid_resat.sql
@@ -0,0 +1 @@
+../ddl/getsatid_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getsatobid.sql b/odb/src/ddl.CCMA/getsatobid.sql
new file mode 120000
index 0000000..d30e080
--- /dev/null
+++ b/odb/src/ddl.CCMA/getsatobid.sql
@@ -0,0 +1 @@
+../ddl/getsatobid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/getsfcobsid.sql b/odb/src/ddl.CCMA/getsfcobsid.sql
new file mode 120000
index 0000000..2a3b153
--- /dev/null
+++ b/odb/src/ddl.CCMA/getsfcobsid.sql
@@ -0,0 +1 @@
+../ddl/getsfcobsid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_1.sql b/odb/src/ddl.CCMA/global_enkf_1.sql
new file mode 120000
index 0000000..cdcb517
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_1.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_10.sql b/odb/src/ddl.CCMA/global_enkf_10.sql
new file mode 120000
index 0000000..645905b
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_10.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_100.sql b/odb/src/ddl.CCMA/global_enkf_100.sql
new file mode 120000
index 0000000..fabda69
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_100.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_100.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_105.sql b/odb/src/ddl.CCMA/global_enkf_105.sql
new file mode 120000
index 0000000..a938e0f
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_105.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_105.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_110.sql b/odb/src/ddl.CCMA/global_enkf_110.sql
new file mode 120000
index 0000000..d6b3acd
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_110.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_110.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_115.sql b/odb/src/ddl.CCMA/global_enkf_115.sql
new file mode 120000
index 0000000..41c831b
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_115.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_115.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_120.sql b/odb/src/ddl.CCMA/global_enkf_120.sql
new file mode 120000
index 0000000..b72b2bb
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_120.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_120.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_15.sql b/odb/src/ddl.CCMA/global_enkf_15.sql
new file mode 120000
index 0000000..55b2c38
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_15.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_15.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_2.sql b/odb/src/ddl.CCMA/global_enkf_2.sql
new file mode 120000
index 0000000..f7a6280
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_2.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_20.sql b/odb/src/ddl.CCMA/global_enkf_20.sql
new file mode 120000
index 0000000..c8223ed
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_20.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_20.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_25.sql b/odb/src/ddl.CCMA/global_enkf_25.sql
new file mode 120000
index 0000000..a704ebb
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_25.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_25.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_3.sql b/odb/src/ddl.CCMA/global_enkf_3.sql
new file mode 120000
index 0000000..950db5c
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_3.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_30.sql b/odb/src/ddl.CCMA/global_enkf_30.sql
new file mode 120000
index 0000000..2b0749f
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_30.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_30.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_35.sql b/odb/src/ddl.CCMA/global_enkf_35.sql
new file mode 120000
index 0000000..8d47816
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_35.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_35.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_4.sql b/odb/src/ddl.CCMA/global_enkf_4.sql
new file mode 120000
index 0000000..2081276
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_4.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_40.sql b/odb/src/ddl.CCMA/global_enkf_40.sql
new file mode 120000
index 0000000..79ac4d2
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_40.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_40.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_45.sql b/odb/src/ddl.CCMA/global_enkf_45.sql
new file mode 120000
index 0000000..6b28691
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_45.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_45.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_5.sql b/odb/src/ddl.CCMA/global_enkf_5.sql
new file mode 120000
index 0000000..5217e16
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_5.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_50.sql b/odb/src/ddl.CCMA/global_enkf_50.sql
new file mode 120000
index 0000000..977782c
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_50.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_50.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_55.sql b/odb/src/ddl.CCMA/global_enkf_55.sql
new file mode 120000
index 0000000..77f5c35
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_55.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_55.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_60.sql b/odb/src/ddl.CCMA/global_enkf_60.sql
new file mode 120000
index 0000000..e5b29ea
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_60.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_60.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_65.sql b/odb/src/ddl.CCMA/global_enkf_65.sql
new file mode 120000
index 0000000..c7d73a2
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_65.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_65.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_70.sql b/odb/src/ddl.CCMA/global_enkf_70.sql
new file mode 120000
index 0000000..836f524
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_70.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_70.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_75.sql b/odb/src/ddl.CCMA/global_enkf_75.sql
new file mode 120000
index 0000000..fdf0173
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_75.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_75.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_80.sql b/odb/src/ddl.CCMA/global_enkf_80.sql
new file mode 120000
index 0000000..9399b21
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_80.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_80.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_85.sql b/odb/src/ddl.CCMA/global_enkf_85.sql
new file mode 120000
index 0000000..9472028
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_85.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_85.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_90.sql b/odb/src/ddl.CCMA/global_enkf_90.sql
new file mode 120000
index 0000000..a47f8dd
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_90.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_90.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/global_enkf_95.sql b/odb/src/ddl.CCMA/global_enkf_95.sql
new file mode 120000
index 0000000..64c9850
--- /dev/null
+++ b/odb/src/ddl.CCMA/global_enkf_95.sql
@@ -0,0 +1 @@
+../ddl/global_enkf_95.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/gnssro.h b/odb/src/ddl.CCMA/gnssro.h
new file mode 120000
index 0000000..aa94338
--- /dev/null
+++ b/odb/src/ddl.CCMA/gnssro.h
@@ -0,0 +1 @@
+../ddl/gnssro.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hdr.h b/odb/src/ddl.CCMA/hdr.h
new file mode 120000
index 0000000..9d10f20
--- /dev/null
+++ b/odb/src/ddl.CCMA/hdr.h
@@ -0,0 +1 @@
+../ddl/hdr.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hop_canari_conv.sql b/odb/src/ddl.CCMA/hop_canari_conv.sql
new file mode 120000
index 0000000..d6cd522
--- /dev/null
+++ b/odb/src/ddl.CCMA/hop_canari_conv.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hop_canari_robhdr.sql b/odb/src/ddl.CCMA/hop_canari_robhdr.sql
new file mode 120000
index 0000000..7321038
--- /dev/null
+++ b/odb/src/ddl.CCMA/hop_canari_robhdr.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hop_canari_robody.sql b/odb/src/ddl.CCMA/hop_canari_robody.sql
new file mode 120000
index 0000000..7606498
--- /dev/null
+++ b/odb/src/ddl.CCMA/hop_canari_robody.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hretr_canari_robody.sql b/odb/src/ddl.CCMA/hretr_canari_robody.sql
new file mode 120000
index 0000000..ca04ed9
--- /dev/null
+++ b/odb/src/ddl.CCMA/hretr_canari_robody.sql
@@ -0,0 +1 @@
+../ddl/hretr_canari_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/hretr_canari_satbody.sql b/odb/src/ddl.CCMA/hretr_canari_satbody.sql
new file mode 120000
index 0000000..a5aa678
--- /dev/null
+++ b/odb/src/ddl.CCMA/hretr_canari_satbody.sql
@@ -0,0 +1 @@
+../ddl/hretr_canari_satbody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/idx.h b/odb/src/ddl.CCMA/idx.h
new file mode 120000
index 0000000..cfdb097
--- /dev/null
+++ b/odb/src/ddl.CCMA/idx.h
@@ -0,0 +1 @@
+../ddl/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/info.h b/odb/src/ddl.CCMA/info.h
new file mode 120000
index 0000000..b63984c
--- /dev/null
+++ b/odb/src/ddl.CCMA/info.h
@@ -0,0 +1 @@
+../ddl/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/limb.h b/odb/src/ddl.CCMA/limb.h
new file mode 120000
index 0000000..ab7f4f9
--- /dev/null
+++ b/odb/src/ddl.CCMA/limb.h
@@ -0,0 +1 @@
+../ddl/limb.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/magicwords.h b/odb/src/ddl.CCMA/magicwords.h
new file mode 120000
index 0000000..8135e72
--- /dev/null
+++ b/odb/src/ddl.CCMA/magicwords.h
@@ -0,0 +1 @@
+../ddl/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/manda_gene_body.sql b/odb/src/ddl.CCMA/manda_gene_body.sql
new file mode 120000
index 0000000..9e2970f
--- /dev/null
+++ b/odb/src/ddl.CCMA/manda_gene_body.sql
@@ -0,0 +1 @@
+../ddl/manda_gene_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/manda_gene_hdr.sql b/odb/src/ddl.CCMA/manda_gene_hdr.sql
new file mode 120000
index 0000000..b4836f4
--- /dev/null
+++ b/odb/src/ddl.CCMA/manda_gene_hdr.sql
@@ -0,0 +1 @@
+../ddl/manda_gene_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/manda_laelalo.sql b/odb/src/ddl.CCMA/manda_laelalo.sql
new file mode 120000
index 0000000..7d56338
--- /dev/null
+++ b/odb/src/ddl.CCMA/manda_laelalo.sql
@@ -0,0 +1 @@
+../ddl/manda_laelalo.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_allsky_body.sql b/odb/src/ddl.CCMA/matchup_allsky_body.sql
new file mode 120000
index 0000000..945d4c1
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/matchup_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_atovs_pred.sql b/odb/src/ddl.CCMA/matchup_atovs_pred.sql
new file mode 120000
index 0000000..7b315c9
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_atovs_pred.sql
@@ -0,0 +1 @@
+../ddl/matchup_atovs_pred.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_body.sql b/odb/src/ddl.CCMA/matchup_body.sql
new file mode 120000
index 0000000..20d1f03
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_body.sql
@@ -0,0 +1 @@
+../ddl/matchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_gbrad.sql b/odb/src/ddl.CCMA/matchup_gbrad.sql
new file mode 120000
index 0000000..58a5974
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_gbrad.sql
@@ -0,0 +1 @@
+../ddl/matchup_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_hdr.sql b/odb/src/ddl.CCMA/matchup_hdr.sql
new file mode 120000
index 0000000..a967e01
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/matchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_raingg.sql b/odb/src/ddl.CCMA/matchup_raingg.sql
new file mode 120000
index 0000000..d6a52bf
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_raingg.sql
@@ -0,0 +1 @@
+../ddl/matchup_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_sensorlist.sql b/odb/src/ddl.CCMA/matchup_sensorlist.sql
new file mode 120000
index 0000000..319b5ed
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_sensorlist.sql
@@ -0,0 +1 @@
+../ddl/matchup_sensorlist.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_1.sql b/odb/src/ddl.CCMA/matchup_update_1.sql
new file mode 120000
index 0000000..cfff8e3
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_1.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_10.sql b/odb/src/ddl.CCMA/matchup_update_10.sql
new file mode 120000
index 0000000..eedead1
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_10.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_2.sql b/odb/src/ddl.CCMA/matchup_update_2.sql
new file mode 120000
index 0000000..c838e95
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_2.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_3.sql b/odb/src/ddl.CCMA/matchup_update_3.sql
new file mode 120000
index 0000000..ded6887
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_3.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_4.sql b/odb/src/ddl.CCMA/matchup_update_4.sql
new file mode 120000
index 0000000..9571846
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_4.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_5.sql b/odb/src/ddl.CCMA/matchup_update_5.sql
new file mode 120000
index 0000000..7a210a5
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_5.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_6.sql b/odb/src/ddl.CCMA/matchup_update_6.sql
new file mode 120000
index 0000000..26265e2
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_6.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_7.sql b/odb/src/ddl.CCMA/matchup_update_7.sql
new file mode 120000
index 0000000..214c9a9
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_7.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_8.sql b/odb/src/ddl.CCMA/matchup_update_8.sql
new file mode 120000
index 0000000..f35db26
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_8.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchup_update_9.sql b/odb/src/ddl.CCMA/matchup_update_9.sql
new file mode 120000
index 0000000..a6dfc92
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchup_update_9.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/matchupsink.sql b/odb/src/ddl.CCMA/matchupsink.sql
new file mode 120000
index 0000000..48cd771
--- /dev/null
+++ b/odb/src/ddl.CCMA/matchupsink.sql
@@ -0,0 +1 @@
+../ddl/matchupsink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/mdi.h b/odb/src/ddl.CCMA/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.CCMA/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/mkglobstab.sql b/odb/src/ddl.CCMA/mkglobstab.sql
new file mode 120000
index 0000000..100370c
--- /dev/null
+++ b/odb/src/ddl.CCMA/mkglobstab.sql
@@ -0,0 +1 @@
+../ddl/mkglobstab.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/mkglobstab_gpsro.sql b/odb/src/ddl.CCMA/mkglobstab_gpsro.sql
new file mode 120000
index 0000000..d93a7e2
--- /dev/null
+++ b/odb/src/ddl.CCMA/mkglobstab_gpsro.sql
@@ -0,0 +1 @@
+../ddl/mkglobstab_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/mobhdrca_obsort.sql b/odb/src/ddl.CCMA/mobhdrca_obsort.sql
new file mode 120000
index 0000000..d47a808
--- /dev/null
+++ b/odb/src/ddl.CCMA/mobhdrca_obsort.sql
@@ -0,0 +1 @@
+../ddl/mobhdrca_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/modsurf.h b/odb/src/ddl.CCMA/modsurf.h
new file mode 120000
index 0000000..7223f38
--- /dev/null
+++ b/odb/src/ddl.CCMA/modsurf.h
@@ -0,0 +1 @@
+../ddl/modsurf.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/namecfg.h b/odb/src/ddl.CCMA/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.CCMA/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obatabs_robhdr.sql b/odb/src/ddl.CCMA/obatabs_robhdr.sql
new file mode 120000
index 0000000..6789325
--- /dev/null
+++ b/odb/src/ddl.CCMA/obatabs_robhdr.sql
@@ -0,0 +1 @@
+../ddl/obatabs_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obs_boxes.sql b/odb/src/ddl.CCMA/obs_boxes.sql
new file mode 120000
index 0000000..21f0489
--- /dev/null
+++ b/odb/src/ddl.CCMA/obs_boxes.sql
@@ -0,0 +1 @@
+../ddl/obs_boxes.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist.sql b/odb/src/ddl.CCMA/obsdist.sql
new file mode 120000
index 0000000..b2521b2
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist.sql
@@ -0,0 +1 @@
+../ddl/obsdist.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_allsky.sql b/odb/src/ddl.CCMA/obsdist_allsky.sql
new file mode 120000
index 0000000..1696a9b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_allsky.sql
@@ -0,0 +1 @@
+../ddl/obsdist_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_allsky_body.sql b/odb/src/ddl.CCMA/obsdist_allsky_body.sql
new file mode 120000
index 0000000..52172e8
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_auxiliary.sql b/odb/src/ddl.CCMA/obsdist_auxiliary.sql
new file mode 120000
index 0000000..660f79a
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/obsdist_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_auxiliary_body.sql b/odb/src/ddl.CCMA/obsdist_auxiliary_body.sql
new file mode 120000
index 0000000..7e5d7bb
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_body.sql b/odb/src/ddl.CCMA/obsdist_body.sql
new file mode 120000
index 0000000..f31a752
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_errstat.sql b/odb/src/ddl.CCMA/obsdist_errstat.sql
new file mode 120000
index 0000000..b3c1c79
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_errstat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_errstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_gbrad.sql b/odb/src/ddl.CCMA/obsdist_gbrad.sql
new file mode 120000
index 0000000..136d079
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_gbrad.sql
@@ -0,0 +1 @@
+../ddl/obsdist_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_gbrad_body.sql b/odb/src/ddl.CCMA/obsdist_gbrad_body.sql
new file mode 120000
index 0000000..fcbf4c5
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr.sql b/odb/src/ddl.CCMA/obsdist_hdr.sql
new file mode 120000
index 0000000..8bd4703
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2allsky_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2allsky_body.sql
new file mode 120000
index 0000000..b85d8ae
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2auxiliary_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..6d7c11b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2body.sql b/odb/src/ddl.CCMA/obsdist_hdr2body.sql
new file mode 120000
index 0000000..c7b9058
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2gbrad_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2gbrad_body.sql
new file mode 120000
index 0000000..73f43ae
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2radar_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2radar_body.sql
new file mode 120000
index 0000000..6aae5bd
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2radiance_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2radiance_body.sql
new file mode 120000
index 0000000..77105cf
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2raingg_body.sql b/odb/src/ddl.CCMA/obsdist_hdr2raingg_body.sql
new file mode 120000
index 0000000..93e4b3a
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_hdr2resat_averaging_kernel.sql b/odb/src/ddl.CCMA/obsdist_hdr2resat_averaging_kernel.sql
new file mode 120000
index 0000000..2690586
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_hdr2resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_index.sql b/odb/src/ddl.CCMA/obsdist_index.sql
new file mode 120000
index 0000000..c9c5f18
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_index.sql
@@ -0,0 +1 @@
+../ddl/obsdist_index.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_index2hdr.sql b/odb/src/ddl.CCMA/obsdist_index2hdr.sql
new file mode 120000
index 0000000..1856d68
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_index2hdr.sql
@@ -0,0 +1 @@
+../ddl/obsdist_index2hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_limb.sql b/odb/src/ddl.CCMA/obsdist_limb.sql
new file mode 120000
index 0000000..d252d67
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_limb.sql
@@ -0,0 +1 @@
+../ddl/obsdist_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_modsurf.sql b/odb/src/ddl.CCMA/obsdist_modsurf.sql
new file mode 120000
index 0000000..72c0e45
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_modsurf.sql
@@ -0,0 +1 @@
+../ddl/obsdist_modsurf.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_poolno.sql b/odb/src/ddl.CCMA/obsdist_poolno.sql
new file mode 120000
index 0000000..b14b21b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_poolno.sql
@@ -0,0 +1 @@
+../ddl/obsdist_poolno.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_radar.sql b/odb/src/ddl.CCMA/obsdist_radar.sql
new file mode 120000
index 0000000..b73566b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_radar.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_radar_body.sql b/odb/src/ddl.CCMA/obsdist_radar_body.sql
new file mode 120000
index 0000000..81c6ce7
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_radar_station.sql b/odb/src/ddl.CCMA/obsdist_radar_station.sql
new file mode 120000
index 0000000..816f996
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_radar_station.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar_station.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_radiance.sql b/odb/src/ddl.CCMA/obsdist_radiance.sql
new file mode 120000
index 0000000..15cf272
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_radiance.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radiance.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_radiance_body.sql b/odb/src/ddl.CCMA/obsdist_radiance_body.sql
new file mode 120000
index 0000000..d5b9306
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_raingg.sql b/odb/src/ddl.CCMA/obsdist_raingg.sql
new file mode 120000
index 0000000..14ee7aa
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_raingg.sql
@@ -0,0 +1 @@
+../ddl/obsdist_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_raingg_body.sql b/odb/src/ddl.CCMA/obsdist_raingg_body.sql
new file mode 120000
index 0000000..32242cd
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_resat.sql b/odb/src/ddl.CCMA/obsdist_resat.sql
new file mode 120000
index 0000000..ed8e4af
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_resat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_resat_averaging_kernel.sql b/odb/src/ddl.CCMA/obsdist_resat_averaging_kernel.sql
new file mode 120000
index 0000000..9112e70
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/obsdist_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_sat.sql b/odb/src/ddl.CCMA/obsdist_sat.sql
new file mode 120000
index 0000000..bb230f3
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_sat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_satob.sql b/odb/src/ddl.CCMA/obsdist_satob.sql
new file mode 120000
index 0000000..86b662d
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_satob.sql
@@ -0,0 +1 @@
+../ddl/obsdist_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_1.sql b/odb/src/ddl.CCMA/obsdist_update_1.sql
new file mode 120000
index 0000000..665f67b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_1.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_10.sql b/odb/src/ddl.CCMA/obsdist_update_10.sql
new file mode 120000
index 0000000..49a2429
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_10.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_2.sql b/odb/src/ddl.CCMA/obsdist_update_2.sql
new file mode 120000
index 0000000..10e6d56
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_2.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_3.sql b/odb/src/ddl.CCMA/obsdist_update_3.sql
new file mode 120000
index 0000000..6522ff2
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_3.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_4.sql b/odb/src/ddl.CCMA/obsdist_update_4.sql
new file mode 120000
index 0000000..d54a3a7
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_4.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_5.sql b/odb/src/ddl.CCMA/obsdist_update_5.sql
new file mode 120000
index 0000000..1c2ddb3
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_5.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_6.sql b/odb/src/ddl.CCMA/obsdist_update_6.sql
new file mode 120000
index 0000000..a7e9797
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_6.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_7.sql b/odb/src/ddl.CCMA/obsdist_update_7.sql
new file mode 120000
index 0000000..5aafe9b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_7.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_8.sql b/odb/src/ddl.CCMA/obsdist_update_8.sql
new file mode 120000
index 0000000..9ff3e27
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_8.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_update_9.sql b/odb/src/ddl.CCMA/obsdist_update_9.sql
new file mode 120000
index 0000000..2fbdd7b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_update_9.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsdist_windows.sql b/odb/src/ddl.CCMA/obsdist_windows.sql
new file mode 120000
index 0000000..8f9f080
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsdist_windows.sql
@@ -0,0 +1 @@
+../ddl/obsdist_windows.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obshor.sql b/odb/src/ddl.CCMA/obshor.sql
new file mode 120000
index 0000000..8e94e24
--- /dev/null
+++ b/odb/src/ddl.CCMA/obshor.sql
@@ -0,0 +1 @@
+../ddl/obshor.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_gnssro_body.sql b/odb/src/ddl.CCMA/obsort_gnssro_body.sql
new file mode 120000
index 0000000..be9c099
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_gnssro_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_gnssro_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2allsky_body.sql b/odb/src/ddl.CCMA/obsort_hdr2allsky_body.sql
new file mode 120000
index 0000000..7fe238d
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2auxiliary_body.sql b/odb/src/ddl.CCMA/obsort_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..1e96822
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2gbrad_body.sql b/odb/src/ddl.CCMA/obsort_hdr2gbrad_body.sql
new file mode 120000
index 0000000..f8b384b
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2gnssro_body.sql b/odb/src/ddl.CCMA/obsort_hdr2gnssro_body.sql
new file mode 120000
index 0000000..a7e587f
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2gnssro_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2gnssro_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2radar_body.sql b/odb/src/ddl.CCMA/obsort_hdr2radar_body.sql
new file mode 120000
index 0000000..afc5a66
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2raingg_body.sql b/odb/src/ddl.CCMA/obsort_hdr2raingg_body.sql
new file mode 120000
index 0000000..2d2aa74
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsort_hdr2scatt_body.sql b/odb/src/ddl.CCMA/obsort_hdr2scatt_body.sql
new file mode 120000
index 0000000..a0615b8
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsort_hdr2scatt_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2scatt_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_auxiliary.sql b/odb/src/ddl.CCMA/obsortca_auxiliary.sql
new file mode 120000
index 0000000..3ad3d7f
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/obsortca_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_body.sql b/odb/src/ddl.CCMA/obsortca_body.sql
new file mode 120000
index 0000000..1f7795a
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_errstat.sql b/odb/src/ddl.CCMA/obsortca_errstat.sql
new file mode 120000
index 0000000..071dfce
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_errstat.sql
@@ -0,0 +1 @@
+../ddl/obsortca_errstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_hdr.sql b/odb/src/ddl.CCMA/obsortca_hdr.sql
new file mode 120000
index 0000000..4cbf6bb
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_hdr.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_hdr2auxiliary_body.sql b/odb/src/ddl.CCMA/obsortca_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..b6d7981
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_hdr2body.sql b/odb/src/ddl.CCMA/obsortca_hdr2body.sql
new file mode 120000
index 0000000..df22a29
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_hdr2body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr2body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_index.sql b/odb/src/ddl.CCMA/obsortca_index.sql
new file mode 120000
index 0000000..5076f62
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_index.sql
@@ -0,0 +1 @@
+../ddl/obsortca_index.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_update_1.sql b/odb/src/ddl.CCMA/obsortca_update_1.sql
new file mode 120000
index 0000000..80eb117
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_update_1.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_update_2.sql b/odb/src/ddl.CCMA/obsortca_update_2.sql
new file mode 120000
index 0000000..6fbd538
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_update_2.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obsortca_update_3.sql b/odb/src/ddl.CCMA/obsortca_update_3.sql
new file mode 120000
index 0000000..63c18d5
--- /dev/null
+++ b/odb/src/ddl.CCMA/obsortca_update_3.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/obstype.h b/odb/src/ddl.CCMA/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.CCMA/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odb.h b/odb/src/ddl.CCMA/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.CCMA/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odb98.flags b/odb/src/ddl.CCMA/odb98.flags
new file mode 120000
index 0000000..bc6a361
--- /dev/null
+++ b/odb/src/ddl.CCMA/odb98.flags
@@ -0,0 +1 @@
+../ddl/odb98.flags
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odb_info.sql b/odb/src/ddl.CCMA/odb_info.sql
new file mode 120000
index 0000000..ae3129e
--- /dev/null
+++ b/odb/src/ddl.CCMA/odb_info.sql
@@ -0,0 +1 @@
+../ddl/odb_info.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odb_macros.h b/odb/src/ddl.CCMA/odb_macros.h
new file mode 120000
index 0000000..01fe8a8
--- /dev/null
+++ b/odb/src/ddl.CCMA/odb_macros.h
@@ -0,0 +1 @@
+../ddl/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odbcrc.h b/odb/src/ddl.CCMA/odbcrc.h
new file mode 120000
index 0000000..fcd0f0c
--- /dev/null
+++ b/odb/src/ddl.CCMA/odbcrc.h
@@ -0,0 +1 @@
+../ddl/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/odbmd5.h b/odb/src/ddl.CCMA/odbmd5.h
new file mode 120000
index 0000000..b81990c
--- /dev/null
+++ b/odb/src/ddl.CCMA/odbmd5.h
@@ -0,0 +1 @@
+../ddl/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/pcma_extern.h b/odb/src/ddl.CCMA/pcma_extern.h
new file mode 120000
index 0000000..dba5539
--- /dev/null
+++ b/odb/src/ddl.CCMA/pcma_extern.h
@@ -0,0 +1 @@
+../ddl/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/poolmask_1.sql b/odb/src/ddl.CCMA/poolmask_1.sql
new file mode 120000
index 0000000..b6f8a03
--- /dev/null
+++ b/odb/src/ddl.CCMA/poolmask_1.sql
@@ -0,0 +1 @@
+../ddl/poolmask_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/poolmask_2.sql b/odb/src/ddl.CCMA/poolmask_2.sql
new file mode 120000
index 0000000..5596d64
--- /dev/null
+++ b/odb/src/ddl.CCMA/poolmask_2.sql
@@ -0,0 +1 @@
+../ddl/poolmask_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ppcode.h b/odb/src/ddl.CCMA/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.CCMA/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/privpub.h b/odb/src/ddl.CCMA/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.CCMA/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/prtdpst_robhdr.sql b/odb/src/ddl.CCMA/prtdpst_robhdr.sql
new file mode 120000
index 0000000..e65b878
--- /dev/null
+++ b/odb/src/ddl.CCMA/prtdpst_robhdr.sql
@@ -0,0 +1 @@
+../ddl/prtdpst_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/prtdpst_robody.sql b/odb/src/ddl.CCMA/prtdpst_robody.sql
new file mode 120000
index 0000000..d3a8f06
--- /dev/null
+++ b/odb/src/ddl.CCMA/prtdpst_robody.sql
@@ -0,0 +1 @@
+../ddl/prtdpst_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/radar.h b/odb/src/ddl.CCMA/radar.h
new file mode 120000
index 0000000..79dddc7
--- /dev/null
+++ b/odb/src/ddl.CCMA/radar.h
@@ -0,0 +1 @@
+../ddl/radar.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/radar_station.h b/odb/src/ddl.CCMA/radar_station.h
new file mode 120000
index 0000000..85482f7
--- /dev/null
+++ b/odb/src/ddl.CCMA/radar_station.h
@@ -0,0 +1 @@
+../ddl/radar_station.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/radiance.h b/odb/src/ddl.CCMA/radiance.h
new file mode 120000
index 0000000..62c3289
--- /dev/null
+++ b/odb/src/ddl.CCMA/radiance.h
@@ -0,0 +1 @@
+../ddl/radiance.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/raingg.h b/odb/src/ddl.CCMA/raingg.h
new file mode 120000
index 0000000..3f077a8
--- /dev/null
+++ b/odb/src/ddl.CCMA/raingg.h
@@ -0,0 +1 @@
+../ddl/raingg.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/raingg_body_rr.sql b/odb/src/ddl.CCMA/raingg_body_rr.sql
new file mode 120000
index 0000000..5581b08
--- /dev/null
+++ b/odb/src/ddl.CCMA/raingg_body_rr.sql
@@ -0,0 +1 @@
+../ddl/raingg_body_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/raingg_rr.sql b/odb/src/ddl.CCMA/raingg_rr.sql
new file mode 120000
index 0000000..7edda37
--- /dev/null
+++ b/odb/src/ddl.CCMA/raingg_rr.sql
@@ -0,0 +1 @@
+../ddl/raingg_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/resat.h b/odb/src/ddl.CCMA/resat.h
new file mode 120000
index 0000000..23bd5e9
--- /dev/null
+++ b/odb/src/ddl.CCMA/resat.h
@@ -0,0 +1 @@
+../ddl/resat.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/revmatchup_body.sql b/odb/src/ddl.CCMA/revmatchup_body.sql
new file mode 120000
index 0000000..ebc2394
--- /dev/null
+++ b/odb/src/ddl.CCMA/revmatchup_body.sql
@@ -0,0 +1 @@
+../ddl/revmatchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/revmatchup_hdr.sql b/odb/src/ddl.CCMA/revmatchup_hdr.sql
new file mode 120000
index 0000000..26e5af2
--- /dev/null
+++ b/odb/src/ddl.CCMA/revmatchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/revmatchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr.sql b/odb/src/ddl.CCMA/robhdr.sql
new file mode 120000
index 0000000..40c605d
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr.sql
@@ -0,0 +1 @@
+../ddl/robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_gbrad_get_rr.sql b/odb/src/ddl.CCMA/robhdr_gbrad_get_rr.sql
new file mode 120000
index 0000000..e599f3e
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_gbrad_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_gbrad_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_gbrad_put_rr.sql b/odb/src/ddl.CCMA/robhdr_gbrad_put_rr.sql
new file mode 120000
index 0000000..179b3d7
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_gbrad_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_gbrad_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_grid_distribute.sql b/odb/src/ddl.CCMA/robhdr_grid_distribute.sql
new file mode 120000
index 0000000..5021cd8
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_grid_distribute.sql
@@ -0,0 +1 @@
+../ddl/robhdr_grid_distribute.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_rad.sql b/odb/src/ddl.CCMA/robhdr_rad.sql
new file mode 120000
index 0000000..8b512c5
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_rad.sql
@@ -0,0 +1 @@
+../ddl/robhdr_rad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_raingg_get_rr.sql b/odb/src/ddl.CCMA/robhdr_raingg_get_rr.sql
new file mode 120000
index 0000000..0c23d98
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_raingg_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_raingg_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_raingg_put_rr.sql b/odb/src/ddl.CCMA/robhdr_raingg_put_rr.sql
new file mode 120000
index 0000000..fe0ba4e
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_raingg_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_raingg_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_screen.sql b/odb/src/ddl.CCMA/robhdr_screen.sql
new file mode 120000
index 0000000..f03a2af
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_screen.sql
@@ -0,0 +1 @@
+../ddl/robhdr_screen.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_screen_conv.sql b/odb/src/ddl.CCMA/robhdr_screen_conv.sql
new file mode 120000
index 0000000..c16d295
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_screen_conv.sql
@@ -0,0 +1 @@
+../ddl/robhdr_screen_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdr_tc.sql b/odb/src/ddl.CCMA/robhdr_tc.sql
new file mode 120000
index 0000000..3cddffb
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdr_tc.sql
@@ -0,0 +1 @@
+../ddl/robhdr_tc.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robhdrca_obsort.sql b/odb/src/ddl.CCMA/robhdrca_obsort.sql
new file mode 120000
index 0000000..a0e1f72
--- /dev/null
+++ b/odb/src/ddl.CCMA/robhdrca_obsort.sql
@@ -0,0 +1 @@
+../ddl/robhdrca_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody.sql b/odb/src/ddl.CCMA/robody.sql
new file mode 120000
index 0000000..bb96a50
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody.sql
@@ -0,0 +1 @@
+../ddl/robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_gbrad_get_rr.sql b/odb/src/ddl.CCMA/robody_gbrad_get_rr.sql
new file mode 120000
index 0000000..9d6eb48
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_gbrad_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_gbrad_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_gbrad_put_rr.sql b/odb/src/ddl.CCMA/robody_gbrad_put_rr.sql
new file mode 120000
index 0000000..62f73f0
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_gbrad_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_gbrad_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_rad.sql b/odb/src/ddl.CCMA/robody_rad.sql
new file mode 120000
index 0000000..c9d3765
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_rad.sql
@@ -0,0 +1 @@
+../ddl/robody_rad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_raingg_get_rr.sql b/odb/src/ddl.CCMA/robody_raingg_get_rr.sql
new file mode 120000
index 0000000..902a5ea
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_raingg_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_raingg_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_raingg_put_rr.sql b/odb/src/ddl.CCMA/robody_raingg_put_rr.sql
new file mode 120000
index 0000000..6daee3a
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_raingg_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_raingg_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_tc.sql b/odb/src/ddl.CCMA/robody_tc.sql
new file mode 120000
index 0000000..153efdd
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_tc.sql
@@ -0,0 +1 @@
+../ddl/robody_tc.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/robody_traj.sql b/odb/src/ddl.CCMA/robody_traj.sql
new file mode 120000
index 0000000..bc999c3
--- /dev/null
+++ b/odb/src/ddl.CCMA/robody_traj.sql
@@ -0,0 +1 @@
+../ddl/robody_traj.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat.h b/odb/src/ddl.CCMA/sat.h
new file mode 120000
index 0000000..ffd2d1e
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat.h
@@ -0,0 +1 @@
+../ddl/sat.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_aeolus.sql b/odb/src/ddl.CCMA/sat_aeolus.sql
new file mode 120000
index 0000000..41a113e
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_aeolus.sql
@@ -0,0 +1 @@
+../ddl/sat_aeolus.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_atovs.sql b/odb/src/ddl.CCMA/sat_atovs.sql
new file mode 120000
index 0000000..93d84b0
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_atovs.sql
@@ -0,0 +1 @@
+../ddl/sat_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_gpsro.sql b/odb/src/ddl.CCMA/sat_gpsro.sql
new file mode 120000
index 0000000..0feacd4
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_gpsro.sql
@@ -0,0 +1 @@
+../ddl/sat_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_lrad.sql b/odb/src/ddl.CCMA/sat_lrad.sql
new file mode 120000
index 0000000..b915217
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_lrad.sql
@@ -0,0 +1 @@
+../ddl/sat_lrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_radar.sql b/odb/src/ddl.CCMA/sat_radar.sql
new file mode 120000
index 0000000..ebb7ab2
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_radar.sql
@@ -0,0 +1 @@
+../ddl/sat_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_satob.sql b/odb/src/ddl.CCMA/sat_satob.sql
new file mode 120000
index 0000000..16512f8
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_satob.sql
@@ -0,0 +1 @@
+../ddl/sat_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sat_ssmi.sql b/odb/src/ddl.CCMA/sat_ssmi.sql
new file mode 120000
index 0000000..8891ef8
--- /dev/null
+++ b/odb/src/ddl.CCMA/sat_ssmi.sql
@@ -0,0 +1 @@
+../ddl/sat_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/satbody_allsky.sql b/odb/src/ddl.CCMA/satbody_allsky.sql
new file mode 120000
index 0000000..38b6d05
--- /dev/null
+++ b/odb/src/ddl.CCMA/satbody_allsky.sql
@@ -0,0 +1 @@
+../ddl/satbody_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/satbody_atovs.sql b/odb/src/ddl.CCMA/satbody_atovs.sql
new file mode 120000
index 0000000..2503a7f
--- /dev/null
+++ b/odb/src/ddl.CCMA/satbody_atovs.sql
@@ -0,0 +1 @@
+../ddl/satbody_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/satbody_gpsro.sql b/odb/src/ddl.CCMA/satbody_gpsro.sql
new file mode 120000
index 0000000..d31f469
--- /dev/null
+++ b/odb/src/ddl.CCMA/satbody_gpsro.sql
@@ -0,0 +1 @@
+../ddl/satbody_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/satbody_radar.sql b/odb/src/ddl.CCMA/satbody_radar.sql
new file mode 120000
index 0000000..af71a2d
--- /dev/null
+++ b/odb/src/ddl.CCMA/satbody_radar.sql
@@ -0,0 +1 @@
+../ddl/satbody_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sathdr_cloud_sink.sql b/odb/src/ddl.CCMA/sathdr_cloud_sink.sql
new file mode 120000
index 0000000..231c896
--- /dev/null
+++ b/odb/src/ddl.CCMA/sathdr_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/sathdr_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sathdr_radar.sql b/odb/src/ddl.CCMA/sathdr_radar.sql
new file mode 120000
index 0000000..ccc6c51
--- /dev/null
+++ b/odb/src/ddl.CCMA/sathdr_radar.sql
@@ -0,0 +1 @@
+../ddl/sathdr_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/satob.h b/odb/src/ddl.CCMA/satob.h
new file mode 120000
index 0000000..3230a42
--- /dev/null
+++ b/odb/src/ddl.CCMA/satob.h
@@ -0,0 +1 @@
+../ddl/satob.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/scatt.h b/odb/src/ddl.CCMA/scatt.h
new file mode 120000
index 0000000..0a2840c
--- /dev/null
+++ b/odb/src/ddl.CCMA/scatt.h
@@ -0,0 +1 @@
+../ddl/scatt.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/scatt.sql b/odb/src/ddl.CCMA/scatt.sql
new file mode 120000
index 0000000..7a1a418
--- /dev/null
+++ b/odb/src/ddl.CCMA/scatt.sql
@@ -0,0 +1 @@
+../ddl/scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/scatt_flag.sql b/odb/src/ddl.CCMA/scatt_flag.sql
new file mode 120000
index 0000000..0c9b5a0
--- /dev/null
+++ b/odb/src/ddl.CCMA/scatt_flag.sql
@@ -0,0 +1 @@
+../ddl/scatt_flag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sensor.h b/odb/src/ddl.CCMA/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.CCMA/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/set_active.sql b/odb/src/ddl.CCMA/set_active.sql
new file mode 120000
index 0000000..5381e96
--- /dev/null
+++ b/odb/src/ddl.CCMA/set_active.sql
@@ -0,0 +1 @@
+../ddl/set_active.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/set_active_smos.sql b/odb/src/ddl.CCMA/set_active_smos.sql
new file mode 120000
index 0000000..f432f82
--- /dev/null
+++ b/odb/src/ddl.CCMA/set_active_smos.sql
@@ -0,0 +1 @@
+../ddl/set_active_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/setup_tovscv.sql b/odb/src/ddl.CCMA/setup_tovscv.sql
new file mode 120000
index 0000000..35327f9
--- /dev/null
+++ b/odb/src/ddl.CCMA/setup_tovscv.sql
@@ -0,0 +1 @@
+../ddl/setup_tovscv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/setup_tovscv_cloud_sink.sql b/odb/src/ddl.CCMA/setup_tovscv_cloud_sink.sql
new file mode 120000
index 0000000..4017614
--- /dev/null
+++ b/odb/src/ddl.CCMA/setup_tovscv_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/setup_tovscv_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/small.sql b/odb/src/ddl.CCMA/small.sql
new file mode 120000
index 0000000..4d2f543
--- /dev/null
+++ b/odb/src/ddl.CCMA/small.sql
@@ -0,0 +1 @@
+../ddl/small.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/smos.h b/odb/src/ddl.CCMA/smos.h
new file mode 120000
index 0000000..78794a4
--- /dev/null
+++ b/odb/src/ddl.CCMA/smos.h
@@ -0,0 +1 @@
+../ddl/smos.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/ssmi1d.h b/odb/src/ddl.CCMA/ssmi1d.h
new file mode 120000
index 0000000..716724f
--- /dev/null
+++ b/odb/src/ddl.CCMA/ssmi1d.h
@@ -0,0 +1 @@
+../ddl/ssmi1d.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/stat_obs_1.sql b/odb/src/ddl.CCMA/stat_obs_1.sql
new file mode 120000
index 0000000..f9868fd
--- /dev/null
+++ b/odb/src/ddl.CCMA/stat_obs_1.sql
@@ -0,0 +1 @@
+../ddl/stat_obs_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/sugoms.sql b/odb/src/ddl.CCMA/sugoms.sql
new file mode 120000
index 0000000..27fa4b8
--- /dev/null
+++ b/odb/src/ddl.CCMA/sugoms.sql
@@ -0,0 +1 @@
+../ddl/sugoms.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobarea.sql b/odb/src/ddl.CCMA/suobarea.sql
new file mode 120000
index 0000000..2c557c2
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobarea.sql
@@ -0,0 +1 @@
+../ddl/suobarea.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobarea_limb.sql b/odb/src/ddl.CCMA/suobarea_limb.sql
new file mode 120000
index 0000000..9bce292
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobarea_limb.sql
@@ -0,0 +1 @@
+../ddl/suobarea_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobarea_sat.sql b/odb/src/ddl.CCMA/suobarea_sat.sql
new file mode 120000
index 0000000..a66954c
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobarea_sat.sql
@@ -0,0 +1 @@
+../ddl/suobarea_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobarea_satob.sql b/odb/src/ddl.CCMA/suobarea_satob.sql
new file mode 120000
index 0000000..c0e67a2
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobarea_satob.sql
@@ -0,0 +1 @@
+../ddl/suobarea_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobarea_scatt.sql b/odb/src/ddl.CCMA/suobarea_scatt.sql
new file mode 120000
index 0000000..afbc7bc
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobarea_scatt.sql
@@ -0,0 +1 @@
+../ddl/suobarea_scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobsaddr.sql b/odb/src/ddl.CCMA/suobsaddr.sql
new file mode 120000
index 0000000..51e4131
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobsaddr.sql
@@ -0,0 +1 @@
+../ddl/suobsaddr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobscor_robhdr.sql b/odb/src/ddl.CCMA/suobscor_robhdr.sql
new file mode 120000
index 0000000..be691d3
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobscor_robhdr.sql
@@ -0,0 +1 @@
+../ddl/suobscor_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suobscor_robody.sql b/odb/src/ddl.CCMA/suobscor_robody.sql
new file mode 120000
index 0000000..4840c9d
--- /dev/null
+++ b/odb/src/ddl.CCMA/suobscor_robody.sql
@@ -0,0 +1 @@
+../ddl/suobscor_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/surfbody_feedback.h b/odb/src/ddl.CCMA/surfbody_feedback.h
new file mode 120000
index 0000000..bfe4184
--- /dev/null
+++ b/odb/src/ddl.CCMA/surfbody_feedback.h
@@ -0,0 +1 @@
+../ddl/surfbody_feedback.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suvarbc_robhdr_0.sql b/odb/src/ddl.CCMA/suvarbc_robhdr_0.sql
new file mode 120000
index 0000000..3095dda
--- /dev/null
+++ b/odb/src/ddl.CCMA/suvarbc_robhdr_0.sql
@@ -0,0 +1 @@
+../ddl/suvarbc_robhdr_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/suvarbc_robody_0.sql b/odb/src/ddl.CCMA/suvarbc_robody_0.sql
new file mode 120000
index 0000000..f61b0c2
--- /dev/null
+++ b/odb/src/ddl.CCMA/suvarbc_robody_0.sql
@@ -0,0 +1 @@
+../ddl/suvarbc_robody_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/swapbytes.h b/odb/src/ddl.CCMA/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.CCMA/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/time_info.sql b/odb/src/ddl.CCMA/time_info.sql
new file mode 120000
index 0000000..847c1a7
--- /dev/null
+++ b/odb/src/ddl.CCMA/time_info.sql
@@ -0,0 +1 @@
+../ddl/time_info.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/time_numtsl.sql b/odb/src/ddl.CCMA/time_numtsl.sql
new file mode 120000
index 0000000..a3f68b5
--- /dev/null
+++ b/odb/src/ddl.CCMA/time_numtsl.sql
@@ -0,0 +1 @@
+../ddl/time_numtsl.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/tslot.sql b/odb/src/ddl.CCMA/tslot.sql
new file mode 120000
index 0000000..be7bbab
--- /dev/null
+++ b/odb/src/ddl.CCMA/tslot.sql
@@ -0,0 +1 @@
+../ddl/tslot.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/type_definitions.h b/odb/src/ddl.CCMA/type_definitions.h
new file mode 120000
index 0000000..3711447
--- /dev/null
+++ b/odb/src/ddl.CCMA/type_definitions.h
@@ -0,0 +1 @@
+../ddl/type_definitions.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update.h b/odb/src/ddl.CCMA/update.h
new file mode 120000
index 0000000..8068022
--- /dev/null
+++ b/odb/src/ddl.CCMA/update.h
@@ -0,0 +1 @@
+../ddl/update.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_desc_1.sql b/odb/src/ddl.CCMA/update_desc_1.sql
new file mode 120000
index 0000000..bf1795e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_desc_1.sql
@@ -0,0 +1 @@
+../ddl/update_desc_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_desc_2.sql b/odb/src/ddl.CCMA/update_desc_2.sql
new file mode 120000
index 0000000..721686d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_desc_2.sql
@@ -0,0 +1 @@
+../ddl/update_desc_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_enkf_links.sql b/odb/src/ddl.CCMA/update_enkf_links.sql
new file mode 120000
index 0000000..b508939
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_enkf_links.sql
@@ -0,0 +1 @@
+../ddl/update_enkf_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_1.sql b/odb/src/ddl.CCMA/update_hprior_1.sql
new file mode 120000
index 0000000..a294c35
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_1.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_10.sql b/odb/src/ddl.CCMA/update_hprior_10.sql
new file mode 120000
index 0000000..8e40778
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_10.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_100.sql b/odb/src/ddl.CCMA/update_hprior_100.sql
new file mode 120000
index 0000000..615477a
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_100.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_100.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_101.sql b/odb/src/ddl.CCMA/update_hprior_101.sql
new file mode 120000
index 0000000..6b49671
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_101.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_101.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_102.sql b/odb/src/ddl.CCMA/update_hprior_102.sql
new file mode 120000
index 0000000..389dc9e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_102.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_102.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_103.sql b/odb/src/ddl.CCMA/update_hprior_103.sql
new file mode 120000
index 0000000..cf8a654
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_103.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_103.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_104.sql b/odb/src/ddl.CCMA/update_hprior_104.sql
new file mode 120000
index 0000000..0fbaedf
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_104.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_104.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_105.sql b/odb/src/ddl.CCMA/update_hprior_105.sql
new file mode 120000
index 0000000..dcda9c9
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_105.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_105.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_106.sql b/odb/src/ddl.CCMA/update_hprior_106.sql
new file mode 120000
index 0000000..bce8309
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_106.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_106.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_107.sql b/odb/src/ddl.CCMA/update_hprior_107.sql
new file mode 120000
index 0000000..2256c94
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_107.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_107.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_108.sql b/odb/src/ddl.CCMA/update_hprior_108.sql
new file mode 120000
index 0000000..681b74c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_108.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_108.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_109.sql b/odb/src/ddl.CCMA/update_hprior_109.sql
new file mode 120000
index 0000000..b33f97e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_109.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_109.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_11.sql b/odb/src/ddl.CCMA/update_hprior_11.sql
new file mode 120000
index 0000000..c16ea0c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_11.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_110.sql b/odb/src/ddl.CCMA/update_hprior_110.sql
new file mode 120000
index 0000000..2d70a2e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_110.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_110.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_111.sql b/odb/src/ddl.CCMA/update_hprior_111.sql
new file mode 120000
index 0000000..73d14fc
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_111.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_111.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_112.sql b/odb/src/ddl.CCMA/update_hprior_112.sql
new file mode 120000
index 0000000..13ea414
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_112.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_112.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_113.sql b/odb/src/ddl.CCMA/update_hprior_113.sql
new file mode 120000
index 0000000..a16c1e9
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_113.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_113.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_114.sql b/odb/src/ddl.CCMA/update_hprior_114.sql
new file mode 120000
index 0000000..efda5c8
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_114.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_114.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_115.sql b/odb/src/ddl.CCMA/update_hprior_115.sql
new file mode 120000
index 0000000..169bb81
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_115.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_115.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_116.sql b/odb/src/ddl.CCMA/update_hprior_116.sql
new file mode 120000
index 0000000..6973f3c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_116.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_116.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_117.sql b/odb/src/ddl.CCMA/update_hprior_117.sql
new file mode 120000
index 0000000..d21e5dd
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_117.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_117.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_118.sql b/odb/src/ddl.CCMA/update_hprior_118.sql
new file mode 120000
index 0000000..7be3cd9
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_118.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_118.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_119.sql b/odb/src/ddl.CCMA/update_hprior_119.sql
new file mode 120000
index 0000000..dc08d15
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_119.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_119.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_12.sql b/odb/src/ddl.CCMA/update_hprior_12.sql
new file mode 120000
index 0000000..9970716
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_12.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_12.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_120.sql b/odb/src/ddl.CCMA/update_hprior_120.sql
new file mode 120000
index 0000000..4804497
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_120.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_120.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_13.sql b/odb/src/ddl.CCMA/update_hprior_13.sql
new file mode 120000
index 0000000..3175c0e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_13.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_13.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_14.sql b/odb/src/ddl.CCMA/update_hprior_14.sql
new file mode 120000
index 0000000..5a2e772
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_14.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_14.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_15.sql b/odb/src/ddl.CCMA/update_hprior_15.sql
new file mode 120000
index 0000000..e9e2fa1
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_15.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_15.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_16.sql b/odb/src/ddl.CCMA/update_hprior_16.sql
new file mode 120000
index 0000000..4a945db
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_16.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_16.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_17.sql b/odb/src/ddl.CCMA/update_hprior_17.sql
new file mode 120000
index 0000000..36854a2
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_17.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_17.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_18.sql b/odb/src/ddl.CCMA/update_hprior_18.sql
new file mode 120000
index 0000000..ddd8cc4
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_18.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_18.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_19.sql b/odb/src/ddl.CCMA/update_hprior_19.sql
new file mode 120000
index 0000000..5c4e73f
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_19.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_19.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_2.sql b/odb/src/ddl.CCMA/update_hprior_2.sql
new file mode 120000
index 0000000..d5258bb
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_2.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_20.sql b/odb/src/ddl.CCMA/update_hprior_20.sql
new file mode 120000
index 0000000..05fb1eb
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_20.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_20.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_21.sql b/odb/src/ddl.CCMA/update_hprior_21.sql
new file mode 120000
index 0000000..d0c37eb
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_21.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_21.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_22.sql b/odb/src/ddl.CCMA/update_hprior_22.sql
new file mode 120000
index 0000000..a8d9650
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_22.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_22.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_23.sql b/odb/src/ddl.CCMA/update_hprior_23.sql
new file mode 120000
index 0000000..c37fc2d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_23.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_23.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_24.sql b/odb/src/ddl.CCMA/update_hprior_24.sql
new file mode 120000
index 0000000..4018ad4
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_24.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_24.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_25.sql b/odb/src/ddl.CCMA/update_hprior_25.sql
new file mode 120000
index 0000000..5b20e1c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_25.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_25.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_26.sql b/odb/src/ddl.CCMA/update_hprior_26.sql
new file mode 120000
index 0000000..bcceb54
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_26.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_26.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_27.sql b/odb/src/ddl.CCMA/update_hprior_27.sql
new file mode 120000
index 0000000..c00eaee
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_27.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_27.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_28.sql b/odb/src/ddl.CCMA/update_hprior_28.sql
new file mode 120000
index 0000000..d82d543
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_28.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_28.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_29.sql b/odb/src/ddl.CCMA/update_hprior_29.sql
new file mode 120000
index 0000000..39602ca
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_29.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_29.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_3.sql b/odb/src/ddl.CCMA/update_hprior_3.sql
new file mode 120000
index 0000000..960f13d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_3.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_30.sql b/odb/src/ddl.CCMA/update_hprior_30.sql
new file mode 120000
index 0000000..7f6a7f2
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_30.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_30.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_31.sql b/odb/src/ddl.CCMA/update_hprior_31.sql
new file mode 120000
index 0000000..f30157d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_31.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_31.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_32.sql b/odb/src/ddl.CCMA/update_hprior_32.sql
new file mode 120000
index 0000000..4f43f68
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_32.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_32.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_33.sql b/odb/src/ddl.CCMA/update_hprior_33.sql
new file mode 120000
index 0000000..de9c2fe
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_33.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_33.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_34.sql b/odb/src/ddl.CCMA/update_hprior_34.sql
new file mode 120000
index 0000000..56999ef
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_34.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_34.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_35.sql b/odb/src/ddl.CCMA/update_hprior_35.sql
new file mode 120000
index 0000000..6bf7f18
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_35.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_35.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_36.sql b/odb/src/ddl.CCMA/update_hprior_36.sql
new file mode 120000
index 0000000..02c4832
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_36.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_36.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_37.sql b/odb/src/ddl.CCMA/update_hprior_37.sql
new file mode 120000
index 0000000..97acb87
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_37.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_37.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_38.sql b/odb/src/ddl.CCMA/update_hprior_38.sql
new file mode 120000
index 0000000..7bfe757
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_38.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_38.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_39.sql b/odb/src/ddl.CCMA/update_hprior_39.sql
new file mode 120000
index 0000000..fc0ec33
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_39.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_39.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_4.sql b/odb/src/ddl.CCMA/update_hprior_4.sql
new file mode 120000
index 0000000..1dcad03
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_4.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_40.sql b/odb/src/ddl.CCMA/update_hprior_40.sql
new file mode 120000
index 0000000..da8767a
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_40.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_40.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_41.sql b/odb/src/ddl.CCMA/update_hprior_41.sql
new file mode 120000
index 0000000..df0698f
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_41.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_41.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_42.sql b/odb/src/ddl.CCMA/update_hprior_42.sql
new file mode 120000
index 0000000..48caf16
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_42.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_42.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_43.sql b/odb/src/ddl.CCMA/update_hprior_43.sql
new file mode 120000
index 0000000..838ad87
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_43.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_43.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_44.sql b/odb/src/ddl.CCMA/update_hprior_44.sql
new file mode 120000
index 0000000..8f19d91
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_44.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_44.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_45.sql b/odb/src/ddl.CCMA/update_hprior_45.sql
new file mode 120000
index 0000000..b5ac61c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_45.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_45.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_46.sql b/odb/src/ddl.CCMA/update_hprior_46.sql
new file mode 120000
index 0000000..f87d955
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_46.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_46.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_47.sql b/odb/src/ddl.CCMA/update_hprior_47.sql
new file mode 120000
index 0000000..bc7fc05
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_47.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_47.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_48.sql b/odb/src/ddl.CCMA/update_hprior_48.sql
new file mode 120000
index 0000000..5728af7
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_48.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_48.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_49.sql b/odb/src/ddl.CCMA/update_hprior_49.sql
new file mode 120000
index 0000000..179b487
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_49.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_49.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_5.sql b/odb/src/ddl.CCMA/update_hprior_5.sql
new file mode 120000
index 0000000..e6fed9f
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_5.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_50.sql b/odb/src/ddl.CCMA/update_hprior_50.sql
new file mode 120000
index 0000000..bfe2f65
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_50.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_50.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_51.sql b/odb/src/ddl.CCMA/update_hprior_51.sql
new file mode 120000
index 0000000..046914c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_51.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_51.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_52.sql b/odb/src/ddl.CCMA/update_hprior_52.sql
new file mode 120000
index 0000000..bce7331
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_52.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_52.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_53.sql b/odb/src/ddl.CCMA/update_hprior_53.sql
new file mode 120000
index 0000000..f3da957
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_53.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_53.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_54.sql b/odb/src/ddl.CCMA/update_hprior_54.sql
new file mode 120000
index 0000000..2f4e60d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_54.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_54.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_55.sql b/odb/src/ddl.CCMA/update_hprior_55.sql
new file mode 120000
index 0000000..f66625f
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_55.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_55.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_56.sql b/odb/src/ddl.CCMA/update_hprior_56.sql
new file mode 120000
index 0000000..1ebcd42
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_56.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_56.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_57.sql b/odb/src/ddl.CCMA/update_hprior_57.sql
new file mode 120000
index 0000000..b37cbff
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_57.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_57.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_58.sql b/odb/src/ddl.CCMA/update_hprior_58.sql
new file mode 120000
index 0000000..629da8d
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_58.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_58.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_59.sql b/odb/src/ddl.CCMA/update_hprior_59.sql
new file mode 120000
index 0000000..652a1f0
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_59.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_59.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_6.sql b/odb/src/ddl.CCMA/update_hprior_6.sql
new file mode 120000
index 0000000..be02f09
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_6.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_60.sql b/odb/src/ddl.CCMA/update_hprior_60.sql
new file mode 120000
index 0000000..6ed4caf
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_60.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_60.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_61.sql b/odb/src/ddl.CCMA/update_hprior_61.sql
new file mode 120000
index 0000000..9780163
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_61.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_61.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_62.sql b/odb/src/ddl.CCMA/update_hprior_62.sql
new file mode 120000
index 0000000..f71cc64
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_62.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_62.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_63.sql b/odb/src/ddl.CCMA/update_hprior_63.sql
new file mode 120000
index 0000000..86fc0a8
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_63.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_63.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_64.sql b/odb/src/ddl.CCMA/update_hprior_64.sql
new file mode 120000
index 0000000..3e0e982
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_64.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_64.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_65.sql b/odb/src/ddl.CCMA/update_hprior_65.sql
new file mode 120000
index 0000000..fc6d6a6
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_65.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_65.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_66.sql b/odb/src/ddl.CCMA/update_hprior_66.sql
new file mode 120000
index 0000000..3974e57
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_66.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_66.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_67.sql b/odb/src/ddl.CCMA/update_hprior_67.sql
new file mode 120000
index 0000000..b3f9d56
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_67.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_67.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_68.sql b/odb/src/ddl.CCMA/update_hprior_68.sql
new file mode 120000
index 0000000..859e6f5
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_68.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_68.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_69.sql b/odb/src/ddl.CCMA/update_hprior_69.sql
new file mode 120000
index 0000000..46d8bd2
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_69.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_69.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_7.sql b/odb/src/ddl.CCMA/update_hprior_7.sql
new file mode 120000
index 0000000..f91a67c
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_7.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_70.sql b/odb/src/ddl.CCMA/update_hprior_70.sql
new file mode 120000
index 0000000..2b8d92e
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_70.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_70.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_71.sql b/odb/src/ddl.CCMA/update_hprior_71.sql
new file mode 120000
index 0000000..4be7a23
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_71.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_71.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_72.sql b/odb/src/ddl.CCMA/update_hprior_72.sql
new file mode 120000
index 0000000..aa1e7d6
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_72.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_72.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_73.sql b/odb/src/ddl.CCMA/update_hprior_73.sql
new file mode 120000
index 0000000..c207ee0
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_73.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_73.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_74.sql b/odb/src/ddl.CCMA/update_hprior_74.sql
new file mode 120000
index 0000000..d6b6f07
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_74.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_74.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_75.sql b/odb/src/ddl.CCMA/update_hprior_75.sql
new file mode 120000
index 0000000..7e0c6a3
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_75.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_75.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_76.sql b/odb/src/ddl.CCMA/update_hprior_76.sql
new file mode 120000
index 0000000..e0b1782
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_76.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_76.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_77.sql b/odb/src/ddl.CCMA/update_hprior_77.sql
new file mode 120000
index 0000000..1f7a0cf
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_77.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_77.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_78.sql b/odb/src/ddl.CCMA/update_hprior_78.sql
new file mode 120000
index 0000000..4213679
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_78.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_78.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_79.sql b/odb/src/ddl.CCMA/update_hprior_79.sql
new file mode 120000
index 0000000..fa1c502
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_79.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_79.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_8.sql b/odb/src/ddl.CCMA/update_hprior_8.sql
new file mode 120000
index 0000000..85aada7
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_8.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_80.sql b/odb/src/ddl.CCMA/update_hprior_80.sql
new file mode 120000
index 0000000..67aefa4
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_80.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_80.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_81.sql b/odb/src/ddl.CCMA/update_hprior_81.sql
new file mode 120000
index 0000000..7114a87
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_81.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_81.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_82.sql b/odb/src/ddl.CCMA/update_hprior_82.sql
new file mode 120000
index 0000000..1d79f13
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_82.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_82.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_83.sql b/odb/src/ddl.CCMA/update_hprior_83.sql
new file mode 120000
index 0000000..9944749
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_83.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_83.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_84.sql b/odb/src/ddl.CCMA/update_hprior_84.sql
new file mode 120000
index 0000000..b470eb8
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_84.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_84.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_85.sql b/odb/src/ddl.CCMA/update_hprior_85.sql
new file mode 120000
index 0000000..a1276eb
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_85.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_85.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_86.sql b/odb/src/ddl.CCMA/update_hprior_86.sql
new file mode 120000
index 0000000..fd95579
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_86.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_86.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_87.sql b/odb/src/ddl.CCMA/update_hprior_87.sql
new file mode 120000
index 0000000..98f03f6
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_87.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_87.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_88.sql b/odb/src/ddl.CCMA/update_hprior_88.sql
new file mode 120000
index 0000000..ea74870
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_88.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_88.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_89.sql b/odb/src/ddl.CCMA/update_hprior_89.sql
new file mode 120000
index 0000000..0aa85b8
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_89.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_89.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_9.sql b/odb/src/ddl.CCMA/update_hprior_9.sql
new file mode 120000
index 0000000..4320e82
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_9.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_90.sql b/odb/src/ddl.CCMA/update_hprior_90.sql
new file mode 120000
index 0000000..a5b496a
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_90.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_90.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_91.sql b/odb/src/ddl.CCMA/update_hprior_91.sql
new file mode 120000
index 0000000..66515f0
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_91.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_91.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_92.sql b/odb/src/ddl.CCMA/update_hprior_92.sql
new file mode 120000
index 0000000..18722f8
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_92.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_92.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_93.sql b/odb/src/ddl.CCMA/update_hprior_93.sql
new file mode 120000
index 0000000..66eb076
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_93.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_93.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_94.sql b/odb/src/ddl.CCMA/update_hprior_94.sql
new file mode 120000
index 0000000..a5051c9
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_94.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_94.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_95.sql b/odb/src/ddl.CCMA/update_hprior_95.sql
new file mode 120000
index 0000000..414f7f3
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_95.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_95.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_96.sql b/odb/src/ddl.CCMA/update_hprior_96.sql
new file mode 120000
index 0000000..c1a6e5f
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_96.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_96.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_97.sql b/odb/src/ddl.CCMA/update_hprior_97.sql
new file mode 120000
index 0000000..fd0fcb4
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_97.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_97.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_98.sql b/odb/src/ddl.CCMA/update_hprior_98.sql
new file mode 120000
index 0000000..7182a78
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_98.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_98.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/update_hprior_99.sql b/odb/src/ddl.CCMA/update_hprior_99.sql
new file mode 120000
index 0000000..ad2d381
--- /dev/null
+++ b/odb/src/ddl.CCMA/update_hprior_99.sql
@@ -0,0 +1 @@
+../ddl/update_hprior_99.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_allsky_robhdr.sql b/odb/src/ddl.CCMA/varbc_allsky_robhdr.sql
new file mode 120000
index 0000000..694efab
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_allsky_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_allsky_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_allsky_robody.sql b/odb/src/ddl.CCMA/varbc_allsky_robody.sql
new file mode 120000
index 0000000..281add1
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_allsky_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_allsky_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_gbrad_robhdr.sql b/odb/src/ddl.CCMA/varbc_gbrad_robhdr.sql
new file mode 120000
index 0000000..ad11101
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_gbrad_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_gbrad_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_gbrad_robody.sql b/odb/src/ddl.CCMA/varbc_gbrad_robody.sql
new file mode 120000
index 0000000..42d0ecb
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_gbrad_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_gbrad_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_rad_robhdr.sql b/odb/src/ddl.CCMA/varbc_rad_robhdr.sql
new file mode 120000
index 0000000..fbd8182
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_rad_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_rad_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_rad_robody.sql b/odb/src/ddl.CCMA/varbc_rad_robody.sql
new file mode 120000
index 0000000..959a958
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_rad_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_rad_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_setup_robhdr.sql b/odb/src/ddl.CCMA/varbc_setup_robhdr.sql
new file mode 120000
index 0000000..40ea481
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_setup_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_setup_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_setup_robody.sql b/odb/src/ddl.CCMA/varbc_setup_robody.sql
new file mode 120000
index 0000000..884a2ce
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_setup_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_setup_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_sfcobs_robhdr.sql b/odb/src/ddl.CCMA/varbc_sfcobs_robhdr.sql
new file mode 120000
index 0000000..cc0d75b
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_sfcobs_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_sfcobs_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_sfcobs_robody.sql b/odb/src/ddl.CCMA/varbc_sfcobs_robody.sql
new file mode 120000
index 0000000..3bab245
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_sfcobs_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_sfcobs_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_tcwv_robhdr.sql b/odb/src/ddl.CCMA/varbc_tcwv_robhdr.sql
new file mode 120000
index 0000000..0e83d64
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_tcwv_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_tcwv_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_tcwv_robody.sql b/odb/src/ddl.CCMA/varbc_tcwv_robody.sql
new file mode 120000
index 0000000..a9650f9
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_tcwv_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_tcwv_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_to3_robhdr.sql b/odb/src/ddl.CCMA/varbc_to3_robhdr.sql
new file mode 120000
index 0000000..5442c5b
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_to3_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_to3_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varbc_to3_robody.sql b/odb/src/ddl.CCMA/varbc_to3_robody.sql
new file mode 120000
index 0000000..26bebf9
--- /dev/null
+++ b/odb/src/ddl.CCMA/varbc_to3_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_to3_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/varno.h b/odb/src/ddl.CCMA/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.CCMA/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.CCMA/vertco_type.h b/odb/src/ddl.CCMA/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.CCMA/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/CMakeLists.txt b/odb/src/ddl.COUNTRYRSTRHBIAS/CMakeLists.txt
new file mode 100644
index 0000000..0e3b44c
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/CMakeLists.txt
@@ -0,0 +1,44 @@
+set(sources
+
+    COUNTRYRSTRHBIAS.ddl
+    aeolus.h
+    allsky.h
+    auxiliary.h
+    body.h
+    cloud_sink.h
+    cma.h
+    collocated_imager_information.h
+    conv.h
+    ensemble.h
+    errstat.h
+    forecast_diagnostic.h
+    gbrad.h
+    gnssro.h
+    hdr.h
+    idx.h
+    limb.h
+    mdi.h
+    modsurf.h
+    obstype.h
+    ppcode.h
+    radar.h
+    radar_station.h
+    radiance.h
+    raingg.h
+    resat.h
+    sat.h
+    satob.h
+    scatt.h
+    sensor.h
+    smos.h
+    ssmi1d.h
+    surfbody_feedback.h
+    type_definitions.h
+    update.h
+    varno.h
+    vertco_type.h
+)
+
+set(views countryrstrhbody.sql countryrstrhhdr.sql)
+
+odb_add_schema(TARGET COUNTRYRSTRHBIAS SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_COUNTRYRSTRHBIAS TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.ddl b/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.ddl
new file mode 100644
index 0000000..e1baba7
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.ddl
@@ -0,0 +1,113 @@
+//
+//  COUNTRYRSTRHBIAS hierarchy:
+//
+//      1  desc
+//      2  +---> hdr
+//      2  +--------> body
+//
+
+CREATE TABLE desc AS (
+// creation date, time and created by whom (username)
+creadate YYYYMMDD,
+creatime HHMMSS,
+creaby   string,
+
+// modification date, time and modified by whom (username)
+moddate YYYYMMDD,
+modtime HHMMSS,
+modby   string,
+);
+
+CREATE TABLE hdr AS (
+  seqno pk1int,                        //     1 SEQUENCE NO
+  country_group_code pk1int,           //     2 COUNTRY GROUP CODE
+  country_statid_from_i pk1int,        //     3 COUNTRY STAT ID FROM
+  country_statid_from_c string,        //     4 COUNTRY STAT ID FROM
+  country_statid_to_i pk1int,          //     5 COUNTRY STAT ID TO
+  country_statid_to_c string,          //     6 COUNTRY STAT ID TO
+  country_lat_from pk1int,             //     7 COUNTRY LAT FROM
+  country_lat_to pk1int,               //     8 COUNTRY LAT TO
+  country_lon_from pk1int,             //     9 COUNTRY LON FROM
+  country_lon_to pk1int,               //    10 COUNTRY LON TO
+  country_name[8] string,              // 11-18 COUNTRY NAME
+  country_name_with_lat_lon[8] string, // 19-26 COUNTRY NAME WITH ATTACHED LAT/LON BOUNDS FOR SOME OF THEM
+  country_grouped_seqno pk1int,        //    27 COUNTRY GROUPED SEQUENCE NO
+  country_name_grouped[8] string,      // 28-35 COUNTRY NAME GROUPED
+  body @LINK,                          // 36-37 Offset, len
+);
+
+CREATE TABLE body AS (
+  press pk9real,                 //  1 VERTICAL COORDINATE (PRESSURE)
+
+  T_N_m75 pk1int,                    //  2 No. of T data FOR ANGLEs up TO -7.5
+  T_N_m75_75 pk1int,                 //  3 No. of T data FOR ANGLEs -7.5 to 7.5
+  T_N_75_225 pk1int,                 //  4 No. of T data FOR ANGLEs 7.5 to 22.5
+  T_N_225 pk1int,                    //  5 No. of T data FOR ANGLEs above 22.5
+  T_N_mean pk1int,                   //  6 No. of T data FOR MEAN
+
+  T_D_m75 pk9real,                   //  7 T Uncorrected Departures FOR ANGLEs up TO -7.5
+  T_D_m75_75 pk9real,                //  8 T Uncorrected Departures FOR ANGLEs -7.5 to 7.5
+  T_D_75_225 pk9real,                //  9 T Uncorrected Departures FOR ANGLEs 7.5 to 22.5
+  T_D_225 pk9real,                   // 10 T Uncorrected Departures FOR ANGLEs above 22.5
+  T_D_mean pk9real,                  // 11 T Uncorrected Departures FOR MEAN
+
+  T_C_m75 pk9real,                   // 12 T Corrected Departures FOR ANGLEs up TO -7.5
+  T_C_m75_75 pk9real,                // 13 T Corrected Departures FOR ANGLEs -7.5 to 7.5
+  T_C_75_225 pk9real,                // 14 T Corrected Departures FOR ANGLEs 7.5 to 22.5
+  T_C_225 pk9real,                   // 15 T Corrected Departures FOR ANGLEs above 22.5
+  T_C_mean pk9real,                  // 16 T Corrected Departures FOR MEAN
+ 
+  T_B_m75_vs_all_mean pk9real,       // 17 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs ALL MEAN
+  T_B_m75_75_vs_all_mean pk9real,    // 18 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  T_B_75_225_vs_all_mean pk9real,    // 19 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  T_B_225_vs_all_mean pk9real,       // 20 T SOLAR BIAS FOR ANGLEs above 22.5 vs ALL MEAN
+  T_B_all_mean pk9real,              // 21 T MEAN BIAS ALL MEAN
+  
+  T_B_m75_vs_night_mean pk9real,     // 22 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs NIGHT MEAN 
+  T_B_m75_75_vs_night_mean pk9real,  // 23 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs NIGHT MEAN
+  T_B_75_225_vs_night_mean pk9real,  // 24 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs NIGHT MEAN
+  T_B_225_vs_night_mean pk9real,     // 25 T SOLAR BIAS FOR ANGLEs above 22.5 vs NIGHT MEAN
+  T_B_night_mean pk9real,            // 26 T MEAN BIAS NIGHT MEAN
+
+  T_B_m75_vs_day_mean pk9real,       // 27 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs DAY MEAN
+  T_B_m75_75_vs_day_mean pk9real,    // 28 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs DAY MEAN
+  T_B_75_225_vs_day_mean pk9real,    // 29 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs DAY MEAN
+  T_B_225_vs_day_mean pk9real,       // 30 T SOLAR BIAS FOR ANGLEs above 22.5 vs DAY MEAN
+  T_B_day_mean pk9real,              // 31 T MEAN BIAS DAY MEAN
+
+  RH_N_m75 pk1int,                   // 32 No. of RH data FOR ANGLEs up TO -7.5
+  RH_N_m75_75 pk1int,                // 33 No. of RH data FOR ANGLEs -7.5 to 7.5
+  RH_N_75_225 pk1int,                // 34 No. of RH data FOR ANGLEs 7.5 to 22.5
+  RH_N_225 pk1int,                   // 35 No. of RH data FOR ANGLEs above 22.5
+  RH_N_mean pk1int,                  // 36 No. of RH data FOR MEAN
+
+  RH_D_m75 pk9real,                  // 37 RH Uncorrected Departures FOR ANGLEs up TO -7.5
+  RH_D_m75_75 pk9real,               // 38 RH Uncorrected Departures FOR ANGLEs -7.5 to 7.5
+  RH_D_75_225 pk9real,               // 39 RH Uncorrected Departures FOR ANGLEs 7.5 to 22.5
+  RH_D_225 pk9real,                  // 40 RH Uncorrected Departures FOR ANGLEs above 22.5
+  RH_D_mean pk9real,                 // 41 RH Uncorrected Departures FOR MEAN
+
+  RH_C_m75 pk9real,                  // 42 RH Corrected Departures FOR ANGLEs up TO -7.5 vs ALL MEAN
+  RH_C_m75_75 pk9real,               // 43 RH Corrected Departures FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  RH_C_75_225 pk9real,               // 44 RH Corrected Departures FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  RH_C_225 pk9real,                  // 45 RH Corrected Departures FOR ANGLEs above 22.5 vs ALL MEAN
+  RH_C_mean pk9real,                 // 46 RH Corrected Departures FOR MEAN
+
+  RH_B_m75_vs_all_mean pk9real,      // 47 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs ALL MEAN
+  RH_B_m75_75_vs_all_mean pk9real,   // 48 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  RH_B_75_225_vs_all_mean pk9real,   // 49 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  RH_B_225_vs_all_mean pk9real,      // 50 RH SOLAR BIAS FOR ANGLEs above 22.5 vs ALL MEAN
+  RH_B_all_mean pk9real,             // 51 RH MEAN BIAS  FOR ALL MEAN
+
+  RH_B_m75_vs_night_mean pk9real,    // 52 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs NIGHT MEAN
+  RH_B_m75_75_vs_night_mean pk9real, // 53 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs NIGHT MEAN
+  RH_B_75_225_vs_night_mean pk9real, // 54 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs NIGHT MEAN
+  RH_B_225_vs_night_mean pk9real,    // 55 RH SOLAR BIAS FOR ANGLEs above 22.5 vs NIGHT MEAN
+  RH_B_night_mean pk9real,           // 56 RH MEAN BIAS FOR NIGHT MEAN
+
+  RH_B_m75_vs_day_mean pk9real,      // 57 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs DAY MEAN
+  RH_B_m75_75_vs_day_mean pk9real,   // 58 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs DAY MEAN
+  RH_B_75_225_vs_day_mean pk9real,   // 59 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs DAY MEAN
+  RH_B_225_vs_day_mean pk9real,      // 60 RH SOLAR BIAS FOR ANGLEs above 22.5 vs DAY MEAN
+  RH_B_day_mean pk9real,             // 61 RH MEAN BIAS FOR DAY MEAN
+);
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.dep b/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.dep
new file mode 100644
index 0000000..a0944a0
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/COUNTRYRSTRHBIAS.dep
@@ -0,0 +1,18 @@
+#-- First version:  02-Feb-2009
+
+DDLS=\
+	COUNTRYRSTRHBIAS.ddl \
+	mdi.inc \
+	obstype.inc \
+	varno.inc \
+	vertco_type.inc \
+	ppcode.inc
+
+TABLES=\
+	desc \
+	hdr \
+	body
+
+VIEWS=\
+	countryrstrhbody \
+	countryrstrhhdr
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/aeolus.h b/odb/src/ddl.COUNTRYRSTRHBIAS/aeolus.h
new file mode 120000
index 0000000..d9f814d
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/aeolus.h
@@ -0,0 +1 @@
+../ddl/aeolus.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/alloc.h b/odb/src/ddl.COUNTRYRSTRHBIAS/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/allsky.h b/odb/src/ddl.COUNTRYRSTRHBIAS/allsky.h
new file mode 120000
index 0000000..0a19265
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/allsky.h
@@ -0,0 +1 @@
+../ddl/allsky.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/auxiliary.h b/odb/src/ddl.COUNTRYRSTRHBIAS/auxiliary.h
new file mode 120000
index 0000000..8ae1b08
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/auxiliary.h
@@ -0,0 +1 @@
+../ddl/auxiliary.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/bits.h b/odb/src/ddl.COUNTRYRSTRHBIAS/bits.h
new file mode 120000
index 0000000..c4ce6ab
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/bits.h
@@ -0,0 +1 @@
+../include/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/body.h b/odb/src/ddl.COUNTRYRSTRHBIAS/body.h
new file mode 120000
index 0000000..ccd0f32
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/body.h
@@ -0,0 +1 @@
+../ddl/body.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/cdrhook.h b/odb/src/ddl.COUNTRYRSTRHBIAS/cdrhook.h
new file mode 120000
index 0000000..4656498
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/cdrhook.h
@@ -0,0 +1 @@
+../include/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/cloud_sink.h b/odb/src/ddl.COUNTRYRSTRHBIAS/cloud_sink.h
new file mode 120000
index 0000000..3cdc586
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/cloud_sink.h
@@ -0,0 +1 @@
+../ddl/cloud_sink.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/cma.h b/odb/src/ddl.COUNTRYRSTRHBIAS/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/collocated_imager_information.h b/odb/src/ddl.COUNTRYRSTRHBIAS/collocated_imager_information.h
new file mode 120000
index 0000000..3b061d6
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/collocated_imager_information.h
@@ -0,0 +1 @@
+../ddl/collocated_imager_information.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/conv.h b/odb/src/ddl.COUNTRYRSTRHBIAS/conv.h
new file mode 120000
index 0000000..9280d6d
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/conv.h
@@ -0,0 +1 @@
+../ddl/conv.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhbody.sql b/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhbody.sql
new file mode 120000
index 0000000..5fbb2fa
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhbody.sql
@@ -0,0 +1 @@
+../ddl/countryrstrhbody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhhdr.sql b/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhhdr.sql
new file mode 120000
index 0000000..4d26bd1
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/countryrstrhhdr.sql
@@ -0,0 +1 @@
+../ddl/countryrstrhhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/dca.h b/odb/src/ddl.COUNTRYRSTRHBIAS/dca.h
new file mode 120000
index 0000000..c1c5561
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/dca.h
@@ -0,0 +1 @@
+../include/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/ecstdlib.h b/odb/src/ddl.COUNTRYRSTRHBIAS/ecstdlib.h
new file mode 120000
index 0000000..dff2199
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/ecstdlib.h
@@ -0,0 +1 @@
+../include/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/ensemble.h b/odb/src/ddl.COUNTRYRSTRHBIAS/ensemble.h
new file mode 120000
index 0000000..8963a78
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/ensemble.h
@@ -0,0 +1 @@
+../ddl/ensemble.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/errstat.h b/odb/src/ddl.COUNTRYRSTRHBIAS/errstat.h
new file mode 120000
index 0000000..217465a
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/errstat.h
@@ -0,0 +1 @@
+../ddl/errstat.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/forecast_diagnostic.h b/odb/src/ddl.COUNTRYRSTRHBIAS/forecast_diagnostic.h
new file mode 120000
index 0000000..8d17f2d
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/forecast_diagnostic.h
@@ -0,0 +1 @@
+../ddl/forecast_diagnostic.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/funcs.h b/odb/src/ddl.COUNTRYRSTRHBIAS/funcs.h
new file mode 120000
index 0000000..e02a4cd
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/funcs.h
@@ -0,0 +1 @@
+../include/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/gbrad.h b/odb/src/ddl.COUNTRYRSTRHBIAS/gbrad.h
new file mode 120000
index 0000000..a94ed8e
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/gbrad.h
@@ -0,0 +1 @@
+../ddl/gbrad.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/gnssro.h b/odb/src/ddl.COUNTRYRSTRHBIAS/gnssro.h
new file mode 120000
index 0000000..aa94338
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/gnssro.h
@@ -0,0 +1 @@
+../ddl/gnssro.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/hdr.h b/odb/src/ddl.COUNTRYRSTRHBIAS/hdr.h
new file mode 120000
index 0000000..9d10f20
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/hdr.h
@@ -0,0 +1 @@
+../ddl/hdr.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/idx.h b/odb/src/ddl.COUNTRYRSTRHBIAS/idx.h
new file mode 120000
index 0000000..c25b0cc
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/idx.h
@@ -0,0 +1 @@
+../include/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/info.h b/odb/src/ddl.COUNTRYRSTRHBIAS/info.h
new file mode 120000
index 0000000..47734e7
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/info.h
@@ -0,0 +1 @@
+../include/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/limb.h b/odb/src/ddl.COUNTRYRSTRHBIAS/limb.h
new file mode 120000
index 0000000..ab7f4f9
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/limb.h
@@ -0,0 +1 @@
+../ddl/limb.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/magicwords.h b/odb/src/ddl.COUNTRYRSTRHBIAS/magicwords.h
new file mode 120000
index 0000000..48f2e3b
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/magicwords.h
@@ -0,0 +1 @@
+../include/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/mdi.h b/odb/src/ddl.COUNTRYRSTRHBIAS/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/modsurf.h b/odb/src/ddl.COUNTRYRSTRHBIAS/modsurf.h
new file mode 120000
index 0000000..7223f38
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/modsurf.h
@@ -0,0 +1 @@
+../ddl/modsurf.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/namecfg.h b/odb/src/ddl.COUNTRYRSTRHBIAS/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/obstype.h b/odb/src/ddl.COUNTRYRSTRHBIAS/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/odb.h b/odb/src/ddl.COUNTRYRSTRHBIAS/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/odb_macros.h b/odb/src/ddl.COUNTRYRSTRHBIAS/odb_macros.h
new file mode 120000
index 0000000..2082332
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/odb_macros.h
@@ -0,0 +1 @@
+../include/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/odbcrc.h b/odb/src/ddl.COUNTRYRSTRHBIAS/odbcrc.h
new file mode 120000
index 0000000..0313e9d
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/odbcrc.h
@@ -0,0 +1 @@
+../include/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/odbmd5.h b/odb/src/ddl.COUNTRYRSTRHBIAS/odbmd5.h
new file mode 120000
index 0000000..7331ca5
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/odbmd5.h
@@ -0,0 +1 @@
+../include/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/pcma_extern.h b/odb/src/ddl.COUNTRYRSTRHBIAS/pcma_extern.h
new file mode 120000
index 0000000..ef41751
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/pcma_extern.h
@@ -0,0 +1 @@
+../include/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/ppcode.h b/odb/src/ddl.COUNTRYRSTRHBIAS/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/privpub.h b/odb/src/ddl.COUNTRYRSTRHBIAS/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/radar.h b/odb/src/ddl.COUNTRYRSTRHBIAS/radar.h
new file mode 120000
index 0000000..79dddc7
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/radar.h
@@ -0,0 +1 @@
+../ddl/radar.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/radar_station.h b/odb/src/ddl.COUNTRYRSTRHBIAS/radar_station.h
new file mode 120000
index 0000000..85482f7
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/radar_station.h
@@ -0,0 +1 @@
+../ddl/radar_station.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/radiance.h b/odb/src/ddl.COUNTRYRSTRHBIAS/radiance.h
new file mode 120000
index 0000000..62c3289
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/radiance.h
@@ -0,0 +1 @@
+../ddl/radiance.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/raingg.h b/odb/src/ddl.COUNTRYRSTRHBIAS/raingg.h
new file mode 120000
index 0000000..3f077a8
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/raingg.h
@@ -0,0 +1 @@
+../ddl/raingg.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/resat.h b/odb/src/ddl.COUNTRYRSTRHBIAS/resat.h
new file mode 120000
index 0000000..23bd5e9
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/resat.h
@@ -0,0 +1 @@
+../ddl/resat.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/sat.h b/odb/src/ddl.COUNTRYRSTRHBIAS/sat.h
new file mode 120000
index 0000000..ffd2d1e
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/sat.h
@@ -0,0 +1 @@
+../ddl/sat.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/satob.h b/odb/src/ddl.COUNTRYRSTRHBIAS/satob.h
new file mode 120000
index 0000000..3230a42
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/satob.h
@@ -0,0 +1 @@
+../ddl/satob.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/scatt.h b/odb/src/ddl.COUNTRYRSTRHBIAS/scatt.h
new file mode 120000
index 0000000..0a2840c
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/scatt.h
@@ -0,0 +1 @@
+../ddl/scatt.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/sensor.h b/odb/src/ddl.COUNTRYRSTRHBIAS/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/smos.h b/odb/src/ddl.COUNTRYRSTRHBIAS/smos.h
new file mode 120000
index 0000000..78794a4
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/smos.h
@@ -0,0 +1 @@
+../ddl/smos.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/ssmi1d.h b/odb/src/ddl.COUNTRYRSTRHBIAS/ssmi1d.h
new file mode 120000
index 0000000..716724f
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/ssmi1d.h
@@ -0,0 +1 @@
+../ddl/ssmi1d.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/surfbody_feedback.h b/odb/src/ddl.COUNTRYRSTRHBIAS/surfbody_feedback.h
new file mode 120000
index 0000000..bfe4184
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/surfbody_feedback.h
@@ -0,0 +1 @@
+../ddl/surfbody_feedback.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/swapbytes.h b/odb/src/ddl.COUNTRYRSTRHBIAS/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/type_definitions.h b/odb/src/ddl.COUNTRYRSTRHBIAS/type_definitions.h
new file mode 120000
index 0000000..3711447
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/type_definitions.h
@@ -0,0 +1 @@
+../ddl/type_definitions.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/update.h b/odb/src/ddl.COUNTRYRSTRHBIAS/update.h
new file mode 120000
index 0000000..8068022
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/update.h
@@ -0,0 +1 @@
+../ddl/update.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/varno.h b/odb/src/ddl.COUNTRYRSTRHBIAS/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.COUNTRYRSTRHBIAS/vertco_type.h b/odb/src/ddl.COUNTRYRSTRHBIAS/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.COUNTRYRSTRHBIAS/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/CMakeLists.txt b/odb/src/ddl.ECMA/CMakeLists.txt
new file mode 100644
index 0000000..859c844
--- /dev/null
+++ b/odb/src/ddl.ECMA/CMakeLists.txt
@@ -0,0 +1,597 @@
+set(sources
+
+    ECMA.ddl
+
+    aeolus.h
+    allsky.h
+    auxiliary.h
+    body.h
+    cloud_sink.h
+    cma.h
+    collocated_imager_information.h
+    conv.h
+    errstat.h
+    forecast_diagnostic.h
+    gbrad.h
+    gnssro.h
+    hdr.h
+    idx.h
+    limb.h
+    mdi.h
+    modsurf.h
+    obstype.h
+    ppcode.h
+    radar.h
+    radar_station.h
+    radiance.h
+    raingg.h
+    resat.h
+    sat.h
+    satob.h
+    scatt.h
+    sensor.h
+    smos.h
+    ssmi1d.h
+    surfbody_feedback.h
+    type_definitions.h
+    update.h
+    varno.h
+    vertco_type.h
+)
+
+set(views
+
+    adjust_distribid.sql
+    aeolus_auxmet_update_hdrflag.sql
+    airep_flight_phase_robhdr.sql
+    airep_flight_phase_robody.sql
+    airs.sql
+    airs_flag.sql
+    ak_resat_averaging_kernel.sql
+    allsky_update_links.sql
+    amv.sql
+    amv2.sql
+    amv_flag.sql
+    amv_flag2.sql
+    ascatsm_robhdr_1.sql
+    ascatsm_robody_1.sql
+    averaging_smos.sql
+    bator_hdr_1.sql
+    bator_hdr_2.sql
+    bator_hdr_3.sql
+    bator_hdr_4.sql
+    bator_hdr_5.sql
+    bator_hdr_6.sql
+    black_robhdr_1.sql
+    black_robhdr_10.sql
+    black_robhdr_2.sql
+    black_robhdr_3.sql
+    black_robhdr_4.sql
+    black_robhdr_7.sql
+    black_robhdr_8.sql
+    black_robhdr_9.sql
+    black_robody_1.sql
+    black_robody_10.sql
+    black_robody_2.sql
+    black_robody_3.sql
+    black_robody_4.sql
+    black_robody_7.sql
+    black_robody_8.sql
+    black_robody_9.sql
+    btemdup_robhdr_1.sql
+    caifc1.sql
+    camelo_robhdr.sql
+    camelo_robody.sql
+    canaco_robhdr.sql
+    canaco_robody.sql
+    cancer_robhdr.sql
+    cancer_robody.sql
+    cantik_robhdr.sql
+    cantik_robody.sql
+    carcfo.sql
+    caredo_robhdr.sql
+    caredo_robody.sql
+    castor.sql
+    caviso_robhdr.sql
+    caviso_robody.sql
+    cavodk_robhdr.sql
+    cavodk_robody.sql
+    check_linksdb.sql
+    conv_hdr.sql
+    conv_update_links.sql
+    conventional_robhdr_1.sql
+    conventional_robody_1.sql
+    count_orbit.sql
+    count_scanpos.sql
+    cycle_biasprep_robhdr.sql
+    cycle_biasprep_robody.sql
+    cycle_biasprep_sathdr.sql
+    cycle_biasprep_satpred.sql
+    data_radar_station.sql
+    date_time.sql
+    decis_convbody_1.sql
+    decis_convbody_2.sql
+    decis_robhdr_1.sql
+    decis_robhdr_2.sql
+    decis_robhdr_3.sql
+    decis_robhdr_4.sql
+    decis_robody_1.sql
+    decis_robody_2.sql
+    decis_robody_3.sql
+    decis_robody_4.sql
+    discard_dep_1.sql
+    discard_dep_2.sql
+    dmsprainy.sql
+    ecma_body_4_psbias.sql
+    ecma_body_4_rstrhbias.sql
+    ecma_hdr_4_psbias.sql
+    ecma_hdr_4_rstrhbias.sql
+    ecmwf_matchup_allsky_body.sql
+    ecmwf_matchup_body.sql
+    ecmwf_matchup_gbrad.sql
+    ecmwf_matchup_hdr.sql
+    ecmwf_matchup_raingg.sql
+    ecmwf_matchup_update_1.sql
+    ecmwf_matchup_update_2.sql
+    ecmwf_matchup_update_3.sql
+    ecmwf_matchupsink.sql
+    ecset.sql
+    emiskf_amsua.sql
+    emiskf_amsub.sql
+    emiskf_atms.sql
+    emiskf_mhs.sql
+    emiskf_mwts2.sql
+    exp_info_1.sql
+    fcq_robhdr_0.sql
+    fcq_robhdr_1.sql
+    fcq_robhdr_2.sql
+    fcq_robody_0.sql
+    fcq_robody_1.sql
+    fcq_robody_2.sql
+    fix_date_and_time.sql
+    fixresatlen.sql
+    flago_mobhdr.sql
+    flago_mobody.sql
+    gather4poolmask.sql
+    gather4poolmask_counts.sql
+    gbrad_body_rr.sql
+    gbrad_rr.sql
+    gbrad_update_links.sql
+    get_soe_resat.sql
+    getairepid.sql
+    getgbradid.sql
+    getlimbid.sql
+    getsatid.sql
+    getsatid_resat.sql
+    getsatobid.sql
+    getsfcobsid.sql
+    gnssro_update_links.sql
+    gpsro_2.sql
+    hdr_update_links.sql
+    hop_canari_conv.sql
+    hop_canari_robhdr.sql
+    hop_canari_robody.sql
+    hretr_canari_robody.sql
+    hretr_canari_satbody.sql
+    init_update_1.sql
+    init_update_2.sql
+    init_update_3.sql
+    level1cgeos_robhdr_1.sql
+    level1cgeos_robody_1.sql
+    links_aeolus_hdr.sql
+    links_auxiliary.sql
+    links_body.sql
+    links_ensemble.sql
+    links_gbrad.sql
+    links_modsurf.sql
+    links_raingg.sql
+    links_sat.sql
+    links_surfbody_feedback.sql
+    manda_gene_body.sql
+    manda_gene_hdr.sql
+    manda_laelalo.sql
+    map_ssmi_rain_ssmi.sql
+    matchup_allsky_body.sql
+    matchup_atovs_pred.sql
+    matchup_body.sql
+    matchup_gbrad.sql
+    matchup_hdr.sql
+    matchup_procid.sql
+    matchup_raingg.sql
+    matchup_update_1.sql
+    matchup_update_10.sql
+    matchup_update_2.sql
+    matchup_update_3.sql
+    matchup_update_4.sql
+    matchup_update_5.sql
+    matchup_update_6.sql
+    matchup_update_7.sql
+    matchup_update_8.sql
+    matchup_update_9.sql
+    matchupsink.sql
+    max_values.sql
+    mkglobstab.sql
+    mkglobstab_gpsro.sql
+    mobhdr_obsort.sql
+    mobhdrca_obsort.sql
+    nak_resat_averaging_kernel.sql
+    nesdis_get.sql
+    new_thinn_robhdr_10.sql
+    new_thinn_robhdr_11.sql
+    new_thinn_robhdr_2.sql
+    new_thinn_robhdr_3.sql
+    new_thinn_robhdr_4.sql
+    new_thinn_robhdr_5.sql
+    new_thinn_robhdr_6.sql
+    new_thinn_robhdr_7.sql
+    new_thinn_robhdr_8.sql
+    new_thinn_robhdr_9.sql
+    new_thinn_robody_10.sql
+    new_thinn_robody_11.sql
+    new_thinn_robody_3.sql
+    new_thinn_robody_4.sql
+    new_thinn_robody_5.sql
+    new_thinn_robody_8.sql
+    new_thinn_robody_9.sql
+    obatabs_robhdr.sql
+    obs_boxes.sql
+    obscount_1.sql
+    obscount_2.sql
+    obsdist.sql
+    obsdist_allsky.sql
+    obsdist_allsky_body.sql
+    obsdist_auxiliary.sql
+    obsdist_auxiliary_body.sql
+    obsdist_body.sql
+    obsdist_errstat.sql
+    obsdist_gbrad.sql
+    obsdist_gbrad_body.sql
+    obsdist_hdr.sql
+    obsdist_hdr2allsky_body.sql
+    obsdist_hdr2auxiliary_body.sql
+    obsdist_hdr2body.sql
+    obsdist_hdr2gbrad_body.sql
+    obsdist_hdr2radar_body.sql
+    obsdist_hdr2radiance_body.sql
+    obsdist_hdr2raingg_body.sql
+    obsdist_hdr2resat_averaging_kernel.sql
+    obsdist_index.sql
+    obsdist_index2hdr.sql
+    obsdist_limb.sql
+    obsdist_modsurf.sql
+    obsdist_poolno.sql
+    obsdist_radar.sql
+    obsdist_radar_body.sql
+    obsdist_radar_station.sql
+    obsdist_radiance.sql
+    obsdist_radiance_body.sql
+    obsdist_raingg.sql
+    obsdist_raingg_body.sql
+    obsdist_resat.sql
+    obsdist_resat_averaging_kernel.sql
+    obsdist_sat.sql
+    obsdist_satob.sql
+    obsdist_scatt.sql
+    obsdist_scatt_body.sql
+    obsdist_smos.sql
+    obsdist_ssmi.sql
+    obsdist_ssmi_body.sql
+    obsdist_update_1.sql
+    obsdist_update_10.sql
+    obsdist_update_2.sql
+    obsdist_update_3.sql
+    obsdist_update_4.sql
+    obsdist_update_5.sql
+    obsdist_update_6.sql
+    obsdist_update_7.sql
+    obsdist_update_8.sql
+    obsdist_update_9.sql
+    obsdist_windows.sql
+    obshor.sql
+    obsort_allsky.sql
+    obsort_allsky_body.sql
+    obsort_auxiliary.sql
+    obsort_body.sql
+    obsort_cloud_sink.sql
+    obsort_collocated_imager_information.sql
+    obsort_conv.sql
+    obsort_conv_body.sql
+    obsort_errstat.sql
+    obsort_gbrad.sql
+    obsort_gbrad_body.sql
+    obsort_gnssro.sql
+    obsort_gnssro_body.sql
+    obsort_hdr.sql
+    obsort_hdr2allsky_body.sql
+    obsort_hdr2auxiliary_body.sql
+    obsort_hdr2body.sql
+    obsort_hdr2conv_body.sql
+    obsort_hdr2gbrad_body.sql
+    obsort_hdr2gnssro_body.sql
+    obsort_hdr2radar_body.sql
+    obsort_hdr2radiance_body.sql
+    obsort_hdr2raingg_body.sql
+    obsort_hdr2scatt_body.sql
+    obsort_index.sql
+    obsort_limb.sql
+    obsort_modsurf.sql
+    obsort_radar.sql
+    obsort_radar_body.sql
+    obsort_radar_station.sql
+    obsort_radiance.sql
+    obsort_radiance_body.sql
+    obsort_raingg.sql
+    obsort_raingg_body.sql
+    obsort_resat.sql
+    obsort_resat_averaging_kernel.sql
+    obsort_sat.sql
+    obsort_satob.sql
+    obsort_scatt.sql
+    obsort_scatt_body.sql
+    obsort_smos.sql
+    obsort_ssmi.sql
+    obsort_ssmi_body.sql
+    obsort_update_1.sql
+    obsort_update_2.sql
+    obsort_update_3.sql
+    obsortca_auxiliary.sql
+    obsortca_body.sql
+    obsortca_errstat.sql
+    obsortca_hdr.sql
+    obsortca_hdr2auxiliary_body.sql
+    obsortca_hdr2body.sql
+    obsortca_index.sql
+    obsortca_update_1.sql
+    obsortca_update_2.sql
+    obsortca_update_3.sql
+    obstat.sql
+    obstat_conv.sql
+    obstat_fcdep.sql
+    obstat_fcdep_gpsro.sql
+    obstat_geos.sql
+    obstat_gpsro.sql
+    obstat_mwimg.sql
+    obstat_radar.sql
+    obstat_resat.sql
+    obstat_satob.sql
+    obstat_scatt.sql
+    obstat_smos.sql
+    obstat_smos_land.sql
+    obstat_tovs.sql
+    obstatfc_1.sql
+    obstatfc_10.sql
+    obstatfc_11.sql
+    obstatfc_12.sql
+    obstatfc_13.sql
+    obstatfc_14.sql
+    obstatfc_15.sql
+    obstatfc_16.sql
+    obstatfc_17.sql
+    obstatfc_18.sql
+    obstatfc_19.sql
+    obstatfc_2.sql
+    obstatfc_20.sql
+    obstatfc_3.sql
+    obstatfc_4.sql
+    obstatfc_5.sql
+    obstatfc_6.sql
+    obstatfc_7.sql
+    obstatfc_8.sql
+    obstatfc_9.sql
+    odb2ee_aeolus_auxmet.sql
+    odb_info.sql
+    ozone_robhdr_1.sql
+    ozone_robody_1.sql
+    pertobs_corr_robhdr.sql
+    pertobs_corr_robody.sql
+    pertobs_uncorr_robhdr.sql
+    pertobs_uncorr_robody.sql
+    poolmask_1.sql
+    poolmask_2.sql
+    post_thinn_robhdr_2.sql
+    post_thinn_robhdr_3.sql
+    post_thinn_robhdr_4.sql
+    post_thinn_robhdr_5.sql
+    post_thinn_robhdr_6.sql
+    post_thinn_robhdr_7.sql
+    post_thinn_robhdr_8.sql
+    post_thinn_robhdr_9.sql
+    post_thinn_robody_2.sql
+    post_thinn_robody_3.sql
+    post_thinn_robody_4.sql
+    post_thinn_robody_5.sql
+    post_thinn_robody_6.sql
+    post_thinn_robody_7.sql
+    post_thinn_robody_8.sql
+    post_thinn_robody_9.sql
+    pre_thinn_robhdr_10.sql
+    pre_thinn_robhdr_11.sql
+    pre_thinn_robhdr_2.sql
+    pre_thinn_robhdr_3.sql
+    pre_thinn_robhdr_4.sql
+    pre_thinn_robhdr_5.sql
+    pre_thinn_robhdr_6.sql
+    pre_thinn_robhdr_7.sql
+    pre_thinn_robhdr_8.sql
+    pre_thinn_robhdr_9.sql
+    pre_thinn_robody_10.sql
+    pre_thinn_robody_11.sql
+    pre_thinn_robody_2.sql
+    pre_thinn_robody_3.sql
+    pre_thinn_robody_4.sql
+    pre_thinn_robody_5.sql
+    pre_thinn_robody_6.sql
+    pre_thinn_robody_7.sql
+    pre_thinn_robody_8.sql
+    pre_thinn_robody_9.sql
+    prtdpst_robhdr.sql
+    prtdpst_robody.sql
+    radiance_averaging.sql
+    radiance_update_links.sql
+    raingg_body_rr.sql
+    raingg_rr.sql
+    ralt.sql
+    ralt_wam.sql
+    redun_robhdr_1.sql
+    redun_robhdr_2.sql
+    redun_robhdr_3.sql
+    redun_robhdr_4.sql
+    redun_robhdr_5.sql
+    redun_robhdr_6.sql
+    redun_robhdr_7.sql
+    redun_robody_1.sql
+    redun_robody_2.sql
+    redun_robody_3.sql
+    redun_robody_4.sql
+    redun_robody_5.sql
+    redun_robody_6.sql
+    redun_robody_7.sql
+    reini_body.sql
+    reini_hdr.sql
+    reprod_seqno_1.sql
+    reprod_seqno_2.sql
+    reprod_seqno_3.sql
+    reprod_seqno_4.sql
+    resat_update_links.sql
+    revmatchup_body.sql
+    revmatchup_hdr.sql
+    robhdr.sql
+    robhdr_gbrad_get_rr.sql
+    robhdr_gbrad_put_rr.sql
+    robhdr_gp_get_ssmi.sql
+    robhdr_grid_distribute.sql
+    robhdr_mwave_count_smos.sql
+    robhdr_mwave_process_smos.sql
+    robhdr_mwave_update_smos.sql
+    robhdr_obsort.sql
+    robhdr_rad.sql
+    robhdr_raingg_get_rr.sql
+    robhdr_raingg_put_rr.sql
+    robhdr_screen.sql
+    robhdr_screen_conv.sql
+    robhdr_tc.sql
+    robhdrca_obsort.sql
+    robody.sql
+    robody_gbrad_get_rr.sql
+    robody_gbrad_put_rr.sql
+    robody_gp_get_ssmi.sql
+    robody_mwave_process_smos.sql
+    robody_mwave_update_smos.sql
+    robody_rad.sql
+    robody_raingg_get_rr.sql
+    robody_raingg_put_rr.sql
+    robody_screen.sql
+    robody_smos_sekf.sql
+    robody_tc.sql
+    robody_traj.sql
+    sat_aeolusl2c.sql
+    sat_atovs.sql
+    sat_gpsro.sql
+    sat_lrad.sql
+    sat_satob.sql
+    sat_smos.sql
+    sat_ssmi.sql
+    sat_update_links.sql
+    satbody_allsky.sql
+    satbody_atovs.sql
+    satbody_gpsro.sql
+    satbody_radar.sql
+    satbody_scat.sql
+    satbody_screen_atovs.sql
+    satellite_identifier_list.sql
+    sathdr_cloud_sink.sql
+    sathdr_limb.sql
+    sathdr_ozone.sql
+    sathdr_radar.sql
+    sathdr_satob.sql
+    sathdr_scat.sql
+    sathdr_screen_aeolus_auxmet.sql
+    sathdr_screen_atovs.sql
+    sathdr_screen_cloud_sink.sql
+    sathdr_screen_gpsro.sql
+    sathdr_screen_lrad.sql
+    sathdr_screen_resat.sql
+    sathdr_screen_satob.sql
+    satob_robhdr_1.sql
+    satob_robody_1.sql
+    scat_robhdr_1.sql
+    scat_robody_1.sql
+    scatt.sql
+    scatt_flag.sql
+    scatt_update_links.sql
+    screen_robhdr_1.sql
+    screen_robhdr_2.sql
+    screen_robhdr_3.sql
+    screen_robody_1.sql
+    screen_robody_2.sql
+    screen_robody_3.sql
+    set_active.sql
+    set_active_smos.sql
+    setup_tovscv.sql
+    setup_tovscv_cloud_sink.sql
+    size_hdr.sql
+    small.sql
+    ssa_robhdr_2m.sql
+    ssa_robhdr_snow.sql
+    ssa_robody_2m.sql
+    ssa_robody_snow.sql
+    ssafb_surfbody_2m.sql
+    ssafb_surfbody_snow.sql
+    stat_obs_1.sql
+    stat_obs_2.sql
+    stat_obs_3.sql
+    store_enda.sql
+    sufger_allsky.sql
+    sufger_allsky_body.sql
+    sufger_robhdr_1.sql
+    sufger_robody_1.sql
+    sufger_sat.sql
+    sugoms.sql
+    suobarea.sql
+    suobarea_limb.sql
+    suobarea_sat.sql
+    suobarea_satob.sql
+    suobarea_scatt.sql
+    suobsaddr.sql
+    suvarbc_robhdr_0.sql
+    suvarbc_robody_0.sql
+    tcwv.sql
+    time_info.sql
+    time_numtsl.sql
+    tovsrtovs_robody_1.sql
+    tslot.sql
+    update_body_3.sql
+    update_desc_1.sql
+    update_desc_2.sql
+    update_fcdiag_links.sql
+    update_hdr_1.sql
+    update_hdr_2.sql
+    update_hdr_3.sql
+    update_links_allsky.sql
+    update_links_auxiliary.sql
+    update_links_gbrad.sql
+    update_links_radiance.sql
+    update_links_raingg.sql
+    update_links_ssmi.sql
+    update_modstep.sql
+    varbc_airep_robhdr.sql
+    varbc_airep_robody.sql
+    varbc_allsky_robhdr.sql
+    varbc_allsky_robody.sql
+    varbc_gbrad_robhdr.sql
+    varbc_gbrad_robody.sql
+    varbc_mode_hist_robhdr.sql
+    varbc_mode_hist_robody.sql
+    varbc_rad_robhdr.sql
+    varbc_rad_robody.sql
+    varbc_setup_robhdr.sql
+    varbc_setup_robody.sql
+    varbc_sfcobs_robhdr.sql
+    varbc_sfcobs_robody.sql
+    varbc_tcwv_robhdr.sql
+    varbc_tcwv_robody.sql
+    varbc_to3_robhdr.sql
+    varbc_to3_robody.sql
+)
+
+odb_add_schema(TARGET ECMA SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_ECMA TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.ECMA/ECMA.ddl b/odb/src/ddl.ECMA/ECMA.ddl
new file mode 100644
index 0000000..f0ea766
--- /dev/null
+++ b/odb/src/ddl.ECMA/ECMA.ddl
@@ -0,0 +1,3 @@
+#define ECMA
+
+#include "cma.h"
diff --git a/odb/src/ddl.ECMA/ECMA.dep b/odb/src/ddl.ECMA/ECMA.dep
new file mode 100644
index 0000000..9c695c4
--- /dev/null
+++ b/odb/src/ddl.ECMA/ECMA.dep
@@ -0,0 +1,272 @@
+#-- Last updated:  07-Feb-2000
+
+DDLS=\
+	ECMA.ddl \
+	CMA.inc \
+	mdi.inc \
+	obstype.inc \
+	varno.inc \
+	vertco_type.inc \
+	ppcode.inc \
+	sensor.inc \
+	blacklist.inc
+
+TABLES=\
+	desc \
+	ddrs \
+	index \
+	hdr \
+	sat \
+	reo3 \
+	satob \
+	rtovs \
+	rtovs_slev \
+	rtovs_mlev \
+	rtovs_pred \
+	atovs \
+	atovs_pred \
+	scatt \
+	ssmi \
+	ssmi_slev \
+	ssmi_mlev \
+	body \
+	errstat \
+	update \
+	rtovs_body \
+	ssmi_body \
+	scatt_body
+
+VIEWS=\
+	a_atovs \
+	a_atovs_pred \
+	a_body \
+	a_errstat \
+	a_hdr \
+	a_reo3 \
+	a_rtovs \
+	a_rtovs_body \
+	a_rtovs_mlev \
+	a_rtovs_pred \
+	a_rtovs_slev \
+	a_satob \
+	a_scatt \
+	a_scatt_body \
+	a_ssmi \
+	a_ssmi_body \
+	a_ssmi_mlev \
+	a_ssmi_slev \
+	a_update \
+	black_allsky \
+	bator_hdr_1 \
+	bator_hdr_2 \
+	bator_hdr_3 \
+	bator_hdr_4 \
+	bator_hdr_5 \
+	bator_hdr_6 \
+	black_atovs \
+	black_robhdr_1 \
+	black_robhdr_2 \
+	black_robhdr_3 \
+	black_robhdr_4 \
+	black_robhdr_5 \
+	black_robhdr_6 \
+	black_robhdr_7 \
+	black_robhdr_9 \
+	black_robody_1 \
+	black_robody_2 \
+	black_robody_3 \
+	black_robody_4 \
+	black_robody_5 \
+	black_robody_6 \
+	black_robody_7 \
+	black_robody_9 \
+	black_rtovs \
+	black_satob \
+	black_scatt \
+	data_radar_station \
+	date_time \
+	ddrdata \
+	decis_robhdr_1 \
+	decis_robhdr_2 \
+	decis_robhdr_3 \
+	decis_robhdr_4 \
+	decis_robody_1 \
+	decis_robody_2 \
+	decis_robody_3 \
+	decis_robody_4 \
+	ecset \
+	getsatid \
+	getsatobid \
+	matchup_atovs_pred \
+	matchup_body \
+	matchup_hdr \
+	mkglobstab \
+	mkglobstab_atovs \
+	mkglobstab_gpsro \
+	mobhdr_obsort \
+	mobhdrca_obsort \
+	obatabs_robhdr \
+	obatabs_robody \
+	obs_boxes \
+	obsort_atovs \
+	obsort_atovs_pred \
+	obsort_body \
+	obsort_ddrs \
+	obsort_errstat \
+	obsort_hdr \
+	obsort_hdr2body \
+	obsort_index \
+	obsort_radar \
+	obsort_radar_body \
+	obsort_radar_station \
+	obsort_reo3 \
+	obsort_rtovs \
+	obsort_rtovs_body \
+	obsort_rtovs_mlev \
+	obsort_rtovs_pred \
+	obsort_rtovs_slev \
+	obsort_sat \
+	obsort_satob \
+	obsort_scatt \
+	obsort_scatt_body \
+	obsort_ssmi \
+	obsort_ssmi_body \
+	obsort_ssmi_mlev \
+	obsort_ssmi_slev \
+	obsort_update \
+	obsortca_auxiliary \
+	obsortca_body \
+	obsortca_errstat \
+	obsortca_hdr \
+	obsortca_hdr2auxiliary_body \
+	obsortca_hdr2body \
+	obsortca_index \
+	obsortca_update \
+	pertcma \
+	prtgom \
+	redun_robhdr_1 \
+	redun_robhdr_2 \
+	redun_robhdr_3 \
+	redun_robhdr_4 \
+	redun_robhdr_5 \
+	redun_robhdr_6 \
+	redun_robhdr_7 \
+	redun_robody_1 \
+	redun_robody_2 \
+	redun_robody_3 \
+	redun_robody_4 \
+	redun_robody_5 \
+	redun_robody_6 \
+	redun_robody_7 \
+	reini_body \
+	reini_hdr \
+	robhdr \
+	robhdr_obsort \
+	robhdr_screen \
+	robhdr_tc \
+	robhdrca_obsort \
+	robody \
+	robody_screen \
+	robody_tc \
+	robody_traj \
+	sat_atovs \
+	sat_rtovs \
+	sat_rtovs_mlev \
+        satbody_screen_atovs \
+	satbody_screen_rtovs \
+	satbody_screen_ssmi \
+	sathdr_screen_atovs \
+	sathdr_screen_rtovs \
+	sathdr_screen_ssmi \
+	sathdr_screen_satob \
+	satmlev_screen_rtovs \
+	satmlev_screen_ssmi \
+	screen_robhdr_1 \
+	screen_robhdr_2 \
+	screen_robhdr_3 \
+	screen_robody_1 \
+	screen_robody_2 \
+	screen_robody_3 \
+	sufger_robody_1 \
+	sufger_robhdr_1 \
+	suobarea \
+	suobarea_sat \
+	suobarea_satob \
+	update_ddrs \
+	extrtovs \
+	flago_mobhdr \
+	flago_mobody \
+	prtdpst_robhdr \
+	prtdpst_robody \
+	matchup_rtovs_pred \
+	caifc1 \
+	camelo_robhdr \
+	camelo_robody \
+	canaco_robhdr \
+	canaco_robody \
+	cancer_robhdr \
+	cancer_robody \
+	cantik_robhdr \
+	cantik_robody \
+	carcfo \
+	caredo_robhdr \
+	caredo_robody \
+	castor \
+	caviso_robhdr \
+	caviso_robody \
+	cavodk_robhdr \
+	cavodk_robody \
+	get_soe_reo3 \
+	hop_canari_robhdr \
+	hop_canari_robody \
+	mobhdrca_obsort \
+	obsortca_body \
+	obsortca_errstat \
+	obsortca_hdr2body \
+	obsortca_hdr \
+	obsortca_index \
+	obsortca_update \
+	robhdrca_obsort \
+	satbody_radar \
+	sathdr_radar \
+	sathdr_screen_aeolus_sat \
+	obsort_hdr2radar_body \
+	new_thinn_robody_9 \
+	new_thinn_robhdr_9 \
+	post_thinn_robhdr_9 \
+	post_thinn_robody_9 \
+	pre_thinn_robhdr_9 \
+	pre_thinn_robody_9 \
+	new_thinn_robhdr_10 \
+	new_thinn_robody_10 \
+	pre_thinn_robody_10 \
+	pre_thinn_robhdr_10 \
+	new_thinn_robhdr_11 \
+	new_thinn_robody_11 \
+	pre_thinn_robhdr_11 \
+	pre_thinn_robody_11 \
+	obstat_radrefl \
+	obstat_radhure \
+	time_numtsl \
+	setup_tovscv \
+	setup_tovscv_cloud_sink \
+	getsatid_resat \
+	hop_canari_conv \
+	robhdr_screen_conv \
+	gbrad_update_links \
+	gnssro_update_links \
+	hdr_update_links \
+	links_aeolus_hdr \
+	links_ensemble \
+	radiance_update_links \
+	resat_update_links \
+	robody_smos_sekf \
+	sat_update_links \
+	scatt_update_links \
+	stat_obs_3 \
+	store_enda \
+	sugoms \
+	suobarea_scatt \
+	update_modstep
+	obsort_hdr2scatt_body
+
diff --git a/odb/src/ddl.ECMA/adjust_distribid.sql b/odb/src/ddl.ECMA/adjust_distribid.sql
new file mode 120000
index 0000000..cc6a068
--- /dev/null
+++ b/odb/src/ddl.ECMA/adjust_distribid.sql
@@ -0,0 +1 @@
+../ddl/adjust_distribid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/aeolus.h b/odb/src/ddl.ECMA/aeolus.h
new file mode 120000
index 0000000..d9f814d
--- /dev/null
+++ b/odb/src/ddl.ECMA/aeolus.h
@@ -0,0 +1 @@
+../ddl/aeolus.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/aeolus_auxmet_update_hdrflag.sql b/odb/src/ddl.ECMA/aeolus_auxmet_update_hdrflag.sql
new file mode 120000
index 0000000..c110193
--- /dev/null
+++ b/odb/src/ddl.ECMA/aeolus_auxmet_update_hdrflag.sql
@@ -0,0 +1 @@
+../ddl/aeolus_auxmet_update_hdrflag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/airep_flight_phase_robhdr.sql b/odb/src/ddl.ECMA/airep_flight_phase_robhdr.sql
new file mode 120000
index 0000000..a5e6e72
--- /dev/null
+++ b/odb/src/ddl.ECMA/airep_flight_phase_robhdr.sql
@@ -0,0 +1 @@
+../ddl/airep_flight_phase_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/airep_flight_phase_robody.sql b/odb/src/ddl.ECMA/airep_flight_phase_robody.sql
new file mode 120000
index 0000000..684f790
--- /dev/null
+++ b/odb/src/ddl.ECMA/airep_flight_phase_robody.sql
@@ -0,0 +1 @@
+../ddl/airep_flight_phase_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/airs.sql b/odb/src/ddl.ECMA/airs.sql
new file mode 120000
index 0000000..df05e28
--- /dev/null
+++ b/odb/src/ddl.ECMA/airs.sql
@@ -0,0 +1 @@
+../ddl/airs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/airs_flag.sql b/odb/src/ddl.ECMA/airs_flag.sql
new file mode 120000
index 0000000..3e18f59
--- /dev/null
+++ b/odb/src/ddl.ECMA/airs_flag.sql
@@ -0,0 +1 @@
+../ddl/airs_flag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ak_resat_averaging_kernel.sql b/odb/src/ddl.ECMA/ak_resat_averaging_kernel.sql
new file mode 120000
index 0000000..2860589
--- /dev/null
+++ b/odb/src/ddl.ECMA/ak_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/ak_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/alloc.h b/odb/src/ddl.ECMA/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.ECMA/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/allsky.h b/odb/src/ddl.ECMA/allsky.h
new file mode 120000
index 0000000..0a19265
--- /dev/null
+++ b/odb/src/ddl.ECMA/allsky.h
@@ -0,0 +1 @@
+../ddl/allsky.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/allsky_update_links.sql b/odb/src/ddl.ECMA/allsky_update_links.sql
new file mode 120000
index 0000000..8877ee2
--- /dev/null
+++ b/odb/src/ddl.ECMA/allsky_update_links.sql
@@ -0,0 +1 @@
+../ddl/allsky_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/amv.sql b/odb/src/ddl.ECMA/amv.sql
new file mode 120000
index 0000000..37eb366
--- /dev/null
+++ b/odb/src/ddl.ECMA/amv.sql
@@ -0,0 +1 @@
+../ddl/amv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/amv2.sql b/odb/src/ddl.ECMA/amv2.sql
new file mode 120000
index 0000000..84338ea
--- /dev/null
+++ b/odb/src/ddl.ECMA/amv2.sql
@@ -0,0 +1 @@
+../ddl/amv2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/amv_flag.sql b/odb/src/ddl.ECMA/amv_flag.sql
new file mode 120000
index 0000000..b0f5a0e
--- /dev/null
+++ b/odb/src/ddl.ECMA/amv_flag.sql
@@ -0,0 +1 @@
+../ddl/amv_flag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/amv_flag2.sql b/odb/src/ddl.ECMA/amv_flag2.sql
new file mode 120000
index 0000000..de40940
--- /dev/null
+++ b/odb/src/ddl.ECMA/amv_flag2.sql
@@ -0,0 +1 @@
+../ddl/amv_flag2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ascatsm_robhdr_1.sql b/odb/src/ddl.ECMA/ascatsm_robhdr_1.sql
new file mode 120000
index 0000000..9ec53da
--- /dev/null
+++ b/odb/src/ddl.ECMA/ascatsm_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/ascatsm_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ascatsm_robody_1.sql b/odb/src/ddl.ECMA/ascatsm_robody_1.sql
new file mode 120000
index 0000000..6dc5081
--- /dev/null
+++ b/odb/src/ddl.ECMA/ascatsm_robody_1.sql
@@ -0,0 +1 @@
+../ddl/ascatsm_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/auxiliary.h b/odb/src/ddl.ECMA/auxiliary.h
new file mode 120000
index 0000000..8ae1b08
--- /dev/null
+++ b/odb/src/ddl.ECMA/auxiliary.h
@@ -0,0 +1 @@
+../ddl/auxiliary.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/averaging_smos.sql b/odb/src/ddl.ECMA/averaging_smos.sql
new file mode 120000
index 0000000..68de96e
--- /dev/null
+++ b/odb/src/ddl.ECMA/averaging_smos.sql
@@ -0,0 +1 @@
+../ddl/averaging_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_1.sql b/odb/src/ddl.ECMA/bator_hdr_1.sql
new file mode 120000
index 0000000..eec31c9
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_1.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_2.sql b/odb/src/ddl.ECMA/bator_hdr_2.sql
new file mode 120000
index 0000000..8dff8bc
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_2.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_3.sql b/odb/src/ddl.ECMA/bator_hdr_3.sql
new file mode 120000
index 0000000..70602d2
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_3.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_4.sql b/odb/src/ddl.ECMA/bator_hdr_4.sql
new file mode 120000
index 0000000..143ad5d
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_4.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_5.sql b/odb/src/ddl.ECMA/bator_hdr_5.sql
new file mode 120000
index 0000000..140896c
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_5.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bator_hdr_6.sql b/odb/src/ddl.ECMA/bator_hdr_6.sql
new file mode 120000
index 0000000..a72ba2e
--- /dev/null
+++ b/odb/src/ddl.ECMA/bator_hdr_6.sql
@@ -0,0 +1 @@
+../ddl/bator_hdr_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/bits.h b/odb/src/ddl.ECMA/bits.h
new file mode 120000
index 0000000..459b52a
--- /dev/null
+++ b/odb/src/ddl.ECMA/bits.h
@@ -0,0 +1 @@
+../ddl/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_1.sql b/odb/src/ddl.ECMA/black_robhdr_1.sql
new file mode 120000
index 0000000..bfc8fc3
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_10.sql b/odb/src/ddl.ECMA/black_robhdr_10.sql
new file mode 120000
index 0000000..005e57d
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_10.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_2.sql b/odb/src/ddl.ECMA/black_robhdr_2.sql
new file mode 120000
index 0000000..3cdfe35
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_3.sql b/odb/src/ddl.ECMA/black_robhdr_3.sql
new file mode 120000
index 0000000..453352e
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_4.sql b/odb/src/ddl.ECMA/black_robhdr_4.sql
new file mode 120000
index 0000000..3182294
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_7.sql b/odb/src/ddl.ECMA/black_robhdr_7.sql
new file mode 120000
index 0000000..0e17fe6
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_7.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_8.sql b/odb/src/ddl.ECMA/black_robhdr_8.sql
new file mode 120000
index 0000000..3da87bd
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_8.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robhdr_9.sql b/odb/src/ddl.ECMA/black_robhdr_9.sql
new file mode 120000
index 0000000..68f84bd
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robhdr_9.sql
@@ -0,0 +1 @@
+../ddl/black_robhdr_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_1.sql b/odb/src/ddl.ECMA/black_robody_1.sql
new file mode 120000
index 0000000..cdac52a
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_1.sql
@@ -0,0 +1 @@
+../ddl/black_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_10.sql b/odb/src/ddl.ECMA/black_robody_10.sql
new file mode 120000
index 0000000..8b100a6
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_10.sql
@@ -0,0 +1 @@
+../ddl/black_robody_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_2.sql b/odb/src/ddl.ECMA/black_robody_2.sql
new file mode 120000
index 0000000..dee99c4
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_2.sql
@@ -0,0 +1 @@
+../ddl/black_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_3.sql b/odb/src/ddl.ECMA/black_robody_3.sql
new file mode 120000
index 0000000..88519f4
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_3.sql
@@ -0,0 +1 @@
+../ddl/black_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_4.sql b/odb/src/ddl.ECMA/black_robody_4.sql
new file mode 120000
index 0000000..d35cb30
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_4.sql
@@ -0,0 +1 @@
+../ddl/black_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_7.sql b/odb/src/ddl.ECMA/black_robody_7.sql
new file mode 120000
index 0000000..e3c366b
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_7.sql
@@ -0,0 +1 @@
+../ddl/black_robody_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_8.sql b/odb/src/ddl.ECMA/black_robody_8.sql
new file mode 120000
index 0000000..12b0ed6
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_8.sql
@@ -0,0 +1 @@
+../ddl/black_robody_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/black_robody_9.sql b/odb/src/ddl.ECMA/black_robody_9.sql
new file mode 120000
index 0000000..f370318
--- /dev/null
+++ b/odb/src/ddl.ECMA/black_robody_9.sql
@@ -0,0 +1 @@
+../ddl/black_robody_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/body.h b/odb/src/ddl.ECMA/body.h
new file mode 120000
index 0000000..ccd0f32
--- /dev/null
+++ b/odb/src/ddl.ECMA/body.h
@@ -0,0 +1 @@
+../ddl/body.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/btemdup_robhdr_1.sql b/odb/src/ddl.ECMA/btemdup_robhdr_1.sql
new file mode 120000
index 0000000..9b41be3
--- /dev/null
+++ b/odb/src/ddl.ECMA/btemdup_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/btemdup_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/caifc1.sql b/odb/src/ddl.ECMA/caifc1.sql
new file mode 120000
index 0000000..9243a2f
--- /dev/null
+++ b/odb/src/ddl.ECMA/caifc1.sql
@@ -0,0 +1 @@
+../ddl/caifc1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/camelo_robhdr.sql b/odb/src/ddl.ECMA/camelo_robhdr.sql
new file mode 120000
index 0000000..a95c3e4
--- /dev/null
+++ b/odb/src/ddl.ECMA/camelo_robhdr.sql
@@ -0,0 +1 @@
+../ddl/camelo_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/camelo_robody.sql b/odb/src/ddl.ECMA/camelo_robody.sql
new file mode 120000
index 0000000..df5c6e7
--- /dev/null
+++ b/odb/src/ddl.ECMA/camelo_robody.sql
@@ -0,0 +1 @@
+../ddl/camelo_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/canaco_robhdr.sql b/odb/src/ddl.ECMA/canaco_robhdr.sql
new file mode 120000
index 0000000..59034bd
--- /dev/null
+++ b/odb/src/ddl.ECMA/canaco_robhdr.sql
@@ -0,0 +1 @@
+../ddl/canaco_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/canaco_robody.sql b/odb/src/ddl.ECMA/canaco_robody.sql
new file mode 120000
index 0000000..1020ce8
--- /dev/null
+++ b/odb/src/ddl.ECMA/canaco_robody.sql
@@ -0,0 +1 @@
+../ddl/canaco_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cancer_robhdr.sql b/odb/src/ddl.ECMA/cancer_robhdr.sql
new file mode 120000
index 0000000..d218b14
--- /dev/null
+++ b/odb/src/ddl.ECMA/cancer_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cancer_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cancer_robody.sql b/odb/src/ddl.ECMA/cancer_robody.sql
new file mode 120000
index 0000000..8a4f855
--- /dev/null
+++ b/odb/src/ddl.ECMA/cancer_robody.sql
@@ -0,0 +1 @@
+../ddl/cancer_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cantik_robhdr.sql b/odb/src/ddl.ECMA/cantik_robhdr.sql
new file mode 120000
index 0000000..84fe03b
--- /dev/null
+++ b/odb/src/ddl.ECMA/cantik_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cantik_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cantik_robody.sql b/odb/src/ddl.ECMA/cantik_robody.sql
new file mode 120000
index 0000000..7655217
--- /dev/null
+++ b/odb/src/ddl.ECMA/cantik_robody.sql
@@ -0,0 +1 @@
+../ddl/cantik_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/carcfo.sql b/odb/src/ddl.ECMA/carcfo.sql
new file mode 120000
index 0000000..ca7f67e
--- /dev/null
+++ b/odb/src/ddl.ECMA/carcfo.sql
@@ -0,0 +1 @@
+../ddl/carcfo.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/caredo_robhdr.sql b/odb/src/ddl.ECMA/caredo_robhdr.sql
new file mode 120000
index 0000000..e72e0b7
--- /dev/null
+++ b/odb/src/ddl.ECMA/caredo_robhdr.sql
@@ -0,0 +1 @@
+../ddl/caredo_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/caredo_robody.sql b/odb/src/ddl.ECMA/caredo_robody.sql
new file mode 120000
index 0000000..5ebb425
--- /dev/null
+++ b/odb/src/ddl.ECMA/caredo_robody.sql
@@ -0,0 +1 @@
+../ddl/caredo_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/castor.sql b/odb/src/ddl.ECMA/castor.sql
new file mode 120000
index 0000000..4b5ac23
--- /dev/null
+++ b/odb/src/ddl.ECMA/castor.sql
@@ -0,0 +1 @@
+../ddl/castor.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/caviso_robhdr.sql b/odb/src/ddl.ECMA/caviso_robhdr.sql
new file mode 120000
index 0000000..53c7d7e
--- /dev/null
+++ b/odb/src/ddl.ECMA/caviso_robhdr.sql
@@ -0,0 +1 @@
+../ddl/caviso_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/caviso_robody.sql b/odb/src/ddl.ECMA/caviso_robody.sql
new file mode 120000
index 0000000..dcd7bef
--- /dev/null
+++ b/odb/src/ddl.ECMA/caviso_robody.sql
@@ -0,0 +1 @@
+../ddl/caviso_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cavodk_robhdr.sql b/odb/src/ddl.ECMA/cavodk_robhdr.sql
new file mode 120000
index 0000000..9725d5d
--- /dev/null
+++ b/odb/src/ddl.ECMA/cavodk_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cavodk_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cavodk_robody.sql b/odb/src/ddl.ECMA/cavodk_robody.sql
new file mode 120000
index 0000000..2394b44
--- /dev/null
+++ b/odb/src/ddl.ECMA/cavodk_robody.sql
@@ -0,0 +1 @@
+../ddl/cavodk_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cdrhook.h b/odb/src/ddl.ECMA/cdrhook.h
new file mode 120000
index 0000000..8784f89
--- /dev/null
+++ b/odb/src/ddl.ECMA/cdrhook.h
@@ -0,0 +1 @@
+../ddl/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/check_linksdb.sql b/odb/src/ddl.ECMA/check_linksdb.sql
new file mode 120000
index 0000000..f39f217
--- /dev/null
+++ b/odb/src/ddl.ECMA/check_linksdb.sql
@@ -0,0 +1 @@
+../ddl/check_linksdb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cloud_sink.h b/odb/src/ddl.ECMA/cloud_sink.h
new file mode 120000
index 0000000..3cdc586
--- /dev/null
+++ b/odb/src/ddl.ECMA/cloud_sink.h
@@ -0,0 +1 @@
+../ddl/cloud_sink.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cma.h b/odb/src/ddl.ECMA/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.ECMA/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/collocated_imager_information.h b/odb/src/ddl.ECMA/collocated_imager_information.h
new file mode 120000
index 0000000..3b061d6
--- /dev/null
+++ b/odb/src/ddl.ECMA/collocated_imager_information.h
@@ -0,0 +1 @@
+../ddl/collocated_imager_information.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/conv.h b/odb/src/ddl.ECMA/conv.h
new file mode 120000
index 0000000..9280d6d
--- /dev/null
+++ b/odb/src/ddl.ECMA/conv.h
@@ -0,0 +1 @@
+../ddl/conv.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/conv_hdr.sql b/odb/src/ddl.ECMA/conv_hdr.sql
new file mode 120000
index 0000000..708dae7
--- /dev/null
+++ b/odb/src/ddl.ECMA/conv_hdr.sql
@@ -0,0 +1 @@
+../ddl/conv_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/conv_update_links.sql b/odb/src/ddl.ECMA/conv_update_links.sql
new file mode 120000
index 0000000..64d6226
--- /dev/null
+++ b/odb/src/ddl.ECMA/conv_update_links.sql
@@ -0,0 +1 @@
+../ddl/conv_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/conventional_robhdr_1.sql b/odb/src/ddl.ECMA/conventional_robhdr_1.sql
new file mode 120000
index 0000000..fceaba2
--- /dev/null
+++ b/odb/src/ddl.ECMA/conventional_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/conventional_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/conventional_robody_1.sql b/odb/src/ddl.ECMA/conventional_robody_1.sql
new file mode 120000
index 0000000..1b75cb4
--- /dev/null
+++ b/odb/src/ddl.ECMA/conventional_robody_1.sql
@@ -0,0 +1 @@
+../ddl/conventional_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/count_orbit.sql b/odb/src/ddl.ECMA/count_orbit.sql
new file mode 120000
index 0000000..e4caf3b
--- /dev/null
+++ b/odb/src/ddl.ECMA/count_orbit.sql
@@ -0,0 +1 @@
+../ddl/count_orbit.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/count_scanpos.sql b/odb/src/ddl.ECMA/count_scanpos.sql
new file mode 120000
index 0000000..c17ca76
--- /dev/null
+++ b/odb/src/ddl.ECMA/count_scanpos.sql
@@ -0,0 +1 @@
+../ddl/count_scanpos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cycle_biasprep_robhdr.sql b/odb/src/ddl.ECMA/cycle_biasprep_robhdr.sql
new file mode 120000
index 0000000..5b88e35
--- /dev/null
+++ b/odb/src/ddl.ECMA/cycle_biasprep_robhdr.sql
@@ -0,0 +1 @@
+../ddl/cycle_biasprep_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cycle_biasprep_robody.sql b/odb/src/ddl.ECMA/cycle_biasprep_robody.sql
new file mode 120000
index 0000000..faf054b
--- /dev/null
+++ b/odb/src/ddl.ECMA/cycle_biasprep_robody.sql
@@ -0,0 +1 @@
+../ddl/cycle_biasprep_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cycle_biasprep_sathdr.sql b/odb/src/ddl.ECMA/cycle_biasprep_sathdr.sql
new file mode 120000
index 0000000..536e67a
--- /dev/null
+++ b/odb/src/ddl.ECMA/cycle_biasprep_sathdr.sql
@@ -0,0 +1 @@
+../ddl/cycle_biasprep_sathdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/cycle_biasprep_satpred.sql b/odb/src/ddl.ECMA/cycle_biasprep_satpred.sql
new file mode 120000
index 0000000..72e1a80
--- /dev/null
+++ b/odb/src/ddl.ECMA/cycle_biasprep_satpred.sql
@@ -0,0 +1 @@
+../ddl/cycle_biasprep_satpred.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/data_radar_station.sql b/odb/src/ddl.ECMA/data_radar_station.sql
new file mode 120000
index 0000000..90b082e
--- /dev/null
+++ b/odb/src/ddl.ECMA/data_radar_station.sql
@@ -0,0 +1 @@
+../ddl/data_radar_station.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/date_time.sql b/odb/src/ddl.ECMA/date_time.sql
new file mode 120000
index 0000000..7e66570
--- /dev/null
+++ b/odb/src/ddl.ECMA/date_time.sql
@@ -0,0 +1 @@
+../ddl/date_time.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/dca.h b/odb/src/ddl.ECMA/dca.h
new file mode 120000
index 0000000..005f5d7
--- /dev/null
+++ b/odb/src/ddl.ECMA/dca.h
@@ -0,0 +1 @@
+../ddl/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_convbody_1.sql b/odb/src/ddl.ECMA/decis_convbody_1.sql
new file mode 120000
index 0000000..69aebc8
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_convbody_1.sql
@@ -0,0 +1 @@
+../ddl/decis_convbody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_convbody_2.sql b/odb/src/ddl.ECMA/decis_convbody_2.sql
new file mode 120000
index 0000000..cb85618
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_convbody_2.sql
@@ -0,0 +1 @@
+../ddl/decis_convbody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robhdr_1.sql b/odb/src/ddl.ECMA/decis_robhdr_1.sql
new file mode 120000
index 0000000..049b7c9
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/decis_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robhdr_2.sql b/odb/src/ddl.ECMA/decis_robhdr_2.sql
new file mode 120000
index 0000000..636edd6
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/decis_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robhdr_3.sql b/odb/src/ddl.ECMA/decis_robhdr_3.sql
new file mode 120000
index 0000000..bb5b67d
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/decis_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robhdr_4.sql b/odb/src/ddl.ECMA/decis_robhdr_4.sql
new file mode 120000
index 0000000..2e62f23
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/decis_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robody_1.sql b/odb/src/ddl.ECMA/decis_robody_1.sql
new file mode 120000
index 0000000..cf27e6a
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robody_1.sql
@@ -0,0 +1 @@
+../ddl/decis_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robody_2.sql b/odb/src/ddl.ECMA/decis_robody_2.sql
new file mode 120000
index 0000000..94e905e
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robody_2.sql
@@ -0,0 +1 @@
+../ddl/decis_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robody_3.sql b/odb/src/ddl.ECMA/decis_robody_3.sql
new file mode 120000
index 0000000..59d90f9
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robody_3.sql
@@ -0,0 +1 @@
+../ddl/decis_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/decis_robody_4.sql b/odb/src/ddl.ECMA/decis_robody_4.sql
new file mode 120000
index 0000000..bf543b4
--- /dev/null
+++ b/odb/src/ddl.ECMA/decis_robody_4.sql
@@ -0,0 +1 @@
+../ddl/decis_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/discard_dep_1.sql b/odb/src/ddl.ECMA/discard_dep_1.sql
new file mode 120000
index 0000000..73e8537
--- /dev/null
+++ b/odb/src/ddl.ECMA/discard_dep_1.sql
@@ -0,0 +1 @@
+../ddl/discard_dep_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/discard_dep_2.sql b/odb/src/ddl.ECMA/discard_dep_2.sql
new file mode 120000
index 0000000..2644ecf
--- /dev/null
+++ b/odb/src/ddl.ECMA/discard_dep_2.sql
@@ -0,0 +1 @@
+../ddl/discard_dep_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/dmsprainy.sql b/odb/src/ddl.ECMA/dmsprainy.sql
new file mode 120000
index 0000000..9e0f7de
--- /dev/null
+++ b/odb/src/ddl.ECMA/dmsprainy.sql
@@ -0,0 +1 @@
+../ddl/dmsprainy.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecma_body_4_psbias.sql b/odb/src/ddl.ECMA/ecma_body_4_psbias.sql
new file mode 120000
index 0000000..144870c
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecma_body_4_psbias.sql
@@ -0,0 +1 @@
+../ddl/ecma_body_4_psbias.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecma_body_4_rstrhbias.sql b/odb/src/ddl.ECMA/ecma_body_4_rstrhbias.sql
new file mode 120000
index 0000000..091af66
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecma_body_4_rstrhbias.sql
@@ -0,0 +1 @@
+../ddl/ecma_body_4_rstrhbias.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecma_hdr_4_psbias.sql b/odb/src/ddl.ECMA/ecma_hdr_4_psbias.sql
new file mode 120000
index 0000000..7c788f6
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecma_hdr_4_psbias.sql
@@ -0,0 +1 @@
+../ddl/ecma_hdr_4_psbias.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecma_hdr_4_rstrhbias.sql b/odb/src/ddl.ECMA/ecma_hdr_4_rstrhbias.sql
new file mode 120000
index 0000000..acd4c98
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecma_hdr_4_rstrhbias.sql
@@ -0,0 +1 @@
+../ddl/ecma_hdr_4_rstrhbias.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_allsky_body.sql b/odb/src/ddl.ECMA/ecmwf_matchup_allsky_body.sql
new file mode 120000
index 0000000..ece85d2
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_body.sql b/odb/src/ddl.ECMA/ecmwf_matchup_body.sql
new file mode 120000
index 0000000..b818336
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_body.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_gbrad.sql b/odb/src/ddl.ECMA/ecmwf_matchup_gbrad.sql
new file mode 120000
index 0000000..5173cb9
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_gbrad.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_hdr.sql b/odb/src/ddl.ECMA/ecmwf_matchup_hdr.sql
new file mode 120000
index 0000000..88cc790
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_raingg.sql b/odb/src/ddl.ECMA/ecmwf_matchup_raingg.sql
new file mode 120000
index 0000000..b88e6ae
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_raingg.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_update_1.sql b/odb/src/ddl.ECMA/ecmwf_matchup_update_1.sql
new file mode 120000
index 0000000..3cef54f
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_update_1.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_update_2.sql b/odb/src/ddl.ECMA/ecmwf_matchup_update_2.sql
new file mode 120000
index 0000000..7ceaa64
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_update_2.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchup_update_3.sql b/odb/src/ddl.ECMA/ecmwf_matchup_update_3.sql
new file mode 120000
index 0000000..3c45f49
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchup_update_3.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchup_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecmwf_matchupsink.sql b/odb/src/ddl.ECMA/ecmwf_matchupsink.sql
new file mode 120000
index 0000000..ed1a9b7
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecmwf_matchupsink.sql
@@ -0,0 +1 @@
+../ddl/ecmwf_matchupsink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecset.sql b/odb/src/ddl.ECMA/ecset.sql
new file mode 120000
index 0000000..171c3e1
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecset.sql
@@ -0,0 +1 @@
+../ddl/ecset.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ecstdlib.h b/odb/src/ddl.ECMA/ecstdlib.h
new file mode 120000
index 0000000..32bb85b
--- /dev/null
+++ b/odb/src/ddl.ECMA/ecstdlib.h
@@ -0,0 +1 @@
+../ddl/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/emiskf_amsua.sql b/odb/src/ddl.ECMA/emiskf_amsua.sql
new file mode 120000
index 0000000..9ef3c01
--- /dev/null
+++ b/odb/src/ddl.ECMA/emiskf_amsua.sql
@@ -0,0 +1 @@
+../ddl/emiskf_amsua.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/emiskf_amsub.sql b/odb/src/ddl.ECMA/emiskf_amsub.sql
new file mode 120000
index 0000000..cb723d2
--- /dev/null
+++ b/odb/src/ddl.ECMA/emiskf_amsub.sql
@@ -0,0 +1 @@
+../ddl/emiskf_amsub.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/emiskf_atms.sql b/odb/src/ddl.ECMA/emiskf_atms.sql
new file mode 120000
index 0000000..d402bab
--- /dev/null
+++ b/odb/src/ddl.ECMA/emiskf_atms.sql
@@ -0,0 +1 @@
+../ddl/emiskf_atms.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/emiskf_mhs.sql b/odb/src/ddl.ECMA/emiskf_mhs.sql
new file mode 120000
index 0000000..b7304c5
--- /dev/null
+++ b/odb/src/ddl.ECMA/emiskf_mhs.sql
@@ -0,0 +1 @@
+../ddl/emiskf_mhs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/emiskf_mwts2.sql b/odb/src/ddl.ECMA/emiskf_mwts2.sql
new file mode 120000
index 0000000..ef83efa
--- /dev/null
+++ b/odb/src/ddl.ECMA/emiskf_mwts2.sql
@@ -0,0 +1 @@
+../ddl/emiskf_mwts2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ensemble.h b/odb/src/ddl.ECMA/ensemble.h
new file mode 120000
index 0000000..8963a78
--- /dev/null
+++ b/odb/src/ddl.ECMA/ensemble.h
@@ -0,0 +1 @@
+../ddl/ensemble.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/errstat.h b/odb/src/ddl.ECMA/errstat.h
new file mode 120000
index 0000000..217465a
--- /dev/null
+++ b/odb/src/ddl.ECMA/errstat.h
@@ -0,0 +1 @@
+../ddl/errstat.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/exp_info_1.sql b/odb/src/ddl.ECMA/exp_info_1.sql
new file mode 120000
index 0000000..ef6ea5d
--- /dev/null
+++ b/odb/src/ddl.ECMA/exp_info_1.sql
@@ -0,0 +1 @@
+../ddl/exp_info_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robhdr_0.sql b/odb/src/ddl.ECMA/fcq_robhdr_0.sql
new file mode 120000
index 0000000..ac9f59f
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robhdr_0.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robhdr_1.sql b/odb/src/ddl.ECMA/fcq_robhdr_1.sql
new file mode 120000
index 0000000..4066238
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robhdr_2.sql b/odb/src/ddl.ECMA/fcq_robhdr_2.sql
new file mode 120000
index 0000000..35ed6cc
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/fcq_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robody_0.sql b/odb/src/ddl.ECMA/fcq_robody_0.sql
new file mode 120000
index 0000000..ff0fac0
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robody_0.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robody_1.sql b/odb/src/ddl.ECMA/fcq_robody_1.sql
new file mode 120000
index 0000000..1dc87a2
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robody_1.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fcq_robody_2.sql b/odb/src/ddl.ECMA/fcq_robody_2.sql
new file mode 120000
index 0000000..9614780
--- /dev/null
+++ b/odb/src/ddl.ECMA/fcq_robody_2.sql
@@ -0,0 +1 @@
+../ddl/fcq_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fix_date_and_time.sql b/odb/src/ddl.ECMA/fix_date_and_time.sql
new file mode 120000
index 0000000..911c543
--- /dev/null
+++ b/odb/src/ddl.ECMA/fix_date_and_time.sql
@@ -0,0 +1 @@
+../ddl/fix_date_and_time.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/fixresatlen.sql b/odb/src/ddl.ECMA/fixresatlen.sql
new file mode 120000
index 0000000..d3ed207
--- /dev/null
+++ b/odb/src/ddl.ECMA/fixresatlen.sql
@@ -0,0 +1 @@
+../ddl/fixresatlen.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/flago_mobhdr.sql b/odb/src/ddl.ECMA/flago_mobhdr.sql
new file mode 120000
index 0000000..65d4e61
--- /dev/null
+++ b/odb/src/ddl.ECMA/flago_mobhdr.sql
@@ -0,0 +1 @@
+../ddl/flago_mobhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/flago_mobody.sql b/odb/src/ddl.ECMA/flago_mobody.sql
new file mode 120000
index 0000000..2d2b69f
--- /dev/null
+++ b/odb/src/ddl.ECMA/flago_mobody.sql
@@ -0,0 +1 @@
+../ddl/flago_mobody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/forecast_diagnostic.h b/odb/src/ddl.ECMA/forecast_diagnostic.h
new file mode 120000
index 0000000..8d17f2d
--- /dev/null
+++ b/odb/src/ddl.ECMA/forecast_diagnostic.h
@@ -0,0 +1 @@
+../ddl/forecast_diagnostic.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/funcs.h b/odb/src/ddl.ECMA/funcs.h
new file mode 120000
index 0000000..e16dc7c
--- /dev/null
+++ b/odb/src/ddl.ECMA/funcs.h
@@ -0,0 +1 @@
+../ddl/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gather4poolmask.sql b/odb/src/ddl.ECMA/gather4poolmask.sql
new file mode 120000
index 0000000..ab32525
--- /dev/null
+++ b/odb/src/ddl.ECMA/gather4poolmask.sql
@@ -0,0 +1 @@
+../ddl/gather4poolmask.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gather4poolmask_counts.sql b/odb/src/ddl.ECMA/gather4poolmask_counts.sql
new file mode 120000
index 0000000..f44cb2c
--- /dev/null
+++ b/odb/src/ddl.ECMA/gather4poolmask_counts.sql
@@ -0,0 +1 @@
+../ddl/gather4poolmask_counts.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gbrad.h b/odb/src/ddl.ECMA/gbrad.h
new file mode 120000
index 0000000..a94ed8e
--- /dev/null
+++ b/odb/src/ddl.ECMA/gbrad.h
@@ -0,0 +1 @@
+../ddl/gbrad.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gbrad_body_rr.sql b/odb/src/ddl.ECMA/gbrad_body_rr.sql
new file mode 120000
index 0000000..177d585
--- /dev/null
+++ b/odb/src/ddl.ECMA/gbrad_body_rr.sql
@@ -0,0 +1 @@
+../ddl/gbrad_body_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gbrad_rr.sql b/odb/src/ddl.ECMA/gbrad_rr.sql
new file mode 120000
index 0000000..d1c0f67
--- /dev/null
+++ b/odb/src/ddl.ECMA/gbrad_rr.sql
@@ -0,0 +1 @@
+../ddl/gbrad_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gbrad_update_links.sql b/odb/src/ddl.ECMA/gbrad_update_links.sql
new file mode 120000
index 0000000..0f9ba2e
--- /dev/null
+++ b/odb/src/ddl.ECMA/gbrad_update_links.sql
@@ -0,0 +1 @@
+../ddl/gbrad_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/get_soe_resat.sql b/odb/src/ddl.ECMA/get_soe_resat.sql
new file mode 120000
index 0000000..a288979
--- /dev/null
+++ b/odb/src/ddl.ECMA/get_soe_resat.sql
@@ -0,0 +1 @@
+../ddl/get_soe_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getairepid.sql b/odb/src/ddl.ECMA/getairepid.sql
new file mode 120000
index 0000000..d9d12c1
--- /dev/null
+++ b/odb/src/ddl.ECMA/getairepid.sql
@@ -0,0 +1 @@
+../ddl/getairepid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getgbradid.sql b/odb/src/ddl.ECMA/getgbradid.sql
new file mode 120000
index 0000000..c9a9862
--- /dev/null
+++ b/odb/src/ddl.ECMA/getgbradid.sql
@@ -0,0 +1 @@
+../ddl/getgbradid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getlimbid.sql b/odb/src/ddl.ECMA/getlimbid.sql
new file mode 120000
index 0000000..6db0e04
--- /dev/null
+++ b/odb/src/ddl.ECMA/getlimbid.sql
@@ -0,0 +1 @@
+../ddl/getlimbid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getsatid.sql b/odb/src/ddl.ECMA/getsatid.sql
new file mode 120000
index 0000000..d806462
--- /dev/null
+++ b/odb/src/ddl.ECMA/getsatid.sql
@@ -0,0 +1 @@
+../ddl/getsatid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getsatid_resat.sql b/odb/src/ddl.ECMA/getsatid_resat.sql
new file mode 120000
index 0000000..596c1d9
--- /dev/null
+++ b/odb/src/ddl.ECMA/getsatid_resat.sql
@@ -0,0 +1 @@
+../ddl/getsatid_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getsatobid.sql b/odb/src/ddl.ECMA/getsatobid.sql
new file mode 120000
index 0000000..d30e080
--- /dev/null
+++ b/odb/src/ddl.ECMA/getsatobid.sql
@@ -0,0 +1 @@
+../ddl/getsatobid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/getsfcobsid.sql b/odb/src/ddl.ECMA/getsfcobsid.sql
new file mode 120000
index 0000000..2a3b153
--- /dev/null
+++ b/odb/src/ddl.ECMA/getsfcobsid.sql
@@ -0,0 +1 @@
+../ddl/getsfcobsid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gnssro.h b/odb/src/ddl.ECMA/gnssro.h
new file mode 120000
index 0000000..aa94338
--- /dev/null
+++ b/odb/src/ddl.ECMA/gnssro.h
@@ -0,0 +1 @@
+../ddl/gnssro.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gnssro_update_links.sql b/odb/src/ddl.ECMA/gnssro_update_links.sql
new file mode 120000
index 0000000..ba42c9a
--- /dev/null
+++ b/odb/src/ddl.ECMA/gnssro_update_links.sql
@@ -0,0 +1 @@
+../ddl/gnssro_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/gpsro_2.sql b/odb/src/ddl.ECMA/gpsro_2.sql
new file mode 120000
index 0000000..cc3d56d
--- /dev/null
+++ b/odb/src/ddl.ECMA/gpsro_2.sql
@@ -0,0 +1 @@
+../ddl/gpsro_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hdr.h b/odb/src/ddl.ECMA/hdr.h
new file mode 120000
index 0000000..9d10f20
--- /dev/null
+++ b/odb/src/ddl.ECMA/hdr.h
@@ -0,0 +1 @@
+../ddl/hdr.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hdr_update_links.sql b/odb/src/ddl.ECMA/hdr_update_links.sql
new file mode 120000
index 0000000..fc195c4
--- /dev/null
+++ b/odb/src/ddl.ECMA/hdr_update_links.sql
@@ -0,0 +1 @@
+../ddl/hdr_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hop_canari_conv.sql b/odb/src/ddl.ECMA/hop_canari_conv.sql
new file mode 120000
index 0000000..d6cd522
--- /dev/null
+++ b/odb/src/ddl.ECMA/hop_canari_conv.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hop_canari_robhdr.sql b/odb/src/ddl.ECMA/hop_canari_robhdr.sql
new file mode 120000
index 0000000..7321038
--- /dev/null
+++ b/odb/src/ddl.ECMA/hop_canari_robhdr.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hop_canari_robody.sql b/odb/src/ddl.ECMA/hop_canari_robody.sql
new file mode 120000
index 0000000..7606498
--- /dev/null
+++ b/odb/src/ddl.ECMA/hop_canari_robody.sql
@@ -0,0 +1 @@
+../ddl/hop_canari_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hretr_canari_robody.sql b/odb/src/ddl.ECMA/hretr_canari_robody.sql
new file mode 120000
index 0000000..ca04ed9
--- /dev/null
+++ b/odb/src/ddl.ECMA/hretr_canari_robody.sql
@@ -0,0 +1 @@
+../ddl/hretr_canari_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/hretr_canari_satbody.sql b/odb/src/ddl.ECMA/hretr_canari_satbody.sql
new file mode 120000
index 0000000..a5aa678
--- /dev/null
+++ b/odb/src/ddl.ECMA/hretr_canari_satbody.sql
@@ -0,0 +1 @@
+../ddl/hretr_canari_satbody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/idx.h b/odb/src/ddl.ECMA/idx.h
new file mode 120000
index 0000000..cfdb097
--- /dev/null
+++ b/odb/src/ddl.ECMA/idx.h
@@ -0,0 +1 @@
+../ddl/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/info.h b/odb/src/ddl.ECMA/info.h
new file mode 120000
index 0000000..b63984c
--- /dev/null
+++ b/odb/src/ddl.ECMA/info.h
@@ -0,0 +1 @@
+../ddl/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/init_update_1.sql b/odb/src/ddl.ECMA/init_update_1.sql
new file mode 120000
index 0000000..2f54f42
--- /dev/null
+++ b/odb/src/ddl.ECMA/init_update_1.sql
@@ -0,0 +1 @@
+../ddl/init_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/init_update_2.sql b/odb/src/ddl.ECMA/init_update_2.sql
new file mode 120000
index 0000000..cdfabf9
--- /dev/null
+++ b/odb/src/ddl.ECMA/init_update_2.sql
@@ -0,0 +1 @@
+../ddl/init_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/init_update_3.sql b/odb/src/ddl.ECMA/init_update_3.sql
new file mode 120000
index 0000000..016bb98
--- /dev/null
+++ b/odb/src/ddl.ECMA/init_update_3.sql
@@ -0,0 +1 @@
+../ddl/init_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/level1cgeos_robhdr_1.sql b/odb/src/ddl.ECMA/level1cgeos_robhdr_1.sql
new file mode 120000
index 0000000..f7315bb
--- /dev/null
+++ b/odb/src/ddl.ECMA/level1cgeos_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/level1cgeos_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/level1cgeos_robody_1.sql b/odb/src/ddl.ECMA/level1cgeos_robody_1.sql
new file mode 120000
index 0000000..db2c55e
--- /dev/null
+++ b/odb/src/ddl.ECMA/level1cgeos_robody_1.sql
@@ -0,0 +1 @@
+../ddl/level1cgeos_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/limb.h b/odb/src/ddl.ECMA/limb.h
new file mode 120000
index 0000000..ab7f4f9
--- /dev/null
+++ b/odb/src/ddl.ECMA/limb.h
@@ -0,0 +1 @@
+../ddl/limb.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_aeolus_hdr.sql b/odb/src/ddl.ECMA/links_aeolus_hdr.sql
new file mode 120000
index 0000000..ec8c87c
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_aeolus_hdr.sql
@@ -0,0 +1 @@
+../ddl/links_aeolus_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_auxiliary.sql b/odb/src/ddl.ECMA/links_auxiliary.sql
new file mode 120000
index 0000000..dc9d3e3
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/links_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_body.sql b/odb/src/ddl.ECMA/links_body.sql
new file mode 120000
index 0000000..32f0f5f
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_body.sql
@@ -0,0 +1 @@
+../ddl/links_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_ensemble.sql b/odb/src/ddl.ECMA/links_ensemble.sql
new file mode 120000
index 0000000..5409777
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_ensemble.sql
@@ -0,0 +1 @@
+../ddl/links_ensemble.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_gbrad.sql b/odb/src/ddl.ECMA/links_gbrad.sql
new file mode 120000
index 0000000..0a13fee
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_gbrad.sql
@@ -0,0 +1 @@
+../ddl/links_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_modsurf.sql b/odb/src/ddl.ECMA/links_modsurf.sql
new file mode 120000
index 0000000..0d7419c
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_modsurf.sql
@@ -0,0 +1 @@
+../ddl/links_modsurf.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_raingg.sql b/odb/src/ddl.ECMA/links_raingg.sql
new file mode 120000
index 0000000..5ece8ce
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_raingg.sql
@@ -0,0 +1 @@
+../ddl/links_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_sat.sql b/odb/src/ddl.ECMA/links_sat.sql
new file mode 120000
index 0000000..7f973e5
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_sat.sql
@@ -0,0 +1 @@
+../ddl/links_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/links_surfbody_feedback.sql b/odb/src/ddl.ECMA/links_surfbody_feedback.sql
new file mode 120000
index 0000000..15711df
--- /dev/null
+++ b/odb/src/ddl.ECMA/links_surfbody_feedback.sql
@@ -0,0 +1 @@
+../ddl/links_surfbody_feedback.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/magicwords.h b/odb/src/ddl.ECMA/magicwords.h
new file mode 120000
index 0000000..8135e72
--- /dev/null
+++ b/odb/src/ddl.ECMA/magicwords.h
@@ -0,0 +1 @@
+../ddl/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/manda_gene_body.sql b/odb/src/ddl.ECMA/manda_gene_body.sql
new file mode 120000
index 0000000..9e2970f
--- /dev/null
+++ b/odb/src/ddl.ECMA/manda_gene_body.sql
@@ -0,0 +1 @@
+../ddl/manda_gene_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/manda_gene_hdr.sql b/odb/src/ddl.ECMA/manda_gene_hdr.sql
new file mode 120000
index 0000000..b4836f4
--- /dev/null
+++ b/odb/src/ddl.ECMA/manda_gene_hdr.sql
@@ -0,0 +1 @@
+../ddl/manda_gene_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/manda_laelalo.sql b/odb/src/ddl.ECMA/manda_laelalo.sql
new file mode 120000
index 0000000..7d56338
--- /dev/null
+++ b/odb/src/ddl.ECMA/manda_laelalo.sql
@@ -0,0 +1 @@
+../ddl/manda_laelalo.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/map_ssmi_rain_ssmi.sql b/odb/src/ddl.ECMA/map_ssmi_rain_ssmi.sql
new file mode 120000
index 0000000..7c98536
--- /dev/null
+++ b/odb/src/ddl.ECMA/map_ssmi_rain_ssmi.sql
@@ -0,0 +1 @@
+../ddl/map_ssmi_rain_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_allsky_body.sql b/odb/src/ddl.ECMA/matchup_allsky_body.sql
new file mode 120000
index 0000000..945d4c1
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/matchup_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_atovs_pred.sql b/odb/src/ddl.ECMA/matchup_atovs_pred.sql
new file mode 120000
index 0000000..7b315c9
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_atovs_pred.sql
@@ -0,0 +1 @@
+../ddl/matchup_atovs_pred.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_body.sql b/odb/src/ddl.ECMA/matchup_body.sql
new file mode 120000
index 0000000..20d1f03
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_body.sql
@@ -0,0 +1 @@
+../ddl/matchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_gbrad.sql b/odb/src/ddl.ECMA/matchup_gbrad.sql
new file mode 120000
index 0000000..58a5974
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_gbrad.sql
@@ -0,0 +1 @@
+../ddl/matchup_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_hdr.sql b/odb/src/ddl.ECMA/matchup_hdr.sql
new file mode 120000
index 0000000..a967e01
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/matchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_procid.sql b/odb/src/ddl.ECMA/matchup_procid.sql
new file mode 120000
index 0000000..09fff4a
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_procid.sql
@@ -0,0 +1 @@
+../ddl/matchup_procid.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_raingg.sql b/odb/src/ddl.ECMA/matchup_raingg.sql
new file mode 120000
index 0000000..d6a52bf
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_raingg.sql
@@ -0,0 +1 @@
+../ddl/matchup_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_1.sql b/odb/src/ddl.ECMA/matchup_update_1.sql
new file mode 120000
index 0000000..cfff8e3
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_1.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_10.sql b/odb/src/ddl.ECMA/matchup_update_10.sql
new file mode 120000
index 0000000..eedead1
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_10.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_2.sql b/odb/src/ddl.ECMA/matchup_update_2.sql
new file mode 120000
index 0000000..c838e95
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_2.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_3.sql b/odb/src/ddl.ECMA/matchup_update_3.sql
new file mode 120000
index 0000000..ded6887
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_3.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_4.sql b/odb/src/ddl.ECMA/matchup_update_4.sql
new file mode 120000
index 0000000..9571846
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_4.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_5.sql b/odb/src/ddl.ECMA/matchup_update_5.sql
new file mode 120000
index 0000000..7a210a5
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_5.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_6.sql b/odb/src/ddl.ECMA/matchup_update_6.sql
new file mode 120000
index 0000000..26265e2
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_6.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_7.sql b/odb/src/ddl.ECMA/matchup_update_7.sql
new file mode 120000
index 0000000..214c9a9
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_7.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_8.sql b/odb/src/ddl.ECMA/matchup_update_8.sql
new file mode 120000
index 0000000..f35db26
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_8.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchup_update_9.sql b/odb/src/ddl.ECMA/matchup_update_9.sql
new file mode 120000
index 0000000..a6dfc92
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchup_update_9.sql
@@ -0,0 +1 @@
+../ddl/matchup_update_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/matchupsink.sql b/odb/src/ddl.ECMA/matchupsink.sql
new file mode 120000
index 0000000..48cd771
--- /dev/null
+++ b/odb/src/ddl.ECMA/matchupsink.sql
@@ -0,0 +1 @@
+../ddl/matchupsink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/max_values.sql b/odb/src/ddl.ECMA/max_values.sql
new file mode 120000
index 0000000..c91740f
--- /dev/null
+++ b/odb/src/ddl.ECMA/max_values.sql
@@ -0,0 +1 @@
+../ddl/max_values.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/mdi.h b/odb/src/ddl.ECMA/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.ECMA/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/mkglobstab.sql b/odb/src/ddl.ECMA/mkglobstab.sql
new file mode 120000
index 0000000..100370c
--- /dev/null
+++ b/odb/src/ddl.ECMA/mkglobstab.sql
@@ -0,0 +1 @@
+../ddl/mkglobstab.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/mkglobstab_gpsro.sql b/odb/src/ddl.ECMA/mkglobstab_gpsro.sql
new file mode 120000
index 0000000..d93a7e2
--- /dev/null
+++ b/odb/src/ddl.ECMA/mkglobstab_gpsro.sql
@@ -0,0 +1 @@
+../ddl/mkglobstab_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/mobhdr_obsort.sql b/odb/src/ddl.ECMA/mobhdr_obsort.sql
new file mode 120000
index 0000000..de0d5c0
--- /dev/null
+++ b/odb/src/ddl.ECMA/mobhdr_obsort.sql
@@ -0,0 +1 @@
+../ddl/mobhdr_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/mobhdrca_obsort.sql b/odb/src/ddl.ECMA/mobhdrca_obsort.sql
new file mode 120000
index 0000000..d47a808
--- /dev/null
+++ b/odb/src/ddl.ECMA/mobhdrca_obsort.sql
@@ -0,0 +1 @@
+../ddl/mobhdrca_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/modsurf.h b/odb/src/ddl.ECMA/modsurf.h
new file mode 120000
index 0000000..7223f38
--- /dev/null
+++ b/odb/src/ddl.ECMA/modsurf.h
@@ -0,0 +1 @@
+../ddl/modsurf.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/nak_resat_averaging_kernel.sql b/odb/src/ddl.ECMA/nak_resat_averaging_kernel.sql
new file mode 120000
index 0000000..6e239d9
--- /dev/null
+++ b/odb/src/ddl.ECMA/nak_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/nak_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/namecfg.h b/odb/src/ddl.ECMA/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.ECMA/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/nesdis_get.sql b/odb/src/ddl.ECMA/nesdis_get.sql
new file mode 120000
index 0000000..fa222c0
--- /dev/null
+++ b/odb/src/ddl.ECMA/nesdis_get.sql
@@ -0,0 +1 @@
+../ddl/nesdis_get.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_10.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_10.sql
new file mode 120000
index 0000000..838ce33
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_10.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_11.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_11.sql
new file mode 120000
index 0000000..8b96399
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_11.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_2.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_2.sql
new file mode 120000
index 0000000..bebfd80
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_3.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_3.sql
new file mode 120000
index 0000000..febd06d
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_4.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_4.sql
new file mode 120000
index 0000000..8bedd67
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_5.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_5.sql
new file mode 120000
index 0000000..052a604
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_5.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_6.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_6.sql
new file mode 120000
index 0000000..230ea70
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_6.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_7.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_7.sql
new file mode 120000
index 0000000..488d871
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_7.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_8.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_8.sql
new file mode 120000
index 0000000..782ea19
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_8.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robhdr_9.sql b/odb/src/ddl.ECMA/new_thinn_robhdr_9.sql
new file mode 120000
index 0000000..0749dd0
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robhdr_9.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robhdr_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_10.sql b/odb/src/ddl.ECMA/new_thinn_robody_10.sql
new file mode 120000
index 0000000..4259de1
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_10.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_11.sql b/odb/src/ddl.ECMA/new_thinn_robody_11.sql
new file mode 120000
index 0000000..c158657
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_11.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_3.sql b/odb/src/ddl.ECMA/new_thinn_robody_3.sql
new file mode 120000
index 0000000..bd167bf
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_3.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_4.sql b/odb/src/ddl.ECMA/new_thinn_robody_4.sql
new file mode 120000
index 0000000..1f0eef2
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_4.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_5.sql b/odb/src/ddl.ECMA/new_thinn_robody_5.sql
new file mode 120000
index 0000000..257a291
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_5.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_8.sql b/odb/src/ddl.ECMA/new_thinn_robody_8.sql
new file mode 120000
index 0000000..cb9af9e
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_8.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/new_thinn_robody_9.sql b/odb/src/ddl.ECMA/new_thinn_robody_9.sql
new file mode 120000
index 0000000..0f24df4
--- /dev/null
+++ b/odb/src/ddl.ECMA/new_thinn_robody_9.sql
@@ -0,0 +1 @@
+../ddl/new_thinn_robody_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obatabs_robhdr.sql b/odb/src/ddl.ECMA/obatabs_robhdr.sql
new file mode 120000
index 0000000..6789325
--- /dev/null
+++ b/odb/src/ddl.ECMA/obatabs_robhdr.sql
@@ -0,0 +1 @@
+../ddl/obatabs_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obs_boxes.sql b/odb/src/ddl.ECMA/obs_boxes.sql
new file mode 120000
index 0000000..21f0489
--- /dev/null
+++ b/odb/src/ddl.ECMA/obs_boxes.sql
@@ -0,0 +1 @@
+../ddl/obs_boxes.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obscount_1.sql b/odb/src/ddl.ECMA/obscount_1.sql
new file mode 120000
index 0000000..57f607f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obscount_1.sql
@@ -0,0 +1 @@
+../ddl/obscount_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obscount_2.sql b/odb/src/ddl.ECMA/obscount_2.sql
new file mode 120000
index 0000000..79052a4
--- /dev/null
+++ b/odb/src/ddl.ECMA/obscount_2.sql
@@ -0,0 +1 @@
+../ddl/obscount_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist.sql b/odb/src/ddl.ECMA/obsdist.sql
new file mode 120000
index 0000000..b2521b2
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist.sql
@@ -0,0 +1 @@
+../ddl/obsdist.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_allsky.sql b/odb/src/ddl.ECMA/obsdist_allsky.sql
new file mode 120000
index 0000000..1696a9b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_allsky.sql
@@ -0,0 +1 @@
+../ddl/obsdist_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_allsky_body.sql b/odb/src/ddl.ECMA/obsdist_allsky_body.sql
new file mode 120000
index 0000000..52172e8
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_auxiliary.sql b/odb/src/ddl.ECMA/obsdist_auxiliary.sql
new file mode 120000
index 0000000..660f79a
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/obsdist_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_auxiliary_body.sql b/odb/src/ddl.ECMA/obsdist_auxiliary_body.sql
new file mode 120000
index 0000000..7e5d7bb
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_body.sql b/odb/src/ddl.ECMA/obsdist_body.sql
new file mode 120000
index 0000000..f31a752
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_errstat.sql b/odb/src/ddl.ECMA/obsdist_errstat.sql
new file mode 120000
index 0000000..b3c1c79
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_errstat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_errstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_gbrad.sql b/odb/src/ddl.ECMA/obsdist_gbrad.sql
new file mode 120000
index 0000000..136d079
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_gbrad.sql
@@ -0,0 +1 @@
+../ddl/obsdist_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_gbrad_body.sql b/odb/src/ddl.ECMA/obsdist_gbrad_body.sql
new file mode 120000
index 0000000..fcbf4c5
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr.sql b/odb/src/ddl.ECMA/obsdist_hdr.sql
new file mode 120000
index 0000000..8bd4703
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2allsky_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2allsky_body.sql
new file mode 120000
index 0000000..b85d8ae
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2auxiliary_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..6d7c11b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2body.sql b/odb/src/ddl.ECMA/obsdist_hdr2body.sql
new file mode 120000
index 0000000..c7b9058
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2gbrad_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2gbrad_body.sql
new file mode 120000
index 0000000..73f43ae
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2radar_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2radar_body.sql
new file mode 120000
index 0000000..6aae5bd
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2radiance_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2radiance_body.sql
new file mode 120000
index 0000000..77105cf
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2raingg_body.sql b/odb/src/ddl.ECMA/obsdist_hdr2raingg_body.sql
new file mode 120000
index 0000000..93e4b3a
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_hdr2resat_averaging_kernel.sql b/odb/src/ddl.ECMA/obsdist_hdr2resat_averaging_kernel.sql
new file mode 120000
index 0000000..2690586
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_hdr2resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/obsdist_hdr2resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_index.sql b/odb/src/ddl.ECMA/obsdist_index.sql
new file mode 120000
index 0000000..c9c5f18
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_index.sql
@@ -0,0 +1 @@
+../ddl/obsdist_index.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_index2hdr.sql b/odb/src/ddl.ECMA/obsdist_index2hdr.sql
new file mode 120000
index 0000000..1856d68
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_index2hdr.sql
@@ -0,0 +1 @@
+../ddl/obsdist_index2hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_limb.sql b/odb/src/ddl.ECMA/obsdist_limb.sql
new file mode 120000
index 0000000..d252d67
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_limb.sql
@@ -0,0 +1 @@
+../ddl/obsdist_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_modsurf.sql b/odb/src/ddl.ECMA/obsdist_modsurf.sql
new file mode 120000
index 0000000..72c0e45
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_modsurf.sql
@@ -0,0 +1 @@
+../ddl/obsdist_modsurf.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_poolno.sql b/odb/src/ddl.ECMA/obsdist_poolno.sql
new file mode 120000
index 0000000..b14b21b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_poolno.sql
@@ -0,0 +1 @@
+../ddl/obsdist_poolno.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_radar.sql b/odb/src/ddl.ECMA/obsdist_radar.sql
new file mode 120000
index 0000000..b73566b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_radar.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_radar_body.sql b/odb/src/ddl.ECMA/obsdist_radar_body.sql
new file mode 120000
index 0000000..81c6ce7
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_radar_station.sql b/odb/src/ddl.ECMA/obsdist_radar_station.sql
new file mode 120000
index 0000000..816f996
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_radar_station.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radar_station.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_radiance.sql b/odb/src/ddl.ECMA/obsdist_radiance.sql
new file mode 120000
index 0000000..15cf272
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_radiance.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radiance.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_radiance_body.sql b/odb/src/ddl.ECMA/obsdist_radiance_body.sql
new file mode 120000
index 0000000..d5b9306
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_raingg.sql b/odb/src/ddl.ECMA/obsdist_raingg.sql
new file mode 120000
index 0000000..14ee7aa
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_raingg.sql
@@ -0,0 +1 @@
+../ddl/obsdist_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_raingg_body.sql b/odb/src/ddl.ECMA/obsdist_raingg_body.sql
new file mode 120000
index 0000000..32242cd
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_resat.sql b/odb/src/ddl.ECMA/obsdist_resat.sql
new file mode 120000
index 0000000..ed8e4af
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_resat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_resat_averaging_kernel.sql b/odb/src/ddl.ECMA/obsdist_resat_averaging_kernel.sql
new file mode 120000
index 0000000..9112e70
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/obsdist_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_sat.sql b/odb/src/ddl.ECMA/obsdist_sat.sql
new file mode 120000
index 0000000..bb230f3
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_sat.sql
@@ -0,0 +1 @@
+../ddl/obsdist_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_satob.sql b/odb/src/ddl.ECMA/obsdist_satob.sql
new file mode 120000
index 0000000..86b662d
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_satob.sql
@@ -0,0 +1 @@
+../ddl/obsdist_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_scatt.sql b/odb/src/ddl.ECMA/obsdist_scatt.sql
new file mode 120000
index 0000000..0cecaa7
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_scatt.sql
@@ -0,0 +1 @@
+../ddl/obsdist_scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_scatt_body.sql b/odb/src/ddl.ECMA/obsdist_scatt_body.sql
new file mode 120000
index 0000000..af44779
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_scatt_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_scatt_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_smos.sql b/odb/src/ddl.ECMA/obsdist_smos.sql
new file mode 120000
index 0000000..1ec1ba2
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_smos.sql
@@ -0,0 +1 @@
+../ddl/obsdist_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_ssmi.sql b/odb/src/ddl.ECMA/obsdist_ssmi.sql
new file mode 120000
index 0000000..f5983fc
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_ssmi.sql
@@ -0,0 +1 @@
+../ddl/obsdist_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_ssmi_body.sql b/odb/src/ddl.ECMA/obsdist_ssmi_body.sql
new file mode 120000
index 0000000..896e69c
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_ssmi_body.sql
@@ -0,0 +1 @@
+../ddl/obsdist_ssmi_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_1.sql b/odb/src/ddl.ECMA/obsdist_update_1.sql
new file mode 120000
index 0000000..665f67b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_1.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_10.sql b/odb/src/ddl.ECMA/obsdist_update_10.sql
new file mode 120000
index 0000000..49a2429
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_10.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_2.sql b/odb/src/ddl.ECMA/obsdist_update_2.sql
new file mode 120000
index 0000000..10e6d56
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_2.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_3.sql b/odb/src/ddl.ECMA/obsdist_update_3.sql
new file mode 120000
index 0000000..6522ff2
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_3.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_4.sql b/odb/src/ddl.ECMA/obsdist_update_4.sql
new file mode 120000
index 0000000..d54a3a7
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_4.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_5.sql b/odb/src/ddl.ECMA/obsdist_update_5.sql
new file mode 120000
index 0000000..1c2ddb3
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_5.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_6.sql b/odb/src/ddl.ECMA/obsdist_update_6.sql
new file mode 120000
index 0000000..a7e9797
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_6.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_7.sql b/odb/src/ddl.ECMA/obsdist_update_7.sql
new file mode 120000
index 0000000..5aafe9b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_7.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_8.sql b/odb/src/ddl.ECMA/obsdist_update_8.sql
new file mode 120000
index 0000000..9ff3e27
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_8.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_update_9.sql b/odb/src/ddl.ECMA/obsdist_update_9.sql
new file mode 120000
index 0000000..2fbdd7b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_update_9.sql
@@ -0,0 +1 @@
+../ddl/obsdist_update_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsdist_windows.sql b/odb/src/ddl.ECMA/obsdist_windows.sql
new file mode 120000
index 0000000..8f9f080
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsdist_windows.sql
@@ -0,0 +1 @@
+../ddl/obsdist_windows.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obshor.sql b/odb/src/ddl.ECMA/obshor.sql
new file mode 120000
index 0000000..8e94e24
--- /dev/null
+++ b/odb/src/ddl.ECMA/obshor.sql
@@ -0,0 +1 @@
+../ddl/obshor.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_allsky.sql b/odb/src/ddl.ECMA/obsort_allsky.sql
new file mode 120000
index 0000000..9fdf073
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_allsky.sql
@@ -0,0 +1 @@
+../ddl/obsort_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_allsky_body.sql b/odb/src/ddl.ECMA/obsort_allsky_body.sql
new file mode 120000
index 0000000..ff51423
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_auxiliary.sql b/odb/src/ddl.ECMA/obsort_auxiliary.sql
new file mode 120000
index 0000000..e6ca7b8
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/obsort_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_body.sql b/odb/src/ddl.ECMA/obsort_body.sql
new file mode 120000
index 0000000..e3e6b7d
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_cloud_sink.sql b/odb/src/ddl.ECMA/obsort_cloud_sink.sql
new file mode 120000
index 0000000..6dea4d3
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/obsort_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_collocated_imager_information.sql b/odb/src/ddl.ECMA/obsort_collocated_imager_information.sql
new file mode 120000
index 0000000..2f8fb0f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_collocated_imager_information.sql
@@ -0,0 +1 @@
+../ddl/obsort_collocated_imager_information.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_conv.sql b/odb/src/ddl.ECMA/obsort_conv.sql
new file mode 120000
index 0000000..3033ced
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_conv.sql
@@ -0,0 +1 @@
+../ddl/obsort_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_conv_body.sql b/odb/src/ddl.ECMA/obsort_conv_body.sql
new file mode 120000
index 0000000..82aa492
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_conv_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_conv_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_errstat.sql b/odb/src/ddl.ECMA/obsort_errstat.sql
new file mode 120000
index 0000000..a55b1fa
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_errstat.sql
@@ -0,0 +1 @@
+../ddl/obsort_errstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_gbrad.sql b/odb/src/ddl.ECMA/obsort_gbrad.sql
new file mode 120000
index 0000000..9d782fe
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_gbrad.sql
@@ -0,0 +1 @@
+../ddl/obsort_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_gbrad_body.sql b/odb/src/ddl.ECMA/obsort_gbrad_body.sql
new file mode 120000
index 0000000..be2a879
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_gnssro.sql b/odb/src/ddl.ECMA/obsort_gnssro.sql
new file mode 120000
index 0000000..bcad6cb
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_gnssro.sql
@@ -0,0 +1 @@
+../ddl/obsort_gnssro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_gnssro_body.sql b/odb/src/ddl.ECMA/obsort_gnssro_body.sql
new file mode 120000
index 0000000..be9c099
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_gnssro_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_gnssro_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr.sql b/odb/src/ddl.ECMA/obsort_hdr.sql
new file mode 120000
index 0000000..a8875d6
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2allsky_body.sql b/odb/src/ddl.ECMA/obsort_hdr2allsky_body.sql
new file mode 120000
index 0000000..7fe238d
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2allsky_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2auxiliary_body.sql b/odb/src/ddl.ECMA/obsort_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..1e96822
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2body.sql b/odb/src/ddl.ECMA/obsort_hdr2body.sql
new file mode 120000
index 0000000..86d5021
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2conv_body.sql b/odb/src/ddl.ECMA/obsort_hdr2conv_body.sql
new file mode 120000
index 0000000..5776c67
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2conv_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2conv_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2gbrad_body.sql b/odb/src/ddl.ECMA/obsort_hdr2gbrad_body.sql
new file mode 120000
index 0000000..f8b384b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2gbrad_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2gbrad_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2gnssro_body.sql b/odb/src/ddl.ECMA/obsort_hdr2gnssro_body.sql
new file mode 120000
index 0000000..a7e587f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2gnssro_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2gnssro_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2radar_body.sql b/odb/src/ddl.ECMA/obsort_hdr2radar_body.sql
new file mode 120000
index 0000000..afc5a66
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2radiance_body.sql b/odb/src/ddl.ECMA/obsort_hdr2radiance_body.sql
new file mode 120000
index 0000000..90e0b5b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2raingg_body.sql b/odb/src/ddl.ECMA/obsort_hdr2raingg_body.sql
new file mode 120000
index 0000000..2d2aa74
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_hdr2scatt_body.sql b/odb/src/ddl.ECMA/obsort_hdr2scatt_body.sql
new file mode 120000
index 0000000..a0615b8
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_hdr2scatt_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_hdr2scatt_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_index.sql b/odb/src/ddl.ECMA/obsort_index.sql
new file mode 120000
index 0000000..a42941b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_index.sql
@@ -0,0 +1 @@
+../ddl/obsort_index.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_limb.sql b/odb/src/ddl.ECMA/obsort_limb.sql
new file mode 120000
index 0000000..16c685c
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_limb.sql
@@ -0,0 +1 @@
+../ddl/obsort_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_modsurf.sql b/odb/src/ddl.ECMA/obsort_modsurf.sql
new file mode 120000
index 0000000..3f6c769
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_modsurf.sql
@@ -0,0 +1 @@
+../ddl/obsort_modsurf.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_radar.sql b/odb/src/ddl.ECMA/obsort_radar.sql
new file mode 120000
index 0000000..a4bcad5
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_radar.sql
@@ -0,0 +1 @@
+../ddl/obsort_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_radar_body.sql b/odb/src/ddl.ECMA/obsort_radar_body.sql
new file mode 120000
index 0000000..9e7288c
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_radar_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_radar_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_radar_station.sql b/odb/src/ddl.ECMA/obsort_radar_station.sql
new file mode 120000
index 0000000..104e6ee
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_radar_station.sql
@@ -0,0 +1 @@
+../ddl/obsort_radar_station.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_radiance.sql b/odb/src/ddl.ECMA/obsort_radiance.sql
new file mode 120000
index 0000000..42b7d22
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_radiance.sql
@@ -0,0 +1 @@
+../ddl/obsort_radiance.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_radiance_body.sql b/odb/src/ddl.ECMA/obsort_radiance_body.sql
new file mode 120000
index 0000000..45f6c41
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_radiance_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_radiance_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_raingg.sql b/odb/src/ddl.ECMA/obsort_raingg.sql
new file mode 120000
index 0000000..81f1f02
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_raingg.sql
@@ -0,0 +1 @@
+../ddl/obsort_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_raingg_body.sql b/odb/src/ddl.ECMA/obsort_raingg_body.sql
new file mode 120000
index 0000000..1155fc4
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_raingg_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_raingg_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_resat.sql b/odb/src/ddl.ECMA/obsort_resat.sql
new file mode 120000
index 0000000..1cc3400
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_resat.sql
@@ -0,0 +1 @@
+../ddl/obsort_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_resat_averaging_kernel.sql b/odb/src/ddl.ECMA/obsort_resat_averaging_kernel.sql
new file mode 120000
index 0000000..e8d8d77
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_resat_averaging_kernel.sql
@@ -0,0 +1 @@
+../ddl/obsort_resat_averaging_kernel.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_sat.sql b/odb/src/ddl.ECMA/obsort_sat.sql
new file mode 120000
index 0000000..ef84328
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_sat.sql
@@ -0,0 +1 @@
+../ddl/obsort_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_satob.sql b/odb/src/ddl.ECMA/obsort_satob.sql
new file mode 120000
index 0000000..eab608a
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_satob.sql
@@ -0,0 +1 @@
+../ddl/obsort_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_scatt.sql b/odb/src/ddl.ECMA/obsort_scatt.sql
new file mode 120000
index 0000000..1413cb4
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_scatt.sql
@@ -0,0 +1 @@
+../ddl/obsort_scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_scatt_body.sql b/odb/src/ddl.ECMA/obsort_scatt_body.sql
new file mode 120000
index 0000000..1e69b1d
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_scatt_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_scatt_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_smos.sql b/odb/src/ddl.ECMA/obsort_smos.sql
new file mode 120000
index 0000000..20cac0f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_smos.sql
@@ -0,0 +1 @@
+../ddl/obsort_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_ssmi.sql b/odb/src/ddl.ECMA/obsort_ssmi.sql
new file mode 120000
index 0000000..f05562a
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_ssmi.sql
@@ -0,0 +1 @@
+../ddl/obsort_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_ssmi_body.sql b/odb/src/ddl.ECMA/obsort_ssmi_body.sql
new file mode 120000
index 0000000..17bdc18
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_ssmi_body.sql
@@ -0,0 +1 @@
+../ddl/obsort_ssmi_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_update_1.sql b/odb/src/ddl.ECMA/obsort_update_1.sql
new file mode 120000
index 0000000..9a983a0
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_update_1.sql
@@ -0,0 +1 @@
+../ddl/obsort_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_update_2.sql b/odb/src/ddl.ECMA/obsort_update_2.sql
new file mode 120000
index 0000000..2af2260
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_update_2.sql
@@ -0,0 +1 @@
+../ddl/obsort_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsort_update_3.sql b/odb/src/ddl.ECMA/obsort_update_3.sql
new file mode 120000
index 0000000..2aeb9f9
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsort_update_3.sql
@@ -0,0 +1 @@
+../ddl/obsort_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_auxiliary.sql b/odb/src/ddl.ECMA/obsortca_auxiliary.sql
new file mode 120000
index 0000000..3ad3d7f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/obsortca_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_body.sql b/odb/src/ddl.ECMA/obsortca_body.sql
new file mode 120000
index 0000000..1f7795a
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_errstat.sql b/odb/src/ddl.ECMA/obsortca_errstat.sql
new file mode 120000
index 0000000..071dfce
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_errstat.sql
@@ -0,0 +1 @@
+../ddl/obsortca_errstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_hdr.sql b/odb/src/ddl.ECMA/obsortca_hdr.sql
new file mode 120000
index 0000000..4cbf6bb
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_hdr.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_hdr2auxiliary_body.sql b/odb/src/ddl.ECMA/obsortca_hdr2auxiliary_body.sql
new file mode 120000
index 0000000..b6d7981
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_hdr2auxiliary_body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr2auxiliary_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_hdr2body.sql b/odb/src/ddl.ECMA/obsortca_hdr2body.sql
new file mode 120000
index 0000000..df22a29
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_hdr2body.sql
@@ -0,0 +1 @@
+../ddl/obsortca_hdr2body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_index.sql b/odb/src/ddl.ECMA/obsortca_index.sql
new file mode 120000
index 0000000..5076f62
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_index.sql
@@ -0,0 +1 @@
+../ddl/obsortca_index.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_update_1.sql b/odb/src/ddl.ECMA/obsortca_update_1.sql
new file mode 120000
index 0000000..80eb117
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_update_1.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_update_2.sql b/odb/src/ddl.ECMA/obsortca_update_2.sql
new file mode 120000
index 0000000..6fbd538
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_update_2.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obsortca_update_3.sql b/odb/src/ddl.ECMA/obsortca_update_3.sql
new file mode 120000
index 0000000..63c18d5
--- /dev/null
+++ b/odb/src/ddl.ECMA/obsortca_update_3.sql
@@ -0,0 +1 @@
+../ddl/obsortca_update_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat.sql b/odb/src/ddl.ECMA/obstat.sql
new file mode 120000
index 0000000..567b4f3
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat.sql
@@ -0,0 +1 @@
+../ddl/obstat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_conv.sql b/odb/src/ddl.ECMA/obstat_conv.sql
new file mode 120000
index 0000000..3427daf
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_conv.sql
@@ -0,0 +1 @@
+../ddl/obstat_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_fcdep.sql b/odb/src/ddl.ECMA/obstat_fcdep.sql
new file mode 120000
index 0000000..9b21954
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_fcdep.sql
@@ -0,0 +1 @@
+../ddl/obstat_fcdep.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_fcdep_gpsro.sql b/odb/src/ddl.ECMA/obstat_fcdep_gpsro.sql
new file mode 120000
index 0000000..b504e25
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_fcdep_gpsro.sql
@@ -0,0 +1 @@
+../ddl/obstat_fcdep_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_geos.sql b/odb/src/ddl.ECMA/obstat_geos.sql
new file mode 120000
index 0000000..f915339
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_geos.sql
@@ -0,0 +1 @@
+../ddl/obstat_geos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_gpsro.sql b/odb/src/ddl.ECMA/obstat_gpsro.sql
new file mode 120000
index 0000000..560bae9
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_gpsro.sql
@@ -0,0 +1 @@
+../ddl/obstat_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_mwimg.sql b/odb/src/ddl.ECMA/obstat_mwimg.sql
new file mode 120000
index 0000000..5c3f43b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_mwimg.sql
@@ -0,0 +1 @@
+../ddl/obstat_mwimg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_radar.sql b/odb/src/ddl.ECMA/obstat_radar.sql
new file mode 120000
index 0000000..04c0634
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_radar.sql
@@ -0,0 +1 @@
+../ddl/obstat_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_resat.sql b/odb/src/ddl.ECMA/obstat_resat.sql
new file mode 120000
index 0000000..a732435
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_resat.sql
@@ -0,0 +1 @@
+../ddl/obstat_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_satob.sql b/odb/src/ddl.ECMA/obstat_satob.sql
new file mode 120000
index 0000000..7126c1f
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_satob.sql
@@ -0,0 +1 @@
+../ddl/obstat_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_scatt.sql b/odb/src/ddl.ECMA/obstat_scatt.sql
new file mode 120000
index 0000000..309b008
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_scatt.sql
@@ -0,0 +1 @@
+../ddl/obstat_scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_smos.sql b/odb/src/ddl.ECMA/obstat_smos.sql
new file mode 120000
index 0000000..47da090
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_smos.sql
@@ -0,0 +1 @@
+../ddl/obstat_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_smos_land.sql b/odb/src/ddl.ECMA/obstat_smos_land.sql
new file mode 120000
index 0000000..5b7618b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_smos_land.sql
@@ -0,0 +1 @@
+../ddl/obstat_smos_land.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstat_tovs.sql b/odb/src/ddl.ECMA/obstat_tovs.sql
new file mode 120000
index 0000000..8812903
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstat_tovs.sql
@@ -0,0 +1 @@
+../ddl/obstat_tovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_1.sql b/odb/src/ddl.ECMA/obstatfc_1.sql
new file mode 120000
index 0000000..d31979b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_1.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_10.sql b/odb/src/ddl.ECMA/obstatfc_10.sql
new file mode 120000
index 0000000..6d8d71c
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_10.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_11.sql b/odb/src/ddl.ECMA/obstatfc_11.sql
new file mode 120000
index 0000000..e0e48c9
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_11.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_12.sql b/odb/src/ddl.ECMA/obstatfc_12.sql
new file mode 120000
index 0000000..ddcb270
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_12.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_12.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_13.sql b/odb/src/ddl.ECMA/obstatfc_13.sql
new file mode 120000
index 0000000..c6c3ee1
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_13.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_13.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_14.sql b/odb/src/ddl.ECMA/obstatfc_14.sql
new file mode 120000
index 0000000..cfda7a4
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_14.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_14.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_15.sql b/odb/src/ddl.ECMA/obstatfc_15.sql
new file mode 120000
index 0000000..9f6fc54
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_15.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_15.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_16.sql b/odb/src/ddl.ECMA/obstatfc_16.sql
new file mode 120000
index 0000000..a73fb1d
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_16.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_16.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_17.sql b/odb/src/ddl.ECMA/obstatfc_17.sql
new file mode 120000
index 0000000..607a291
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_17.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_17.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_18.sql b/odb/src/ddl.ECMA/obstatfc_18.sql
new file mode 120000
index 0000000..3fe11f5
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_18.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_18.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_19.sql b/odb/src/ddl.ECMA/obstatfc_19.sql
new file mode 120000
index 0000000..c30a838
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_19.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_19.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_2.sql b/odb/src/ddl.ECMA/obstatfc_2.sql
new file mode 120000
index 0000000..365c499
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_2.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_20.sql b/odb/src/ddl.ECMA/obstatfc_20.sql
new file mode 120000
index 0000000..dc5b038
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_20.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_20.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_3.sql b/odb/src/ddl.ECMA/obstatfc_3.sql
new file mode 120000
index 0000000..e37eee8
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_3.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_4.sql b/odb/src/ddl.ECMA/obstatfc_4.sql
new file mode 120000
index 0000000..bb1204e
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_4.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_5.sql b/odb/src/ddl.ECMA/obstatfc_5.sql
new file mode 120000
index 0000000..c752814
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_5.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_6.sql b/odb/src/ddl.ECMA/obstatfc_6.sql
new file mode 120000
index 0000000..9e5e506
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_6.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_7.sql b/odb/src/ddl.ECMA/obstatfc_7.sql
new file mode 120000
index 0000000..bc20bae
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_7.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_8.sql b/odb/src/ddl.ECMA/obstatfc_8.sql
new file mode 120000
index 0000000..d41fd5b
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_8.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstatfc_9.sql b/odb/src/ddl.ECMA/obstatfc_9.sql
new file mode 120000
index 0000000..d9bda2c
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstatfc_9.sql
@@ -0,0 +1 @@
+../ddl/obstatfc_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/obstype.h b/odb/src/ddl.ECMA/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.ECMA/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odb.h b/odb/src/ddl.ECMA/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.ECMA/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odb2ee_aeolus_auxmet.sql b/odb/src/ddl.ECMA/odb2ee_aeolus_auxmet.sql
new file mode 120000
index 0000000..6458140
--- /dev/null
+++ b/odb/src/ddl.ECMA/odb2ee_aeolus_auxmet.sql
@@ -0,0 +1 @@
+../ddl/odb2ee_aeolus_auxmet.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odb98.flags b/odb/src/ddl.ECMA/odb98.flags
new file mode 120000
index 0000000..bc6a361
--- /dev/null
+++ b/odb/src/ddl.ECMA/odb98.flags
@@ -0,0 +1 @@
+../ddl/odb98.flags
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odb_info.sql b/odb/src/ddl.ECMA/odb_info.sql
new file mode 120000
index 0000000..ae3129e
--- /dev/null
+++ b/odb/src/ddl.ECMA/odb_info.sql
@@ -0,0 +1 @@
+../ddl/odb_info.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odb_macros.h b/odb/src/ddl.ECMA/odb_macros.h
new file mode 120000
index 0000000..01fe8a8
--- /dev/null
+++ b/odb/src/ddl.ECMA/odb_macros.h
@@ -0,0 +1 @@
+../ddl/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odbcrc.h b/odb/src/ddl.ECMA/odbcrc.h
new file mode 120000
index 0000000..fcd0f0c
--- /dev/null
+++ b/odb/src/ddl.ECMA/odbcrc.h
@@ -0,0 +1 @@
+../ddl/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/odbmd5.h b/odb/src/ddl.ECMA/odbmd5.h
new file mode 120000
index 0000000..b81990c
--- /dev/null
+++ b/odb/src/ddl.ECMA/odbmd5.h
@@ -0,0 +1 @@
+../ddl/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ozone_robhdr_1.sql b/odb/src/ddl.ECMA/ozone_robhdr_1.sql
new file mode 120000
index 0000000..4be7988
--- /dev/null
+++ b/odb/src/ddl.ECMA/ozone_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/ozone_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ozone_robody_1.sql b/odb/src/ddl.ECMA/ozone_robody_1.sql
new file mode 120000
index 0000000..7440709
--- /dev/null
+++ b/odb/src/ddl.ECMA/ozone_robody_1.sql
@@ -0,0 +1 @@
+../ddl/ozone_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pcma_extern.h b/odb/src/ddl.ECMA/pcma_extern.h
new file mode 120000
index 0000000..dba5539
--- /dev/null
+++ b/odb/src/ddl.ECMA/pcma_extern.h
@@ -0,0 +1 @@
+../ddl/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pertobs_corr_robhdr.sql b/odb/src/ddl.ECMA/pertobs_corr_robhdr.sql
new file mode 120000
index 0000000..82acd0f
--- /dev/null
+++ b/odb/src/ddl.ECMA/pertobs_corr_robhdr.sql
@@ -0,0 +1 @@
+../ddl/pertobs_corr_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pertobs_corr_robody.sql b/odb/src/ddl.ECMA/pertobs_corr_robody.sql
new file mode 120000
index 0000000..aad8c0f
--- /dev/null
+++ b/odb/src/ddl.ECMA/pertobs_corr_robody.sql
@@ -0,0 +1 @@
+../ddl/pertobs_corr_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pertobs_uncorr_robhdr.sql b/odb/src/ddl.ECMA/pertobs_uncorr_robhdr.sql
new file mode 120000
index 0000000..c43902e
--- /dev/null
+++ b/odb/src/ddl.ECMA/pertobs_uncorr_robhdr.sql
@@ -0,0 +1 @@
+../ddl/pertobs_uncorr_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pertobs_uncorr_robody.sql b/odb/src/ddl.ECMA/pertobs_uncorr_robody.sql
new file mode 120000
index 0000000..075e6c5
--- /dev/null
+++ b/odb/src/ddl.ECMA/pertobs_uncorr_robody.sql
@@ -0,0 +1 @@
+../ddl/pertobs_uncorr_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/poolmask_1.sql b/odb/src/ddl.ECMA/poolmask_1.sql
new file mode 120000
index 0000000..b6f8a03
--- /dev/null
+++ b/odb/src/ddl.ECMA/poolmask_1.sql
@@ -0,0 +1 @@
+../ddl/poolmask_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/poolmask_2.sql b/odb/src/ddl.ECMA/poolmask_2.sql
new file mode 120000
index 0000000..5596d64
--- /dev/null
+++ b/odb/src/ddl.ECMA/poolmask_2.sql
@@ -0,0 +1 @@
+../ddl/poolmask_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_2.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_2.sql
new file mode 120000
index 0000000..516fe73
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_3.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_3.sql
new file mode 120000
index 0000000..eee366d
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_4.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_4.sql
new file mode 120000
index 0000000..40753db
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_5.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_5.sql
new file mode 120000
index 0000000..64c4ceb
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_5.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_6.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_6.sql
new file mode 120000
index 0000000..9db523d
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_6.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_7.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_7.sql
new file mode 120000
index 0000000..cf24c66
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_7.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_8.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_8.sql
new file mode 120000
index 0000000..6ce5d5f
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_8.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robhdr_9.sql b/odb/src/ddl.ECMA/post_thinn_robhdr_9.sql
new file mode 120000
index 0000000..18c6a3b
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robhdr_9.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robhdr_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_2.sql b/odb/src/ddl.ECMA/post_thinn_robody_2.sql
new file mode 120000
index 0000000..ae9f7d6
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_2.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_3.sql b/odb/src/ddl.ECMA/post_thinn_robody_3.sql
new file mode 120000
index 0000000..91918ef
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_3.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_4.sql b/odb/src/ddl.ECMA/post_thinn_robody_4.sql
new file mode 120000
index 0000000..cd8280b
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_4.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_5.sql b/odb/src/ddl.ECMA/post_thinn_robody_5.sql
new file mode 120000
index 0000000..42bd379
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_5.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_6.sql b/odb/src/ddl.ECMA/post_thinn_robody_6.sql
new file mode 120000
index 0000000..9791595
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_6.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_7.sql b/odb/src/ddl.ECMA/post_thinn_robody_7.sql
new file mode 120000
index 0000000..73c5ed9
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_7.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_8.sql b/odb/src/ddl.ECMA/post_thinn_robody_8.sql
new file mode 120000
index 0000000..d9e6d21
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_8.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/post_thinn_robody_9.sql b/odb/src/ddl.ECMA/post_thinn_robody_9.sql
new file mode 120000
index 0000000..0e77934
--- /dev/null
+++ b/odb/src/ddl.ECMA/post_thinn_robody_9.sql
@@ -0,0 +1 @@
+../ddl/post_thinn_robody_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ppcode.h b/odb/src/ddl.ECMA/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.ECMA/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_10.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_10.sql
new file mode 120000
index 0000000..8c3f4ac
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_10.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_11.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_11.sql
new file mode 120000
index 0000000..1a27264
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_11.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_2.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_2.sql
new file mode 120000
index 0000000..5bc2289
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_3.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_3.sql
new file mode 120000
index 0000000..ad21aac
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_4.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_4.sql
new file mode 120000
index 0000000..5a62ab6
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_5.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_5.sql
new file mode 120000
index 0000000..133e956
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_5.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_6.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_6.sql
new file mode 120000
index 0000000..3cacbbe
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_6.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_7.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_7.sql
new file mode 120000
index 0000000..a10c2b6
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_7.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_8.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_8.sql
new file mode 120000
index 0000000..f44b46b
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_8.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robhdr_9.sql b/odb/src/ddl.ECMA/pre_thinn_robhdr_9.sql
new file mode 120000
index 0000000..80a2581
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robhdr_9.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robhdr_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_10.sql b/odb/src/ddl.ECMA/pre_thinn_robody_10.sql
new file mode 120000
index 0000000..fd40da3
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_10.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_10.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_11.sql b/odb/src/ddl.ECMA/pre_thinn_robody_11.sql
new file mode 120000
index 0000000..f1fd970
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_11.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_11.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_2.sql b/odb/src/ddl.ECMA/pre_thinn_robody_2.sql
new file mode 120000
index 0000000..ab1a961
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_2.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_3.sql b/odb/src/ddl.ECMA/pre_thinn_robody_3.sql
new file mode 120000
index 0000000..7edd520
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_3.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_4.sql b/odb/src/ddl.ECMA/pre_thinn_robody_4.sql
new file mode 120000
index 0000000..50d0575
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_4.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_5.sql b/odb/src/ddl.ECMA/pre_thinn_robody_5.sql
new file mode 120000
index 0000000..bfec9ff
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_5.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_6.sql b/odb/src/ddl.ECMA/pre_thinn_robody_6.sql
new file mode 120000
index 0000000..727a4bf
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_6.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_7.sql b/odb/src/ddl.ECMA/pre_thinn_robody_7.sql
new file mode 120000
index 0000000..1784206
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_7.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_8.sql b/odb/src/ddl.ECMA/pre_thinn_robody_8.sql
new file mode 120000
index 0000000..13c5d46
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_8.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_8.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/pre_thinn_robody_9.sql b/odb/src/ddl.ECMA/pre_thinn_robody_9.sql
new file mode 120000
index 0000000..db9d6bb
--- /dev/null
+++ b/odb/src/ddl.ECMA/pre_thinn_robody_9.sql
@@ -0,0 +1 @@
+../ddl/pre_thinn_robody_9.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/privpub.h b/odb/src/ddl.ECMA/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.ECMA/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/prtdpst_robhdr.sql b/odb/src/ddl.ECMA/prtdpst_robhdr.sql
new file mode 120000
index 0000000..e65b878
--- /dev/null
+++ b/odb/src/ddl.ECMA/prtdpst_robhdr.sql
@@ -0,0 +1 @@
+../ddl/prtdpst_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/prtdpst_robody.sql b/odb/src/ddl.ECMA/prtdpst_robody.sql
new file mode 120000
index 0000000..d3a8f06
--- /dev/null
+++ b/odb/src/ddl.ECMA/prtdpst_robody.sql
@@ -0,0 +1 @@
+../ddl/prtdpst_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/radar.h b/odb/src/ddl.ECMA/radar.h
new file mode 120000
index 0000000..79dddc7
--- /dev/null
+++ b/odb/src/ddl.ECMA/radar.h
@@ -0,0 +1 @@
+../ddl/radar.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/radar_station.h b/odb/src/ddl.ECMA/radar_station.h
new file mode 120000
index 0000000..85482f7
--- /dev/null
+++ b/odb/src/ddl.ECMA/radar_station.h
@@ -0,0 +1 @@
+../ddl/radar_station.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/radiance.h b/odb/src/ddl.ECMA/radiance.h
new file mode 120000
index 0000000..62c3289
--- /dev/null
+++ b/odb/src/ddl.ECMA/radiance.h
@@ -0,0 +1 @@
+../ddl/radiance.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/radiance_averaging.sql b/odb/src/ddl.ECMA/radiance_averaging.sql
new file mode 120000
index 0000000..6497a3b
--- /dev/null
+++ b/odb/src/ddl.ECMA/radiance_averaging.sql
@@ -0,0 +1 @@
+../ddl/radiance_averaging.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/radiance_update_links.sql b/odb/src/ddl.ECMA/radiance_update_links.sql
new file mode 120000
index 0000000..fa1bc02
--- /dev/null
+++ b/odb/src/ddl.ECMA/radiance_update_links.sql
@@ -0,0 +1 @@
+../ddl/radiance_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/raingg.h b/odb/src/ddl.ECMA/raingg.h
new file mode 120000
index 0000000..3f077a8
--- /dev/null
+++ b/odb/src/ddl.ECMA/raingg.h
@@ -0,0 +1 @@
+../ddl/raingg.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/raingg_body_rr.sql b/odb/src/ddl.ECMA/raingg_body_rr.sql
new file mode 120000
index 0000000..5581b08
--- /dev/null
+++ b/odb/src/ddl.ECMA/raingg_body_rr.sql
@@ -0,0 +1 @@
+../ddl/raingg_body_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/raingg_rr.sql b/odb/src/ddl.ECMA/raingg_rr.sql
new file mode 120000
index 0000000..7edda37
--- /dev/null
+++ b/odb/src/ddl.ECMA/raingg_rr.sql
@@ -0,0 +1 @@
+../ddl/raingg_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ralt.sql b/odb/src/ddl.ECMA/ralt.sql
new file mode 120000
index 0000000..b3bad6a
--- /dev/null
+++ b/odb/src/ddl.ECMA/ralt.sql
@@ -0,0 +1 @@
+../ddl/ralt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ralt_wam.sql b/odb/src/ddl.ECMA/ralt_wam.sql
new file mode 120000
index 0000000..cb1d3be
--- /dev/null
+++ b/odb/src/ddl.ECMA/ralt_wam.sql
@@ -0,0 +1 @@
+../ddl/ralt_wam.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_1.sql b/odb/src/ddl.ECMA/redun_robhdr_1.sql
new file mode 120000
index 0000000..7718404
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_2.sql b/odb/src/ddl.ECMA/redun_robhdr_2.sql
new file mode 120000
index 0000000..1b1a8b5
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_3.sql b/odb/src/ddl.ECMA/redun_robhdr_3.sql
new file mode 120000
index 0000000..2135ac9
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_4.sql b/odb/src/ddl.ECMA/redun_robhdr_4.sql
new file mode 120000
index 0000000..a07f241
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_4.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_5.sql b/odb/src/ddl.ECMA/redun_robhdr_5.sql
new file mode 120000
index 0000000..1fdf21a
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_5.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_6.sql b/odb/src/ddl.ECMA/redun_robhdr_6.sql
new file mode 120000
index 0000000..a24ddfd
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_6.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robhdr_7.sql b/odb/src/ddl.ECMA/redun_robhdr_7.sql
new file mode 120000
index 0000000..45977a2
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robhdr_7.sql
@@ -0,0 +1 @@
+../ddl/redun_robhdr_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_1.sql b/odb/src/ddl.ECMA/redun_robody_1.sql
new file mode 120000
index 0000000..b8fb1a6
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_1.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_2.sql b/odb/src/ddl.ECMA/redun_robody_2.sql
new file mode 120000
index 0000000..2543c09
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_2.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_3.sql b/odb/src/ddl.ECMA/redun_robody_3.sql
new file mode 120000
index 0000000..ab2ab76
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_3.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_4.sql b/odb/src/ddl.ECMA/redun_robody_4.sql
new file mode 120000
index 0000000..acdeaf6
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_4.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_5.sql b/odb/src/ddl.ECMA/redun_robody_5.sql
new file mode 120000
index 0000000..97e175e
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_5.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_5.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_6.sql b/odb/src/ddl.ECMA/redun_robody_6.sql
new file mode 120000
index 0000000..1f1bc76
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_6.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_6.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/redun_robody_7.sql b/odb/src/ddl.ECMA/redun_robody_7.sql
new file mode 120000
index 0000000..f730faa
--- /dev/null
+++ b/odb/src/ddl.ECMA/redun_robody_7.sql
@@ -0,0 +1 @@
+../ddl/redun_robody_7.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reini_body.sql b/odb/src/ddl.ECMA/reini_body.sql
new file mode 120000
index 0000000..b3cdd8b
--- /dev/null
+++ b/odb/src/ddl.ECMA/reini_body.sql
@@ -0,0 +1 @@
+../ddl/reini_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reini_hdr.sql b/odb/src/ddl.ECMA/reini_hdr.sql
new file mode 120000
index 0000000..234f081
--- /dev/null
+++ b/odb/src/ddl.ECMA/reini_hdr.sql
@@ -0,0 +1 @@
+../ddl/reini_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reprod_seqno_1.sql b/odb/src/ddl.ECMA/reprod_seqno_1.sql
new file mode 120000
index 0000000..e217102
--- /dev/null
+++ b/odb/src/ddl.ECMA/reprod_seqno_1.sql
@@ -0,0 +1 @@
+../ddl/reprod_seqno_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reprod_seqno_2.sql b/odb/src/ddl.ECMA/reprod_seqno_2.sql
new file mode 120000
index 0000000..c8f7fe8
--- /dev/null
+++ b/odb/src/ddl.ECMA/reprod_seqno_2.sql
@@ -0,0 +1 @@
+../ddl/reprod_seqno_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reprod_seqno_3.sql b/odb/src/ddl.ECMA/reprod_seqno_3.sql
new file mode 120000
index 0000000..87e134e
--- /dev/null
+++ b/odb/src/ddl.ECMA/reprod_seqno_3.sql
@@ -0,0 +1 @@
+../ddl/reprod_seqno_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/reprod_seqno_4.sql b/odb/src/ddl.ECMA/reprod_seqno_4.sql
new file mode 120000
index 0000000..2ac23fe
--- /dev/null
+++ b/odb/src/ddl.ECMA/reprod_seqno_4.sql
@@ -0,0 +1 @@
+../ddl/reprod_seqno_4.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/resat.h b/odb/src/ddl.ECMA/resat.h
new file mode 120000
index 0000000..23bd5e9
--- /dev/null
+++ b/odb/src/ddl.ECMA/resat.h
@@ -0,0 +1 @@
+../ddl/resat.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/resat_update_links.sql b/odb/src/ddl.ECMA/resat_update_links.sql
new file mode 120000
index 0000000..e6a4060
--- /dev/null
+++ b/odb/src/ddl.ECMA/resat_update_links.sql
@@ -0,0 +1 @@
+../ddl/resat_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/revmatchup_body.sql b/odb/src/ddl.ECMA/revmatchup_body.sql
new file mode 120000
index 0000000..ebc2394
--- /dev/null
+++ b/odb/src/ddl.ECMA/revmatchup_body.sql
@@ -0,0 +1 @@
+../ddl/revmatchup_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/revmatchup_hdr.sql b/odb/src/ddl.ECMA/revmatchup_hdr.sql
new file mode 120000
index 0000000..26e5af2
--- /dev/null
+++ b/odb/src/ddl.ECMA/revmatchup_hdr.sql
@@ -0,0 +1 @@
+../ddl/revmatchup_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr.sql b/odb/src/ddl.ECMA/robhdr.sql
new file mode 120000
index 0000000..40c605d
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr.sql
@@ -0,0 +1 @@
+../ddl/robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_gbrad_get_rr.sql b/odb/src/ddl.ECMA/robhdr_gbrad_get_rr.sql
new file mode 120000
index 0000000..e599f3e
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_gbrad_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_gbrad_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_gbrad_put_rr.sql b/odb/src/ddl.ECMA/robhdr_gbrad_put_rr.sql
new file mode 120000
index 0000000..179b3d7
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_gbrad_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_gbrad_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_gp_get_ssmi.sql b/odb/src/ddl.ECMA/robhdr_gp_get_ssmi.sql
new file mode 120000
index 0000000..fc04841
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_gp_get_ssmi.sql
@@ -0,0 +1 @@
+../ddl/robhdr_gp_get_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_grid_distribute.sql b/odb/src/ddl.ECMA/robhdr_grid_distribute.sql
new file mode 120000
index 0000000..5021cd8
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_grid_distribute.sql
@@ -0,0 +1 @@
+../ddl/robhdr_grid_distribute.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_mwave_count_smos.sql b/odb/src/ddl.ECMA/robhdr_mwave_count_smos.sql
new file mode 120000
index 0000000..c2af565
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_mwave_count_smos.sql
@@ -0,0 +1 @@
+../ddl/robhdr_mwave_count_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_mwave_process_smos.sql b/odb/src/ddl.ECMA/robhdr_mwave_process_smos.sql
new file mode 120000
index 0000000..2afe7dc
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_mwave_process_smos.sql
@@ -0,0 +1 @@
+../ddl/robhdr_mwave_process_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_mwave_update_smos.sql b/odb/src/ddl.ECMA/robhdr_mwave_update_smos.sql
new file mode 120000
index 0000000..80ac083
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_mwave_update_smos.sql
@@ -0,0 +1 @@
+../ddl/robhdr_mwave_update_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_obsort.sql b/odb/src/ddl.ECMA/robhdr_obsort.sql
new file mode 120000
index 0000000..0d90e9a
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_obsort.sql
@@ -0,0 +1 @@
+../ddl/robhdr_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_rad.sql b/odb/src/ddl.ECMA/robhdr_rad.sql
new file mode 120000
index 0000000..8b512c5
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_rad.sql
@@ -0,0 +1 @@
+../ddl/robhdr_rad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_raingg_get_rr.sql b/odb/src/ddl.ECMA/robhdr_raingg_get_rr.sql
new file mode 120000
index 0000000..0c23d98
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_raingg_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_raingg_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_raingg_put_rr.sql b/odb/src/ddl.ECMA/robhdr_raingg_put_rr.sql
new file mode 120000
index 0000000..fe0ba4e
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_raingg_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robhdr_raingg_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_screen.sql b/odb/src/ddl.ECMA/robhdr_screen.sql
new file mode 120000
index 0000000..f03a2af
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_screen.sql
@@ -0,0 +1 @@
+../ddl/robhdr_screen.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_screen_conv.sql b/odb/src/ddl.ECMA/robhdr_screen_conv.sql
new file mode 120000
index 0000000..c16d295
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_screen_conv.sql
@@ -0,0 +1 @@
+../ddl/robhdr_screen_conv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdr_tc.sql b/odb/src/ddl.ECMA/robhdr_tc.sql
new file mode 120000
index 0000000..3cddffb
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdr_tc.sql
@@ -0,0 +1 @@
+../ddl/robhdr_tc.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robhdrca_obsort.sql b/odb/src/ddl.ECMA/robhdrca_obsort.sql
new file mode 120000
index 0000000..a0e1f72
--- /dev/null
+++ b/odb/src/ddl.ECMA/robhdrca_obsort.sql
@@ -0,0 +1 @@
+../ddl/robhdrca_obsort.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody.sql b/odb/src/ddl.ECMA/robody.sql
new file mode 120000
index 0000000..bb96a50
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody.sql
@@ -0,0 +1 @@
+../ddl/robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_gbrad_get_rr.sql b/odb/src/ddl.ECMA/robody_gbrad_get_rr.sql
new file mode 120000
index 0000000..9d6eb48
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_gbrad_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_gbrad_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_gbrad_put_rr.sql b/odb/src/ddl.ECMA/robody_gbrad_put_rr.sql
new file mode 120000
index 0000000..62f73f0
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_gbrad_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_gbrad_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_gp_get_ssmi.sql b/odb/src/ddl.ECMA/robody_gp_get_ssmi.sql
new file mode 120000
index 0000000..0a7441a
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_gp_get_ssmi.sql
@@ -0,0 +1 @@
+../ddl/robody_gp_get_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_mwave_process_smos.sql b/odb/src/ddl.ECMA/robody_mwave_process_smos.sql
new file mode 120000
index 0000000..a631aae
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_mwave_process_smos.sql
@@ -0,0 +1 @@
+../ddl/robody_mwave_process_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_mwave_update_smos.sql b/odb/src/ddl.ECMA/robody_mwave_update_smos.sql
new file mode 120000
index 0000000..0575f98
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_mwave_update_smos.sql
@@ -0,0 +1 @@
+../ddl/robody_mwave_update_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_rad.sql b/odb/src/ddl.ECMA/robody_rad.sql
new file mode 120000
index 0000000..c9d3765
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_rad.sql
@@ -0,0 +1 @@
+../ddl/robody_rad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_raingg_get_rr.sql b/odb/src/ddl.ECMA/robody_raingg_get_rr.sql
new file mode 120000
index 0000000..902a5ea
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_raingg_get_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_raingg_get_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_raingg_put_rr.sql b/odb/src/ddl.ECMA/robody_raingg_put_rr.sql
new file mode 120000
index 0000000..6daee3a
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_raingg_put_rr.sql
@@ -0,0 +1 @@
+../ddl/robody_raingg_put_rr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_screen.sql b/odb/src/ddl.ECMA/robody_screen.sql
new file mode 120000
index 0000000..0ef611e
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_screen.sql
@@ -0,0 +1 @@
+../ddl/robody_screen.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_smos_sekf.sql b/odb/src/ddl.ECMA/robody_smos_sekf.sql
new file mode 120000
index 0000000..4cae2ba
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_smos_sekf.sql
@@ -0,0 +1 @@
+../ddl/robody_smos_sekf.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_tc.sql b/odb/src/ddl.ECMA/robody_tc.sql
new file mode 120000
index 0000000..153efdd
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_tc.sql
@@ -0,0 +1 @@
+../ddl/robody_tc.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/robody_traj.sql b/odb/src/ddl.ECMA/robody_traj.sql
new file mode 120000
index 0000000..bc999c3
--- /dev/null
+++ b/odb/src/ddl.ECMA/robody_traj.sql
@@ -0,0 +1 @@
+../ddl/robody_traj.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat.h b/odb/src/ddl.ECMA/sat.h
new file mode 120000
index 0000000..ffd2d1e
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat.h
@@ -0,0 +1 @@
+../ddl/sat.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_aeolusl2c.sql b/odb/src/ddl.ECMA/sat_aeolusl2c.sql
new file mode 120000
index 0000000..b336e13
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_aeolusl2c.sql
@@ -0,0 +1 @@
+../ddl/sat_aeolusl2c.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_atovs.sql b/odb/src/ddl.ECMA/sat_atovs.sql
new file mode 120000
index 0000000..93d84b0
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_atovs.sql
@@ -0,0 +1 @@
+../ddl/sat_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_gpsro.sql b/odb/src/ddl.ECMA/sat_gpsro.sql
new file mode 120000
index 0000000..0feacd4
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_gpsro.sql
@@ -0,0 +1 @@
+../ddl/sat_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_lrad.sql b/odb/src/ddl.ECMA/sat_lrad.sql
new file mode 120000
index 0000000..b915217
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_lrad.sql
@@ -0,0 +1 @@
+../ddl/sat_lrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_satob.sql b/odb/src/ddl.ECMA/sat_satob.sql
new file mode 120000
index 0000000..16512f8
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_satob.sql
@@ -0,0 +1 @@
+../ddl/sat_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_smos.sql b/odb/src/ddl.ECMA/sat_smos.sql
new file mode 120000
index 0000000..c871c37
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_smos.sql
@@ -0,0 +1 @@
+../ddl/sat_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_ssmi.sql b/odb/src/ddl.ECMA/sat_ssmi.sql
new file mode 120000
index 0000000..8891ef8
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_ssmi.sql
@@ -0,0 +1 @@
+../ddl/sat_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sat_update_links.sql b/odb/src/ddl.ECMA/sat_update_links.sql
new file mode 120000
index 0000000..c7aac87
--- /dev/null
+++ b/odb/src/ddl.ECMA/sat_update_links.sql
@@ -0,0 +1 @@
+../ddl/sat_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_allsky.sql b/odb/src/ddl.ECMA/satbody_allsky.sql
new file mode 120000
index 0000000..38b6d05
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_allsky.sql
@@ -0,0 +1 @@
+../ddl/satbody_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_atovs.sql b/odb/src/ddl.ECMA/satbody_atovs.sql
new file mode 120000
index 0000000..2503a7f
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_atovs.sql
@@ -0,0 +1 @@
+../ddl/satbody_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_gpsro.sql b/odb/src/ddl.ECMA/satbody_gpsro.sql
new file mode 120000
index 0000000..d31f469
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_gpsro.sql
@@ -0,0 +1 @@
+../ddl/satbody_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_radar.sql b/odb/src/ddl.ECMA/satbody_radar.sql
new file mode 120000
index 0000000..af71a2d
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_radar.sql
@@ -0,0 +1 @@
+../ddl/satbody_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_scat.sql b/odb/src/ddl.ECMA/satbody_scat.sql
new file mode 120000
index 0000000..faf7315
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_scat.sql
@@ -0,0 +1 @@
+../ddl/satbody_scat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satbody_screen_atovs.sql b/odb/src/ddl.ECMA/satbody_screen_atovs.sql
new file mode 120000
index 0000000..b8b2a84
--- /dev/null
+++ b/odb/src/ddl.ECMA/satbody_screen_atovs.sql
@@ -0,0 +1 @@
+../ddl/satbody_screen_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satellite_identifier_list.sql b/odb/src/ddl.ECMA/satellite_identifier_list.sql
new file mode 120000
index 0000000..1532ad8
--- /dev/null
+++ b/odb/src/ddl.ECMA/satellite_identifier_list.sql
@@ -0,0 +1 @@
+../ddl/satellite_identifier_list.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_cloud_sink.sql b/odb/src/ddl.ECMA/sathdr_cloud_sink.sql
new file mode 120000
index 0000000..231c896
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/sathdr_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_limb.sql b/odb/src/ddl.ECMA/sathdr_limb.sql
new file mode 120000
index 0000000..582fcc3
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_limb.sql
@@ -0,0 +1 @@
+../ddl/sathdr_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_ozone.sql b/odb/src/ddl.ECMA/sathdr_ozone.sql
new file mode 120000
index 0000000..0b0ee31
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_ozone.sql
@@ -0,0 +1 @@
+../ddl/sathdr_ozone.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_radar.sql b/odb/src/ddl.ECMA/sathdr_radar.sql
new file mode 120000
index 0000000..ccc6c51
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_radar.sql
@@ -0,0 +1 @@
+../ddl/sathdr_radar.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_satob.sql b/odb/src/ddl.ECMA/sathdr_satob.sql
new file mode 120000
index 0000000..884b5be
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_satob.sql
@@ -0,0 +1 @@
+../ddl/sathdr_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_scat.sql b/odb/src/ddl.ECMA/sathdr_scat.sql
new file mode 120000
index 0000000..4ca6e0a
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_scat.sql
@@ -0,0 +1 @@
+../ddl/sathdr_scat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_aeolus_auxmet.sql b/odb/src/ddl.ECMA/sathdr_screen_aeolus_auxmet.sql
new file mode 120000
index 0000000..9762b68
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_aeolus_auxmet.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_aeolus_auxmet.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_atovs.sql b/odb/src/ddl.ECMA/sathdr_screen_atovs.sql
new file mode 120000
index 0000000..187fe53
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_atovs.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_atovs.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_cloud_sink.sql b/odb/src/ddl.ECMA/sathdr_screen_cloud_sink.sql
new file mode 120000
index 0000000..4b78c69
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_gpsro.sql b/odb/src/ddl.ECMA/sathdr_screen_gpsro.sql
new file mode 120000
index 0000000..474b513
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_gpsro.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_gpsro.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_lrad.sql b/odb/src/ddl.ECMA/sathdr_screen_lrad.sql
new file mode 120000
index 0000000..1188285
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_lrad.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_lrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_resat.sql b/odb/src/ddl.ECMA/sathdr_screen_resat.sql
new file mode 120000
index 0000000..08c8463
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_resat.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_resat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sathdr_screen_satob.sql b/odb/src/ddl.ECMA/sathdr_screen_satob.sql
new file mode 120000
index 0000000..2b7c621
--- /dev/null
+++ b/odb/src/ddl.ECMA/sathdr_screen_satob.sql
@@ -0,0 +1 @@
+../ddl/sathdr_screen_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satob.h b/odb/src/ddl.ECMA/satob.h
new file mode 120000
index 0000000..3230a42
--- /dev/null
+++ b/odb/src/ddl.ECMA/satob.h
@@ -0,0 +1 @@
+../ddl/satob.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satob_robhdr_1.sql b/odb/src/ddl.ECMA/satob_robhdr_1.sql
new file mode 120000
index 0000000..f43441d
--- /dev/null
+++ b/odb/src/ddl.ECMA/satob_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/satob_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/satob_robody_1.sql b/odb/src/ddl.ECMA/satob_robody_1.sql
new file mode 120000
index 0000000..5eb82bc
--- /dev/null
+++ b/odb/src/ddl.ECMA/satob_robody_1.sql
@@ -0,0 +1 @@
+../ddl/satob_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scat_robhdr_1.sql b/odb/src/ddl.ECMA/scat_robhdr_1.sql
new file mode 120000
index 0000000..30d4cde
--- /dev/null
+++ b/odb/src/ddl.ECMA/scat_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/scat_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scat_robody_1.sql b/odb/src/ddl.ECMA/scat_robody_1.sql
new file mode 120000
index 0000000..cbc90ae
--- /dev/null
+++ b/odb/src/ddl.ECMA/scat_robody_1.sql
@@ -0,0 +1 @@
+../ddl/scat_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scatt.h b/odb/src/ddl.ECMA/scatt.h
new file mode 120000
index 0000000..0a2840c
--- /dev/null
+++ b/odb/src/ddl.ECMA/scatt.h
@@ -0,0 +1 @@
+../ddl/scatt.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scatt.sql b/odb/src/ddl.ECMA/scatt.sql
new file mode 120000
index 0000000..7a1a418
--- /dev/null
+++ b/odb/src/ddl.ECMA/scatt.sql
@@ -0,0 +1 @@
+../ddl/scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scatt_flag.sql b/odb/src/ddl.ECMA/scatt_flag.sql
new file mode 120000
index 0000000..0c9b5a0
--- /dev/null
+++ b/odb/src/ddl.ECMA/scatt_flag.sql
@@ -0,0 +1 @@
+../ddl/scatt_flag.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/scatt_update_links.sql b/odb/src/ddl.ECMA/scatt_update_links.sql
new file mode 120000
index 0000000..00408d3
--- /dev/null
+++ b/odb/src/ddl.ECMA/scatt_update_links.sql
@@ -0,0 +1 @@
+../ddl/scatt_update_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robhdr_1.sql b/odb/src/ddl.ECMA/screen_robhdr_1.sql
new file mode 120000
index 0000000..5766763
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/screen_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robhdr_2.sql b/odb/src/ddl.ECMA/screen_robhdr_2.sql
new file mode 120000
index 0000000..332b0ff
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robhdr_2.sql
@@ -0,0 +1 @@
+../ddl/screen_robhdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robhdr_3.sql b/odb/src/ddl.ECMA/screen_robhdr_3.sql
new file mode 120000
index 0000000..66fb0c7
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robhdr_3.sql
@@ -0,0 +1 @@
+../ddl/screen_robhdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robody_1.sql b/odb/src/ddl.ECMA/screen_robody_1.sql
new file mode 120000
index 0000000..095abd1
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robody_1.sql
@@ -0,0 +1 @@
+../ddl/screen_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robody_2.sql b/odb/src/ddl.ECMA/screen_robody_2.sql
new file mode 120000
index 0000000..aa2c788
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robody_2.sql
@@ -0,0 +1 @@
+../ddl/screen_robody_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/screen_robody_3.sql b/odb/src/ddl.ECMA/screen_robody_3.sql
new file mode 120000
index 0000000..fa099d8
--- /dev/null
+++ b/odb/src/ddl.ECMA/screen_robody_3.sql
@@ -0,0 +1 @@
+../ddl/screen_robody_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sensor.h b/odb/src/ddl.ECMA/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.ECMA/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/set_active.sql b/odb/src/ddl.ECMA/set_active.sql
new file mode 120000
index 0000000..5381e96
--- /dev/null
+++ b/odb/src/ddl.ECMA/set_active.sql
@@ -0,0 +1 @@
+../ddl/set_active.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/set_active_smos.sql b/odb/src/ddl.ECMA/set_active_smos.sql
new file mode 120000
index 0000000..f432f82
--- /dev/null
+++ b/odb/src/ddl.ECMA/set_active_smos.sql
@@ -0,0 +1 @@
+../ddl/set_active_smos.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/setup_tovscv.sql b/odb/src/ddl.ECMA/setup_tovscv.sql
new file mode 120000
index 0000000..35327f9
--- /dev/null
+++ b/odb/src/ddl.ECMA/setup_tovscv.sql
@@ -0,0 +1 @@
+../ddl/setup_tovscv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/setup_tovscv_cloud_sink.sql b/odb/src/ddl.ECMA/setup_tovscv_cloud_sink.sql
new file mode 120000
index 0000000..4017614
--- /dev/null
+++ b/odb/src/ddl.ECMA/setup_tovscv_cloud_sink.sql
@@ -0,0 +1 @@
+../ddl/setup_tovscv_cloud_sink.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/size_hdr.sql b/odb/src/ddl.ECMA/size_hdr.sql
new file mode 120000
index 0000000..4fa6223
--- /dev/null
+++ b/odb/src/ddl.ECMA/size_hdr.sql
@@ -0,0 +1 @@
+../ddl/size_hdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/small.sql b/odb/src/ddl.ECMA/small.sql
new file mode 120000
index 0000000..4d2f543
--- /dev/null
+++ b/odb/src/ddl.ECMA/small.sql
@@ -0,0 +1 @@
+../ddl/small.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/smos.h b/odb/src/ddl.ECMA/smos.h
new file mode 120000
index 0000000..78794a4
--- /dev/null
+++ b/odb/src/ddl.ECMA/smos.h
@@ -0,0 +1 @@
+../ddl/smos.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssa_robhdr_2m.sql b/odb/src/ddl.ECMA/ssa_robhdr_2m.sql
new file mode 120000
index 0000000..d9df8d9
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssa_robhdr_2m.sql
@@ -0,0 +1 @@
+../ddl/ssa_robhdr_2m.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssa_robhdr_snow.sql b/odb/src/ddl.ECMA/ssa_robhdr_snow.sql
new file mode 120000
index 0000000..acac2aa
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssa_robhdr_snow.sql
@@ -0,0 +1 @@
+../ddl/ssa_robhdr_snow.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssa_robody_2m.sql b/odb/src/ddl.ECMA/ssa_robody_2m.sql
new file mode 120000
index 0000000..9298294
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssa_robody_2m.sql
@@ -0,0 +1 @@
+../ddl/ssa_robody_2m.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssa_robody_snow.sql b/odb/src/ddl.ECMA/ssa_robody_snow.sql
new file mode 120000
index 0000000..13e2078
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssa_robody_snow.sql
@@ -0,0 +1 @@
+../ddl/ssa_robody_snow.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssafb_surfbody_2m.sql b/odb/src/ddl.ECMA/ssafb_surfbody_2m.sql
new file mode 120000
index 0000000..cdeb37d
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssafb_surfbody_2m.sql
@@ -0,0 +1 @@
+../ddl/ssafb_surfbody_2m.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssafb_surfbody_snow.sql b/odb/src/ddl.ECMA/ssafb_surfbody_snow.sql
new file mode 120000
index 0000000..3e673ef
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssafb_surfbody_snow.sql
@@ -0,0 +1 @@
+../ddl/ssafb_surfbody_snow.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/ssmi1d.h b/odb/src/ddl.ECMA/ssmi1d.h
new file mode 120000
index 0000000..716724f
--- /dev/null
+++ b/odb/src/ddl.ECMA/ssmi1d.h
@@ -0,0 +1 @@
+../ddl/ssmi1d.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/stat_obs_1.sql b/odb/src/ddl.ECMA/stat_obs_1.sql
new file mode 120000
index 0000000..f9868fd
--- /dev/null
+++ b/odb/src/ddl.ECMA/stat_obs_1.sql
@@ -0,0 +1 @@
+../ddl/stat_obs_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/stat_obs_2.sql b/odb/src/ddl.ECMA/stat_obs_2.sql
new file mode 120000
index 0000000..e1b4424
--- /dev/null
+++ b/odb/src/ddl.ECMA/stat_obs_2.sql
@@ -0,0 +1 @@
+../ddl/stat_obs_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/stat_obs_3.sql b/odb/src/ddl.ECMA/stat_obs_3.sql
new file mode 120000
index 0000000..10986bf
--- /dev/null
+++ b/odb/src/ddl.ECMA/stat_obs_3.sql
@@ -0,0 +1 @@
+../ddl/stat_obs_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/store_enda.sql b/odb/src/ddl.ECMA/store_enda.sql
new file mode 120000
index 0000000..0948057
--- /dev/null
+++ b/odb/src/ddl.ECMA/store_enda.sql
@@ -0,0 +1 @@
+../ddl/store_enda.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sufger_allsky.sql b/odb/src/ddl.ECMA/sufger_allsky.sql
new file mode 120000
index 0000000..7b64821
--- /dev/null
+++ b/odb/src/ddl.ECMA/sufger_allsky.sql
@@ -0,0 +1 @@
+../ddl/sufger_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sufger_allsky_body.sql b/odb/src/ddl.ECMA/sufger_allsky_body.sql
new file mode 120000
index 0000000..e7a4467
--- /dev/null
+++ b/odb/src/ddl.ECMA/sufger_allsky_body.sql
@@ -0,0 +1 @@
+../ddl/sufger_allsky_body.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sufger_robhdr_1.sql b/odb/src/ddl.ECMA/sufger_robhdr_1.sql
new file mode 120000
index 0000000..f432e99
--- /dev/null
+++ b/odb/src/ddl.ECMA/sufger_robhdr_1.sql
@@ -0,0 +1 @@
+../ddl/sufger_robhdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sufger_robody_1.sql b/odb/src/ddl.ECMA/sufger_robody_1.sql
new file mode 120000
index 0000000..4c3e691
--- /dev/null
+++ b/odb/src/ddl.ECMA/sufger_robody_1.sql
@@ -0,0 +1 @@
+../ddl/sufger_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sufger_sat.sql b/odb/src/ddl.ECMA/sufger_sat.sql
new file mode 120000
index 0000000..44e0086
--- /dev/null
+++ b/odb/src/ddl.ECMA/sufger_sat.sql
@@ -0,0 +1 @@
+../ddl/sufger_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/sugoms.sql b/odb/src/ddl.ECMA/sugoms.sql
new file mode 120000
index 0000000..27fa4b8
--- /dev/null
+++ b/odb/src/ddl.ECMA/sugoms.sql
@@ -0,0 +1 @@
+../ddl/sugoms.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobarea.sql b/odb/src/ddl.ECMA/suobarea.sql
new file mode 120000
index 0000000..2c557c2
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobarea.sql
@@ -0,0 +1 @@
+../ddl/suobarea.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobarea_limb.sql b/odb/src/ddl.ECMA/suobarea_limb.sql
new file mode 120000
index 0000000..9bce292
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobarea_limb.sql
@@ -0,0 +1 @@
+../ddl/suobarea_limb.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobarea_sat.sql b/odb/src/ddl.ECMA/suobarea_sat.sql
new file mode 120000
index 0000000..a66954c
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobarea_sat.sql
@@ -0,0 +1 @@
+../ddl/suobarea_sat.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobarea_satob.sql b/odb/src/ddl.ECMA/suobarea_satob.sql
new file mode 120000
index 0000000..c0e67a2
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobarea_satob.sql
@@ -0,0 +1 @@
+../ddl/suobarea_satob.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobarea_scatt.sql b/odb/src/ddl.ECMA/suobarea_scatt.sql
new file mode 120000
index 0000000..afbc7bc
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobarea_scatt.sql
@@ -0,0 +1 @@
+../ddl/suobarea_scatt.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suobsaddr.sql b/odb/src/ddl.ECMA/suobsaddr.sql
new file mode 120000
index 0000000..51e4131
--- /dev/null
+++ b/odb/src/ddl.ECMA/suobsaddr.sql
@@ -0,0 +1 @@
+../ddl/suobsaddr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/surfbody_feedback.h b/odb/src/ddl.ECMA/surfbody_feedback.h
new file mode 120000
index 0000000..bfe4184
--- /dev/null
+++ b/odb/src/ddl.ECMA/surfbody_feedback.h
@@ -0,0 +1 @@
+../ddl/surfbody_feedback.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suvarbc_robhdr_0.sql b/odb/src/ddl.ECMA/suvarbc_robhdr_0.sql
new file mode 120000
index 0000000..3095dda
--- /dev/null
+++ b/odb/src/ddl.ECMA/suvarbc_robhdr_0.sql
@@ -0,0 +1 @@
+../ddl/suvarbc_robhdr_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/suvarbc_robody_0.sql b/odb/src/ddl.ECMA/suvarbc_robody_0.sql
new file mode 120000
index 0000000..f61b0c2
--- /dev/null
+++ b/odb/src/ddl.ECMA/suvarbc_robody_0.sql
@@ -0,0 +1 @@
+../ddl/suvarbc_robody_0.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/swapbytes.h b/odb/src/ddl.ECMA/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.ECMA/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/tcwv.sql b/odb/src/ddl.ECMA/tcwv.sql
new file mode 120000
index 0000000..f89c6e9
--- /dev/null
+++ b/odb/src/ddl.ECMA/tcwv.sql
@@ -0,0 +1 @@
+../ddl/tcwv.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/time_info.sql b/odb/src/ddl.ECMA/time_info.sql
new file mode 120000
index 0000000..847c1a7
--- /dev/null
+++ b/odb/src/ddl.ECMA/time_info.sql
@@ -0,0 +1 @@
+../ddl/time_info.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/time_numtsl.sql b/odb/src/ddl.ECMA/time_numtsl.sql
new file mode 120000
index 0000000..a3f68b5
--- /dev/null
+++ b/odb/src/ddl.ECMA/time_numtsl.sql
@@ -0,0 +1 @@
+../ddl/time_numtsl.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/tovsrtovs_robody_1.sql b/odb/src/ddl.ECMA/tovsrtovs_robody_1.sql
new file mode 120000
index 0000000..a868601
--- /dev/null
+++ b/odb/src/ddl.ECMA/tovsrtovs_robody_1.sql
@@ -0,0 +1 @@
+../ddl/tovsrtovs_robody_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/tslot.sql b/odb/src/ddl.ECMA/tslot.sql
new file mode 120000
index 0000000..be7bbab
--- /dev/null
+++ b/odb/src/ddl.ECMA/tslot.sql
@@ -0,0 +1 @@
+../ddl/tslot.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/type_definitions.h b/odb/src/ddl.ECMA/type_definitions.h
new file mode 120000
index 0000000..3711447
--- /dev/null
+++ b/odb/src/ddl.ECMA/type_definitions.h
@@ -0,0 +1 @@
+../ddl/type_definitions.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update.h b/odb/src/ddl.ECMA/update.h
new file mode 120000
index 0000000..8068022
--- /dev/null
+++ b/odb/src/ddl.ECMA/update.h
@@ -0,0 +1 @@
+../ddl/update.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_body_3.sql b/odb/src/ddl.ECMA/update_body_3.sql
new file mode 120000
index 0000000..70fa910
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_body_3.sql
@@ -0,0 +1 @@
+../ddl/update_body_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_desc_1.sql b/odb/src/ddl.ECMA/update_desc_1.sql
new file mode 120000
index 0000000..bf1795e
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_desc_1.sql
@@ -0,0 +1 @@
+../ddl/update_desc_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_desc_2.sql b/odb/src/ddl.ECMA/update_desc_2.sql
new file mode 120000
index 0000000..721686d
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_desc_2.sql
@@ -0,0 +1 @@
+../ddl/update_desc_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_fcdiag_links.sql b/odb/src/ddl.ECMA/update_fcdiag_links.sql
new file mode 120000
index 0000000..81f5ccd
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_fcdiag_links.sql
@@ -0,0 +1 @@
+../ddl/update_fcdiag_links.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_hdr_1.sql b/odb/src/ddl.ECMA/update_hdr_1.sql
new file mode 120000
index 0000000..6d9bb2a
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_hdr_1.sql
@@ -0,0 +1 @@
+../ddl/update_hdr_1.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_hdr_2.sql b/odb/src/ddl.ECMA/update_hdr_2.sql
new file mode 120000
index 0000000..067d0c5
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_hdr_2.sql
@@ -0,0 +1 @@
+../ddl/update_hdr_2.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_hdr_3.sql b/odb/src/ddl.ECMA/update_hdr_3.sql
new file mode 120000
index 0000000..76fd8c7
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_hdr_3.sql
@@ -0,0 +1 @@
+../ddl/update_hdr_3.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_allsky.sql b/odb/src/ddl.ECMA/update_links_allsky.sql
new file mode 120000
index 0000000..fff6d95
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_allsky.sql
@@ -0,0 +1 @@
+../ddl/update_links_allsky.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_auxiliary.sql b/odb/src/ddl.ECMA/update_links_auxiliary.sql
new file mode 120000
index 0000000..6d1a761
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_auxiliary.sql
@@ -0,0 +1 @@
+../ddl/update_links_auxiliary.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_gbrad.sql b/odb/src/ddl.ECMA/update_links_gbrad.sql
new file mode 120000
index 0000000..d4c4838
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_gbrad.sql
@@ -0,0 +1 @@
+../ddl/update_links_gbrad.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_radiance.sql b/odb/src/ddl.ECMA/update_links_radiance.sql
new file mode 120000
index 0000000..ad6561a
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_radiance.sql
@@ -0,0 +1 @@
+../ddl/update_links_radiance.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_raingg.sql b/odb/src/ddl.ECMA/update_links_raingg.sql
new file mode 120000
index 0000000..6d163cd
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_raingg.sql
@@ -0,0 +1 @@
+../ddl/update_links_raingg.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_links_ssmi.sql b/odb/src/ddl.ECMA/update_links_ssmi.sql
new file mode 120000
index 0000000..95cd0a0
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_links_ssmi.sql
@@ -0,0 +1 @@
+../ddl/update_links_ssmi.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/update_modstep.sql b/odb/src/ddl.ECMA/update_modstep.sql
new file mode 120000
index 0000000..d7c44cd
--- /dev/null
+++ b/odb/src/ddl.ECMA/update_modstep.sql
@@ -0,0 +1 @@
+../ddl/update_modstep.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_airep_robhdr.sql b/odb/src/ddl.ECMA/varbc_airep_robhdr.sql
new file mode 120000
index 0000000..9febd9d
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_airep_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_airep_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_airep_robody.sql b/odb/src/ddl.ECMA/varbc_airep_robody.sql
new file mode 120000
index 0000000..f36d1cc
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_airep_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_airep_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_allsky_robhdr.sql b/odb/src/ddl.ECMA/varbc_allsky_robhdr.sql
new file mode 120000
index 0000000..694efab
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_allsky_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_allsky_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_allsky_robody.sql b/odb/src/ddl.ECMA/varbc_allsky_robody.sql
new file mode 120000
index 0000000..281add1
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_allsky_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_allsky_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_gbrad_robhdr.sql b/odb/src/ddl.ECMA/varbc_gbrad_robhdr.sql
new file mode 120000
index 0000000..ad11101
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_gbrad_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_gbrad_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_gbrad_robody.sql b/odb/src/ddl.ECMA/varbc_gbrad_robody.sql
new file mode 120000
index 0000000..42d0ecb
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_gbrad_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_gbrad_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_mode_hist_robhdr.sql b/odb/src/ddl.ECMA/varbc_mode_hist_robhdr.sql
new file mode 120000
index 0000000..cd9be79
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_mode_hist_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_mode_hist_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_mode_hist_robody.sql b/odb/src/ddl.ECMA/varbc_mode_hist_robody.sql
new file mode 120000
index 0000000..f76d563
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_mode_hist_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_mode_hist_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_rad_robhdr.sql b/odb/src/ddl.ECMA/varbc_rad_robhdr.sql
new file mode 120000
index 0000000..fbd8182
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_rad_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_rad_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_rad_robody.sql b/odb/src/ddl.ECMA/varbc_rad_robody.sql
new file mode 120000
index 0000000..959a958
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_rad_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_rad_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_setup_robhdr.sql b/odb/src/ddl.ECMA/varbc_setup_robhdr.sql
new file mode 120000
index 0000000..40ea481
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_setup_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_setup_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_setup_robody.sql b/odb/src/ddl.ECMA/varbc_setup_robody.sql
new file mode 120000
index 0000000..884a2ce
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_setup_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_setup_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_sfcobs_robhdr.sql b/odb/src/ddl.ECMA/varbc_sfcobs_robhdr.sql
new file mode 120000
index 0000000..cc0d75b
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_sfcobs_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_sfcobs_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_sfcobs_robody.sql b/odb/src/ddl.ECMA/varbc_sfcobs_robody.sql
new file mode 120000
index 0000000..3bab245
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_sfcobs_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_sfcobs_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_tcwv_robhdr.sql b/odb/src/ddl.ECMA/varbc_tcwv_robhdr.sql
new file mode 120000
index 0000000..0e83d64
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_tcwv_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_tcwv_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_tcwv_robody.sql b/odb/src/ddl.ECMA/varbc_tcwv_robody.sql
new file mode 120000
index 0000000..a9650f9
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_tcwv_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_tcwv_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_to3_robhdr.sql b/odb/src/ddl.ECMA/varbc_to3_robhdr.sql
new file mode 120000
index 0000000..5442c5b
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_to3_robhdr.sql
@@ -0,0 +1 @@
+../ddl/varbc_to3_robhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varbc_to3_robody.sql b/odb/src/ddl.ECMA/varbc_to3_robody.sql
new file mode 120000
index 0000000..26bebf9
--- /dev/null
+++ b/odb/src/ddl.ECMA/varbc_to3_robody.sql
@@ -0,0 +1 @@
+../ddl/varbc_to3_robody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/varno.h b/odb/src/ddl.ECMA/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.ECMA/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.ECMA/vertco_type.h b/odb/src/ddl.ECMA/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.ECMA/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE11/CMakeLists.txt b/odb/src/ddl.ERACOUNTRYTTABLE11/CMakeLists.txt
new file mode 100644
index 0000000..ff2fe07
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE11/CMakeLists.txt
@@ -0,0 +1,5 @@
+odb_add_schema(TARGET ERACOUNTRYTTABLE11
+    TYPE ${ODB_LIBS_TYPE}
+    SOURCES ERACOUNTRYTTABLE11.ddl
+    VIEWS table11_hdr.sql
+    CONDITION ODB_HAVE_ERACOUNTRYTTABLE11)
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE11/ERACOUNTRYTTABLE11.ddl b/odb/src/ddl.ERACOUNTRYTTABLE11/ERACOUNTRYTTABLE11.ddl
new file mode 100644
index 0000000..026bbbb
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE11/ERACOUNTRYTTABLE11.ddl
@@ -0,0 +1,34 @@
+//
+//  ERACOUNTRYTTABLE11 hierarchy:
+//
+//      1  era_country_t_table11_desc
+//      2  +---> era_country_t_table11_hdr
+//
+//RESET ALIGN;
+//ALIGN(body[1:12]);
+
+CREATE TABLE era_country_t_table11_desc AS (
+// creation date, time and created by whom (username)
+creadate YYYYMMDD,
+creatime HHMMSS,
+creaby   string,
+
+// modification date, time and modified by whom (username)
+moddate YYYYMMDD,
+modtime HHMMSS,
+modby   string,
+);
+
+CREATE TABLE era_country_t_table11_hdr AS (
+  seqno pk1int,                        //     1 SEQUENCE NO
+  active_line pk1int,                  //     2 ACTIVE LINE IND (=1)
+  active_inactive_seqno pk1int,        //     3 ACTIVE LINE SEQUENCE NO
+  country_group pk1int,                //     4 COUNTRY GROUP
+  country_statid_from pk1int,          //     5 COUNTRY STAT ID FROM
+  country_statid_to pk1int,            //     6 COUNTRY STAT ID TO
+  country_lat_from pk1int,             //     7 COUNTRY LAT FROM
+  country_lat_to pk1int,               //     8 COUNTRY LAT TO
+  country_lon_from pk1int,             //     9 COUNTRY LON FROM
+  country_lon_to pk1int,               //    10 COUNTRY LON TO
+  country_name[8] string,              // 11-18 COUNTRY NAME
+);
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE11/table11_hdr.sql b/odb/src/ddl.ERACOUNTRYTTABLE11/table11_hdr.sql
new file mode 100644
index 0000000..39bc5d0
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE11/table11_hdr.sql
@@ -0,0 +1,22 @@
+READONLY;
+CREATE VIEW table11_hdr AS
+SELECT seqno,                      //  1
+       active_line,                //  2
+       active_inactive_seqno,      //  3
+       country_group,              //  4
+       country_statid_from,        //  5
+       country_statid_to,          //  6
+       country_lat_from,           //  7
+       country_lat_to,             //  8
+       country_lon_from,           //  9
+       country_lon_to,             // 10
+       country_name_1,             // 11
+       country_name_2,             // 12
+       country_name_3,             // 13
+       country_name_4,             // 14
+       country_name_5,             // 15
+       country_name_6,             // 16
+       country_name_7,             // 17
+       country_name_8              // 18
+FROM era_country_t_table11_hdr
+;
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE12/CMakeLists.txt b/odb/src/ddl.ERACOUNTRYTTABLE12/CMakeLists.txt
new file mode 100644
index 0000000..21b4b0d
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE12/CMakeLists.txt
@@ -0,0 +1,5 @@
+odb_add_schema(TARGET ERACOUNTRYTTABLE12
+    TYPE ${ODB_LIBS_TYPE}
+    SOURCES ERACOUNTRYTTABLE12.ddl
+    VIEWS table12_hdr.sql
+    CONDITION ODB_HAVE_ERACOUNTRYTTABLE12)
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE12/ERACOUNTRYTTABLE12.ddl b/odb/src/ddl.ERACOUNTRYTTABLE12/ERACOUNTRYTTABLE12.ddl
new file mode 100644
index 0000000..149b13a
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE12/ERACOUNTRYTTABLE12.ddl
@@ -0,0 +1,29 @@
+//
+//  ERACOUNTRYTTABLE12 hierarchy:
+//
+//      1  country_t_table12_desc
+//      2  +---> country_t_table12_hdr
+//
+//RESET ALIGN;
+//ALIGN(body[1:12]);
+
+CREATE TABLE era_country_t_table12_desc AS (
+// creation date, time and created by whom (username)
+creadate YYYYMMDD,
+creatime HHMMSS,
+creaby   string,
+
+// modification date, time and modified by whom (username)
+moddate YYYYMMDD,
+modtime HHMMSS,
+modby   string,
+);
+
+CREATE TABLE era_country_t_table12_hdr AS (
+  seqno pk1int,                        //     1 SEQUENCE NO
+  active_line pk1int,                  //     2 ACTIVE LINE IND
+  active_inactive_seqno pk1int,        //     3 active/inactive line count
+  country_group pk1int,                //     4 COUNTRY GROUP
+  country_name[8] string,              //  5-12 COUNTRY name
+);
+
diff --git a/odb/src/ddl.ERACOUNTRYTTABLE12/table12_hdr.sql b/odb/src/ddl.ERACOUNTRYTTABLE12/table12_hdr.sql
new file mode 100644
index 0000000..8b909bb
--- /dev/null
+++ b/odb/src/ddl.ERACOUNTRYTTABLE12/table12_hdr.sql
@@ -0,0 +1,10 @@
+READONLY;
+CREATE VIEW table12_hdr AS
+SELECT seqno,
+//        1 
+       active_line, active_inactive_seqno, country_group,
+//        2                    3                4
+       country_name_1, country_name_2, country_name_3, country_name_4, country_name_5, country_name_6, country_name_7, country_name_8
+//          5                 6              7                8            9               10              11              12
+FROM era_country_t_table12_hdr
+;
diff --git a/odb/src/ddl.MTOCOMP/CMakeLists.txt b/odb/src/ddl.MTOCOMP/CMakeLists.txt
new file mode 100644
index 0000000..7cc99f6
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/CMakeLists.txt
@@ -0,0 +1,34 @@
+set(sources
+
+    MTOCOMP.ddl
+
+    alloc.h
+    bits.h
+    cdrhook.h
+    cma.h
+    dca.h
+    ecstdlib.h
+    funcs.h
+    idx.h
+    info.h
+    magicwords.h
+    mdi.h
+    namecfg.h
+    obstype.h
+    odb.h
+    odb98.flags
+    odb_macros.h
+    odbcrc.h
+    odbmd5.h
+    pcma_extern.h
+    ppcode.h
+    privpub.h
+    sensor.h
+    swapbytes.h
+    varno.h
+    vertco_type.h
+)
+
+set(views)
+
+odb_add_schema(TARGET MTOCOMP SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_MTOCOMP TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.MTOCOMP/MTOCOMP.ddl b/odb/src/ddl.MTOCOMP/MTOCOMP.ddl
new file mode 100644
index 0000000..ada49ac
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/MTOCOMP.ddl
@@ -0,0 +1,196 @@
+SET  $NMXUPD = 3;
+
+CREATE TYPE report_rdbflag_t AS (
+  lat_humon bit1,  
+  lat_QCsub bit1,  
+  lat_override bit1,  
+  lat_flag bit2,  
+  lat_HQC_flag bit1,  
+  lon_humon bit1,  
+  lon_QCsub bit1,  
+  lon_override bit1,  
+  lon_flag bit2,  
+  lon_HQC_flag bit1,  
+  date_humon bit1,  
+  date_QCsub bit1,  
+  date_override bit1,  
+  date_flag bit2,  
+  date_HQC_flag bit1,  
+  time_humon bit1,  
+  time_QCsub bit1,  
+  time_override bit1,  
+  time_flag bit2,  
+  time_HQC_flag bit1,  
+  stalt_humon bit1,  
+  stalt_QCsub bit1,  
+  stalt_override bit1,  
+  stalt_flag bit2,  
+  stalt_HQC_flag bit1,  
+);
+
+CREATE TYPE status_t AS (
+  active bit1,                          // ACTIVE FLAG
+  passive bit1,                         // PASSIVE FLAG
+  rejected bit1,                        // REJECTED FLAG
+  blacklisted bit1,                     // BLACKLISTED
+  monthly bit1,
+  constant bit1,
+  experimental bit1,
+  whitelist bit1,
+);
+
+CREATE TYPE datum_flag_t AS (
+  final bit4,                           // FINAL FLAG
+  fg bit4,                              // FIRST GUESS FLAG
+  depar bit4,                           // DEPARTURE FLAG
+  varQC bit4,                           // VARIATIONAL QUALITY FLAG
+  blacklist bit4,                       // BLACKLIST FLAG
+  ups bit1,                             // d'utilisation par analyse de pression de surface
+  uvt bit1,                             // d'utilisation par analyse de vent et temperature
+  uhu bit1,                             // d'utilisation par analyse d'humidite
+  ut2 bit1,                             // d'utilisation par analyse de temperat ure a 2m
+  uh2 bit1,                             // d'utilisation par analyse d'humidite a 2m
+  uv1 bit1,                             // d'utilisation par analyse de vent a 10m
+  urr bit1,                             // d'utilisation par analyse de precipitations
+  usn bit1,                             // d'utilisation par analyse de neige
+  usst bit1,                            // d'utilisation par analyse de temperature de surface de la mer
+);
+
+CREATE TYPE report_event1_t AS (
+  no_data bit1,  
+  all_rejected bit1,  
+  bad_practice bit1,  
+  rdb_rejected bit1,  
+  rdb_activated bit1,  
+  whitelist_activated bit1,  
+  horipos_outrange bit1,  
+  vertpos_outrange bit1,  
+  time_outrange bit1,  
+  redundant bit1,  
+  land bit1,  
+  sea bit1,  
+  stalt_missing bit1,  
+  modsurf_stalt_distance bit1,  
+  namelist_rejected bit1,  
+  QC_failed bit1,  
+);
+
+CREATE TYPE report_event2_t = pk1int;
+
+CREATE TYPE datum_event1_t AS (
+  vertco_missing bit1,  
+  obsvalue_missing bit1,  
+  fg_missing bit1,  
+  rdb_rejected bit1,  
+  rdb_activated bit1,  
+  whitelist_activated bit1,  
+  bad_practice bit1,  
+  vertpos_outrange bit1,  
+  reflevel_outrange bit1,  
+  fg2big bit1,  
+  depar2big bit1,  
+  obs_error2big bit1,  
+  datum_redundant bit1,  
+  level_redundant bit1,  
+  land bit1,  
+  sea bit1,  
+  not_analysis_varno bit1,  
+  duplicate bit1,  
+  levels2many bit1,  
+  multilevel_check bit1,  
+  level_selection bit1,  
+  vertco_consistency bit1,  
+  vertco_type_changed bit1,  
+  namelist_rejected bit1,  
+  combined_flagging bit1,  
+  report_rejected bit1,  
+  varQC_performed bit1,
+  contam_cld_flag bit1,  // cloud contamination
+  contam_rain_flag bit1, // rain contamination
+  contam_aerosol_flag bit1, // aerosol contamination
+);
+
+CREATE TABLE ddrs AS (
+  ddrno pk1int,  
+  wordno pk1int,  
+  bulkdata pk9real,  
+);
+
+CREATE TABLE hdr AS (
+  obstype pk1int,                       // OBSERVATION TYPE
+  codetype pk1int,                      // OBSERVATION CODE TYPE
+  insttype pk1int,                      // OBSERVATION INSTRUMENT TYPE
+  date YYYYMMDD,                        // OBS. DATE
+  time HHMMSS,                          // OBS. EXACT TIME
+  status STATUS_t,                      // REPORT'S STATUS
+  event1 REPORT_EVENT1_t,               // REPORT'S EVENTS (PART 1)
+  statid string,                        // STATION ID (CHARACTER*8)
+  ident pk1int,                         // Integer equivalent of STATION ID (or zero)
+  lat pk9real,                          // LATITUDE
+  lon pk9real,                          // LONGITUDE
+  stalt pk9real,                        // ALTITUDE
+  modoro pk9real,                       // MODEL'S OROGRAPHY
+  sensor pk1int,                        // SATELLITE SENSOR INDICATOR
+  sat @LINK,  
+  body @LINK,  
+  errstat @LINK,  
+  update[1:$NMXUPD] @LINK,  
+  rdbflag REPORT_RDBFLAG_t,             // REPORT'S FLAGS
+  event2 REPORT_EVENT2_t,               // REPORT EVENTS (PART 2) WORD POS.
+);
+
+CREATE TABLE sat AS (
+  satid pk1int,                        // Integer equivalent to statid at hdr or 0; same as ident at hdr
+  atovs @LINK,  
+  reo3  @LINK,  
+  satob @LINK,  
+  scatt @LINK,  
+);
+
+CREATE TABLE reo3 AS (
+  solar_elevation pk9real,              // SOLAR ELEVATION
+);
+
+CREATE TABLE satob AS (
+  comp_method pk1int,                   // CLOUD MOTION COMP. METHOD
+);
+
+CREATE TABLE atovs AS (
+  scanline pk1int,                      // SCAN LINE NUMBER                   
+  fov pk1int,                           // FIELD OF VIEW NUMBER               
+  bearing_azimuth pk9real,              // BEARING OR AZIMUTH
+  cldne[1:2] pk9real,                   // CLOUD EMISSIVITY FROM HIRS RADIANCES
+);
+
+CREATE TABLE atovs_pred AS (
+  predictor[16] pk9real,  
+);
+
+CREATE TABLE scatt AS (
+  cellno pk1int,                        // CELL NO.
+);
+
+CREATE TABLE body AS (
+  varno pk1int,                         // VARIABLE NUMBER
+  anflag DATUM_FLAG_t,                  // OBSERVATION FLAGS
+  status STATUS_t,                      // OBSERVATION STATUS
+  event1 DATUM_EVENT1_t,                // OBSERVATION EVENTS (PART 1)
+  press pk9real,                        // VERTICAL COORDINATE REFERENCE 1
+  press_rl pk9real,                     // VERTICAL COORDINATE REFERENCE 2
+  obsvalue pk9real,                     // OBSERVED VARIABLE
+  biascorr pk9real,                     // RADIANCE BIAS CORRECTION
+  an_depar pk9real,                     // OBSERVED MINUS ANALYSED VALUE
+  fg_depar pk9real,                     // OBSERVED MINUS FIRST GUESS VALUE
+  fg_check[2] pk9real,  
+);
+
+CREATE TABLE errstat AS (
+  obs_error pk9real,                    // OBSERVATION ERROR
+  repres_error pk9real,                 // REPRESENTATIVENESS ERROR
+  fg_error pk9real,                     // FIRST GUESS ERROR
+);
+
+CREATE TABLE update[1:$NMXUPD] AS (
+  hires pk9real,               // OBS. MINUS UPD. U HIGH RES. VALUE
+  lores pk9real,               // OBS. MINUS UPD. U LOW RES. VALUE
+);
diff --git a/odb/src/ddl.MTOCOMP/alloc.h b/odb/src/ddl.MTOCOMP/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/bits.h b/odb/src/ddl.MTOCOMP/bits.h
new file mode 120000
index 0000000..459b52a
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/bits.h
@@ -0,0 +1 @@
+../ddl/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/cdrhook.h b/odb/src/ddl.MTOCOMP/cdrhook.h
new file mode 120000
index 0000000..8784f89
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/cdrhook.h
@@ -0,0 +1 @@
+../ddl/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/cma.h b/odb/src/ddl.MTOCOMP/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/dca.h b/odb/src/ddl.MTOCOMP/dca.h
new file mode 120000
index 0000000..005f5d7
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/dca.h
@@ -0,0 +1 @@
+../ddl/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/ecstdlib.h b/odb/src/ddl.MTOCOMP/ecstdlib.h
new file mode 120000
index 0000000..32bb85b
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/ecstdlib.h
@@ -0,0 +1 @@
+../ddl/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/funcs.h b/odb/src/ddl.MTOCOMP/funcs.h
new file mode 120000
index 0000000..e16dc7c
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/funcs.h
@@ -0,0 +1 @@
+../ddl/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/idx.h b/odb/src/ddl.MTOCOMP/idx.h
new file mode 120000
index 0000000..cfdb097
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/idx.h
@@ -0,0 +1 @@
+../ddl/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/info.h b/odb/src/ddl.MTOCOMP/info.h
new file mode 120000
index 0000000..b63984c
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/info.h
@@ -0,0 +1 @@
+../ddl/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/magicwords.h b/odb/src/ddl.MTOCOMP/magicwords.h
new file mode 120000
index 0000000..8135e72
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/magicwords.h
@@ -0,0 +1 @@
+../ddl/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/mdi.h b/odb/src/ddl.MTOCOMP/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/namecfg.h b/odb/src/ddl.MTOCOMP/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/obstype.h b/odb/src/ddl.MTOCOMP/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/odb.h b/odb/src/ddl.MTOCOMP/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/odb98.flags b/odb/src/ddl.MTOCOMP/odb98.flags
new file mode 120000
index 0000000..bc6a361
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/odb98.flags
@@ -0,0 +1 @@
+../ddl/odb98.flags
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/odb_macros.h b/odb/src/ddl.MTOCOMP/odb_macros.h
new file mode 120000
index 0000000..01fe8a8
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/odb_macros.h
@@ -0,0 +1 @@
+../ddl/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/odbcrc.h b/odb/src/ddl.MTOCOMP/odbcrc.h
new file mode 120000
index 0000000..fcd0f0c
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/odbcrc.h
@@ -0,0 +1 @@
+../ddl/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/odbmd5.h b/odb/src/ddl.MTOCOMP/odbmd5.h
new file mode 120000
index 0000000..b81990c
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/odbmd5.h
@@ -0,0 +1 @@
+../ddl/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/pcma_extern.h b/odb/src/ddl.MTOCOMP/pcma_extern.h
new file mode 120000
index 0000000..dba5539
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/pcma_extern.h
@@ -0,0 +1 @@
+../ddl/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/ppcode.h b/odb/src/ddl.MTOCOMP/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/privpub.h b/odb/src/ddl.MTOCOMP/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/sensor.h b/odb/src/ddl.MTOCOMP/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/swapbytes.h b/odb/src/ddl.MTOCOMP/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/varno.h b/odb/src/ddl.MTOCOMP/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.MTOCOMP/vertco_type.h b/odb/src/ddl.MTOCOMP/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.MTOCOMP/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.PSBIAS/CMakeLists.txt b/odb/src/ddl.PSBIAS/CMakeLists.txt
new file mode 100644
index 0000000..af4b679
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(views
+
+    psbias_compress_method_0.sql
+    psbias_compress_method_1a.sql
+    psbias_compress_method_1b.sql
+    psbiasbody.sql
+    psbiasbody_maintenance.sql
+    psbiashdr.sql
+    psbiashdr_maintenance.sql
+)
+
+odb_add_schema(TARGET PSBIAS SOURCES PSBIAS.ddl VIEWS ${views} CONDITION ODB_HAVE_PSBIAS TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.PSBIAS/PSBIAS.ddl b/odb/src/ddl.PSBIAS/PSBIAS.ddl
new file mode 100644
index 0000000..3013831
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/PSBIAS.ddl
@@ -0,0 +1,366 @@
+//
+//  PSBIAS hierarchy:
+//
+//      1  desc
+//      2  +---> hdr
+//      3  +---> body
+
+SET $mdi = 2147483647;
+
+SET $synop = 1;
+SET $manual_synop = 11;
+SET $automatic_synop = 14;
+SET $manual_ship = 21;
+SET $abbreviated_ship = 22;
+SET $reduced_ship = 23;
+SET $automatic_ship = 24;
+SET $metar = 140;
+SET $dribu = 4;
+SET $buoy = 165;
+SET $bathy = 63;
+SET $tesac = 64;
+
+SET $bufr_land_surface = 0;
+SET $bufr_land_manual = 1;
+SET $bufr_land_automatic = 3;
+SET $bufr_land_abbreviated = 9;
+SET $bufr_land_metar = 140;
+SET $bufr_sea_surface = 1;
+SET $bufr_sea_manual_1 = 11;
+SET $bufr_sea_manual_2 = 9;
+SET $bufr_sea_reduced = 19;
+SET $bufr_sea_automatic = 13;
+SET $bufr_sea_dribu = 21;
+SET $bufr_sea_bathy = 22;
+SET $bufr_sea_tesac = 23;
+
+SET $psvarno = 110;
+
+SET $max_body_len = 756;
+
+SET $reduced_press_code = 0;
+SET $station_level_press_code = 1;
+
+
+CREATE TYPE status_t AS (
+  active bit1,                          // ACTIVE FLAG
+  passive bit1,                         // PASSIVE FLAG
+  rejected bit1,                        // REJECTED FLAG
+  blacklisted bit1,                     // BLACKLISTED
+// BLACKLIST FAILCODE BITS
+  monthly bit1,
+  constant bit1,
+  experimental bit1,
+  whitelist bit1,
+);
+
+CREATE TYPE report_rdbflag_t AS (
+  lat_humon bit1,
+  lat_QCsub bit1,
+  lat_override bit1,
+  lat_flag bit2,
+  lat_HQC_flag bit1,
+  lon_humon bit1,
+  lon_QCsub bit1,
+  lon_override bit1,
+  lon_flag bit2,
+  lon_HQC_flag bit1,
+  date_humon bit1,
+  date_QCsub bit1,
+  date_override bit1,
+  date_flag bit2,
+  date_HQC_flag bit1,
+  time_humon bit1, 
+  time_QCsub bit1, 
+  time_override bit1,
+  time_flag bit2, 
+  time_HQC_flag bit1,
+  stalt_humon bit1, 
+  stalt_QCsub bit1, 
+  stalt_override bit1,
+  stalt_flag bit2, 
+  stalt_HQC_flag bit1,
+);
+
+CREATE TYPE datum_rdbflag_t AS (
+  press_humon bit1,
+  press_QCsub bit1,
+  press_override bit1,
+  press_flag bit2,
+  press_HQC_flag bit1,
+  press_judged_prev_an bit2,
+  press_used_prev_an bit1,
+  _press_unused_6 bit6,
+  varno_humon bit1,
+  varno_QCsub bit1,
+  varno_override bit1,
+  varno_flag bit2,
+  varno_HQC_flag bit1,
+  varno_judged_prev_an bit2,
+  varno_used_prev_an bit1,
+//  _varno_unused_6 bit6,
+);
+
+CREATE TYPE datum_flag_t AS (
+  final bit4,           // FINAL FLAG
+  fg bit4,              // FIRST GUESS FLAG
+  depar bit4,           // DEPARTURE FLAG
+  varQC bit4,           // VARIATIONAL QUALITY FLAG
+  blacklist bit4,       // BLACKLIST FLAG
+  ups bit1,             // d'utilisation par analyse de pression de surface
+  uvt bit1,             // d'utilisation par analyse de vent et temperature
+  uhu bit1,             // d'utilisation par analyse d'humidite
+  ut2 bit1,             // d'utilisation par analyse de temperature a 2m
+  uh2 bit1,             // d'utilisation par analyse d'humidite a 2m
+  uv1 bit1,             // d'utilisation par analyse de vent a 10m
+  urr bit1,             // d'utilisation par analyse de precipitations
+  usn bit1,             // d'utilisation par analyse de neige
+  usst bit1,            // d'utilisation par analyse de temperature de surface de la mer
+);
+
+CREATE TYPE report_event1_t AS (
+  no_data bit1,
+  all_rejected bit1,
+  bad_practice bit1,
+  rdb_rejected bit1,
+  rdb_activated bit1,
+  whitelist_activated bit1,
+  horipos_outrange bit1,
+  vertpos_outrange bit1,
+  time_outrange bit1,
+  redundant bit1,
+  land bit1,
+  sea bit1,
+  stalt_missing bit1,
+  modsurf_stalt_distance bit1,
+  namelist_rejected bit1,
+  QC_failed bit1,
+);
+
+CREATE TYPE report_event2_t = pk1int;
+
+CREATE TYPE datum_event1_t AS (
+  vertco_missing bit1,
+  obsvalue_missing bit1,
+  fg_missing bit1,
+  rdb_rejected bit1,
+  rdb_activated bit1,
+  whitelist_activated bit1,
+  bad_practice bit1,
+  vertpos_outrange bit1,
+  reflevel_outrange bit1,
+  fg2big bit1,
+  depar2big bit1,
+  obs_error2big bit1,
+  datum_redundant bit1,
+  level_redundant bit1,
+  land bit1,
+  sea bit1,
+  not_analysis_varno bit1,
+  duplicate bit1,
+  levels2many bit1,
+  multilevel_check bit1,
+  level_selection bit1,
+  vertco_consistency bit1,
+  vertco_type_changed bit1,
+  namelist_rejected bit1,
+  combined_flagging bit1,
+  report_rejected bit1,
+  varQC_performed bit1,
+  contam_cld_flag bit1,  // cloud contamination
+  contam_rain_flag bit1, // rain contamination
+);
+
+CREATE TYPE datum_event2_t = pk1int;
+
+CREATE TYPE report_blacklist_t AS (
+  obstype bit1,
+  statid bit1,
+  codetype bit1,
+  instype bit1,
+  date bit1,
+  time bit1,
+  lat bit1,
+  lon bit1,
+  stalt bit1,
+  scanpos bit1,
+  retrtype bit1,
+  QI_1 bit1,
+  QI_2 bit1,
+  QI_3 bit1,
+  modoro bit1,
+  lsmask bit1,
+  rlsmask bit1,
+  modPS bit1,
+  modTS bit1,
+  modT2M bit1,
+  modtop bit1,
+  sensor bit1,
+  fov bit1,
+  satza bit1,
+  andate bit1,
+  antime bit1,
+);
+
+CREATE TYPE datum_blacklist_t AS (
+  varno bit1,
+  vertco_type bit1,
+  press bit1,
+  press_rl bit1,
+  ppcode bit1,
+  obsvalue bit1,
+  fg_depar bit1,
+  obs_error bit1,
+  fg_error bit1,
+  winchan_dep bit1,
+  obs_t bit1,
+);
+
+CREATE TYPE bc_info_t AS (
+  cold_start bit1,
+  duplicate_report bit1,
+  quasiduplicate_report bit1,
+  code_type_switch_over bit1,
+  instrument_change bit1,
+  ps_code_change bit1,
+  kalman_method_flag bit1,
+  oi_method_flag bit1,
+  auxiliary bit1,
+);
+
+CREATE TABLE desc AS (
+  // creation date, time and created by whom (username)
+  creadate YYYYMMDD,
+  creatime HHMMSS,
+  creaby   string,
+
+  // modification date, time and modified by whom (username)
+  moddate YYYYMMDD,
+  modtime HHMMSS,
+  modby   string,
+);
+
+CREATE TABLE hdr AS (
+  seqno pk1int,                                //  1 OBSERVATION SEQUENCE
+  obstype pk1int,                              //  2 OBSERVATION TYPE
+  code_type pk1int,                            //  3 OBSERVATION CODE TYPE
+  instrument_type pk1int,                      //  4 OBSERVATION INSTRUMENT TYPE
+  date YYYYMMDD,                               //  5 OBS. DATE
+  time HHMMSS,                                 //  6 OBS. EXACT TIME
+  source string,                               //  7 Source ID of obs. (CHARACTER*8): ERA
+  statid string,                               //  8 STATION ID (CHARACTER*8)
+  lat pk9real,                                 //  9 LATITUDE
+  lon pk9real,                                 // 10 LONGITUDE
+  stalt pk9real,                               // 11 ALTITUDE
+  modoro pk9real,                              // 12 MODEL'S OROGRAPHY
+  anemoht pk9real,                             // 13 HEIGHT OF ANEMOMETER
+  baroht pk9real,                              // 14 HEIGHT OF BAROMETRE
+  numlev pk1int,		   	                   // 15 No. of levels
+  subtype pk1int,                              // 16 BUFR subtype for reference
+  bufrtype pk1int,                             // 17 BUFR-type
+  station_type pk1int,                         // 18 SYNOP/SHIPs (needed to find out if DRIBU)
+//bias_correction_on pk1int,                   // 19 bias correction on (0/1=bias correction off/on)
+  reserved_0 pk9real,                          // 19 reserved 
+  bc_info BC_INFO_t,                           // 20 station info 
+//
+  variable_no pk1int,                          // 21 variable no
+  vertical_coordin_type pk1int,                // 22 vertical coordinate type 
+  order_no pk1int,                             // 23 order/entry no.
+  vertical_coordin pk9real,                    // 24 vertical coordinate
+  observed_value pk9real,                      // 25 observed value
+  biascorr_ind pk1int,                         // 26 current BIAS CORRECTION INDICATOR:
+//                                                   00=no bias/decision
+//                                                   11=long term bias
+//                                                   21=KALMAN current bias
+//                                                   22=KALMAN long term bias
+//                                                   31=OI current bias
+//                                                   32=OI long term bias
+  biascorr pk9real,                            // 27 BIAS CORRECTION
+//
+  pressure_code pk1int,                        // 28 PRESSURE CODE
+  departure pk9real,                           // 29 current OBSERVED MINUS FIRST GUESS VALUE
+  previous_departure pk9real,                  // 30 PREVIOUS OBSERVED MINUS FIRST GUESS VALUE
+//
+  kl_weight pk9real,                           // 31 KALMAN METHOD WEIGHT
+  kl_current_bias_estimate pk9real,            // 32 CURRERNT KALMAN METHOD BIAS ESTIMATE
+  kl_previous_bias_estimate pk9real,           // 33 PREVIOUS KALMAN METHOD BIAS ESTIMATE
+  kl_current_variance pk9real,                 // 34 CURRERNT KALMAN METHOD BIAS VARIANCE
+  kl_previous_variance pk9real,                // 35 PREVIOUS KALMAN METHOD BIAS VARIANCE
+  kl_current_obserr pk9real,                   // 36 CURRERNT KALMAN METHOD BIAS OBS ERROR
+  kl_previous_obserr pk9real,                  // 37 PREVIOUS KALMAN METHOD BIAS OBS ERROR
+  kl_c_parameter pk9real,                      // 38 KALMAN METHOD BIAS ESTIMATE C (confidence) 
+  kl_long_term_bias pk9real,                   // 39 Kalman method long term bias estimate
+  reserved_1 pk9real,                          // 40 reserved 
+//
+  oi_weight pk9real,                           // 41 OI METHOD WEIGHT
+  oi_current_bias_estimate pk9real,            // 42 CURRERNT OI METHOD BIAS ESTIMATE
+  oi_previous_bias_estimate pk9real,           // 43 PREVIOUS OI METHOD BIAS ESTIMATE
+  oi_current_variance pk9real,                 // 44 CURRERNT OI METHOD BIAS VARIANCE
+  oi_previous_variance pk9real,                // 45 PREVIOUS OI METHOD BIAS VARIANCE
+  oi_current_obserr pk9real,                   // 46 CURRERNT OI METHOD BIAS OBS ERROR
+  oi_previous_obserr pk9real,                  // 47 PREVIOUS OI METHOD BIAS OBS ERROR
+  oi_q_varance pk9real,                        // 48 OI METHOD QUALITY
+  oi_bias_err_estimate pk9real,                // 49 OI METHOD BIAS ERROR ESTIMATE
+  oi_long_term_bias pk9real,                   // 50 OI method long term bias estimate
+//
+  long_term_sample_size pk1int,                // 51 long term sample size
+  long_term_mean_departure pk9real,            // 52 long term mean
+  long_term_bias pk9real,                      // 53 long term bias
+  long_term_std  pk9real,                      // 54 long term std
+  long_term_rms  pk9real,                      // 55 long term rms
+//
+  biascorr_applied pk9real,                    // 56 BIAS CORRECTION
+//
+  report_status STATUS_t,                      // 57 REPORT'S STATUS
+  report_event_1 REPORT_EVENT1_t,              // 58 REPORT'S EVENTS (PART 1)
+  report_event_2 REPORT_EVENT2_t,              // 59 REPORT'S EVENTS (PART 2)
+  report_rdb_flag REPORT_RDBFLAG_T,            // 60 REPORT'S RDB FLAG
+  report_blacklist REPORT_BLACKLIST_T,         // 61 REPORT'S BLACKLIST EVENTS
+//
+  ps_status STATUS_t,                          // 62 Ps STATUS
+  ps_event_1 DATUM_EVENT1_t,                   // 63 Ps EVENTS (PART 1)
+  ps_event_2 DATUM_EVENT2_t,                   // 64 Ps EVENTS (PART 2)
+  ps_blacklist DATUM_BLACKLIST_T,              // 65 Ps BLACKLIST EVENTS
+  ps_flag DATUM_FLAG_T,                        // 66 Ps FLAG
+  ps_rdb_flag DATUM_RDBFLAG_T,                 // 67 Ps RDB FLAG
+//
+  body @LINK,                                  // 68-69 offset and length
+);
+
+CREATE TABLE body AS (
+  history_date YYYYMMDD,                       //  1 DATE
+  history_time HHMMSS,                         //  2 TIME
+  history_departure pk9real,                   //  3 departure
+//
+  history_kl_bias pk9real,                     //  4 kalman method bias estimate
+  history_kl_weight pk9real,                   //  5 KALMAN WEIGHT
+  history_kl_variance pk9real,                 //  6 KALMAN variance
+  history_kl_obserr  pk9real,                  //  7 KALMAN obs error
+  history_kl_c_parameter pk9real,              //  8 KALMAN C param
+//
+  history_oi_bias pk9real,                     //  9 oi method bias estimate
+  history_oi_weight pk9real,                   // 10 OI WEIGHT
+  history_oi_variance pk9real,                 // 11 OI variance
+  history_oi_obserr  pk9real,                  // 12 OI obs error
+  history_oi_q_varance pk9real,                // 13 OI METHOD QUALITY
+  history_oi_err_estimate  pk9real,            // 14 OI METHOD BIAS ERROR ESTIMATE
+//
+  history_bc_info BC_INFO_t,                   // 15 info
+//
+  history_report_status STATUS_t,              // 16 REPORT'S STATUS
+  history_report_event_1 REPORT_EVENT1_t,      // 17 REPORT'S EVENTS (PART 1)
+  history_report_event_2 REPORT_EVENT2_t,      // 18 REPORT'S EVENTS (PART 2)
+  history_report_rdb_flag REPORT_RDBFLAG_T,    // 19 REPORT'S RDB FLAG
+  history_report_blacklist REPORT_BLACKLIST_T, // 20 REPORT'S BLACKLIST EVENTS
+//
+  history_ps_status STATUS_t,                  // 21 Ps STATUS
+  history_ps_event_1 DATUM_EVENT1_t,           // 22 Ps EVENTS (PART 1)
+  history_ps_event_2 DATUM_EVENT2_t,           // 23 Ps EVENTS (PART 2)
+  history_ps_blacklist DATUM_BLACKLIST_T,      // 24 Ps BLACKLIST EVENTS
+  history_ps_flag DATUM_FLAG_T,                // 25 Ps FLAG
+  history_ps_rdb_flag DATUM_RDBFLAG_T,         // 26 Ps RDB FLAG
+//
+  history_biascorr_ind pk1int,                 // 27 BIAS CORRECTION INDICATOR
+  history_biascorr pk9real,                    // 28 NEW BIAS CORRECTION
+  history_biascorr_applied pk9real,            // 29 APPLIED BIAS CORRECTION
+);
diff --git a/odb/src/ddl.PSBIAS/PSBIAS.flags b/odb/src/ddl.PSBIAS/PSBIAS.flags
new file mode 100644
index 0000000..be4e93a
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/PSBIAS.flags
@@ -0,0 +1,29 @@
+-Abody=(update,errstat,rtovs_body,scatt_body,ssmi_body,update_1,update_2,update_3,update_4)
+-Artovs=(rtovs_slev,rtovs_pred)
+-Aatovs=atovs_pred
+-Assmi=ssmi_slev
+-Abody=(update,errstat,rtovs_body,scatt_body,ssmi_body,update_1,update_2,update_3,update_4)
+-Aupdate=(errstat,rtovs_body,scatt_body,ssmi_body,update_1,update_2,update_3,update_4)
+-Aerrstat=(rtovs_body,scatt_body,ssmi_body,update_1,update_2,update_3,update_4)
+-Artovs_body=(scatt_body,ssmi_body,update_1,update_2,update_3,update_4)
+-Ascatt_body=(ssmi_body,update_1,update_2,update_3,update_4)
+-Assmi_body=(update_1,update_2,update_3,update_4)
+-Aupdate_1=(update_2,update_3,update_4)
+-Aupdate_2=(update_3,update_4)
+-Aupdate_3=update_4
+-Artovs=(rtovs_slev,rtovs_pred)
+-Artovs_slev=rtovs_pred
+-Aatovs=atovs_pred
+-Assmi=ssmi_slev
+-1index=hdr
+-1hdr=sat
+-1sat=(reo3,atovs,rtovs,rtovs,ssmi,scatt,satob,satem)
+-1index=hdr
+-1hdr=sat
+-1sat=(reo3,atovs,rtovs,rtovs,ssmi,scatt,satob,satem)
+-1reo3=(atovs,rtovs,rtovs,ssmi,scatt,satob,satem)
+-1atovs=(rtovs,rtovs,ssmi,scatt,satob,satem)
+-1rtovs=(rtovs,ssmi,scatt,satob,satem,ssmi,scatt,satob,satem)
+-1ssmi=(scatt,satob,satem)
+-1scatt=(satob,satem)
+-1satob=satem
diff --git a/odb/src/ddl.PSBIAS/psbias_compress_method_0.sql b/odb/src/ddl.PSBIAS/psbias_compress_method_0.sql
new file mode 100644
index 0000000..6964f88
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbias_compress_method_0.sql
@@ -0,0 +1,21 @@
+// psbias_compress_method_0
+
+SET $basedate = -1;
+SET $basetime = -1;
+SET $no_of_days_ago = -1;
+
+SET $body_min = -1;
+SET $body_chunk = -1;
+
+CREATE VIEW psbias_compress_method_0 AS
+SELECT "*@body" FROM hdr,body
+ WHERE date is not null
+   AND time is not null
+   AND date < $basedate
+   AND ABS(tdiff(date,time,$basedate,$basetime)) > $no_of_days_ago * 24 * 3600
+   AND (
+    ($body_min == -1) OR 
+    ($body_chunk == -1) OR 
+    ($body_min <= #body < $body_min + $body_chunk)
+       )
+;
diff --git a/odb/src/ddl.PSBIAS/psbias_compress_method_1a.sql b/odb/src/ddl.PSBIAS/psbias_compress_method_1a.sql
new file mode 100644
index 0000000..3cfe1cb
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbias_compress_method_1a.sql
@@ -0,0 +1,18 @@
+// psbias_compress_method_1a
+
+SET $basedate = -1;
+SET $basetime = -1;
+SET $no_of_days_ago = -1;
+
+SET $all = 0;
+
+CREATE VIEW psbias_compress_method_1a AS
+SELECT body FROM hdr // gets body.offset & body.len, in this order
+ WHERE ($all == 1) OR (
+       date is not null
+   AND time is not null
+   AND date < $basedate
+   AND ABS(tdiff(date,time,$basedate,$basetime)) > $no_of_days_ago * 24 * 3600
+                      )
+ORDER BY 1 // Sort w.r.t. body.offset in ODB_get()
+;
diff --git a/odb/src/ddl.PSBIAS/psbias_compress_method_1b.sql b/odb/src/ddl.PSBIAS/psbias_compress_method_1b.sql
new file mode 100644
index 0000000..c14edc8
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbias_compress_method_1b.sql
@@ -0,0 +1,10 @@
+// psbias_compress_method_1b
+
+SET $body_min = -1;
+SET $body_chunk = -1;
+
+CREATE VIEW psbias_compress_method_1b AS
+// Apply this only AFTER links have been massaged
+SELECT "*@body" FROM hdr,body
+ WHERE ($body_min <= #body < $body_min + $body_chunk)
+;
diff --git a/odb/src/ddl.PSBIAS/psbiasbody.sql b/odb/src/ddl.PSBIAS/psbiasbody.sql
new file mode 100644
index 0000000..8bb7b9b
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbiasbody.sql
@@ -0,0 +1,30 @@
+UPDATED;
+CREATE VIEW psbiasbody AS
+SELECT seqno, 
+//       1
+       history_date, history_time, history_departure,
+//       2                 3                      4
+       history_kl_bias,
+//       5
+       history_kl_weight, history_kl_variance, history_kl_obserr, history_kl_c_parameter,
+//       6                 7                      8                   9
+       history_oi_bias,
+//      10
+       history_oi_weight, history_oi_variance, history_oi_obserr, history_oi_q_varance, history_oi_err_estimate,
+//      11                12                     13                  14                      15
+       history_bc_info,
+//      16
+       history_report_status, history_report_event_1, history_report_event_2, history_report_rdb_flag,
+//      17                      18                         19                      20
+       history_report_blacklist,
+//      21
+       history_ps_status, history_ps_event_1, history_ps_event_2, history_ps_blacklist,
+//      22                      23                         24                      25
+       history_ps_flag, history_ps_rdb_flag,
+//      26                      27
+       history_biascorr_ind, history_biascorr, history_biascorr_applied
+//      28                      29               30
+FROM  hdr, body
+//WHERE
+;
+
diff --git a/odb/src/ddl.PSBIAS/psbiasbody_maintenance.sql b/odb/src/ddl.PSBIAS/psbiasbody_maintenance.sql
new file mode 100644
index 0000000..d0c6af9
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbiasbody_maintenance.sql
@@ -0,0 +1,29 @@
+UPDATED;
+CREATE VIEW psbiasbody_maintenance AS
+SELECT seqno,
+//       1 
+       history_date, history_time, history_departure,
+//       2                 3                      4
+       history_kl_bias,
+//       5
+       history_kl_weight, history_kl_variance, history_kl_obserr, history_kl_c_parameter,
+//       6                 7                      9                   9
+       history_oi_bias,
+//      10
+       history_oi_weight, history_oi_variance, history_oi_obserr, history_oi_q_varance, history_oi_err_estimate,
+//      11                12                     13                  14                      15
+       history_bc_info,
+//      16
+       history_report_status, history_report_event_1, history_report_event_2, history_report_rdb_flag,
+//      17                      18                         19                      20
+       history_report_blacklist,
+//      21
+       history_ps_status, history_ps_event_1, history_ps_event_2, history_ps_blacklist,
+//      22                      23                         24                      25
+       history_ps_flag, history_ps_rdb_flag,
+//      26                      27
+       history_biascorr_ind, history_biascorr, history_biascorr_applied
+//      28                      29               30
+FROM  hdr, body
+WHERE statid/='        '
+;
diff --git a/odb/src/ddl.PSBIAS/psbiashdr.sql b/odb/src/ddl.PSBIAS/psbiashdr.sql
new file mode 100644
index 0000000..da7feef
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbiashdr.sql
@@ -0,0 +1,37 @@
+UPDATED;
+CREATE VIEW psbiashdr AS
+SELECT seqno,
+//       1
+  obstype, code_type, instrument_type, date, time, source, statid,
+//  2          3          4              5     6      7       8   
+  lat, lon, stalt, modoro, anemoht, baroht, numlev, subtype, bufrtype, station_type,
+//  9   10    11     12       13      14      15      16        17         18
+// bias_correction_on, bc_info,
+   reserved_0, bc_info,
+// 19                    20
+  variable_no, vertical_coordin_type, order_no, vertical_coordin, observed_value,
+//     21             22                 23            24               25   
+  biascorr_ind, biascorr, pressure_code, departure, previous_departure,
+//      26        27            28          29              30
+//
+  kl_weight, kl_current_bias_estimate, kl_previous_bias_estimate, kl_current_variance, kl_previous_variance,
+//      31               32                        33                     34                     35
+  kl_current_obserr, kl_previous_obserr, kl_c_parameter, kl_long_term_bias, reserved_1,
+//      36                    37                38          39                 40
+  oi_weight, oi_current_bias_estimate, oi_previous_bias_estimate, oi_current_variance, oi_previous_variance,
+//      41            42                       43                       44                    45
+  oi_current_obserr, oi_previous_obserr, oi_q_varance, oi_bias_err_estimate, oi_long_term_bias,
+//      46                  47                48                49              50
+  long_term_sample_size, long_term_mean_departure, long_term_bias, long_term_std, long_term_rms,
+//      51                        52                  53               54            55 
+  biascorr_applied,
+//      56
+  report_status, report_event_1, report_event_2, report_rdb_flag, report_blacklist,
+//      57            58             59                60               61
+  ps_status, ps_event_1, ps_event_2, ps_blacklist, ps_flag, ps_rdb_flag,
+//      62      63           64           65         66         67   
+  body.offset, body.len
+//   68          69
+FROM hdr
+//WHERE
+;
diff --git a/odb/src/ddl.PSBIAS/psbiashdr_maintenance.sql b/odb/src/ddl.PSBIAS/psbiashdr_maintenance.sql
new file mode 100644
index 0000000..83cd766
--- /dev/null
+++ b/odb/src/ddl.PSBIAS/psbiashdr_maintenance.sql
@@ -0,0 +1,37 @@
+UPDATED;
+CREATE VIEW psbiashdr_maintenance AS
+SELECT seqno,
+//       1
+  obstype, code_type, instrument_type, date, time, source, statid,
+//  2          3          4              5     6      7       8   
+  lat, lon, stalt, modoro, anemoht, baroht, numlev, subtype, bufrtype, station_type,
+//  9   10    11     12       13      14      15      16        17         18
+// bias_correction_on, bc_info,
+   reserved_0, bc_info,
+// 19                      20
+  variable_no, vertical_coordin_type, order_no, vertical_coordin, observed_value,
+//     21             22                 23            24               25   
+  biascorr_ind, biascorr, pressure_code, departure, previous_departure,
+//      26        27            28          29              30
+//
+  kl_weight, kl_current_bias_estimate, kl_previous_bias_estimate, kl_current_variance, kl_previous_variance,
+//      31               32                        33                     34                     35
+  kl_current_obserr, kl_previous_obserr, kl_c_parameter, kl_long_term_bias, reserved_1,
+//      36                    37                38          39                 40
+  oi_weight, oi_current_bias_estimate, oi_previous_bias_estimate, oi_current_variance, oi_previous_variance,
+//      41            42                       43                       44                    45
+  oi_current_obserr, oi_previous_obserr, oi_q_varance, oi_bias_err_estimate, oi_long_term_bias,
+//      46                  47                48                49              50
+  long_term_sample_size, long_term_mean_departure, long_term_bias, long_term_std, long_term_rms,
+//      51                        52                  53             54             55  
+  biascorr_applied,
+//      56
+  report_status, report_event_1, report_event_2, report_rdb_flag, report_blacklist,
+//      57            58             59                60               61
+  ps_status, ps_event_1, ps_event_2, ps_blacklist, ps_flag, ps_rdb_flag,
+//      62      63           64           65         66         67
+  body.offset, body.len
+//   68          69
+FROM hdr
+WHERE statid/='        '
+;
diff --git a/odb/src/ddl.RSTBIAS/CMakeLists.txt b/odb/src/ddl.RSTBIAS/CMakeLists.txt
new file mode 100644
index 0000000..1a746d4
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/CMakeLists.txt
@@ -0,0 +1,45 @@
+set(sources
+
+    RSTBIAS.ddl
+
+    aeolus.h
+    allsky.h
+    auxiliary.h
+    body.h
+    cloud_sink.h
+    cma.h
+    collocated_imager_information.h
+    conv.h
+    ensemble.h
+    errstat.h
+    forecast_diagnostic.h
+    gbrad.h
+    gnssro.h
+    hdr.h
+    idx.h
+    limb.h
+    mdi.h
+    modsurf.h
+    obstype.h
+    ppcode.h
+    radar.h
+    radar_station.h
+    radiance.h
+    raingg.h
+    resat.h
+    sat.h
+    satob.h
+    scatt.h
+    sensor.h
+    smos.h
+    ssmi1d.h
+    surfbody_feedback.h
+    type_definitions.h
+    update.h
+    varno.h
+    vertco_type.h
+)
+
+set(views rstbody.sql rsthdr.sql)
+
+odb_add_schema(TARGET RSTBIAS SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_RSTBIAS TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.RSTBIAS/RSTBIAS.ddl b/odb/src/ddl.RSTBIAS/RSTBIAS.ddl
new file mode 100644
index 0000000..15200ff
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/RSTBIAS.ddl
@@ -0,0 +1,40 @@
+//
+//  RSTBIAS hierarchy:
+//
+//      1  desc
+//      2  +---> hdr
+//      3  +---> body
+
+CREATE TABLE desc AS (
+  // creation date, time and created by whom (username)
+  creadate YYYYMMDD,
+  creatime HHMMSS,
+  creaby   string,
+
+  // modification date, time and modified by whom (username)
+  moddate YYYYMMDD,
+  modtime HHMMSS,
+  modby   string,
+);
+
+CREATE TABLE hdr AS (
+  seqno pk1int,                        //  1 SEQUENCE NO
+  statid string,                       //  2 STATION ID (CHARACTER*8)
+  lat pk9real,                         //  3 LATITUDE
+  lon pk9real,                         //  4 LONGITUDE
+  stalt pk9real,                       //  5 ALTITUDE
+  sonde_name string,                   //  6 SONDE NAME
+  sonde_code pk1int,                   //  7 SONDE CODE
+  date_from YYYYMMDD,                  //  8 VALID DATE FROM
+  time_from HHMMSS,                    //  9 VALID TIME FROM
+  date_to YYYYMMDD,                    // 10 VALID DATE TO
+  time_to HHMMSS,                      // 11 VALID TIME TO
+  body @LINK,
+);
+
+
+CREATE TABLE body AS (
+  press pk9real,                       //    1 VERTICAL COORDINATE (PRESSURE)
+  bccf[13] pk9real,                    // 2-14 BIAS CORRECTIONS COEFFICINTS
+);
+
diff --git a/odb/src/ddl.RSTBIAS/RSTBIAS.dep b/odb/src/ddl.RSTBIAS/RSTBIAS.dep
new file mode 100644
index 0000000..0de27ee
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/RSTBIAS.dep
@@ -0,0 +1,18 @@
+#-- First version:  02-Feb-2009
+
+DDLS=\
+	RSTBIAS.ddl \
+	mdi.inc \
+	obstype.inc \
+	varno.inc \
+	vertco_type.inc \
+	ppcode.inc
+
+TABLES=\
+	desc \
+	hdr \
+	body
+
+VIEWS=\
+	rstbody \
+	rsthdr
diff --git a/odb/src/ddl.RSTBIAS/aeolus.h b/odb/src/ddl.RSTBIAS/aeolus.h
new file mode 120000
index 0000000..d9f814d
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/aeolus.h
@@ -0,0 +1 @@
+../ddl/aeolus.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/alloc.h b/odb/src/ddl.RSTBIAS/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/allsky.h b/odb/src/ddl.RSTBIAS/allsky.h
new file mode 120000
index 0000000..0a19265
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/allsky.h
@@ -0,0 +1 @@
+../ddl/allsky.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/auxiliary.h b/odb/src/ddl.RSTBIAS/auxiliary.h
new file mode 120000
index 0000000..8ae1b08
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/auxiliary.h
@@ -0,0 +1 @@
+../ddl/auxiliary.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/bits.h b/odb/src/ddl.RSTBIAS/bits.h
new file mode 120000
index 0000000..459b52a
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/bits.h
@@ -0,0 +1 @@
+../ddl/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/body.h b/odb/src/ddl.RSTBIAS/body.h
new file mode 120000
index 0000000..ccd0f32
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/body.h
@@ -0,0 +1 @@
+../ddl/body.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/cdrhook.h b/odb/src/ddl.RSTBIAS/cdrhook.h
new file mode 120000
index 0000000..8784f89
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/cdrhook.h
@@ -0,0 +1 @@
+../ddl/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/cloud_sink.h b/odb/src/ddl.RSTBIAS/cloud_sink.h
new file mode 120000
index 0000000..3cdc586
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/cloud_sink.h
@@ -0,0 +1 @@
+../ddl/cloud_sink.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/cma.h b/odb/src/ddl.RSTBIAS/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/collocated_imager_information.h b/odb/src/ddl.RSTBIAS/collocated_imager_information.h
new file mode 120000
index 0000000..3b061d6
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/collocated_imager_information.h
@@ -0,0 +1 @@
+../ddl/collocated_imager_information.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/conv.h b/odb/src/ddl.RSTBIAS/conv.h
new file mode 120000
index 0000000..9280d6d
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/conv.h
@@ -0,0 +1 @@
+../ddl/conv.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/dca.h b/odb/src/ddl.RSTBIAS/dca.h
new file mode 120000
index 0000000..005f5d7
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/dca.h
@@ -0,0 +1 @@
+../ddl/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/ecstdlib.h b/odb/src/ddl.RSTBIAS/ecstdlib.h
new file mode 120000
index 0000000..32bb85b
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/ecstdlib.h
@@ -0,0 +1 @@
+../ddl/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/ensemble.h b/odb/src/ddl.RSTBIAS/ensemble.h
new file mode 120000
index 0000000..8963a78
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/ensemble.h
@@ -0,0 +1 @@
+../ddl/ensemble.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/errstat.h b/odb/src/ddl.RSTBIAS/errstat.h
new file mode 120000
index 0000000..217465a
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/errstat.h
@@ -0,0 +1 @@
+../ddl/errstat.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/forecast_diagnostic.h b/odb/src/ddl.RSTBIAS/forecast_diagnostic.h
new file mode 120000
index 0000000..8d17f2d
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/forecast_diagnostic.h
@@ -0,0 +1 @@
+../ddl/forecast_diagnostic.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/funcs.h b/odb/src/ddl.RSTBIAS/funcs.h
new file mode 120000
index 0000000..e16dc7c
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/funcs.h
@@ -0,0 +1 @@
+../ddl/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/gbrad.h b/odb/src/ddl.RSTBIAS/gbrad.h
new file mode 120000
index 0000000..a94ed8e
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/gbrad.h
@@ -0,0 +1 @@
+../ddl/gbrad.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/gnssro.h b/odb/src/ddl.RSTBIAS/gnssro.h
new file mode 120000
index 0000000..aa94338
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/gnssro.h
@@ -0,0 +1 @@
+../ddl/gnssro.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/hdr.h b/odb/src/ddl.RSTBIAS/hdr.h
new file mode 120000
index 0000000..9d10f20
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/hdr.h
@@ -0,0 +1 @@
+../ddl/hdr.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/idx.h b/odb/src/ddl.RSTBIAS/idx.h
new file mode 120000
index 0000000..cfdb097
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/idx.h
@@ -0,0 +1 @@
+../ddl/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/info.h b/odb/src/ddl.RSTBIAS/info.h
new file mode 120000
index 0000000..b63984c
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/info.h
@@ -0,0 +1 @@
+../ddl/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/limb.h b/odb/src/ddl.RSTBIAS/limb.h
new file mode 120000
index 0000000..ab7f4f9
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/limb.h
@@ -0,0 +1 @@
+../ddl/limb.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/magicwords.h b/odb/src/ddl.RSTBIAS/magicwords.h
new file mode 120000
index 0000000..8135e72
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/magicwords.h
@@ -0,0 +1 @@
+../ddl/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/mdi.h b/odb/src/ddl.RSTBIAS/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/modsurf.h b/odb/src/ddl.RSTBIAS/modsurf.h
new file mode 120000
index 0000000..7223f38
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/modsurf.h
@@ -0,0 +1 @@
+../ddl/modsurf.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/namecfg.h b/odb/src/ddl.RSTBIAS/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/obstype.h b/odb/src/ddl.RSTBIAS/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/odb.h b/odb/src/ddl.RSTBIAS/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/odb_macros.h b/odb/src/ddl.RSTBIAS/odb_macros.h
new file mode 120000
index 0000000..01fe8a8
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/odb_macros.h
@@ -0,0 +1 @@
+../ddl/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/odbcrc.h b/odb/src/ddl.RSTBIAS/odbcrc.h
new file mode 120000
index 0000000..fcd0f0c
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/odbcrc.h
@@ -0,0 +1 @@
+../ddl/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/odbmd5.h b/odb/src/ddl.RSTBIAS/odbmd5.h
new file mode 120000
index 0000000..b81990c
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/odbmd5.h
@@ -0,0 +1 @@
+../ddl/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/pcma_extern.h b/odb/src/ddl.RSTBIAS/pcma_extern.h
new file mode 120000
index 0000000..dba5539
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/pcma_extern.h
@@ -0,0 +1 @@
+../ddl/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/ppcode.h b/odb/src/ddl.RSTBIAS/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/privpub.h b/odb/src/ddl.RSTBIAS/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/radar.h b/odb/src/ddl.RSTBIAS/radar.h
new file mode 120000
index 0000000..79dddc7
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/radar.h
@@ -0,0 +1 @@
+../ddl/radar.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/radar_station.h b/odb/src/ddl.RSTBIAS/radar_station.h
new file mode 120000
index 0000000..85482f7
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/radar_station.h
@@ -0,0 +1 @@
+../ddl/radar_station.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/radiance.h b/odb/src/ddl.RSTBIAS/radiance.h
new file mode 120000
index 0000000..62c3289
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/radiance.h
@@ -0,0 +1 @@
+../ddl/radiance.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/raingg.h b/odb/src/ddl.RSTBIAS/raingg.h
new file mode 120000
index 0000000..3f077a8
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/raingg.h
@@ -0,0 +1 @@
+../ddl/raingg.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/resat.h b/odb/src/ddl.RSTBIAS/resat.h
new file mode 120000
index 0000000..23bd5e9
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/resat.h
@@ -0,0 +1 @@
+../ddl/resat.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/rstbody.sql b/odb/src/ddl.RSTBIAS/rstbody.sql
new file mode 120000
index 0000000..3ecb6cc
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/rstbody.sql
@@ -0,0 +1 @@
+../ddl/rstbody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/rsthdr.sql b/odb/src/ddl.RSTBIAS/rsthdr.sql
new file mode 120000
index 0000000..e296aa6
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/rsthdr.sql
@@ -0,0 +1 @@
+../ddl/rsthdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/sat.h b/odb/src/ddl.RSTBIAS/sat.h
new file mode 120000
index 0000000..ffd2d1e
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/sat.h
@@ -0,0 +1 @@
+../ddl/sat.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/satob.h b/odb/src/ddl.RSTBIAS/satob.h
new file mode 120000
index 0000000..3230a42
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/satob.h
@@ -0,0 +1 @@
+../ddl/satob.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/scatt.h b/odb/src/ddl.RSTBIAS/scatt.h
new file mode 120000
index 0000000..0a2840c
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/scatt.h
@@ -0,0 +1 @@
+../ddl/scatt.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/sensor.h b/odb/src/ddl.RSTBIAS/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/smos.h b/odb/src/ddl.RSTBIAS/smos.h
new file mode 120000
index 0000000..78794a4
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/smos.h
@@ -0,0 +1 @@
+../ddl/smos.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/ssmi1d.h b/odb/src/ddl.RSTBIAS/ssmi1d.h
new file mode 120000
index 0000000..716724f
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/ssmi1d.h
@@ -0,0 +1 @@
+../ddl/ssmi1d.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/surfbody_feedback.h b/odb/src/ddl.RSTBIAS/surfbody_feedback.h
new file mode 120000
index 0000000..bfe4184
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/surfbody_feedback.h
@@ -0,0 +1 @@
+../ddl/surfbody_feedback.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/swapbytes.h b/odb/src/ddl.RSTBIAS/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/type_definitions.h b/odb/src/ddl.RSTBIAS/type_definitions.h
new file mode 120000
index 0000000..3711447
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/type_definitions.h
@@ -0,0 +1 @@
+../ddl/type_definitions.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/update.h b/odb/src/ddl.RSTBIAS/update.h
new file mode 120000
index 0000000..8068022
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/update.h
@@ -0,0 +1 @@
+../ddl/update.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/varno.h b/odb/src/ddl.RSTBIAS/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.RSTBIAS/vertco_type.h b/odb/src/ddl.RSTBIAS/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.RSTBIAS/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/CMakeLists.txt b/odb/src/ddl.SONDETYPERSTRHBIAS/CMakeLists.txt
new file mode 100644
index 0000000..ed77fde
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/CMakeLists.txt
@@ -0,0 +1,45 @@
+set(sources
+
+    SONDETYPERSTRHBIAS.ddl
+
+    aeolus.h
+    allsky.h
+    auxiliary.h
+    body.h
+    cloud_sink.h
+    cma.h
+    collocated_imager_information.h
+    conv.h
+    ensemble.h
+    errstat.h
+    forecast_diagnostic.h
+    gbrad.h
+    gnssro.h
+    hdr.h
+    idx.h
+    limb.h
+    mdi.h
+    modsurf.h
+    obstype.h
+    ppcode.h
+    radar.h
+    radar_station.h
+    radiance.h
+    raingg.h
+    resat.h
+    sat.h
+    satob.h
+    scatt.h
+    sensor.h
+    smos.h
+    ssmi1d.h
+    surfbody_feedback.h
+    type_definitions.h
+    update.h
+    varno.h
+    vertco_type.h
+)
+
+set(views sondetyperstrhbody.sql sondetyperstrhhdr.sql)
+
+odb_add_schema(TARGET SONDETYPERSTRHBIAS SOURCES ${sources} VIEWS ${views} CONDITION ODB_HAVE_SONDETYPERSTRHBIAS TYPE ${ODB_LIBS_TYPE})
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.ddl b/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.ddl
new file mode 100644
index 0000000..508e88d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.ddl
@@ -0,0 +1,102 @@
+//
+//  SONDETYPERSTRHBIAS hierarchy:
+//
+//      1  desc
+//      2  +---> hdr
+//      2  +--------> body
+//
+
+CREATE TABLE desc AS (
+// creation date, time and created by whom (username)
+creadate YYYYMMDD,
+creatime HHMMSS,
+creaby   string,
+
+// modification date, time and modified by whom (username)
+moddate YYYYMMDD,
+modtime HHMMSS,
+modby   string,
+);
+
+CREATE TABLE hdr AS (
+  seqno pk1int,                      //     1 SEQUENCE NO
+  sonde_type_code pk1int,            //     2 SONDE TYPE CODE
+  sonde_name[8] string,              //  3-10 SONDE TYPE NAME
+  body @LINK,                        // 11-12 Offset, len
+);
+
+CREATE TABLE body AS (
+  press pk9real,                     //  1 VERTICAL COORDINATE (PRESSURE)
+
+  T_N_m75 pk1int,                    //  2 No. of T data FOR ANGLEs up TO -7.5
+  T_N_m75_75 pk1int,                 //  3 No. of T data FOR ANGLEs -7.5 to 7.5
+  T_N_75_225 pk1int,                 //  4 No. of T data FOR ANGLEs 7.5 to 22.5
+  T_N_225 pk1int,                    //  5 No. of T data FOR ANGLEs above 22.5
+  T_N_mean pk1int,                   //  6 No. of T data FOR MEAN
+
+  T_D_m75 pk9real,                   //  7 T Uncorrected Departures FOR ANGLEs up TO -7.5
+  T_D_m75_75 pk9real,                //  8 T Uncorrected Departures FOR ANGLEs -7.5 to 7.5
+  T_D_75_225 pk9real,                //  9 T Uncorrected Departures FOR ANGLEs 7.5 to 22.5
+  T_D_225 pk9real,                   // 10 T Uncorrected Departures FOR ANGLEs above 22.5
+  T_D_mean pk9real,                  // 11 T Uncorrected Departures FOR MEAN
+
+  T_C_m75 pk9real,                   // 12 T Corrected Departures FOR ANGLEs up TO -7.5
+  T_C_m75_75 pk9real,                // 13 T Corrected Departures FOR ANGLEs -7.5 to 7.5
+  T_C_75_225 pk9real,                // 14 T Corrected Departures FOR ANGLEs 7.5 to 22.5
+  T_C_225 pk9real,                   // 15 T Corrected Departures FOR ANGLEs above 22.5
+  T_C_mean pk9real,                  // 16 T Corrected Departures FOR MEAN
+
+  T_B_m75_vs_all_mean pk9real,       // 17 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs ALL MEAN
+  T_B_m75_75_vs_all_mean pk9real,    // 18 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  T_B_75_225_vs_all_mean pk9real,    // 19 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  T_B_225_vs_all_mean pk9real,       // 20 T SOLAR BIAS FOR ANGLEs above 22.5 vs ALL MEAN
+  T_B_all_mean pk9real,              // 21 T MEAN BIAS ALL MEAN
+
+  T_B_m75_vs_night_mean pk9real,     // 22 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs NIGHT MEAN
+  T_B_m75_75_vs_night_mean pk9real,  // 23 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs NIGHT MEAN
+  T_B_75_225_vs_night_mean pk9real,  // 24 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs NIGHT MEAN
+  T_B_225_vs_night_mean pk9real,     // 25 T SOLAR BIAS FOR ANGLEs above 22.5 vs NIGHT MEAN
+  T_B_night_mean pk9real,            // 26 T MEAN BIAS NIGHT MEAN
+
+  T_B_m75_vs_day_mean pk9real,       // 27 T SOLAR BIAS FOR ANGLEs up TO -7.5 vs DAY MEAN
+  T_B_m75_75_vs_day_mean pk9real,    // 28 T SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs DAY MEAN
+  T_B_75_225_vs_day_mean pk9real,    // 29 T SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs DAY MEAN
+  T_B_225_vs_day_mean pk9real,       // 30 T SOLAR BIAS FOR ANGLEs above 22.5 vs DAY MEAN
+  T_B_day_mean pk9real,              // 31 T MEAN BIAS DAY MEAN
+
+  RH_N_m75 pk1int,                   // 32 No. of RH data FOR ANGLEs up TO -7.5
+  RH_N_m75_75 pk1int,                // 33 No. of RH data FOR ANGLEs -7.5 to 7.5
+  RH_N_75_225 pk1int,                // 34 No. of RH data FOR ANGLEs 7.5 to 22.5
+  RH_N_225 pk1int,                   // 35 No. of RH data FOR ANGLEs above 22.5
+  RH_N_mean pk1int,                  // 36 No. of RH data FOR MEAN
+
+  RH_D_m75 pk9real,                  // 37 RH Uncorrected Departures FOR ANGLEs up TO -7.5
+  RH_D_m75_75 pk9real,               // 38 RH Uncorrected Departures FOR ANGLEs -7.5 to 7.5
+  RH_D_75_225 pk9real,               // 39 RH Uncorrected Departures FOR ANGLEs 7.5 to 22.5
+  RH_D_225 pk9real,                  // 40 RH Uncorrected Departures FOR ANGLEs above 22.5
+  RH_D_mean pk9real,                 // 41 RH Uncorrected Departures FOR MEAN
+
+  RH_C_m75 pk9real,                  // 42 RH Corrected Departures FOR ANGLEs up TO -7.5 vs ALL MEAN
+  RH_C_m75_75 pk9real,               // 43 RH Corrected Departures FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  RH_C_75_225 pk9real,               // 44 RH Corrected Departures FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  RH_C_225 pk9real,                  // 45 RH Corrected Departures FOR ANGLEs above 22.5 vs ALL MEAN
+  RH_C_mean pk9real,                 // 46 RH Corrected Departures FOR MEAN
+
+  RH_B_m75_vs_all_mean pk9real,      // 47 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs ALL MEAN
+  RH_B_m75_75_vs_all_mean pk9real,   // 48 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs ALL MEAN
+  RH_B_75_225_vs_all_mean pk9real,   // 49 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs ALL MEAN
+  RH_B_225_vs_all_mean pk9real,      // 50 RH SOLAR BIAS FOR ANGLEs above 22.5 vs ALL MEAN
+  RH_B_all_mean pk9real,             // 51 RH MEAN BIAS  FOR ALL MEAN
+
+  RH_B_m75_vs_night_mean pk9real,    // 52 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs NIGHT MEAN
+  RH_B_m75_75_vs_night_mean pk9real, // 53 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs NIGHT MEAN
+  RH_B_75_225_vs_night_mean pk9real, // 54 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs NIGHT MEAN
+  RH_B_225_vs_night_mean pk9real,    // 55 RH SOLAR BIAS FOR ANGLEs above 22.5 vs NIGHT MEAN
+  RH_B_night_mean pk9real,           // 56 RH MEAN BIAS FOR NIGHT MEAN
+
+  RH_B_m75_vs_day_mean pk9real,      // 57 RH SOLAR BIAS FOR ANGLEs up TO -7.5 vs DAY MEAN
+  RH_B_m75_75_vs_day_mean pk9real,   // 58 RH SOLAR BIAS FOR ANGLEs -7.5 to 7.5 vs DAY MEAN
+  RH_B_75_225_vs_day_mean pk9real,   // 59 RH SOLAR BIAS FOR ANGLEs 7.5 to 22.5 vs DAY MEAN
+  RH_B_225_vs_day_mean pk9real,      // 60 RH SOLAR BIAS FOR ANGLEs above 22.5 vs DAY MEAN
+  RH_B_day_mean pk9real,             // 61 RH MEAN BIAS FOR DAY MEAN
+);
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.dep b/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.dep
new file mode 100644
index 0000000..867418d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/SONDETYPERSTRHBIAS.dep
@@ -0,0 +1,18 @@
+#-- First version:  02-Feb-2009
+
+DDLS=\
+	SONDETYPERSTRHBIAS.ddl \
+	mdi.inc \
+	obstype.inc \
+	varno.inc \
+	vertco_type.inc \
+	ppcode.inc
+
+TABLES=\
+	desc \
+	hdr \
+	body
+
+VIEWS=\
+	sondetyperstrhbody \
+	sondetyperstrhhdr
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/aeolus.h b/odb/src/ddl.SONDETYPERSTRHBIAS/aeolus.h
new file mode 120000
index 0000000..d9f814d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/aeolus.h
@@ -0,0 +1 @@
+../ddl/aeolus.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/alloc.h b/odb/src/ddl.SONDETYPERSTRHBIAS/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/allsky.h b/odb/src/ddl.SONDETYPERSTRHBIAS/allsky.h
new file mode 120000
index 0000000..0a19265
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/allsky.h
@@ -0,0 +1 @@
+../ddl/allsky.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/auxiliary.h b/odb/src/ddl.SONDETYPERSTRHBIAS/auxiliary.h
new file mode 120000
index 0000000..8ae1b08
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/auxiliary.h
@@ -0,0 +1 @@
+../ddl/auxiliary.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/bits.h b/odb/src/ddl.SONDETYPERSTRHBIAS/bits.h
new file mode 120000
index 0000000..c4ce6ab
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/bits.h
@@ -0,0 +1 @@
+../include/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/body.h b/odb/src/ddl.SONDETYPERSTRHBIAS/body.h
new file mode 120000
index 0000000..ccd0f32
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/body.h
@@ -0,0 +1 @@
+../ddl/body.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/cdrhook.h b/odb/src/ddl.SONDETYPERSTRHBIAS/cdrhook.h
new file mode 120000
index 0000000..4656498
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/cdrhook.h
@@ -0,0 +1 @@
+../include/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/cloud_sink.h b/odb/src/ddl.SONDETYPERSTRHBIAS/cloud_sink.h
new file mode 120000
index 0000000..3cdc586
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/cloud_sink.h
@@ -0,0 +1 @@
+../ddl/cloud_sink.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/cma.h b/odb/src/ddl.SONDETYPERSTRHBIAS/cma.h
new file mode 120000
index 0000000..4f6ca76
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/cma.h
@@ -0,0 +1 @@
+../ddl/cma.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/collocated_imager_information.h b/odb/src/ddl.SONDETYPERSTRHBIAS/collocated_imager_information.h
new file mode 120000
index 0000000..3b061d6
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/collocated_imager_information.h
@@ -0,0 +1 @@
+../ddl/collocated_imager_information.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/conv.h b/odb/src/ddl.SONDETYPERSTRHBIAS/conv.h
new file mode 120000
index 0000000..9280d6d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/conv.h
@@ -0,0 +1 @@
+../ddl/conv.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/dca.h b/odb/src/ddl.SONDETYPERSTRHBIAS/dca.h
new file mode 120000
index 0000000..c1c5561
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/dca.h
@@ -0,0 +1 @@
+../include/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/ecstdlib.h b/odb/src/ddl.SONDETYPERSTRHBIAS/ecstdlib.h
new file mode 120000
index 0000000..dff2199
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/ecstdlib.h
@@ -0,0 +1 @@
+../include/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/ensemble.h b/odb/src/ddl.SONDETYPERSTRHBIAS/ensemble.h
new file mode 120000
index 0000000..8963a78
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/ensemble.h
@@ -0,0 +1 @@
+../ddl/ensemble.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/errstat.h b/odb/src/ddl.SONDETYPERSTRHBIAS/errstat.h
new file mode 120000
index 0000000..217465a
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/errstat.h
@@ -0,0 +1 @@
+../ddl/errstat.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/forecast_diagnostic.h b/odb/src/ddl.SONDETYPERSTRHBIAS/forecast_diagnostic.h
new file mode 120000
index 0000000..8d17f2d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/forecast_diagnostic.h
@@ -0,0 +1 @@
+../ddl/forecast_diagnostic.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/funcs.h b/odb/src/ddl.SONDETYPERSTRHBIAS/funcs.h
new file mode 120000
index 0000000..e02a4cd
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/funcs.h
@@ -0,0 +1 @@
+../include/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/gbrad.h b/odb/src/ddl.SONDETYPERSTRHBIAS/gbrad.h
new file mode 120000
index 0000000..a94ed8e
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/gbrad.h
@@ -0,0 +1 @@
+../ddl/gbrad.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/gnssro.h b/odb/src/ddl.SONDETYPERSTRHBIAS/gnssro.h
new file mode 120000
index 0000000..aa94338
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/gnssro.h
@@ -0,0 +1 @@
+../ddl/gnssro.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/hdr.h b/odb/src/ddl.SONDETYPERSTRHBIAS/hdr.h
new file mode 120000
index 0000000..9d10f20
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/hdr.h
@@ -0,0 +1 @@
+../ddl/hdr.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/idx.h b/odb/src/ddl.SONDETYPERSTRHBIAS/idx.h
new file mode 120000
index 0000000..c25b0cc
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/idx.h
@@ -0,0 +1 @@
+../include/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/info.h b/odb/src/ddl.SONDETYPERSTRHBIAS/info.h
new file mode 120000
index 0000000..47734e7
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/info.h
@@ -0,0 +1 @@
+../include/info.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/limb.h b/odb/src/ddl.SONDETYPERSTRHBIAS/limb.h
new file mode 120000
index 0000000..ab7f4f9
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/limb.h
@@ -0,0 +1 @@
+../ddl/limb.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/magicwords.h b/odb/src/ddl.SONDETYPERSTRHBIAS/magicwords.h
new file mode 120000
index 0000000..48f2e3b
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/magicwords.h
@@ -0,0 +1 @@
+../include/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/mdi.h b/odb/src/ddl.SONDETYPERSTRHBIAS/mdi.h
new file mode 120000
index 0000000..87c8121
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/mdi.h
@@ -0,0 +1 @@
+../ddl/mdi.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/modsurf.h b/odb/src/ddl.SONDETYPERSTRHBIAS/modsurf.h
new file mode 120000
index 0000000..7223f38
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/modsurf.h
@@ -0,0 +1 @@
+../ddl/modsurf.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/namecfg.h b/odb/src/ddl.SONDETYPERSTRHBIAS/namecfg.h
new file mode 120000
index 0000000..a572a8d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/namecfg.h
@@ -0,0 +1 @@
+../ddl/namecfg.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/obstype.h b/odb/src/ddl.SONDETYPERSTRHBIAS/obstype.h
new file mode 120000
index 0000000..cdee312
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/obstype.h
@@ -0,0 +1 @@
+../ddl/obstype.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/odb.h b/odb/src/ddl.SONDETYPERSTRHBIAS/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/odb_macros.h b/odb/src/ddl.SONDETYPERSTRHBIAS/odb_macros.h
new file mode 120000
index 0000000..2082332
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/odb_macros.h
@@ -0,0 +1 @@
+../include/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/odbcrc.h b/odb/src/ddl.SONDETYPERSTRHBIAS/odbcrc.h
new file mode 120000
index 0000000..0313e9d
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/odbcrc.h
@@ -0,0 +1 @@
+../include/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/odbmd5.h b/odb/src/ddl.SONDETYPERSTRHBIAS/odbmd5.h
new file mode 120000
index 0000000..7331ca5
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/odbmd5.h
@@ -0,0 +1 @@
+../include/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/pcma_extern.h b/odb/src/ddl.SONDETYPERSTRHBIAS/pcma_extern.h
new file mode 120000
index 0000000..ef41751
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/pcma_extern.h
@@ -0,0 +1 @@
+../include/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/ppcode.h b/odb/src/ddl.SONDETYPERSTRHBIAS/ppcode.h
new file mode 120000
index 0000000..34c1cd2
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/ppcode.h
@@ -0,0 +1 @@
+../ddl/ppcode.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/privpub.h b/odb/src/ddl.SONDETYPERSTRHBIAS/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/radar.h b/odb/src/ddl.SONDETYPERSTRHBIAS/radar.h
new file mode 120000
index 0000000..79dddc7
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/radar.h
@@ -0,0 +1 @@
+../ddl/radar.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/radar_station.h b/odb/src/ddl.SONDETYPERSTRHBIAS/radar_station.h
new file mode 120000
index 0000000..85482f7
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/radar_station.h
@@ -0,0 +1 @@
+../ddl/radar_station.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/radiance.h b/odb/src/ddl.SONDETYPERSTRHBIAS/radiance.h
new file mode 120000
index 0000000..62c3289
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/radiance.h
@@ -0,0 +1 @@
+../ddl/radiance.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/raingg.h b/odb/src/ddl.SONDETYPERSTRHBIAS/raingg.h
new file mode 120000
index 0000000..3f077a8
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/raingg.h
@@ -0,0 +1 @@
+../ddl/raingg.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/resat.h b/odb/src/ddl.SONDETYPERSTRHBIAS/resat.h
new file mode 120000
index 0000000..23bd5e9
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/resat.h
@@ -0,0 +1 @@
+../ddl/resat.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/sat.h b/odb/src/ddl.SONDETYPERSTRHBIAS/sat.h
new file mode 120000
index 0000000..ffd2d1e
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/sat.h
@@ -0,0 +1 @@
+../ddl/sat.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/satob.h b/odb/src/ddl.SONDETYPERSTRHBIAS/satob.h
new file mode 120000
index 0000000..3230a42
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/satob.h
@@ -0,0 +1 @@
+../ddl/satob.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/scatt.h b/odb/src/ddl.SONDETYPERSTRHBIAS/scatt.h
new file mode 120000
index 0000000..0a2840c
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/scatt.h
@@ -0,0 +1 @@
+../ddl/scatt.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/sensor.h b/odb/src/ddl.SONDETYPERSTRHBIAS/sensor.h
new file mode 120000
index 0000000..ba75b15
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/sensor.h
@@ -0,0 +1 @@
+../ddl/sensor.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/smos.h b/odb/src/ddl.SONDETYPERSTRHBIAS/smos.h
new file mode 120000
index 0000000..78794a4
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/smos.h
@@ -0,0 +1 @@
+../ddl/smos.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhbody.sql b/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhbody.sql
new file mode 120000
index 0000000..6ccc2f2
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhbody.sql
@@ -0,0 +1 @@
+../ddl/sondetyperstrhbody.sql
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhhdr.sql b/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhhdr.sql
new file mode 120000
index 0000000..080f612
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/sondetyperstrhhdr.sql
@@ -0,0 +1 @@
+../ddl/sondetyperstrhhdr.sql
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/ssmi1d.h b/odb/src/ddl.SONDETYPERSTRHBIAS/ssmi1d.h
new file mode 120000
index 0000000..716724f
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/ssmi1d.h
@@ -0,0 +1 @@
+../ddl/ssmi1d.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/surfbody_feedback.h b/odb/src/ddl.SONDETYPERSTRHBIAS/surfbody_feedback.h
new file mode 120000
index 0000000..bfe4184
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/surfbody_feedback.h
@@ -0,0 +1 @@
+../ddl/surfbody_feedback.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/swapbytes.h b/odb/src/ddl.SONDETYPERSTRHBIAS/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/type_definitions.h b/odb/src/ddl.SONDETYPERSTRHBIAS/type_definitions.h
new file mode 120000
index 0000000..3711447
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/type_definitions.h
@@ -0,0 +1 @@
+../ddl/type_definitions.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/update.h b/odb/src/ddl.SONDETYPERSTRHBIAS/update.h
new file mode 120000
index 0000000..8068022
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/update.h
@@ -0,0 +1 @@
+../ddl/update.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/varno.h b/odb/src/ddl.SONDETYPERSTRHBIAS/varno.h
new file mode 120000
index 0000000..662286e
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/varno.h
@@ -0,0 +1 @@
+../ddl/varno.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPERSTRHBIAS/vertco_type.h b/odb/src/ddl.SONDETYPERSTRHBIAS/vertco_type.h
new file mode 120000
index 0000000..e7cf89b
--- /dev/null
+++ b/odb/src/ddl.SONDETYPERSTRHBIAS/vertco_type.h
@@ -0,0 +1 @@
+../ddl/vertco_type.h
\ No newline at end of file
diff --git a/odb/src/ddl.SONDETYPES/CMakeLists.txt b/odb/src/ddl.SONDETYPES/CMakeLists.txt
new file mode 100644
index 0000000..17e80d5
--- /dev/null
+++ b/odb/src/ddl.SONDETYPES/CMakeLists.txt
@@ -0,0 +1,5 @@
+odb_add_schema(TARGET SONDETYPES
+    TYPE ${ODB_LIBS_TYPE}
+    SOURCES SONDETYPES.ddl
+    VIEWS sondehdr.sql
+    CONDITION ODB_HAVE_SONDETYPES)
diff --git a/odb/src/ddl.SONDETYPES/SONDETYPES.ddl b/odb/src/ddl.SONDETYPES/SONDETYPES.ddl
new file mode 100644
index 0000000..54d9b10
--- /dev/null
+++ b/odb/src/ddl.SONDETYPES/SONDETYPES.ddl
@@ -0,0 +1,26 @@
+//
+//  SONDETYPES hierarchy:
+//
+//      1  desc
+//      2  +---> hdr
+//RESET ALIGN;
+//ALIGN(body[1:12]);
+
+CREATE TABLE desc AS (
+// creation date, time and created by whom (username)
+creadate YYYYMMDD,
+creatime HHMMSS,
+creaby   string,
+
+// modification date, time and modified by whom (username)
+moddate YYYYMMDD,
+modtime HHMMSS,
+modby   string,
+);
+
+CREATE TABLE hdr AS (
+
+  seqno pk1int,                             //  1 SEQUENCE NO
+  sonde_code pk1int,                        //  2 SONDE CODE
+  sonde_name[8] string,                     //  3 SONDE NAME
+);
diff --git a/odb/src/ddl.SONDETYPES/sondehdr.sql b/odb/src/ddl.SONDETYPES/sondehdr.sql
new file mode 100644
index 0000000..92ada61
--- /dev/null
+++ b/odb/src/ddl.SONDETYPES/sondehdr.sql
@@ -0,0 +1,14 @@
+READONLY;
+CREATE VIEW sondehdr AS
+SELECT seqno,                         //  1
+       sonde_code,                    //  2
+       sonde_name_1,                  //  3
+       sonde_name_2,                  //  3
+       sonde_name_3,                  //  3
+       sonde_name_4,                  //  3
+       sonde_name_5,                  //  3
+       sonde_name_6,                  //  3
+       sonde_name_7,                  //  3
+       sonde_name_8                   //  3
+FROM hdr
+;
diff --git a/odb/src/ddl/BUFRBASE.ddl b/odb/src/ddl/BUFRBASE.ddl
new file mode 100644
index 0000000..367bf37
--- /dev/null
+++ b/odb/src/ddl/BUFRBASE.ddl
@@ -0,0 +1,82 @@
+//
+// === TYPE and TABLE definitions for the BUFRBASE ===
+//
+// As of 17-Jun-1999 : by Sami Saarinen for MAKECMA/FEEDBACK
+//
+//
+// The present TABLE hierarchy
+// ===========================
+//
+//
+//    hdr --> bufr
+//         
+//         
+
+// 
+// === Global $-variables ===
+//
+
+SET  $MDI = 2147483647; // Absolute value of the Missing Data Indicator
+
+SET  $SYNOP = 1;
+SET  $AIREP = 2;
+SET  $SATOB = 3;
+SET  $DRIBU = 4;
+SET  $TEMP = 5;
+SET  $PILOT = 6;
+SET  $SATEM = 7;
+SET  $PAOB = 8;
+SET  $SCATT = 9;
+SET  $ALLSKY = 16;
+
+TYPEDEF obschar_t = (
+  codetype bit9,                        // OBS. CODE TYPE 
+  instype bit10,                        // INS. TYPE 
+  retrtype bit6,                        // RETRIEVAL TYPE 
+  datagroup bit6,                       // DATA PROCESSING GROUP
+);
+
+//
+// === TABLE definitions ===
+//
+
+
+//--------------------------//
+//  #    #  #####   #####   //
+//  #    #  #    #  #    #  //
+//  ######  #    #  #    #  //
+//  #    #  #    #  #####   //
+//  #    #  #    #  #   #   //
+//  #    #  #####   #    #  //
+//--------------------------//
+
+
+CREATE TABLE hdr AS (
+  seqno int,                            // OBSERVATION SEQUENCE NUMBER (CMA)
+
+  obstype pk2int,                       // OBSERVATION TYPE (CMA)
+  obschar OBSCHAR_t,                    // OBSERVATION CHARACTERISTICS (CMA)
+
+  RDBtype pk5int,                       // RDB-type (BUFR)
+  subtype pk5int,                       // Sub-type (BUFR)
+  bufrtype pk5int,                      // BUFR-type (BUFR)
+
+// Links
+  bufr		@LINK,
+);
+
+//----------------------------------//
+//  #####   #    #  ######  #####   //
+//  #    #  #    #  #       #    #  //
+//  #####   #    #  #####   #    #  //
+//  #    #  #    #  #       #####   //
+//  #    #  #    #  #       #   #   //
+//  #####    ####   #       #    #  //
+//----------------------------------//
+
+
+CREATE TABLE bufr AS (
+	msg		bufr,
+);
+
+
diff --git a/odb/src/ddl/BUFRBASE.dep b/odb/src/ddl/BUFRBASE.dep
new file mode 100644
index 0000000..ab63b0e
--- /dev/null
+++ b/odb/src/ddl/BUFRBASE.dep
@@ -0,0 +1,11 @@
+#-- Last updated:  22-Jan-2000
+
+DDLS=\
+	BUFRBASE.ddl
+
+TABLES=\
+	hdr \
+	bufr
+
+VIEWS=\
+	fetchbufr
diff --git a/odb/src/ddl/CMakeLists.txt b/odb/src/ddl/CMakeLists.txt
new file mode 100644
index 0000000..8c35a2e
--- /dev/null
+++ b/odb/src/ddl/CMakeLists.txt
@@ -0,0 +1,4 @@
+install(FILES odb98.flags DESTINATION share/odb)
+install(FILES odb98.flags DESTINATION include) # TODO: until Xavi installs new odb module template
+
+configure_file(odb98.flags ${CMAKE_BINARY_DIR}/share/odb/odb98.flags COPYONLY)
diff --git a/odb/src/ddl/PRESCREEN.ddl b/odb/src/ddl/PRESCREEN.ddl
new file mode 100644
index 0000000..a395362
--- /dev/null
+++ b/odb/src/ddl/PRESCREEN.ddl
@@ -0,0 +1,79 @@
+//
+// Data layout for TOVS & SSM/I PRESCREEN-jobs
+//
+// The present TABLE hierarchy
+// ===========================
+//
+//                   +--> body
+//                   |
+//             hdr --+--> bufr
+//
+//
+
+//--------------------------//
+//  #    #  #####   #####   //
+//  #    #  #    #  #    #  //
+//  ######  #    #  #    #  //
+//  #    #  #    #  #####   //
+//  #    #  #    #  #   #   //
+//  #    #  #####   #    #  //
+//--------------------------//
+
+CREATE TABLE hdr AS (
+	seqno		int,		// Unique sequence no. (>0) across PE-ids
+	duplseqno[1]	pk9int,		// Seqno of master, if duplicate
+
+	sortbox		pk9int,		// Sorting box to be formed
+	thinbox		pk9int,		// Equal to sorting box if NOT thinned
+
+	date		YYYYMMDD,	// Date
+	time		HHMMSS,		// Time
+	msec		pk9int,		// Milliseconds
+
+	satid		pk5int,		// Satellite id
+	sensor		pk5int,		// Sensor id
+
+	orbit		pk9int,		// Orbit no.
+	fov		pk9int,		// Spot no.
+	scanline	pk9int,		// Scanline no.
+
+	lat		real4,		// LATITUDE (in degrees: -90..+90)
+	lon		real4,		// LONGITUDE (in degrees: -180..+180)
+	stalt		pk9int,		// Height of station
+
+	zenith		real4,		// Zenith angle
+
+	body		@LINK,		// Link to body	(brightness temperatures)
+	bufr		@LINK,		// Link to the originating BUFR-message (if required)
+)
+;
+
+//----------------------------------//
+//  #####    ####   #####    #   #  //
+//  #    #  #    #  #    #    # #   //
+//  #####   #    #  #    #     #    //
+//  #    #  #    #  #    #     #    //
+//  #    #  #    #  #    #     #    //
+//  #####    ####   #####      #    //
+//----------------------------------//
+
+
+CREATE TABLE body AS (
+	varno		pk9int,		// Variable number (e.g. NVNUMB(50) = 119)
+	obsvalue	real4,		// Observed value (e.g. BRIGHTNESS TEMPERATURE)
+);
+
+
+//----------------------------------//
+//  #####   #    #  ######  #####   //
+//  #    #  #    #  #       #    #  //
+//  #####   #    #  #####   #    #  //
+//  #    #  #    #  #       #####   //
+//  #    #  #    #  #       #   #   //
+//  #####    ####   #       #    #  //
+//----------------------------------//
+
+
+CREATE TABLE bufr AS (
+	msg		bufr,
+);
diff --git a/odb/src/ddl/PRESCREEN.dep b/odb/src/ddl/PRESCREEN.dep
new file mode 100644
index 0000000..b01c637
--- /dev/null
+++ b/odb/src/ddl/PRESCREEN.dep
@@ -0,0 +1,14 @@
+#-- Last updated:  22-Jan-2000
+
+DDLS=\
+	PRESCREEN.ddl
+
+TABLES=\
+	hdr \
+	body \
+	bufr
+
+VIEWS=\
+	duplchk_ps_1 \
+	duplchk_ps_2
+
diff --git a/odb/src/ddl/adjust_ccma_distribid.sql b/odb/src/ddl/adjust_ccma_distribid.sql
new file mode 100644
index 0000000..8d903f8
--- /dev/null
+++ b/odb/src/ddl/adjust_ccma_distribid.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'adjust_ccma_distribid.sql'
+//
+//   Last updated:  4-Dec-2009
+//
+
+
+CREATE VIEW adjust_ccma_distribid AS
+  SELECT seqno, 
+         target UPDATED,
+         distribid 
+    FROM hdr,index
+    WHERE distribtype = 1 
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/adjust_distribid.sql b/odb/src/ddl/adjust_distribid.sql
new file mode 100644
index 0000000..7f0590b
--- /dev/null
+++ b/odb/src/ddl/adjust_distribid.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'adjust_distribid.sql'
+//
+//   Last updated:  15-Jun-2009
+//
+
+
+CREATE VIEW adjust_distribid AS
+  SELECT seqno, 
+         target UPDATED,
+         distribid 
+    FROM hdr,index
+    WHERE distribtype = 1 AND report_status.active = 1
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/adjust_seqnos.sql b/odb/src/ddl/adjust_seqnos.sql
new file mode 100644
index 0000000..e2da43b
--- /dev/null
+++ b/odb/src/ddl/adjust_seqnos.sql
@@ -0,0 +1,11 @@
+//
+//-- ODB/SQL file 'adjust_seqnos.sql'
+//
+//   Last updated:  01-Jun-2008
+//
+
+
+CREATE VIEW adjust_seqnos AS
+  SELECT seqno, subseqno UPDATED
+    FROM hdr
+;
diff --git a/odb/src/ddl/aeolus.h b/odb/src/ddl/aeolus.h
new file mode 100644
index 0000000..3504255
--- /dev/null
+++ b/odb/src/ddl/aeolus.h
@@ -0,0 +1,50 @@
+//
+// Table Definition: aeolus tables
+//
+
+// aeolus header table, things that don't change at measurement level
+CREATE TABLE aeolus_hdr AS (
+  aeolus_hdrflag aeolus_hdrflag_t,      // Aeolus header flags
+
+  aeolus_auxmet @LINK, 
+
+  aeolus_l2c @LINK, 
+
+);
+
+// table for auxiliary meteorological data
+CREATE TABLE aeolus_auxmet AS (
+  lev           pk9real,              // Model level (zero for surface values)
+  ptop          pk9real,              // Pressure at top of layer
+  pnom          pk9real,              // Nominal pressure within layer
+  ztop          pk9real,              // Geopotential height at top of layer
+  znom          pk9real,              // Nominal geopotential height within layer
+  u             pk9real,              // Uwind
+  v             pk9real,              // Vwind
+  t             pk9real,              // Temperature
+  rh            pk9real,              // Relative humidity
+  q             pk9real,              // Specific humidity
+  cc            pk9real,              // Cloud cover
+  clwc          pk9real,              // Cloud liquid water content
+  ciwc          pk9real,              // Cloud ice water content
+  error_t       pk9real,              // Error estimate for temperature
+  error_rh      pk9real,              // Error estimate for relative humidity
+  error_p       pk9real,              // Error estimate for pressure
+);
+
+// table for Level 2C products
+CREATE TABLE aeolus_l2c AS (
+  hlos_ob_err   pk9real,              // Final HLOS obs error
+  hlos_fg       pk9real,              // HLOS from first guess
+  u_fg          pk9real,              // First guess zonal wind
+  u_fg_err      pk9real,              // u component first guess error
+  v_fg          pk9real,              // First guess meridional wind
+  v_fg_err      pk9real,              // v component first guess error
+  hlos_fg_err   pk9real,              // HLOS err from first guess
+  hlos_an       pk9real,              // HLOS from analysis
+  hlos_an_err   pk9real,              // HLOS err from analysis
+  u_an          pk9real,              // Analysis zonal wind
+  v_an          pk9real,              // Analysis meridional wind
+);
+
+
diff --git a/odb/src/ddl/aeolus_auxmet_update_hdrflag.sql b/odb/src/ddl/aeolus_auxmet_update_hdrflag.sql
new file mode 100644
index 0000000..36f1380
--- /dev/null
+++ b/odb/src/ddl/aeolus_auxmet_update_hdrflag.sql
@@ -0,0 +1,10 @@
+UPDATED;
+CREATE VIEW aeolus_auxmet_update_hdrflag AS
+    SELECT date at hdr READONLY,
+           time at hdr READONLY, 
+           retrtype at hdr READONLY,
+           aeolus_hdrflag at aeolus_hdr 
+     FROM hdr, aeolus_hdr
+     WHERE retrtype at hdr=1
+;
+
diff --git a/odb/src/ddl/airep_flight_phase_robhdr.sql b/odb/src/ddl/airep_flight_phase_robhdr.sql
new file mode 100644
index 0000000..38c85cf
--- /dev/null
+++ b/odb/src/ddl/airep_flight_phase_robhdr.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'airep_flight_phase_robhdr.sql'
+//
+//   Last updated:  30-Mar-2011
+
+//
+
+READONLY;
+
+CREATE VIEW airep_flight_phase_robhdr AS
+     SELECT seqno,
+            body.len,
+            statid, obstype, codetype, date,
+            time,
+            flight_phase, 
+            flight_dp_o_dt UPDATED,
+            varno, obsvalue,
+            vertco_type,
+            vertco_reference_1,
+      FROM index, hdr, conv, body
+      WHERE obstype==$airep and varno==2
+      ORDERBY codetype, statid, date, time, vertco_reference_1
+;
diff --git a/odb/src/ddl/airep_flight_phase_robody.sql b/odb/src/ddl/airep_flight_phase_robody.sql
new file mode 100644
index 0000000..3b405ca
--- /dev/null
+++ b/odb/src/ddl/airep_flight_phase_robody.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'airep_flight_phase_robody.sql'
+//
+//   Last updated:  30-Jun-2005
+
+//
+
+READONLY;
+
+CREATE VIEW airep_flight_phase_robody AS
+     SELECT seqno,
+            varno, obsvalue,
+            vertco_type,
+            vertco_reference_1,
+      FROM  index, hdr, body
+      WHERE obstype==$airep and varno==2
+      ORDERBY codetype, statid, date, time, vertco_reference_1
+;
diff --git a/odb/src/ddl/airs.sql b/odb/src/ddl/airs.sql
new file mode 100644
index 0000000..6ef3f3b
--- /dev/null
+++ b/odb/src/ddl/airs.sql
@@ -0,0 +1,13 @@
+CREATE VIEW airs AS
+SELECT 
+lat, lon, body.len,
+solar_zenith at sat, scanpos at radiance, time, lsm, date, 
+vertco_reference_1, obsvalue, fg_depar, an_depar, lores at update_1,
+biascorr, seqno
+FROM
+hdr, body, sat, radiance, modsurf, update_1
+WHERE
+obstype=7 AND satellite_identifier at sat=784
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/airs_flag.sql b/odb/src/ddl/airs_flag.sql
new file mode 100644
index 0000000..23ca28c
--- /dev/null
+++ b/odb/src/ddl/airs_flag.sql
@@ -0,0 +1,14 @@
+CREATE VIEW airs_flag AS
+SELECT  datum_status.active at body,       datum_status.passive at body,
+        datum_status.rejected at body,     datum_status.blacklisted at body,
+        datum_event1.rdb_rejected at body,     datum_event1.datum_redundant at body,
+        datum_event1.level_redundant at body,  datum_event1.duplicate at body,
+        report_event1.redundant at hdr,
+	datum_anflag.varqc at body,        datum_anflag.fg at body,   seqno
+FROM    
+      hdr, body, sat
+WHERE  
+      obstype=7 AND satellite_identifier at sat=784
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/ak_resat_averaging_kernel.sql b/odb/src/ddl/ak_resat_averaging_kernel.sql
new file mode 100644
index 0000000..aa6308c
--- /dev/null
+++ b/odb/src/ddl/ak_resat_averaging_kernel.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'ak_resat_averaging_kernel.sql'
+//
+//   New:  13-Jul-2005
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW ak_resat_averaging_kernel AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         nak,                          // r/o
+         obs_ak_error,                 // r/o
+         pak[1:$mx_ak],                // r/o
+         wak[1:$mx_ak],                // r/o
+         apak[1:$mx_ak]                // r/o
+    FROM timeslot_index, index, hdr, sat, resat, resat_averaging_kernel, errstat
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $satem AND codetype = $resat
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/alloc.h b/odb/src/ddl/alloc.h
new file mode 120000
index 0000000..3496363
--- /dev/null
+++ b/odb/src/ddl/alloc.h
@@ -0,0 +1 @@
+../include/alloc.h
\ No newline at end of file
diff --git a/odb/src/ddl/allsky.h b/odb/src/ddl/allsky.h
new file mode 100644
index 0000000..75bc3ca
--- /dev/null
+++ b/odb/src/ddl/allsky.h
@@ -0,0 +1,55 @@
+//
+// Table Definition: allsky tables
+//
+CREATE TABLE allsky AS (
+  fg_rain_rate             pk9real,      // Surface rain @ FG [mm h-1] 
+  fg_snow_rate             pk9real,      // Surface frozen precipitation @ FG [ mm h-1]
+  fg_tcwv                  pk9real,      // Total column water vapour @ FG [ kg m-2]
+  fg_cwp                   pk9real,      // Cloud liquid water path @ FG [ kg m-2 ] 
+  fg_iwp                   pk9real,      // Cloud ice water path @ FG [ kg m-2 ]
+  fg_rwp                   pk9real,      // Rain water path @ FG [ kg m-2 ]
+  fg_swp                   pk9real,      // Snow water path @ FG [ kg m-2 ] 
+  fg_rttov_cld_fraction    pk9real,      // Cloud fraction used in RTTOV_SCATT [0-1] 
+  fg_theta700              pk9real,      // Potential Temperature in 700hPa @ FG [K]
+  fg_thetasfc              pk9real,      // Potential Temperature at the surface @ FG [K]
+  fg_uth                   pk9real,      // 200-500hPa weighted average relative humidity wrt water @ FG [0-1]  
+  an_rain_rate             pk9real,      // Surface rain @ AN [mm h-1] 
+  an_snow_rate             pk9real,      // Surface frozen precipitation @ AN [ mm h-1]
+  an_tcwv                  pk9real,      // Total column water vapour @ AN [ kg m-2]
+  an_cwp                   pk9real,      // Cloud liquid water path @ AN [ kg m-2 ] 
+  an_iwp                   pk9real,      // Cloud ice water path @ AN [ kg m-2 ]
+  an_rwp                   pk9real,      // Rain water path @ AN [ kg m-2 ]
+  an_swp                   pk9real,      // Snow water path @ AN [ kg m-2 ] 
+  an_rttov_cld_fraction    pk9real,      // Cloud fraction used in RTTOV_SCATT [0-1] 
+  an_theta700              pk9real,      // Potential Temperature in 700hPa @ FG [K]
+  an_thetasfc              pk9real,      // Potential Temperature at the surface @ FG [K]
+  an_uth                   pk9real,      // 200-500hPa weighted average relative humidity wrt water @ AN [0-1]                          
+  gnorm_10mwind            pk9real,      // Norm of gradient against 10m wind 
+  gnorm_skintemp           pk9real,      // Norm of gradient against skin temperature 
+  gnorm_temp               pk9real,      // Norm of gradient against temperature
+  gnorm_q                  pk9real,      // Norm of gradient against specific humidity 
+  gnorm_rainflux           pk9real,      // Norm of gradient against rain flux 
+  gnorm_snowflux           pk9real,      // Norm of gradient against snow flux
+  gnorm_clw                pk9real,      // Norm of gradient against cloud water
+  gnorm_ciw                pk9real,      // Norm of gradient against cloud ice
+  gnorm_cc                 pk9real,      // Norm of gradient against cloud cover
+
+  ob_p19                   pk9real,      // 19 GHz normalised polarisation difference observed
+  fg_p19                   pk9real,      // 19 GHz normalised polarisation difference first guess
+  an_p19                   pk9real,      // 19 GHz normalised polarisation difference analysis
+  
+  ob_p37                   pk9real,      // 19 GHz normalised polarisation difference observed
+  fg_p37                   pk9real,      // 19 GHz normalised polarisation difference first guess
+  an_p37                   pk9real,      // 19 GHz normalised polarisation difference analysis
+
+  report_tbcloud           pk1int,       // Cloud and rain cloud bitfield flag determined from TB bitfield - See yommwave.F90
+  allsky_body              @LINK,
+);
+
+CREATE TABLE allsky_body AS (
+  tbvalue                 pk9real,       // Simulated brightness temperature
+  tbvaluetl               pk9real,       // Simulated TL of brightness temperature
+  tbvaluead               pk9real,       // Simulated AD in brightness temperature
+  datum_tbflag            pk1int,        // Status flag for all-sky  - See yommwave.F90
+);
+
diff --git a/odb/src/ddl/allsky_update_links.sql b/odb/src/ddl/allsky_update_links.sql
new file mode 100644
index 0000000..24963d7
--- /dev/null
+++ b/odb/src/ddl/allsky_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'allsky_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW allsky_update_links AS
+  SELECT "/LINK.*/"
+    FROM allsky
+;
+
diff --git a/odb/src/ddl/amv.sql b/odb/src/ddl/amv.sql
new file mode 100644
index 0000000..7b3e475
--- /dev/null
+++ b/odb/src/ddl/amv.sql
@@ -0,0 +1,18 @@
+SET $refdt_l=0;
+SET $refdt_r=0;
+SET $refdate=0;
+SET $reftime=0;
+SET $zatid  =-1;
+SET $zenzor =-1;
+
+CREATE VIEW amv AS
+SELECT  date, time, lat, lon, satellite_identifier at sat, comp_method, qi_fc, vertco_reference_1,
+        obsvalue, fg_depar, an_depar, u_old, v_old, seqno
+FROM    hdr, body, sat, satob
+WHERE   obstype=$satob 
+  AND   satellite_identifier at sat = $zatid 
+  AND   comp_method = $zenzor
+  AND   twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)
+  AND   varno IN ($u, $v)
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/amv2.sql b/odb/src/ddl/amv2.sql
new file mode 100644
index 0000000..db1fd80
--- /dev/null
+++ b/odb/src/ddl/amv2.sql
@@ -0,0 +1,10 @@
+CREATE VIEW amv2 AS
+SELECT  date, time, lat, lon, satellite_identifier at sat, comp_method, qi_fc, vertco_reference_1,
+        obsvalue, fg_depar, an_depar, u_old, v_old, qi_nofc,datastream,
+        seqno
+FROM    hdr, body, sat, satob
+WHERE   obstype=$satob 
+  AND   varno IN ($u, $v)
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/amv_flag.sql b/odb/src/ddl/amv_flag.sql
new file mode 100644
index 0000000..8b52b3b
--- /dev/null
+++ b/odb/src/ddl/amv_flag.sql
@@ -0,0 +1,22 @@
+SET $refdt_l=0;
+SET $refdt_r=0;
+SET $refdate=0;
+SET $reftime=0;
+SET $zatid  =-1;
+SET $zenzor =-1;
+
+CREATE VIEW amv_flag AS
+SELECT  datum_status.active at body, datum_status.passive at body,
+        datum_status.rejected at body,datum_status.blacklisted at body,
+        datum_event1.rdb_rejected at body,datum_event1.datum_redundant at body,
+        datum_event1.level_redundant at body,datum_event1.duplicate at body,
+        report_event1.redundant at hdr,datum_anflag.varqc at body,datum_anflag.fg at body,
+        datum_event1.vertco_consistency at body,seqno
+FROM    hdr, body, sat, satob
+WHERE   obstype=$satob 
+  AND   satellite_identifier at sat = $zatid 
+  AND   comp_method = $zenzor
+  AND   twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)
+  AND   varno IN ($u)
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/amv_flag2.sql b/odb/src/ddl/amv_flag2.sql
new file mode 100644
index 0000000..81ecd6a
--- /dev/null
+++ b/odb/src/ddl/amv_flag2.sql
@@ -0,0 +1,12 @@
+CREATE VIEW amv_flag2 AS
+SELECT  datum_status.active at body, datum_status.passive at body,
+        datum_status.rejected at body,datum_status.blacklisted at body,
+        datum_event1.rdb_rejected at body,datum_event1.datum_redundant at body,
+        datum_event1.level_redundant at body,datum_event1.duplicate at body,
+        report_event1.redundant at hdr,datum_anflag.varqc at body,datum_anflag.fg at body,
+        datum_event1.vertco_consistency at body,seqno
+FROM    hdr, body
+WHERE   obstype=$satob 
+  AND   varno IN ($u)
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/ascatsm_robhdr_1.sql b/odb/src/ddl/ascatsm_robhdr_1.sql
new file mode 100644
index 0000000..50f0ac8
--- /dev/null
+++ b/odb/src/ddl/ascatsm_robhdr_1.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'ascatsm_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW ascatsm_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_rdbflag,                      // r/o
+         report_status,                       // possibly updated (in ECMA)
+         report_event1,                       // possibly updated (in ECMA)
+         report_event2,                       // possibly updated (in ECMA)
+         date,                         // r/o
+         time,                         // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE  obstype = $scatt
+    AND  (($codetype == -1) OR (codetype == $codetype))
+    AND  (($sensor == -1) OR (sensor == $sensor))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/ascatsm_robody_1.sql b/odb/src/ddl/ascatsm_robody_1.sql
new file mode 100644
index 0000000..3db1c4d
--- /dev/null
+++ b/odb/src/ddl/ascatsm_robody_1.sql
@@ -0,0 +1,41 @@
+//
+//-- ODB/SQL file 'ascatsm_robody_1.sql'
+//
+//   Last updated:  06-Jun-2007
+//
+
+UPDATED;
+
+SET $tslot = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW ascatsm_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,                  // possibly updated
+         datum_event2 at body,                  // possibly updated
+         datum_status at body,                  // possibly updated
+         datum_anflag at body,                  // possibly updated
+         datum_rdbflag at body,                 // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                // possibly updated
+         qc_l,                // possibly updated
+         qc_pge,                // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  obstype = $scatt
+    AND  (($codetype == -1) OR (codetype == $codetype))
+    AND  (($sensor == -1) OR (sensor == $sensor))
+    AND         (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/auxiliary.h b/odb/src/ddl/auxiliary.h
new file mode 100644
index 0000000..ce36bef
--- /dev/null
+++ b/odb/src/ddl/auxiliary.h
@@ -0,0 +1,18 @@
+//
+// Table Definition: auxiliary tables
+//
+CREATE TABLE auxiliary AS (
+// only exist if LAUXILIARY
+// temporary table (auxiliary) which is never archived
+
+  report_aux[$NUMAUX]          pk9real,                     // Auxiliary header-like entries; 
+  auxiliary_body               @LINK,
+);
+
+CREATE TABLE auxiliary_body AS (
+// only exist if LAUXILIARY
+// temporary table (auxiliary) which is never archived
+  datum_aux[$NUMAUX]          pk9real,                     // Auxiliary body-like entries;
+);
+
+
diff --git a/odb/src/ddl/averaging_smos.sql b/odb/src/ddl/averaging_smos.sql
new file mode 100644
index 0000000..e498345
--- /dev/null
+++ b/odb/src/ddl/averaging_smos.sql
@@ -0,0 +1,27 @@
+READONLY;
+
+SET $angle_min = -1;
+SET $angle_max = -1;
+SET $polarisation = -1;
+
+CREATE VIEW averaging_smos
+  SELECT  seqno,
+          entryno,
+          lat,
+          lon,
+          date,
+          time,
+          obsvalue UPDATED,
+          incidence_angle UPDATED,
+          nobs_averaged UPDATED,
+          stdev_averaged UPDATED,
+          report_status UPDATED,
+          datum_status UPDATED,
+          rad_acc_pure UPDATED,
+          faradey_rot_angle UPDATED,
+          pixel_rot_angle UPDATED,
+FROM hdr,body,smos
+WHERE $angle_min <= incidence_angle <= $angle_max
+AND polarisation=$polarisation
+ORDER BY lat,lon, date, time
+
diff --git a/odb/src/ddl/bator_hdr_1.sql b/odb/src/ddl/bator_hdr_1.sql
new file mode 100644
index 0000000..8e2afea
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_1.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_1 AS
+SELECT "*@sat","*@satob"
+FROM  hdr,sat,satob
+WHERE obstype = $satob
diff --git a/odb/src/ddl/bator_hdr_2.sql b/odb/src/ddl/bator_hdr_2.sql
new file mode 100644
index 0000000..3625d71
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_2.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_2 AS
+SELECT "*@sat","*@radiance"
+FROM  hdr,sat,radiance
+WHERE obstype = $satem AND codetype = $atovs
diff --git a/odb/src/ddl/bator_hdr_3.sql b/odb/src/ddl/bator_hdr_3.sql
new file mode 100644
index 0000000..4817b58
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_3.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_3 AS
+SELECT "*@sat","*@scatt"
+FROM  hdr,sat,scatt
+WHERE obstype = $scatt
diff --git a/odb/src/ddl/bator_hdr_4.sql b/odb/src/ddl/bator_hdr_4.sql
new file mode 100644
index 0000000..2265f85
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_4.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_4 AS
+SELECT "*@sat","*@radiance","*@ssmi"
+FROM  hdr,sat,radiance,ssmi
+WHERE obstype = $satem AND codetype = $ssmi 
diff --git a/odb/src/ddl/bator_hdr_5.sql b/odb/src/ddl/bator_hdr_5.sql
new file mode 100644
index 0000000..cb34c23
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_5.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_5 AS
+SELECT "*@sat","*@radar"
+FROM  hdr,sat,radar
+WHERE obstype = $radar
diff --git a/odb/src/ddl/bator_hdr_6.sql b/odb/src/ddl/bator_hdr_6.sql
new file mode 100644
index 0000000..c6c2f79
--- /dev/null
+++ b/odb/src/ddl/bator_hdr_6.sql
@@ -0,0 +1,4 @@
+CREATE VIEW bator_hdr_6 AS
+SELECT "*@sat","*@gnssro"
+FROM  hdr,sat,gnssro
+WHERE codetype = $gpsro
diff --git a/odb/src/ddl/bits.h b/odb/src/ddl/bits.h
new file mode 120000
index 0000000..c4ce6ab
--- /dev/null
+++ b/odb/src/ddl/bits.h
@@ -0,0 +1 @@
+../include/bits.h
\ No newline at end of file
diff --git a/odb/src/ddl/black_robhdr_1.sql b/odb/src/ddl/black_robhdr_1.sql
new file mode 100644
index 0000000..0b91490
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_1.sql
@@ -0,0 +1,40 @@
+//
+//   Blacklisting default header query + conv
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_1 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         sonde_type at conv,
+         collection_identifier at conv,
+  FROM   timeslot_index, index, hdr, modsurf, conv
+  WHERE  (obstype IN ($synop, $airep, $dribu, $temp, $pilot, $paob))
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_10.sql b/odb/src/ddl/black_robhdr_10.sql
new file mode 100644
index 0000000..2a932d6
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_10.sql
@@ -0,0 +1,39 @@
+//
+//-- ODB/SQL file 'black_robhdr_10.sql'
+//
+//   Blacklisting default header query
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_10 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+  FROM   timeslot_index, index, hdr, modsurf
+  WHERE  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_2.sql b/odb/src/ddl/black_robhdr_2.sql
new file mode 100644
index 0000000..9f0781a
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_2.sql
@@ -0,0 +1,49 @@
+//
+//   Blacklisting default header query + sat default + satob
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_2 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         satellite_identifier at sat, // SAT CORE HDR START
+         zenith at sat,
+         azimuth at sat,
+         gen_centre at sat,
+         gen_subcentre at sat,
+         datastream at sat,
+         solar_zenith at sat, // SAT CORE HDR END
+         comp_method at satob,
+         QI_fc at satob,
+         RFF at satob,
+         QI_nofc at satob,
+  FROM   timeslot_index, index, hdr, modsurf, sat, satob
+  WHERE (obstype = $satob)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_3.sql b/odb/src/ddl/black_robhdr_3.sql
new file mode 100644
index 0000000..fcd3f23
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_3.sql
@@ -0,0 +1,45 @@
+//
+//   Blacklisting default header query + sat default
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_3 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         satellite_identifier at sat, // SAT CORE HDR START
+         zenith at sat,
+         azimuth at sat,
+         gen_centre at sat,
+         gen_subcentre at sat,
+         datastream at sat,
+         solar_zenith at sat, // SAT CORE HDR END
+  FROM   timeslot_index, index, hdr, modsurf, sat
+  WHERE  (obstype = $scatt)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_4.sql b/odb/src/ddl/black_robhdr_4.sql
new file mode 100644
index 0000000..031e7a2
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_4.sql
@@ -0,0 +1,53 @@
+//
+//   Blacklisting default header query + sat default + radiance
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_4 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         satellite_identifier at sat, // SAT CORE HDR START
+         zenith at sat,
+         azimuth at sat,
+         gen_centre at sat,
+         gen_subcentre at sat,
+         datastream at sat,
+         solar_zenith at sat, // SAT CORE HDR END
+         scanpos at radiance,
+         scanline at radiance,
+         typesurf at radiance,
+         asr_pclear at radiance,
+         asr_pcloudy at radiance,
+         asr_pcloudy_low at radiance,
+         asr_pcloudy_middle at radiance,
+         asr_pcloudy_high at radiance,  
+  FROM   timeslot_index, index, hdr, modsurf, sat, radiance
+  WHERE ((obstype = $satem AND codetype = $atovs) OR (obstype = $allsky AND codetype = $ssmi))
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_7.sql b/odb/src/ddl/black_robhdr_7.sql
new file mode 100644
index 0000000..354c73e
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_7.sql
@@ -0,0 +1,55 @@
+//
+//   Blacklisting default header query + sat default + resat
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_7 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         satellite_identifier at sat, // SAT CORE HDR START
+         zenith at sat,
+         azimuth at sat,
+         gen_centre at sat,
+         gen_subcentre at sat,
+         datastream at sat,
+         solar_zenith at sat, // SAT CORE HDR END
+         retrsource at resat,
+         instrument_type at resat,
+         product_type at resat,
+         scanpos at resat,
+         quality_retrieval at resat,
+         solar_elevation at resat,
+         cloud_cover at resat,
+         cloud_top_press at resat,
+         surface_type_indicator at resat,
+  FROM   timeslot_index, index, hdr, modsurf, sat, resat
+  WHERE	 (obstype = $satem)
+    AND  (codetype = $resat)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_8.sql b/odb/src/ddl/black_robhdr_8.sql
new file mode 100644
index 0000000..47fbd9f
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_8.sql
@@ -0,0 +1,46 @@
+//
+//   Blacklisting default header query + sat default + gnssro 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_8 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+         satellite_identifier at sat, // SAT CORE HDR START
+         zenith at sat,
+         azimuth at sat,
+         gen_centre at sat,
+         gen_subcentre at sat,
+         datastream at sat,
+         solar_zenith at sat, // SAT CORE HDR END    
+         radcurv at gnssro,           
+  FROM   timeslot_index, index, hdr, modsurf, sat, gnssro
+  WHERE  (obstype = $limb)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robhdr_9.sql b/odb/src/ddl/black_robhdr_9.sql
new file mode 100644
index 0000000..e4dce72
--- /dev/null
+++ b/odb/src/ddl/black_robhdr_9.sql
@@ -0,0 +1,38 @@
+//
+//   Blacklisting default header query
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robhdr_9 AS
+  SELECT seqno, // BLACKLIST CORE HDR START. SEQNO MUST COME FIRST
+         abnob,
+         mapomm,
+         body.len,
+         obstype,
+         codetype,
+         instrument_type at hdr,
+         retrtype,
+         areatype,
+         date,
+         time,
+         report_status  UPDATED,
+         report_blacklist  UPDATED,
+         stalt,
+         lat,
+         lon,
+         orography,
+         statid,
+         reportype,
+         source,
+         sensor, // BLACKLIST CORE HDR END
+  FROM   timeslot_index, index, hdr, modsurf,
+  WHERE	 (obstype = $radar)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_1.sql b/odb/src/ddl/black_robody_1.sql
new file mode 100644
index 0000000..ca3fa84
--- /dev/null
+++ b/odb/src/ddl/black_robody_1.sql
@@ -0,0 +1,30 @@
+//
+//   Blacklisting default body query + conv
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_1 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+         ppcode at conv_body,
+  FROM   timeslot_index, index, hdr, body, errstat, conv_body
+  WHERE	 (obstype IN ($synop, $airep, $dribu, $temp, $pilot, $paob))
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
diff --git a/odb/src/ddl/black_robody_10.sql b/odb/src/ddl/black_robody_10.sql
new file mode 100644
index 0000000..48ffc37
--- /dev/null
+++ b/odb/src/ddl/black_robody_10.sql
@@ -0,0 +1,28 @@
+//
+//   Blacklisting default body query 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_10 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
diff --git a/odb/src/ddl/black_robody_2.sql b/odb/src/ddl/black_robody_2.sql
new file mode 100644
index 0000000..7b1e874
--- /dev/null
+++ b/odb/src/ddl/black_robody_2.sql
@@ -0,0 +1,30 @@
+//
+//   Blacklisting default body query 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_2 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (obstype = $satob)
+    AND  (kset = $kset) 
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_3.sql b/odb/src/ddl/black_robody_3.sql
new file mode 100644
index 0000000..61577b4
--- /dev/null
+++ b/odb/src/ddl/black_robody_3.sql
@@ -0,0 +1,30 @@
+//
+//   Blacklisting default body query 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_3 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (obstype = $scatt)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_4.sql b/odb/src/ddl/black_robody_4.sql
new file mode 100644
index 0000000..43bdcd3
--- /dev/null
+++ b/odb/src/ddl/black_robody_4.sql
@@ -0,0 +1,32 @@
+//
+//   Blacklisting default header query + radiance
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_4 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+         tausfc at radiance_body,
+         csr_pclear at radiance_body,
+  FROM   timeslot_index, index, hdr, body, errstat, radiance_body
+  WHERE ((obstype = $satem AND codetype = $atovs) OR (obstype = $allsky AND codetype = $ssmi))
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_7.sql b/odb/src/ddl/black_robody_7.sql
new file mode 100644
index 0000000..964ade9
--- /dev/null
+++ b/odb/src/ddl/black_robody_7.sql
@@ -0,0 +1,31 @@
+//
+//   Blacklisting default body query 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_7 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (obstype = $satem)
+    AND  (codetype = $resat)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_8.sql b/odb/src/ddl/black_robody_8.sql
new file mode 100644
index 0000000..528e194
--- /dev/null
+++ b/odb/src/ddl/black_robody_8.sql
@@ -0,0 +1,30 @@
+//
+//   Blacklisting default body query 
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_8 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (obstype = $limb)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/black_robody_9.sql b/odb/src/ddl/black_robody_9.sql
new file mode 100644
index 0000000..65c3aa8
--- /dev/null
+++ b/odb/src/ddl/black_robody_9.sql
@@ -0,0 +1,31 @@
+//
+//   Blacklisting default body query + radar
+//
+//   == ALWAYS keep black*1.sql to black*10.sql consistent! ==
+//
+
+READONLY; // Except entries those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW black_robody_9 AS
+  SELECT seqno, // BLACKLIST CORE BODY START. SEQNO MUST COME FIRST
+         entryno,
+         datum_status at body     UPDATED, 
+         datum_blacklist at body  UPDATED,
+         datum_anflag          UPDATED,
+         vertco_type,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         fg_depar,
+         final_obs_error,
+         fg_error, // BLACKLIST CORE BODY END
+         elevation at radar_body,
+  FROM   timeslot_index, index, hdr, body, errstat, radar_body
+  WHERE	 (obstype = $radar)
+    AND  (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/body.h b/odb/src/ddl/body.h
new file mode 100644
index 0000000..24a93f7
--- /dev/null
+++ b/odb/src/ddl/body.h
@@ -0,0 +1,52 @@
+//
+// Table Definition: body table
+//
+CREATE TABLE body AS (
+  entryno               pk1int,                      // ENTRY SQ. NO. 
+  obsvalue              pk9real,                     // OBSERVED VARIABLE as used in IFS (may contain noise correction, etc.)
+  varno                 pk1int,                      // VARIABLE NUMBER
+  vertco_type           pk1int,                      // VERTICAL COORDINATE TYPE
+  vertco_reference_1    pk9real,                     // VERTICAL COORDINATE REFERENCE 1
+  vertco_reference_2    pk9real,                     // VERTICAL COORDINATE REFERENCE 2
+
+// DATUM flags
+  datum_anflag          DATUM_FLAG_t,                // OBSERVATION FLAGS
+  datum_status          TYPEOF(report_status at hdr),   // New feature; equivalent to old def : "status STATUS_t"
+  datum_event1          DATUM_EVENT1_t,              // OBSERVATION EVENTS (PART 1)
+  datum_rdbflag         DATUM_RDBFLAG_t,             // OBSERVATION FLAGS (RDB)
+  datum_blacklist       DATUM_BLACKLIST_t,           // OBSERVATION BLACKLIST EVENTS
+  datum_event2          DATUM_EVENT2_t,              // DATUM EVENTS (PART 2) WORD POS.
+
+
+  varbc_ix              pk1int,                      // VarBC group index
+  biascorr              pk9real,                     // RADIANCE BIAS CORRECTION
+  biascorr_fg           pk9real,                     // FG bias correction
+  tbcorr                pk9real,                     // Correction to Brightness temperature (radiance only)
+  bias_volatility       pk9real,                     // Estimated volatility of the observation bias
+  wdeff_bcorr           pk9real,                     // Wind-induced error bias correction for rain gauges
+
+  an_depar              pk9real,                     // OBSERVED MINUS ANALYSED VALUE
+  fg_depar              pk9real,                     // OBSERVED MINUS FIRST GUESS VALUE
+  actual_depar          pk9real,                     // We store the actual departure during the minimization
+  qc_a                  pk9real,                     // VAR QC prior probability of gross error (by variable and obstype) 
+  qc_l                  pk9real,                     // VAR QC width of the distribution
+  qc_pge                pk9real,                     // VAR QC a posteriori probability of gross error
+ 
+  fc_sens_obs           pk9real,                     // forecast sensitivity to the observations
+  an_sens_obs           pk9real,                     // analysis sensitivity to the obs
+
+  jacobian_peak         pk9real,  // used for ENKF; to move to radiance_body and gnssro_body
+  jacobian_peakl        pk9real, // used for ENKF; to move to radiance_body and gnssro_body
+  jacobian_hpeak        pk9real, // used for ENKF; to move to radiance_body and gnssro_body
+  jacobian_hpeakl       pk9real, // used for ENKF; to move to radiance_body and gnssro_body
+
+
+  mf_vertco_type        pk1int,                      // vertical coordinate type
+  mf_log_p              pk9real,                     // pressure used in CANARI (Log P)
+  mf_stddev             pk9real,                     // obs. std dev at bottom layer
+
+// for resat data only
+  nlayer                pk1int,                      // layer number used in resat varbc  
+
+);
+
diff --git a/odb/src/ddl/btemdup_robhdr_1.sql b/odb/src/ddl/btemdup_robhdr_1.sql
new file mode 100644
index 0000000..e644ea5
--- /dev/null
+++ b/odb/src/ddl/btemdup_robhdr_1.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'btemdup_robhdr_1.sql'
+//
+//   Last updated:  08-Apr-2014
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW btemdup_robhdr_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         statid,                       // r/o
+         trlat,                        // r/o
+         trlon,                        // r/o
+	 lat, lon,                     // r/o
+ 	 numlev,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 obstype IN ($temp, $pilot)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/caifc1.sql b/odb/src/ddl/caifc1.sql
new file mode 100644
index 0000000..472afe3
--- /dev/null
+++ b/odb/src/ddl/caifc1.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'caifc1.sql'
+//
+//   Last updated:  11-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW caifc1 AS
+  SELECT seqno,
+	 body.len,
+	 fg_depar,
+         hires UPDATED
+    FROM index, hdr, body, update[1]
+;
diff --git a/odb/src/ddl/camelo_robhdr.sql b/odb/src/ddl/camelo_robhdr.sql
new file mode 100644
index 0000000..761312b
--- /dev/null
+++ b/odb/src/ddl/camelo_robhdr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'camelo_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW camelo_robhdr AS
+  SELECT seqno,
+         body.len,
+         codetype,
+         instrument_type,
+         obstype,
+         sortbox UPDATED,
+         trlat,
+         date,
+         lat,
+         lon
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/camelo_robody.sql b/odb/src/ddl/camelo_robody.sql
new file mode 100644
index 0000000..74a735d
--- /dev/null
+++ b/odb/src/ddl/camelo_robody.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'camelo_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW camelo_robody AS
+  SELECT seqno READONLY,
+         varno READONLY,
+         datum_rdbflag at body,
+         datum_anflag,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         mf_log_p,
+         final_obs_error,
+         obs_error,
+         repres_error,
+         pers_error
+  FROM   index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/canaco_robhdr.sql b/odb/src/ddl/canaco_robhdr.sql
new file mode 100644
index 0000000..c507078
--- /dev/null
+++ b/odb/src/ddl/canaco_robhdr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'canaco_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001 / 25-Jan-2012
+//
+
+READONLY;
+
+CREATE VIEW canaco_robhdr AS
+  SELECT  seqno,
+          body.len,
+          obstype,
+          sortbox,
+          instrument_type,
+          report_blacklist,
+          lon,
+          lat,
+          trlat,
+          stalt,
+          orography,
+          lsm
+  FROM    index, hdr, modsurf
+  ORDERBY obstype, sortbox
+;
diff --git a/odb/src/ddl/canaco_robhdr_ccma.sql b/odb/src/ddl/canaco_robhdr_ccma.sql
new file mode 100644
index 0000000..b5ffab0
--- /dev/null
+++ b/odb/src/ddl/canaco_robhdr_ccma.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'canaco_robhdr_ccma.sql'
+//
+//   Created : 21/02/2012
+//
+
+READONLY;
+
+CREATE VIEW canaco_robhdr_ccma AS
+  SELECT  seqno,
+          body.len,
+          obstype,
+          sortbox,
+          instrument_type,
+          lon,
+          lat,
+          trlat
+  FROM    index, hdr
+  ORDERBY obstype, sortbox
+;
diff --git a/odb/src/ddl/canaco_robody.sql b/odb/src/ddl/canaco_robody.sql
new file mode 100644
index 0000000..64f61c9
--- /dev/null
+++ b/odb/src/ddl/canaco_robody.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'canaco_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW canaco_robody AS
+  SELECT  seqno,
+          varno,
+          obstype,
+          sortbox,
+          entryno,
+          datum_anflag at body UPDATED, // CANACO, version#1 updates
+          vertco_reference_1,
+          vertco_reference_2,
+          obs_error,
+          repres_error,
+          fg_error,
+          fg_depar,
+          obsvalue,
+          mf_log_p,
+          mf_stddev
+  FROM    index, hdr, body, errstat
+  ORDERBY obstype, sortbox
+;
diff --git a/odb/src/ddl/cancer_robhdr.sql b/odb/src/ddl/cancer_robhdr.sql
new file mode 100644
index 0000000..faed38f
--- /dev/null
+++ b/odb/src/ddl/cancer_robhdr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'cancer_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW cancer_robhdr AS
+  SELECT seqno,
+         body.len,
+         abnob, mapomm,
+         obstype,
+         codetype,
+         lat,
+         trlat,
+         stalt,
+         orography  UPDATED,
+         lsm        UPDATED
+  FROM   index, hdr, modsurf
+;
diff --git a/odb/src/ddl/cancer_robody.sql b/odb/src/ddl/cancer_robody.sql
new file mode 100644
index 0000000..4be7fab
--- /dev/null
+++ b/odb/src/ddl/cancer_robody.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'cancer_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW cancer_robody AS
+  SELECT seqno,
+         varno,
+         datum_anflag at body UPDATED,
+         vertco_reference_1,
+         vertco_reference_2,
+         mf_log_p,
+         an_depar,
+         fg_depar,
+         mf_stddev,
+         fg_error,
+         final_obs_error,
+         qc_l UPDATED,
+         qc_a at body UPDATED,
+         qc_pge at body UPDATED,
+  FROM   index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/cantik_robhdr.sql b/odb/src/ddl/cantik_robhdr.sql
new file mode 100644
index 0000000..5bbc54d
--- /dev/null
+++ b/odb/src/ddl/cantik_robhdr.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'cantik_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW cantik_robhdr AS
+  SELECT seqno,
+         body.len,
+         obstype,
+         trlat
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/cantik_robody.sql b/odb/src/ddl/cantik_robody.sql
new file mode 100644
index 0000000..872eb4b
--- /dev/null
+++ b/odb/src/ddl/cantik_robody.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'cantik_robody.sql'
+//
+//   Last updated:  01-11-2000
+//
+
+READONLY;
+
+CREATE VIEW cantik_robody AS
+  SELECT seqno,
+         varno,
+         datum_rdbflag at body,
+         datum_anflag at body UPDATED,
+         vertco_reference_1
+  FROM   index, hdr, body
+;
diff --git a/odb/src/ddl/carcfo.sql b/odb/src/ddl/carcfo.sql
new file mode 100644
index 0000000..713abb2
--- /dev/null
+++ b/odb/src/ddl/carcfo.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'carcfo.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW carcfo AS
+  SELECT  varno READONLY,
+          vertco_reference_2,
+          mf_log_p
+  FROM    body
+;
diff --git a/odb/src/ddl/caredo_robhdr.sql b/odb/src/ddl/caredo_robhdr.sql
new file mode 100644
index 0000000..009bb23
--- /dev/null
+++ b/odb/src/ddl/caredo_robhdr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'caredo_robhdr.sql'
+//
+//   Last updated:  10-Aug-2009 / 25-Jan-2012
+//
+
+READONLY;
+
+CREATE VIEW caredo_robhdr AS
+  SELECT seqno,
+         body.len,
+         obstype,
+         codetype,
+         date,
+         time,
+         statid,
+         report_blacklist UPDATED,
+         lat,
+         lon
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/caredo_robody.sql b/odb/src/ddl/caredo_robody.sql
new file mode 100644
index 0000000..7ce741f
--- /dev/null
+++ b/odb/src/ddl/caredo_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'caredo_robody.sql'
+//
+//   Last updated:  10-Aug-2009
+//
+
+UPDATED;
+
+CREATE VIEW caredo_robody AS
+  SELECT seqno READONLY,
+         varno READONLY,
+         datum_anflag,
+  FROM   index, hdr, body
+;
diff --git a/odb/src/ddl/castor.sql b/odb/src/ddl/castor.sql
new file mode 100644
index 0000000..c12a130
--- /dev/null
+++ b/odb/src/ddl/castor.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'castor.sql'
+//
+//   Last updated:  09-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW castor AS
+  SELECT kset UPDATED, abnob UPDATED, mapomm UPDATED,   // updated
+     body.len,                       // r/o
+     obstype,                        // r/o
+     time, trlat,                    // r/o
+    FROM index, hdr
+;
diff --git a/odb/src/ddl/caviso_robhdr.sql b/odb/src/ddl/caviso_robhdr.sql
new file mode 100644
index 0000000..d348c35
--- /dev/null
+++ b/odb/src/ddl/caviso_robhdr.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'caviso_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW caviso_robhdr AS
+  SELECT seqno,
+         body.len,
+         codetype,
+         instrument_type,
+         retrtype,
+         obstype,
+         sortbox,
+         date,
+         time,
+         statid,
+         trlat,
+         lat,
+         lon,
+         stalt
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/caviso_robody.sql b/odb/src/ddl/caviso_robody.sql
new file mode 100644
index 0000000..5ed772e
--- /dev/null
+++ b/odb/src/ddl/caviso_robody.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'caviso_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW caviso_robody AS
+  SELECT seqno,
+         varno,
+         datum_rdbflag at body,
+         datum_anflag,
+         vertco_reference_1,
+         vertco_reference_2,
+         mf_log_p,
+         obsvalue,
+         an_depar,
+         fg_depar,
+         final_obs_error,
+         fg_error,
+         qc_a,
+         qc_l,
+         qc_pge,
+  FROM   index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/cavodk_robhdr.sql b/odb/src/ddl/cavodk_robhdr.sql
new file mode 100644
index 0000000..c9381a8
--- /dev/null
+++ b/odb/src/ddl/cavodk_robhdr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'cavodk_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW cavodk_robhdr AS
+  SELECT  seqno,
+          body.len,
+          obstype,
+          lon,
+          lat,
+          trlat,
+          orography,
+          lsm
+  FROM    index, hdr, modsurf
+;
diff --git a/odb/src/ddl/cavodk_robody.sql b/odb/src/ddl/cavodk_robody.sql
new file mode 100644
index 0000000..1abfa0d
--- /dev/null
+++ b/odb/src/ddl/cavodk_robody.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'cavodk_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW cavodk_robody AS
+  SELECT  seqno,
+          varno,
+          datum_anflag at body UPDATED,
+          vertco_reference_2,
+          obs_error,
+          repres_error,
+          fg_error,
+          fg_depar,
+          mf_log_p,
+          mf_stddev,
+         qc_l UPDATED
+  FROM    index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/cdrhook.h b/odb/src/ddl/cdrhook.h
new file mode 120000
index 0000000..4656498
--- /dev/null
+++ b/odb/src/ddl/cdrhook.h
@@ -0,0 +1 @@
+../include/cdrhook.h
\ No newline at end of file
diff --git a/odb/src/ddl/check_linksdb.sql b/odb/src/ddl/check_linksdb.sql
new file mode 100644
index 0000000..a7a75d7
--- /dev/null
+++ b/odb/src/ddl/check_linksdb.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'check_linksdb.sql'
+//
+//   Last updated:  20-Mar-2002
+//
+
+READONLY;
+
+CREATE VIEW check_linksdb AS
+  SELECT body, errstat, update[1:$nmxupd]
+    FROM hdr
+;
diff --git a/odb/src/ddl/cloud_sink.h b/odb/src/ddl/cloud_sink.h
new file mode 100644
index 0000000..1eb304d
--- /dev/null
+++ b/odb/src/ddl/cloud_sink.h
@@ -0,0 +1,15 @@
+//
+// Table Definition: cloud_sink tables
+//
+CREATE TABLE cloud_sink AS (
+// only created if LCLDSINK is TRUE
+  ctop[$NMXUPD]    pk9real,      // CTOP per NRESUPD
+  camt[$NMXUPD]    pk9real,      // Camt per NRESUPD
+  ctopbg           pk9real,      // CTOP BACKGROUND
+  ctoper           pk9real,      // CTOP BACKGROUND ERROR
+  ctopinc          pk9real,      // CTOP INCREMENT 
+  camtbg           pk9real,      // CAMT BACKGROUND
+  camter           pk9real,      // CAMT BACKGROUND ERROR
+  camtinc          pk9real,      // CAMT INCREMENT 
+);
+
diff --git a/odb/src/ddl/cma.h b/odb/src/ddl/cma.h
new file mode 100644
index 0000000..d0d78a2
--- /dev/null
+++ b/odb/src/ddl/cma.h
@@ -0,0 +1,226 @@
+//
+//  Data layout (schema) for CY37R3 : 
+//
+//   ECMA & CCMA table hierarchy:
+//
+//      1  desc
+//      2  +---> poolmask
+//      3  +---> timeslot_index
+//      4  |     +---> index
+//      5  |     |     +---> hdr
+//      6  |     |     |     +---> sat
+//      7  |     |     |     |     +---> radiance
+//      8  |     |     |     |     |     +---> allsky
+//      9  |     |     |     |     |           +---> allsky_body
+//     11  |     |     |     |     |     +---> cloud_sink
+//     12  |     |     |     |     |     +---> radiance_body
+//     14  |     |     |     |     |     +---> collocated_imager_information
+//     15  |     |     |     |     +---> resat
+//     16  |     |     |     |     |     +---> resat_averaging_kernel
+//     17  |     |     |     |     +---> gnssro
+//     18  |     |     |     |     |     +---> gnssro_body
+//     19  v     v     v     v     +---> satob
+//     20  |     |     |     |     +---> scatt
+//     21  |     |     |     |     |     +---> scatt_body
+//     22  |     |     |     |     +---> ssmi
+//     23  |     |     |     |     |     +---> ssmi_body
+//     24  |     |     |     |     +---> limb
+//     25  |     |     |     |     +---> aeolus_hdr
+//     26  |     |     |     |     |     +---> aeolus_auxmet
+//     27  |     |     |     |     |     +---> aeolus_l2c
+//     28  |     |     |     |     +---> radar_station
+//     29  |     |     |     |     +---> radar            
+//     30  |     |     |     |     |     +---> radar_body 
+//     31  |     |     !     !     +---> smos
+//     32  |     |     |     +---> body
+//     33  |     |     |     +---> auxiliary
+//     34  |     |     |     +---> errstat
+//     35  |     |     |     +---> update_1
+//     36  |     |     |     +---> update_2
+//     37  |     |     |     +---> update_3
+//
+// Variables
+//
+
+SET  $NMXUPD = 3; // Maximum number of updates supported with this layout (min = 1 & max = 10)
+
+#ifdef ODB_NMXENKF
+SET  $NMXENKF  = ODB_NMXENKF; // Maximum number of ensembles
+#endif
+
+#ifndef ODB_NMXENKF
+SET  $NMXENKF  = 120; // Maximum number of ensembles
+#endif
+
+#ifdef ODB_NMXENDA
+SET  $NMXENDA  = ODB_NMXENDA; // Maximum number of ensembles
+#endif
+
+#ifndef ODB_NMXENDA
+SET  $NMXENDA  = 100; // Maximum number of ensembles
+#endif
+
+SET  $NMXFCDIAG  = 20; // Maximum number of forecast diagnostics
+
+SET  $NUMAUX = 9; // No. of auxiliary obsvalue's per body; aux1 ==> aux[$NUMAUX]
+SET  $NUMTHBOX = 3; // No. of thinning boxes (see also ifs/module/yomdb.F90)
+SET  $NUMEV = 1;  // Maximum number of retained eigenvectors of obs. err. corr. matrix
+SET  $NUMDIAG = 1;  // Maximum number of retained diagnostics of obs. err. corr. matrix (must be the same as JP_NUMDIAG in yomdb.h)
+
+// Aligned tables (contain the same no. of rows when requested over the @LINK)
+RESET ALIGN;
+ALIGN(body,surfbody_feedback);
+ALIGN(body,errstat,update[1:$NMXUPD],fcdiagnostic_body[1:$NMXFCDIAG],conv_body, scatt_body,ssmi_body,gbrad_body, radar_body,resat_averaging_kernel, auxiliary_body, allsky_body, radiance_body, gnssro_body, raingg_body);
+ALIGN(body,enkf[1:$NMXENKF]);
+ALIGN(body,enda[1:$NMXENDA]);
+ALIGN(body,surfbody_feedback[1:$NMXENDA]);
+
+// @LINKs with maximum jump of one ("one-loopers")
+// Rows in these tables have one-to-one correspondence over the @LINK
+RESET ONELOOPER;
+ALIGN(hdr, fcdiagnostic);
+ONELOOPER(index,hdr);
+ONELOOPER(hdr, auxiliary);
+ONELOOPER(hdr, ensemble);
+ONELOOPER(hdr,sat);
+ONELOOPER(hdr,modsurf);
+ONELOOPER(hdr,gbrad);
+ONELOOPER(hdr,raingg);
+ONELOOPER(hdr,conv);
+ONELOOPER(sat,radiance,ssmi,scatt,satob,resat,limb,radar,radar_station,smos, gnssro, aeolus_hdr);
+ONELOOPER(radiance,allsky, cloud_sink, collocated_imager_information, surfemiss);
+
+// Define shared links (new option; not available through command line)
+// (these aren't working properly ... yet (as of 29/8/2001 SS)
+//SHAREDLINK(body,errstat,update[1:$NMXUPD]);
+
+#include "mdi.h"
+#include "obstype.h"
+#include "varno.h"
+#include "vertco_type.h"
+#include "ppcode.h"
+#include "sensor.h"
+
+SET  $BG = 1;
+SET  $ADJ = 2;
+
+//
+// Type definitions
+//
+
+#include "type_definitions.h"
+
+//
+// Table definitions 
+//
+
+CREATE TABLE desc AS (
+  expver string,     // MARS key - Experiment ID
+  class  pk1int,     // MARS key - ECMWF classification for data
+  stream pk1int,     // MARS key - forecasting system used to generate data
+  type   pk1int,     // MARS key - type of field used to retrieve data
+
+  andate YYYYMMDD,   // Analysis date 
+  antime HHMMSS,     // Analysis time
+
+  inidate YYYYMMDD, // The starting date for the whole assimilation period
+  initime HHMMSS,   // The starting time for the whole assimilation period 
+
+  creadate YYYYMMDD, // Creation date
+  creatime HHMMSS,   // Creation time
+  creaby   string,   // Created by whom (username)
+
+  moddate YYYYMMDD,  // Modification date
+  modtime HHMMSS,    // Modification time
+  modby   string,    // Modified by whom (username)
+
+  mxup_traj pk1int,  // max. no. of updates for this database (= $MXUP_TRAJ)
+  numtsl pk1int,     // total number of timeslots
+
+  poolmask @LINK,
+  timeslot_index @LINK,  
+  fcdiagnostic    @LINK,                    // table used to store forecast diagnostics (post-processing only)
+
+  latlon_rad pk1int, // ==1 if (lat,lon) is in radians, ==0 if in degrees 
+
+  // Ensemble Data Assimilation (enda)-setup
+  enda_member     pk1int, // enda-member number : 0=control, >0 member#
+
+);
+
+CREATE TABLE poolmask AS (
+  timeslot pk1int,                 // Timeslot number
+  obstype pk1int,                  // IFS Observation type
+  codetype pk1int,                 // IFS Codetype
+  sensor pk1int,                   // IFS Local Satellite Sensor (not necessarily WMO)
+  bufrtype pk1int,                 // WMO BUFR type
+  subtype pk1int,                  // WMO BUFR subtype
+  poolno pk1int,                   // Pool number
+  hdr_count pk1int,                // Number of reports
+  body_count pk1int,               // Number of datum
+  max_bodylen pk1int,              // Maximum number of datum
+);
+
+CREATE TABLE timeslot_index AS ( // More direct access to time slot data
+  timeslot pk1int,    // Timeslot number
+  model_timestep  pk1int,    // Model time step
+  enddate  YYYYMMDD,  // End date of the timeslot
+  endtime  HHMMSS,    // End time of the timeslot
+  index @LINK,
+);
+
+CREATE TABLE index AS (
+  target pk1int,      // Target pool number for CCMA
+  procid pk1int,      // Normally the same as pool number (in ECMA)
+  timeslot pk1int,    // Timeslot number
+  kset pk1int,        // kset as from ECSET
+  abnob pk1int,       // ECxxx-array pointer
+  mapomm pk1int,      // GOMxxx-array pointer 
+  maptovscv pk1int,   // TOVS control variable array pointer 
+  hdr @LINK,  
+);
+
+#include "hdr.h"
+#include "ensemble.h"
+#include "forecast_diagnostic.h"
+#include "gbrad.h"
+#include "raingg.h"
+#include "conv.h"
+
+#include "sat.h"
+
+#include "modsurf.h"
+#include "surfbody_feedback.h"
+
+#include "radiance.h"
+#include "allsky.h"
+#include "cloud_sink.h"
+#include "collocated_imager_information.h"
+#include "auxiliary.h"
+
+#include "resat.h"
+
+#include "gnssro.h"
+
+#include "satob.h"
+
+#include "scatt.h"
+
+#include "ssmi1d.h"
+
+#include "smos.h"
+
+#include "radar_station.h"
+
+#include "radar.h"
+
+#include "limb.h"
+
+#include "body.h"
+
+#include "errstat.h"
+
+#include "update.h"
+
+#include "aeolus.h"
+
diff --git a/odb/src/ddl/collocated_imager_information.h b/odb/src/ddl/collocated_imager_information.h
new file mode 100644
index 0000000..6ab3dd4
--- /dev/null
+++ b/odb/src/ddl/collocated_imager_information.h
@@ -0,0 +1,46 @@
+//
+// Table Definition: collocated_imager_information tables
+//
+// For collocated_imager_information only - these ODB attributes are not used in IFS (table not loaded) but
+// can be used to post-process IASI data
+//
+CREATE TABLE collocated_imager_information AS (
+  avhrr_mean_ir pk9real,               // Mean BT on channel Ir in FOV
+  avhrr_stddev_ir pk9real,             // Std. Dev. of BT on channel Ir in FOV
+  avhrr_stddev_ir2 pk9real,             // Std. Dev. of BT on channel Ir2 in FOV
+  avhrr_num_clusters pk9real,           // Number of clusters FOV
+
+  avhrr_mean_vis pk9real,               // Mean visible reflectance in FOV
+  avhrr_stddev_vis pk9real,             // Std. Dev. of visible reflectance in FOV
+  avhrr_max_cluster pk9real,            // Fractional size of the largest cluster
+  avhrr_coldest_cluster_ir pk9real,    // Mean Ir BT for the coldest cluster
+  avhrr_warmest_cluster_ir pk9real,    // Mean Ir BT for the warmest cluster
+  avhrr_largest_cluster_ir pk9real,    // Mean Ir BT for the largest cluster
+// For iasi only (filled in bufr)
+  provider_qc pk1int,                    // QC as determined by data provider
+  avhrr_frac_cl1 pk9real,               // Fractional size of cluster 1
+  avhrr_frac_cl2 pk9real,               // Fractional size of cluster 2
+  avhrr_frac_cl3 pk9real,               // Fractional size of cluster 3
+  avhrr_frac_cl4 pk9real,               // Fractional size of cluster 4
+  avhrr_frac_cl5 pk9real,               // Fractional size of cluster 5
+  avhrr_frac_cl6 pk9real,               // Fractional size of cluster 6
+  avhrr_frac_cl7 pk9real,               // Fractional size of cluster 7
+  avhrr_m_ir1_cl1 pk9real,              // Mean Ir1 BT in cluster 1
+  avhrr_m_ir1_cl2 pk9real,              // Mean Ir1 BT in cluster 2
+  avhrr_m_ir1_cl3 pk9real,              // Mean Ir1 BT in cluster 3
+  avhrr_m_ir1_cl4 pk9real,              // Mean Ir1 BT in cluster 4
+  avhrr_m_ir1_cl5 pk9real,              // Mean Ir1 BT in cluster 5
+  avhrr_m_ir1_cl6 pk9real,              // Mean Ir1 BT in cluster 6
+  avhrr_m_ir1_cl7 pk9real,              // Mean Ir1 BT in cluster 7
+  avhrr_m_ir2_cl1 pk9real,              // Mean Ir2 BT in cluster 1
+  avhrr_m_ir2_cl2 pk9real,              // Mean Ir2 BT in cluster 2
+  avhrr_m_ir2_cl3 pk9real,              // Mean Ir2 BT in cluster 3
+  avhrr_m_ir2_cl4 pk9real,              // Mean Ir2 BT in cluster 4
+  avhrr_m_ir2_cl5 pk9real,              // Mean Ir2 BT in cluster 5
+  avhrr_m_ir2_cl6 pk9real,              // Mean Ir2 BT in cluster 6
+  avhrr_m_ir2_cl7 pk9real,              // Mean Ir2 BT in cluster 7
+  avhrr_fg_ir1 pk9real,                 // First guess Ir1 BT
+  avhrr_fg_ir2 pk9real,                 // First guess Ir2 BT
+  avhrr_cloud_flag pk1int,              // AVHRR cloud flag (determined during screening)
+);
+
diff --git a/odb/src/ddl/conv.h b/odb/src/ddl/conv.h
new file mode 100644
index 0000000..b3bb259
--- /dev/null
+++ b/odb/src/ddl/conv.h
@@ -0,0 +1,23 @@
+//
+// Table Definitions: conv (header table)
+//
+CREATE TABLE conv AS (
+  flight_phase           pk1int,             // BUFR aircraft flight phase
+  flight_dp_o_dt         pk9real,            // aircraft flight dp/dt
+// should be movde from hdr to here... statid                 string,             // STATION ID (CHARACTER*8)
+  anemoht                pk9real,            // HEIGHT OF ANEMOMETER
+  baroht                 pk9real,            // HEIGHT OF BAROMETRE
+  station_type           pk1int,             // SYNOP/SHIPs (needed to find out if DRIBU)
+  sonde_type             pk1int,             // In order to do bias corr. of TEMPs
+  collection_identifier  pk1int,             // Identifier for a collection within a specific source        
+  country                pk1int,             // WMO State Identifier (Code Table 0 01 101). Used if statid is national id rather than WMO station id.
+  unique_identifier      pk1int,             // Unique record identifier for a given date and time and source : Reanalysis purpose
+  timeseries_index       pk1int,             // Index to uniquely identify data timeseries from station/ship/buoy/radiosonde/etc.: Reanalysis purpose
+  conv_body              @LINK,             
+);
+
+CREATE TABLE conv_body AS (
+  ppcode                pk1int,              // PRESSURE CODE
+  level                 LEVEL_t,             // PILOT LEVEL ID.
+  datum_qcflag          pk1int,              // quality flag coming from BUFR for windprofiler
+);
diff --git a/odb/src/ddl/conv_hdr.sql b/odb/src/ddl/conv_hdr.sql
new file mode 100644
index 0000000..ebae99a
--- /dev/null
+++ b/odb/src/ddl/conv_hdr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'conv_hdr.sql'
+//
+//   Last updated:  27-Mar-2011
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW conv_hdr AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         anemoht at conv,                 // r/o
+         flight_dp_o_dt,               // r/o
+  FROM   timeslot_index, index, hdr, conv
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/conv_update_links.sql b/odb/src/ddl/conv_update_links.sql
new file mode 100644
index 0000000..5bb9e4b
--- /dev/null
+++ b/odb/src/ddl/conv_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'conv_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW conv_update_links AS
+  SELECT "/LINK.*/"
+    FROM conv
+;
+
diff --git a/odb/src/ddl/conventional_robhdr_1.sql b/odb/src/ddl/conventional_robhdr_1.sql
new file mode 100644
index 0000000..123eda4
--- /dev/null
+++ b/odb/src/ddl/conventional_robhdr_1.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'conventional_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+SET $kobstype_v = 0; // Must be initialized to zero; used by in_vector()-function
+
+CREATE VIEW conventional_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len  READONLY,           // r/o
+         obstype,                      // r/o
+         codetype,                     // possibly updated (in ECMA)
+         instrument_type,              // possibly updated (in ECMA)
+         retrtype,                     // possibly updated (in ECMA)
+         areatype,                     // possibly updated (in ECMA)
+         report_rdbflag,               // possibly updated (in ECMA)
+         report_status,                // possibly updated (in ECMA)
+         report_event1,                // possibly updated (in ECMA)
+         report_event2,                // possibly updated (in ECMA)
+         date,                         // r/o
+         time,                         // r/o
+         sonde_type at conv,              // r/o
+         station_type at conv,            // r/o
+         lat, lon,                     // r/o
+         statid at hdr,                   // r/o
+         stalt,                        // r/o
+         anemoht at conv,                 // possibly updated (in ECMA)
+         baroht at conv,                  // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, conv
+//  WHERE  obstype IN ($synop, $airep, $dribu, $temp, $pilot, $paob)
+  WHERE  in_vector(obstype, $kobstype_v)
+    AND	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/conventional_robody_1.sql b/odb/src/ddl/conventional_robody_1.sql
new file mode 100644
index 0000000..a4e571f
--- /dev/null
+++ b/odb/src/ddl/conventional_robody_1.sql
@@ -0,0 +1,41 @@
+//
+//-- ODB/SQL file 'conventional_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+SET $kobstype_v = 0; // Must be initialized to zero; used by in_vector()-function
+
+CREATE VIEW conventional_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         level at conv_body,              // possibly updated
+         datum_event1,                 // possibly updated
+         datum_event2,                 // possibly updated
+         datum_status,                 // possibly updated
+         datum_anflag,                 // possibly updated
+         datum_rdbflag,                // possibly updated
+         ppcode at conv_body,             // r/o
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         datum_qcflag,                 // possibly updated 
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                         // possibly updated
+         qc_l,                         // possibly updated
+         qc_pge,                       // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+         biascorr,                     // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat, conv, conv_body
+//  WHERE  obstype IN ($synop, $airep, $dribu, $temp, $pilot, $paob)
+  WHERE  in_vector(obstype, $kobstype_v)
+    AND	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/count_orbit.sql b/odb/src/ddl/count_orbit.sql
new file mode 100644
index 0000000..b34040b
--- /dev/null
+++ b/odb/src/ddl/count_orbit.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'count_orbit.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+set satellite_identifier=-1;
+READONLY;
+CREATE VIEW count_orbit AS
+    SELECT distinct orbit,
+    FROM hdr,radiance,sat 
+    WHERE datastream=0 and satellite_identifier at sat=$satellite_identifier
+;
+
diff --git a/odb/src/ddl/count_scanpos.sql b/odb/src/ddl/count_scanpos.sql
new file mode 100644
index 0000000..899ba40
--- /dev/null
+++ b/odb/src/ddl/count_scanpos.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'count_scanpos.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+set satellite_identifier=-1;
+READONLY;
+CREATE VIEW count_scanpos AS
+    SELECT orbit,
+           time,
+           count(scanpos) 
+    FROM hdr,radiance,sat 
+    WHERE datastream=0 and satellite_identifier at sat=$satellite_identifier
+    order by orbit,time
+;
+
diff --git a/odb/src/ddl/countryrstrhbody.sql b/odb/src/ddl/countryrstrhbody.sql
new file mode 100644
index 0000000..9522036
--- /dev/null
+++ b/odb/src/ddl/countryrstrhbody.sql
@@ -0,0 +1,21 @@
+READONLY;
+CREATE VIEW countryrstrhbody AS
+SELECT seqno, press,
+//        1     2
+       T_B_m75_vs_all_mean, T_B_m75_75_vs_all_mean, T_B_75_225_vs_all_mean, T_B_225_vs_all_mean, T_B_all_mean,
+//        3                          4                        5                       6                  7
+       RH_B_m75_vs_all_mean, RH_B_m75_75_vs_all_mean, RH_B_75_225_vs_all_mean, RH_B_225_vs_all_mean, RH_B_all_mean,
+//        8                          9                       10                      11                 12 
+       T_B_m75_vs_night_mean, T_B_m75_75_vs_night_mean, T_B_75_225_vs_night_mean, T_B_225_vs_night_mean, T_B_night_mean,
+//       13                         14                       15                      16                 17
+       RH_B_m75_vs_night_mean, RH_B_m75_75_vs_night_mean, RH_B_75_225_vs_night_mean, RH_B_225_vs_night_mean, RH_B_night_mean,
+//       18                         19                       20                      21                 22 
+       T_B_m75_vs_day_mean, T_B_m75_75_vs_day_mean, T_B_75_225_vs_day_mean, T_B_225_vs_day_mean, T_B_day_mean,
+//       23                         24                       25                      26                 27
+       RH_B_m75_vs_day_mean, RH_B_m75_75_vs_day_mean, RH_B_75_225_vs_day_mean, RH_B_225_vs_day_mean, RH_B_day_mean
+//       28                         29                       30                      31                 32 
+FROM  hdr, body
+//WHERE
+//ORDERBY
+;
+
diff --git a/odb/src/ddl/countryrstrhhdr.sql b/odb/src/ddl/countryrstrhhdr.sql
new file mode 100644
index 0000000..5de8540
--- /dev/null
+++ b/odb/src/ddl/countryrstrhhdr.sql
@@ -0,0 +1,32 @@
+READONLY;
+CREATE VIEW countryrstrhhdr AS
+SELECT seqno, country_group_code,
+//       1           2
+       country_statid_from_i, country_statid_from_c, country_statid_to_i, country_statid_to_c,
+//              3                    4                     5                      6
+       country_lat_from, country_lat_to, country_lon_from, country_lon_to,
+//              7               8              9               10
+       country_name_1,  country_name_2,  country_name_3, country_name_4,
+//            11              12              13            14
+       country_name_5,  country_name_6,  country_name_7, country_name_8,
+//            15              16              17            18
+       country_name_with_lat_lon_1, country_name_with_lat_lon_2,
+//            19                              20 
+       country_name_with_lat_lon_3, country_name_with_lat_lon_4,
+//            21                             22
+       country_name_with_lat_lon_5, country_name_with_lat_lon_7,
+//            23                              24
+       country_name_with_lat_lon_6, country_name_with_lat_lon_8,
+//            25                              26
+       country_grouped_seqno,
+//            27
+       country_name_grouped_1, country_name_grouped_2, country_name_grouped_3, country_name_grouped_4,
+//            28                        29                    30                     31
+       country_name_grouped_5, country_name_grouped_6, country_name_grouped_7, country_name_grouped_8,
+//            32                        33                    34                     35
+       body.offset, body.len
+//        36           37
+FROM hdr
+//WHERE
+//ORDERBY
+;
diff --git a/odb/src/ddl/cycle_biasprep_robhdr.sql b/odb/src/ddl/cycle_biasprep_robhdr.sql
new file mode 100644
index 0000000..8b433cb
--- /dev/null
+++ b/odb/src/ddl/cycle_biasprep_robhdr.sql
@@ -0,0 +1,8 @@
+// add sat table to have satellite_identifier at sat
+CREATE VIEW cycle_biasprep_robhdr AS
+SELECT  
+   body.len,codetype, satellite_identifier at sat, sensor,         //  table hdr
+   date, time, lat, lon                      //  table hdr
+FROM  hdr, sat
+WHERE  (obstype = $satem)
+ AND   (codetype = $atovs)
diff --git a/odb/src/ddl/cycle_biasprep_robody.sql b/odb/src/ddl/cycle_biasprep_robody.sql
new file mode 100644
index 0000000..33e7956
--- /dev/null
+++ b/odb/src/ddl/cycle_biasprep_robody.sql
@@ -0,0 +1,6 @@
+CREATE VIEW cycle_biasprep_robody AS
+SELECT entryno,
+   varno, vertco_reference_1, obsvalue, biascorr, fg_depar, an_depar  //  table body
+FROM  index, hdr, body
+WHERE  (obstype = $satem)
+ AND   (codetype = $atovs)
diff --git a/odb/src/ddl/cycle_biasprep_sathdr.sql b/odb/src/ddl/cycle_biasprep_sathdr.sql
new file mode 100644
index 0000000..1287c44
--- /dev/null
+++ b/odb/src/ddl/cycle_biasprep_sathdr.sql
@@ -0,0 +1,6 @@
+CREATE VIEW cycle_biasprep_sathdr AS
+SELECT 
+   scanpos at radiance,                                           //  table radiance
+FROM  hdr, sat, radiance
+WHERE  (obstype = $satem)
+ AND   (codetype = $atovs)
diff --git a/odb/src/ddl/cycle_biasprep_satpred.sql b/odb/src/ddl/cycle_biasprep_satpred.sql
new file mode 100644
index 0000000..a3893f6
--- /dev/null
+++ b/odb/src/ddl/cycle_biasprep_satpred.sql
@@ -0,0 +1,16 @@
+CREATE VIEW cycle_biasprep_satpred AS
+SELECT
+   lsm,
+   orography,
+   snow_depth,
+   t2m,
+   albedo,
+   windspeed10m,
+   surface_class,
+   skintemper,
+   skintemp[1:($NMXUPD+1)],
+   cldptop_3,
+   cldne_3,
+FROM  hdr, sat, modsurf, radiance, radiance
+WHERE  (obstype = $satem)
+ AND   (codetype = $atovs)
diff --git a/odb/src/ddl/data_radar_station.sql b/odb/src/ddl/data_radar_station.sql
new file mode 100644
index 0000000..0c4f1f9
--- /dev/null
+++ b/odb/src/ddl/data_radar_station.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'data_radar_station.sql'
+//
+//   Last updated:  21-May-2008
+//
+
+READONLY;
+
+CREATE VIEW data_radar_station AS
+  SELECT DISTINCT *
+  FROM radar_station
+  ORDER BY ident
+;
diff --git a/odb/src/ddl/date_time.sql b/odb/src/ddl/date_time.sql
new file mode 100644
index 0000000..482c8ea
--- /dev/null
+++ b/odb/src/ddl/date_time.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'date_time.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+CREATE VIEW date_time AS
+  SELECT date, time  // All r/o
+    FROM hdr
+;
diff --git a/odb/src/ddl/dca.h b/odb/src/ddl/dca.h
new file mode 120000
index 0000000..c1c5561
--- /dev/null
+++ b/odb/src/ddl/dca.h
@@ -0,0 +1 @@
+../include/dca.h
\ No newline at end of file
diff --git a/odb/src/ddl/decis_convbody_1.sql b/odb/src/ddl/decis_convbody_1.sql
new file mode 100644
index 0000000..b3f269c
--- /dev/null
+++ b/odb/src/ddl/decis_convbody_1.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'decis_convbody_1.sql'
+//
+//   Last updated:  27-Mar-2011
+//
+
+READONLY; // .. except those marked with  UPDATED
+NOREORDER;
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_convbody_1 AS
+  SELECT level at conv_body,                        // r/o
+         ppcode at conv_body,                       // r/o
+  FROM   timeslot_index, index, hdr, conv, conv_body
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND (obstype = $synop OR obstype = $temp OR obstype = $pilot)
+    AND (conv.len > 0)
+;
diff --git a/odb/src/ddl/decis_convbody_2.sql b/odb/src/ddl/decis_convbody_2.sql
new file mode 100644
index 0000000..665b38e
--- /dev/null
+++ b/odb/src/ddl/decis_convbody_2.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'decis_convbody_1.sql'
+//
+//   Last updated:  27-Mar-2011
+//
+
+READONLY; // .. except those marked with  UPDATED
+NOREORDER;
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_convbody_2 AS
+  SELECT level at conv_body,              // r/o
+         ppcode at conv_body,             // r/o
+  FROM   timeslot_index, index, hdr, conv, conv_body
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND (obstype = $synop OR obstype = $temp OR obstype = $pilot)
+    AND (conv.len > 0)
+;
diff --git a/odb/src/ddl/decis_robhdr_1.sql b/odb/src/ddl/decis_robhdr_1.sql
new file mode 100644
index 0000000..41e9804
--- /dev/null
+++ b/odb/src/ddl/decis_robhdr_1.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'decis_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_robhdr_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     obstype,                  // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_rdbflag,                      // r/o
+         stalt,                        // r/o
+         trlat, trlon,                 // r/o
+         lat,lon,
+         orography,
+  FROM   timeslot_index, index, hdr, modsurf
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/decis_robhdr_2.sql b/odb/src/ddl/decis_robhdr_2.sql
new file mode 100644
index 0000000..f8d073c
--- /dev/null
+++ b/odb/src/ddl/decis_robhdr_2.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'decis_robhdr_2.sql'
+//
+//   Last updated: 27-Apr-2015
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         satellite_identifier,         // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         report_event1  UPDATED,       // possibly updated (in ECMA)
+         report_status  UPDATED,       // possibly updated (in ECMA)
+         report_rdbflag,               // r/o
+         sensor,                       // r/o
+         stalt  UPDATED,               // possibly updated (in ECMA)
+         lat, lon,                     // r/o
+         statid,                       // r/o
+  FROM   timeslot_index, index, hdr, sat
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
\ No newline at end of file
diff --git a/odb/src/ddl/decis_robhdr_3.sql b/odb/src/ddl/decis_robhdr_3.sql
new file mode 100644
index 0000000..db91e75
--- /dev/null
+++ b/odb/src/ddl/decis_robhdr_3.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'decis_robhdr_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $tslot = -1;
+
+CREATE VIEW decis_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         statid,                       // r/o
+         lat, lon,                     // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $airep)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/decis_robhdr_4.sql b/odb/src/ddl/decis_robhdr_4.sql
new file mode 100644
index 0000000..eff63c7
--- /dev/null
+++ b/odb/src/ddl/decis_robhdr_4.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'decis_robhdr_4.sql'
+//
+//   Last updated:  27-Apr-2015
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = -1;
+SET $tslot = -1;
+
+CREATE VIEW decis_robhdr_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+         report_event2 UPDATED,               // possibly updated (in ECMA)
+         report_status UPDATED,               // possibly updated (in ECMA)
+         codetype UPDATED,             // possibly updated (in ECMA)
+         instrument_type UPDATED,             // possibly updated (in ECMA)
+         retrtype UPDATED,             // possibly updated (in ECMA)
+         areatype UPDATED,             // possibly updated (in ECMA)
+         satellite_identifier,         // r/o
+         cellno,                       // r/o
+         prodflag,                     // r/o
+         wvc_qf,                       // r/o
+         nretr_amb,                    // r/o
+         lat, lon,
+  FROM   timeslot_index, index, hdr, sat, scatt
+  WHERE	 (obstype = $scatt)
+    AND  (kset = $kset OR $kset = -1)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
\ No newline at end of file
diff --git a/odb/src/ddl/decis_robody_1.sql b/odb/src/ddl/decis_robody_1.sql
new file mode 100644
index 0000000..dbdaa96
--- /dev/null
+++ b/odb/src/ddl/decis_robody_1.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'decis_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_robody_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         vertco_type,                  // r/o
+         varno,                        // r/o
+         vertco_reference_1  UPDATED,  // possibly updated (in ECMA)
+         obsvalue,                     // r/o
+         fg_depar,                     // r/o
+         pers_error,                   // r/o
+         final_obs_error  UPDATED,     // possibly updated (in ECMA)
+         obs_error  UPDATED,           // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/decis_robody_2.sql b/odb/src/ddl/decis_robody_2.sql
new file mode 100644
index 0000000..d9aa53f
--- /dev/null
+++ b/odb/src/ddl/decis_robody_2.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'decis_robody_2.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW decis_robody_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_anflag  UPDATED,              // possibly updated (in ECMA)
+         vertco_type,                  // r/o
+         varno,                        // r/o
+         datum_rdbflag at body,           // r/o
+         vertco_reference_1  UPDATED,  // possibly updated (in ECMA)
+         vertco_reference_2,           // r/o
+         obsvalue,                     // r/o
+         pers_error,                   // r/o
+         final_obs_error  UPDATED,     // possibly updated (in ECMA)
+         fg_error UPDATED,             // possibly updated (in ECMA)
+         obs_error  UPDATED,           // possibly updated (in ECMA)
+	 fg_depar UPDATED,             // possibly updated (in ECMA)
+	 biascorr UPDATED,             // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/decis_robody_3.sql b/odb/src/ddl/decis_robody_3.sql
new file mode 100644
index 0000000..5505272
--- /dev/null
+++ b/odb/src/ddl/decis_robody_3.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'decis_robody_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $tslot = -1;
+
+CREATE VIEW decis_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+         vertco_reference_1,                        // r/o
+         fg_depar,                     // r/o
+         fg_error,                     // r/o
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (obstype = $airep)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/decis_robody_4.sql b/odb/src/ddl/decis_robody_4.sql
new file mode 100644
index 0000000..a29ce74
--- /dev/null
+++ b/odb/src/ddl/decis_robody_4.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'decis_robody_4.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // .. except those marked with  UPDATED
+
+SET $kset = -1;
+SET $tslot = -1;
+
+CREATE VIEW decis_robody_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         varno,                        // r/o
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         invresid,                     // r/o
+         obsvalue,                     // r/o
+  FROM   timeslot_index, index, hdr, sat, scatt, body, scatt_body
+  WHERE	 (obstype = $scatt)
+    AND	 (kset = $kset OR $kset = -1)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/discard_dep_1.sql b/odb/src/ddl/discard_dep_1.sql
new file mode 100644
index 0000000..8f80c6d
--- /dev/null
+++ b/odb/src/ddl/discard_dep_1.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'discard_dep_1.sql'
+//
+//   Last updated:   28-Aug-2001
+//
+
+UPDATED;
+
+SET $tslot = -1;
+
+CREATE VIEW discard_dep_1 AS
+  SELECT hires,    // Updated
+	 lores,    // Updated
+  FROM   index, hdr, update[1] 
+  WHERE	 timeslot = $tslot OR $tslot = -1
+;
diff --git a/odb/src/ddl/discard_dep_2.sql b/odb/src/ddl/discard_dep_2.sql
new file mode 100644
index 0000000..91f8baa
--- /dev/null
+++ b/odb/src/ddl/discard_dep_2.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'discard_dep_2.sql'
+//
+//   Last updated:   28-Aug-2001
+//
+
+UPDATED;
+
+SET $tslot = -1;
+
+CREATE VIEW discard_dep_2 AS
+  SELECT hires,    // Updated
+	 lores,    // Updated
+  FROM   index, hdr, update[min(2,$nmxupd)] 
+  WHERE	 timeslot = $tslot OR $tslot = -1
+;
diff --git a/odb/src/ddl/dmsprainy.sql b/odb/src/ddl/dmsprainy.sql
new file mode 100644
index 0000000..778453d
--- /dev/null
+++ b/odb/src/ddl/dmsprainy.sql
@@ -0,0 +1,16 @@
+CREATE VIEW dmsprainy AS
+SELECT
+date, time, satellite_identifier at sat, lat, lon, typesurf at radiance,
+vertco_reference_1 at body,obsvalue, rad_fg_depar at ssmi_body, rad_an_depar at ssmi_body, rad_bias at ssmi_body,
+failure_1dvar, iterno_conv_1dvar,
+datum_status.active at body, datum_status.passive at body,
+datum_status.rejected at body, datum_status.blacklisted at body,
+datum_event1.rdb_rejected at body, datum_event1.datum_redundant at body,
+datum_event1.level_redundant at body,  datum_event1.duplicate at body,
+report_event1.redundant at hdr, datum_anflag.varqc at body, datum_anflag.fg at body, seqno
+FROM
+hdr, body, sat, radiance, ssmi, ssmi_body
+WHERE
+obstype at hdr=7 AND codetype=215 AND varno at body=119
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/ecma_body_4_psbias.sql b/odb/src/ddl/ecma_body_4_psbias.sql
new file mode 100644
index 0000000..b6d0f0b
--- /dev/null
+++ b/odb/src/ddl/ecma_body_4_psbias.sql
@@ -0,0 +1,20 @@
+READONLY;
+CREATE VIEW ecma_body_4_psbias AS
+SELECT seqno, body.len,
+//        1        2
+       varno, entryno, vertco_type,
+//       3        4         5
+       datum_anflag, datum_status at body, datum_rdbflag at body,
+//       6        7               8
+       datum_event1 at body, datum_event2 at body, ppcode at conv_body,
+//       9             10            11
+       vertco_reference_1, obsvalue, fg_depar, fg_error,
+//      12                   13        14         15
+       vertco_reference_2, an_depar, final_obs_error, obs_error, pers_error,
+//      16                   17        18               19        20
+       repres_error, biascorr, date, time
+//      21            22        23    24
+FROM  hdr, body, errstat, conv, conv_body
+WHERE obstype=1 OR obstype=4
+ORDERBY date, time
+;
diff --git a/odb/src/ddl/ecma_body_4_rstrhbias.sql b/odb/src/ddl/ecma_body_4_rstrhbias.sql
new file mode 100644
index 0000000..2893dbf
--- /dev/null
+++ b/odb/src/ddl/ecma_body_4_rstrhbias.sql
@@ -0,0 +1,18 @@
+READONLY;
+CREATE VIEW ecma_body_4_rstrhbias AS
+SELECT seqno, body.len,
+//        1        2
+       varno,
+//       3 
+       datum_anflag, datum_status at body,
+//       4        5
+       vertco_reference_1, obsvalue, fg_depar, an_depar,
+//       6       7         8         9 
+       biascorr, datum_event1 at body, datum_event2 at body
+//      10           11            12
+//     repres_error
+FROM  hdr, body
+//FROM  hdr, body
+WHERE obstype=5
+//ORDERBY date, time
+;
diff --git a/odb/src/ddl/ecma_hdr_4_psbias.sql b/odb/src/ddl/ecma_hdr_4_psbias.sql
new file mode 100644
index 0000000..61fd565
--- /dev/null
+++ b/odb/src/ddl/ecma_hdr_4_psbias.sql
@@ -0,0 +1,14 @@
+READONLY;
+CREATE VIEW ecma_hdr_4_psbias AS
+SELECT seqno, body.len,
+//        1       2
+       report_rdbflag at hdr, obstype, instrument_type, codetype, report_status at hdr, report_event1 at hdr,
+//        3         4        5           6        7           8
+       lat, lon, statid at hdr, time, date, source,
+//      9   10    11      12    13    14
+       stalt, orography, anemoht at conv, baroht at conv, numlev, subtype, bufrtype, station_type at conv
+//      15      16       17     18       19      20       21           22
+FROM hdr, modsurf, conv
+WHERE obstype=1 OR obstype=4
+ORDERBY date, time
+;
diff --git a/odb/src/ddl/ecma_hdr_4_rstrhbias.sql b/odb/src/ddl/ecma_hdr_4_rstrhbias.sql
new file mode 100644
index 0000000..901272d
--- /dev/null
+++ b/odb/src/ddl/ecma_hdr_4_rstrhbias.sql
@@ -0,0 +1,14 @@
+READONLY;
+CREATE VIEW ecma_hdr_4_rstrhbias AS
+SELECT seqno, body.len,
+//        1       2
+       obstype, codetype, bufrtype, subtype, report_status at hdr,
+//        3         4        5        6         7
+       lat, lon, statid at hdr, date, time,
+//      8    9    10      11    12
+       stalt, sonde_type at conv, report_rdbflag at hdr, report_event1 at hdr, report_event2 at hdr,
+//      13      14            15          16           17
+FROM hdr, conv
+WHERE obstype=5
+//ORDERBY date, time
+;
diff --git a/odb/src/ddl/ecmwf_matchup_allsky_body.sql b/odb/src/ddl/ecmwf_matchup_allsky_body.sql
new file mode 100644
index 0000000..70bc335
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_allsky_body.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_allsky_body.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $sensor = -1;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_allsky_body AS
+  SELECT seqno  READONLY,            // r/o
+         entryno  READONLY,          // r/o
+         datum_tbflag at allsky_body UPDATED         // mwave (all-sky) observations
+    FROM timeslot_index, index, hdr, body, allsky_body
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND obstype = $allsky
+     AND codetype = $ssmi
+     AND (($sensor == -1) OR (sensor == $sensor))
+     AND paral($pe, procid - $hdr_min + 1)
+;
+
diff --git a/odb/src/ddl/ecmwf_matchup_body.sql b/odb/src/ddl/ecmwf_matchup_body.sql
new file mode 100644
index 0000000..c9fe1d8
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_body.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_body.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_body AS
+  SELECT seqno  READONLY,            // r/o
+         entryno  READONLY,          // r/o
+         datum_anflag at body UPDATED,
+         datum_status at body UPDATED,
+         datum_event1 at body UPDATED,
+         an_sens_obs at body UPDATED,
+    FROM timeslot_index, index, hdr, body
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
+
diff --git a/odb/src/ddl/ecmwf_matchup_gbrad.sql b/odb/src/ddl/ecmwf_matchup_gbrad.sql
new file mode 100644
index 0000000..46610e5
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_gbrad.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_gbrad.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_gbrad AS
+  SELECT seqno  READONLY,      // r/o
+         report_rrflag,       // update
+    FROM timeslot_index, index, hdr, gbrad
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND obstype = $gbrad
+     AND codetype = $radrr
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecmwf_matchup_hdr.sql b/odb/src/ddl/ecmwf_matchup_hdr.sql
new file mode 100644
index 0000000..ccaaa52
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_hdr.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_hdr.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_hdr AS
+  SELECT seqno  READONLY,      // r/o
+         report_status,               // update
+         report_event1,               // update
+    FROM timeslot_index, index, hdr
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecmwf_matchup_raingg.sql b/odb/src/ddl/ecmwf_matchup_raingg.sql
new file mode 100644
index 0000000..7bc37b4
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_raingg.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_raingg.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_raingg AS
+  SELECT seqno  READONLY,      // r/o
+         report_rrflag,       // update
+    FROM timeslot_index, index, hdr, raingg
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND reportype >= $synop_rg6h AND reportype <= $synop_rg24h
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecmwf_matchup_update_1.sql b/odb/src/ddl/ecmwf_matchup_update_1.sql
new file mode 100644
index 0000000..4e35e2f
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_update_1.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_update_1.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_update_1 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[1]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe,procid - $hdr_min + 1) 
+;
diff --git a/odb/src/ddl/ecmwf_matchup_update_2.sql b/odb/src/ddl/ecmwf_matchup_update_2.sql
new file mode 100644
index 0000000..f4a4fbf
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_update_2.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_update_2.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_update_2 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(2,$nmxupd)]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecmwf_matchup_update_3.sql b/odb/src/ddl/ecmwf_matchup_update_3.sql
new file mode 100644
index 0000000..dbc30c4
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchup_update_3.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'ecmwf_matchup_update_3.sql'
+//
+//   updated     :  22-Jun-2005
+//   Last updated:  22-Apr-2009
+//   revert back to what we had in CY31R2 i.e.
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//   It was wrong from CY32R2
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW ecmwf_matchup_update_3 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(3,$nmxupd)]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecmwf_matchupsink.sql b/odb/src/ddl/ecmwf_matchupsink.sql
new file mode 100644
index 0000000..6232d02
--- /dev/null
+++ b/odb/src/ddl/ecmwf_matchupsink.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'ecmwf_matchupsink.sql'
+//
+//   updated     :  23-Nov-2007
+//   Last updated:  22-Apr-2009
+//   changed to
+//   paral($pe, procid - $hdr_min + 1)
+//   and NOT paral($pe, target - $hdr_min + 1)
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $sensor = -1;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+UPDATABLE;
+CREATE VIEW ecmwf_matchupsink AS
+  SELECT seqno  READONLY,        // r/o
+         skintemp[1:($NMXUPD+1)]@radiance,
+    FROM timeslot_index, index, hdr, sat, radiance
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND obstype = $satem
+     AND codetype = $atovs
+     AND (($sensor == -1) OR (sensor == $sensor))
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/ecset.sql b/odb/src/ddl/ecset.sql
new file mode 100644
index 0000000..bfa6ae1
--- /dev/null
+++ b/odb/src/ddl/ecset.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'ecset.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW ecset AS
+  SELECT seqno, // seqno for debugging purposes only
+         timeslot at index,
+	 obstype, codetype, instrument_type, retrtype, areatype,
+         reportype,
+         trlat,
+// get abnob & mapomm for debugging purposes only
+	 abnob, mapomm,
+	 body.len,
+         kset UPDATED,       // updated
+    FROM timeslot_index, index, hdr
+   WHERE ($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot)
+  ORDERBY timeslot at index, reportype, seqno
+;
diff --git a/odb/src/ddl/ecstdlib.h b/odb/src/ddl/ecstdlib.h
new file mode 120000
index 0000000..dff2199
--- /dev/null
+++ b/odb/src/ddl/ecstdlib.h
@@ -0,0 +1 @@
+../include/ecstdlib.h
\ No newline at end of file
diff --git a/odb/src/ddl/emiskf_amsua.sql b/odb/src/ddl/emiskf_amsua.sql
new file mode 100644
index 0000000..97201b8
--- /dev/null
+++ b/odb/src/ddl/emiskf_amsua.sql
@@ -0,0 +1,27 @@
+CREATE VIEW emiskf_amsua AS
+  SELECT
+    satellite_identifier at sat,
+    vertco_reference_1,
+    date,
+    time,
+    lldegrees(lon at hdr),
+    lldegrees(lat at hdr),
+    scanpos at radiance,
+    emis_retr,
+    zenith,
+    fg_depar,
+    sensor
+  FROM hdr,sat,radiance, body, modsurf, radiance_body
+  WHERE
+    sensor at hdr == 3
+    AND vertco_reference_1 at body == 3
+    AND emis_retr is not NULL
+    AND emis_retr >= 0.45 and emis_retr <= 1.0
+    AND fg_depar is not NULL
+    AND zenith is not NULL
+    AND datum_status.blacklisted at body == 1
+    AND datum_status.use_emiskf_only at body == 1
+    AND datum_event1.contam_cld_flag at body == 0
+    AND lsm > 0.8
+    AND datastream = 0
+;
diff --git a/odb/src/ddl/emiskf_amsub.sql b/odb/src/ddl/emiskf_amsub.sql
new file mode 100644
index 0000000..cbed988
--- /dev/null
+++ b/odb/src/ddl/emiskf_amsub.sql
@@ -0,0 +1,27 @@
+CREATE VIEW emiskf_amsub AS
+  SELECT
+    satellite_identifier at sat,
+    vertco_reference_1 at body,
+    date at hdr,
+    time at hdr,
+    lldegrees(lon at hdr),
+    lldegrees(lat at hdr),
+    scanpos at radiance,
+    emis_retr,
+    zenith,
+    fg_depar at body,
+    sensor
+  FROM hdr,sat,radiance, modsurf, body, radiance_body
+  WHERE
+    sensor == 4
+    AND vertco_reference_1 at body == 1
+    AND emis_retr is not NULL
+    AND emis_retr >= 0.45 and emis_retr <= 1.0
+    AND fg_depar is not NULL
+    AND zenith is not NULL
+    AND datum_status.blacklisted at body == 1
+    AND datum_status.use_emiskf_only at body == 1
+    AND datum_event1.contam_cld_flag at body == 0
+    AND lsm > 0.8
+    AND datastream = 0
+;
diff --git a/odb/src/ddl/emiskf_atms.sql b/odb/src/ddl/emiskf_atms.sql
new file mode 100644
index 0000000..e800123
--- /dev/null
+++ b/odb/src/ddl/emiskf_atms.sql
@@ -0,0 +1,27 @@
+CREATE VIEW emiskf_atms AS
+  SELECT
+    satellite_identifier at sat,
+    vertco_reference_1,
+    date,
+    time,
+    lldegrees(lon at hdr),
+    lldegrees(lat at hdr),
+    scanpos at radiance,
+    emis_retr,
+    zenith,
+    fg_depar,
+    sensor
+  FROM hdr,sat,radiance, body, modsurf, radiance_body
+  WHERE
+    sensor = 19
+    AND  vertco_reference_1 at body in (3,16)
+    AND emis_retr is not NULL
+    AND emis_retr >= 0.45 and emis_retr <= 1.0
+    AND fg_depar is not NULL
+    AND zenith is not NULL
+    AND datum_status.blacklisted at body == 1
+    AND datum_status.use_emiskf_only at body == 1
+    AND datum_event1.contam_cld_flag at body == 0
+    AND lsm > 0.8
+    AND datastream = 0
+;
diff --git a/odb/src/ddl/emiskf_mhs.sql b/odb/src/ddl/emiskf_mhs.sql
new file mode 100644
index 0000000..26042b2
--- /dev/null
+++ b/odb/src/ddl/emiskf_mhs.sql
@@ -0,0 +1,27 @@
+CREATE VIEW emiskf_mhs AS
+  SELECT
+    satellite_identifier at sat,
+    vertco_reference_1 at body,
+    date at hdr,
+    time at hdr,
+    lldegrees(lon at hdr),
+    lldegrees(lat at hdr),
+    scanpos at radiance,
+    emis_retr,
+    zenith,
+    fg_depar at body,
+    sensor
+  FROM hdr,sat,radiance, modsurf, body, radiance_body
+  WHERE
+    sensor == 15
+    AND vertco_reference_1 at body == 1
+    AND emis_retr is not NULL
+    AND emis_retr >= 0.45 and emis_retr <= 1.0
+    AND fg_depar is not NULL
+    AND zenith is not NULL
+    AND datum_status.blacklisted at body == 1
+    AND datum_status.use_emiskf_only at body == 1
+    AND datum_event1.contam_cld_flag at body == 0
+    AND lsm > 0.8
+    AND datastream = 0
+;
diff --git a/odb/src/ddl/emiskf_mwts2.sql b/odb/src/ddl/emiskf_mwts2.sql
new file mode 100644
index 0000000..a1f00ae
--- /dev/null
+++ b/odb/src/ddl/emiskf_mwts2.sql
@@ -0,0 +1,27 @@
+CREATE VIEW emiskf_mwts2 AS
+  SELECT
+    satellite_identifier at sat,
+    vertco_reference_1,
+    date,
+    time,
+    lldegrees(lon at hdr),
+    lldegrees(lat at hdr),
+    scanpos at radiance,
+    emis_retr,
+    zenith,
+    fg_depar,
+    sensor
+  FROM hdr,sat,radiance, body, modsurf, radiance_body
+  WHERE
+    sensor = 72
+    AND  vertco_reference_1 at body in (1)
+    AND emis_retr is not NULL
+    AND emis_retr >= 0.45 and emis_retr <= 1.0
+    AND fg_depar is not NULL
+    AND zenith is not NULL
+    AND datum_status.blacklisted at body == 1
+    AND datum_status.use_emiskf_only at body == 1
+    AND datum_event1.contam_cld_flag at body == 0
+    AND lsm > 0.8
+    AND datastream = 0
+;
diff --git a/odb/src/ddl/ensemble.h b/odb/src/ddl/ensemble.h
new file mode 100644
index 0000000..c6fd8fd
--- /dev/null
+++ b/odb/src/ddl/ensemble.h
@@ -0,0 +1,52 @@
+// Define up to $NMXENKF enkf-tables with
+// the naming convention enkf_1 enkf_2, ..., enkf_<$NMXENKF>.
+// Each of them has got exactly the same attributes.
+// Note: It is up to the software to decide how many of these tables will
+// actually be filled !!
+
+CREATE TABLE ensemble AS (
+ nensemble                            pk1int,   // Number of members active (<=$NMXENKF or <=$NMXENDA
+ enkf[1:$NMXENKF]                      @LINK,
+ enda[1:$NMXENDA]                      @LINK,       // one table for each member
+ surfbody_feedback[1:$NMXENDA]         @LINK,       // one table for each member
+);
+
+CREATE TABLE enkf[1:$NMXENKF] AS (
+  member          pk1int,             // enkf-member number
+  hprior          pk9real,            // H(x)
+);
+// Define up to $NMXENDA enda-tables with
+// the naming convention enda_1, enda_2, ..., enda_<$NMXENDA>.
+// Each of them has got exactly the same attributes.
+// Note: It is up to the software to decide how many of these tables will
+// actually be filled !!
+
+CREATE TABLE enda[1:$NMXENDA] AS (
+  member                pk1int,                      // enda-member number
+  report_status         STATUS_t,                    // REPORT'S STATUS
+  report_event1         REPORT_EVENT1_t,             // REPORT'S EVENTS (PART 1)
+  obsvalue              pk9real,                     // OBSERVED VARIABLE as used in IFS (may contain noise correction, etc.)
+  datum_anflag          DATUM_FLAG_t,                // OBSERVATION FLAGS
+  datum_status          TYPEOF(report_status at hdr),   // New feature; equivalent to old def : "status STATUS_t"
+  datum_event1          DATUM_EVENT1_t,              // OBSERVATION EVENTS (PART 1)
+  biascorr              pk9real,                     // RADIANCE BIAS CORRECTION
+  biascorr_fg           pk9real,                     // FG bias correction
+  an_depar              pk9real,                     // OBSERVED MINUS ANALYSED VALUE
+  fg_depar              pk9real,                     // OBSERVED MINUS FIRST GUESS VALUE
+  qc_pge                pk9real,                     // VAR QC a posteriori probability of gross error
+  final_obs_error       pk9real,                     // FINAL OBSERVATION ERROR (combination of Prescribed and persistence errors)
+  obs_error             pk9real,                     // Prescribed observation error
+  fg_error              pk9real,                     // FIRST GUESS ERROR
+  skintemp[$NMXUPD+1]   pk9real,                     // skin temperture per NRESUPD, 1 - FG, 2 - end of 1st min, 3 - end of 2nd min, etc
+);
+
+CREATE TABLE surfbody_feedback[1:$NMXENDA] AS (
+  datum_status          TYPEOF(report_status at hdr),   // New feature; equivalent to old def : "status STATUS_t"
+  datum_sfc_event       datum_sfc_event_t,           // OBSERVATION EVENTS FOR SURFACE ANALYSIS 
+  an_depar              pk9real,                     // OBSERVED MINUS ANALYSED VALUE
+  fg_depar              pk9real,                     // OBSERVED MINUS FIRST GUESS VALUE
+  snow_depth            pk9real,                     // model first-guess snow depth (m)
+  snow_density          pk9real,                     // model first-guess snow density 
+  lsm                   pk9real,                     // model land-sea mask
+);
+
diff --git a/odb/src/ddl/errstat.h b/odb/src/ddl/errstat.h
new file mode 100644
index 0000000..897c871
--- /dev/null
+++ b/odb/src/ddl/errstat.h
@@ -0,0 +1,18 @@
+// To be cleaned. 
+CREATE TABLE errstat AS (
+  final_obs_error pk9real,              // FINAL OBSERVATION ERROR (combination of Prescribed and persistence errors)
+  obs_error pk9real,                    // Prescribed observation error
+  repres_error pk9real,                 // REPRESENTATIVENESS ERROR
+  pers_error pk9real,                   // PERSISTENCE ERROR
+  fg_error pk9real,                     // FIRST GUESS ERROR
+  eda_spread pk9real,                   // SPREAD FROM EDA
+
+// very specific to resat... why everybody has it?
+  obs_ak_error pk9real,                 // OBSERVATION ERROR WITHOUT CONTRIBUTION FROM PROFILE ERROR
+
+  obs_corr_ev[$NUMEV] pk9real,          // OBS. ERR. CORRELATION EIGENVECTORS
+  obs_corr_mask pk1int,                 // OBS. ERROR CORRELATION MASK
+
+  obs_corr_diag[$NUMDIAG] pk9real,      // OBS. ERR. CORRELATION DIAGNOSTICS
+);
+
diff --git a/odb/src/ddl/exp_info_1.sql b/odb/src/ddl/exp_info_1.sql
new file mode 100644
index 0000000..ad793ab
--- /dev/null
+++ b/odb/src/ddl/exp_info_1.sql
@@ -0,0 +1,7 @@
+//
+// Created by Anne Fouilloux - 27/05/2010
+//
+CREATE VIEW exp_info_1 AS
+SELECT andate, antime, numtsl, mxup_traj
+FROM desc
+;
diff --git a/odb/src/ddl/fc_sens_obs.sql b/odb/src/ddl/fc_sens_obs.sql
new file mode 100644
index 0000000..ace08e4
--- /dev/null
+++ b/odb/src/ddl/fc_sens_obs.sql
@@ -0,0 +1,11 @@
+
+//-- ODB/SQL file 'fc_sens_obs.sql'
+//
+//   Last updated:  27-Apr-2010
+//
+
+CREATE VIEW fc_sens_obs AS
+  SELECT seqno, entryno, fc_sens_obs
+    FROM hdr,body
+    WHERE datum_status.passive at body=0
+;
diff --git a/odb/src/ddl/fcq_robhdr_0.sql b/odb/src/ddl/fcq_robhdr_0.sql
new file mode 100644
index 0000000..ae0075c
--- /dev/null
+++ b/odb/src/ddl/fcq_robhdr_0.sql
@@ -0,0 +1,13 @@
+READONLY;
+
+SET $obstype = 0;
+SET $codetype = 0;
+
+CREATE VIEW fcq_robhdr_0 AS
+SELECT  
+   body.len,
+   obstype, sitedep, bufrtype, stalt,           //  tables hdr integer
+   codetype, date, time, lat, lon, statid,       //  table hdr
+   report_status,
+FROM  index, hdr
+WHERE  (obstype = $obstype) AND (codetype = $codetype)
\ No newline at end of file
diff --git a/odb/src/ddl/fcq_robhdr_1.sql b/odb/src/ddl/fcq_robhdr_1.sql
new file mode 100644
index 0000000..a289619
--- /dev/null
+++ b/odb/src/ddl/fcq_robhdr_1.sql
@@ -0,0 +1,10 @@
+READONLY;
+
+CREATE VIEW fcq_robhdr_1 AS
+SELECT  
+   body.len,
+   obstype, sitedep, bufrtype, stalt,              //  tables hdr integer
+   codetype, date, time, lat, lon, statid         //  table hdr
+FROM  index, hdr
+WHERE  (obstype = $synop)
+ AND   ((codetype = 11) OR (codetype = 14))
diff --git a/odb/src/ddl/fcq_robhdr_2.sql b/odb/src/ddl/fcq_robhdr_2.sql
new file mode 100644
index 0000000..c298070
--- /dev/null
+++ b/odb/src/ddl/fcq_robhdr_2.sql
@@ -0,0 +1,10 @@
+READONLY;
+
+CREATE VIEW fcq_robhdr_2 AS
+SELECT  
+   body.len,
+   obstype, sitedep, bufrtype, stalt,         //  tables hdr integer
+   codetype, date, time, lat, lon, statid    //  table hdr
+FROM  index, hdr
+WHERE  (obstype = $synop)
+ AND   ((codetype = 21) OR (codetype = 24))
diff --git a/odb/src/ddl/fcq_robody_0.sql b/odb/src/ddl/fcq_robody_0.sql
new file mode 100644
index 0000000..12645df
--- /dev/null
+++ b/odb/src/ddl/fcq_robody_0.sql
@@ -0,0 +1,12 @@
+READONLY;
+
+SET $obstype = 0;
+SET $codetype = 0;
+
+CREATE VIEW fcq_robody_0 AS
+SELECT 
+   varno, datum_status at body, datum_event1 at body, datum_anflag,     //  table body
+   vertco_reference_1, vertco_reference_2, obsvalue, biascorr,
+   level,mf_vertco_type,
+FROM  index, hdr, conv, conv_body,body
+WHERE  (obstype = $obstype) AND (codetype = $codetype)
\ No newline at end of file
diff --git a/odb/src/ddl/fcq_robody_1.sql b/odb/src/ddl/fcq_robody_1.sql
new file mode 100644
index 0000000..7b20146
--- /dev/null
+++ b/odb/src/ddl/fcq_robody_1.sql
@@ -0,0 +1,9 @@
+READONLY;
+
+CREATE VIEW fcq_robody_1 AS
+SELECT 
+   varno, datum_status at body, datum_anflag,                    //  table body
+   vertco_reference_2, obsvalue, biascorr,
+FROM  index, hdr, body
+WHERE  (obstype = $synop)
+ AND   ((codetype = 11) OR (codetype = 14))
diff --git a/odb/src/ddl/fcq_robody_2.sql b/odb/src/ddl/fcq_robody_2.sql
new file mode 100644
index 0000000..3b58955
--- /dev/null
+++ b/odb/src/ddl/fcq_robody_2.sql
@@ -0,0 +1,9 @@
+READONLY;
+
+CREATE VIEW fcq_robody_2 AS
+SELECT 
+   varno, datum_status at body, datum_anflag,                    //  table body
+   vertco_reference_2, obsvalue, biascorr,
+FROM  index, hdr, body
+WHERE  (obstype = $synop)
+ AND   ((codetype = 21) OR (codetype = 24))
diff --git a/odb/src/ddl/fix_date_and_time.sql b/odb/src/ddl/fix_date_and_time.sql
new file mode 100644
index 0000000..bfc9d22
--- /dev/null
+++ b/odb/src/ddl/fix_date_and_time.sql
@@ -0,0 +1,9 @@
+// To fetch incorrect times (seconds at 60) for fixing
+
+UPDATED; // Note : NOT Read/Only !!
+
+CREATE VIEW fix_date_and_time AS
+  SELECT date, time
+    FROM hdr
+   WHERE mod(time,100) = 60
+;
diff --git a/odb/src/ddl/fixresatlen.sql b/odb/src/ddl/fixresatlen.sql
new file mode 100644
index 0000000..82a85b4
--- /dev/null
+++ b/odb/src/ddl/fixresatlen.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'fixresatlen.sql'
+//
+//   New:  07-Mar-2006
+//
+
+CREATE VIEW fixresatlen
+SELECT body.len, resat_averaging_kernel UPDATED // this fetches 3 columns: 1) body.len 
+                           //                         2) resat_averaging_kernel.offset at resat
+                           //                         3) resat_averaging_kernel.len at resat
+FROM hdr, sat, resat
+;
diff --git a/odb/src/ddl/flago_mobhdr.sql b/odb/src/ddl/flago_mobhdr.sql
new file mode 100644
index 0000000..5fe26f9
--- /dev/null
+++ b/odb/src/ddl/flago_mobhdr.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'flago_mobhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW flago_mobhdr AS
+SELECT
+   seqno,
+   abnob, mapomm,
+   body.len,
+   report_event1 UPDATED, report_blacklist UPDATED
+FROM index, hdr
diff --git a/odb/src/ddl/flago_mobody.sql b/odb/src/ddl/flago_mobody.sql
new file mode 100644
index 0000000..ddd0a87
--- /dev/null
+++ b/odb/src/ddl/flago_mobody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'flago_mobody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW flago_mobody AS
+SELECT
+   seqno READONLY,
+   entryno READONLY,
+   datum_anflag,datum_status at body, datum_event1 at body, datum_blacklist at body   
+FROM hdr, body
diff --git a/odb/src/ddl/forecast_diagnostic.h b/odb/src/ddl/forecast_diagnostic.h
new file mode 100644
index 0000000..c8be4bd
--- /dev/null
+++ b/odb/src/ddl/forecast_diagnostic.h
@@ -0,0 +1,17 @@
+// Define forecast_diagnostic table
+// Define up to $NMXFDIAG forecast_diagnostic-tables with
+// the naming convention forecast_diagnostic_1 forecast_diagnostic_2, ..., forecast_diagnostic_<$NMXFDIAG>.
+// Each of them has got exactly the same attributes.
+// Note: It is up to the software to decide how many of these tables will
+// actually be filled !!
+
+
+CREATE TABLE fcdiagnostic AS (
+  max_fcdiag        pk1int,               // number of forecast diagnostic valid for this experiment 
+  fcdiagnostic_body[$NMXFCDIAG] @LINK,     // one table for each forecast departure to run in //
+);
+
+CREATE TABLE fcdiagnostic_body[1:$NMXFCDIAG] AS (
+  fc_depar          pk9real,            // forecast departure
+  fc_step           YYYYMMDD,            // Corresponding forecast step
+);
diff --git a/odb/src/ddl/funcs.h b/odb/src/ddl/funcs.h
new file mode 120000
index 0000000..e02a4cd
--- /dev/null
+++ b/odb/src/ddl/funcs.h
@@ -0,0 +1 @@
+../include/funcs.h
\ No newline at end of file
diff --git a/odb/src/ddl/gather4poolmask.sql b/odb/src/ddl/gather4poolmask.sql
new file mode 100644
index 0000000..d230baa
--- /dev/null
+++ b/odb/src/ddl/gather4poolmask.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'gather4poolmask.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+CREATE VIEW gather4poolmask AS
+  SELECT DISTINCT timeslot at index, obstype, codetype, sensor
+                 ,bufrtype, subtype
+    FROM index, hdr
+ ORDERBY timeslot at index, obstype, codetype, sensor
+        ,bufrtype, subtype
+;
diff --git a/odb/src/ddl/gather4poolmask_counts.sql b/odb/src/ddl/gather4poolmask_counts.sql
new file mode 100644
index 0000000..5398857
--- /dev/null
+++ b/odb/src/ddl/gather4poolmask_counts.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'gather4poolmask_counts.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+CREATE VIEW gather4poolmask_counts AS
+   SELECT timeslot, obstype, codetype, sensor
+         ,bufrtype, subtype
+  	 ,body.len
+     FROM index, hdr
+  ORDERBY timeslot, obstype, codetype, sensor
+         ,bufrtype, subtype
+;
diff --git a/odb/src/ddl/gbrad.h b/odb/src/ddl/gbrad.h
new file mode 100644
index 0000000..7d26855
--- /dev/null
+++ b/odb/src/ddl/gbrad.h
@@ -0,0 +1,14 @@
+//
+// Table Definition: gbrad tables
+//
+CREATE TABLE gbrad AS (
+  report_rrflag           pk1int,       // Rain Rate status flag - See yomgbrad.F90
+  gbrad_body              @LINK,
+);
+
+CREATE TABLE gbrad_body AS (
+  rrvalue                 pk9real,       // Simulated rain rates
+  rrvaluetl               pk9real,       // Simulated TL of rain rates
+  rrvaluead               pk9real,       // Simulated AD of rain rates
+);
+
diff --git a/odb/src/ddl/gbrad_body_rr.sql b/odb/src/ddl/gbrad_body_rr.sql
new file mode 100644
index 0000000..4013827
--- /dev/null
+++ b/odb/src/ddl/gbrad_body_rr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'gbrad_body_rr.sql'
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW gbrad_body_rr AS
+
+  SELECT seqno  READONLY,         // MDBONM (used to build MLNKH2B)
+         rrvalue at gbrad_body,      // MDB_RRVALUE    gbrad_body
+         rrvaluetl at gbrad_body,    // MDB_RRVALUETL  gbrad_body
+         rrvaluead at gbrad_body,    // MDB_RRVALUEAD  gbrad_body
+
+  FROM   timeslot_index, index, hdr, gbrad_body
+
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+          AND kset = $kset 
+          AND obstype == 14 AND codetype == 3
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/gbrad_rr.sql b/odb/src/ddl/gbrad_rr.sql
new file mode 100644
index 0000000..2dc43fe
--- /dev/null
+++ b/odb/src/ddl/gbrad_rr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'gbrad_rr.sql'
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW gbrad_rr AS
+  SELECT seqno,                   // MDBONM (must be the first index; used to build MLNKH2B)
+         report_rrflag at gbrad,     // MDB_REPORT_RRFLAG  gbrad
+
+  FROM   timeslot_index, index, hdr, gbrad
+
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset 
+     AND obstype == 14 AND codetype == 3 
+ ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/gbrad_update_links.sql b/odb/src/ddl/gbrad_update_links.sql
new file mode 100644
index 0000000..6f302eb
--- /dev/null
+++ b/odb/src/ddl/gbrad_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'gbrad_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW gbrad_update_links AS
+  SELECT "/LINK.*/"
+    FROM gbrad
+;
+
diff --git a/odb/src/ddl/get_soe_resat.sql b/odb/src/ddl/get_soe_resat.sql
new file mode 100644
index 0000000..4f7326d
--- /dev/null
+++ b/odb/src/ddl/get_soe_resat.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'get_soe_resat.sql'
+//
+//   Last updated:  11-Oct-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW get_soe_resat AS
+  SELECT seqno  READONLY,        // r/o; MUST COME FIRST
+         solar_elevation,        // r/o
+         methane_correction UPDATED,        // r/o
+         surface_height,        // r/o
+         retrtype,
+         cloud_top_press UPDATED,
+  FROM   timeslot_index, index, hdr, sat, resat
+  WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND kset = $kset
+    AND obstype = $satem AND codetype = $resat
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/getairepid.sql b/odb/src/ddl/getairepid.sql
new file mode 100644
index 0000000..838af3f
--- /dev/null
+++ b/odb/src/ddl/getairepid.sql
@@ -0,0 +1,17 @@
+//
+//-- ODB/SQL file 'getairepid.sql'
+//
+//   Last updated:  11-Jan-2016
+
+//
+
+READONLY;
+
+CREATE VIEW getairepid AS
+     SELECT DISTINCT statid at hdr, codetype
+      FROM hdr, body
+      WHERE obstype==$airep and codetype IN (144, 145, 146, 148, 149) and
+            varno==$t and obsvalue IS NOT NULL
+      ORDERBY codetype, statid at hdr
+;
+
diff --git a/odb/src/ddl/getgbradid.sql b/odb/src/ddl/getgbradid.sql
new file mode 100644
index 0000000..2aa8d45
--- /dev/null
+++ b/odb/src/ddl/getgbradid.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'getgbradid.sql'
+//
+//   Last updated:  27-Sep-2010
+//
+
+READONLY;
+
+CREATE VIEW getgbradid AS
+     SELECT DISTINCT subtype at hdr, codetype, source at hdr
+       FROM hdr
+      WHERE obstype = $gbrad
+      ORDERBY subtype at hdr, codetype
+;
diff --git a/odb/src/ddl/getlimbid.sql b/odb/src/ddl/getlimbid.sql
new file mode 100644
index 0000000..fb208aa
--- /dev/null
+++ b/odb/src/ddl/getlimbid.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'getlimbid.sql'
+//
+//   Last updated:  30-Jun-2005
+//
+
+READONLY;
+
+CREATE VIEW getlimbid AS
+     SELECT DISTINCT satellite_identifier at sat, codetype, sensor
+       FROM hdr, sat
+      WHERE obstype = $limb
+      ORDERBY satellite_identifier at sat, codetype, sensor
+;
diff --git a/odb/src/ddl/getsatid.sql b/odb/src/ddl/getsatid.sql
new file mode 100644
index 0000000..edcca5a
--- /dev/null
+++ b/odb/src/ddl/getsatid.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'getsatid.sql'
+//
+//   Last updated:  30-Jun-2005
+//
+
+READONLY;
+
+CREATE VIEW getsatid AS
+     SELECT DISTINCT satellite_identifier at sat, codetype, retrtype, sensor
+       FROM hdr, sat
+      WHERE ((obstype = $satem) OR (obstype = $allsky))
+      ORDERBY satellite_identifier at sat, codetype, retrtype, sensor
+;
diff --git a/odb/src/ddl/getsatid_resat.sql b/odb/src/ddl/getsatid_resat.sql
new file mode 100644
index 0000000..793722f
--- /dev/null
+++ b/odb/src/ddl/getsatid_resat.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'getsatid_resat.sql'
+//
+//   Last updated:  20-Feb-2009
+//
+
+READONLY;
+
+CREATE VIEW getsatid_resat AS
+     SELECT DISTINCT satellite_identifier at sat, product_type at resat, retrtype, sensor, varno
+       FROM hdr, sat, resat, body
+      WHERE codetype = $resat
+      ORDERBY satellite_identifier at sat, product_type at resat, retrtype, sensor, varno
+;
diff --git a/odb/src/ddl/getsatobid.sql b/odb/src/ddl/getsatobid.sql
new file mode 100644
index 0000000..a24d88c
--- /dev/null
+++ b/odb/src/ddl/getsatobid.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'getsatobid.sql'
+//
+//   Last updated:  30-Jun-2005
+//
+
+READONLY;
+
+CREATE VIEW getsatobid AS
+     SELECT DISTINCT
+            satellite_identifier at sat,
+            codetype,
+            comp_method
+       FROM hdr, sat, satob
+      WHERE obstype = $satob
+    ORDERBY satellite_identifier at sat, 
+            codetype,   
+            comp_method
+;
diff --git a/odb/src/ddl/getsfcobsid.sql b/odb/src/ddl/getsfcobsid.sql
new file mode 100644
index 0000000..49b3579
--- /dev/null
+++ b/odb/src/ddl/getsfcobsid.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'getsfcobsid.sql'
+//
+//   Last updated:  30-Jul-2010
+//
+
+READONLY;
+
+CREATE VIEW getsfcobsid AS
+      SELECT DISTINCT reportype, statid, stalt, varno, ppcode at conv_body
+      FROM timeslot_index, index, hdr, body, conv, conv_body
+      WHERE obstype in ($synop,$dribu,$paob) and varno in ($ps,$apdss) and obsvalue at body is not null
+;
+
+// Notes:
+// 1. if the elements in the SELECT are changed, remember to update varbc_sfcobs.F90
+// 2. if the list of varno in the WHERE are changed, remember to update
+//        hdepart.F90, hretr.F90, hop.F90, hoptl.F90, and hopad.F90
+
diff --git a/odb/src/ddl/global_enkf_1.sql b/odb/src/ddl/global_enkf_1.sql
new file mode 100644
index 0000000..ba3091b
--- /dev/null
+++ b/odb/src/ddl/global_enkf_1.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_1.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_1 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,1)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,1)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_10.sql b/odb/src/ddl/global_enkf_10.sql
new file mode 100644
index 0000000..df37bf8
--- /dev/null
+++ b/odb/src/ddl/global_enkf_10.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_10.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_10 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,10)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,10)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_100.sql b/odb/src/ddl/global_enkf_100.sql
new file mode 100644
index 0000000..68e463f
--- /dev/null
+++ b/odb/src/ddl/global_enkf_100.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_100.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_100 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,100)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,100)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_105.sql b/odb/src/ddl/global_enkf_105.sql
new file mode 100644
index 0000000..8e5a816
--- /dev/null
+++ b/odb/src/ddl/global_enkf_105.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_105.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_105 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,105)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,105)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_110.sql b/odb/src/ddl/global_enkf_110.sql
new file mode 100644
index 0000000..5a0a5f7
--- /dev/null
+++ b/odb/src/ddl/global_enkf_110.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_110.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_110 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,110)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,110)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_115.sql b/odb/src/ddl/global_enkf_115.sql
new file mode 100644
index 0000000..5b1ce6f
--- /dev/null
+++ b/odb/src/ddl/global_enkf_115.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_115.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_115 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,115)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,115)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_120.sql b/odb/src/ddl/global_enkf_120.sql
new file mode 100644
index 0000000..fa65a4c
--- /dev/null
+++ b/odb/src/ddl/global_enkf_120.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_120.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_120 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,120)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,120)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_15.sql b/odb/src/ddl/global_enkf_15.sql
new file mode 100644
index 0000000..ab71eac
--- /dev/null
+++ b/odb/src/ddl/global_enkf_15.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_15.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_15 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,15)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,15)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_2.sql b/odb/src/ddl/global_enkf_2.sql
new file mode 100644
index 0000000..a86db29
--- /dev/null
+++ b/odb/src/ddl/global_enkf_2.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_2.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_2 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,2)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,2)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_20.sql b/odb/src/ddl/global_enkf_20.sql
new file mode 100644
index 0000000..ef50176
--- /dev/null
+++ b/odb/src/ddl/global_enkf_20.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_20.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_20 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,20)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,20)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_25.sql b/odb/src/ddl/global_enkf_25.sql
new file mode 100644
index 0000000..435aea2
--- /dev/null
+++ b/odb/src/ddl/global_enkf_25.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_25.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_25 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,25)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,25)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_3.sql b/odb/src/ddl/global_enkf_3.sql
new file mode 100644
index 0000000..5462d33
--- /dev/null
+++ b/odb/src/ddl/global_enkf_3.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_3.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_3 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,3)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,3)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_30.sql b/odb/src/ddl/global_enkf_30.sql
new file mode 100644
index 0000000..3dd38ce
--- /dev/null
+++ b/odb/src/ddl/global_enkf_30.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_30.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_30 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,30)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,30)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_35.sql b/odb/src/ddl/global_enkf_35.sql
new file mode 100644
index 0000000..70ab26b
--- /dev/null
+++ b/odb/src/ddl/global_enkf_35.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_35.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_35 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,35)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,35)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_4.sql b/odb/src/ddl/global_enkf_4.sql
new file mode 100644
index 0000000..a26113d
--- /dev/null
+++ b/odb/src/ddl/global_enkf_4.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_4.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_4 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,4)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,4)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_40.sql b/odb/src/ddl/global_enkf_40.sql
new file mode 100644
index 0000000..a7809a1
--- /dev/null
+++ b/odb/src/ddl/global_enkf_40.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_40.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_40 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,40)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,40)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_45.sql b/odb/src/ddl/global_enkf_45.sql
new file mode 100644
index 0000000..7a60e3c
--- /dev/null
+++ b/odb/src/ddl/global_enkf_45.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_45.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_45 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,45)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,45)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_5.sql b/odb/src/ddl/global_enkf_5.sql
new file mode 100644
index 0000000..30a3c79
--- /dev/null
+++ b/odb/src/ddl/global_enkf_5.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_5.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_5 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,5)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,5)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_50.sql b/odb/src/ddl/global_enkf_50.sql
new file mode 100644
index 0000000..b1e65b6
--- /dev/null
+++ b/odb/src/ddl/global_enkf_50.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_50.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_50 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,50)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,50)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_55.sql b/odb/src/ddl/global_enkf_55.sql
new file mode 100644
index 0000000..d621188
--- /dev/null
+++ b/odb/src/ddl/global_enkf_55.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_55.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_55 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,55)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,55)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_60.sql b/odb/src/ddl/global_enkf_60.sql
new file mode 100644
index 0000000..280b787
--- /dev/null
+++ b/odb/src/ddl/global_enkf_60.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_60.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_60 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,60)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,60)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_65.sql b/odb/src/ddl/global_enkf_65.sql
new file mode 100644
index 0000000..26a9cdc
--- /dev/null
+++ b/odb/src/ddl/global_enkf_65.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_65.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_65 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,65)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,65)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_70.sql b/odb/src/ddl/global_enkf_70.sql
new file mode 100644
index 0000000..8279fed
--- /dev/null
+++ b/odb/src/ddl/global_enkf_70.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_70.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_70 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,70)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,70)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_75.sql b/odb/src/ddl/global_enkf_75.sql
new file mode 100644
index 0000000..f963795
--- /dev/null
+++ b/odb/src/ddl/global_enkf_75.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_75.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_75 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,75)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,75)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_80.sql b/odb/src/ddl/global_enkf_80.sql
new file mode 100644
index 0000000..6069e93
--- /dev/null
+++ b/odb/src/ddl/global_enkf_80.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_80.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_80 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,80)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,80)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_85.sql b/odb/src/ddl/global_enkf_85.sql
new file mode 100644
index 0000000..9384a3a
--- /dev/null
+++ b/odb/src/ddl/global_enkf_85.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_85.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_85 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,85)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,85)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_90.sql b/odb/src/ddl/global_enkf_90.sql
new file mode 100644
index 0000000..4cbdadf
--- /dev/null
+++ b/odb/src/ddl/global_enkf_90.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_90.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_90 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,90)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,90)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/global_enkf_95.sql b/odb/src/ddl/global_enkf_95.sql
new file mode 100644
index 0000000..72201cd
--- /dev/null
+++ b/odb/src/ddl/global_enkf_95.sql
@@ -0,0 +1,45 @@
+//
+//-- ODB/SQL file 'global_enkf_95.sql'
+//
+//   Last updated:  
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW global_enkf_95 AS
+  SELECT
+    lat,
+    lon,
+    date,
+    time,
+    obstype,
+    codetype,
+    reportype,
+    varno,
+    seqno,
+    vertco_reference_1,
+    vertco_reference_2,
+    stalt,
+    orography,
+    fg_depar,
+    an_depar  UPDATED,
+    biascorr_fg,
+    biascorr,
+    obs_error,
+    final_obs_error,
+    qc_a,
+    qc_l,
+    qc_pge  UPDATED,
+    datum_anflag   UPDATED,
+    datum_status   UPDATED,
+    datum_event1   UPDATED,
+    obsvalue,
+    jacobian_peak,
+    jacobian_hpeak,
+    satellite_identifier,
+    sensor,
+    hprior at enkf[1:min($NMXENKF,95)],
+   FROM hdr,body,sat,errstat,modsurf,ensemble, enkf[1:min($NMXENKF,95)]
+   WHERE datum_status = 1
+;
+
diff --git a/odb/src/ddl/gnssro.h b/odb/src/ddl/gnssro.h
new file mode 100644
index 0000000..cd717a3
--- /dev/null
+++ b/odb/src/ddl/gnssro.h
@@ -0,0 +1,24 @@
+//
+// Table Definitions: gnssro (header-like table)
+//
+CREATE TABLE gnssro AS (
+
+// GNSSRO
+  radcurv                            pk9real,        // RADIUS OF CURVATURE 
+  undulation                         pk9real,        // UNDULATION AT OBS LOCATION  
+  gnssro_body                        @LINK,  
+);
+
+// Filled by Meteo-France only
+CREATE TABLE gnssro_body AS (
+// GNSSRO
+  obs_dndz              pk9real,                     // Vertical gradient of refractivity (dN/Dz in m-1) from the observation
+  obs_refractivity      pk9real,                     // Refractivity observation
+  bg_dndz               pk9real,                     // Vertical gradient of refractivity (dN/Dz in m-1) from the background
+  bg_refractivity       pk9real,                     // Refractivity from the background
+  bg_layerno            pk9real,                     // Background layer number in which the observation is found (1=layer
+                                                     // immediately above the surface
+  obs_tvalue            pk9real,                     // observed temperature
+  obs_zvalue            pk9real,                     // observed geopotential height
+  bg_tvalue             pk9real,                     // background temperature
+);
diff --git a/odb/src/ddl/gnssro_update_links.sql b/odb/src/ddl/gnssro_update_links.sql
new file mode 100644
index 0000000..66dff8d
--- /dev/null
+++ b/odb/src/ddl/gnssro_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'gnssro_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW gnssro_update_links AS
+  SELECT "/LINK.*/"
+    FROM gnssro
+;
+
diff --git a/odb/src/ddl/gpsro.sql b/odb/src/ddl/gpsro.sql
new file mode 100644
index 0000000..74e0b89
--- /dev/null
+++ b/odb/src/ddl/gpsro.sql
@@ -0,0 +1,11 @@
+CREATE VIEW gpsro AS
+SELECT 
+lat, lon, body.len, time, date, 
+vertco_reference_1, obsvalue, fg_depar, an_depar, seqno
+FROM
+hdr, body, sat
+WHERE
+obstype=$limb
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/gpsro_2.sql b/odb/src/ddl/gpsro_2.sql
new file mode 100644
index 0000000..d78b1c9
--- /dev/null
+++ b/odb/src/ddl/gpsro_2.sql
@@ -0,0 +1,15 @@
+CREATE VIEW gpsro_2 AS
+SELECT
+date, time, satellite_identifier at sat, lat, lon, retrtype, radcurv at gnssro,
+vertco_reference_1 at body, obsvalue, fg_depar, an_depar, final_obs_error, biascorr,
+datum_status.active at body, datum_status.passive at body,
+datum_status.rejected at body, datum_status.blacklisted at body,
+datum_event1.rdb_rejected at body, datum_event1.datum_redundant at body,
+datum_event1.level_redundant at body,  datum_event1.duplicate at body,
+report_event1.redundant at hdr, datum_anflag.varqc at body, datum_anflag.fg at body, seqno
+FROM
+index, hdr, body, errstat, sat, gnssro
+WHERE
+obsvalue is not NULL
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/gpsro_flag.sql b/odb/src/ddl/gpsro_flag.sql
new file mode 100644
index 0000000..ee3cb7e
--- /dev/null
+++ b/odb/src/ddl/gpsro_flag.sql
@@ -0,0 +1,14 @@
+CREATE VIEW gpsro_flag AS
+SELECT  datum_status.active at body,       datum_status.passive at body,
+        datum_status.rejected at body,     datum_status.blacklisted at body,
+        datum_event1.rdb_rejected at body,     datum_event1.datum_redundant at body,
+        datum_event1.level_redundant at body,  datum_event1.duplicate at body,
+        report_event1.redundant at hdr,
+	datum_anflag.varqc at body,        datum_anflag.fg at body,   seqno
+FROM    
+      hdr, body, sat
+WHERE  
+      obstype=$limb 
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/hdr.h b/odb/src/ddl/hdr.h
new file mode 100644
index 0000000..435eccb
--- /dev/null
+++ b/odb/src/ddl/hdr.h
@@ -0,0 +1,76 @@
+//
+// Table Definitions: hdr (header table)
+//
+CREATE TABLE hdr AS (
+  seqno                  pk1int,              // OBSERVATION SEQUENCE
+  subseqno               pk1int,              // OBSERVATION SEQUENCE for SUB-WINDOWS
+  bufrtype               pk1int,              // BUFR-type
+  subtype                pk1int,              // BUFR subtype for reference
+  subsetno               pk9int,              // Multisubset number in BUFR-msg (=0 for single subset) useful for odb2bufr
+// Local classification of observation
+  groupid                pk1int,              // MARS key - Observation group
+  reportype              pk1int,              // MARS key - report type for MAR
+  obstype                pk1int,              // OBSERVATION TYPE
+  codetype               pk1int,              // OBSERVATION CODE TYPE
+  sensor                 pk1int,              // ECMWF SATELLITE LOCAL (RTTOV) SENSOR INDICATOR
+
+  retrtype               pk1int,              // OBSERVATION RETRIEVAL TYPE
+
+// to be removed? 
+  instrument_type        pk1int,              // OBSERVATION INSTRUMENT TYPE
+
+  stalt                  pk9real,             // ALTITUDE 
+
+
+  date                   YYYYMMDD,            // OBS. DATE
+  time                   HHMMSS,              // OBS. EXACT TIME
+
+  distribtype            pk1int,              // type of distribution - default is 0 i.e. no redistribution
+  distribid              pk1int,              // target pool when data is re-distributed (for instance on model grid)
+  gp_dist                pk9real,             // DIST TO NEAREST GP - only if observations need to be distributed on model grid
+  gp_number              pk1int,              // JROF - grid point number (on the local PE grid)
+  numlev                 pk1int,              // No. of distinct pressure levels in bodies
+  numactiveb             pk1int,              // No. of active body entries (i.e. status.active at body == 1)
+  checksum               pk9real,             // A check sum of obsvalues where press & obsvalue is not NULL
+  sortbox                pk1int,              // SORTING BOX
+  areatype               pk1int,              // OBSERVATION AREA TYPE
+
+  report_status          STATUS_t,            // REPORT'S STATUS
+  report_event1          REPORT_EVENT1_t,     // REPORT'S EVENTS (PART 1)
+  report_rdbflag         REPORT_RDBFLAG_t,    // REPORT'S FLAGS
+  report_blacklist       REPORT_BLACKLIST_t,  // REPORT'S BLACKLIST EVENTS
+  report_event2          REPORT_EVENT2_t,     // REPORT EVENTS (PART 2) WORD POS.
+
+  thinningkey[$NUMTHBOX] pk9real,             // Thinning key
+  thinningtimekey        pk9real,             // Thinning time key
+
+// why do we have datastream, gen_centre + gen_subcentre in sat table??? They should be here, no?
+  sitedep                pk1int,             // site dependent
+  source                 string,             // Source ID of obs. (CHARACTER*8) : Reanalysis purposes
+
+  lat                    pk9real,            // LATITUDE
+  lon                    pk9real,            // LONGITUDE
+  trlat                  pk9real,            // TRANSFORMED LAT. 
+  trlon                  pk9real,            // TRANSFORMED LON.
+
+  modsurf                @LINK,              // Model surface fields, at observation points
+
+  statid                 string,             // STATION ID (CHARACTER*8)
+
+  conv                   @LINK,              // put here all ODB conventional for conventional data only
+  sat                    @LINK,  
+  body                   @LINK,  
+  errstat                @LINK,             // errstat table to be cleaned...
+  update[1:$NMXUPD]      @LINK,             // update tables to be cleaned...
+  auxiliary              @LINK,             // only created if ODB_AUXILIARY=1
+  ensemble               @LINK,             // one enkf or enda table per ensemble
+
+  gbrad                  @LINK,             // ground-based radar
+  raingg                 @LINK,             // rain gauges
+
+  surfbody_feedback      @LINK,             // storage of feedbacks from the surface analysis
+
+ // for subwindows
+  window_offset          pk1int,  // use for subwindows to identify the subwindow 
+);
+
diff --git a/odb/src/ddl/hdr_update_links.sql b/odb/src/ddl/hdr_update_links.sql
new file mode 100644
index 0000000..ebc8d89
--- /dev/null
+++ b/odb/src/ddl/hdr_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'hdr_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW hdr_update_links AS
+  SELECT "/LINK.*/"
+    FROM hdr
+;
+
diff --git a/odb/src/ddl/hop_canari_conv.sql b/odb/src/ddl/hop_canari_conv.sql
new file mode 100644
index 0000000..67e58d0
--- /dev/null
+++ b/odb/src/ddl/hop_canari_conv.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'hop_canari_conv.sql'
+//
+//   Last updated:  25-Mar-2011
+//
+
+READONLY;
+
+SET $kset = 0;
+
+CREATE VIEW hop_canari_conv AS
+  SELECT seqno,
+         body.len,
+         anemoht at conv,
+         baroht at conv
+  FROM   index, hdr, conv
+  WHERE  kset = $kset
+;
diff --git a/odb/src/ddl/hop_canari_robhdr.sql b/odb/src/ddl/hop_canari_robhdr.sql
new file mode 100644
index 0000000..889b2a2
--- /dev/null
+++ b/odb/src/ddl/hop_canari_robhdr.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'hop_canari_robhdr.sql'
+//
+//   Last updated:  09-Oct-2001
+//
+
+READONLY;
+
+SET $kset = 0;
+
+CREATE VIEW hop_canari_robhdr AS
+  SELECT seqno,
+         body.len,
+         abnob, mapomm,
+         codetype,
+         lat,
+         stalt,
+  FROM   index, hdr
+  WHERE  kset = $kset
+;
diff --git a/odb/src/ddl/hop_canari_robody.sql b/odb/src/ddl/hop_canari_robody.sql
new file mode 100644
index 0000000..29e8541
--- /dev/null
+++ b/odb/src/ddl/hop_canari_robody.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'hop_canari_robody.sql'
+//
+//   Last updated:  09-Oct-2001
+//
+
+READONLY;
+
+SET $kset = 0;
+
+CREATE VIEW hop_canari_robody AS
+  SELECT seqno,
+         varno,
+         vertco_reference_1,
+         vertco_reference_2,
+         obsvalue,
+         mf_log_p UPDATED,
+         final_obs_error,
+         an_depar UPDATED,
+         fg_depar UPDATED,
+         mf_stddev UPDATED,
+         fg_error UPDATED
+  FROM   index, hdr, body, errstat
+  WHERE  kset = $kset
+;
diff --git a/odb/src/ddl/hretr_canari_robody.sql b/odb/src/ddl/hretr_canari_robody.sql
new file mode 100644
index 0000000..2a764e7
--- /dev/null
+++ b/odb/src/ddl/hretr_canari_robody.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'hretr_canari_robody.sql'
+//
+//   Last updated:  12-Aug-2004
+//
+
+READONLY;
+
+SET $kset = 0;
+
+CREATE VIEW hretr_canari_robody AS
+  SELECT seqno,
+         varno,
+         vertco_type at body,
+         mf_log_p UPDATED,
+         vertco_reference_1 UPDATED,
+         pers_error,
+         repres_error,
+  FROM   index, hdr, body, errstat
+  WHERE  kset = $kset
+;
diff --git a/odb/src/ddl/hretr_canari_satbody.sql b/odb/src/ddl/hretr_canari_satbody.sql
new file mode 100644
index 0000000..3303d42
--- /dev/null
+++ b/odb/src/ddl/hretr_canari_satbody.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'hretr_canari_satbody.sql'
+//
+//   Last updated:  16-Mar-2011
+//
+// AF: added this SQL query but cannot test anything (CANARI configuration)
+//     may need to add something in getdb (same as hretr for IFS/ARPEGE)
+
+READONLY;
+
+SET $kset = 0;
+
+CREATE VIEW hretr_canari_satbody AS
+  SELECT seqno,
+         entryno,
+         bg_refractivity UPDATED,           // possibly updated
+         bg_dndz UPDATED,          // possibly updated
+         bg_layerno UPDATED             // possibly updated
+  FROM   index, hdr, body, gnssro, gnssro_body
+  WHERE  kset = $kset
+  AND obstype = $satem AND codetype = $gpsro
+;
diff --git a/odb/src/ddl/idx.h b/odb/src/ddl/idx.h
new file mode 120000
index 0000000..c25b0cc
--- /dev/null
+++ b/odb/src/ddl/idx.h
@@ -0,0 +1 @@
+../include/idx.h
\ No newline at end of file
diff --git a/odb/src/ddl/info.h b/odb/src/ddl/info.h
new file mode 120000
index 0000000..47734e7
--- /dev/null
+++ b/odb/src/ddl/info.h
@@ -0,0 +1 @@
+../include/info.h
\ No newline at end of file
diff --git a/odb/src/ddl/init_update_1.sql b/odb/src/ddl/init_update_1.sql
new file mode 100644
index 0000000..fbc587a
--- /dev/null
+++ b/odb/src/ddl/init_update_1.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'init_update_1.sql'
+//
+//   Last updated:  01-Jun-2011
+//
+
+UPDATED;
+
+CREATE VIEW init_update_1 AS
+  SELECT update[1],body
+    FROM hdr
+;
diff --git a/odb/src/ddl/init_update_2.sql b/odb/src/ddl/init_update_2.sql
new file mode 100644
index 0000000..59364cd
--- /dev/null
+++ b/odb/src/ddl/init_update_2.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'init_update_2.sql'
+//
+//   Last updated:  01-Jun-2011
+//
+
+UPDATED;
+
+CREATE VIEW init_update_2 AS
+  SELECT update[2],body
+    FROM hdr
+;
diff --git a/odb/src/ddl/init_update_3.sql b/odb/src/ddl/init_update_3.sql
new file mode 100644
index 0000000..adb5f3e
--- /dev/null
+++ b/odb/src/ddl/init_update_3.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'init_update_3.sql'
+//
+//   Last updated:  01-Jun-2011
+//
+
+UPDATED;
+
+CREATE VIEW init_update_3 AS
+  SELECT update[3],body
+    FROM hdr
+;
diff --git a/odb/src/ddl/level1cgeos_robhdr_1.sql b/odb/src/ddl/level1cgeos_robhdr_1.sql
new file mode 100644
index 0000000..7a6c876
--- /dev/null
+++ b/odb/src/ddl/level1cgeos_robhdr_1.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'level1cgeos_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW level1cgeos_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len  READONLY,           // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         sensor,                       // possibly updated (in ECMA)
+         report_rdbflag,                      // r/o
+         report_status,                       // possibly updated (in ECMA)
+         report_event1,                       // possibly updated (in ECMA)
+         report_event2,                       // possibly updated (in ECMA)
+         date,                         // r/o
+         time,                         // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $satem)
+    AND  (codetype = $rad1c)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/level1cgeos_robody_1.sql b/odb/src/ddl/level1cgeos_robody_1.sql
new file mode 100644
index 0000000..aaa2287
--- /dev/null
+++ b/odb/src/ddl/level1cgeos_robody_1.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'level1cgeos_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW level1cgeos_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,                  // possibly updated
+         datum_event2 at body,                  // possibly updated
+         datum_status at body,                  // possibly updated
+         datum_anflag at body,                  // possibly updated
+         datum_rdbflag at body,                 // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                // possibly updated
+         qc_l,                // possibly updated
+         qc_pge,                // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  ((obstype = $satem) AND (codetype = $rad1c))
+    AND	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/limb.h b/odb/src/ddl/limb.h
new file mode 100644
index 0000000..1c172a3
--- /dev/null
+++ b/odb/src/ddl/limb.h
@@ -0,0 +1,13 @@
+
+-- The following depends on rtlimb instruments (jpmxtan in mod_rtlimb_cparam),
+-- so watch for it!
+SET $mx_limb_tan = 17;
+
+CREATE TABLE limb AS (
+  ntan pk1int,                           // Number of sweeps
+  ztan[$mx_limb_tan] pk9real,            // Tangent height
+  ptan[$mx_limb_tan] pk9real,            // Tangent pressure
+  thtan[$mx_limb_tan] pk9real,           // Along-orbit angle, relative to lat/long
+  cloud_index[$mx_limb_tan] pk9real,     // Remedios & Spang cloud index
+  window_rad[$mx_limb_tan] pk9real,      // Radiance in 960.7 cm-1 channel
+);
diff --git a/odb/src/ddl/links_aeolus_hdr.sql b/odb/src/ddl/links_aeolus_hdr.sql
new file mode 100644
index 0000000..5964d67
--- /dev/null
+++ b/odb/src/ddl/links_aeolus_hdr.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'links_aeolus_hdr.sql'
+//
+//   Last updated:  14-Jun-2012
+//
+
+UPDATED;
+
+CREATE VIEW links_aeolus_hdr AS
+  SELECT aeolus_l2c, aeolus_auxmet
+    FROM aeolus_hdr
+;
diff --git a/odb/src/ddl/links_auxiliary.sql b/odb/src/ddl/links_auxiliary.sql
new file mode 100644
index 0000000..5c5aeb7
--- /dev/null
+++ b/odb/src/ddl/links_auxiliary.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'links_auxiliary.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+UPDATED;
+
+CREATE VIEW links_auxiliary AS
+  SELECT auxiliary
+    FROM hdr
+;
diff --git a/odb/src/ddl/links_body.sql b/odb/src/ddl/links_body.sql
new file mode 100644
index 0000000..b64b069
--- /dev/null
+++ b/odb/src/ddl/links_body.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'links_body.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+SET $codetype = -1;
+
+READONLY;
+
+CREATE VIEW links_body AS
+  SELECT body, auxiliary
+    FROM hdr
+    WHERE ((obstype=$satem) OR (obstype=$allsky))
+    AND  (($codetype == -1) OR (codetype == $codetype))
+;
diff --git a/odb/src/ddl/links_ensemble.sql b/odb/src/ddl/links_ensemble.sql
new file mode 100644
index 0000000..ea2deff
--- /dev/null
+++ b/odb/src/ddl/links_ensemble.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'links_ensemble.sql'
+//
+//   Last updated:  19-Jun-2012
+//
+
+UPDATED;
+
+CREATE VIEW links_ensemble AS
+  SELECT ensemble,
+    body READONLY,
+    FROM hdr
+;
diff --git a/odb/src/ddl/links_gbrad.sql b/odb/src/ddl/links_gbrad.sql
new file mode 100644
index 0000000..92abc0d
--- /dev/null
+++ b/odb/src/ddl/links_gbrad.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'links_gbrad.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+UPDATED;
+
+CREATE VIEW links_gbrad AS
+  SELECT gbrad
+    FROM hdr
+  WHERE obstype=$gbrad and codetype=$radrr
+;
diff --git a/odb/src/ddl/links_modsurf.sql b/odb/src/ddl/links_modsurf.sql
new file mode 100644
index 0000000..bfd79d3
--- /dev/null
+++ b/odb/src/ddl/links_modsurf.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'links_modsurf.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+UPDATED;
+
+CREATE VIEW links_modsurf AS
+  SELECT modsurf
+    FROM hdr
+;
diff --git a/odb/src/ddl/links_raingg.sql b/odb/src/ddl/links_raingg.sql
new file mode 100644
index 0000000..6abe352
--- /dev/null
+++ b/odb/src/ddl/links_raingg.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'links_raingg.sql'
+//
+//   Last updated:  22-Aug-2012
+//
+
+UPDATED;
+
+CREATE VIEW links_raingg AS
+  SELECT raingg
+    FROM hdr
+  WHERE reportype >= $synop_rg6h AND reportype <= $synop_rg24h
+;
diff --git a/odb/src/ddl/links_sat.sql b/odb/src/ddl/links_sat.sql
new file mode 100644
index 0000000..f135821
--- /dev/null
+++ b/odb/src/ddl/links_sat.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'links_sat.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+SET $codetype = -1;
+
+UPDATED;
+
+CREATE VIEW links_sat AS
+  SELECT sat, body
+    FROM hdr
+  WHERE ((obstype=$satem) OR (obstype=$allsky))
+    AND  (($codetype == -1) OR (codetype == $codetype))
+;
diff --git a/odb/src/ddl/links_surfbody_feedback.sql b/odb/src/ddl/links_surfbody_feedback.sql
new file mode 100644
index 0000000..c822955
--- /dev/null
+++ b/odb/src/ddl/links_surfbody_feedback.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'links_surfbody_feedback.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+UPDATED;
+
+CREATE VIEW links_surfbody_feedback AS
+  SELECT body, surfbody_feedback
+    FROM hdr
+;
diff --git a/odb/src/ddl/magicwords.h b/odb/src/ddl/magicwords.h
new file mode 120000
index 0000000..48f2e3b
--- /dev/null
+++ b/odb/src/ddl/magicwords.h
@@ -0,0 +1 @@
+../include/magicwords.h
\ No newline at end of file
diff --git a/odb/src/ddl/manda_gene_body.sql b/odb/src/ddl/manda_gene_body.sql
new file mode 100644
index 0000000..13839db
--- /dev/null
+++ b/odb/src/ddl/manda_gene_body.sql
@@ -0,0 +1,8 @@
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW manda_gene_body AS
+SELECT varno, datum_status at body
+FROM  index, hdr, body
+WHERE timeslot = $tslot
diff --git a/odb/src/ddl/manda_gene_hdr.sql b/odb/src/ddl/manda_gene_hdr.sql
new file mode 100644
index 0000000..8bfec9d
--- /dev/null
+++ b/odb/src/ddl/manda_gene_hdr.sql
@@ -0,0 +1,11 @@
+// Anne Fouilloux - Add sat table. I know this is not what you want...
+// need to discuss with Dominique...
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW manda_gene_hdr AS
+SELECT body.len, procid, obstype, codetype, report_status at hdr, satellite_identifier at sat, sensor
+FROM  index, hdr,sat 
+WHERE timeslot = $tslot
diff --git a/odb/src/ddl/manda_laelalo.sql b/odb/src/ddl/manda_laelalo.sql
new file mode 100644
index 0000000..1b0a172
--- /dev/null
+++ b/odb/src/ddl/manda_laelalo.sql
@@ -0,0 +1,5 @@
+CREATE VIEW manda_laelalo AS
+SELECT  
+   lon, lat,                      //  table hdr
+   obstype, codetype, statid       //  table hdr
+FROM  hdr
diff --git a/odb/src/ddl/map_ssmi_rain_ssmi.sql b/odb/src/ddl/map_ssmi_rain_ssmi.sql
new file mode 100644
index 0000000..6206fec
--- /dev/null
+++ b/odb/src/ddl/map_ssmi_rain_ssmi.sql
@@ -0,0 +1,17 @@
+//
+//-- ODB/SQL file 'map_ssmi_rain_ssmi.sql'
+//
+//   Last updated:  18-May-2004
+//
+
+READONLY;
+
+CREATE VIEW map_ssmi_rain_ssmi AS
+  SELECT ssmi_body UPDATED // Update @LINK to ssmi_body (i.e. 2 columns)
+  FROM   hdr, sat, ssmi
+  WHERE	 bufrtype = 12
+    AND  subtype  = 127
+    AND  (sensor = 6 OR sensor = 10 OR sensor = 9 OR sensor = 17)
+    AND  sat.len  = 1 // Play safe
+    AND  ssmi.len = 1 // Play safe
+;
diff --git a/odb/src/ddl/matchup_allsky_body.sql b/odb/src/ddl/matchup_allsky_body.sql
new file mode 100644
index 0000000..d35c897
--- /dev/null
+++ b/odb/src/ddl/matchup_allsky_body.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'matchup_allsky_body.sql'
+//
+//   Created:  10-May-2010
+//
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $sensor = -1;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_allsky_body AS
+  SELECT seqno  READONLY,            // r/o
+         entryno  READONLY,          // r/o
+         datum_tbflag at allsky_body UPDATED         // mwave (all-sky) observations
+    FROM timeslot_index, index, hdr, body, allsky_body
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND obstype = $allsky
+     AND codetype = $ssmi
+     AND (($sensor == -1) OR (sensor == $sensor))
+     AND paral($pe, procid - $hdr_min + 1)
+;
+
diff --git a/odb/src/ddl/matchup_atovs_pred.sql b/odb/src/ddl/matchup_atovs_pred.sql
new file mode 100644
index 0000000..698ef37
--- /dev/null
+++ b/odb/src/ddl/matchup_atovs_pred.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'matchup_atovs_pred.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $sensor = -1;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_atovs_pred AS
+  SELECT seqno  READONLY,                         // r/o
+         "/skintemp.*@radiance/"          // update all non-MDIs
+
+    FROM timeslot_index, index, hdr, sat, radiance
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND obstype = $satem
+     AND codetype = $atovs
+     AND (($sensor == -1) OR (sensor == $sensor))
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_body.sql b/odb/src/ddl/matchup_body.sql
new file mode 100644
index 0000000..b72ac3e
--- /dev/null
+++ b/odb/src/ddl/matchup_body.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'matchup_body.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_body AS
+  SELECT seqno  READONLY,            // r/o
+         entryno  READONLY,          // r/o
+         datum_anflag at body UPDATED,
+         datum_status at body UPDATED,
+         datum_event1 at body UPDATED,
+         an_depar at body UPDATED,
+         an_sens_obs at body UPDATED,
+    FROM timeslot_index, index, hdr, body
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
+
diff --git a/odb/src/ddl/matchup_gbrad.sql b/odb/src/ddl/matchup_gbrad.sql
new file mode 100644
index 0000000..4920963
--- /dev/null
+++ b/odb/src/ddl/matchup_gbrad.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'matchup_gbrad.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_gbrad AS
+  SELECT seqno  READONLY,      // r/o
+         report_rrflag,               // update
+    FROM timeslot_index, index, hdr, gbrad
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_hdr.sql b/odb/src/ddl/matchup_hdr.sql
new file mode 100644
index 0000000..0c4da4e
--- /dev/null
+++ b/odb/src/ddl/matchup_hdr.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'matchup_hdr.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_hdr AS
+  SELECT seqno  READONLY,      // r/o
+         report_status,               // update
+         report_event1,               // update
+    FROM timeslot_index, index, hdr
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_procid.sql b/odb/src/ddl/matchup_procid.sql
new file mode 100644
index 0000000..156debb
--- /dev/null
+++ b/odb/src/ddl/matchup_procid.sql
@@ -0,0 +1,11 @@
+//
+//-- ODB/SQL file 'matchup_procid.sql'
+//
+//   Last updated:  28-Jan-2005
+//
+
+CREATE VIEW matchup_procid AS
+  SELECT procid
+    FROM index
+   WHERE #index == 1  // The first row is sufficient
+;
diff --git a/odb/src/ddl/matchup_raingg.sql b/odb/src/ddl/matchup_raingg.sql
new file mode 100644
index 0000000..b456f7d
--- /dev/null
+++ b/odb/src/ddl/matchup_raingg.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'matchup_raingg.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_raingg AS
+  SELECT seqno  READONLY,      // r/o
+         report_rrflag,               // update
+    FROM timeslot_index, index, hdr, raingg
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_sensorlist.sql b/odb/src/ddl/matchup_sensorlist.sql
new file mode 100644
index 0000000..0f21662
--- /dev/null
+++ b/odb/src/ddl/matchup_sensorlist.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_sensorlist.sql'
+//
+//   Last updated:  16-Aug-2006
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+
+CREATE VIEW matchup_sensorlist AS
+  SELECT DISTINCT timeslot at index, sensor
+    FROM index,hdr
+   WHERE ($obstype  == -1 OR obstype  == $obstype)
+     AND ($codetype == -1 OR codetype == $codetype)
+     AND sensor is not NULL
+ SORT BY timeslot at index, sensor
+;
diff --git a/odb/src/ddl/matchup_update_1.sql b/odb/src/ddl/matchup_update_1.sql
new file mode 100644
index 0000000..d3aea4d
--- /dev/null
+++ b/odb/src/ddl/matchup_update_1.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'matchup_update_1.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_update_1 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[1]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_update_10.sql b/odb/src/ddl/matchup_update_10.sql
new file mode 100644
index 0000000..4b9d48e
--- /dev/null
+++ b/odb/src/ddl/matchup_update_10.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_10.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_10 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(10,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_2.sql b/odb/src/ddl/matchup_update_2.sql
new file mode 100644
index 0000000..9d71356
--- /dev/null
+++ b/odb/src/ddl/matchup_update_2.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'matchup_update_2.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_update_2 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(2,$nmxupd)]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_update_3.sql b/odb/src/ddl/matchup_update_3.sql
new file mode 100644
index 0000000..7c1773c
--- /dev/null
+++ b/odb/src/ddl/matchup_update_3.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'matchup_update_3.sql'
+//
+//   Last updated:  22-Jun-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+CREATE VIEW matchup_update_3 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(3,$nmxupd)]
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/matchup_update_4.sql b/odb/src/ddl/matchup_update_4.sql
new file mode 100644
index 0000000..a98e097
--- /dev/null
+++ b/odb/src/ddl/matchup_update_4.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_4.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_4 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(4,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_5.sql b/odb/src/ddl/matchup_update_5.sql
new file mode 100644
index 0000000..6b29370
--- /dev/null
+++ b/odb/src/ddl/matchup_update_5.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_5.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_5 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(5,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_6.sql b/odb/src/ddl/matchup_update_6.sql
new file mode 100644
index 0000000..7411478
--- /dev/null
+++ b/odb/src/ddl/matchup_update_6.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_6.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_6 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(6,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_7.sql b/odb/src/ddl/matchup_update_7.sql
new file mode 100644
index 0000000..7628885
--- /dev/null
+++ b/odb/src/ddl/matchup_update_7.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_7.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_7 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(7,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_8.sql b/odb/src/ddl/matchup_update_8.sql
new file mode 100644
index 0000000..94c3056
--- /dev/null
+++ b/odb/src/ddl/matchup_update_8.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_8.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_8 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(8,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchup_update_9.sql b/odb/src/ddl/matchup_update_9.sql
new file mode 100644
index 0000000..515e7b2
--- /dev/null
+++ b/odb/src/ddl/matchup_update_9.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'matchup_update_9.sql'
+//
+//   Last updated:  27-Feb-2003
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW matchup_update_9 AS
+  SELECT seqno READONLY,            // r/o
+         entryno READONLY,          // r/o
+         "/.*@update.*/"        // update (even if an MDI)
+    FROM timeslot_index, index, hdr, body , update[min(9,$nmxupd)]
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, procid)
+;
diff --git a/odb/src/ddl/matchupsink.sql b/odb/src/ddl/matchupsink.sql
new file mode 100644
index 0000000..16ac428
--- /dev/null
+++ b/odb/src/ddl/matchupsink.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'matchupsink.sql'
+//
+//   Last updated:  23-Nov-2007
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+SET $sensor = -1;
+SET $hdr_min = 1; // Here: the smallest procid (=global poolno) of the obs.grp. (ECMA)
+SET $hdr_max = 0; // Here: the number of pools in (output) ECMA-database
+
+UPDATABLE;
+CREATE VIEW matchupsink AS
+  SELECT seqno  READONLY,        // r/o
+         skintemp[1:($NMXUPD+1)]@radiance,
+    FROM timeslot_index, index, hdr, sat, radiance
+   WHERE target > 0
+     AND 1 <= procid - $hdr_min + 1 <= $hdr_max
+     AND (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND obstype = $satem
+     AND codetype = $atovs
+     AND (($sensor == -1) OR (sensor == $sensor))
+     AND paral($pe, procid - $hdr_min + 1)
+;
diff --git a/odb/src/ddl/max_values.sql b/odb/src/ddl/max_values.sql
new file mode 100644
index 0000000..9015aba
--- /dev/null
+++ b/odb/src/ddl/max_values.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'max_values.sql'
+//
+//   Last updated:  01/03/2011
+//
+
+READONLY;
+
+CREATE VIEW max_values AS
+  SELECT max(scanpos), max(vertco_reference_1),
+    FROM hdr,sat,radiance, body
+;
+
diff --git a/odb/src/ddl/mdi.h b/odb/src/ddl/mdi.h
new file mode 100644
index 0000000..1d4ee82
--- /dev/null
+++ b/odb/src/ddl/mdi.h
@@ -0,0 +1 @@
+SET $MDI = 2147483647; // Absolute value of the Missing Data Indicator
diff --git a/odb/src/ddl/mkglobstab.sql b/odb/src/ddl/mkglobstab.sql
new file mode 100644
index 0000000..aacfbb7
--- /dev/null
+++ b/odb/src/ddl/mkglobstab.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'mkglobstab.sql'
+//
+
+CREATE VIEW mkglobstab AS
+  SELECT seqno READONLY,
+         timeslot READONLY,
+         obstype READONLY,
+         codetype READONLY,
+         instrument_type READONLY,
+         retrtype READONLY,
+         areatype READONLY,
+	       abnob READONLY, 
+         mapomm,
+         lat READONLY, 
+         lon READONLY, 
+         trlat READONLY,
+         trlon READONLY,
+    FROM index, hdr
+ ORDERBY timeslot, seqno
+;
diff --git a/odb/src/ddl/mkglobstab_gpsro.sql b/odb/src/ddl/mkglobstab_gpsro.sql
new file mode 100644
index 0000000..2fbd47b
--- /dev/null
+++ b/odb/src/ddl/mkglobstab_gpsro.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'mkglobstab_gpsro.sql'
+//
+//   Last updated:  16-Mar-2011
+//
+
+READONLY;
+
+CREATE VIEW mkglobstab_gpsro AS
+  SELECT seqno,timeslot, 
+         azimuth,
+    FROM index, hdr, sat
+    WHERE ( obstype=$limb AND codetype=$gpsro ) OR obstype=$satem
+ ORDERBY timeslot, seqno
+;
diff --git a/odb/src/ddl/mobhdr_obsort.sql b/odb/src/ddl/mobhdr_obsort.sql
new file mode 100644
index 0000000..140e620
--- /dev/null
+++ b/odb/src/ddl/mobhdr_obsort.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'mobhdr_obsort.sql'
+//
+//   Last updated:  11-Mar-2003
+//
+
+READONLY;
+
+SET $all = 1;
+SET $hdr_min = 0; // here $hdr_min corresponds to distribtype 1 if on the model grid
+
+CREATE VIEW mobhdr_obsort AS
+  SELECT seqno,              //  r/o
+         obstype , codetype,  sensor, //  r/o
+         date, time,         //  r/o
+         body.len,           //  r/o
+         numactiveb,         //  r/o
+         distribid,          // r/o
+         target  UPDATED,          //  this is the "dest_proc" and will be updated
+         gp_number,
+    FROM index, hdr
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1)
+	  OR ($all = 2 ) )
+      AND distribtype = $hdr_min
+   ORDERBY sensor, distribid, gp_number
+;
diff --git a/odb/src/ddl/mobhdrca_obsort.sql b/odb/src/ddl/mobhdrca_obsort.sql
new file mode 100644
index 0000000..b0b342b
--- /dev/null
+++ b/odb/src/ddl/mobhdrca_obsort.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'mobhdrca_obsort.sql'
+//
+//   Last updated:  17-May-2000 ; 06-Mar-2012
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW mobhdrca_obsort AS
+  SELECT seqno,              //  r/o
+         obstype , codetype,  sensor, //  r/o
+         date, time,         //  r/o
+         body.len,           //  r/o
+	 numactiveb,         //  r/o
+         distribid,          // r/o
+         target UPDATED,           //  this is the "dest_proc" and will be updated
+  FROM index, hdr
+  WHERE ($all >= 1 OR report_status.active = 1)
+    AND (timeslot = 4)
+    AND ($all = 2 OR $all = -2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+;
diff --git a/odb/src/ddl/modsurf.h b/odb/src/ddl/modsurf.h
new file mode 100644
index 0000000..3fa8615
--- /dev/null
+++ b/odb/src/ddl/modsurf.h
@@ -0,0 +1,18 @@
+//
+// Table Definition: modsurf tables
+//
+
+CREATE TABLE modsurf AS (
+  lsm                pk9real,     // model land-sea mask
+  seaice             pk9real,     // model sea-ice  mask
+  orography          pk9real,     // model orography 
+  snow_depth         pk9real,     // model snow depth (m)
+  t2m                pk9real,     // 2m temperature
+  albedo             pk9real,     // albedo
+  windspeed10m       pk9real,     // 10 metre wind speed
+  u10m               pk9real,     // 10 metre U wind component
+  v10m               pk9real,     // 10 metre V wind component
+  surface_class      pk1int,      // surface type (used for radiances only; see satrad/emiss/amsu_sfc.F90)
+  tsfc               pk9real,     // model skin temperature (used for some radiances only)
+);
+
diff --git a/odb/src/ddl/nak_resat_averaging_kernel.sql b/odb/src/ddl/nak_resat_averaging_kernel.sql
new file mode 100644
index 0000000..8b140b5
--- /dev/null
+++ b/odb/src/ddl/nak_resat_averaging_kernel.sql
@@ -0,0 +1,17 @@
+//
+//-- ODB/SQL file 'nak_resat_averaging_kernel.sql'
+//
+//   New:  12-Sep-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW nak_resat_averaging_kernel AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         nak                           // r/o
+//    FROM timeslot_index, index, hdr, sat, resat, resat_averaging_kernel
+FROM   timeslot_index, index, hdr, sat, resat, resat_averaging_kernel
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+     AND obstype = $satem AND codetype = $resat
+;
diff --git a/odb/src/ddl/namecfg.h b/odb/src/ddl/namecfg.h
new file mode 100644
index 0000000..b92773c
--- /dev/null
+++ b/odb/src/ddl/namecfg.h
@@ -0,0 +1,15 @@
+#ifdef _NAMECFG_
+! odb_name mapname long_name units conversion_factor_a conversion_factor_b
+! conversion : A * obtained_value + B
+
+lat at hdr latitude - degrees_north 57.295779513082323 0
+lon at hdr longitude - degrees_east 57.295779513082323 0
+date at hdr date 'Observation date' yyyymmdd
+time at hdr time 'Observation time' hhmmss
+
+$t2m  t2m  '2m temperature' K
+$ts   ts   'surface temperature' K
+$u10m u10m 'u-component of 10m wind' 'm/s'
+$v10m v10m 'v-component of 10m wind' 'm/s'
+#endif
+
diff --git a/odb/src/ddl/nesdis_get.sql b/odb/src/ddl/nesdis_get.sql
new file mode 100644
index 0000000..866a146
--- /dev/null
+++ b/odb/src/ddl/nesdis_get.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'nesdis_get.sql'
+//
+//   Last updated:  17-Dec-2012
+//
+
+
+READONLY;
+
+CREATE VIEW nesdis_get AS // SSA-analysis (snow only); Get nesdis data
+  SELECT seqno,                      // r/o; Must become first
+         lat,
+         lon,
+         obsvalue,
+         varno,                      // r/o
+    FROM hdr, body
+   WHERE obstype = $imsims
+   AND varno =  $binary_snow_cover
+   AND obsvalue IS NOT NULL
+   ORDER BY lat DESC
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_10.sql b/odb/src/ddl/new_thinn_robhdr_10.sql
new file mode 100644
index 0000000..f51bb96
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_10.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_10.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_10 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status UPDATED,               // possibly updated (in ECMA)
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_11.sql b/odb/src/ddl/new_thinn_robhdr_11.sql
new file mode 100644
index 0000000..8d7ef64
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_11.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_11.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_11 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status UPDATED,        // possibly updated (in ECMA)
+         report_event1 UPDATED,        // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+    WHERE  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_2.sql b/odb/src/ddl/new_thinn_robhdr_2.sql
new file mode 100644
index 0000000..ab8e719
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_2.sql
@@ -0,0 +1,39 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_2.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $ksensor_v = 0; // Must be initialized to zero
+
+CREATE VIEW new_thinn_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         zenith,                       // r/o
+         scanline at radiance,            // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr, sat, radiance
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND   (codetype = $atovs)
+    AND  (in_vector(sensor, $ksensor_v))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_3.sql b/odb/src/ddl/new_thinn_robhdr_3.sql
new file mode 100644
index 0000000..bec26b7
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_3.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_3.sql'
+//
+//   Last updated:  31-Mar-2010
+//
+//   For TCWC (meris,...) only
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         sensor,                 // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_4.sql b/odb/src/ddl/new_thinn_robhdr_4.sql
new file mode 100644
index 0000000..a9fa283
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_4.sql
@@ -0,0 +1,39 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_4.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW new_thinn_robhdr_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         gen_centre,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_5.sql b/odb/src/ddl/new_thinn_robhdr_5.sql
new file mode 100644
index 0000000..87cb9c9
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_5.sql
@@ -0,0 +1,40 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_5.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW new_thinn_robhdr_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         gen_centre,                   // r/o
+         QI_fc at satob,                   // r/o
+         QI_nofc at satob,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_6.sql b/odb/src/ddl/new_thinn_robhdr_6.sql
new file mode 100644
index 0000000..d68d369
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_6.sql
@@ -0,0 +1,36 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_6.sql'
+//
+//   Last updated:  08-Nov-2007
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  ( obstype = $obstype )
+    AND  (codetype = $codetype)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_7.sql b/odb/src/ddl/new_thinn_robhdr_7.sql
new file mode 100644
index 0000000..184624f
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_7.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_7.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                         // r/o
+	     time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status UPDATED,               // possibly updated (in ECMA)
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $satem500)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_8.sql b/odb/src/ddl/new_thinn_robhdr_8.sql
new file mode 100644
index 0000000..bee1f15
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_8.sql
@@ -0,0 +1,37 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_8.sql'
+//
+//   Last updated:  13-Aug-2004
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW new_thinn_robhdr_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+//       obschar,                      // r/o
+         codetype,                     // r/o
+         instrument_type at hdr,          // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,       // possibly updated (in ECMA)
+         report_event1  UPDATED,       // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+//  AND  (obschar.codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robhdr_9.sql b/odb/src/ddl/new_thinn_robhdr_9.sql
new file mode 100644
index 0000000..965f569
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robhdr_9.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'new_thinn_robhdr_9.sql'
+//
+//   Last updated:  07-Dec-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robhdr_9 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX],     // r/o
+         thinningtimekey               // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = 10)
+    AND  (codetype =  250)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_10.sql b/odb/src/ddl/new_thinn_robody_10.sql
new file mode 100644
index 0000000..5811417
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_10.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_10.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_10 AS
+  SELECT entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+         fg_depar,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_11.sql b/odb/src/ddl/new_thinn_robody_11.sql
new file mode 100644
index 0000000..bf2715c
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_11.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_11.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_11 AS
+  SELECT entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+         fg_depar,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_3.sql b/odb/src/ddl/new_thinn_robody_3.sql
new file mode 100644
index 0000000..47a6af3
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_3.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_3.sql'
+//
+//   Created:  18-Aug-2009 - Alan Geer - need to distinguish MERIS TCWV from All-Sky
+//   31-Mar-2010 - Anne Fouilloux - needed for tcwc (MERIS, etc.) only
+//
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,                  // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,                  // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_4.sql b/odb/src/ddl/new_thinn_robody_4.sql
new file mode 100644
index 0000000..056db2f
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_4.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_4.sql'
+//
+//   Created:  16-Oct-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+         vertco_reference_1,           // r/o
+         obsvalue,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE  (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+   AND   (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_5.sql b/odb/src/ddl/new_thinn_robody_5.sql
new file mode 100644
index 0000000..2b61282
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_5.sql
@@ -0,0 +1,24 @@
+//-- ODB/SQL file 'new_thinn_robody_5.sql'
+//
+//   Created:  16-Oct-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+         vertco_reference_1,           // r/o
+         obsvalue,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE  (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_8.sql b/odb/src/ddl/new_thinn_robody_8.sql
new file mode 100644
index 0000000..a1d7f7f
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_8.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_8.sql'
+//
+//   Created:  15-Oct-2007
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW new_thinn_robody_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+//  AND  (obschar.codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/new_thinn_robody_9.sql b/odb/src/ddl/new_thinn_robody_9.sql
new file mode 100644
index 0000000..f8438d8
--- /dev/null
+++ b/odb/src/ddl/new_thinn_robody_9.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'new_thinn_robody_9.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW new_thinn_robody_9 AS
+  SELECT entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+         fg_depar,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/obatabs_robhdr.sql b/odb/src/ddl/obatabs_robhdr.sql
new file mode 100644
index 0000000..4b762b4
--- /dev/null
+++ b/odb/src/ddl/obatabs_robhdr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obatabs_robhdr.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW obatabs_robhdr AS
+   SELECT seqno, timeslot at index, obstype, codetype, instrument_type, retrtype, areatype,
+// get abnob & mapomm for debugging purposes only
+	 abnob, mapomm,
+	 body.len,  // r/o (MLNK_hdr2body(2))
+         lat, lon,  // r/o
+	 trlat  UPDATED, 
+         trlon  UPDATED,
+         statid // needed for some LELAM-case
+    FROM timeslot_index, index, hdr
+   WHERE ($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot)
+ ORDERBY timeslot at index, seqno
+;
diff --git a/odb/src/ddl/obs_boxes.sql b/odb/src/ddl/obs_boxes.sql
new file mode 100644
index 0000000..80079e2
--- /dev/null
+++ b/odb/src/ddl/obs_boxes.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'obs_boxes.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+CREATE VIEW obs_boxes AS
+  SELECT timeslot, obstype
+    FROM index, hdr
+;
diff --git a/odb/src/ddl/obscount_1.sql b/odb/src/ddl/obscount_1.sql
new file mode 100644
index 0000000..3b542d9
--- /dev/null
+++ b/odb/src/ddl/obscount_1.sql
@@ -0,0 +1,14 @@
+//
+// obscount_1.sql 
+//
+// Created:   16-Oct-2007  : Sami Saarinen, ECMWF (SS)
+// Modified:  19-Oct-2007  : sum(index.len) -> sum(hdr.len) & ORDERBY adjusted
+//
+
+READONLY;
+
+CREATE VIEW obscount_1 AS
+SELECT timeslot at timeslot_index,sum(hdr.len),sum(body.len) 
+  FROM timeslot_index,index,hdr 
+ORDERBY -2,-3,1;
+
diff --git a/odb/src/ddl/obscount_2.sql b/odb/src/ddl/obscount_2.sql
new file mode 100644
index 0000000..530510c
--- /dev/null
+++ b/odb/src/ddl/obscount_2.sql
@@ -0,0 +1,13 @@
+//
+// obscount_2.sql 
+//
+// Created:   02-Nov-2007  : Sami Saarinen, ECMWF
+//
+
+READONLY;
+
+CREATE VIEW obscount_2 AS
+SELECT timeslot,sum(index.len)
+  FROM timeslot_index
+ORDERBY -2, 1
+
diff --git a/odb/src/ddl/obsdist.sql b/odb/src/ddl/obsdist.sql
new file mode 100644
index 0000000..cb0faf0
--- /dev/null
+++ b/odb/src/ddl/obsdist.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'obsdist.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY; // the view is treated as read/only
+
+CREATE VIEW obsdist AS
+  SELECT distinct obstype,codetype, sensor                //  r/o
+    FROM hdr
+      WHERE (distribtype = 1)
+;
diff --git a/odb/src/ddl/obsdist_allsky.sql b/odb/src/ddl/obsdist_allsky.sql
new file mode 100644
index 0000000..146f4ea
--- /dev/null
+++ b/odb/src/ddl/obsdist_allsky.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_allsky.sql'
+//
+//   Created:  22-Apr-2010
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window_offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & allsky.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_allsky AS
+  SELECT distribid, seqno, window_offset, "*@allsky"
+    FROM hdr, sat, radiance, allsky
+    WHERE obstype = $allsky
+      AND codetype = $ssmi
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_allsky_body.sql b/odb/src/ddl/obsdist_allsky_body.sql
new file mode 100644
index 0000000..88c83a1
--- /dev/null
+++ b/odb/src/ddl/obsdist_allsky_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_allsky_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+CREATE VIEW obsdist_allsky_body AS
+  SELECT distribid, seqno, window_offset, "*@allsky_body"
+    FROM hdr, sat, radiance, allsky, allsky_body
+   WHERE obstype = $allsky
+     AND codetype = $ssmi
+      AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND allsky_body.len > 0
+     AND allsky_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_auxiliary.sql b/odb/src/ddl/obsdist_auxiliary.sql
new file mode 100644
index 0000000..b9043d5
--- /dev/null
+++ b/odb/src/ddl/obsdist_auxiliary.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsdist_auxiliary.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_auxiliary AS
+  SELECT distribid, seqno, window_offset, "*@auxiliary"
+    FROM hdr, auxiliary
+    WHERE (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND auxiliary.len > 0
+     AND distribtype = 1
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_auxiliary_body.sql b/odb/src/ddl/obsdist_auxiliary_body.sql
new file mode 100644
index 0000000..3ad707c
--- /dev/null
+++ b/odb/src/ddl/obsdist_auxiliary_body.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'obsdist_auxiliary_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_auxiliary_body AS
+  SELECT distribid, seqno, window_offset, "*@auxiliary_body"
+    FROM hdr, auxiliary, auxiliary_body
+    WHERE (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND  auxiliary_body.len > 0
+     AND  auxiliary_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_body.sql b/odb/src/ddl/obsdist_body.sql
new file mode 100644
index 0000000..0da8a1a
--- /dev/null
+++ b/odb/src/ddl/obsdist_body.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsdist_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_body AS
+  SELECT distribid, seqno, window_offset, "*@body"
+    FROM hdr, body
+     WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1 )
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_errstat.sql b/odb/src/ddl/obsdist_errstat.sql
new file mode 100644
index 0000000..59c8efb
--- /dev/null
+++ b/odb/src/ddl/obsdist_errstat.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsdist_errstat.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_errstat AS
+  SELECT distribid, seqno, window_offset, "*@errstat"
+    FROM hdr, errstat
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_gbrad.sql b/odb/src/ddl/obsdist_gbrad.sql
new file mode 100644
index 0000000..dccf276
--- /dev/null
+++ b/odb/src/ddl/obsdist_gbrad.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'obsdist_gbrad.sql'
+//
+//   Created:  22-July-2010
+//
+
+READONLY;
+NOREORDER;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window_offset
+
+// Make sure the SQL applies only to rows where gbrad.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_gbrad AS
+  SELECT distribid, seqno, window_offset, "*@gbrad"
+    FROM hdr, gbrad
+    WHERE obstype = $gbrad
+      AND codetype = $radrr
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_gbrad_body.sql b/odb/src/ddl/obsdist_gbrad_body.sql
new file mode 100644
index 0000000..925e776
--- /dev/null
+++ b/odb/src/ddl/obsdist_gbrad_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_gbrad_body.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+CREATE VIEW obsdist_gbrad_body AS
+  SELECT distribid, seqno, window_offset, "*@gbrad_body"
+    FROM hdr, gbrad, gbrad_body
+   WHERE obstype = $gbrad
+     AND codetype = $radrr
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND gbrad_body.len > 0
+     AND gbrad_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr.sql b/odb/src/ddl/obsdist_hdr.sql
new file mode 100644
index 0000000..bf58b5c
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_hdr.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_hdr AS
+  SELECT distribid, seqno, window_offset, "*@hdr"
+    FROM hdr
+       WHERE 1 <= distribid
+       AND distribtype = 1 
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2allsky_body.sql b/odb/src/ddl/obsdist_hdr2allsky_body.sql
new file mode 100644
index 0000000..9dcfa77
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2allsky_body.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2allsky_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2allsky_body AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr, allsky, allsky_body
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (#allsky_body >= 1)
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND (obstype = $allsky) AND (codetype = $ssmi)
+       AND  allsky_body.len > 0
+       AND  allsky_body.len == body.len
+       AND  paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2auxiliary_body.sql b/odb/src/ddl/obsdist_hdr2auxiliary_body.sql
new file mode 100644
index 0000000..c0367f0
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2auxiliary_body.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2auxiliary_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_hdr2auxiliary_body AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr, auxiliary, auxiliary_body
+       WHERE 1 <= distribid
+       AND (#auxiliary_body >= 1)
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2body.sql b/odb/src/ddl/obsdist_hdr2body.sql
new file mode 100644
index 0000000..c57e5a0
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2body.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_hdr2body AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2gbrad_body.sql b/odb/src/ddl/obsdist_hdr2gbrad_body.sql
new file mode 100644
index 0000000..2b6681d
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2gbrad_body.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2gbrad_body.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2gbrad_body AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr, gbrad, gbrad_body
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (#gbrad_body >= 1)
+       AND (obstype = $gbrad)
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND (obstype=$gbrad) AND (codetype = $radrr)
+       AND  gbrad_body.len > 0
+       AND  gbrad_body.len == body.len
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2radar_body.sql b/odb/src/ddl/obsdist_hdr2radar_body.sql
new file mode 100644
index 0000000..35666af
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2radar_body.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2radar_body.sql'
+//
+// Created: 22-Jun-2009
+//
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2radar_body AS
+  SELECT distribid, seqno, window_offset
+   FROM hdr, sat, radar, radar_body
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (#radar_body >= 1)
+       AND (radar_body.len at radar > 0)
+       AND (obstype = $radar)
+       AND (obstype = $obstype OR $obstype = -1 )
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2radiance_body.sql b/odb/src/ddl/obsdist_hdr2radiance_body.sql
new file mode 100644
index 0000000..a14211d
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2radiance_body.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2radiance_body.sql'
+//
+//   Created:  22-Mar-2011
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2radiance_body AS
+  SELECT distribid, seqno
+    FROM hdr, radiance
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND  radiance_body.len > 0
+       AND  radiance_body.len == body.len
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2raingg_body.sql b/odb/src/ddl/obsdist_hdr2raingg_body.sql
new file mode 100644
index 0000000..6464010
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2raingg_body.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2raingg_body.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2raingg_body AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr, raingg, raingg_body
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (#raingg_body >= 1)
+       AND (obstype = $raingg)
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND (obstype=$raingg) AND (codetype = $radrr)
+       AND  raingg_body.len > 0
+       AND  raingg_body.len == body.len
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_hdr2resat_averaging_kernel.sql b/odb/src/ddl/obsdist_hdr2resat_averaging_kernel.sql
new file mode 100644
index 0000000..5d4520f
--- /dev/null
+++ b/odb/src/ddl/obsdist_hdr2resat_averaging_kernel.sql
@@ -0,0 +1,44 @@
+//
+//-- ODB/SQL file 'obsdist_hdr2resat_averaging_kernel.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsdist_hdr2resat_averaging_kernel AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr, sat, resat, resat_averaging_kernel
+       WHERE 1 <= distribid
+       AND distribtype = 1
+
+// the following are always true and needed in order to make sure that:
+
+// (a) search order is preserved as in obsdist_hdr2body [-> NOREORDER]
+// (b) tables "sat, resat, resat_averaging_kernel"  won't get ignored
+
+     AND (#resat_averaging_kernel >= 1)
+
+// (c) query doesn't return anything, when resat_averaging_kernel is in fact empty
+//      (this is needed only during the transition period when ALIGNment
+//       between body & resat_averaging_kernel may not be established/true)
+
+     AND (resat_averaging_kernel.len at resat > 0)
+
+// (d) data is *REALLY* resat-related (see obsdist_resat.sql)
+
+     AND (obstype = $satem) AND (codetype = $resat)
+       AND (obstype = $obstype OR $obstype = -1 )
+       AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_index.sql b/odb/src/ddl/obsdist_index.sql
new file mode 100644
index 0000000..c5ec340
--- /dev/null
+++ b/odb/src/ddl/obsdist_index.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_index.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_index AS
+  SELECT distribid, seqno, window_offset, "*@index"
+    FROM index, hdr
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_index2hdr.sql b/odb/src/ddl/obsdist_index2hdr.sql
new file mode 100644
index 0000000..b8256d0
--- /dev/null
+++ b/odb/src/ddl/obsdist_index2hdr.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_index2hdr.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_index2hdr AS
+  SELECT distribid, seqno, window_offset
+    FROM hdr
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_limb.sql b/odb/src/ddl/obsdist_limb.sql
new file mode 100644
index 0000000..fd36fd8
--- /dev/null
+++ b/odb/src/ddl/obsdist_limb.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_limb.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & limb.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_limb AS
+  SELECT distribid, seqno, window_offset, "*@limb"
+    FROM hdr, sat, limb
+    WHERE obstype = $limb
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_modsurf.sql b/odb/src/ddl/obsdist_modsurf.sql
new file mode 100644
index 0000000..f949190
--- /dev/null
+++ b/odb/src/ddl/obsdist_modsurf.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsdist_modsurf.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_modsurf AS
+  SELECT distribid, seqno, window_offset, "*@modsurf"
+    FROM hdr, modsurf
+     WHERE  modsurf.len == 1
+     AND 1 <= distribid
+     AND  distribtype = 1
+     AND (obstype = $obstype OR $obstype = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_poolno.sql b/odb/src/ddl/obsdist_poolno.sql
new file mode 100644
index 0000000..8aa5d45
--- /dev/null
+++ b/odb/src/ddl/obsdist_poolno.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsdist_poolno.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY; // the view is treated as read/only
+
+SET $obstype=-1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_poolno AS
+  SELECT distinct procid                //  r/o
+    FROM index, hdr
+    WHERE (obstype = $obstype OR $obstype = -1 )
+          AND (codetype = $codetype OR $codetype = -1)
+          AND (sensor = $sensor OR $sensor = -1)
+          AND (window_offset = $hdr_min OR $hdr_min = -1)
+;
diff --git a/odb/src/ddl/obsdist_radar.sql b/odb/src/ddl/obsdist_radar.sql
new file mode 100644
index 0000000..d0b65b2
--- /dev/null
+++ b/odb/src/ddl/obsdist_radar.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_radar.sql'
+//
+//  Created :  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radar.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_radar AS
+  SELECT distribid, seqno, window_offset, "*@radar"
+    FROM hdr, sat, radar
+    WHERE obstype = $radar
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_radar_body.sql b/odb/src/ddl/obsdist_radar_body.sql
new file mode 100644
index 0000000..edea495
--- /dev/null
+++ b/odb/src/ddl/obsdist_radar_body.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_radar_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_radar_body AS
+  SELECT distribid, seqno, window_offset, "*@radar_body"
+    FROM hdr, sat, radar, radar_body
+   WHERE obstype = $radar
+     AND 1 <= distribid
+     AND  distribtype = 1
+     AND  radar_body.len > 0
+     AND  radar_body.len == body.len
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_radar_station.sql b/odb/src/ddl/obsdist_radar_station.sql
new file mode 100644
index 0000000..d41ba61
--- /dev/null
+++ b/odb/src/ddl/obsdist_radar_station.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_radar_station.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radar_station.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_radar_station AS
+  SELECT distribid, seqno, window_offset, "*@radar_station"
+    FROM hdr, sat, radar_station
+    WHERE obstype = $radar
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_radiance.sql b/odb/src/ddl/obsdist_radiance.sql
new file mode 100644
index 0000000..fce6a95
--- /dev/null
+++ b/odb/src/ddl/obsdist_radiance.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_radiance.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radiance.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_radiance AS
+  SELECT distribid, seqno, window_offset, "*@radiance"
+    FROM hdr, sat, radiance
+    WHERE ((obstype = $satem) OR (obstype = $allsky))
+      AND codetype = $ssmi
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_radiance_body.sql b/odb/src/ddl/obsdist_radiance_body.sql
new file mode 100644
index 0000000..1a31e0d
--- /dev/null
+++ b/odb/src/ddl/obsdist_radiance_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_radiance_body.sql'
+//
+//   Created:  22-Mar-2011
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; 
+
+CREATE VIEW obsdist_radiance_body AS
+  SELECT distribid, seqno, window_offset, "*@radiance_body"
+    FROM hdr, sat, radiance, radiance_body
+   WHERE ((obstype = $satem) OR (obstype = $allsky))
+     AND codetype = $ssmi
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND radiance_body.len > 0
+     AND radiance_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_raingg.sql b/odb/src/ddl/obsdist_raingg.sql
new file mode 100644
index 0000000..0eab1a4
--- /dev/null
+++ b/odb/src/ddl/obsdist_raingg.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'obsdist_raingg.sql'
+//
+//   Created:  22-July-2010
+//
+
+READONLY;
+NOREORDER;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window_offset
+
+// Make sure the SQL applies only to rows where raingg.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_raingg AS
+  SELECT distribid, seqno, window_offset, "*@raingg"
+    FROM hdr, raingg
+    WHERE obstype = $raingg
+      AND codetype = $radrr
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_raingg_body.sql b/odb/src/ddl/obsdist_raingg_body.sql
new file mode 100644
index 0000000..2295319
--- /dev/null
+++ b/odb/src/ddl/obsdist_raingg_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_raingg_body.sql'
+//
+//   Created:  22-Jul-2010
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min= -1; // contains window offset
+
+CREATE VIEW obsdist_raingg_body AS
+  SELECT distribid, seqno, window_offset, "*@raingg_body"
+    FROM hdr, raingg, raingg_body
+   WHERE obstype = $raingg
+     AND codetype = $radrr
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND raingg_body.len > 0
+     AND raingg_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_resat.sql b/odb/src/ddl/obsdist_resat.sql
new file mode 100644
index 0000000..db946fc
--- /dev/null
+++ b/odb/src/ddl/obsdist_resat.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_resat.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & resat.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_resat AS
+  SELECT distribid, seqno, window_offset, "*@resat"
+    FROM hdr, sat, resat
+    WHERE obstype = $satem
+      AND (codetype = $resat)
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+      AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_resat_averaging_kernel.sql b/odb/src/ddl/obsdist_resat_averaging_kernel.sql
new file mode 100644
index 0000000..1d20e28
--- /dev/null
+++ b/odb/src/ddl/obsdist_resat_averaging_kernel.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_resat_averaging_kernel.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_resat_averaging_kernel AS
+  SELECT distribid, seqno, window_offset, "*@resat_averaging_kernel"
+    FROM hdr, sat, resat, resat_averaging_kernel
+   WHERE obstype = $satem
+     AND (codetype = $resat)
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND  resat_averaging_kernel.len > 0
+     AND  resat_averaging_kernel.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_sat.sql b/odb/src/ddl/obsdist_sat.sql
new file mode 100644
index 0000000..9e9f0da
--- /dev/null
+++ b/odb/src/ddl/obsdist_sat.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsdist_sat.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_sat AS
+  SELECT distribid, seqno, window_offset, "*@sat"
+    FROM hdr, sat
+     WHERE  sat.len == 1
+     AND 1 <= distribid
+     AND  distribtype = 1
+     AND (obstype = $obstype OR $obstype = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)  
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_satob.sql b/odb/src/ddl/obsdist_satob.sql
new file mode 100644
index 0000000..7b8c0e4
--- /dev/null
+++ b/odb/src/ddl/obsdist_satob.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_satob.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; 
+
+// Make sure the SQL applies only to rows where sat.len at hdr & satob.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_satob AS
+  SELECT distribid, seqno, window_offset, "*@satob"
+    FROM hdr, sat, satob
+    WHERE obstype = $satob
+     AND 1 <= distribid
+     AND  distribtype = 1
+      AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_scatt.sql b/odb/src/ddl/obsdist_scatt.sql
new file mode 100644
index 0000000..9dd0d2b
--- /dev/null
+++ b/odb/src/ddl/obsdist_scatt.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'obsdist_scatt.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & scatt.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_scatt AS
+  SELECT distribid, seqno, window_offset, "*@scatt"
+    FROM hdr, sat, scatt
+    WHERE obstype = $scatt
+     AND 1 <= distribid
+     AND  distribtype = 1
+      AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_scatt_body.sql b/odb/src/ddl/obsdist_scatt_body.sql
new file mode 100644
index 0000000..608be85
--- /dev/null
+++ b/odb/src/ddl/obsdist_scatt_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_scatt_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_scatt_body AS
+  SELECT distribid, seqno, window_offset, "*@scatt_body"
+    FROM hdr, sat, scatt, scatt_body
+    WHERE obstype = $scatt
+     AND 1 <= distribid
+      AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND  distribtype = 1
+     AND  scatt_body.len > 0
+     AND  scatt_body.len == body.len
+     AND paral($pe, distribid)
+
+;
diff --git a/odb/src/ddl/obsdist_smos.sql b/odb/src/ddl/obsdist_smos.sql
new file mode 100644
index 0000000..939426b
--- /dev/null
+++ b/odb/src/ddl/obsdist_smos.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_smos.sql'
+//
+//   Created:  30-Jun-2010
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window_offset
+
+// Make sure the SQL applies only to rows where sat.len at hdr & smos.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_smos AS
+  SELECT distribid, seqno, window_offset, "*@smos"
+    FROM hdr, sat, smos
+    WHERE obstype = $satem
+      AND codetype = 400
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_ssmi.sql b/odb/src/ddl/obsdist_ssmi.sql
new file mode 100644
index 0000000..5ceae72
--- /dev/null
+++ b/odb/src/ddl/obsdist_ssmi.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_ssmi.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; 
+
+// Make sure the SQL applies only to rows where sat.len at hdr & ssmi.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsdist_ssmi AS
+  SELECT distribid, seqno, window_offset, "*@ssmi"
+    FROM hdr, sat, ssmi
+    WHERE obstype = $satem
+      AND codetype = $ssmi
+      AND (obstype = $obstype OR $obstype = -1 )
+      AND (codetype = $codetype OR $codetype = -1)
+      AND (sensor = $sensor OR $sensor = -1)
+      AND (window_offset = $hdr_min OR $hdr_min = -1)
+      AND 1 <= distribid
+      AND distribtype = 1
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_ssmi_body.sql b/odb/src/ddl/obsdist_ssmi_body.sql
new file mode 100644
index 0000000..edd83b7
--- /dev/null
+++ b/odb/src/ddl/obsdist_ssmi_body.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'obsdist_ssmi_body.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_ssmi_body AS
+  SELECT distribid, seqno, window_offset, "*@ssmi_body"
+    FROM hdr, sat, ssmi, ssmi_body
+   WHERE obstype = $satem
+     AND codetype = $ssmi
+     AND (obstype = $obstype OR $obstype = -1 )
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (window_offset = $hdr_min OR $hdr_min = -1)
+     AND 1 <= distribid
+     AND distribtype = 1
+     AND ssmi_body.len > 0
+     AND ssmi_body.len == body.len
+     AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_1.sql b/odb/src/ddl/obsdist_update_1.sql
new file mode 100644
index 0000000..bb2b7b7
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_1.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_1.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_update_1 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[1]
+       WHERE 1 <= distribid
+       AND  distribtype = 1 
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_10.sql b/odb/src/ddl/obsdist_update_10.sql
new file mode 100644
index 0000000..eb08fba
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_10.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_10.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_update_10 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(10,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_2.sql b/odb/src/ddl/obsdist_update_2.sql
new file mode 100644
index 0000000..a35556d
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_2.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_2.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_update_2 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(2,$nmxupd)]
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_3.sql b/odb/src/ddl/obsdist_update_3.sql
new file mode 100644
index 0000000..173f57f
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_3.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_3.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_update_3 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(3,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_4.sql b/odb/src/ddl/obsdist_update_4.sql
new file mode 100644
index 0000000..c35ba39
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_4.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_4.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; 
+
+CREATE VIEW obsdist_update_4 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(4,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_5.sql b/odb/src/ddl/obsdist_update_5.sql
new file mode 100644
index 0000000..056ab79
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_5.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_5.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_update_5 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(5,$nmxupd)]
+       WHERE 1 <= distribid
+       AND distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_6.sql b/odb/src/ddl/obsdist_update_6.sql
new file mode 100644
index 0000000..08ae024
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_6.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_6.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_update_6 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(6,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_7.sql b/odb/src/ddl/obsdist_update_7.sql
new file mode 100644
index 0000000..980db49
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_7.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_7.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1;
+
+CREATE VIEW obsdist_update_7 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(7,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_8.sql b/odb/src/ddl/obsdist_update_8.sql
new file mode 100644
index 0000000..adf4a07
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_8.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_8.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // ctonains window offset
+
+CREATE VIEW obsdist_update_8 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(8,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_update_9.sql b/odb/src/ddl/obsdist_update_9.sql
new file mode 100644
index 0000000..f1bb1b9
--- /dev/null
+++ b/odb/src/ddl/obsdist_update_9.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsdist_update_9.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY;
+
+SET $pe = 0;
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+SET $hdr_min = -1; // contains window offset
+
+CREATE VIEW obsdist_update_9 AS
+  SELECT distribid, seqno, window_offset, "/.*@update.*/"
+    FROM hdr, update[min(9,$nmxupd)]
+       WHERE 1 <= distribid
+       AND  distribtype = 1
+       AND (obstype = $obstype OR $obstype = -1)
+       AND (codetype = $codetype OR $codetype = -1)
+       AND (sensor = $sensor OR $sensor = -1)
+       AND (window_offset = $hdr_min OR $hdr_min = -1)
+       AND paral($pe, distribid)
+;
diff --git a/odb/src/ddl/obsdist_windows.sql b/odb/src/ddl/obsdist_windows.sql
new file mode 100644
index 0000000..015780d
--- /dev/null
+++ b/odb/src/ddl/obsdist_windows.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'obsdist_windows.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+READONLY; // the view is treated as read/only
+
+CREATE VIEW obsdist_windows AS
+  SELECT distinct window_offset                //  r/o
+    FROM hdr
+      WHERE (distribtype = 1)
+;
diff --git a/odb/src/ddl/obshor.sql b/odb/src/ddl/obshor.sql
new file mode 100644
index 0000000..ae149cb
--- /dev/null
+++ b/odb/src/ddl/obshor.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obshor.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW obshor AS
+  SELECT seqno, // for debugging purposes only
+         timeslot at index, obstype, 
+         codetype,       // for debugging purposes only
+         instrument_type,       // for debugging purposes only
+         retrtype,       // for debugging purposes only
+         areatype,       // for debugging purposes only
+         abnob, mapomm
+    FROM timeslot_index, index, hdr
+   WHERE ($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot)
+ ORDERBY timeslot at index, seqno
+;
diff --git a/odb/src/ddl/obsort_allsky.sql b/odb/src/ddl/obsort_allsky.sql
new file mode 100644
index 0000000..6a36612
--- /dev/null
+++ b/odb/src/ddl/obsort_allsky.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_allsky.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & allsky.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_allsky AS
+  SELECT target, seqno, "*@allsky"
+    FROM index, hdr, sat, radiance, allsky
+   WHERE obstype = $allsky
+     AND codetype = $ssmi
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_allsky_body.sql b/odb/src/ddl/obsort_allsky_body.sql
new file mode 100644
index 0000000..790c56e
--- /dev/null
+++ b/odb/src/ddl/obsort_allsky_body.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_allsky_body.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_allsky_body AS
+  SELECT target, seqno, "*@allsky_body"
+    FROM index, hdr, sat, radiance, allsky, allsky_body, body
+   WHERE obstype = $allsky
+     AND codetype = $ssmi
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  allsky_body.len > 0
+     AND  allsky_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_auxiliary.sql b/odb/src/ddl/obsort_auxiliary.sql
new file mode 100644
index 0000000..feb7300
--- /dev/null
+++ b/odb/src/ddl/obsort_auxiliary.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsort_auxiliary.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_auxiliary AS
+  SELECT target, seqno, "*@auxiliary"
+    FROM index, hdr, auxiliary, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  auxiliary.len > 0
+     AND  auxiliary.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_body.sql b/odb/src/ddl/obsort_body.sql
new file mode 100644
index 0000000..0a06696
--- /dev/null
+++ b/odb/src/ddl/obsort_body.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsort_body.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_body AS
+  SELECT target, seqno, "*@body"
+    FROM index, hdr, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_cloud_sink.sql b/odb/src/ddl/obsort_cloud_sink.sql
new file mode 100644
index 0000000..fa4e11e
--- /dev/null
+++ b/odb/src/ddl/obsort_cloud_sink.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_cloud_sink.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & cloud_sink.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_cloud_sink AS
+  SELECT target, seqno, "*@cloud_sink"
+    FROM index, hdr, sat, radiance, cloud_sink
+   WHERE obstype = $satem
+     AND (codetype = $ssmi OR codetype = $atovs)
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_collocated_imager_information.sql b/odb/src/ddl/obsort_collocated_imager_information.sql
new file mode 100644
index 0000000..8758ef8
--- /dev/null
+++ b/odb/src/ddl/obsort_collocated_imager_information.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsort_collocated_imager_information.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & collocated_imager_information.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_collocated_imager_information AS
+  SELECT target, seqno, "*@collocated_imager_information"
+    FROM index, hdr, sat, radiance, collocated_imager_information
+   WHERE obstype = $satem
+     AND codetype = $atovs
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     AND collocated_imager_information.len > 0
+     AND collocated_imager_information.len == radiance.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_conv.sql b/odb/src/ddl/obsort_conv.sql
new file mode 100644
index 0000000..3d3721c
--- /dev/null
+++ b/odb/src/ddl/obsort_conv.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsort_conv.sql'
+//
+//   Last updated:  22-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where conv.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_conv AS
+  SELECT target, seqno, "*@conv"
+    FROM index, hdr, conv
+   WHERE conv.len > 0
+     AND conv.len == hdr.len
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND ( groupid = 17 OR obstype IN ($synop,$airep,$dribu,$temp,$pilot,$paob) ) //IFS OR AAA-H
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_conv_body.sql b/odb/src/ddl/obsort_conv_body.sql
new file mode 100644
index 0000000..2798d38
--- /dev/null
+++ b/odb/src/ddl/obsort_conv_body.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obsort_conv_body.sql'
+//
+//   Last updated:  22-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_conv_body AS
+  SELECT target, seqno, "*@conv_body"
+    FROM index, hdr, conv, conv_body, body
+   WHERE conv_body.len > 0
+     AND conv_body.len == body.len
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND ( groupid = 17 OR obstype IN ($synop,$airep,$dribu,$temp,$pilot,$paob) ) //IFS OR AAA-H
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_errstat.sql b/odb/src/ddl/obsort_errstat.sql
new file mode 100644
index 0000000..9350a9b
--- /dev/null
+++ b/odb/src/ddl/obsort_errstat.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsort_errstat.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_errstat AS
+  SELECT target, seqno, "*@errstat"
+    FROM index, hdr, errstat, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_gbrad.sql b/odb/src/ddl/obsort_gbrad.sql
new file mode 100644
index 0000000..6861e01
--- /dev/null
+++ b/odb/src/ddl/obsort_gbrad.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_gbrad.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where gbrad.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_gbrad AS
+  SELECT target, seqno, "*@gbrad"
+    FROM index, hdr, gbrad
+   WHERE obstype = $gbrad
+     AND codetype = $radrr
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_gbrad_body.sql b/odb/src/ddl/obsort_gbrad_body.sql
new file mode 100644
index 0000000..637bcf3
--- /dev/null
+++ b/odb/src/ddl/obsort_gbrad_body.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_gbrad_body.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_gbrad_body AS
+  SELECT target, seqno, "*@gbrad_body"
+    FROM index, hdr, gbrad, gbrad_body, body
+   WHERE obstype = $gbrad
+     AND codetype = $radrr
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  gbrad_body.len > 0
+     AND  gbrad_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_gnssro.sql b/odb/src/ddl/obsort_gnssro.sql
new file mode 100644
index 0000000..323ca93
--- /dev/null
+++ b/odb/src/ddl/obsort_gnssro.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_gnssro.sql'
+//
+//   Last updated:  16-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where gnssro.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_gnssro AS
+  SELECT target, seqno, "*@gnssro"
+    FROM index, hdr, sat, gnssro
+   WHERE obstype = $limb
+     AND codetype = $gpsro
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_gnssro_body.sql b/odb/src/ddl/obsort_gnssro_body.sql
new file mode 100644
index 0000000..bd89d2f
--- /dev/null
+++ b/odb/src/ddl/obsort_gnssro_body.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_gnssro_body.sql'
+//
+//   Last updated:  16-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_gnssro_body AS
+  SELECT target, seqno, "*@gnssro_body"
+    FROM index, hdr, sat, gnssro, gnssro_body, body
+   WHERE obstype = $limb
+     AND codetype = $gpsro
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  gnssro_body.len > 0
+     AND  gnssro_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr.sql b/odb/src/ddl/obsort_hdr.sql
new file mode 100644
index 0000000..824410a
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'obsort_hdr.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_hdr AS
+  SELECT target, seqno, "*@hdr"
+    FROM index, hdr
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2allsky_body.sql b/odb/src/ddl/obsort_hdr2allsky_body.sql
new file mode 100644
index 0000000..a5df05a
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2allsky_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2allsky_body.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2allsky_body AS
+  SELECT target, seqno
+    FROM index, hdr, sat, radiance, allsky, body, allsky_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#allsky_body >= 1)
+     AND (allsky_body.len at allsky > 0)
+     AND (obstype = $allsky AND codetype = $ssmi)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2auxiliary_body.sql b/odb/src/ddl/obsort_hdr2auxiliary_body.sql
new file mode 100644
index 0000000..17e1e6b
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2auxiliary_body.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'obsort_hdr2auxiliary_body.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_hdr2auxiliary_body AS
+  SELECT target, seqno
+    FROM index, hdr, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2body.sql b/odb/src/ddl/obsort_hdr2body.sql
new file mode 100644
index 0000000..bf74ff7
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2body.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'obsort_hdr2body.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_hdr2body AS
+  SELECT target, seqno
+    FROM index, hdr, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2conv_body.sql b/odb/src/ddl/obsort_hdr2conv_body.sql
new file mode 100644
index 0000000..e854a23
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2conv_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2conv_body.sql'
+//
+//   Last updated:  22-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2conv_body AS
+  SELECT target, seqno
+    FROM index, hdr, conv, body, conv_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND ( groupid = 17 OR obstype IN ($synop,$airep,$dribu,$temp,$pilot,$paob) ) //IFS OR AAA-H
+     AND (#conv_body >= 1)
+     AND (conv_body.len at conv > 0)
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2gbrad_body.sql b/odb/src/ddl/obsort_hdr2gbrad_body.sql
new file mode 100644
index 0000000..4a2d43e
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2gbrad_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2gbrad_body.sql'
+//
+//   Last updated:  22-July-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2gbrad_body AS
+  SELECT target, seqno
+    FROM index, hdr, gbrad, body, gbrad_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#gbrad_body >= 1)
+     AND (gbrad_body.len at gbrad > 0)
+     AND (obstype = $gbrad AND codetype = $radrr)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2gnssro_body.sql b/odb/src/ddl/obsort_hdr2gnssro_body.sql
new file mode 100644
index 0000000..3fe4fc5
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2gnssro_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2gnssro_body.sql'
+//
+//   Last updated:  16-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2gnssro_body AS
+  SELECT target, seqno
+    FROM index, hdr, sat, gnssro, body, gnssro_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#gnssro_body >= 1)
+     AND (gnssro_body.len at gnssro > 0)
+     AND (obstype = $limb AND codetype = $gpsro)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2radar_body.sql b/odb/src/ddl/obsort_hdr2radar_body.sql
new file mode 100644
index 0000000..f49b571
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2radar_body.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsort_hdr2radar_body.sql'
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2radar_body AS
+  SELECT target, seqno
+   FROM index, hdr, sat, radar, body, radar_body
+   WHERE (   ($all = 1)
+          OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#radar_body >= 1)
+     AND (radar_body.len at radar > 0)
+     AND (obstype = $radar)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2radiance_body.sql b/odb/src/ddl/obsort_hdr2radiance_body.sql
new file mode 100644
index 0000000..873ebd9
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2radiance_body.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsort_hdr2radiance_body.sql'
+//
+//   Last updated:  18-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2radiance_body AS
+  SELECT target, seqno
+    FROM index, hdr, sat, radiance, body, radiance_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#radiance_body >= 1)
+     AND (radiance_body.len at radiance > 0)
+     AND ((obstype = $satem OR obstype = $allsky)
+           AND (codetype = $ssmi OR codetype = $atovs))
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2raingg_body.sql b/odb/src/ddl/obsort_hdr2raingg_body.sql
new file mode 100644
index 0000000..486632a
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2raingg_body.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsort_hdr2raingg_body.sql'
+//
+//   Last updated:  22-July-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2raingg_body AS
+  SELECT target, seqno
+    FROM index, hdr, raingg, body, raingg_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1)
+	  OR ($all = 2 ) )
+     AND  paral($pe, target)
+     AND (#raingg_body >= 1)
+     AND (raingg_body.len at raingg > 0)
+     AND (obstype = $raingg AND codetype = $radrr)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2ralt_body.sql b/odb/src/ddl/obsort_hdr2ralt_body.sql
new file mode 100644
index 0000000..fe46043
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2ralt_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2ralt_body.sql'
+//
+//   Last updated:  14-Aug-2014
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2ralt_body AS
+  SELECT target, seqno
+    FROM index, hdr, sat, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+// we may need to replace the following two by something similar:
+//     AND (#ralt_body >= 1)
+//     AND (ralt_body.len at ralt > 0)
+     AND obstype = $ralt 
+;
diff --git a/odb/src/ddl/obsort_hdr2resat_averaging_kernel.sql b/odb/src/ddl/obsort_hdr2resat_averaging_kernel.sql
new file mode 100644
index 0000000..1e7ceef
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2resat_averaging_kernel.sql
@@ -0,0 +1,38 @@
+//
+//-- ODB/SQL file 'obsort_hdr2resat_averaging_kernel.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2resat_averaging_kernel AS
+  SELECT target, seqno
+    FROM index, hdr, sat, resat, body, resat_averaging_kernel
+   WHERE (   ($all = 1)
+          OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+
+// the following are always true and needed in order to make sure that:
+
+// (a) search order is preserved as in obsort_hdr2body [-> NOREORDER]
+// (b) tables "sat, resat, resat_averaging_kernel"  won't get ignored
+
+     AND (#resat_averaging_kernel >= 1)
+
+// (c) query doesn't return anything, when resat_averaging_kernel is in fact empty
+//      (this is needed only during the transition period when ALIGNment
+//       between body & resat_averaging_kernel may not be established/true)
+
+     AND (resat_averaging_kernel.len at resat > 0)
+
+// (d) data is *REALLY* resat-related (see obsort_resat.sql)
+
+     AND (obstype = $satem) AND (codetype = $resat)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_hdr2scatt_body.sql b/odb/src/ddl/obsort_hdr2scatt_body.sql
new file mode 100644
index 0000000..c9ca949
--- /dev/null
+++ b/odb/src/ddl/obsort_hdr2scatt_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_hdr2scatt_body.sql'
+//
+//   Last updated:  13-Jan-2012
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+NOREORDER; // Do not change the given table order in FROM-statement (important)
+
+CREATE VIEW obsort_hdr2scatt_body AS
+  SELECT target, seqno
+    FROM index, hdr, sat, scatt, body, scatt_body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND (#scatt_body >= 1)
+     AND (scatt_body.len at scatt > 0)
+     AND obstype = $scatt
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_index.sql b/odb/src/ddl/obsort_index.sql
new file mode 100644
index 0000000..e922c84
--- /dev/null
+++ b/odb/src/ddl/obsort_index.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'obsort_index.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_index AS
+  SELECT target, seqno, "*@index"
+    FROM index, hdr
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_limb.sql b/odb/src/ddl/obsort_limb.sql
new file mode 100644
index 0000000..d5e7043
--- /dev/null
+++ b/odb/src/ddl/obsort_limb.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_limb.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & limb.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_limb AS
+  SELECT target, seqno, "*@limb"
+    FROM index, hdr, sat, limb
+   WHERE obstype = $limb
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_modsurf.sql b/odb/src/ddl/obsort_modsurf.sql
new file mode 100644
index 0000000..8f577cd
--- /dev/null
+++ b/odb/src/ddl/obsort_modsurf.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsort_modsurf.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_modsurf AS
+  SELECT target, seqno, "*@modsurf"
+    FROM index, hdr, modsurf
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  modsurf.len == 1
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_radar.sql b/odb/src/ddl/obsort_radar.sql
new file mode 100644
index 0000000..b9472cd
--- /dev/null
+++ b/odb/src/ddl/obsort_radar.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_radar.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radar.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_radar AS
+  SELECT target, seqno, "*@radar"
+    FROM index, hdr, sat, radar
+   WHERE obstype = $radar
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_radar_body.sql b/odb/src/ddl/obsort_radar_body.sql
new file mode 100644
index 0000000..bba66d7
--- /dev/null
+++ b/odb/src/ddl/obsort_radar_body.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obsort_radar_body.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_radar_body AS
+  SELECT target, seqno, "*@radar_body"
+    FROM index, hdr, sat, radar, radar_body, body
+   WHERE obstype = $radar
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  radar_body.len > 0
+     AND  radar_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_radar_station.sql b/odb/src/ddl/obsort_radar_station.sql
new file mode 100644
index 0000000..ad90153
--- /dev/null
+++ b/odb/src/ddl/obsort_radar_station.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_radar_station.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radar_station.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_radar_station AS
+  SELECT target, seqno, "*@radar_station"
+    FROM index, hdr, sat, radar_station
+   WHERE obstype = $radar
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_radiance.sql b/odb/src/ddl/obsort_radiance.sql
new file mode 100644
index 0000000..9fd832b
--- /dev/null
+++ b/odb/src/ddl/obsort_radiance.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_radiance.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & radiance.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_radiance AS
+  SELECT target, seqno, "*@radiance"
+    FROM index, hdr, sat, radiance
+   WHERE (obstype = $satem OR obstype = $allsky)
+     AND (codetype = $ssmi OR codetype = $atovs)
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_radiance_body.sql b/odb/src/ddl/obsort_radiance_body.sql
new file mode 100644
index 0000000..91cf021
--- /dev/null
+++ b/odb/src/ddl/obsort_radiance_body.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_radiance_body.sql'
+//
+//   Last updated:  22-Mar-2011
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_radiance_body AS
+  SELECT target, seqno, "*@radiance_body"
+    FROM index, hdr, sat, radiance, radiance_body, body
+   WHERE (obstype = $satem OR obstype = $allsky)
+     AND (codetype = $ssmi OR codetype = $atovs)
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  radiance_body.len > 0
+     AND  radiance_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_raingg.sql b/odb/src/ddl/obsort_raingg.sql
new file mode 100644
index 0000000..f810ff0
--- /dev/null
+++ b/odb/src/ddl/obsort_raingg.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'obsort_raingg.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where raingg.len at hdr are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_raingg AS
+  SELECT target, seqno, "*@raingg"
+    FROM index, hdr, raingg
+   WHERE obstype = $raingg
+     AND codetype = $radrr
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1)
+	  OR ($all = 2 ) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_raingg_body.sql b/odb/src/ddl/obsort_raingg_body.sql
new file mode 100644
index 0000000..dd4ec84
--- /dev/null
+++ b/odb/src/ddl/obsort_raingg_body.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_raingg_body.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_raingg_body AS
+  SELECT target, seqno, "*@raingg_body"
+    FROM index, hdr, raingg, raingg_body, body
+   WHERE obstype = $raingg
+     AND codetype = $radrr
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1)
+	  OR ($all = 2 ) )
+     AND  paral($pe, target)
+     AND  raingg_body.len > 0
+     AND  raingg_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_ralt.sql b/odb/src/ddl/obsort_ralt.sql
new file mode 100644
index 0000000..463e2eb
--- /dev/null
+++ b/odb/src/ddl/obsort_ralt.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_ralt.sql'
+//
+//   Last updated:  14 August 20146
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & ralt.len at sat are > 0 :
+SAFEGUARD;
+
+//  SELECT target, seqno, "*@ralt"
+CREATE VIEW obsort_ralt  AS
+  SELECT target, seqno
+    FROM index, hdr, body, sat 
+   WHERE obstype = $ralt
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+;
diff --git a/odb/src/ddl/obsort_resat.sql b/odb/src/ddl/obsort_resat.sql
new file mode 100644
index 0000000..07f1048
--- /dev/null
+++ b/odb/src/ddl/obsort_resat.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_resat.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & resat.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_resat AS
+  SELECT target, seqno, "*@resat"
+    FROM index, hdr, sat, resat
+   WHERE obstype = $satem
+     AND (codetype = $resat)
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_resat_averaging_kernel.sql b/odb/src/ddl/obsort_resat_averaging_kernel.sql
new file mode 100644
index 0000000..43df657
--- /dev/null
+++ b/odb/src/ddl/obsort_resat_averaging_kernel.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_resat_averaging_kernel.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_resat_averaging_kernel AS
+  SELECT target, seqno, "*@resat_averaging_kernel"
+    FROM index, hdr, sat, resat, resat_averaging_kernel, body
+   WHERE obstype = $satem
+     AND (codetype = $resat)
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  resat_averaging_kernel.len > 0
+     AND  resat_averaging_kernel.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_sat.sql b/odb/src/ddl/obsort_sat.sql
new file mode 100644
index 0000000..7b2487f
--- /dev/null
+++ b/odb/src/ddl/obsort_sat.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsort_sat.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_sat AS
+  SELECT target, seqno, "*@sat"
+    FROM index, hdr, sat
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  sat.len == 1
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_satob.sql b/odb/src/ddl/obsort_satob.sql
new file mode 100644
index 0000000..048187a
--- /dev/null
+++ b/odb/src/ddl/obsort_satob.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_satob.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & satob.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_satob AS
+  SELECT target, seqno, "*@satob"
+    FROM index, hdr, sat, satob
+   WHERE obstype = $satob
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_scatt.sql b/odb/src/ddl/obsort_scatt.sql
new file mode 100644
index 0000000..57f01ab
--- /dev/null
+++ b/odb/src/ddl/obsort_scatt.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_scatt.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & scatt.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_scatt AS
+  SELECT target, seqno, "*@scatt"
+    FROM index, hdr, sat, scatt
+   WHERE obstype = $scatt
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_scatt_body.sql b/odb/src/ddl/obsort_scatt_body.sql
new file mode 100644
index 0000000..8ddfcbc
--- /dev/null
+++ b/odb/src/ddl/obsort_scatt_body.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obsort_scatt_body.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_scatt_body AS
+  SELECT target, seqno, "*@scatt_body"
+    FROM index, hdr, sat, scatt, scatt_body, body
+   WHERE obstype = $scatt
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  scatt_body.len > 0
+     AND  scatt_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_smos.sql b/odb/src/ddl/obsort_smos.sql
new file mode 100644
index 0000000..4499e3f
--- /dev/null
+++ b/odb/src/ddl/obsort_smos.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'obsort_smos.sql'
+//
+//   Last updated:  20-Jul-2013
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & smos.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_smos AS
+  SELECT target, seqno, "*@smos"
+    FROM index, hdr, sat, smos
+   WHERE obstype = $satem 
+     AND codetype = 400
+     AND (   ($all = 1)
+      OR ($all = 0 AND report_status.active = 1)
+      OR ($all = 2 ) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/obsort_ssmi.sql b/odb/src/ddl/obsort_ssmi.sql
new file mode 100644
index 0000000..9537f90
--- /dev/null
+++ b/odb/src/ddl/obsort_ssmi.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsort_ssmi.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+// Make sure the SQL applies only to rows where sat.len at hdr & ssmi.len at sat are > 0 :
+SAFEGUARD;
+
+CREATE VIEW obsort_ssmi AS
+  SELECT target, seqno, "*@ssmi"
+    FROM index, hdr, sat, ssmi
+   WHERE obstype = $satem
+     AND codetype = $ssmi
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_ssmi_body.sql b/odb/src/ddl/obsort_ssmi_body.sql
new file mode 100644
index 0000000..7da2bf7
--- /dev/null
+++ b/odb/src/ddl/obsort_ssmi_body.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'obsort_ssmi_body.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_ssmi_body AS
+  SELECT target, seqno, "*@ssmi_body"
+    FROM index, hdr, sat, ssmi, ssmi_body, body
+   WHERE obstype = $satem
+     AND codetype = $ssmi
+     AND (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+     AND  paral($pe, target)
+     AND  ssmi_body.len > 0
+     AND  ssmi_body.len == body.len
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_update.sql b/odb/src/ddl/obsort_update.sql
new file mode 100644
index 0000000..125cae8
--- /dev/null
+++ b/odb/src/ddl/obsort_update.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'obsort_update.sql' (obsolete)
+//
+//   Last updated:  20-Jul-2006
+//
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_update AS
+  SELECT target, seqno, "*@update"
+    FROM index, hdr, update, body
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1)
+	  OR ($all = 2 ) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_update_1.sql b/odb/src/ddl/obsort_update_1.sql
new file mode 100644
index 0000000..1a727d9
--- /dev/null
+++ b/odb/src/ddl/obsort_update_1.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsort_update_1.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_update_1 AS
+  SELECT target, seqno, "/.*@update.*/"
+    FROM index, hdr, update[1], body
+   WHERE ( ($all = 1)
+         OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+//   AND update_1.len > 0
+//   AND update_1.len == body.len
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_update_2.sql b/odb/src/ddl/obsort_update_2.sql
new file mode 100644
index 0000000..07bc228
--- /dev/null
+++ b/odb/src/ddl/obsort_update_2.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsort_update_2.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_update_2 AS
+  SELECT target, seqno, "/.*@update.*/"
+    FROM index, hdr, update[min(2,$nmxupd)], body
+   WHERE ( ($all = 1)
+         OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+//   AND update_2.len > 0
+//   AND update_2.len == body.len
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsort_update_3.sql b/odb/src/ddl/obsort_update_3.sql
new file mode 100644
index 0000000..73b9fc0
--- /dev/null
+++ b/odb/src/ddl/obsort_update_3.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsort_update_3.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsort_update_3 AS
+  SELECT target, seqno, "/.*@update.*/"
+    FROM index, hdr, update[min(3,$nmxupd)], body
+   WHERE ( ($all = 1)
+         OR ($all = 0 AND report_status.active at hdr = 1 AND datum_status.active at body = 1) )
+//   AND update_3.len > 0
+//   AND update_3.len == body.len
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_auxiliary.sql b/odb/src/ddl/obsortca_auxiliary.sql
new file mode 100644
index 0000000..c516da5
--- /dev/null
+++ b/odb/src/ddl/obsortca_auxiliary.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'obsortca_auxiliary.sql'
+//
+//   Last updated:  20-Jul-2006
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_auxiliary AS
+  SELECT target, seqno, "*@auxiliary"
+    FROM index, hdr, auxiliary, body
+    WHERE ( ($all >= 1 OR report_status.active at hdr = 1)
+     AND ($all >= 1 OR datum_status.active at body = 1)
+     AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+     AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) )
+     AND  paral($pe, target)
+     AND  auxiliary.len > 0
+     AND  auxiliary.len == body.len
+     ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/obsortca_body.sql b/odb/src/ddl/obsortca_body.sql
new file mode 100644
index 0000000..a4607e6
--- /dev/null
+++ b/odb/src/ddl/obsortca_body.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_body.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_body AS
+  SELECT target, "*@body"
+  FROM index, hdr, body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt,$limb))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob))
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_errstat.sql b/odb/src/ddl/obsortca_errstat.sql
new file mode 100644
index 0000000..e550aac
--- /dev/null
+++ b/odb/src/ddl/obsortca_errstat.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_errstat.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_errstat AS
+  SELECT target, "*@errstat"
+  FROM index, hdr, errstat, body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_hdr.sql b/odb/src/ddl/obsortca_hdr.sql
new file mode 100644
index 0000000..286ee60
--- /dev/null
+++ b/odb/src/ddl/obsortca_hdr.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsortca_hdr.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_hdr AS
+  SELECT target, "*@hdr"
+  FROM index, hdr
+  WHERE ($all >= 1 OR report_status.active = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_hdr2auxiliary_body.sql b/odb/src/ddl/obsortca_hdr2auxiliary_body.sql
new file mode 100644
index 0000000..ca49d76
--- /dev/null
+++ b/odb/src/ddl/obsortca_hdr2auxiliary_body.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obsortca_hdr2auxiliary_body.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_hdr2auxiliary_body AS
+  SELECT target, seqno
+    FROM index, hdr, body
+    WHERE ( ($all >= 1 OR report_status.active at hdr = 1)
+     AND ($all >= 1 OR datum_status.active at body = 1)
+     AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+     AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) )
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/obsortca_hdr2body.sql b/odb/src/ddl/obsortca_hdr2body.sql
new file mode 100644
index 0000000..d829098
--- /dev/null
+++ b/odb/src/ddl/obsortca_hdr2body.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_hdr2body.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_hdr2body AS
+  SELECT target, seqno
+  FROM index, hdr, body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_index.sql b/odb/src/ddl/obsortca_index.sql
new file mode 100644
index 0000000..9b77cb5
--- /dev/null
+++ b/odb/src/ddl/obsortca_index.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'obsortca_index.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_index AS
+  SELECT "*@index"
+    FROM index, hdr
+   WHERE ($all >= 1 OR report_status.active = 1)
+     AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+     AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob))
+     AND  paral($pe, target)
+     ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_update_1.sql b/odb/src/ddl/obsortca_update_1.sql
new file mode 100644
index 0000000..838b672
--- /dev/null
+++ b/odb/src/ddl/obsortca_update_1.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_update_1.sql'
+//
+//   Last updated:  11-Apr-2003
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_update_1 AS
+  SELECT target, "*@update[1]"
+  FROM index, hdr, update[1], body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_update_2.sql b/odb/src/ddl/obsortca_update_2.sql
new file mode 100644
index 0000000..5aa5872
--- /dev/null
+++ b/odb/src/ddl/obsortca_update_2.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_update_2.sql'
+//
+//   Last updated:  11-Apr-2003
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_update_2 AS
+  SELECT target, "/.*@update.*/"
+  FROM index, hdr, update[min(2,$nmxupd)], body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obsortca_update_3.sql b/odb/src/ddl/obsortca_update_3.sql
new file mode 100644
index 0000000..1a34892
--- /dev/null
+++ b/odb/src/ddl/obsortca_update_3.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'obsortca_update_3.sql'
+//
+//   Last updated:  11-Apr-2003
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW obsortca_update_3 AS
+  SELECT target, "/.*@update.*/"
+  FROM index, hdr, update[min(3,$nmxupd)], body
+  WHERE ($all >= 1 OR report_status.active at hdr = 1)
+    AND ($all >= 1 OR datum_status.active at body = 1)
+    AND (timeslot = 4) AND (obstype NOT IN ($satem,$scatt))
+    AND ($all = 2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob)) 
+    AND  paral($pe, target)
+    ORDERBY seqno
+;
diff --git a/odb/src/ddl/obstat.sql b/odb/src/ddl/obstat.sql
new file mode 100644
index 0000000..c79b3e9
--- /dev/null
+++ b/odb/src/ddl/obstat.sql
@@ -0,0 +1,41 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)],
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  vertco_reference_2,
+//   18
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date, 
+//   19      20      21    22  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    23          24          25          26
+  datum_anflag, datum_event1 at body
+//   27        28    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, modsurf, body, update[min(2,$nmxupd)], errstat
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_conv.sql b/odb/src/ddl/obstat_conv.sql
new file mode 100644
index 0000000..e88ebf4
--- /dev/null
+++ b/odb/src/ddl/obstat_conv.sql
@@ -0,0 +1,41 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_conv AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid at hdr, biascorr_fg,
+//   13          14         15        16      17
+  vertco_reference_2,
+//   18
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date, 
+//   19      20      21    22  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    23          24          25          26
+  datum_anflag, datum_event1 at body, sonde_type at conv
+//   27        28    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, modsurf, body, update[min(2,$nmxupd)], errstat, conv
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_fcdep.sql b/odb/src/ddl/obstat_fcdep.sql
new file mode 100644
index 0000000..216940d
--- /dev/null
+++ b/odb/src/ddl/obstat_fcdep.sql
@@ -0,0 +1,43 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_fcdep AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, vertco_reference_1,
+//   1     2    3     4  
+  obsvalue, fg_depar, an_depar, fc_depar at fcdiagnostic_body[1], fc_depar at fcdiagnostic_body[2],
+//   5       6          7          8                               9 
+  obs_error, fg_error,
+//     10         11
+  hires at update[min(2,$nmxupd)], 
+//   12              13               14
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   16          17         18        19      20
+  vertco_reference_2,
+//   21
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date, 
+//   22      23      24    25  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    26          27          28          29
+  datum_anflag, datum_event1 at body
+//   30        31    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, body, update[min(2,$nmxupd)], errstat, fcdiagnostic, fcdiagnostic_body[1:2]
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_fcdep_gpsro.sql b/odb/src/ddl/obstat_fcdep_gpsro.sql
new file mode 100644
index 0000000..778925a
--- /dev/null
+++ b/odb/src/ddl/obstat_fcdep_gpsro.sql
@@ -0,0 +1,42 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_fcdep_gpsro AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, fc_depar at fcdiagnostic_body[1], fc_depar at fcdiagnostic_body[2], obs_error,
+//   5        6          7          8         9   
+  fg_error, hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  vertco_reference_2,
+//   18
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, satellite_instrument, time, date, 
+//   19      20      21    22  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    23          24          25          26
+  datum_anflag, datum_event1 at body,
+//   27        28    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+  radcurv at gnssro, retrtype
+//   29      30
+FROM hdr, modsurf, gnssro, sat, body, update[min(2,$nmxupd)], errstat, fcdiagnostic, fcdiagnostic_body[1:2]
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstat_geos.sql b/odb/src/ddl/obstat_geos.sql
new file mode 100644
index 0000000..3712f48
--- /dev/null
+++ b/odb/src/ddl/obstat_geos.sql
@@ -0,0 +1,41 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_geos AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9
+  hires at update_2, 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+   csr_pclear at radiance_body,
+//   18
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date,
+//   19       20     21    22
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    23          24          25          26
+  datum_anflag, datum_event1 at body
+//   27        28
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, modsurf, body, update_2, errstat, radiance_body
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_gpsro.sql b/odb/src/ddl/obstat_gpsro.sql
new file mode 100644
index 0000000..1f59f0e
--- /dev/null
+++ b/odb/src/ddl/obstat_gpsro.sql
@@ -0,0 +1,42 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_gpsro AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  vertco_reference_2,
+//   18
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, satellite_instrument, time, date, 
+//   19      20      21    22  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    23          24          25          26
+  datum_anflag, datum_event1 at body,
+//   27        28    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+  radcurv at gnssro, retrtype 
+//   29      30
+FROM hdr, modsurf, sat, gnssro, body, update[min(2,$nmxupd)], errstat
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstat_mwimg.sql b/odb/src/ddl/obstat_mwimg.sql
new file mode 100644
index 0000000..6393295
--- /dev/null
+++ b/odb/src/ddl/obstat_mwimg.sql
@@ -0,0 +1,39 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_mwimg AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4      5
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   6        7          8          9         10
+  hires at update_2, 
+//   11              12               13
+  qc_pge, qc_l, biascorr, statid, biascorr_fg, vertco_reference_2,
+//   14          15         16        17      18        19
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date,
+//   20      21       22   23
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//     24          25          26         27
+  datum_anflag, datum_event1 at body, report_tbcloud
+//   28          29      30
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, modsurf, body, update_2, errstat, sat, allsky
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_radar.sql b/odb/src/ddl/obstat_radar.sql
new file mode 100644
index 0000000..40c801d
--- /dev/null
+++ b/odb/src/ddl/obstat_radar.sql
@@ -0,0 +1,42 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_radar AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, vertco_reference_1 at body,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  lores at update_1, hires at update_1, lores at update_2,
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  vertco_reference_2,
+//   18
+  elevation at radar_body, azimuth at radar_body, 
+//   19      20
+// --------- Integer part of sql request -------------
+  codetype, satellite_identifier at sat, time at hdr, date, 
+//   21      22      23    24  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    25          26          27          28
+  datum_anflag, datum_event1 at body,
+//   29        30    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM index, hdr, sat, radar, radar_body, body, update_1,update_2, errstat
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time at hdr,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstat_resat.sql b/odb/src/ddl/obstat_resat.sql
new file mode 100644
index 0000000..e89ebca
--- /dev/null
+++ b/odb/src/ddl/obstat_resat.sql
@@ -0,0 +1,44 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_resat AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  solar_elevation at resat, vertco_reference_2, quality_retrieval at resat,
+//   18                     19           20
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date, 
+//   21      22      23    24  
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    25          26          27          28
+  datum_anflag, datum_event1 at body,
+//   29        30    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+  product_type at resat
+//  31
+
+FROM hdr, modsurf, body, update[min(2,$nmxupd)], errstat, sat, resat
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_satob.sql b/odb/src/ddl/obstat_satob.sql
new file mode 100644
index 0000000..c0669dc
--- /dev/null
+++ b/odb/src/ddl/obstat_satob.sql
@@ -0,0 +1,41 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_satob AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9
+  hires at update_2,
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  qi_fc at satob, qi_nofc at satob,
+//   18           19
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor,datastream at sat, time, date,
+//   20       21     22             23    24
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    25          26          27          28
+  datum_anflag, datum_event1 at body
+//   29        30
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, modsurf, body, update_2, errstat, satob, sat
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_scatt.sql b/odb/src/ddl/obstat_scatt.sql
new file mode 100644
index 0000000..0007795
--- /dev/null
+++ b/odb/src/ddl/obstat_scatt.sql
@@ -0,0 +1,40 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_scatt AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg, cellno at scatt,
+//   13          14         15        16      17
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, datastream at sat, time, date,
+//   19      20      21              22    23
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    24          25          26          27
+  datum_anflag, datum_event1 at body
+//   28        29    
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM hdr, body, update[min(2,$nmxupd)], errstat, sat, scatt
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND (varno at body IN (124,125,180))
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
+
diff --git a/odb/src/ddl/obstat_smos.sql b/odb/src/ddl/obstat_smos.sql
new file mode 100644
index 0000000..10fec11
--- /dev/null
+++ b/odb/src/ddl/obstat_smos.sql
@@ -0,0 +1,39 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_smos AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error, incidence_angle at smos,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg, vertco_reference_2, 
+// 18              19           20
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date,
+// 21         22          23         24    25
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    26          27          28          29
+  datum_anflag, datum_event1 at body, polarisation at smos
+//    30        31
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM index, hdr, body, update[min(2,$nmxupd)], errstat, sat, smos, modsurf
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND (report_tbflag at smos = 8)
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstat_smos_land.sql b/odb/src/ddl/obstat_smos_land.sql
new file mode 100644
index 0000000..5751fce
--- /dev/null
+++ b/odb/src/ddl/obstat_smos_land.sql
@@ -0,0 +1,39 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_smos_land AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error, incidence_angle at smos,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg, vertco_reference_2, 
+// 18              19           20
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, time, date,
+// 21         22          23         24    25
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    26          27          28          29
+  datum_anflag, datum_event1 at body, polarisation at smos
+//    30        31
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM index, hdr, body, update[min(2,$nmxupd)], errstat, sat, smos, modsurf
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND (report_tbflag at smos = 1)
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstat_tovs.sql b/odb/src/ddl/obstat_tovs.sql
new file mode 100644
index 0000000..427f4d8
--- /dev/null
+++ b/odb/src/ddl/obstat_tovs.sql
@@ -0,0 +1,40 @@
+READONLY;
+
+SET $use_twindow = 0;
+SET $refdate=0; // Reference date (OBSTAT_BASEDATE's yyyymmdd)
+SET $reftime=0; // Reference time (OBSTAT_BASEDATE's hhmmss)
+SET $refdt_l=0; // Left delta margin  (usually : - OBSTAT_TSTEP/2 + 1 minute)
+SET $refdt_r=0; // Right delta margin (usually : + OBSTAT_TSTEP/2 ... exact)
+
+SET $body_min =  1;
+SET $body_max = -1;
+
+CREATE VIEW obstat_tovs AS 
+SELECT
+// --------- Real part of sql request -------------
+   varno, lat, lon, lsm, vertco_reference_1,
+//   1     2    3     4
+  obsvalue, fg_depar, an_depar, obs_error, fg_error,
+//   5        6          7          8         9   
+  hires at update[min(2,$nmxupd)], 
+//   10              11               12
+  qc_pge, qc_l, biascorr, statid, biascorr_fg,
+//   13          14         15        16      17
+  scanpos at radiance, cldcover, vertco_reference_2, 
+// 18              19           20
+// --------- Integer part of sql request -------------
+  codetype, obstype, subtype, sensor, datastream at sat, time, date,
+// 21         22          23         24    25
+  datum_status at body, report_status at hdr, report_event1 at hdr, report_rdbflag at hdr,
+//    26          27          28          29
+  datum_anflag, datum_event1 at body
+//    30        31
+// --------- Auxiliary part of sql request (only used in odbread.F90)
+FROM index, hdr, modsurf, body, update[min(2,$nmxupd)], errstat, sat, radiance
+WHERE (($body_max == -1) OR
+       (#body BETWEEN $body_min AND $body_max))   // delta-rows is $OBSTAT_BODY_CHUNK
+      AND
+      (( $use_twindow = 0) OR
+       ( $use_twindow > 0 AND
+         twindow(date,time,$refdate,$reftime,$refdt_l,$refdt_r)))
+;
diff --git a/odb/src/ddl/obstatfc_1.sql b/odb/src/ddl/obstatfc_1.sql
new file mode 100644
index 0000000..7995173
--- /dev/null
+++ b/odb/src/ddl/obstatfc_1.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_1.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_1 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(1,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_10.sql b/odb/src/ddl/obstatfc_10.sql
new file mode 100644
index 0000000..a5e6029
--- /dev/null
+++ b/odb/src/ddl/obstatfc_10.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_10.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_10 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(10,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_11.sql b/odb/src/ddl/obstatfc_11.sql
new file mode 100644
index 0000000..d396a08
--- /dev/null
+++ b/odb/src/ddl/obstatfc_11.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_11.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_11 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(11,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_12.sql b/odb/src/ddl/obstatfc_12.sql
new file mode 100644
index 0000000..4820ae8
--- /dev/null
+++ b/odb/src/ddl/obstatfc_12.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_12.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_12 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(12,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_13.sql b/odb/src/ddl/obstatfc_13.sql
new file mode 100644
index 0000000..8d891e0
--- /dev/null
+++ b/odb/src/ddl/obstatfc_13.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_13.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_13 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(13,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_14.sql b/odb/src/ddl/obstatfc_14.sql
new file mode 100644
index 0000000..47cf2e7
--- /dev/null
+++ b/odb/src/ddl/obstatfc_14.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_14.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_14 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(14,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_15.sql b/odb/src/ddl/obstatfc_15.sql
new file mode 100644
index 0000000..8b691a1
--- /dev/null
+++ b/odb/src/ddl/obstatfc_15.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_15.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_15 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(15,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_16.sql b/odb/src/ddl/obstatfc_16.sql
new file mode 100644
index 0000000..08cb21d
--- /dev/null
+++ b/odb/src/ddl/obstatfc_16.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_16.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_16 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(16,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_17.sql b/odb/src/ddl/obstatfc_17.sql
new file mode 100644
index 0000000..d12d279
--- /dev/null
+++ b/odb/src/ddl/obstatfc_17.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_17.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_17 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(17,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_18.sql b/odb/src/ddl/obstatfc_18.sql
new file mode 100644
index 0000000..257dec9
--- /dev/null
+++ b/odb/src/ddl/obstatfc_18.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_18.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_18 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(18,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_19.sql b/odb/src/ddl/obstatfc_19.sql
new file mode 100644
index 0000000..454801e
--- /dev/null
+++ b/odb/src/ddl/obstatfc_19.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_19.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_19 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(19,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_2.sql b/odb/src/ddl/obstatfc_2.sql
new file mode 100644
index 0000000..0e60b4a
--- /dev/null
+++ b/odb/src/ddl/obstatfc_2.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_2.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_2 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(2,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_20.sql b/odb/src/ddl/obstatfc_20.sql
new file mode 100644
index 0000000..0372ac2
--- /dev/null
+++ b/odb/src/ddl/obstatfc_20.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_20.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_20 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(20,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_3.sql b/odb/src/ddl/obstatfc_3.sql
new file mode 100644
index 0000000..151b2d8
--- /dev/null
+++ b/odb/src/ddl/obstatfc_3.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_3.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_3 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(3,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_4.sql b/odb/src/ddl/obstatfc_4.sql
new file mode 100644
index 0000000..07265bd
--- /dev/null
+++ b/odb/src/ddl/obstatfc_4.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_4.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_4 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(4,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_5.sql b/odb/src/ddl/obstatfc_5.sql
new file mode 100644
index 0000000..41d74e3
--- /dev/null
+++ b/odb/src/ddl/obstatfc_5.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_5.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_5 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(5,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_6.sql b/odb/src/ddl/obstatfc_6.sql
new file mode 100644
index 0000000..58373b1
--- /dev/null
+++ b/odb/src/ddl/obstatfc_6.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_6.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_6 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(6,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_7.sql b/odb/src/ddl/obstatfc_7.sql
new file mode 100644
index 0000000..219643e
--- /dev/null
+++ b/odb/src/ddl/obstatfc_7.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_7.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_7 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(7,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_8.sql b/odb/src/ddl/obstatfc_8.sql
new file mode 100644
index 0000000..f69e0bb
--- /dev/null
+++ b/odb/src/ddl/obstatfc_8.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_8.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_8 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(8,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstatfc_9.sql b/odb/src/ddl/obstatfc_9.sql
new file mode 100644
index 0000000..c6bdb3c
--- /dev/null
+++ b/odb/src/ddl/obstatfc_9.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'obstatfc_9.sql'
+//
+//   Last updated:  06/09/10
+//   By          :  Gabor Radnoti 
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW obstatfc_9 AS
+  SELECT
+    seqno, entryno, 
+    an_depar,
+    fc_depar UPDATED,
+    FROM   timeslot_index, index, hdr, body, fcdiagnostic, fcdiagnostic_body[min(9,$nmxfcdiag)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/obstype.h b/odb/src/ddl/obstype.h
new file mode 100644
index 0000000..4db24b7
--- /dev/null
+++ b/odb/src/ddl/obstype.h
@@ -0,0 +1,52 @@
+// CMA observation types (obstype at hdr) :
+
+SET  $SYNOP = 1;
+SET  $AIREP = 2;
+SET  $SATOB = 3;
+SET  $DRIBU = 4;
+SET  $BUYO  = 4;
+SET  $TEMP  = 5;
+SET  $PILOT = 6;
+SET  $SATEM = 7;
+SET  $PAOB  = 8;
+SET  $SCATT = 9;
+SET  $LIMB  = 10;
+SET  $ISAC  = 11;
+SET  $RALT  = 12;
+SET  $RADAR = 13;
+SET  $GBRAD = 14;
+SET  $LIDAR = 15;
+SET  $ALLSKY = 16;
+SET  $RAINGG = 17;
+SET  $IMSIMS = 18;
+
+// CMA codetypes (used to be in obschar.codetype at hdr) for $SATEM :
+
+SET  $REO3 = 206;
+SET  $RESAT = 206;
+SET  $ATOVS = 210;
+SET  $RTOVS = 211;
+SET  $TOVS = 212;
+SET  $SSMI = 215;
+SET  $TCWC = 214;
+SET  $RADRR = 3;
+SET  $AEOLUS = 187;
+
+SET $satem500 = 86;
+SET $satem250 = 186;
+SET $rad1c = 210;
+
+SET $gpsro = 250;
+SET $lrad  = 251;
+
+
+SET synop_land = 11;
+SET synop_land_auto = 14;
+SET add_land_surface = 17;
+
+// Report types (various SYNOP rain gauge accumulations)
+SET synop_rg1h  = 39001;
+SET synop_rg3h  = 39002;
+SET synop_rg6h  = 39003;
+SET synop_rg12h = 39004;
+SET synop_rg24h = 39005;
diff --git a/odb/src/ddl/odb.h b/odb/src/ddl/odb.h
new file mode 120000
index 0000000..f8c74ef
--- /dev/null
+++ b/odb/src/ddl/odb.h
@@ -0,0 +1 @@
+../include/odb.h
\ No newline at end of file
diff --git a/odb/src/ddl/odb2ee_aeolus_auxmet.sql b/odb/src/ddl/odb2ee_aeolus_auxmet.sql
new file mode 100644
index 0000000..882be76
--- /dev/null
+++ b/odb/src/ddl/odb2ee_aeolus_auxmet.sql
@@ -0,0 +1,19 @@
+CREATE VIEW odb2ee_aeolus_auxmet AS
+    SELECT seqno at hdr,
+lat at hdr, lon at hdr, lev at aeolus_auxmet,
+ptop at aeolus_auxmet, pnom at aeolus_auxmet, ztop at aeolus_auxmet, znom at aeolus_auxmet, 
+u at aeolus_auxmet, v at aeolus_auxmet, 
+t at aeolus_auxmet, rh at aeolus_auxmet, 
+q at aeolus_auxmet, cc at aeolus_auxmet, 
+clwc at aeolus_auxmet, ciwc at aeolus_auxmet, 
+timeslot at timeslot_index, timeslot at index, 
+date at hdr, time at hdr, 
+andate at desc, antime at desc, 
+error_t at aeolus_auxmet, error_rh at aeolus_auxmet, error_p at aeolus_auxmet, 
+aeolus_hdrflag at aeolus_hdr, 
+retrtype at hdr
+     FROM hdr, sat, aeolus_hdr, aeolus_auxmet, timeslot_index, index, desc
+     WHERE retrtype at hdr=1
+     ORDERBY date at hdr,time at hdr,aeolus_hdrflag at aeolus_hdr
+;
+
diff --git a/odb/src/ddl/odb98.flags b/odb/src/ddl/odb98.flags
new file mode 100644
index 0000000..9cabdf0
--- /dev/null
+++ b/odb/src/ddl/odb98.flags
@@ -0,0 +1,75 @@
+#
+# Default flags for odb98 compiler
+#
+# These flags can be overridden by command line flags
+#
+# Activation:
+#
+# Syntax: 
+#  - One flag per line
+#  - flag is recognized if line begins with dash '-'
+#  - leading blanks and tabs and empty lines are ignored
+#
+# Activation: export ODB_COMPILER_FLAGS=<this_file_name>
+#
+# Author: Sami Saarinen, ECMWF, 1999
+#
+#-----------------------------------
+#
+# Note: In order to have any effect from the following -1 or -A
+#       options, -O3 optimization level must be activated.
+#       This can be reverted back to say -O2 in the cmd line.
+#
+#-O3
+#-----------------------------------
+#
+# The -1xxx=yyy means:
+#
+# Assume no more than one sub-entry in yyy-table when going over
+# a @LINK to it from xxx-table.
+# So called one-to-one option.
+#
+# Alternative format:
+#
+# -1master_table=slave_1,slave_2,...,slave_N
+#
+# or
+#
+# -1master_table=(slave_1,slave_2,...,slave_N)
+#
+-1index=hdr
+-1hdr=sat
+-1sat=(resat,atovs,ssmi,scatt,satob,satem,radar_station,radar)
+#
+#-----------------------------------
+#
+# The -Axxx=yyy means:
+# 
+# Table xxx is to be aligned with table yyy, i.e. they
+# are assumed to have the same number of entries and thus
+# could be fused into the same search loop.
+# So called automatic align option i.e. ALIGN(xxx,yyy,...)
+# is implied by default.
+#
+# Alternative format:
+#
+# -Amaster_table=slave_1,slave_2,...,slave_N
+#
+# or
+#
+# -Amaster_table=(slave_1,slave_2,...,slave_N)
+#
+#-Abody=(update,errstat,rtovs_body,scatt_body,ssmi_body)
+-Abody=(update,errstat,allsky_body,scatt_body,ssmi_body,radar_body, resat_averaging_kernel,update_1,update_2,update_3,update_4)
+-Aatovs=atovs_pred
+#
+#-----------------------------------
+#
+#
+# Merge table indices of aligned slave tables with their master
+# (requires at least -O3 optimization, too)
+#
+#-m
+#
+#-- EOF
+#
diff --git a/odb/src/ddl/odb_info.sql b/odb/src/ddl/odb_info.sql
new file mode 100644
index 0000000..4451298
--- /dev/null
+++ b/odb/src/ddl/odb_info.sql
@@ -0,0 +1,4 @@
+CREATE VIEW odb_info AS
+SELECT expver,andate,antime
+FROM   desc
+;
diff --git a/odb/src/ddl/odb_macros.h b/odb/src/ddl/odb_macros.h
new file mode 120000
index 0000000..2082332
--- /dev/null
+++ b/odb/src/ddl/odb_macros.h
@@ -0,0 +1 @@
+../include/odb_macros.h
\ No newline at end of file
diff --git a/odb/src/ddl/odbcrc.h b/odb/src/ddl/odbcrc.h
new file mode 120000
index 0000000..0313e9d
--- /dev/null
+++ b/odb/src/ddl/odbcrc.h
@@ -0,0 +1 @@
+../include/odbcrc.h
\ No newline at end of file
diff --git a/odb/src/ddl/odbmd5.h b/odb/src/ddl/odbmd5.h
new file mode 120000
index 0000000..7331ca5
--- /dev/null
+++ b/odb/src/ddl/odbmd5.h
@@ -0,0 +1 @@
+../include/odbmd5.h
\ No newline at end of file
diff --git a/odb/src/ddl/out_body.sql b/odb/src/ddl/out_body.sql
new file mode 100644
index 0000000..d9fe6cf
--- /dev/null
+++ b/odb/src/ddl/out_body.sql
@@ -0,0 +1,22 @@
+SET $utc = -1;
+
+SET $varno = -1;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+SET $press = -1;
+
+CREATE VIEW out_body AS
+  SELECT boxid,  // Must be the first entry
+         orography, // Must be the second entry
+         "*@body"
+    FROM desc, hdr, modsurf,body
+   WHERE utc = $utc
+     AND varno = $varno
+     AND (obstype = $obstype OR $obstype = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+     AND (vertco_reference_1 = $press)
+;
diff --git a/odb/src/ddl/out_desc.sql b/odb/src/ddl/out_desc.sql
new file mode 100644
index 0000000..58c1a34
--- /dev/null
+++ b/odb/src/ddl/out_desc.sql
@@ -0,0 +1,17 @@
+SET $utc = -1;
+
+SET $varno = -1;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW out_desc AS
+  SELECT *
+    FROM desc
+//   WHERE utc = $utc
+//     AND varno = $varno
+//     AND (obstype = $obstype OR $obstype = -1)
+//     AND (codetype = $codetype OR $codetype = -1)
+//     AND (sensor = $sensor OR $sensor = -1)
+;
diff --git a/odb/src/ddl/out_hdr.sql b/odb/src/ddl/out_hdr.sql
new file mode 100644
index 0000000..9a0ae2e
--- /dev/null
+++ b/odb/src/ddl/out_hdr.sql
@@ -0,0 +1,17 @@
+SET $utc = -1;
+
+SET $varno = -1;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW out_hdr AS
+  SELECT "*@hdr" // boxid at hdr is implicitly the first entry
+    FROM desc, hdr
+   WHERE utc = $utc
+     AND varno = $varno
+     AND (obstype = $obstype OR $obstype = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor = $sensor OR $sensor = -1)
+;
diff --git a/odb/src/ddl/ozone_robhdr_1.sql b/odb/src/ddl/ozone_robhdr_1.sql
new file mode 100644
index 0000000..a43a69e
--- /dev/null
+++ b/odb/src/ddl/ozone_robhdr_1.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'ozone_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW ozone_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len  READONLY,           // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type at hdr,          // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         sensor,                       // possibly updated (in ECMA)
+         report_rdbflag,               // r/o
+         report_status,                // possibly updated (in ECMA)
+         report_event1,                // possibly updated (in ECMA)
+         report_event2,                // possibly updated (in ECMA)
+         date,                         // r/o
+         time,                         // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+         retrsource,                   // r/o
+  FROM   timeslot_index, index, hdr, resat
+  WHERE	 obstype = $satem
+    AND  (codetype = $resat)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/ozone_robody_1.sql b/odb/src/ddl/ozone_robody_1.sql
new file mode 100644
index 0000000..b5f9aa7
--- /dev/null
+++ b/odb/src/ddl/ozone_robody_1.sql
@@ -0,0 +1,37 @@
+//
+//-- ODB/SQL file 'ozone_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW ozone_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,            // possibly updated
+         datum_event2 at body,            // possibly updated
+         datum_status at body,            // possibly updated
+         datum_anflag at body,            // possibly updated
+         datum_rdbflag at body,           // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a, qc_l,                // possibly updated
+         qc_pge,
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+         obs_ak_error,                 // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  obstype = $satem
+    AND  codetype = $resat
+    AND	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pcma_extern.h b/odb/src/ddl/pcma_extern.h
new file mode 120000
index 0000000..ef41751
--- /dev/null
+++ b/odb/src/ddl/pcma_extern.h
@@ -0,0 +1 @@
+../include/pcma_extern.h
\ No newline at end of file
diff --git a/odb/src/ddl/pertobs_corr_robhdr.sql b/odb/src/ddl/pertobs_corr_robhdr.sql
new file mode 100644
index 0000000..f1071a0
--- /dev/null
+++ b/odb/src/ddl/pertobs_corr_robhdr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'pertobs_corr_robhdr.sql'
+//
+//   Last updated:  14-Oct-2004
+//
+
+READONLY; // All read/only except selected columns marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW pertobs_corr_robhdr AS
+  SELECT seqno,               // r/o; MUST BE FIRST
+         body.len,            // r/o
+         report_status,       // r/o
+         obstype,             // r/o
+         lat,                 // r/o
+         lon,                 // r/o
+         codetype,            // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
\ No newline at end of file
diff --git a/odb/src/ddl/pertobs_corr_robody.sql b/odb/src/ddl/pertobs_corr_robody.sql
new file mode 100644
index 0000000..cc04906
--- /dev/null
+++ b/odb/src/ddl/pertobs_corr_robody.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'pertobs_corr_robody.sql'
+//
+//   Last updated:  14-Oct-2004
+//
+
+UPDATED; // the default: all updated (except those with  READONLY or  READONLY)
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW pertobs_corr_robody AS
+  SELECT seqno  READONLY,              // r/o; MUST BE FIRST
+         datum_status at body READONLY,   // r/o
+         varno at body READONLY,          // r/o
+         vertco_reference_1 at body READONLY,  // r/o
+         final_obs_error READONLY,     // r/o
+         obsvalue,                     // updated
+         hires at update[1],              // updated
+         fg_depar at body,                // updated
+  FROM   timeslot_index, index, hdr, body, errstat, update[1]
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
\ No newline at end of file
diff --git a/odb/src/ddl/pertobs_uncorr_robhdr.sql b/odb/src/ddl/pertobs_uncorr_robhdr.sql
new file mode 100644
index 0000000..cd7815f
--- /dev/null
+++ b/odb/src/ddl/pertobs_uncorr_robhdr.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'pertobs_uncorr_robhdr.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // All read/only except selected columns marked with  UPDATED
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW pertobs_uncorr_robhdr AS
+  SELECT seqno,               // r/o; MUST BE FIRST
+         body.len,            // r/o
+         report_status,              // r/o
+         obstype,             // r/o
+         codetype,            // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pertobs_uncorr_robody.sql b/odb/src/ddl/pertobs_uncorr_robody.sql
new file mode 100644
index 0000000..9c6da29
--- /dev/null
+++ b/odb/src/ddl/pertobs_uncorr_robody.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'pertobs_uncorr_robody.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+UPDATED; // the default: all updated (except those with  READONLY or  READONLY)
+
+SET $kset = 0;
+SET $tslot = -1;
+
+CREATE VIEW pertobs_uncorr_robody AS
+  SELECT seqno  READONLY,              // r/o; MUST BE FIRST
+         datum_status at body READONLY,         // r/o
+         vertco_reference_1 at body READONLY,   // r/o
+         final_obs_error READONLY,     // r/o
+         obsvalue,                     // updated
+         hires at update[1],              // updated
+         fg_depar at body,                // updated
+  FROM   timeslot_index, index, hdr, body, errstat, update[1]
+  WHERE	 (kset = $kset)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/poolmask_1.sql b/odb/src/ddl/poolmask_1.sql
new file mode 100644
index 0000000..a387fd1
--- /dev/null
+++ b/odb/src/ddl/poolmask_1.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'poolmask_1.sql'
+//
+//   Last updated:  15-Oct-2001
+//
+
+SET $obstype  = -1;
+SET $codetype = -1;
+SET $sensor   = -1;
+
+READONLY;
+
+CREATE VIEW poolmask_1 AS
+  SELECT DISTINCT poolno
+    FROM poolmask
+   WHERE (obstype  = $obstype  OR $obstype  = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor   = $sensor   OR $sensor   = -1)
+;
diff --git a/odb/src/ddl/poolmask_2.sql b/odb/src/ddl/poolmask_2.sql
new file mode 100644
index 0000000..2ccf838
--- /dev/null
+++ b/odb/src/ddl/poolmask_2.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'poolmask_2.sql'
+//
+//   Last updated:  15-Oct-2001
+//
+
+SET $obstype  = -1;
+SET $codetype = -1;
+SET $sensor   = -1;
+SET $tslot    = -1;
+
+READONLY;
+
+CREATE VIEW poolmask_2 AS
+  SELECT DISTINCT poolno
+    FROM poolmask
+   WHERE (obstype  = $obstype  OR $obstype  = -1)
+     AND (codetype = $codetype OR $codetype = -1)
+     AND (sensor   = $sensor   OR $sensor   = -1)
+     AND (timeslot    = $tslot    OR $tslot    = -1)
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_2.sql b/odb/src/ddl/post_thinn_robhdr_2.sql
new file mode 100644
index 0000000..fae40d3
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_2.sql
@@ -0,0 +1,37 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_2.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $ksensor_v = 0; // Must be initialized to zero
+
+CREATE VIEW post_thinn_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+         zenith,                       // r/o
+         scanline at radiance             // r/o
+  FROM   timeslot_index, index, hdr, sat, radiance
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $atovs)
+    AND  (in_vector(sensor, $ksensor_v))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_3.sql b/odb/src/ddl/post_thinn_robhdr_3.sql
new file mode 100644
index 0000000..635052f
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_3.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_3.sql'
+//
+//   Last updated:  31-Mar-2010
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         sensor,                 // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+	     lat, lon                      // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_4.sql b/odb/src/ddl/post_thinn_robhdr_4.sql
new file mode 100644
index 0000000..2ad86d5
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_4.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_4.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         gen_centre,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon                      // r/o
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_5.sql b/odb/src/ddl/post_thinn_robhdr_5.sql
new file mode 100644
index 0000000..06c20a7
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_5.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_5.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         gen_centre,                   // r/o
+         QI_fc at satob,                   // r/o
+         QI_nofc at satob,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+	     lat, lon                  // r/o
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_6.sql b/odb/src/ddl/post_thinn_robhdr_6.sql
new file mode 100644
index 0000000..595abde
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_6.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_6.sql'
+//
+//   Last updated:  08-Nov-2007
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+	     lat, lon                      // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  ( obstype = $obstype )
+    AND  (codetype = $codetype)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_7.sql b/odb/src/ddl/post_thinn_robhdr_7.sql
new file mode 100644
index 0000000..a05e3f0
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_7.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_7.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                         // r/o
+	     time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status UPDATED,               // possibly updated (in ECMA)
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+	     lat, lon                      // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $satem500)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_8.sql b/odb/src/ddl/post_thinn_robhdr_8.sql
new file mode 100644
index 0000000..6729394
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_8.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_8.sql'
+//
+//   Last updated:  13-Aug-2004
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW post_thinn_robhdr_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+//       obschar,                      // r/o
+         codetype,                     // r/o
+         instrument_type at hdr,          // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robhdr_9.sql b/odb/src/ddl/post_thinn_robhdr_9.sql
new file mode 100644
index 0000000..49cc222
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robhdr_9.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'post_thinn_robhdr_9.sql'
+//
+//   Last updated:  07-Dec-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robhdr_9 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+	     lat, lon                      // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = 10)
+    AND  (codetype =  250)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_2.sql b/odb/src/ddl/post_thinn_robody_2.sql
new file mode 100644
index 0000000..6a2dedf
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_2.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_2.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $ksensor_v = 0; // Must be initialized to zero
+
+CREATE VIEW post_thinn_robody_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+         repres_error,                 // r/o
+         obsvalue,                     // r/o
+         fg_depar,                     // r/o
+         vertco_reference_1,           // r/o
+         vertco_reference_2,           // r/o
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $atovs)
+    AND  (in_vector(sensor, $ksensor_v))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_3.sql b/odb/src/ddl/post_thinn_robody_3.sql
new file mode 100644
index 0000000..d3a2f44
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_3.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_3.sql'
+//
+//   Last updated:  31-Mar-2010
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_4.sql b/odb/src/ddl/post_thinn_robody_4.sql
new file mode 100644
index 0000000..9e46302
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_4.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_4.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         vertco_reference_1,           // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+   AND   (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_5.sql b/odb/src/ddl/post_thinn_robody_5.sql
new file mode 100644
index 0000000..c944c9a
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_5.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_5.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         vertco_reference_1,           // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_6.sql b/odb/src/ddl/post_thinn_robody_6.sql
new file mode 100644
index 0000000..66477df
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_6.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_6.sql'
+//
+//   Last updated:  08-Nov-2007
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  ( obstype = $obstype )
+    AND  (codetype = $codetype)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_7.sql b/odb/src/ddl/post_thinn_robody_7.sql
new file mode 100644
index 0000000..ed5fc57
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_7.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_7.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $satem500)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_8.sql b/odb/src/ddl/post_thinn_robody_8.sql
new file mode 100644
index 0000000..6263425
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_8.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_8.sql'
+//
+//   Last updated:  130-Aug-2004
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW post_thinn_robody_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+//  AND  (obschar.codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/post_thinn_robody_9.sql b/odb/src/ddl/post_thinn_robody_9.sql
new file mode 100644
index 0000000..d67c600
--- /dev/null
+++ b/odb/src/ddl/post_thinn_robody_9.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'post_thinn_robody_9.sql'
+//
+//   Last updated:  07-Dec-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW post_thinn_robody_9 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = 10)
+    AND  (codetype =  250)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/ppcode.h b/odb/src/ddl/ppcode.h
new file mode 100644
index 0000000..2c9d037
--- /dev/null
+++ b/odb/src/ddl/ppcode.h
@@ -0,0 +1,15 @@
+// Synop pressure codes (ppcode at body) :
+
+SET $psealev  = 0;      // press at body is SEA LEVEL PRESSURE
+SET $pstalev  = 1;	//      "        STATION LEVEL PRESSURE
+SET $g850hpa  = 2;	//      "	 850MB GEOPOTENTIAL
+SET $g700hpa  = 3;	//      "	 700MB GEOPOTENTIAL
+SET $p500gpm  = 4;	//      "	 500GPM PRESSURE
+SET $p1000gpm = 5;	//      "	 1000GPM PRESSURE
+SET $p2000gpm = 6;	//      "	 2000GPM PRESSURE
+SET $p3000gpm = 7;	//      "	 3000GPM PRESSURE
+SET $p4000gpm = 8;	//      "	 4000GPM PRESSURE
+SET $g900hpa  = 9;	//      "	 900MB GEOPOTENTIAL
+SET $g1000hpa = 10;	//      "	 1000MB GEOPOTENTIAL
+SET $g500hpa  = 11;	//      "	 500MB GEOPOTENTIAL
+SET $g925hpa  = 12;	//      "	 925MB GEOPOTENTIAL
diff --git a/odb/src/ddl/pre_thinn_robhdr_10.sql b/odb/src/ddl/pre_thinn_robhdr_10.sql
new file mode 100644
index 0000000..604c5e0
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_10.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_10.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_10 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status UPDATED,               // possibly updated (in ECMA)
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_11.sql b/odb/src/ddl/pre_thinn_robhdr_11.sql
new file mode 100644
index 0000000..b6373ba
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_11.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_11.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_11 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status UPDATED,        // possibly updated (in ECMA)
+         report_event1 UPDATED,        // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+    WHERE  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_2.sql b/odb/src/ddl/pre_thinn_robhdr_2.sql
new file mode 100644
index 0000000..afa390a
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_2.sql
@@ -0,0 +1,41 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_2.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+
+READONLY;
+
+SET $tslot = -1;
+SET $ksensor_v = 0; // Must be initialized to zero
+
+CREATE VIEW pre_thinn_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+         zenith,                       // r/o
+         scanline at radiance,            // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr, sat, radiance
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  ((codetype = $atovs)
+     OR   (codetype = $atovs))
+    AND  (in_vector(sensor, $ksensor_v))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_3.sql b/odb/src/ddl/pre_thinn_robhdr_3.sql
new file mode 100644
index 0000000..16fe47b
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_3.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_3.sql'
+//
+//   Last updated: 31-Mar-2010
+// For MERIS (TCWC only)
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         sensor,                 // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_4.sql b/odb/src/ddl/pre_thinn_robhdr_4.sql
new file mode 100644
index 0000000..e11293a
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_4.sql
@@ -0,0 +1,37 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_4.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         gen_centre,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_5.sql b/odb/src/ddl/pre_thinn_robhdr_5.sql
new file mode 100644
index 0000000..512b6a4
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_5.sql
@@ -0,0 +1,38 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_5.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,              // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         gen_centre,                   // r/o
+         QI_fc at satob,                   // r/o
+         QI_nofc at satob,                   // r/o
+         comp_method,                  // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_6.sql b/odb/src/ddl/pre_thinn_robhdr_6.sql
new file mode 100644
index 0000000..1ea302c
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_6.sql
@@ -0,0 +1,36 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_6.sql'
+//
+//   Last updated:  08-Nov-2007
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         sensor,                       // r/o
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  ( obstype = $obstype )
+    AND  (codetype = $codetype)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_7.sql b/odb/src/ddl/pre_thinn_robhdr_7.sql
new file mode 100644
index 0000000..7a1ea88
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_7.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_7.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	     date,                         // r/o
+	     time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status UPDATED,               // possibly updated (in ECMA)
+         report_event1 UPDATED,               // possibly updated (in ECMA)
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $satem500)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_8.sql b/odb/src/ddl/pre_thinn_robhdr_8.sql
new file mode 100644
index 0000000..0efcc48
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_8.sql
@@ -0,0 +1,36 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_8.sql'
+//
+//   Last updated:  13-Aug-2004
+//
+
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW pre_thinn_robhdr_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                     // r/o
+         instrument_type at hdr,          // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,       // possibly updated (in ECMA)
+         report_event1  UPDATED,       // possibly updated (in ECMA)
+         sensor,                       // r/o
+         statid,                       // r/o
+         trlat, trlon,                 // r/o
+     	 lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robhdr_9.sql b/odb/src/ddl/pre_thinn_robhdr_9.sql
new file mode 100644
index 0000000..358dad7
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robhdr_9.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'pre_thinn_robhdr_9.sql'
+//
+//   Last updated:  07-Dec-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robhdr_9 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         codetype,                    // r/o
+         instrument_type,              // r/o
+         retrtype,               // r/o
+         areatype,                    // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         thinningkey[1:$NUMTHBOX] UPDATED,      // u
+         thinningtimekey UPDATED       // u
+  FROM   timeslot_index, index, hdr
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = 10)
+    AND  (codetype =  250)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_10.sql b/odb/src/ddl/pre_thinn_robody_10.sql
new file mode 100644
index 0000000..04921b8
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_10.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_10.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_10 AS
+  SELECT entryno,                      // r/o
+         datum_status at body,                  // possibly updated (in ECMA)
+         datum_event1 at body,                  // possibly updated (in ECMA)
+         varno,                        // r/o
+         fg_depar,                     // r/o
+         obs_error,                     // r/o
+         azimuth at radar_body                       // r/o
+  FROM   timeslot_index, index, hdr, body, errstat, sat, radar, radar_body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_11.sql b/odb/src/ddl/pre_thinn_robody_11.sql
new file mode 100644
index 0000000..0bdcec0
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_11.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_11.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_11 AS
+  SELECT entryno,                      // r/o
+         datum_status at body,            // possibly updated (in ECMA)
+         datum_event1 at body,            // possibly updated (in ECMA)
+         varno,                        // r/o
+         fg_depar,                     // r/o
+         obs_error,                     // r/o 
+         azimuth at radar_body                       // r/o
+  FROM   timeslot_index, index, hdr, body, errstat, sat, radar, radar_body
+    WHERE  (obstype = $radar)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_2.sql b/odb/src/ddl/pre_thinn_robody_2.sql
new file mode 100644
index 0000000..23544a6
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_2.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_2.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+
+READONLY;
+
+SET $tslot = -1;
+SET $ksensor_v = 0; // Must be initialized to zero
+
+CREATE VIEW pre_thinn_robody_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         varno,                        // r/o
+         repres_error,                 // r/o
+         obsvalue,                     // r/o
+         fg_depar,                     // r/o
+         vertco_reference_1,           // r/o
+         vertco_reference_2,           // r/o
+         csr_pclear,                   // r/o
+  FROM   timeslot_index, index, hdr, sat, radiance, body, errstat, radiance_body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $atovs)
+    AND  (in_vector(sensor, $ksensor_v))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_3.sql b/odb/src/ddl/pre_thinn_robody_3.sql
new file mode 100644
index 0000000..4bee167
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_3.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_3.sql'
+//
+//   Last updated: 31-Mar-2010 
+//   For TCWC (MERIS,etc.) only
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $tcwc)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_4.sql b/odb/src/ddl/pre_thinn_robody_4.sql
new file mode 100644
index 0000000..0220320
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_4.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_4.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         vertco_reference_1,           // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+   AND   (obstype = $satob)
+    AND  ((codetype =  88)
+    OR    (codetype =  89))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_5.sql b/odb/src/ddl/pre_thinn_robody_5.sql
new file mode 100644
index 0000000..87d3cf1
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_5.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_5.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,    // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,    // possibly updated (in ECMA)
+         vertco_reference_1,           // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satob)
+    AND  (codetype =  90)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_6.sql b/odb/src/ddl/pre_thinn_robody_6.sql
new file mode 100644
index 0000000..256d475
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_6.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_6.sql'
+//
+//   Last updated:  08-Nov-2007
+//
+
+READONLY;
+
+SET $obstype = -1;
+SET $codetype = -1;
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  ( obstype = $obstype )
+    AND  (codetype = $codetype)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_7.sql b/odb/src/ddl/pre_thinn_robody_7.sql
new file mode 100644
index 0000000..cd5da74
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_7.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_7.sql'
+//
+//   Last updated:  05-Mar-2003
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+//WHERE  (obstype = $satem)
+    AND  (codetype = $satem500)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_8.sql b/odb/src/ddl/pre_thinn_robody_8.sql
new file mode 100644
index 0000000..e21f8cb
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_8.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_8.sql'
+//
+//   Last updated:  13-Aug-2004
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $sensor = -1;
+
+CREATE VIEW pre_thinn_robody_8 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         varno,                        // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = $satem)
+    AND  (codetype = $resat)
+//  AND  (obschar.codetype = $resat)
+    AND  ($sensor == -1 OR sensor == $sensor)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/pre_thinn_robody_9.sql b/odb/src/ddl/pre_thinn_robody_9.sql
new file mode 100644
index 0000000..c6887d1
--- /dev/null
+++ b/odb/src/ddl/pre_thinn_robody_9.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'pre_thinn_robody_9.sql'
+//
+//   Last updated:  18-Dec-2007
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW pre_thinn_robody_9 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,   // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,   // possibly updated (in ECMA)
+         varno,                        // r/o
+         bg_layerno,                    // r/o
+         vertco_reference_2,           // r/o
+  FROM   timeslot_index, index, hdr, body, sat, gnssro, gnssro_body
+  WHERE	 (report_status.passive at hdr + report_status.rejected at hdr + report_status.blacklisted at hdr == 0)
+    AND  (obstype = 10)
+    AND  (codetype =  250)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/privpub.h b/odb/src/ddl/privpub.h
new file mode 120000
index 0000000..3ceacc9
--- /dev/null
+++ b/odb/src/ddl/privpub.h
@@ -0,0 +1 @@
+../include/privpub.h
\ No newline at end of file
diff --git a/odb/src/ddl/prtdpst_robhdr.sql b/odb/src/ddl/prtdpst_robhdr.sql
new file mode 100644
index 0000000..5fad90b
--- /dev/null
+++ b/odb/src/ddl/prtdpst_robhdr.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'prtdpst_robhdr.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW prtdpst_robhdr AS
+  SELECT seqno, body.len,
+	 obstype, 
+     codetype,
+     instrument_type,
+     retrtype,
+     areatype,
+  FROM   index, hdr
diff --git a/odb/src/ddl/prtdpst_robody.sql b/odb/src/ddl/prtdpst_robody.sql
new file mode 100644
index 0000000..927ecc3
--- /dev/null
+++ b/odb/src/ddl/prtdpst_robody.sql
@@ -0,0 +1,11 @@
+//
+//-- ODB/SQL file 'prtdpst_robody.sql'
+//
+//   Last updated:  10-Oct-2001
+//
+
+CREATE VIEW prtdpst_robody AS
+  SELECT seqno, entryno, varno,
+	 vertco_reference_1, vertco_reference_2, an_depar,  // body
+	 hires                // update[1]
+  FROM   index, hdr, body, update[1]
diff --git a/odb/src/ddl/radar.h b/odb/src/ddl/radar.h
new file mode 100644
index 0000000..9c1d25f
--- /dev/null
+++ b/odb/src/ddl/radar.h
@@ -0,0 +1,29 @@
+//
+// Table Definition: radar tables
+// Used by MF
+//
+SET $mx_radar_niv = 15;
+CREATE TABLE radar AS (
+  iternoconv_1dv     pk1int,          // Number of iterations (1DVAR)
+  failure_1dv        pk1int,          // Error indicator (1DVAR) 
+  qmod[$mx_radar_niv]   pk9real,      // humidity at model levels 
+  zsimp[$mx_radar_niv]  pk9real,      // simple reflectivity          
+  radar_body  @LINK, 
+);
+
+CREATE TABLE radar_body AS (
+  flgdyn        pk1int,              // dynamic quality flag 
+  time          HHMMSS,              // Site starting hour associated to one pixel ???
+  distance      pk9real,             // distance to the radar (meters) 
+  elevation     pk9real,             // elevation 
+  polarisation  pk9real,             // polarity
+  anaprop       pk1int,              // Indicator of anaprop ???
+  reflcost      pk9real,             // Cost function of the 1DVAR 
+  azimuth       pk9real,             // azimuth (of the measurement (angle N/radar->pixel))
+  press          pk9real,            // pressure 1Dvar
+  temp[2]        pk9real,            // temperature 1Dvar
+  q[2]           pk9real,            // specific humidity 
+  temp_1dv       pk9real,            // error 1Dvar for temperature
+  q_1dv          pk9real,            // error 1Dvar for humidity 
+);
+
diff --git a/odb/src/ddl/radar_station.h b/odb/src/ddl/radar_station.h
new file mode 100644
index 0000000..590e115
--- /dev/null
+++ b/odb/src/ddl/radar_station.h
@@ -0,0 +1,14 @@
+CREATE TABLE radar_station AS (
+  ident          pk1int,          // radar identifier
+  type           string,          // type of radar
+
+// Should be named something like latrad if different to lat, etc.? Why is it different?
+// To be clarified by Meteo-France
+  lat            pk9real,         // latitude of the radar
+  lon            pk9real,         // longitude of the radar
+  stalt          pk9real,         // altitude of the radar
+  antenht        pk9real,         // height of the antenna
+  beamwidth      pk9real,         // aperture at 3dBz
+  frequency      pk9real,         // pulse frequency
+);
+
diff --git a/odb/src/ddl/radiance.h b/odb/src/ddl/radiance.h
new file mode 100644
index 0000000..adc9d78
--- /dev/null
+++ b/odb/src/ddl/radiance.h
@@ -0,0 +1,53 @@
+//
+// Table Definitions: radiance (header-like table for all radiances)
+//
+CREATE TABLE radiance AS (
+  scanline                                     pk1int,   // Scan line number
+  scanpos                                      pk1int,   // Position number along scan / Field of View number
+  orbit                                        pk1int,   // Orbit number
+  typesurf                                     pk1int,   // Type of surface
+  corr_version                                 pk1int,   // non linear correction version (a set of coefficients for each version)
+  cldcover                                     pk1int,   // CLOUD PERCENTAGE FROM VISNIR FOR AIRS
+  cldptop[1:3]                                 pk9real,  // CLOUD TOP PRESS. FROM TOVS HIRS RADIANCES: 3 values for 3 differents methods
+  cldne[1:3]                                   pk9real,  // CLOUD EMISSIVITY FROM TOVS HIRS RADIANCES: 3 values for 3 differents methods
+  skintemper                                   pk9real,  // skin temperture background error 
+  skintemp[$NMXUPD+1]                          pk9real,  // skin temperture per NRESUPD, 1 - FG, 2 - end of 1st min, 3 - end of 2nd min, etc
+  scatterindex_89_157                          pk9real,  // Scatter index from 89 and 157 GHz channels
+  scatterindex_23_89                           pk9real,  // Scatter index from 23 and 89 GHz channels
+  scatterindex_23_165                          pk9real,  // Scatter index from 23 and 165 GHz channels
+  lwp_obs                                      pk9real,  // Regression-based liquid water path from observations
+
+  asr_pclear                                   pk1int,   // All-sky AMOUNT SEGMENT CLOUD FREE ASR RADIANCES
+  asr_pcloudy                                  pk1int,   // All-sky CLOUD AMOUNT IN SEGMENT ASR RADIANCES
+  asr_pcloudy_low                              pk1int,   // All-sky CLOUD AMOUNT IN SEGMENT LOW-CLOUDS
+  asr_pcloudy_middle                           pk1int,   // All-sky CLOUD AMOUNT IN SEGMENT MIDLE-CLOUDS
+  asr_pcloudy_high                             pk1int,   // All-sky CLOUD AMOUNT IN SEGMENT HIGH-CLOUDS
+// Children tables
+  allsky                                       @LINK,    // allsky/mwave processing
+  cloud_sink                                   @LINK,    // processing of cloud sink variables, still unclear...
+  collocated_imager_information                @LINK,    // specific entries (from bufr2odb) for IASI - for post-processing only
+  radiance_body                                @LINK,    // specific entries for all radiances boody-like table
+);
+
+
+CREATE TABLE radiance_body AS(
+  csr_pclear      pk9real,      // Percentage of clear pixels in mean CSR
+  cld_fg_depar    pk9real,      // FG departure for cloudy radiances
+  rank_cld        pk9real,      // channel ranking for cloud detection for AIRS and IASI only.
+  tausfc          pk9real,      // Surface transmittance for radiances - to be moved to radiance_body table
+  skintemp_retr   pk9real,      // Skin temperature retrieved from observations, emissivity atlas and FG
+  tbclear         pk9real,      // Diagnostic clear-sky FG brightness temperature
+
+  emis_rtin       pk9real,      // Input surface emissivity for RTTOV (can be outside 0-1 to prompt internal calculations)
+  emis_atlas      pk9real,      // Surface emissivity estimate from an atlas
+  emis_atlas_error pk9real,     // Error in surface emissivity estimate from an atlas
+  emis_retr       pk9real,      // Surface emissivity retrieved from observations and FG
+  emis_fg         pk9real,      // Surface emissivity used in FG simulations (pre-set or RTTOV-internal)
+  cold_nedt       pk9real,      //  NOISE-EQUIVALENT DELTA TEMPERATURE WHILE VIEWING COLD TARGET
+  warm_nedt       pk9real,      //  NOISE-EQUIVALENT DELTA TEMPERATURE WHILE VIEWING COLD TARGET
+  channel_qc      pk1int,       //  Channel quality 12 bits
+  nobs_averaged   pk1int,       // number of obs. used for averaging obsvalues (mask can be 2x2, 3x3, etc.)
+  stdev_averaged  pk9real,      // Standard deviation of averaged values
+  zenith_by_channel pk9real,      // Satellite zenith angle (if variable by channel, rarely, some microwave imagers, e.g. GMI)
+);
+
diff --git a/odb/src/ddl/radiance_averaging.sql b/odb/src/ddl/radiance_averaging.sql
new file mode 100644
index 0000000..2009696
--- /dev/null
+++ b/odb/src/ddl/radiance_averaging.sql
@@ -0,0 +1,53 @@
+//
+//-- ODB/SQL file 'radiance_averaging.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+set $satellite_identifier=-1;
+set $channel=-1;
+
+READONLY;
+CREATE VIEW radiance_averaging AS
+  SELECT seqno, 
+         entryno,
+         orbit,
+         time,
+         scanpos UPDATED, 
+         satellite_identifier,
+         nobs_averaged UPDATED,
+         stdev_averaged UPDATED,
+         vertco_reference_1,
+         obsvalue UPDATED,
+         date, 
+         scanline, 
+         subtype,
+         bufrtype,
+         statid,
+         lat UPDATED,
+         lon UPDATED,
+         stalt,
+         numlev,
+         sensor,
+         satellite_instrument at sat,
+         obstype,
+         codetype,
+         varno,
+         vertco_type,
+         gen_centre,
+         gen_subcentre,
+         zenith UPDATED,
+         azimuth UPDATED,
+         solar_zenith,
+         solar_azimuth,
+         reportype,
+         groupid,
+         channel_qc UPDATED,
+    FROM hdr,sat, radiance, body, radiance_body
+    where datastream=0
+    and   satellite_identifier=$satellite_identifier
+    and   vertco_reference_1=$channel
+    orderby gen_centre, gen_subcentre, date, time, scanpos, orbit, scanline
+;
+
diff --git a/odb/src/ddl/radiance_update_links.sql b/odb/src/ddl/radiance_update_links.sql
new file mode 100644
index 0000000..bef1924
--- /dev/null
+++ b/odb/src/ddl/radiance_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'radiance_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW radiance_update_links AS
+  SELECT "/LINK.*/"
+    FROM radiance
+;
+
diff --git a/odb/src/ddl/raingg.h b/odb/src/ddl/raingg.h
new file mode 100644
index 0000000..c2fa81a
--- /dev/null
+++ b/odb/src/ddl/raingg.h
@@ -0,0 +1,14 @@
+//
+// Table Definition: raingg tables
+//
+CREATE TABLE raingg AS (
+  report_rrflag           pk1int,       // Rain Rate status flag - See yomraingg.F90
+  raingg_body              @LINK,
+);
+
+CREATE TABLE raingg_body AS (
+  rrvalue                 pk9real,       // Simulated rain rates
+  rrvaluetl               pk9real,       // Simulated TL of rain rates
+  rrvaluead               pk9real,       // Simulated AD of rain rates
+);
+
diff --git a/odb/src/ddl/raingg_body_rr.sql b/odb/src/ddl/raingg_body_rr.sql
new file mode 100644
index 0000000..2a67905
--- /dev/null
+++ b/odb/src/ddl/raingg_body_rr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'raingg_body_rr.sql'
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW raingg_body_rr AS
+
+  SELECT seqno  READONLY,          // MDBONM (used to build MLNKH2B)
+         rrvalue at raingg_body,      // MDB_RRVALUE    raingg_body
+         rrvaluetl at raingg_body,    // MDB_RRVALUETL  raingg_body
+         rrvaluead at raingg_body,    // MDB_RRVALUEAD  raingg_body
+
+  FROM   timeslot_index, index, hdr, raingg_body
+
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+          AND kset = $kset 
+          AND reportype >= $synop_rg6h AND reportype <= $synop_rg24h
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/raingg_rr.sql b/odb/src/ddl/raingg_rr.sql
new file mode 100644
index 0000000..08c1ac8
--- /dev/null
+++ b/odb/src/ddl/raingg_rr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'raingg_rr.sql'
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW raingg_rr AS
+  SELECT seqno,                    // MDBONM (must be the first index; used to build MLNKH2B)
+         report_rrflag at raingg,     // MDB_REPORT_RRFLAG  raingg
+
+  FROM   timeslot_index, index, hdr, raingg
+
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset 
+     AND reportype >= $synop_rg6h AND reportype <= $synop_rg24h
+ ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/ralt.sql b/odb/src/ddl/ralt.sql
new file mode 100644
index 0000000..4c03628
--- /dev/null
+++ b/odb/src/ddl/ralt.sql
@@ -0,0 +1,9 @@
+CREATE VIEW ralt  AS
+SELECT  date, time, lat, lon, satellite_identifier at sat,
+        obsvalue, fg_depar, an_depar,datastream,varno
+FROM    hdr, body, sat
+WHERE   obstype=12
+  AND   varno IN (220, 221)
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/ralt_wam.sql b/odb/src/ddl/ralt_wam.sql
new file mode 100644
index 0000000..b81c382
--- /dev/null
+++ b/odb/src/ddl/ralt_wam.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'ralt_wam.sql'
+//
+//   Last updated:  10-Feb-2015
+//
+
+CREATE VIEW ralt_wam AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         obstype,                      // r/o
+         codetype,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         varno,                        // r/o
+         obsvalue,                     // r/o
+         biascorr,                     // r/o
+         obs_error,                    // r/o
+         satellite_identifier,         // r/o
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+         gp_number,                    // r/o
+         report_status,
+         report_event1,
+         report_event2,
+         datum_status,
+         datum_event1,
+         datum_event2,
+         distribtype,                  // type of distribution - default is 0 i.e. no redistribution
+         sensor at hdr,
+  FROM   hdr, sat, body, errstat
+  WHERE         obstype = $ralt
+;
diff --git a/odb/src/ddl/redun_robhdr_1.sql b/odb/src/ddl/redun_robhdr_1.sql
new file mode 100644
index 0000000..1255f64
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_1.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'redun_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 obstype IN ($synop, $paob)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_2.sql b/odb/src/ddl/redun_robhdr_2.sql
new file mode 100644
index 0000000..9ba5200
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_2.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'redun_robhdr_2.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 obstype IN ($synop, $dribu, $temp, $paob)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_3.sql b/odb/src/ddl/redun_robhdr_3.sql
new file mode 100644
index 0000000..59db8bc
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_3.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'redun_robhdr_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+	     lat, lon,                 // r/o
+         statid,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $synop)
+    AND  codetype IN (21 , 22, 23, 24)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_4.sql b/odb/src/ddl/redun_robhdr_4.sql
new file mode 100644
index 0000000..481a0c7
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_4.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'redun_robhdr_4.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         trlat, trlon,                 // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $airep)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_5.sql b/odb/src/ddl/redun_robhdr_5.sql
new file mode 100644
index 0000000..1c56fba
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_5.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'redun_robhdr_5.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+	     date,                     // r/o
+	     time,                     // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         obstype,                      // r/o
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         lat, lon,                     // r/o
+         trlat, trlon,                 // r/o
+         statid,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $dribu)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_6.sql b/odb/src/ddl/redun_robhdr_6.sql
new file mode 100644
index 0000000..2418042
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_6.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'redun_robhdr_6.sql'
+//
+//   Last updated:  10-Apr-2014
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         bufrtype at hdr,                 // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         statid,                       // r/o
+         trlat,                        // r/o
+         trlon,                        // r/o
+	 lat, lon,                     // r/o
+ 	 numlev,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 obstype IN ($temp, $pilot)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robhdr_7.sql b/odb/src/ddl/redun_robhdr_7.sql
new file mode 100644
index 0000000..ba791aa
--- /dev/null
+++ b/odb/src/ddl/redun_robhdr_7.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'redun_robhdr_7.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robhdr_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         date,                         // r/o
+         time,                         // r/o
+         obstype,                      // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         statid,                       // r/o
+         lat, lon,                     // r/o
+         trlat, trlon,                 // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 obstype IN ($temp, $synop)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_1.sql b/odb/src/ddl/redun_robody_1.sql
new file mode 100644
index 0000000..e959a8d
--- /dev/null
+++ b/odb/src/ddl/redun_robody_1.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'redun_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body UPDATED,          // possibly updated (in ECMA)
+         datum_event1 at body UPDATED,          // possibly updated (in ECMA)
+         an_sens_obs at body,             // r/o 
+         final_obs_error at errstat  UPDATED,          // possibly updated (in ECMA)
+         varno UPDATED,                // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 obstype IN ($synop, $paob)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_2.sql b/odb/src/ddl/redun_robody_2.sql
new file mode 100644
index 0000000..e9f76e9
--- /dev/null
+++ b/odb/src/ddl/redun_robody_2.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'redun_robody_2.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         varno  UPDATED,               // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 obstype IN ($synop, $dribu, $temp, $paob)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_3.sql b/odb/src/ddl/redun_robody_3.sql
new file mode 100644
index 0000000..00792d3
--- /dev/null
+++ b/odb/src/ddl/redun_robody_3.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'redun_robody_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (obstype = $synop)
+    AND  codetype IN (21, 22, 23, 24)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_4.sql b/odb/src/ddl/redun_robody_4.sql
new file mode 100644
index 0000000..ec1f7e8
--- /dev/null
+++ b/odb/src/ddl/redun_robody_4.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'redun_robody_4.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_4 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,   // possibly updated (in ECMA)
+         varno,                        // r/o
+         vertco_reference_1,           // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (obstype = $airep)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_5.sql b/odb/src/ddl/redun_robody_5.sql
new file mode 100644
index 0000000..1df17f3
--- /dev/null
+++ b/odb/src/ddl/redun_robody_5.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'redun_robody_5.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_5 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 (obstype = $dribu)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_6.sql b/odb/src/ddl/redun_robody_6.sql
new file mode 100644
index 0000000..e45fa4c
--- /dev/null
+++ b/odb/src/ddl/redun_robody_6.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'redun_robody_6.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_6 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,         // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,         // possibly updated (in ECMA)
+         datum_anflag,                       // r/o
+         level at conv_body,                        // r/o
+         vertco_type,                  // r/o
+         varno,                        // r/o
+         vertco_reference_1,                        // r/o
+  FROM   timeslot_index, index, hdr, body, conv, conv_body
+  WHERE	 obstype IN ($temp, $pilot)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/redun_robody_7.sql b/odb/src/ddl/redun_robody_7.sql
new file mode 100644
index 0000000..2c57e5f
--- /dev/null
+++ b/odb/src/ddl/redun_robody_7.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'redun_robody_7.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW redun_robody_7 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body  UPDATED,   // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,   // possibly updated (in ECMA)
+         varno  UPDATED,               // possibly updated (in ECMA)
+         vertco_reference_1,           // r/o
+         obsvalue,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE	 obstype IN ($temp, $synop)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/reini_body.sql b/odb/src/ddl/reini_body.sql
new file mode 100644
index 0000000..ab80402
--- /dev/null
+++ b/odb/src/ddl/reini_body.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'reini_body.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+UPDATED;
+
+CREATE VIEW reini_body AS
+  SELECT datum_status at body,                       // updated
+	 datum_event1 at body,                       // updated
+	 datum_blacklist at body,                    // updated
+	 datum_anflag at body,                       // updated
+  FROM   hdr, body
+;
diff --git a/odb/src/ddl/reini_hdr.sql b/odb/src/ddl/reini_hdr.sql
new file mode 100644
index 0000000..b6e0073
--- /dev/null
+++ b/odb/src/ddl/reini_hdr.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'reini_hdr.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+CREATE VIEW reini_hdr AS
+  SELECT body.len  READONLY,           // r/o
+	 report_status,                       // updated
+	 report_event1,                       // updated
+	 report_blacklist,                    // updated
+  FROM   hdr
+;
diff --git a/odb/src/ddl/reprod_seqno_1.sql b/odb/src/ddl/reprod_seqno_1.sql
new file mode 100644
index 0000000..f8a998f
--- /dev/null
+++ b/odb/src/ddl/reprod_seqno_1.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'reprod_seqno_1.sql'
+//
+//   Last updated:  05-Jul-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW reprod_seqno_1 AS
+  SELECT seqno UPDATED, // The only time seqno is updated ?
+         bufrtype, subtype,
+         timeslot at timeslot_index, date, time,
+         lat, lon,
+	 stalt, statid
+    FROM timeslot_index, index, hdr
+   WHERE (timeslot at timeslot_index = $tslot OR $tslot = -1)
+ORDER BY timeslot at timeslot_index, bufrtype, subtype, date, time, lat, lon, stalt, statid
+;
diff --git a/odb/src/ddl/reprod_seqno_2.sql b/odb/src/ddl/reprod_seqno_2.sql
new file mode 100644
index 0000000..d20edd4
--- /dev/null
+++ b/odb/src/ddl/reprod_seqno_2.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'reprod_seqno_2.sql'
+//
+//   Last updated:  05-Jul-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW reprod_seqno_2 AS
+  SELECT seqno UPDATED, // The only time seqno is updated ?
+         obstype, codetype, // These MUST be be in this order here
+         timeslot at timeslot_index, date, time,
+         lat, lon,
+	 stalt, statid
+    FROM timeslot_index, index, hdr
+   WHERE (timeslot at timeslot_index = $tslot OR $tslot = -1)
+   ORDER BY timeslot at timeslot_index, obstype, codetype, date, time, lat, lon, stalt, statid
+;
diff --git a/odb/src/ddl/reprod_seqno_3.sql b/odb/src/ddl/reprod_seqno_3.sql
new file mode 100644
index 0000000..ce7cd62
--- /dev/null
+++ b/odb/src/ddl/reprod_seqno_3.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'reprod_seqno_3.sql'
+//
+//   Last updated:  05-Jul-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW reprod_seqno_3 AS
+  SELECT seqno UPDATED, // The only time seqno is updated ?
+         obstype, codetype, // These MUST be be in this order here
+         sensor,
+         timeslot at timeslot_index, date, time,
+         lat, lon,
+	 stalt, statid
+    FROM timeslot_index, index, hdr
+   WHERE (timeslot at timeslot_index = $tslot OR $tslot = -1)
+   ORDER BY timeslot at timeslot_index, obstype, codetype, sensor, date, time, lat, lon, stalt, statid
+;
diff --git a/odb/src/ddl/reprod_seqno_4.sql b/odb/src/ddl/reprod_seqno_4.sql
new file mode 100644
index 0000000..8112e51
--- /dev/null
+++ b/odb/src/ddl/reprod_seqno_4.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'reprod_seqno_4.sql'
+//
+//   Last updated:  05-Jul-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW reprod_seqno_4 AS
+  SELECT seqno UPDATED, // The only time seqno is updated ?
+         obstype, codetype, // These MUST be be in this order here
+         timeslot at timeslot_index, date, time,
+         lat, lon,
+	 stalt, statid, checksum
+    FROM timeslot_index, index, hdr
+   WHERE (timeslot at timeslot_index = $tslot OR $tslot = -1)
+   ORDER BY timeslot at timeslot_index, obstype, codetype, date, time, lat, lon, stalt, statid, checksum
+;
diff --git a/odb/src/ddl/resat.h b/odb/src/ddl/resat.h
new file mode 100644
index 0000000..7e9b119
--- /dev/null
+++ b/odb/src/ddl/resat.h
@@ -0,0 +1,38 @@
+//
+// Table Definition: resat table
+// contains ozone, aerosols, CO2, etc.
+//
+// retrtype at hdr = 1 when it contains averaging kernel 
+// retrtype at hdr = 0 when it does not contain averaging kernel
+SET $resat_retrtype_ak = 1; 
+SET $resat_retrtype = 0;
+
+-- The following depends on resat data, so watch for it!
+SET $mx_ak = 50;                        // depends on jpmx_ak in module/parcma and bufr2odb_gch2.F90  and  varindex_module.F90!!
+CREATE TABLE resat AS (
+  instrument_type pk1int,               // SATELLITE INSTRUMENT
+  product_type pk1int,                  // PRODUCT TYPE FOR RETRIEVED ATMOSPHERIC GASES
+  lat_fovcorner[1:4] pk9real,           // LATITUDE FIELD OF VIEW CORNER 1-4
+  lon_fovcorner[1:4] pk9real,           // LONGITUDE FIELD OF VIEW CORNER 1-4
+  solar_elevation pk9real,              // SOLAR ELEVATION
+  scanpos pk1int,                       // SCAN POSITION i.e. FIELD OF VIEW NUMBER
+  cloud_cover pk9real,                  // CLOUD COVER
+  cloud_top_press pk9real,              // PRESSURE AT TOP OF CLOUD
+  quality_retrieval pk1int,             // QUALITY OF RETRIEVAL
+  number_layers pk1int,                 // NUMBER OF RETRIEVED LAYERS
+  resat_averaging_kernel @LINK,
+  snow_ice_indicator pk1int,            // SNOW/ICE INDICATOR 
+  surface_type_indicator pk1int,        // SURFACE TYPE 
+  methane_correction pk9real,           // SCIAMACHY METHANE CORRECTION FACTOR
+  surface_height pk9real,               // SURFACE HEIGHT
+  retrsource pk1int,                    // SOURCE/ORIGINATOR OF RETRIEVED ATMOSPHERIC CONSTITUENT
+);
+
+CREATE TABLE resat_averaging_kernel AS (
+  nak pk1int,                           // number of averaging kernel elements
+  wak[$mx_ak] pk9real,                  // averaging kernel weights
+  pak[$mx_ak] pk9real,                  // averaging kernel pressures
+  apak[$mx_ak] pk9real,                 // averaging kernel prior profile
+);
+
+
diff --git a/odb/src/ddl/resat_update_links.sql b/odb/src/ddl/resat_update_links.sql
new file mode 100644
index 0000000..76a923a
--- /dev/null
+++ b/odb/src/ddl/resat_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'resat_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW resat_update_links AS
+  SELECT "/LINK.*/"
+    FROM resat
+;
+
diff --git a/odb/src/ddl/revmatchup_body.sql b/odb/src/ddl/revmatchup_body.sql
new file mode 100644
index 0000000..6f3ec41
--- /dev/null
+++ b/odb/src/ddl/revmatchup_body.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'revmatchup_body.sql'
+//
+//   Last updated:  27-Jan-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW revmatchup_body AS
+  SELECT seqno  READONLY,            // r/o
+         entryno  READONLY,          // r/o
+         datum_anflag at body UPDATED,
+         datum_status at body UPDATED,
+         datum_event1 at body UPDATED,
+         qc_a at body UPDATED,
+         qc_l at body UPDATED,
+         qc_pge at body UPDATED,
+         an_depar at body UPDATED,
+    FROM timeslot_index, index, hdr, body
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active at hdr
+     AND datum_status.active at body
+     AND paral($pe, target)
+;
+
diff --git a/odb/src/ddl/revmatchup_hdr.sql b/odb/src/ddl/revmatchup_hdr.sql
new file mode 100644
index 0000000..81998fc
--- /dev/null
+++ b/odb/src/ddl/revmatchup_hdr.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'revmatchup_hdr.sql'
+//
+//   Last updated:  27-Jan-2005
+//
+
+SET $tslot = -1;
+SET $pe = 0;
+
+CREATE VIEW revmatchup_hdr AS
+  SELECT seqno  READONLY,      // r/o
+         report_status,               // update
+         report_event1,               // update
+    FROM timeslot_index, index, hdr
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND report_status.active
+     AND paral($pe, target)
+;
diff --git a/odb/src/ddl/robhdr.sql b/odb/src/ddl/robhdr.sql
new file mode 100644
index 0000000..c67e42b
--- /dev/null
+++ b/odb/src/ddl/robhdr.sql
@@ -0,0 +1,48 @@
+//
+//-- ODB/SQL file 'robhdr.sql'
+//
+//   Last updated:  07-Nov-2002
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW robhdr AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         retrtype UPDATED,             // possibly updated, MUST BE SECOND for Aeolus
+         abnob, mapomm, maptovscv,     // r/o
+         sensor,                       // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         retrtype  UPDATED,            // r/o
+         date, time,                   // r/o
+         stalt  UPDATED,               // possibly updated (in ECMA)
+         statid,                       // r/o
+         lat, lon,                     // r/o
+         sat.offset,                   // r/o for Aeolus processing
+         timeslot at index,               // r/o for Aeolus processing
+         codetype UPDATED,             // possibly updated
+         instrument_type UPDATED,      // possibly updated
+         areatype UPDATED,             // possibly updated
+         report_event1  UPDATED,       // possibly updated
+         report_status  UPDATED,       // possibly updated
+         statid,                       // r/o
+         zenith,
+         lsm           UPDATED,  // Basic surface params at obs locations, archived during screening
+         seaice        UPDATED,
+         orography     UPDATED,
+         tsfc          UPDATED,
+         albedo        UPDATED,
+         windspeed10m  UPDATED,
+         u10m          UPDATED,
+         v10m          UPDATED,
+         t2m           UPDATED,
+         snow_depth    UPDATED,
+  FROM   timeslot_index, index, hdr, modsurf, sat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+  ORDERBY seqno
+;
diff --git a/odb/src/ddl/robhdr_gbrad_get_rr.sql b/odb/src/ddl/robhdr_gbrad_get_rr.sql
new file mode 100644
index 0000000..51a9e64
--- /dev/null
+++ b/odb/src/ddl/robhdr_gbrad_get_rr.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'robhdr_gbrad_get_rr.sql'
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $hdr_min = 999;
+SET $hdr_max = 0;
+
+CREATE VIEW robhdr_gbrad_get_rr AS
+  SELECT seqno,                         // MDBONM (must be the first index; used to build MLNKH2B)
+         gp_number,                     // MDB_GP_NUMBER hdr
+         report_rrflag at gbrad,           // MDB_REPORT_RRFLAG gbrad
+         retrtype at hdr,                  // MDB_RETRTYPE_AT_HDR
+         source at hdr,                    // MDB_SOURCE_AT_HDR
+
+  FROM   timeslot_index, index, hdr, gbrad
+
+  WHERE  (timeslot at timeslot_index BETWEEN $hdr_min AND $hdr_max) 
+     AND codetype == 3 AND obstype == 14
+;
+
diff --git a/odb/src/ddl/robhdr_gbrad_put_rr.sql b/odb/src/ddl/robhdr_gbrad_put_rr.sql
new file mode 100644
index 0000000..c8a0ed0
--- /dev/null
+++ b/odb/src/ddl/robhdr_gbrad_put_rr.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'robhdr_gbrad_put_rr.sql'
+//
+
+SET $hdr_min = 999;
+SET $hdr_max = 0;
+
+CREATE VIEW robhdr_gbrad_put_rr AS
+  SELECT seqno,                       // r/o MUST BE FIRST hdr
+         mapomm,                      // r/o MDB_MAPOMM_AT_INDEX index
+         gp_number,                   // MDB_GP_NUMBER hdr
+         time,                        // MDBETM
+         report_status,               // MDBRST hdr
+         report_event1,               // MDBREV1 hdr
+         report_rrflag at gbrad,         // MDB_REPORT_RRFLAG gbrad
+         retrtype at hdr,                // MDB_RETRTYPE_AT_HDR
+         source at hdr,                  // MDB_SOURCE_AT_HDR
+
+  FROM   timeslot_index, index, hdr, gbrad
+  WHERE  (timeslot at timeslot_index BETWEEN $hdr_min AND $hdr_max) 
+    AND codetype == 3 AND obstype == 14
diff --git a/odb/src/ddl/robhdr_gp_get_ssmi.sql b/odb/src/ddl/robhdr_gp_get_ssmi.sql
new file mode 100644
index 0000000..deb9ad7
--- /dev/null
+++ b/odb/src/ddl/robhdr_gp_get_ssmi.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'robhdr_gp_get_ssmi.sql'
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $tslot = -1;
+
+CREATE VIEW robhdr_gp_get_ssmi AS
+  SELECT seqno,                  // MDBONM (must be the first index; used to build MLNKH2B)
+         lat,                    // MDBLAT
+         lon,                    // MDBLON
+         satellite_identifier at sat,                  // MDB_satid_AT_hdr
+         scanpos at radiance,       // MDB_SCANPOS_AT_RADIANCE (field-of-view for ssmi)
+         sensor at hdr,             // MDBSSIA (sensor ID number)
+         zenith,            // MDB_ZENITH_AT_SAT (satellite zenith  angle in degrees)
+         azimuth,           // MDB_AZIMUTH_AT_SAT (satellite azimuth angle in degrees)
+  FROM   timeslot_index, index, hdr, sat, radiance
+  WHERE  timeslot at timeslot_index == $tslot AND obstype == 7 AND codetype == 215 AND (sensor == 6 OR sensor == 10
+OR sensor == 9 OR sensor == 17)
+;
+
diff --git a/odb/src/ddl/robhdr_grid_distribute.sql b/odb/src/ddl/robhdr_grid_distribute.sql
new file mode 100644
index 0000000..712040d
--- /dev/null
+++ b/odb/src/ddl/robhdr_grid_distribute.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'robhdr_grid_distribute.sql'
+//
+//   Created:  22-Jun-2009
+//
+
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+CREATE VIEW robhdr_grid_distribute AS
+  SELECT seqno,                         // MDBONM (must be the first index; used to build MLNKH2B)
+         lat,                           // MDBLAT
+         lon,                           // MDBLON
+         distribid UPDATED,             // mdb_distribid_at_hdr
+         gp_dist UPDATED,               // MDB_GP_DIST hdr
+         gp_number UPDATED,             // MDB_GP_NUMBER hdr
+         distribtype,
+  FROM   hdr
+  WHERE  distribtype IS NOT NULL AND distribtype > 0 // only observations on the model grid
+;
+
diff --git a/odb/src/ddl/robhdr_mwave_count_smos.sql b/odb/src/ddl/robhdr_mwave_count_smos.sql
new file mode 100644
index 0000000..8f3a720
--- /dev/null
+++ b/odb/src/ddl/robhdr_mwave_count_smos.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'robhdr_mwave_count_smos.sql'
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $hdr_min = 999;   // changed in the call to GETDB
+SET $hdr_max = 0;     // changed in the call to GETDB
+SET $all = -1;
+
+CREATE VIEW robhdr_mwave_count_smos AS
+  SELECT obsvalue,              
+  FROM  hdr, body, smos, timeslot_index
+  WHERE (timeslot at timeslot_index BETWEEN $hdr_min AND $hdr_max) AND codetype == 400 AND obstype == 7 AND varno == 190 and polarisation == $all
+
diff --git a/odb/src/ddl/robhdr_mwave_process_smos.sql b/odb/src/ddl/robhdr_mwave_process_smos.sql
new file mode 100644
index 0000000..c2c5db0
--- /dev/null
+++ b/odb/src/ddl/robhdr_mwave_process_smos.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'robhdr_mwave_process_smos.sql'
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $hdr_min = 999;   // changed in the call to GETDB
+SET $all     = -1;
+
+CREATE VIEW robhdr_mwave_process_smos AS
+  SELECT seqno,                         // MDBONM (must be the first index; used to build MLNKH2B)
+         gp_number,                     // MDB_GP_NUMBER hdr
+         gp_dist,                       // MDB_GP_DIST hdr
+         incidence_angle,               // MDB_TB_ANG_SMOS
+         faradey_rot_angle,             // MDB_TB_FAR_SMOS
+         pixel_rot_angle,               // MDB_TB_GEO_SMOS
+         report_tbflag at smos UPDATED,    // MDB_TB_FLAG_SMOS smos
+  FROM   timeslot_index, index, hdr, smos
+  WHERE  model_timestep at timeslot_index==$hdr_min AND codetype == 400 AND obstype == 7 and polarisation == $all 
+
diff --git a/odb/src/ddl/robhdr_mwave_update_smos.sql b/odb/src/ddl/robhdr_mwave_update_smos.sql
new file mode 100644
index 0000000..5d702a6
--- /dev/null
+++ b/odb/src/ddl/robhdr_mwave_update_smos.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'robhdr_mwave_update_smos.sql'
+//
+
+SET $hdr_min = 999;
+SET $all     =-1;
+
+CREATE VIEW robhdr_mwave_update_smos AS
+  SELECT seqno,                       // r/o MUST BE FIRST hdr
+         report_status,               // MDBRST hdr
+         report_event1,               // MDBREV1 hdr
+         gp_number,                   // MDB_GP_NUMBER hdr
+         incidence_angle,             // MDB_TB_ANG_SMOS
+         report_tbflag at smos,          // MDB_TB_FLAG_SMOS smos
+         tbvalue at smos,                // MDB_TB_SMOS smos
+
+  FROM   timeslot_index, index, hdr, smos
+  WHERE  model_timestep at timeslot_index==$hdr_min AND codetype == 400 AND obstype == 7 AND polarisation == $all 
diff --git a/odb/src/ddl/robhdr_obsort.sql b/odb/src/ddl/robhdr_obsort.sql
new file mode 100644
index 0000000..209b31c
--- /dev/null
+++ b/odb/src/ddl/robhdr_obsort.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'robhdr_obsort.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+READONLY; // the view is treated as read/only
+
+SET $all = 1;
+SET $hdr_min =0; // here $hdr_min corresponds to distribtype 1 if on the model grid
+
+CREATE VIEW robhdr_obsort AS
+  SELECT lat, lon,                //  r/o
+    FROM index, hdr
+   WHERE (   ($all = 1)
+	  OR ($all = 0 AND report_status.active = 1)
+	  OR ($all = 2) )
+      AND distribtype = $hdr_min
+   ORDERBY sensor,distribid, gp_number
+
+;
diff --git a/odb/src/ddl/robhdr_rad.sql b/odb/src/ddl/robhdr_rad.sql
new file mode 100644
index 0000000..b3e549a
--- /dev/null
+++ b/odb/src/ddl/robhdr_rad.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'robhdr_rad.sql'
+//
+//   Last updated:  05-10-10
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW robhdr_rad AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,
+         codetype,                     // r/o
+	     date, time,                   // r/o
+         lat, lon,                     // r/o
+         skintemper,
+         skintemp[1:($NMXUPD+1)],
+         cldne[1:3],
+         cldptop[1:3],
+         zenith,
+         azimuth  READONLY,    // r/o
+         solar_zenith  READONLY,       // r/o
+         solar_azimuth  READONLY,      // r/o
+         scanpos,
+  FROM   timeslot_index, index, hdr, sat, radiance
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+          (timeslot at timeslot_index == $tslot))
+    AND kset = $kset
+    AND obstype = $satem 
+    AND codetype = $atovs
+;
diff --git a/odb/src/ddl/robhdr_raingg_get_rr.sql b/odb/src/ddl/robhdr_raingg_get_rr.sql
new file mode 100644
index 0000000..da7f9d1
--- /dev/null
+++ b/odb/src/ddl/robhdr_raingg_get_rr.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'robhdr_raingg_get_rr.sql'
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $hdr_min = 999;
+SET $hdr_max = -1;
+SET $tslot = -1;
+
+CREATE VIEW robhdr_raingg_get_rr AS
+  SELECT seqno,                         // MDBONM (must be the first index; used to build MLNKH2B)
+         gp_number,                     // MDB_GP_NUMBER hdr
+         report_rrflag at raingg,          // MDB_REPORT_RRFLAG raingg
+
+  FROM   timeslot_index, index, hdr, raingg
+
+  WHERE  timeslot at timeslot_index == $tslot AND reportype == $hdr_max
+;
+
diff --git a/odb/src/ddl/robhdr_raingg_put_rr.sql b/odb/src/ddl/robhdr_raingg_put_rr.sql
new file mode 100644
index 0000000..246d292
--- /dev/null
+++ b/odb/src/ddl/robhdr_raingg_put_rr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'robhdr_raingg_put_rr.sql'
+//
+
+SET $hdr_min = 999;
+SET $hdr_max = -1;
+SET $tslot = -1;
+
+CREATE VIEW robhdr_raingg_put_rr AS
+  SELECT seqno,                       // r/o MUST BE FIRST hdr
+         mapomm,                      // r/o MDB_MAPOMM_AT_INDEX index
+         gp_number,                   // MDB_GP_NUMBER hdr
+         time,                        // MDBETM
+         report_status,               // MDBRST hdr
+         report_event1,               // MDBREV1 hdr
+         report_rrflag at raingg,        // MDB_REPORT_RRFLAG raingg
+
+  FROM   timeslot_index, index, hdr, raingg
+  WHERE  timeslot at timeslot_index == $tslot AND reportype == $hdr_max
diff --git a/odb/src/ddl/robhdr_screen.sql b/odb/src/ddl/robhdr_screen.sql
new file mode 100644
index 0000000..be34891
--- /dev/null
+++ b/odb/src/ddl/robhdr_screen.sql
@@ -0,0 +1,42 @@
+//
+//-- ODB/SQL file 'robhdr_screen.sql'
+//
+//   Last updated:  13-Oct-2008
+//
+
+READONLY; // All read/only except selected columns marked with  UPDATED
+
+SET $kset = 0;
+
+CREATE VIEW robhdr_screen AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         retrtype UPDATED,             // possibly updated, MUST BE SECOND for Aeolus
+         sat.offset,                   // r/o for Aeolus processing
+         timeslot,                        // r/o for Aeolus processing
+         body.len,                     // r/o
+         abnob, mapomm, maptovscv,      // r/o
+         obstype,                      // r/o
+         date, time,                   // r/o
+         sensor,                       // r/o
+         codetype UPDATED,             // possibly updated
+         instrument_type UPDATED,      // possibly updated
+         areatype UPDATED,             // possibly updated
+         report_event1  UPDATED,       // possibly updated
+         report_status  UPDATED,       // possibly updated
+         stalt  UPDATED,               // possibly updated
+         statid,                       // r/o
+         lat,lon,                      // r/o
+         zenith,
+         lsm           UPDATED,                   
+         seaice        UPDATED,                
+         orography     UPDATED,                
+         tsfc          UPDATED,            
+         albedo        UPDATED,            
+         windspeed10m  UPDATED,        
+         u10m          UPDATED,        
+         v10m          UPDATED,   
+         t2m           UPDATED,   
+         snow_depth    UPDATED,            
+  FROM   index, hdr, sat, modsurf
+  WHERE	 kset = $kset
+;
diff --git a/odb/src/ddl/robhdr_screen_conv.sql b/odb/src/ddl/robhdr_screen_conv.sql
new file mode 100644
index 0000000..8467ad4
--- /dev/null
+++ b/odb/src/ddl/robhdr_screen_conv.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'robhdr_screen_conv.sql'
+//
+//   Last updated:  27-Mar-2011
+//
+
+READONLY; // All read/only except selected columns marked with  UPDATED
+
+SET $kset = 0;
+
+CREATE VIEW robhdr_screen_conv AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         anemoht at conv,                 // r/o
+  FROM   index, hdr, conv
+  WHERE	 kset = $kset
+;
diff --git a/odb/src/ddl/robhdr_tc.sql b/odb/src/ddl/robhdr_tc.sql
new file mode 100644
index 0000000..33f556b
--- /dev/null
+++ b/odb/src/ddl/robhdr_tc.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'robhdr_tc.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+READONLY; // ... view
+
+CREATE VIEW robhdr_tc AS     // Time correlation; ROBHDR-part
+  SELECT seqno,              // r/o; Must become first
+         body.len,           // r/o
+         date, time,         // r/o
+         obstype,            // r/o
+         codetype,          // r/o
+         instrument_type,    // r/o
+         retrtype,     // r/o
+         areatype,          // r/o
+         abnob, mapomm,      // r/o
+         lat, lon, statid,   // r/o
+    FROM index, hdr
+   WHERE obstype = $synop
+      OR obstype = $dribu
+;
diff --git a/odb/src/ddl/robhdrca_obsort.sql b/odb/src/ddl/robhdrca_obsort.sql
new file mode 100644
index 0000000..ea1bb25
--- /dev/null
+++ b/odb/src/ddl/robhdrca_obsort.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'robhdrca_obsort.sql'
+//
+//   Last updated:  19-Jan-2000
+//
+
+READONLY;
+
+SET $all = 1;
+SET $pe = 0;
+
+CREATE VIEW robhdrca_obsort AS
+  SELECT lat, lon                //  r/o
+  FROM index, hdr
+  WHERE ($all >= 1 OR report_status.active = 1)
+    AND (timeslot = 4)
+    AND ($all = 2 OR $all = -2 OR obstype IN ($synop,$dribu,$temp,$pilot,$paob))
+;
diff --git a/odb/src/ddl/robody.sql b/odb/src/ddl/robody.sql
new file mode 100644
index 0000000..d8806db
--- /dev/null
+++ b/odb/src/ddl/robody.sql
@@ -0,0 +1,56 @@
+//
+//-- ODB/SQL file 'robody.sql'
+//
+//   Last updated:  08/04/2010 A. Fouilloux Remove tcwv_fg
+//
+// Yannick: hardcoded 3 in obs_diags_*
+
+UPDATED;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW robody AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno READONLY,
+         varno,
+         datum_anflag UPDATED,                           // possibly updated
+         datum_event1 at body UPDATED, datum_status at body UPDATED, // possibly updated
+         an_depar UPDATED, fg_depar UPDATED,       // possibly updated
+         actual_depar  UPDATED,                    // to pass actual departure from one subroutine to another (working ODB column)
+         hires at update[1:$NMXUPD] UPDATED,          // possibly updated
+         lores at update[1:$NMXUPD] UPDATED,          // possibly updated
+         qc_a UPDATED,                    // possibly updated
+         qc_l UPDATED,                    // possibly updated
+         qc_pge UPDATED,                    // possibly updated
+         obs_diags_1 at update[1:$NMXUPD] UPDATED,
+         obs_diags_2 at update[1:$NMXUPD] UPDATED,
+         obs_diags_3 at update[1:$NMXUPD] UPDATED,
+         obsvalue,
+         final_obs_error UPDATED,    // r/o
+         fg_error UPDATED,           // r/o
+         fc_sens_obs UPDATED,      // r/o
+         repres_error UPDATED,           // r/o
+         obs_corr_ev[1:$NUMEV],          // r/o
+         obs_corr_mask at errstat,          // r/o
+         an_sens_obs UPDATED,            // r/o
+         vertco_reference_1,
+         vertco_reference_2,
+         varbc_ix READONLY,                     // r/o
+         biascorr,
+         datum_event2,
+         datum_status,                 // possibly updated
+         datum_blacklist,              // possibly updated
+         datum_rdbflag,                // possibly updated
+         vertco_type,                  // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         biascorr_fg,                     // possibly updated
+         jacobian_peak              UPDATED, // MDB_JACOBIAN_PEAK
+         jacobian_hpeak             UPDATED, // MDB_JACOBIAN_HPEAK
+  FROM   timeslot_index, index, hdr, body, update[1:$NMXUPD], errstat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+   ORDERBY seqno
+;
diff --git a/odb/src/ddl/robody_gbrad_get_rr.sql b/odb/src/ddl/robody_gbrad_get_rr.sql
new file mode 100644
index 0000000..41c309b
--- /dev/null
+++ b/odb/src/ddl/robody_gbrad_get_rr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'robody_gbrad_get_rr.sql'
+//
+
+READONLY;
+
+SET $hdr_min = 999;
+SET $hdr_max = 0;
+
+CREATE VIEW robody_gbrad_get_rr AS
+
+  SELECT seqno,                 // MDBONM (used to build MLNKH2B)
+         varno,                 // MDBVNM
+         obsvalue,              // MDBVAR
+         datum_status at body,     // MDBDSTA body
+         rrvaluead at gbrad_body,  // MDB_RRVALUEAD  gbrad_body
+         retrtype at hdr,          // MDB_RETRTYPE_AT_HDR
+         source at hdr,            // MDB_SOURCE_AT_HDR
+
+  FROM   timeslot_index, index, hdr, body, gbrad_body
+
+  WHERE  (timeslot at timeslot_index BETWEEN $hdr_min AND $hdr_max) 
+    AND  codetype == 3 AND obstype == 14 AND varno == 203
+;
diff --git a/odb/src/ddl/robody_gbrad_put_rr.sql b/odb/src/ddl/robody_gbrad_put_rr.sql
new file mode 100644
index 0000000..ffe66d1
--- /dev/null
+++ b/odb/src/ddl/robody_gbrad_put_rr.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'robody_gbrad_put_rr.sql'
+//
+
+SET $hdr_min = 999;
+SET $hdr_max = 0;
+
+CREATE VIEW robody_gbrad_put_rr AS
+
+  SELECT seqno,                  // r/o MUST BE FIRST hdr
+         entryno,                //     
+         varno,                  //     MDBVNM         body
+         obsvalue,               //     MDBVAR         body
+         rrvalue at gbrad_body,     //     MDB_RRVALUE    gbrad_body
+         rrvaluetl at gbrad_body,   //     MDB_RRVALUETL  gbrad_body
+         rrvaluead at gbrad_body,   //     MDB_RRVALUEAD  gbrad_body
+         datum_status at body,      //     MDBDSTA        body
+         biascorr,               //     MDBTORB        body
+         obs_error,              //     MDBOER         errstat
+         final_obs_error,        //     MDBFOE         errstat
+         retrtype at hdr,           //     MDB_RETRTYPE_AT_HDR
+         source at hdr,             //     MDB_SOURCE_AT_HDR
+
+  FROM   timeslot_index, index, hdr, body, errstat, gbrad_body
+
+  WHERE  (timeslot at timeslot_index BETWEEN $hdr_min AND $hdr_max) 
+    AND codetype == 3 AND obstype == 14 AND varno == 203
+;
diff --git a/odb/src/ddl/robody_gp_get_ssmi.sql b/odb/src/ddl/robody_gp_get_ssmi.sql
new file mode 100644
index 0000000..e19cec0
--- /dev/null
+++ b/odb/src/ddl/robody_gp_get_ssmi.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'robody_gp_get_ssmi.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW robody_gp_get_ssmi AS
+
+  SELECT seqno,         // MDBONM (used to build MLNKH2B)
+         varno,         // MDBVNM (just is case we need this)
+         vertco_type,   // MDBVCO (just is case we need this)
+         datum_anflag,        // MDBFLG
+         vertco_reference_1 at body,    // MDBPPP
+         obsvalue,      // MDBVAR
+
+  FROM   timeslot_index, index, hdr, body
+
+  WHERE  timeslot at timeslot_index == $tslot AND obstype == 7 AND codetype == 215 AND (sensor == 6 OR sensor == 9
+OR sensor == 10 OR sensor == 17)
+    AND  varno = $rawbt           // Brightness temp. i.e. 119
+//  AND  vertco_type = $tovs_cha  // Note: commented out for now
+;
diff --git a/odb/src/ddl/robody_mwave_process_smos.sql b/odb/src/ddl/robody_mwave_process_smos.sql
new file mode 100644
index 0000000..192403d
--- /dev/null
+++ b/odb/src/ddl/robody_mwave_process_smos.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'robody_smos_get_tb.sql'
+//
+
+READONLY;
+
+SET $hdr_min = 999;
+SET $all     = -1;
+
+CREATE VIEW robody_mwave_process_smos AS
+
+  SELECT seqno,           // MDBONM (used to build MLNKH2B)
+         obsvalue,        // MDBVAR
+
+  FROM   timeslot_index, index, hdr, body, smos
+  WHERE  model_timestep at timeslot_index==$hdr_min AND codetype == 400 AND obstype == 7 AND varno == 190 AND polarisation == $all
diff --git a/odb/src/ddl/robody_mwave_update_smos.sql b/odb/src/ddl/robody_mwave_update_smos.sql
new file mode 100644
index 0000000..1676aca
--- /dev/null
+++ b/odb/src/ddl/robody_mwave_update_smos.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'robody_mwave_update_smos.sql'
+//
+
+SET $hdr_min = 999;
+SET $all     = -1;
+
+CREATE VIEW robody_mwave_update_smos AS
+
+  SELECT seqno,                // r/o MUST BE FIRST hdr
+         entryno,              //     
+         varno,                //     MDBVNM   body
+         obsvalue,             //     MDBVAR   body
+         fg_depar,             //     MDBOMF   body
+         datum_status at body,    //     MDBDSTA  body
+         obs_error,            //     MDBOER   errstat
+
+  FROM   timeslot_index, index, hdr, body, errstat, smos
+
+  WHERE  model_timestep at timeslot_index==$hdr_min AND codetype == 400 AND obstype == 7 AND varno == 190 AND polarisation == $all 
diff --git a/odb/src/ddl/robody_rad.sql b/odb/src/ddl/robody_rad.sql
new file mode 100644
index 0000000..19fbebf
--- /dev/null
+++ b/odb/src/ddl/robody_rad.sql
@@ -0,0 +1,51 @@
+//
+//-- ODB/SQL file 'robody_rad.sql'
+//
+//   Last updated:  08/04/2010 A. Fouilloux Remove tcwv_fg
+//
+// Yannick: hardcoded 3 in obs_diags_*
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW robody_rad AS   
+  SELECT seqno, 
+         entryno, 
+         varno,               // r/o
+         datum_anflag,
+         datum_event1 at body UPDATED, 
+         datum_status at body UPDATED, // possibly updated
+         fg_depar UPDATED,       // possibly updated
+         an_depar UPDATED,       // possibly updated
+         hires at update[1:$NMXUPD] UPDATED,          // possibly updated
+         lores at update[1:$NMXUPD] UPDATED,          // possibly updated
+         qc_a UPDATED,                    // possibly updated
+         qc_l UPDATED,                    // possibly updated
+         qc_pge UPDATED,                    // possibly updated
+
+         obs_diags_1 at update[1:$NMXUPD] UPDATED,
+         obs_diags_2 at update[1:$NMXUPD] UPDATED,
+         obs_diags_3 at update[1:$NMXUPD] UPDATED,
+
+	     obsvalue,                     // r/o
+	     final_obs_error,              // r/o
+         fg_error UPDATED,           // r/o
+         obs_corr_ev[1:$NUMEV],          // r/o
+         obs_corr_mask at errstat,          // r/o
+         pers_error,                   // r/o
+         vertco_reference_1, 
+         varbc_ix,                     // r/o
+         biascorr,
+  FROM   timeslot_index, index, hdr, body, update[1:$NMXUPD], errstat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+    AND obstype = $satem 
+    AND codetype = $atovs
+    AND (sensor!= $hirs OR (vertco_reference_1!=20))
+    AND vertco_reference_1 IS NOT NULL 
+    AND vertco_reference_1 > 0
+    AND obsvalue IS NOT NULL
+;
diff --git a/odb/src/ddl/robody_raingg_get_rr.sql b/odb/src/ddl/robody_raingg_get_rr.sql
new file mode 100644
index 0000000..4b8b32f
--- /dev/null
+++ b/odb/src/ddl/robody_raingg_get_rr.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'robody_raingg_get_rr.sql'
+//
+
+READONLY;
+
+SET $hdr_min = 999;
+SET $hdr_max = -1;
+SET $tslot = -1;
+
+CREATE VIEW robody_raingg_get_rr AS
+
+  SELECT seqno,                 // MDBONM (used to build MLNKH2B)
+         varno,                 // MDBVNM
+         obsvalue,              // MDBVAR
+         datum_status at body,     // MDBDSTA body
+         rrvaluead at raingg_body, // MDB_RRVALUEAD  raingg_body
+
+  FROM   timeslot_index, index, hdr, body, raingg_body
+
+  WHERE  timeslot at timeslot_index == $tslot AND reportype == $hdr_max
+    AND  varno == 203
+;
diff --git a/odb/src/ddl/robody_raingg_put_rr.sql b/odb/src/ddl/robody_raingg_put_rr.sql
new file mode 100644
index 0000000..e9250c0
--- /dev/null
+++ b/odb/src/ddl/robody_raingg_put_rr.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'robody_raingg_put_rr.sql'
+//
+
+SET $hdr_min = 999;
+SET $hdr_max = -1;
+SET $tslot = -1;
+
+CREATE VIEW robody_raingg_put_rr AS
+
+  SELECT seqno,                  // r/o MUST BE FIRST hdr
+         entryno,                //     
+         varno,                  //     MDBVNM         body
+         obsvalue,               //     MDBVAR         body
+         rrvalue at raingg_body,    //     MDB_RRVALUE    raingg_body
+         rrvaluetl at raingg_body,  //     MDB_RRVALUETL  raingg_body
+         rrvaluead at raingg_body,  //     MDB_RRVALUEAD  raingg_body
+         datum_status at body,      //     MDBDSTA        body
+         biascorr,               //     MDBTORB        body
+         obs_error,              //     MDBOER         errstat
+         repres_error,           //     MDBRER         errstat
+         final_obs_error,        //     MDBFOE         errstat
+
+  FROM   timeslot_index, index, hdr, body, errstat, raingg_body
+
+  WHERE  timeslot at timeslot_index == $tslot AND reportype == $hdr_max
+    AND  varno == 203
+;
diff --git a/odb/src/ddl/robody_screen.sql b/odb/src/ddl/robody_screen.sql
new file mode 100644
index 0000000..a99b33c
--- /dev/null
+++ b/odb/src/ddl/robody_screen.sql
@@ -0,0 +1,36 @@
+//
+//-- ODB/SQL file 'robody_screen.sql'
+//
+//   Last updated:  16-Nov-2006
+//
+
+UPDATED; // the default: all updated (except those with  READONLY or  READONLY)
+
+SET $kset = 0;
+
+CREATE VIEW robody_screen AS
+  SELECT seqno           READONLY,     // r/o; MUST BECOME FIRST
+         entryno         READONLY,     // r/o
+         datum_anflag, 
+         varno,                        // possibly updated
+         datum_event1,                 // possibly updated
+    	 datum_event2, 
+         datum_status,                 // possibly updated
+         datum_blacklist,              // possibly updated
+         datum_rdbflag,                // possibly updated
+         vertco_type,                  // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         obsvalue,                     // possibly updated
+         fg_depar,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         varbc_ix,                     // r/o
+         biascorr,                     // possibly updated
+         biascorr_fg,                     // possibly updated
+	     lores,                        // possibly updated
+ FROM   index, hdr, body, update[1], errstat
+  WHERE	 kset = $kset
+;
diff --git a/odb/src/ddl/robody_smos_sekf.sql b/odb/src/ddl/robody_smos_sekf.sql
new file mode 100644
index 0000000..817530e
--- /dev/null
+++ b/odb/src/ddl/robody_smos_sekf.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'robody_smos_sekf.sql'
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kang_min = -1;
+SET $kang_max = -1;
+
+CREATE VIEW robody_smos_sekf AS
+
+  SELECT seqno,           // MDBONM (used to build MLNKH2B)
+         date,                          // MDBDAT hdr
+         time,                          // MDBETM hdr
+         lat,                           // MDBLAT hdr
+         lon,                           // MDBLON hdr
+         gp_number,                     // MDB_GP_NUMBER hdr
+         incidence_angle,               // MDB_TB_ANG_SMOS smos
+         polarisation at smos,             // MDB_POLARISATION_AT_SMOS smos
+         rad_acc_pure at smos,             // MDB_RAD_ACC_PURE_SMOS smos
+         report_tbflag at smos,            // MDB_TB_FLAG_SMOS smos
+         varno,                         // MDBVNM body
+         obsvalue,                      // MDBVAR body
+         biascorr at body UPDATED,         // MDBTORB body
+         model_timestep at timeslot_index,        // MDB_MODSTEP_AT_TIMESLOT_INDEX timeslot_index
+  FROM   hdr, smos, body, timeslot_index
+  WHERE codetype == 400
+    AND obstype == 7
+    AND $kang_min <= incidence_angle <= $kang_max
+    AND report_tbflag at smos == 1
diff --git a/odb/src/ddl/robody_tc.sql b/odb/src/ddl/robody_tc.sql
new file mode 100644
index 0000000..a3613aa
--- /dev/null
+++ b/odb/src/ddl/robody_tc.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'robody_tc.sql'
+//
+//   Last updated:  16-Oct-2001
+//
+
+CREATE VIEW robody_tc AS     // Time correlation; READONLYBODY-part
+  SELECT datum_event1 at body,        // possibly updated
+         datum_status at body,        // possibly updated
+         datum_anflag,             // possibly updated
+         entryno  READONLY, varno  READONLY, // r/o
+         qc_a,      // possibly updated
+         qc_l,      // possibly updated
+         qc_pge,      // possibly updated
+         vertco_reference_1  READONLY,   // r/o
+         final_obs_error  READONLY,// r/o
+         fg_error         READONLY,// r/o
+         actual_depar,  // use to store departure (massaged by qc)
+    FROM index, hdr, body, errstat
+   WHERE obstype = $synop
+      OR obstype = $dribu
+;
diff --git a/odb/src/ddl/robody_traj.sql b/odb/src/ddl/robody_traj.sql
new file mode 100644
index 0000000..7e19420
--- /dev/null
+++ b/odb/src/ddl/robody_traj.sql
@@ -0,0 +1,41 @@
+
+//
+//-- ODB/SQL file 'robody_traj.sql'
+//
+//   Last updated: 15/03/2011 A. Fouilloux Remove aux_*
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW robody_traj AS    
+  SELECT entryno, varno,               // r/o
+         datum_anflag UPDATED,                           // possibly updated
+         datum_event1 at body UPDATED, datum_status at body UPDATED, // possibly updated
+         an_depar UPDATED, fg_depar UPDATED,       // possibly updated
+         actual_depar  UPDATED,                    // to pass actual departure from one subroutine to another (working ODB column)
+         hires at update[1:$NMXUPD] UPDATED,          // possibly updated
+         lores at update[1:$NMXUPD] UPDATED,          // possibly updated
+         qc_a UPDATED,                    // possibly updated
+         qc_l UPDATED,                    // possibly updated
+         qc_pge UPDATED,                    // possibly updated
+         final_obs_error UPDATED,                  // possibly updated
+         obs_error at errstat UPDATED,                // possibly updated
+         repres_error,                            // r/o
+         fg_error,                                // r/o
+         pers_error,                              // r/o
+         obsvalue                   UPDATED,      // possibly updated (twin exp)
+         vertco_reference_1, 
+         vertco_reference_2,                      // r/o
+         varbc_ix,                                // r/o
+         biascorr                   UPDATED,      // possibly updated
+         biascorr_fg                UPDATED,      // possibly updated
+         jacobian_peak              UPDATED, // MDB_JACOBIAN_PEAK
+         jacobian_hpeak             UPDATED, // MDB_JACOBIAN_HPEAK
+  FROM   timeslot_index, index, hdr, body, update[1:$NMXUPD], errstat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+           (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/rstbody.sql b/odb/src/ddl/rstbody.sql
new file mode 100644
index 0000000..fe0cdc9
--- /dev/null
+++ b/odb/src/ddl/rstbody.sql
@@ -0,0 +1,11 @@
+READONLY;
+CREATE VIEW rstbody AS
+SELECT seqno, press,
+//        1     2
+       bccf_1, bccf_2, bccf_3, bccf_4, bccf_5, bccf_6, bccf_7, bccf_8, bccf_9, bccf_10, bccf_11, bccf_12, bccf_13
+//        3       4       5       6       7       8       9      10      11      12       13       14       15  
+FROM  hdr, body
+//WHERE
+//ORDERBY
+;
+
diff --git a/odb/src/ddl/rsthdr.sql b/odb/src/ddl/rsthdr.sql
new file mode 100644
index 0000000..6327865
--- /dev/null
+++ b/odb/src/ddl/rsthdr.sql
@@ -0,0 +1,8 @@
+READONLY;
+CREATE VIEW rsthdr AS
+SELECT seqno, statid, lat, lon, stalt, sonde_name, sonde_code, date_from, time_from, date_to, time_to, body.offset, body.len
+//        1      2     3    4     5         6           7          8          9         10        11       12           13 
+FROM hdr
+//WHERE
+//ORDERBY
+;
diff --git a/odb/src/ddl/sat.h b/odb/src/ddl/sat.h
new file mode 100644
index 0000000..7a29ff7
--- /dev/null
+++ b/odb/src/ddl/sat.h
@@ -0,0 +1,30 @@
+//
+// Table Definitions: sat (header-like satellite table)
+//
+CREATE TABLE sat AS (
+  satellite_identifier pk1int,     // WMO Satellite platform identifier
+  satellite_instrument pk1int,     // WMO Satellite instrument on board
+
+  zenith               pk9real,    // SATELLITE INSTRUMENT ZENITH ANGLE 
+  azimuth              pk9real,    // SATELLITE INSTRUMENT AZIMUTH ANGLE
+  solar_zenith         pk9real,    // SOLAR ZENITH ANGLE 
+  solar_azimuth        pk9real,    // SOLAR AZIMUTH ANGLE
+
+// Why for satellite only?
+  gen_centre           pk1int,     // WMO Generating Centre
+  gen_subcentre        pk1int,     // WMO Generating sub-centre
+  datastream           pk1int,     // Datastream
+
+  radiance             @LINK,      // Radiance table  (entry point for all atmospheric radiances)
+  resat                @LINK,      // Retrieval of satellite data (ozone, co2, aerosols, etc.).
+  gnssro               @LINK,      // gnssro table 
+  satob                @LINK,      // satob winds
+  limb                 @LINK,      // For 2D observation operators?
+  ssmi                 @LINK,      // obsolete table for 1DVAR. Will be removed...
+  smos                 @LINK,      // smos satellite 
+  scatt                @LINK,      // Scatterometer satellite
+  aeolus_hdr           @LINK,      // aeolus ADM
+  radar_station        @LINK,      // ??? Meteo-France specific
+  radar                @LINK,      // ??? Meteo-France specific
+);
+
diff --git a/odb/src/ddl/sat_aeolus.sql b/odb/src/ddl/sat_aeolus.sql
new file mode 100644
index 0000000..59d249d
--- /dev/null
+++ b/odb/src/ddl/sat_aeolus.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'sat_aeolus.sql'
+//
+//   Last updated:  17-04-2012
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_aeolus AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         azimuth  READONLY,    // r/o
+    FROM timeslot_index, index, hdr, sat
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $lidar
+     AND codetype = 187
+;
diff --git a/odb/src/ddl/sat_aeolusl2c.sql b/odb/src/ddl/sat_aeolusl2c.sql
new file mode 100644
index 0000000..6bd229e
--- /dev/null
+++ b/odb/src/ddl/sat_aeolusl2c.sql
@@ -0,0 +1,30 @@
+//
+//-- ODB/SQL file 'sat_aeolus.sql'
+//
+//   Last updated:  17-04-2012
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_aeolusl2c AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         azimuth  READONLY,    // r/o
+         hlos_ob_err       UPDATED, // possibly updated 
+         hlos_fg           UPDATED, // possibly updated
+         u_fg              UPDATED, // possibly updated
+         u_fg_err          UPDATED, // possibly updated
+         v_fg              UPDATED, // possibly updated
+         v_fg_err          UPDATED, // possibly updated
+         hlos_fg_err       UPDATED, // possibly updated
+         hlos_an           UPDATED, // possibly updated
+         hlos_an_err       UPDATED, // possibly updated
+         u_an              UPDATED, // possibly updated
+         v_an              UPDATED, // possibly updated
+    FROM timeslot_index, index, hdr, sat, aeolus_hdr, aeolus_l2c
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $lidar
+     AND codetype = 187
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_atovs.sql b/odb/src/ddl/sat_atovs.sql
new file mode 100644
index 0000000..094d2a9
--- /dev/null
+++ b/odb/src/ddl/sat_atovs.sql
@@ -0,0 +1,65 @@
+//
+//-- ODB/SQL file 'sat_atovs.sql'
+//
+//   Last updated:  07-Nov-2002
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_atovs AS
+  SELECT seqno  READONLY,                  // r/o; MUST BECOME FIRST
+         cldcover READONLY,                // r/o; MUST BECOME FIRST
+         skintemper,                       // possibly updated
+         cldptop[1:3],                     // possibly updated
+         cldne[1:3],                       // possibly updated
+         skintemp[1:($NMXUPD+1)]@radiance, // possibly updated
+         scatterindex_89_157 UPDATED,      // possibly updated
+         scatterindex_23_89 UPDATED,       // possibly updated
+         scatterindex_23_165 UPDATED,      // possibly updated
+         lwp_obs UPDATED,                  // possibly updated
+         t2m,
+         typesurf UPDATED,
+         surface_class,
+         cldptop[1:3],                     // possibly updated
+         cldne[1:3],                       // possibly updated
+         scanpos at radiance  READONLY,       // r/o
+         zenith at sat  READONLY,             // r/o
+         azimuth at sat  READONLY,            // r/o
+         solar_zenith at sat  READONLY,       // r/o
+         solar_azimuth at sat  READONLY,      // r/o
+         asr_pcloudy_high,                 // updated for overcast cloudy ir
+         asr_pcloudy_middle  READONLY,     // r/o
+         avhrr_stddev_ir    READONLY,    // r/o
+         avhrr_stddev_ir2    READONLY,    // r/o
+         avhrr_frac_cl1      READONLY,    // r/o
+         avhrr_frac_cl2      READONLY,    // r/o
+         avhrr_frac_cl3      READONLY,    // r/o
+         avhrr_frac_cl4      READONLY,    // r/o
+         avhrr_frac_cl5      READONLY,    // r/o
+         avhrr_frac_cl6      READONLY,    // r/o
+         avhrr_frac_cl7      READONLY,    // r/o
+         avhrr_m_ir1_cl1     READONLY,    // r/o
+         avhrr_m_ir1_cl2     READONLY,    // r/o
+         avhrr_m_ir1_cl3     READONLY,    // r/o
+         avhrr_m_ir1_cl4     READONLY,    // r/o
+         avhrr_m_ir1_cl5     READONLY,    // r/o
+         avhrr_m_ir1_cl6     READONLY,    // r/o
+         avhrr_m_ir1_cl7     READONLY,    // r/o
+         avhrr_m_ir2_cl1     READONLY,    // r/o
+         avhrr_m_ir2_cl2     READONLY,    // r/o
+         avhrr_m_ir2_cl3     READONLY,    // r/o
+         avhrr_m_ir2_cl4     READONLY,    // r/o
+         avhrr_m_ir2_cl5     READONLY,    // r/o
+         avhrr_m_ir2_cl6     READONLY,    // r/o
+         avhrr_m_ir2_cl7     READONLY,    // r/o
+         avhrr_fg_ir1,                    // updated
+         avhrr_fg_ir2,                    // updated
+         avhrr_cloud_flag,                // updated
+    FROM timeslot_index, index, hdr, sat, radiance, modsurf, collocated_imager_information
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $satem 
+     AND codetype = $atovs
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_gpsro.sql b/odb/src/ddl/sat_gpsro.sql
new file mode 100644
index 0000000..302f6d2
--- /dev/null
+++ b/odb/src/ddl/sat_gpsro.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'sat_gpsro.sql'
+//
+//   Last updated:  17-Mar-2011
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_gpsro AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         radcurv UPDATED,                      // maybe updated?
+         undulation,                   // r/o 
+  FROM   timeslot_index, index, hdr, sat, gnssro
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+    AND obstype=$limb AND codetype=$gpsro
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_lrad.sql b/odb/src/ddl/sat_lrad.sql
new file mode 100644
index 0000000..e5a32b9
--- /dev/null
+++ b/odb/src/ddl/sat_lrad.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'sat_lrad.sql'
+//
+//   Last updated:  22-Nov-2004
+//
+
+UPDATED;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_lrad AS
+  SELECT seqno  READONLY,         // r/o; MUST COME FIRST
+         satellite_identifier at sat READONLY,                   // r/o
+         ntan,                    // r/o
+         ztan[1:$mx_limb_tan],     // r/o
+         ptan[1:$mx_limb_tan],     // r/o
+         thtan[1:$mx_limb_tan],     // r/o
+         window_rad[1:$mx_limb_tan],     // r/o
+         cloud_index[1:$mx_limb_tan]     // r/o
+  FROM   timeslot_index, index, hdr, sat, limb
+  WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND kset = $kset
+    AND obstype = $limb AND codetype = $lrad
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_radar.sql b/odb/src/ddl/sat_radar.sql
new file mode 100644
index 0000000..b033d72
--- /dev/null
+++ b/odb/src/ddl/sat_radar.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'sat_radar.sql'
+//
+
+READONLY;
+
+CREATE VIEW sat_radar AS
+  SELECT satellite_identifier, 
+         radar_station.offset UPDATED
+  FROM sat
+  WHERE radar_station.len>0
+;
diff --git a/odb/src/ddl/sat_satob.sql b/odb/src/ddl/sat_satob.sql
new file mode 100644
index 0000000..7531f9b
--- /dev/null
+++ b/odb/src/ddl/sat_satob.sql
@@ -0,0 +1,36 @@
+UPDATED;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_satob AS
+  SELECT seqno READONLY,                   // r/o; MUST BECOME FIRST
+         satellite_identifier at sat READONLY,               // r/o
+         comp_method READONLY,             // r/o
+         tb at satob READONLY,                // r/o
+         height_assignment_method READONLY,  // r/o
+         t at satob,                 // possibly updated
+         zenith,            // possibly updated
+         shear at satob,             // possibly updated
+         t200 at satob,              // possibly updated
+         t500 at satob,              // possibly updated
+         top_mean_t at satob,        // possibly updated
+         top_wv at satob,            // possibly updated
+         dt_by_dp at satob,          // possibly updated
+         p_best at satob,            // possibly updated
+         u_best at satob,            // possibly updated
+         v_best at satob,            // possibly updated
+         p_old at satob,             // possibly updated
+         u_old at satob,             // possibly updated
+         v_old at satob,             // possibly updated
+         tracking_error_u,        // possibly updated
+         tracking_error_v,        // possibly updated
+         h_assignment_error_u,    // possibly updated
+         h_assignment_error_v,    // possibly updated
+         error_in_h_assignment,   // possibly updated
+    FROM timeslot_index, index, hdr, sat, satob
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $satob 
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_smos.sql b/odb/src/ddl/sat_smos.sql
new file mode 100644
index 0000000..f01cf93
--- /dev/null
+++ b/odb/src/ddl/sat_smos.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'sat_smos.sql'
+//
+//   Last updated:  05-May-2010
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_smos AS
+  SELECT seqno  READONLY,                // r/o; MUST BECOME FIRST
+         distribid  READONLY,            // MDB_distribid_AT_hdr 
+         gp_number  READONLY,            // MDB_GP_NUMBER hdr
+         gp_dist  READONLY,              // MDB_GP_DIST hdr
+         report_tbflag at smos  READONLY,   // MDB_TB_FLAG_SMOS smos
+         tbvalue at smos  READONLY          // MDB_TB_SMOS      smos 
+  FROM   timeslot_index, index, hdr, smos
+  WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND kset = $kset
+    AND obstype = $satem AND codetype = 400
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_ssmi.sql b/odb/src/ddl/sat_ssmi.sql
new file mode 100644
index 0000000..8515445
--- /dev/null
+++ b/odb/src/ddl/sat_ssmi.sql
@@ -0,0 +1,60 @@
+//
+//-- ODB/SQL file 'sat_ssmi.sql'
+//
+//   Last updated:  14-Jul-2006
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sat_ssmi AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         scanpos at radiance  READONLY,    // r/o
+         gp_number,                   // MDB_GP_NUMBER hdr
+         distribid,                   // MDB_DISTRIBID_AT_HDR hdr
+         gp_dist,                     // MDB_GP_DIST
+         satellite_identifier at sat,    // MDB_satid_AT_hdr
+         zenith,                      // MDB_ZENITH_AT_SAT (in degrees)
+         azimuth,                     // MDB_AZIMUTH_AT_SAT
+         solar_zenith at sat  READONLY,  // r/o    probably junk
+         fg_rain_rate,                // MDB_FG_RAIN_RATE
+         fg_snow_rate,                // MDB_FG_SNOW_RATE
+         fg_tcwv,                     // MDB_FG_TCWV
+         fg_cwp,                      // MDB_FG_CWP
+         fg_iwp,                      // MDB_FG_IWP
+         fg_rwp,                      // MDB_FG_RWP
+         fg_swp,                      // MDB_FG_SWP
+         fg_rttov_cld_fraction,       // MDB_FG_RTTOV_CLD_FRAC
+         fg_theta700,                 // MDB_FG_THETA700
+         fg_thetasfc,                 // MDB_FG_THETASFC             
+         fg_uth,                      // MDB_FG_UTH
+         an_rain_rate,                // MDB_AN_RAIN_RATE
+         an_snow_rate,                // MDB_AN_SNOW_RATE
+         an_tcwv,                     // MDB_AN_TCWV
+         an_cwp,                      // MDB_AN_CWP
+         an_iwp,                      // MDB_AN_IWP
+         an_rwp,                      // MDB_AN_RWP
+         an_swp,                      // MDB_AN_SWP
+         an_rttov_cld_fraction,       // MDB_AN_RTTOV_CLD_FRAC
+         an_theta700,                 // MDB_AN_THETA700
+         an_thetasfc,                 // MDB_AN_THETASFC        
+         an_uth,                      // MDB_AN_UTH
+         gnorm_10mwind,               // MDB_GNORM_10MWIND
+         gnorm_skintemp,              // MDB_GNORM_SKINTEMP
+         gnorm_temp,                  // MDB_GNORM_TEMP
+         gnorm_q,                     // MDB_GNORM_Q
+         gnorm_rainflux,              // MDB_GNORM_RAINFLUX
+         gnorm_snowflux,              // MDB_GNORM_SNOWFLUX
+         gnorm_clw,                   // MDB_GNORM_CLW
+         gnorm_ciw,                   // MDB_GNORM_CIW 
+         gnorm_cc,                    // MDB_GNORM_CC
+         ob_p19, fg_p19, an_p19,      // MDB_OB_P19, MDB_FG_P19, MDB_AN_P19
+         ob_p37, fg_p37, an_p37,      // MDB_OB_P37, MDB_FG_P37, MDB_AN_P37
+         report_tbcloud,      
+    FROM timeslot_index, index, hdr, sat, radiance, allsky
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $allsky 
+     AND codetype = $ssmi
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sat_update_links.sql b/odb/src/ddl/sat_update_links.sql
new file mode 100644
index 0000000..beb6ede
--- /dev/null
+++ b/odb/src/ddl/sat_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'sat_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW sat_update_links AS
+  SELECT "/LINK.*/"
+    FROM sat
+;
+
diff --git a/odb/src/ddl/satbody_allsky.sql b/odb/src/ddl/satbody_allsky.sql
new file mode 100644
index 0000000..b2f3fb8
--- /dev/null
+++ b/odb/src/ddl/satbody_allsky.sql
@@ -0,0 +1,31 @@
+//
+//-- ODB/SQL file 'satbody_allsky.sql'
+//
+//   New:  05-May-2010
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW satbody_allsky AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+       tbvalue at allsky_body,
+       tbvaluead at allsky_body,
+       tbvaluetl at allsky_body,
+       datum_tbflag at allsky_body,
+       emis_fg,
+       emis_rtin,
+       emis_retr,
+       emis_atlas,
+       tausfc,
+       tbclear,               //  clear sky TB
+       obs_error,             //     Only needed to pass an out-of-date qc check
+       jacobian_peak,         // For Mats ENKF
+       jacobian_hpeak,        // For Mats ENKF
+       zenith_by_channel,
+    FROM timeslot_index, index, hdr, allsky, body, allsky_body, errstat, radiance_body
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $allsky AND codetype = $ssmi
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/satbody_atovs.sql b/odb/src/ddl/satbody_atovs.sql
new file mode 100644
index 0000000..f118c66
--- /dev/null
+++ b/odb/src/ddl/satbody_atovs.sql
@@ -0,0 +1,37 @@
+
+//
+//-- ODB/SQL file 'satbody_atovs.sql'
+//
+//
+
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW satbody_atovs AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         emis_rtin,
+         emis_fg UPDATED,
+         emis_retr,                    // possibly updated
+         emis_atlas,                   // possibly updated
+         emis_atlas_error,             // possibly updated
+         tausfc UPDATED,
+         channel_qc READONLY,              // r/o
+         skintemp_retr,                // possibly updated
+         cld_fg_depar,                 // possibly updated
+         rank_cld,                     // possibly updated
+         nobs_averaged READONLY,       // r/o
+         stdev_averaged READONLY,      // r/o
+         jacobian_peak,                // possibly updated
+         jacobian_hpeak,               // possibly updated
+         jacobian_peakl,               // possibly updated
+         jacobian_hpeakl,              // possibly updated
+         tbclear,                      // clear sky TB
+  FROM   timeslot_index, index, hdr, body, sat, radiance, radiance_body
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR
+(timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+    AND  obstype = $satem AND codetype = $atovs
+
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/satbody_gpsro.sql b/odb/src/ddl/satbody_gpsro.sql
new file mode 100644
index 0000000..407ce20
--- /dev/null
+++ b/odb/src/ddl/satbody_gpsro.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'satbody_gpsro.sql'
+//
+//   New:  15-Mar-2011
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW satbody_gpsro AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+// For GNSSRO only
+     bg_refractivity UPDATED,           // possibly updated
+     bg_dndz UPDATED,          // possibly updated
+     bg_layerno UPDATED,            // possibly updated
+     bg_tvalue UPDATED,            // possibly updated for gnssro (MF) to be cleaned
+	 obs_tvalue,                      // r/o for gnssro (MF) to be cleaned
+	 obs_zvalue UPDATED,            // r/o for gnssro (MF) to be cleaned
+    FROM timeslot_index, index, hdr, sat, gnssro, gnssro_body
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $limb AND codetype = $gpsro
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/satbody_radar.sql b/odb/src/ddl/satbody_radar.sql
new file mode 100644
index 0000000..a034e1c
--- /dev/null
+++ b/odb/src/ddl/satbody_radar.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'satbody_radar.sql'
+//
+//   created : 15-Dec-2004
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW satbody_radar AS
+  SELECT seqno  READONLY,                
+         flgdyn,           // r/o; MUST BECOME FIRS
+         distance,        // r/o 
+         elevation,     // r/o 
+         azimuth at radar_body,       // r/o 
+         q[1]           UPDATED, //
+         q[2]           UPDATED, //
+         q_1dv          UPDATED,//
+    FROM timeslot_index, index, hdr, sat, radar, radar_body
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $radar 
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/satbody_scat.sql b/odb/src/ddl/satbody_scat.sql
new file mode 100644
index 0000000..cdc2e52
--- /dev/null
+++ b/odb/src/ddl/satbody_scat.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'satbody_scat.sql'
+//
+//   Last updated:  15-DEC-2006
+//
+
+UPDATED;
+
+SET $tslot = -1;
+
+CREATE VIEW satbody_scat AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         mpc at scatt_body,          // r/o
+         azimuth at scatt_body,      // r/o
+         incidence,               // r/o
+         Kp,                      // r/o
+         invresid,                // r/o
+         dirskill,                // r/o
+         Kp_qf at scatt_body,        // r/o
+         sigma0_qf at scatt_body,    // r/o
+         sigma0_sm at scatt_body,    // r/o
+         soilmoist_sd at scatt_body, // r/o
+         soilmoist_cf at scatt_body, // r/o
+         soilmoist_pf at scatt_body, // r/o
+         land_fraction at scatt_body,// r/o
+         wetland_fraction at scatt_body,// r/o
+         topo_complex at scatt_body,    // r/o
+
+    FROM timeslot_index, index, hdr, sat, scatt, scatt_body
+   WHERE obstype = $scatt
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/satbody_screen_atovs.sql b/odb/src/ddl/satbody_screen_atovs.sql
new file mode 100644
index 0000000..72c2057
--- /dev/null
+++ b/odb/src/ddl/satbody_screen_atovs.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'satbody_screen_atovs.sql'
+//
+//   Last updated:  27-Aug-2014
+//
+
+UPDATED; // the default: all updated (except those with  READONLY or  READONLY)
+
+SET $kset = 0;
+
+CREATE VIEW satbody_screen_atovs AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         emis_retr,                    // possibly updated
+         emis_atlas,                   // possibly updated
+         emis_atlas_error,             // possibly updated
+         emis_rtin,                    // possibly updated
+         skintemp_retr,                // possibly updated
+         tausfc,                       // possibly updated
+         cld_fg_depar,                 // possibly updated
+         rank_cld,                     // possibly updated
+         nobs_averaged READONLY,       // r/o
+         stdev_averaged READONLY,      // r/o
+         jacobian_peak,                // possibly updated
+         jacobian_hpeak,               // possibly updated
+         jacobian_peakl,               // possibly updated
+         jacobian_hpeakl,              // possibly updated
+         tbclear,                      // clear sky TB
+ FROM   index, hdr, body, sat, radiance, radiance_body
+  WHERE	 kset = $kset
+     AND obstype = $satem
+     AND codetype = $atovs
+;
diff --git a/odb/src/ddl/satellite_identifier_list.sql b/odb/src/ddl/satellite_identifier_list.sql
new file mode 100644
index 0000000..6533380
--- /dev/null
+++ b/odb/src/ddl/satellite_identifier_list.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'satellite_identifier_list.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+READONLY;
+CREATE VIEW satellite_identifier_list AS
+  SELECT DISTINCT satellite_identifier,
+    FROM sat
+    where datastream=0
+;
+
diff --git a/odb/src/ddl/sathdr_cloud_sink.sql b/odb/src/ddl/sathdr_cloud_sink.sql
new file mode 100644
index 0000000..4d85f20
--- /dev/null
+++ b/odb/src/ddl/sathdr_cloud_sink.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'sathdr_cloud_sink.sql'
+//
+//   Last updated:  07-Nov-2002
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sathdr_cloud_sink AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         ctopbg,
+         ctoper,
+         ctopinc,
+         ctop[1:$NMXUPD],
+         camtbg,
+         camter,
+         camtinc,
+         camt[1:$NMXUPD],
+    FROM timeslot_index, index, hdr, sat, radiance, cloud_sink
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+     AND kset = $kset
+     AND obstype = $satem 
+     AND codetype = $atovs
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sathdr_limb.sql b/odb/src/ddl/sathdr_limb.sql
new file mode 100644
index 0000000..ac9c409
--- /dev/null
+++ b/odb/src/ddl/sathdr_limb.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'sathdr_limb.sql'
+//
+//   Last updated:  23-Nov-2004
+//
+
+SET $tslot = -1;
+SET $obstype = 0;
+SET $codetype = 0;
+
+CREATE VIEW sathdr_limb AS
+  SELECT seqno  READONLY,         // r/o; MUST COME FIRST
+         satellite_identifier at sat,                   // r/o
+         ntan,                    // r/o
+         ztan[1:$mx_limb_tan],     // r/o
+         ptan[1:$mx_limb_tan],     // r/o
+         thtan[1:$mx_limb_tan]     // r/o
+  FROM   index, hdr, sat, limb
+  WHERE	 obstype = $limb AND codetype = $lrad
+    AND  (($tslot == -1 AND timeslot > 0) OR (timeslot == $tslot))
+;
diff --git a/odb/src/ddl/sathdr_ozone.sql b/odb/src/ddl/sathdr_ozone.sql
new file mode 100644
index 0000000..a6e5d7d
--- /dev/null
+++ b/odb/src/ddl/sathdr_ozone.sql
@@ -0,0 +1,33 @@
+//
+//-- ODB/SQL file 'sathdr_ozone.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW sathdr_ozone AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         satellite_identifier at sat,                   // r/o
+         instrument_type at resat,    // r/o
+         product_type,            // r/o
+         scanpos at resat,            // r/o
+         quality_retrieval,       // r/o
+         number_layers,           // r/o
+         lat_fovcorner[1:4],      // r/o
+         lon_fovcorner[1:4],      // r/o
+         solar_elevation,         // r/o
+         cloud_cover,             // r/o
+         cloud_top_press,         // r/o
+         solar_zenith,            // r/o
+         solar_azimuth,           // r/o
+         zenith,        // r/o
+         azimuth,       // r/o
+         snow_ice_indicator,      // r/o
+         retrsource,              // r/o
+         surface_type_indicator,  // r/o
+  FROM   timeslot_index, index, hdr, sat, resat
+  WHERE	 obstype = $satem
+    AND  codetype = $resat
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/sathdr_radar.sql b/odb/src/ddl/sathdr_radar.sql
new file mode 100644
index 0000000..e4fba16
--- /dev/null
+++ b/odb/src/ddl/sathdr_radar.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'sathdr_radar.sql'
+//
+//   Last updated:  24-May-2000
+//
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sathdr_radar AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+      stalt at radar_station,         // r/o
+      satellite_identifier at sat,
+      lat at radar_station, // r/o
+      lon at radar_station, // r/o
+      antenht at radar_station, // r/o
+      ident at radar_station, // r/o
+      beamwidth at radar_station, // r/o
+  FROM   timeslot_index, index, hdr, sat, radar_station
+  WHERE	 obstype = $radar
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND kset = $kset
+ ORDERBY seqno
+;
diff --git a/odb/src/ddl/sathdr_satob.sql b/odb/src/ddl/sathdr_satob.sql
new file mode 100644
index 0000000..005cbfe
--- /dev/null
+++ b/odb/src/ddl/sathdr_satob.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'sathdr_satob.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW sathdr_satob AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         satellite_identifier at sat,                   // r/o
+         comp_method,             // r/o
+         instdata,                // r/o
+         dataproc,                // r/o
+         QI_fc,                 // r/o
+         QI_nofc,               // r/o
+         RFF,                    // r/o
+         datastream,              // r/o
+  FROM   timeslot_index, index, hdr, sat, satob
+  WHERE	 obstype = $satob
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/sathdr_scat.sql b/odb/src/ddl/sathdr_scat.sql
new file mode 100644
index 0000000..1000224
--- /dev/null
+++ b/odb/src/ddl/sathdr_scat.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'sathdr_scat.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW sathdr_scat AS
+  SELECT seqno  READONLY,         // r/o; MUST BECOME FIRST
+         satellite_identifier at sat,                   // r/o
+         cellno,                  // r/o
+         prodflag,                // r/o
+         wvc_qf,                  // r/o
+         nretr_amb,               // r/o
+  FROM   timeslot_index, index, hdr, sat, scatt
+  WHERE	 obstype = $scatt
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/sathdr_screen_aeolus_auxmet.sql b/odb/src/ddl/sathdr_screen_aeolus_auxmet.sql
new file mode 100644
index 0000000..2826d5b
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_aeolus_auxmet.sql
@@ -0,0 +1,32 @@
+//
+//-- ODB/SQL file 'sathdr_screen_aeolus_auxmet.sql'
+//
+//   Created:  2-Feb-2005
+//   Last updated: 12-Jun-2012
+//
+
+READONLY; // .. except where  UPDATED qualifier was found
+
+SET $kset = 0;
+CREATE VIEW sathdr_screen_aeolus_auxmet AS
+  SELECT seqno,                        // r/o; MUST BE FIRST
+         retrtype,                   // r/o; MUST BE SECOND
+         lev at aeolus_auxmet UPDATED, // possibly updated // distinct from lev at hdr
+         ptop              UPDATED, // possibly updated
+         pnom              UPDATED, // possibly updated
+         ztop              UPDATED, // possibly updated
+         znom              UPDATED, // possibly updated
+         u                 UPDATED, // possibly updated
+         v                 UPDATED, // possibly updated
+         t                 UPDATED, // possibly updated
+         rh                UPDATED, // possibly updated
+         q                 UPDATED, // possibly updated
+         cc                UPDATED, // possibly updated
+         clwc              UPDATED, // possibly updated
+         ciwc              UPDATED, // possibly updated
+         error_t           UPDATED, // possibly updated
+         error_rh          UPDATED, // possibly updated
+         error_p           UPDATED, // possibly updated
+  FROM index, hdr, sat, aeolus_hdr, aeolus_auxmet
+  WHERE ( ( kset = $kset ) AND ( retrtype at hdr = 1 ) )
+;
diff --git a/odb/src/ddl/sathdr_screen_aeolus_hdr.sql b/odb/src/ddl/sathdr_screen_aeolus_hdr.sql
new file mode 100644
index 0000000..7999808
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_aeolus_hdr.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'sathdr_screen_aeolus_hdr.sql'
+//
+//   Created:  2-Feb-2005
+//   Last updated: 11-Mar-2011
+//
+
+READONLY;
+SET $kset = 0;
+CREATE VIEW sathdr_screen_aeolus_hdr AS
+  SELECT seqno,                        // r/o; MUST BE FIRST
+         retrtype,                     // r/o; MUST BE SECOND
+         aeolus_auxmet.offset    READONLY,
+         aeolus_auxmet.len       READONLY,
+         aeolus_hdrflag          READONLY,
+  FROM index, hdr, sat, aeolus_hdr
+  WHERE ( ( kset = $kset ) AND ( retrtype at hdr = 1 ) )
+//
+;
diff --git a/odb/src/ddl/sathdr_screen_atovs.sql b/odb/src/ddl/sathdr_screen_atovs.sql
new file mode 100644
index 0000000..4f86a65
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_atovs.sql
@@ -0,0 +1,61 @@
+//
+//-- ODB/SQL file 'sathdr_screen_atovs.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+UPDATED;
+SET $kset = 0;
+
+CREATE VIEW sathdr_screen_atovs AS
+  SELECT seqno  READONLY,                  // r/o; MUST BECOME FIRST
+         scanpos at radiance  READONLY,       // r/o
+         zenith at sat  READONLY,             // r/o
+         azimuth  READONLY,                // r/o
+         t2m,                              // possibly updated
+         surface_class,                    // possibly updated
+         skintemper,                       // possibly updated
+         skintemp[1:($NMXUPD+1)]@radiance, // possibly updated
+         cldptop[1:3],                     // possibly updated
+         cldne[1:3],                       // possibly updated
+         cldcover,
+         solar_zenith at sat   READONLY,      // r/o
+         solar_azimuth at sat  READONLY,      // r/o
+         scatterindex_89_157 UPDATED,
+         scatterindex_23_89 UPDATED,
+         scatterindex_23_165 UPDATED,
+         lwp_obs UPDATED,
+         typesurf UPDATED,
+         asr_pcloudy_high,                 // updated
+         asr_pcloudy_middle  READONLY,     // r/o
+         avhrr_stddev_ir    READONLY,    // r/o
+         avhrr_stddev_ir2    READONLY,    // r/o
+         avhrr_frac_cl1      READONLY,    // r/o
+         avhrr_frac_cl2      READONLY,    // r/o
+         avhrr_frac_cl3      READONLY,    // r/o
+         avhrr_frac_cl4      READONLY,    // r/o
+         avhrr_frac_cl5      READONLY,    // r/o
+         avhrr_frac_cl6      READONLY,    // r/o
+         avhrr_frac_cl7      READONLY,    // r/o
+         avhrr_m_ir1_cl1     READONLY,    // r/o
+         avhrr_m_ir1_cl2     READONLY,    // r/o
+         avhrr_m_ir1_cl3     READONLY,    // r/o
+         avhrr_m_ir1_cl4     READONLY,    // r/o
+         avhrr_m_ir1_cl5     READONLY,    // r/o
+         avhrr_m_ir1_cl6     READONLY,    // r/o
+         avhrr_m_ir1_cl7     READONLY,    // r/o
+         avhrr_m_ir2_cl1     READONLY,    // r/o
+         avhrr_m_ir2_cl2     READONLY,    // r/o
+         avhrr_m_ir2_cl3     READONLY,    // r/o
+         avhrr_m_ir2_cl4     READONLY,    // r/o
+         avhrr_m_ir2_cl5     READONLY,    // r/o
+         avhrr_m_ir2_cl6     READONLY,    // r/o
+         avhrr_m_ir2_cl7     READONLY,    // r/o
+         avhrr_fg_ir1,                    // updated
+         avhrr_fg_ir2,                    // updated
+         avhrr_cloud_flag,                // updated
+    FROM index, hdr, sat, radiance, modsurf, collocated_imager_information
+   WHERE kset = $kset
+     AND obstype = $satem 
+     AND codetype = $atovs
+;
diff --git a/odb/src/ddl/sathdr_screen_cloud_sink.sql b/odb/src/ddl/sathdr_screen_cloud_sink.sql
new file mode 100644
index 0000000..5a50aa1
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_cloud_sink.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'sathdr_screen_cloud_sink.sql'
+//
+//   Last updated:  17-May-2001
+//
+
+SET $kset = 0;
+
+CREATE VIEW sathdr_screen_cloud_sink AS
+  SELECT seqno  READONLY,                   // r/o; MUST BECOME FIRST
+         ctopbg,
+         ctoper,
+         ctopinc,
+         ctop[1:$NMXUPD],
+         camtbg,
+         camter,
+         camtinc,
+         camt[1:$NMXUPD],
+    FROM index, hdr, sat, radiance, cloud_sink
+   WHERE kset = $kset
+     AND obstype = $satem 
+     AND codetype = $atovs
+;
diff --git a/odb/src/ddl/sathdr_screen_gpsro.sql b/odb/src/ddl/sathdr_screen_gpsro.sql
new file mode 100644
index 0000000..a46de5c
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_gpsro.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'sathdr_screen_gpsro.sql'
+//
+//   Last updated:  17-Mar-2011
+//
+
+SET $kset = 0;
+
+CREATE VIEW sathdr_screen_gpsro AS
+  SELECT seqno  READONLY,                  // r/o; MUST BECOME FIRST
+    radcurv,
+    FROM index, hdr, gnssro
+   WHERE kset = $kset
+     AND obstype = $limb 
+     AND codetype = $gpsro
+;
diff --git a/odb/src/ddl/sathdr_screen_lrad.sql b/odb/src/ddl/sathdr_screen_lrad.sql
new file mode 100644
index 0000000..fe7ba06
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_lrad.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'sathdr_screen_lrad.sql'
+//
+//   Last updated:  22-Nov-2004
+//
+
+
+UPDATED;
+
+SET $kset = 0;
+
+CREATE VIEW sathdr_screen_lrad AS
+  SELECT seqno READONLY,                   // r/o; MUST COME FIRST
+         satellite_identifier at sat READONLY,               // r/o
+         ntan,                             // r/o
+         ztan[1:$mx_limb_tan],             // r/o
+         ptan[1:$mx_limb_tan],             // r/o
+         window_rad[1:$mx_limb_tan],       // r/o
+         cloud_index[1:$mx_limb_tan]       // r/o
+    FROM index, hdr, sat, limb
+   WHERE kset = $kset
+     AND obstype = $limb AND codetype = $lrad
+;
diff --git a/odb/src/ddl/sathdr_screen_resat.sql b/odb/src/ddl/sathdr_screen_resat.sql
new file mode 100644
index 0000000..e3dbd19
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_resat.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'sathdr_screen_resat.sql'
+//
+//   Created:  6-May-2003
+//
+
+UPDATED;
+SET $kset = 0;
+CREATE VIEW sathdr_screen_resat AS
+SELECT seqno READONLY,
+       solar_elevation READONLY,
+FROM index, hdr, sat, resat
+WHERE kset = $kset
+;
diff --git a/odb/src/ddl/sathdr_screen_satob.sql b/odb/src/ddl/sathdr_screen_satob.sql
new file mode 100644
index 0000000..55f6a0d
--- /dev/null
+++ b/odb/src/ddl/sathdr_screen_satob.sql
@@ -0,0 +1,40 @@
+//
+//-- ODB/SQL file 'sathdr_screen_satob.sql'
+//
+//   Last updated:  07-Jan-2002
+//
+
+
+UPDATED;
+
+SET $kset = 0;
+
+CREATE VIEW sathdr_screen_satob AS
+  SELECT seqno READONLY,                   // r/o; MUST BECOME FIRST
+         satellite_identifier at sat READONLY,               // r/o
+         comp_method READONLY,             // r/o
+         tb at satob READONLY,                // r/o
+         height_assignment_method READONLY,  // r/o
+         t at satob,                 // possibly updated
+         zenith,            // possibly updated
+         shear at satob,             // possibly updated
+         t200 at satob,              // possibly updated
+         t500 at satob,              // possibly updated
+         top_mean_t at satob,        // possibly updated
+         top_wv at satob,            // possibly updated
+         dt_by_dp at satob,          // possibly updated
+         p_best at satob,            // possibly updated
+         u_best at satob,            // possibly updated
+         v_best at satob,            // possibly updated
+         p_old at satob,             // possibly updated
+         u_old at satob,             // possibly updated
+         v_old at satob,             // possibly updated
+         tracking_error_u,        // possibly updated
+         tracking_error_v,        // possibly updated
+         h_assignment_error_u,    // possibly updated
+         h_assignment_error_v,    // possibly updated
+         error_in_h_assignment,   // possibly updated
+    FROM index, hdr, sat, satob
+   WHERE kset = $kset
+     AND obstype = $satob 
+;
diff --git a/odb/src/ddl/satob.h b/odb/src/ddl/satob.h
new file mode 100644
index 0000000..a2c6c4f
--- /dev/null
+++ b/odb/src/ddl/satob.h
@@ -0,0 +1,41 @@
+//
+// Table Definition: satob table
+//
+
+CREATE TABLE satob AS (
+  comp_method pk1int,                   // CLOUD MOTION COMP. METHOD
+  instdata pk1int,                      // INS. DATA USED IN PROC.
+  dataproc pk1int,                      // DATA PROC. TECHNIQUE USED
+  QI_fc pk1int,                         // EUMETSAT Quality Indicators: with forecast dependence
+  QI_nofc pk1int,                       // EUMETSAT Quality Indicators: without forecast dependence
+  RFF pk1int,                           // CIMSS Quality Indicator: Recursive Filter Flag
+  EE pk9real,                           // Expected Error [m/s]
+  segment_size_x pk9real,               // RESOLUTION, x-direction
+  segment_size_y pk9real,               // RESOLUTION, y-direction
+  chan_freq pk9real,                    // Satellite Channel Centre Frequency [Hz] (02197) for subtype=87 only
+  tb pk9real,                           // Coldest cluster temperature
+  t pk9real,                            // Temperature at SATOB p
+  shear pk9real,                        // Diff. in speed 50hPa above/below
+  t200 pk9real,                         // 200 hPa temperature
+  t500 pk9real,                         // 500 hPa temperature
+  top_mean_t pk9real,                   // Mean temperature between 80 hPa & p
+  top_wv pk9real,                       // Integrated WV above p
+  dt_by_dp pk9real,                     // Diff in temp. 50hPa above/below
+  p_best pk9real,                       // "Best fit" pressure
+  u_best pk9real,                       // U at "best fit" pressure
+  v_best pk9real,                       // V at "best fit" pressuree
+  dd_best pk9real,                      // wind direction at "best fit" pressure
+  ff_best pk9real,                      // wind speed at "best fit" pressure
+  p_old pk9real,                        // Originally assigned pressure
+  u_old pk9real,                        // U at old pressure
+  v_old pk9real,                        // V at old pressure
+  height_assignment_method pk1int,      // Height assignment method ( bufr code table 002231)
+  tracer_correlation_method pk1int,     // Tracer correlation method( bufr code table 002232)
+  land_sea pk1int,                      // Land/sea qualifier( bufr code table 008012)
+  tracking_error_u pk9real,             // Error in u due to AMV tracking (m/s)
+  tracking_error_v pk9real,             // Error in v due to AMV tracking (m/s)
+  h_assignment_error_u pk9real,         // Error in u due to to height assignment error (m/s)
+  h_assignment_error_v pk9real,         // Error in v due to to height assignment error (m/s)
+  error_in_h_assignment pk9real,        // Error in height assignment (Pa) 
+);
+
diff --git a/odb/src/ddl/satob_robhdr_1.sql b/odb/src/ddl/satob_robhdr_1.sql
new file mode 100644
index 0000000..fc7448d
--- /dev/null
+++ b/odb/src/ddl/satob_robhdr_1.sql
@@ -0,0 +1,29 @@
+//
+//-- ODB/SQL file 'satob_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW satob_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len  READONLY,           // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_rdbflag,                      // r/o
+         report_status,                       // possibly updated (in ECMA)
+         report_event1,                       // possibly updated (in ECMA)
+         report_event2,                       // possibly updated (in ECMA)
+         date,                         // r/o
+         time,                         // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (obstype = $satob)
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/satob_robody_1.sql b/odb/src/ddl/satob_robody_1.sql
new file mode 100644
index 0000000..a258080
--- /dev/null
+++ b/odb/src/ddl/satob_robody_1.sql
@@ -0,0 +1,35 @@
+//
+//-- ODB/SQL file 'satob_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+CREATE VIEW satob_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,                  // possibly updated
+         datum_event2 at body,                  // possibly updated
+         datum_status at body,                  // possibly updated
+         datum_anflag at body,                  // possibly updated
+         datum_rdbflag at body,                 // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                // possibly updated
+         qc_l,                // possibly updated
+         qc_pge,                // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  (obstype = $satob)
+    AND	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/scat_robhdr_1.sql b/odb/src/ddl/scat_robhdr_1.sql
new file mode 100644
index 0000000..25506a0
--- /dev/null
+++ b/odb/src/ddl/scat_robhdr_1.sql
@@ -0,0 +1,34 @@
+//
+//-- ODB/SQL file 'scat_robhdr_1.sql'
+//
+//   Last updated:  02-Apr-2010
+//
+
+SET $tslot = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW scat_robhdr_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_rdbflag,                      // r/o
+         report_status,                       // possibly updated (in ECMA)
+         report_event1,                       // possibly updated (in ECMA)
+         report_event2,                       // possibly updated (in ECMA)
+         gen_centre,                   // r/o
+         date,                         // r/o
+         time,                         // r/o
+         lat, lon,                     // r/o
+         statid,                       // r/o
+         stalt,                        // r/o
+  FROM   timeslot_index, index, hdr, sat
+  WHERE         obstype = $scatt
+    AND  (($codetype == -1) OR (codetype == $codetype))
+    AND  (($sensor == -1) OR (sensor == $sensor))
+    AND  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/scat_robody_1.sql b/odb/src/ddl/scat_robody_1.sql
new file mode 100644
index 0000000..34214ec
--- /dev/null
+++ b/odb/src/ddl/scat_robody_1.sql
@@ -0,0 +1,41 @@
+//
+//-- ODB/SQL file 'scat_robody_1.sql'
+//
+//   Last updated:  06-Jun-2007
+//
+
+UPDATED;
+
+SET $tslot = -1;
+SET $codetype = -1;
+SET $sensor = -1;
+
+CREATE VIEW scat_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,            // possibly updated
+         datum_event2 at body,            // possibly updated
+         datum_status at body,            // possibly updated
+         datum_anflag at body,            // possibly updated
+         datum_rdbflag at body,           // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                // possibly updated
+         qc_l,                // possibly updated
+         qc_pge,                // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  obstype = $scatt
+    AND  (($codetype == -1) OR (codetype == $codetype))
+    AND  (($sensor == -1) OR (sensor == $sensor))
+    AND         (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/scatt.h b/odb/src/ddl/scatt.h
new file mode 100644
index 0000000..32576bf
--- /dev/null
+++ b/odb/src/ddl/scatt.h
@@ -0,0 +1,30 @@
+//
+// Table Definition: scatt table
+//
+CREATE TABLE scatt AS (
+  cellno pk1int,                        // WAVE-VECTOR CELL NO.
+  nretr_amb pk1int,                     // NUMBER OF RETRIEVED AMBIGUITIES
+  prodflag pk1int,                      // ECMWF PRODUCT FLAG
+  wvc_qf pk1int,                        // ORIGINAL WIND VECTOR CELL QUALITY FLAG
+  scatt_body @LINK,  
+);
+
+CREATE TABLE scatt_body AS (
+  azimuth pk9real,                      // BEAM AZIMUTH ANGLE
+  incidence pk9real,                    // BEAM INCIDENCE ANGLE
+  Kp pk9real,                           // Kp (INSTRUMENT NOISE; Antenna Noise)
+  invresid pk9real,                     // WIND-INVERSION RESIDUAL
+  dirskill pk9real,                     // DIRECTIONAL SKILL
+  mpc pk1int,                           // MISSING PACKET COUNTER
+  Kp_qf pk1int,                         // ASCAT Kp QUALITY FLAG
+  sigma0_qf pk1int,                     // SIGMA 0 USABILITY FLAG
+  sigma0_sm pk9real,                    // EFFECTIVE SIGMA0 FOR SOIL MOISTURE
+  soilmoist_sd pk9real,                 // SOIL MOISTURE STD ERROR
+  soilmoist_cf  pk1int,                 // SOIL MOISTURE CORRECTION FLAG
+  soilmoist_pf  pk1int,                 // SOIL MOISTURE PROCESSING FLAG
+  land_fraction pk9real,                // ASCAT LAND FRACTION
+  wetland_fraction pk9real,             // ASCAT WETLAND FRACTION
+  topo_complex pk9real,                 // ASCAT TOPOGRAPHIC COMPLEXITY
+  likelihood   pk9real,                 // likelihood computed in the model (added for MF)
+);
+
diff --git a/odb/src/ddl/scatt.sql b/odb/src/ddl/scatt.sql
new file mode 100644
index 0000000..fcfff46
--- /dev/null
+++ b/odb/src/ddl/scatt.sql
@@ -0,0 +1,9 @@
+CREATE VIEW scatt AS
+SELECT  date, time, lat, lon, satellite_identifier at sat,
+        obsvalue, fg_depar, an_depar,datastream,varno
+FROM    hdr, body, sat
+WHERE   obstype=9 
+  AND   varno IN (124, 125)
+ORDERBY seqno
+;
+
diff --git a/odb/src/ddl/scatt_flag.sql b/odb/src/ddl/scatt_flag.sql
new file mode 100644
index 0000000..09785aa
--- /dev/null
+++ b/odb/src/ddl/scatt_flag.sql
@@ -0,0 +1,12 @@
+CREATE VIEW scatt_flag AS
+SELECT  datum_status.active at body, datum_status.passive at body,
+        datum_status.rejected at body,datum_status.blacklisted at body,
+        datum_event1.rdb_rejected at body,datum_event1.datum_redundant at body,
+        datum_event1.level_redundant at body,datum_event1.duplicate at body,
+        report_event1.redundant at hdr,datum_event1.depar2big at body,datum_anflag.varqc at body,datum_anflag.fg at body,
+        datum_event1.vertco_consistency at body,seqno
+FROM    hdr, body
+WHERE   obstype=9 
+  AND   varno IN (124)
+ORDERBY seqno
+;
diff --git a/odb/src/ddl/scatt_update_links.sql b/odb/src/ddl/scatt_update_links.sql
new file mode 100644
index 0000000..970e0b5
--- /dev/null
+++ b/odb/src/ddl/scatt_update_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'scatt_update_links.sql'
+//
+//   Last updated:  01-March-2012
+//
+
+UPDATED;
+
+CREATE VIEW scatt_update_links AS
+  SELECT "/LINK.*/"
+    FROM scatt
+;
+
diff --git a/odb/src/ddl/screen_robhdr_1.sql b/odb/src/ddl/screen_robhdr_1.sql
new file mode 100644
index 0000000..8d08ad6
--- /dev/null
+++ b/odb/src/ddl/screen_robhdr_1.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'screen_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // For printing statistics only
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robhdr_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         report_status,                       // r/o
+         report_event1,                       // r/o
+         lat, lon,                     // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/screen_robhdr_2.sql b/odb/src/ddl/screen_robhdr_2.sql
new file mode 100644
index 0000000..5e9eb68
--- /dev/null
+++ b/odb/src/ddl/screen_robhdr_2.sql
@@ -0,0 +1,26 @@
+//
+//-- ODB/SQL file 'screen_robhdr_2.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robhdr_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         report_status  UPDATED,              // possibly updated (in ECMA)
+         report_event1  UPDATED,              // possibly updated (in ECMA)
+         report_event2  UPDATED,              // possibly updated (in ECMA)
+         numactiveb UPDATED,
+  FROM   timeslot_index, index, hdr
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/screen_robhdr_3.sql b/odb/src/ddl/screen_robhdr_3.sql
new file mode 100644
index 0000000..48634de
--- /dev/null
+++ b/odb/src/ddl/screen_robhdr_3.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'screen_robhdr_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // For printing statistics only
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robhdr_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                      // r/o
+         kset, 
+         report_status,                       // r/o
+         report_event1,                       // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/screen_robody_1.sql b/odb/src/ddl/screen_robody_1.sql
new file mode 100644
index 0000000..70c3593
--- /dev/null
+++ b/odb/src/ddl/screen_robody_1.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'screen_robody_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // For printing statistics only
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robody_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_event1 at body,                  // r/o
+         datum_status at body,                  // r/o
+         varno,                        // r/o
+         fg_depar,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/screen_robody_2.sql b/odb/src/ddl/screen_robody_2.sql
new file mode 100644
index 0000000..342f57a
--- /dev/null
+++ b/odb/src/ddl/screen_robody_2.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'screen_robody_2.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robody_2 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+	 datum_rdbflag at body,               // r/o
+         datum_status at body  UPDATED,   // possibly updated (in ECMA)
+         datum_event1 at body  UPDATED,   // possibly updated (in ECMA)
+         datum_event2 at body  UPDATED,   // possibly updated (in ECMA)
+         varno,                        // r/o
+         vertco_reference_1,           // r/o
+	     final_obs_error UPDATED,      // possibly updated (in ECMA)
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/screen_robody_3.sql b/odb/src/ddl/screen_robody_3.sql
new file mode 100644
index 0000000..55a74cd
--- /dev/null
+++ b/odb/src/ddl/screen_robody_3.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'screen_robody_3.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY; // For printing statistics only
+
+SET $tslot = -1;
+
+CREATE VIEW screen_robody_3 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_status at body,                  // r/o
+         datum_event1 at body,                  // r/o
+         varno,                        // r/o
+         fg_depar,                     // r/o
+  FROM   timeslot_index, index, hdr, body
+  WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+;
diff --git a/odb/src/ddl/sensor.h b/odb/src/ddl/sensor.h
new file mode 100644
index 0000000..f1b3b76
--- /dev/null
+++ b/odb/src/ddl/sensor.h
@@ -0,0 +1,19 @@
+// sensor id's (sensor at hdr) :
+
+SET $hirs      =  0;
+SET $msu       =  1;
+SET $ssu       =  2;
+SET $amsua     =  3;
+SET $amsub     =  4;
+SET $tmi       =  9;
+SET $ssmis     = 10;
+SET $iasi      = 16;
+SET $amsre     = 17;
+SET $amsr2     = 63;
+SET $mwri      = 18;
+SET $atms      = 19;
+SET $meteosat  = 20;
+SET $iras      = 26;
+SET $mwts      = 27;
+SET $mwhs      = 28;
+SET $gmi       = 71;
diff --git a/odb/src/ddl/set_active.sql b/odb/src/ddl/set_active.sql
new file mode 100644
index 0000000..01ac210
--- /dev/null
+++ b/odb/src/ddl/set_active.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'set_active.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+READONLY;
+CREATE VIEW set_active AS
+  SELECT seqno, 
+         entryno,
+         report_status UPDATED,
+         datum_status  UPDATED,
+         distribtype   UPDATED,
+    FROM hdr, radiance, body, radiance_body
+    where nobs_averaged IS NOT NULL AND nobs_averaged > 0
+;
+
diff --git a/odb/src/ddl/set_active_smos.sql b/odb/src/ddl/set_active_smos.sql
new file mode 100644
index 0000000..4efe33b
--- /dev/null
+++ b/odb/src/ddl/set_active_smos.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'set_active_smos.sql'
+//
+//   Last updated:  01/02/2011
+//
+
+
+READONLY;
+CREATE VIEW set_active_smos AS
+  SELECT seqno, 
+         entryno,
+         report_status UPDATED,
+         datum_status  UPDATED,
+         distribtype   UPDATED,
+    FROM hdr, smos, body, 
+    where nobs_averaged IS NOT NULL AND nobs_averaged > 0
+;
+
diff --git a/odb/src/ddl/setup_tovscv.sql b/odb/src/ddl/setup_tovscv.sql
new file mode 100644
index 0000000..c980393
--- /dev/null
+++ b/odb/src/ddl/setup_tovscv.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'setup_tovscv.sql'
+//
+//   Last updated:  05-Jul-2002
+//
+
+READONLY;
+
+CREATE VIEW setup_tovscv AS
+  SELECT seqno,timeslot,
+// get obstype and obs characteristix for debugging purposes only
+         obstype,
+         codetype,
+         instrument_type,
+         retrtype,
+         areatype,
+// get abnob for debugging purposes only
+	       abnob, 
+         maptovscv,
+         skintemper,
+         skintemp[1:($NMXUPD+1)]@radiance,
+         tsfc,
+   FROM  index, hdr, sat, radiance, modsurf
+  WHERE  (obstype = $satem)
+     AND (codetype = $atovs)
+ORDERBY  timeslot, seqno
+;
diff --git a/odb/src/ddl/setup_tovscv_cloud_sink.sql b/odb/src/ddl/setup_tovscv_cloud_sink.sql
new file mode 100644
index 0000000..ea226b0
--- /dev/null
+++ b/odb/src/ddl/setup_tovscv_cloud_sink.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'setup_tovscv_cloud_sink.sql'
+//
+//   Last updated:  05-Jul-2002
+//
+
+READONLY;
+
+CREATE VIEW setup_tovscv_cloud_sink AS
+  SELECT seqno,timeslot,
+         ctopbg,
+         ctoper,
+         ctop[1:$NMXUPD],
+         camtbg,
+         camter,
+         camt[1:$NMXUPD],
+   FROM  index, hdr, sat, radiance, cloud_sink
+  WHERE  (obstype = $satem)
+     AND (codetype = $atovs)
+ORDERBY  timeslot, seqno
+;
diff --git a/odb/src/ddl/size_hdr.sql b/odb/src/ddl/size_hdr.sql
new file mode 100644
index 0000000..7c7199a
--- /dev/null
+++ b/odb/src/ddl/size_hdr.sql
@@ -0,0 +1,11 @@
+//
+//-- ODB/SQL file 'size_hdr.sql'
+//
+//   Last updated:  01-Jul-2009
+//
+
+
+CREATE VIEW size_hdr AS
+  SELECT seqno, subseqno UPDATED
+    FROM hdr
+;
diff --git a/odb/src/ddl/small.sql b/odb/src/ddl/small.sql
new file mode 100644
index 0000000..c3cb707
--- /dev/null
+++ b/odb/src/ddl/small.sql
@@ -0,0 +1,4 @@
+CREATE VIEW small AS
+SELECT
+   lat, lon, trlat, trlon, obstype 
+FROM  index, hdr
diff --git a/odb/src/ddl/smos.h b/odb/src/ddl/smos.h
new file mode 100644
index 0000000..48f5708
--- /dev/null
+++ b/odb/src/ddl/smos.h
@@ -0,0 +1,22 @@
+CREATE TABLE smos AS (
+  snapshot_id       pk1int,          // snapshot indentifier
+  grid_point_id     pk1int,          // grid point identifier
+  electron_count    pk9real,         // total electron count 
+  sun_bt            pk9real,         // direct sun BT
+  snapshot_acc      pk9real,         // snapshot accuracy
+  rad_acc_pure      pk9real,         // radiometric accuracy(pure polarisation)
+  rad_acc_cross     pk9real,         // radiometric accuracy(cross polarisation)
+  footprint_axis[2] pk9real,         // footprint axis
+  polarisation      pk1int,          // polarisation
+  water_fraction    pk9real,         // water fraction
+  incidence_angle   pk9real,         // incidence angle
+  faradey_rot_angle pk9real,         // faradey ratational angle
+  pixel_rot_angle   pk9real,         // pixel radiometric accuracy
+  info              pk1int,          // smos information flag
+  snapshot_quality  pk1int,          // snapshot owerall quality
+  report_tbflag     pk1int,          // observation flag in grid point
+  tbvalue           pk9real,         // modelled brightness temperature
+  nobs_averaged     pk1int,          // number of obs. used for averaging obsvalues (mask can be 2x2, 3x3, etc.)
+  stdev_averaged    pk9real,         // Standard deviation of averaged values
+);
+
diff --git a/odb/src/ddl/sondetyperstrhbody.sql b/odb/src/ddl/sondetyperstrhbody.sql
new file mode 100644
index 0000000..6609588
--- /dev/null
+++ b/odb/src/ddl/sondetyperstrhbody.sql
@@ -0,0 +1,21 @@
+READONLY;
+CREATE VIEW sondetyperstrhbody AS
+SELECT seqno, press,
+//        1     2
+       T_B_m75_vs_all_mean, T_B_m75_75_vs_all_mean, T_B_75_225_vs_all_mean, T_B_225_vs_all_mean, T_B_all_mean,
+//        3                          4                        5                       6                      7
+       RH_B_m75_vs_all_mean, RH_B_m75_75_vs_all_mean, RH_B_75_225_vs_all_mean, RH_B_225_vs_all_mean, RH_B_all_mean,
+//        8                          9                       10                      11                      12 
+       T_B_m75_vs_night_mean, T_B_m75_75_vs_night_mean, T_B_75_225_vs_night_mean, T_B_225_vs_night_mean, T_B_night_mean,
+//       13                         14                       15                      16                      17
+       RH_B_m75_vs_night_mean, RH_B_m75_75_vs_night_mean, RH_B_75_225_vs_night_mean, RH_B_225_vs_night_mean, RH_B_night_mean,
+//       18                         19                       20                      21                     22 
+       T_B_m75_vs_day_mean, T_B_m75_75_vs_day_mean, T_B_75_225_vs_day_mean, T_B_225_vs_day_mean, T_B_day_mean,
+//       23                         24                       25                      26                 27
+       RH_B_m75_vs_day_mean, RH_B_m75_75_vs_day_mean, RH_B_75_225_vs_day_mean, RH_B_225_vs_day_mean, RH_B_day_mean
+//       28                         29                       30                      31                 32 
+FROM  hdr, body
+//WHERE
+//ORDERBY
+;
+
diff --git a/odb/src/ddl/sondetyperstrhhdr.sql b/odb/src/ddl/sondetyperstrhhdr.sql
new file mode 100644
index 0000000..ca1d0a7
--- /dev/null
+++ b/odb/src/ddl/sondetyperstrhhdr.sql
@@ -0,0 +1,14 @@
+READONLY;
+CREATE VIEW sondetyperstrhhdr AS
+SELECT seqno, sonde_type_code,
+//       1           2
+       sonde_name_1, sonde_name_2, sonde_name_3, sonde_name_4,
+//           3            4             5            6
+       sonde_name_5, sonde_name_6, sonde_name_7, sonde_name_8,
+//           7            8             9           10
+       body.offset, body.len
+//          11           12
+FROM hdr
+//WHERE
+//ORDERBY
+;
diff --git a/odb/src/ddl/ssa_robhdr_2m.sql b/odb/src/ddl/ssa_robhdr_2m.sql
new file mode 100644
index 0000000..cbb11c7
--- /dev/null
+++ b/odb/src/ddl/ssa_robhdr_2m.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'ssa_robhdr_2m.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+
+READONLY;
+
+CREATE VIEW ssa_robhdr_2m AS // SSA-analysis (2m analyses); ROBHDR-part
+  SELECT seqno,              // r/o; Must become first
+         body.len,           // r/o
+         date, time,         // r/o
+         obstype,            // r/o
+         codetype,          // r/o
+         lat, lon, statid, stalt  // r/o
+    FROM hdr
+   WHERE ( (reportype >= 16001 AND reportype <= 16004 ) 
+            OR reportype == 16022  OR reportype == 16076 )
+;
diff --git a/odb/src/ddl/ssa_robhdr_snow.sql b/odb/src/ddl/ssa_robhdr_snow.sql
new file mode 100644
index 0000000..2679956
--- /dev/null
+++ b/odb/src/ddl/ssa_robhdr_snow.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'ssa_robhdr_snow.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+READONLY;
+
+CREATE VIEW ssa_robhdr_snow AS // SSA-analysis (snow only); ROBHDR-part
+  SELECT seqno,              // r/o; Must become first
+         body.len,           // r/o
+         date, time,         // r/o
+         obstype,            // r/o
+         codetype,          // r/o
+         lat, lon, statid, stalt  // r/o
+    FROM hdr
+   WHERE obstype= $imsims or 
+   (obstype = $synop AND ( codetype = $synop_land OR codetype = $synop_land_auto OR codetype = $add_land_surface OR codetype == 170 ))
+;
diff --git a/odb/src/ddl/ssa_robody_2m.sql b/odb/src/ddl/ssa_robody_2m.sql
new file mode 100644
index 0000000..50c9ff9
--- /dev/null
+++ b/odb/src/ddl/ssa_robody_2m.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'ssa_robody_2m.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+
+READONLY;
+
+CREATE VIEW ssa_robody_2m AS // SSA-analysis (2m analyses); ROBODY-part
+  SELECT seqno,                      // r/o; Must become first
+         entryno,
+         varno,                      // r/o
+         datum_status at surfbody_feedback UPDATED,       
+         datum_sfc_event at surfbody_feedback UPDATED,        
+         lsm at surfbody_feedback UPDATED,
+         obsvalue ,           
+         level at conv_body,                 // r/o
+    FROM hdr, body, conv, conv_body, surfbody_feedback
+   WHERE  ( (reportype >= 16001 AND reportype <= 16004 ) 
+            OR  reportype == 16022 OR reportype == 16076  ) 
+           AND ( varno  == 2 OR varno == 39 OR varno == 59 OR varno == 40
+            OR varno == 29 OR varno == 58 ) 
+;
diff --git a/odb/src/ddl/ssa_robody_snow.sql b/odb/src/ddl/ssa_robody_snow.sql
new file mode 100644
index 0000000..c6cb260
--- /dev/null
+++ b/odb/src/ddl/ssa_robody_snow.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'ssa_robody_snow.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+
+READONLY;
+
+CREATE VIEW ssa_robody_snow AS // SSA-analysis (snow only); ROBODY-part
+  SELECT seqno,                      // r/o; Must become first
+         entryno,
+         varno,                      // r/o
+         datum_status at surfbody_feedback UPDATED,        
+         datum_sfc_event at surfbody_feedback UPDATED,        
+         lsm at surfbody_feedback UPDATED,
+         obsvalue ,           
+    FROM hdr, body, surfbody_feedback
+   WHERE obstype= $imsims or
+   (obstype = $synop AND ( codetype = $synop_land OR codetype = $synop_land_auto OR codetype = $add_land_surface OR codetype == 170 ))
+;
diff --git a/odb/src/ddl/ssafb_surfbody_2m.sql b/odb/src/ddl/ssafb_surfbody_2m.sql
new file mode 100644
index 0000000..a9d96fe
--- /dev/null
+++ b/odb/src/ddl/ssafb_surfbody_2m.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'ssafb_surfbody_2m.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+
+READONLY;
+
+CREATE VIEW ssafb_surfbody_2m AS // SSA-analysis (2m analyses); ROBODY-part
+  SELECT seqno,                      // r/o; Must become first
+         entryno,
+         varno,                      // r/o
+         datum_status at surfbody_feedback UPDATED,        // possibly updated
+         datum_sfc_event at surfbody_feedback UPDATED,        // possibly updated
+         fg_depar at surfbody_feedback  UPDATED,          // possibly updated
+         an_depar at surfbody_feedback  UPDATED,          // possibly updated
+    FROM hdr, body,surfbody_feedback
+   WHERE ( (reportype >= 16001 AND reportype <= 16004 ) 
+      OR  reportype == 16022 OR reportype == 16076 )  
+           AND ( varno  == 2 OR varno == 39 OR varno == 59 OR varno == 40
+            OR varno == 29 OR varno == 58 ) 
+;
diff --git a/odb/src/ddl/ssafb_surfbody_snow.sql b/odb/src/ddl/ssafb_surfbody_snow.sql
new file mode 100644
index 0000000..672343c
--- /dev/null
+++ b/odb/src/ddl/ssafb_surfbody_snow.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'ssafb_surfbody_snow.sql'
+//
+//   Last updated:  17-May-2002
+//
+
+
+READONLY;
+
+CREATE VIEW ssafb_surfbody_snow AS // SSA-analysis (snow only); ROBODY-part
+  SELECT seqno,                      // r/o; Must become first
+         entryno, 
+         varno,                      // r/o
+         datum_status at surfbody_feedback UPDATED,        // possibly updated
+         datum_sfc_event at surfbody_feedback UPDATED,        // possibly updated
+         fg_depar at surfbody_feedback UPDATED,           // possibly updated
+         an_depar at surfbody_feedback UPDATED,           // possibly updated
+         snow_depth at surfbody_feedback UPDATED, 
+         snow_density at surfbody_feedback UPDATED, 
+    FROM hdr, body,surfbody_feedback
+   WHERE obstype = $imsims or 
+   (obstype = $synop AND ( codetype = $synop_land OR codetype = $synop_land_auto OR codetype = $add_land_surface OR codetype == 170 ))
+;
diff --git a/odb/src/ddl/ssmi1d.h b/odb/src/ddl/ssmi1d.h
new file mode 100644
index 0000000..4eebfc5
--- /dev/null
+++ b/odb/src/ddl/ssmi1d.h
@@ -0,0 +1,53 @@
+//
+// Table Definition: ssmi1d tables
+// These tables were used when ssmi data were assimilated with 1DVAR algorithm
+// Currently obsolete
+//
+CREATE TABLE ssmi AS (
+  iterno_conv_1dvar pk1int,         // NO. OF ITERATIONS 
+  simno_conv_1dvar pk1int,          // NO. OF SIMULATIONS 
+  failure_1dvar pk1int,             // FAILURE INDICATOR
+  epsg_1dvar pk9real,               // 1D VAR CONVERGENCE CRITERION
+  minim_status_1dvar pk1int,        // 1D VAR MINIMISATION STATUS
+  surfpress[1] pk9real,             // from slev, SFC PRESSURE
+  skintemp[1] pk9real,              // from slev, SKIN TEMPERATURE
+  u10m[2] pk9real,                  // from slev, U-WIND 10M
+  v10m[2] pk9real,                  // from slev, V-WIND 10M
+  prec_st[2] pk9real,               // new      , SFC STRAT. PRECIP.
+  prec_cv[2] pk9real,               // new      , SFC CONV. PRECIP.
+  cost pk9real,                     // Ratio of cost functions Jo/Jo_n
+  sfc_rain_3d_fg pk9real,           // Rain at FG from 3D model
+  sfc_snow_3d_fg pk9real,           // ditto snow
+  sfc_rain_3d_an pk9real,           // Rain at 4D-Var analysis from 3D model
+  sfc_snow_3d_an pk9real,           // ditto snow  
+  rwp[4] pk9real,                   // Rain, snow, cloud water and cloud ice paths [kg m^-2]
+  swp[4] pk9real,                   // ???
+  cwp[4] pk9real,                   // ???
+  iwp[4] pk9real,                   // ???
+  ssmi_body @LINK,  
+);
+
+CREATE TABLE ssmi_body AS (
+  tcwv_fg pk9real,         // TCWV OBS -> MDB1BPWS  Used for 1D only 
+
+  tcwv_fg_err pk9real,     // TCWV FG  -> MDB1DREP
+  radcost pk9real,         // 1D VAR RADIANCE COST 
+  rad_obs      pk9real,    // new, RADIANCE OBSERVATION
+  rad_fg_depar pk9real,    // new, RADIANCE FG DEPARTURE
+  rad_an_depar pk9real,    // new, RADIANCE AN DEPARTURE
+  rad_obs_err  pk9real,    // new, RADIANCE OBS. ERROR
+  rad_bias     pk9real,    // new, RADIANCE BIAS
+  rad_fg_3d    pk9real,    // new, RADIANCES AT FG USING 3D MODEL CLOUDS
+  rad_4dan     pk9real,    // new, RADIANCES AT 4D AN USING 3D MODEL CLOUDS
+
+  frequency pk9real,       // CHANNEL CENTRE FREQUENCY
+  bandwidth pk9real,       // CHANNEL BAND WIDTH
+  polarisation pk9real,    // ANTENNA POLARISATION
+
+  press pk9real,           // from mlev, PRESSURE
+  temp[2] pk9real,         // from mlev, TEMPERATURE
+  q[2] pk9real,            // from mlev, SPEC. HUMIDITY
+  rain[2] pk9real,         // new      , LIQUID PRECIP FLUX
+  snow[2] pk9real,         // new      , FROZEN PRECIP FLUX.
+);
+
diff --git a/odb/src/ddl/stat_obs_1.sql b/odb/src/ddl/stat_obs_1.sql
new file mode 100644
index 0000000..c13674c
--- /dev/null
+++ b/odb/src/ddl/stat_obs_1.sql
@@ -0,0 +1,8 @@
+//
+// Created by Anne Fouilloux - 13/04/2010
+//
+CREATE VIEW stat_obs_1 AS
+SELECT obstype,codetype
+FROM hdr 
+ORDERBY obstype, codetype
+;
diff --git a/odb/src/ddl/stat_obs_2.sql b/odb/src/ddl/stat_obs_2.sql
new file mode 100644
index 0000000..5e128ff
--- /dev/null
+++ b/odb/src/ddl/stat_obs_2.sql
@@ -0,0 +1,7 @@
+//
+// Created by Anne Fouilloux - 13/04/2010
+//
+CREATE VIEW stat_obs_2 AS
+SELECT count(seqno)
+FROM hdr
+;
diff --git a/odb/src/ddl/stat_obs_3.sql b/odb/src/ddl/stat_obs_3.sql
new file mode 100644
index 0000000..3513222
--- /dev/null
+++ b/odb/src/ddl/stat_obs_3.sql
@@ -0,0 +1,10 @@
+//
+// Created by Anne Fouilloux - 13/05/2012
+//
+
+READONLY;
+
+CREATE VIEW stat_obs_3 AS
+SELECT count(obsvalue), varno, reportype
+FROM hdr, body where fg_depar IS NOT NULL
+;
diff --git a/odb/src/ddl/store_enda.sql b/odb/src/ddl/store_enda.sql
new file mode 100644
index 0000000..9e932f2
--- /dev/null
+++ b/odb/src/ddl/store_enda.sql
@@ -0,0 +1,27 @@
+//
+//-- ODB/SQL file 'store_enda.sql'
+//
+//   Last updated:  15/06/12
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+CREATE VIEW store_enda AS
+  SELECT
+    report_status, 
+    report_event1,
+    obsvalue,
+    datum_anflag,
+    datum_status,
+    datum_event1,
+    biascorr,
+    biascorr_fg,
+    an_depar,
+    fg_depar,
+    qc_pge,
+    obs_error,
+    final_obs_error,
+    fg_error, 
+    FROM   hdr, body, errstat
+;
+
diff --git a/odb/src/ddl/sufger_allsky.sql b/odb/src/ddl/sufger_allsky.sql
new file mode 100644
index 0000000..cf08d1d
--- /dev/null
+++ b/odb/src/ddl/sufger_allsky.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'sufger_allsky.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sufger_allsky AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+	 sensor,                       // r/o
+         satellite_identifier at sat,     // r/o
+         ob_p37, fg_p37, an_p37,       // r/o - used by all-sky mwave only
+         zenith at sat,
+  FROM   timeslot_index, index, hdr, sat, radiance, allsky
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/sufger_allsky_body.sql b/odb/src/ddl/sufger_allsky_body.sql
new file mode 100644
index 0000000..70b9425
--- /dev/null
+++ b/odb/src/ddl/sufger_allsky_body.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'sufger_allsky_body.sql'
+//
+//   Last updated:  08-Sep-2013
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sufger_allsky_body AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         datum_tbflag,
+  FROM   timeslot_index, index, hdr, body, allsky, allsky_body
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/sufger_robhdr_1.sql b/odb/src/ddl/sufger_robhdr_1.sql
new file mode 100644
index 0000000..3404015
--- /dev/null
+++ b/odb/src/ddl/sufger_robhdr_1.sql
@@ -0,0 +1,25 @@
+//
+//-- ODB/SQL file 'sufger_robhdr_1.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sufger_robhdr_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         abnob, mapomm,                // r/o
+         body.len,                     // r/o
+         obstype,                      // r/o
+         codetype,                     // r/o
+         instrument_type,                     // r/o
+         retrtype,                     // r/o
+         areatype,                     // r/o
+         lat, lon,                     // r/o
+  FROM   timeslot_index, index, hdr
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/sufger_robody_1.sql b/odb/src/ddl/sufger_robody_1.sql
new file mode 100644
index 0000000..ec484fd
--- /dev/null
+++ b/odb/src/ddl/sufger_robody_1.sql
@@ -0,0 +1,28 @@
+//
+//-- ODB/SQL file 'sufger_robody_1.sql'
+//
+//   Last updated:  08-Sep-2006
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sufger_robody_1 AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         entryno,                      // r/o
+         vertco_type,                  // r/o
+         varno,                        // r/o
+         datum_status at body,            // possibly updated
+         datum_event1 at body,            // r/o
+         vertco_reference_1,           // r/o
+         vertco_reference_2,           // r/o
+         fg_depar  UPDATED,            // possibly updated (in ECMA)
+         fg_error  UPDATED,            // possibly updated (in ECMA)
+         eda_spread UPDATED,           // possible updated (in ECMA)
+         final_obs_error,              // r/o
+  FROM   timeslot_index, index, hdr, body, errstat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/sufger_sat.sql b/odb/src/ddl/sufger_sat.sql
new file mode 100644
index 0000000..45f49d5
--- /dev/null
+++ b/odb/src/ddl/sufger_sat.sql
@@ -0,0 +1,20 @@
+//
+//-- ODB/SQL file 'sufger_sat.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW sufger_sat AS
+  SELECT seqno,                        // r/o; MUST BECOME FIRST
+         body.len,                     // r/o
+         sensor,                       // r/o
+         satellite_identifier at sat,     // r/o
+  FROM   timeslot_index, index, hdr, sat
+  WHERE	 (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+;
diff --git a/odb/src/ddl/sugoms.sql b/odb/src/ddl/sugoms.sql
new file mode 100644
index 0000000..1e6d3b7
--- /dev/null
+++ b/odb/src/ddl/sugoms.sql
@@ -0,0 +1,12 @@
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW sugoms AS
+  SELECT seqno, // for debugging purposes only
+         timeslot at index, obstype, 
+	       mapomm,
+    FROM timeslot_index, index, hdr
+   WHERE ($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot)
+ ORDERBY mapomm
+;
diff --git a/odb/src/ddl/suobarea.sql b/odb/src/ddl/suobarea.sql
new file mode 100644
index 0000000..f18cf99
--- /dev/null
+++ b/odb/src/ddl/suobarea.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'suobarea.sql'
+//
+//   Last updated:  08-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW suobarea AS
+  SELECT codetype,
+         instrument_type,
+         retrtype,
+         areatype UPDATED,
+	 obstype,
+    FROM timeslot_index, index, hdr
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+         AND (obstype /= $satem) AND (obstype /= $satob) AND (obstype /= $limb)
+         AND (obstype /= $allsky)
+         AND (obstype /= $scatt)
+;
diff --git a/odb/src/ddl/suobarea_limb.sql b/odb/src/ddl/suobarea_limb.sql
new file mode 100644
index 0000000..e55143e
--- /dev/null
+++ b/odb/src/ddl/suobarea_limb.sql
@@ -0,0 +1,17 @@
+//
+//-- ODB/SQL file 'suobarea_limb.sql'
+//
+//   Last updated:  22-Nov-2004
+//
+
+SET $tslot = -1;
+
+CREATE VIEW suobarea_limb AS
+  SELECT areatype,                    // updated
+	     codetype READONLY, 
+         satellite_identifier at sat READONLY, 
+         sensor READONLY  // r/o
+    FROM index, hdr, sat
+   WHERE (($tslot == -1 AND timeslot > 0) OR (timeslot == $tslot))
+         AND (obstype = $limb )
+;
diff --git a/odb/src/ddl/suobarea_sat.sql b/odb/src/ddl/suobarea_sat.sql
new file mode 100644
index 0000000..9eb0baa
--- /dev/null
+++ b/odb/src/ddl/suobarea_sat.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'suobarea_sat.sql'
+//
+//   Last updated:  08-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW suobarea_sat AS
+  SELECT codetype,
+         instrument_type,
+         retrtype,
+         areatype UPDATED,
+         obstype, 
+         satellite_identifier at sat, 
+         sensor,
+    FROM timeslot_index, index, hdr, sat
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+         AND ((obstype = $satem) OR (obstype = $allsky))
+;
diff --git a/odb/src/ddl/suobarea_satob.sql b/odb/src/ddl/suobarea_satob.sql
new file mode 100644
index 0000000..4a80efa
--- /dev/null
+++ b/odb/src/ddl/suobarea_satob.sql
@@ -0,0 +1,22 @@
+//
+//-- ODB/SQL file 'suobarea_satob.sql'
+//
+//   Last updated:  08-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW suobarea_satob AS
+  SELECT codetype,
+         instrument_type,
+         retrtype,
+         areatype UPDATED,
+    	 obstype, 
+         satellite_identifier at sat,
+         comp_method at satob,
+    FROM timeslot_index, index, hdr, sat, satob
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+         AND (obstype = $satob)
+;
diff --git a/odb/src/ddl/suobarea_scatt.sql b/odb/src/ddl/suobarea_scatt.sql
new file mode 100644
index 0000000..f55a1e4
--- /dev/null
+++ b/odb/src/ddl/suobarea_scatt.sql
@@ -0,0 +1,21 @@
+//
+//-- ODB/SQL file 'suobarea_scatt.sql'
+//
+//   Last updated:  08-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW suobarea_scatt AS
+  SELECT codetype,
+         instrument_type,
+         retrtype,
+         areatype UPDATED,
+    	 obstype, 
+         reportype,
+    FROM timeslot_index, index, hdr
+   WHERE (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+         AND (obstype = $scatt)
+;
diff --git a/odb/src/ddl/suobsaddr.sql b/odb/src/ddl/suobsaddr.sql
new file mode 100644
index 0000000..395704f
--- /dev/null
+++ b/odb/src/ddl/suobsaddr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'suobsaddr.sql'
+//
+//   Last updated:  02-Feb-2005
+//
+
+SET $tslot = -1;
+
+READONLY;
+
+CREATE VIEW suobsaddr AS
+  SELECT seqno, // for debugging purposes only
+         timeslot at index, obstype, 
+         codetype,       // for debugging purposes only
+         instrument_type, // for debugging purposes only
+         retrtype,  // for debugging purposes only
+         areatype,       // for debugging purposes only
+	 abnob UPDATED, 
+	 maptovscv UPDATED,
+         codetype, // r/o
+    FROM timeslot_index, index, hdr
+   WHERE ($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot)
+ ORDERBY timeslot at index, seqno
+;
diff --git a/odb/src/ddl/suobsbias_robhdr_0.sql b/odb/src/ddl/suobsbias_robhdr_0.sql
new file mode 100644
index 0000000..e69de29
diff --git a/odb/src/ddl/suobsbias_robody_0.sql b/odb/src/ddl/suobsbias_robody_0.sql
new file mode 100644
index 0000000..e69de29
diff --git a/odb/src/ddl/suobscor_robhdr.sql b/odb/src/ddl/suobscor_robhdr.sql
new file mode 100644
index 0000000..5d41591
--- /dev/null
+++ b/odb/src/ddl/suobscor_robhdr.sql
@@ -0,0 +1,24 @@
+//
+//-- ODB/SQL file 'suobscor_robhdr.sql'
+//
+//   Last updated:  27-Mar-2006
+//
+
+READONLY;
+
+CREATE VIEW suobscor_robhdr AS
+  SELECT seqno  READONLY,              // r/o; MUST COME FIRST
+         body.len  READONLY,           // r/o
+         date, time,         // r/o
+         obstype,            // r/o
+         codetype,          // r/o
+         instrument_type,    // r/o
+         retrtype,     // r/o
+         areatype,          // r/o
+         sensor,          // r/o
+         satellite_identifier at sat,          // r/o
+         abnob, mapomm,      // r/o
+         lat, lon, statid,   // r/o
+         timeslot at timeslot_index,   // r/o
+  FROM   index, hdr, sat,  timeslot_index
+;
diff --git a/odb/src/ddl/suobscor_robody.sql b/odb/src/ddl/suobscor_robody.sql
new file mode 100644
index 0000000..8322e5c
--- /dev/null
+++ b/odb/src/ddl/suobscor_robody.sql
@@ -0,0 +1,19 @@
+//
+//-- ODB/SQL file 'suobscor_robody.sql'
+//
+//   Last updated:  27-March-2006
+//
+
+UPDATED;
+
+
+CREATE VIEW suobscor_robody AS   
+  SELECT entryno, varno,     
+         obs_corr_ev[1:$NUMEV],
+         obs_corr_mask at errstat,
+         obs_corr_diag[1:$NUMDIAG],   
+         final_obs_error READONLY,
+         obsvalue READONLY,
+         vertco_reference_1 READONLY,
+  FROM   index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/surfbody_feedback.h b/odb/src/ddl/surfbody_feedback.h
new file mode 100644
index 0000000..518cb59
--- /dev/null
+++ b/odb/src/ddl/surfbody_feedback.h
@@ -0,0 +1,14 @@
+//
+// Table Definition: surface analysis feedback tables
+//
+
+CREATE TABLE surfbody_feedback AS (
+  datum_status          TYPEOF(report_status at hdr),   // New feature; equivalent to old def : "status STATUS_t"
+  datum_sfc_event       datum_sfc_event_t,           // OBSERVATION EVENTS FOR SURFACE ANALYSIS 
+  an_depar              pk9real,                     // OBSERVED MINUS ANALYSED VALUE
+  fg_depar              pk9real,                     // OBSERVED MINUS FIRST GUESS VALUE
+  snow_depth            pk9real,                     // model first-guess snow depth (m)
+  snow_density          pk9real,                     // model first-guess snow density 
+  lsm                   pk9real,                     // model land-sea mask
+);
+
diff --git a/odb/src/ddl/suvarbc_robhdh_0.sql b/odb/src/ddl/suvarbc_robhdh_0.sql
new file mode 100644
index 0000000..e69de29
diff --git a/odb/src/ddl/suvarbc_robhdr_0.sql b/odb/src/ddl/suvarbc_robhdr_0.sql
new file mode 100644
index 0000000..c999de8
--- /dev/null
+++ b/odb/src/ddl/suvarbc_robhdr_0.sql
@@ -0,0 +1,17 @@
+//
+//-- ODB/SQL file 'suvarbc_robhdr_0.sql'
+//
+//   Last updated:  19-Mar-2004
+//
+
+READONLY;
+
+CREATE VIEW suvarbc_robhdr_0 AS
+  SELECT seqno  READONLY,              // r/o; MUST COME FIRST
+         body.len  READONLY,           // r/o
+         satellite_identifier at sat,                    // r/o
+         sensor,                       // r/o
+         codetype at hdr,                 // r/o
+  FROM   index, hdr, sat
+  WHERE  obstype = $satem
+;
diff --git a/odb/src/ddl/suvarbc_robody_0.sql b/odb/src/ddl/suvarbc_robody_0.sql
new file mode 100644
index 0000000..f07d993
--- /dev/null
+++ b/odb/src/ddl/suvarbc_robody_0.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'suvarbc_robody_0.sql'
+//
+//   Last updated:  19-Mar-2004
+//
+
+READONLY;
+
+CREATE VIEW suvarbc_robody_0 AS
+  SELECT seqno  READONLY,              // r/o; MUST COME FIRST
+         vertco_reference_1,           // possibly updated
+         final_obs_error,              // possibly updated
+         fg_depar,                     // possibly updated
+  FROM   index, hdr, body, errstat
+  WHERE  obstype = $satem
+;
diff --git a/odb/src/ddl/swapbytes.h b/odb/src/ddl/swapbytes.h
new file mode 120000
index 0000000..0b73ac2
--- /dev/null
+++ b/odb/src/ddl/swapbytes.h
@@ -0,0 +1 @@
+../include/swapbytes.h
\ No newline at end of file
diff --git a/odb/src/ddl/tcwv.sql b/odb/src/ddl/tcwv.sql
new file mode 100644
index 0000000..2264e4e
--- /dev/null
+++ b/odb/src/ddl/tcwv.sql
@@ -0,0 +1,15 @@
+CREATE VIEW tcwv AS
+SELECT
+date, time, satellite_identifier at sat,
+lat, lon, lsm, obsvalue, fg_depar, an_depar, biascorr,
+datum_status.active at body, datum_status.passive at body,
+datum_status.rejected at body, datum_status.blacklisted at body,
+datum_event1.rdb_rejected at body, datum_event1.datum_redundant at body,
+datum_event1.level_redundant at body,
+datum_event1.duplicate at body, report_event1.redundant at hdr,
+datum_anflag.varqc at body, datum_anflag.fg at body
+
+FROM hdr, body, sat, modsurf
+WHERE
+obstype at hdr=7 AND codetype=214 AND varno at body=9 AND fg_depar is not NULL
+;
diff --git a/odb/src/ddl/time_info.sql b/odb/src/ddl/time_info.sql
new file mode 100644
index 0000000..b674f03
--- /dev/null
+++ b/odb/src/ddl/time_info.sql
@@ -0,0 +1,8 @@
+//
+// Created by Anne Fouilloux - 13/04/2010
+//
+CREATE VIEW time_info AS
+SELECT distinct timeslot, enddate, endtime
+FROM   timeslot_index
+ORDERBY timeslot
+;
diff --git a/odb/src/ddl/time_numtsl.sql b/odb/src/ddl/time_numtsl.sql
new file mode 100644
index 0000000..9d811d5
--- /dev/null
+++ b/odb/src/ddl/time_numtsl.sql
@@ -0,0 +1,7 @@
+//
+// Created by Anne Fouilloux - 13/04/2010
+//
+CREATE VIEW time_numtsl AS
+SELECT distinct andate,antime, inidate, initime, numtsl
+FROM   desc
+;
diff --git a/odb/src/ddl/tovsrtovs_robody_1.sql b/odb/src/ddl/tovsrtovs_robody_1.sql
new file mode 100644
index 0000000..2674310
--- /dev/null
+++ b/odb/src/ddl/tovsrtovs_robody_1.sql
@@ -0,0 +1,36 @@
+//
+//-- ODB/SQL file 'tovsrtovs_robody_1.sql'
+//
+//   Last updated:  24-May-2000
+//
+
+SET $tslot = -1;
+
+CREATE VIEW tovsrtovs_robody_1 AS
+  SELECT seqno  READONLY,              // r/o; MUST BECOME FIRST
+         entryno,                      // possibly updated
+         vertco_type,                  // possibly updated
+         varno,                        // possibly updated
+         datum_event1 at body,                  // possibly updated
+         datum_event2 at body,                  // possibly updated
+         datum_status at body,                  // possibly updated
+         datum_anflag at body,                  // possibly updated
+         datum_rdbflag at body,                 // possibly updated
+         obsvalue,                     // possibly updated
+         vertco_reference_1,           // possibly updated
+         vertco_reference_2,           // possibly updated
+         final_obs_error,              // possibly updated
+         obs_error,                    // possibly updated
+         pers_error,                   // possibly updated
+         repres_error,                 // possibly updated
+         fg_error,                     // possibly updated
+         qc_a,                // possibly updated
+         qc_l,                // possibly updated
+         qc_pge,                // possibly updated
+         fg_depar,                     // possibly updated
+         an_depar,                     // possibly updated
+  FROM   index, hdr, body, errstat
+  WHERE  obstype = $satem
+    AND  (codetype = $tovs OR codetype = $rtovs)
+    AND	 (($tslot == -1 AND timeslot > 0) OR (timeslot == $tslot))
+;
diff --git a/odb/src/ddl/tslot.sql b/odb/src/ddl/tslot.sql
new file mode 100644
index 0000000..c3403b2
--- /dev/null
+++ b/odb/src/ddl/tslot.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'tslot.sql'
+//
+//   Last updated:  11-Oct-2001
+//
+
+READONLY;
+
+CREATE VIEW tslot AS
+  SELECT timeslot
+    FROM index
+;
diff --git a/odb/src/ddl/type_definitions.h b/odb/src/ddl/type_definitions.h
new file mode 100644
index 0000000..9862cd5
--- /dev/null
+++ b/odb/src/ddl/type_definitions.h
@@ -0,0 +1,209 @@
+//
+// Type definitions
+//
+
+CREATE TYPE report_rdbflag_t AS (
+  lat_humon bit1,  
+  lat_QCsub bit1,  
+  lat_override bit1,  
+  lat_flag bit2,  
+  lat_HQC_flag bit1,  
+  lon_humon bit1,  
+  lon_QCsub bit1,  
+  lon_override bit1,  
+  lon_flag bit2,  
+  lon_HQC_flag bit1,  
+  date_humon bit1,  
+  date_QCsub bit1,  
+  date_override bit1,  
+  date_flag bit2,  
+  date_HQC_flag bit1,  
+  time_humon bit1,  
+  time_QCsub bit1,  
+  time_override bit1,  
+  time_flag bit2,  
+  time_HQC_flag bit1,  
+  stalt_humon bit1,  
+  stalt_QCsub bit1,  
+  stalt_override bit1,  
+  stalt_flag bit2,  
+  stalt_HQC_flag bit1,  
+);
+
+CREATE TYPE status_t AS (
+  active bit1,                          // ACTIVE FLAG
+  passive bit1,                         // PASSIVE FLAG
+  rejected bit1,                        // REJECTED FLAG
+  blacklisted bit1,                     // BLACKLISTED
+  use_emiskf_only bit1,                 // to be used for emiskf only
+);
+
+CREATE TYPE datum_rdbflag_t AS (
+  press_humon bit1,  
+  press_QCsub bit1,  
+  press_override bit1,  
+  press_flag bit2,  
+  press_HQC_flag bit1,  
+  press_judged_prev_an bit2,  
+  press_used_prev_an bit1,  
+  _press_unused_6 bit6,  
+  varno_humon bit1,  
+  varno_QCsub bit1,  
+  varno_override bit1,  
+  varno_flag bit2,  
+  varno_HQC_flag bit1,  
+  varno_judged_prev_an bit2,  
+  varno_used_prev_an bit1,  
+//  _varno_unused_6 bit6,  
+);
+
+CREATE TYPE datum_flag_t AS (
+  final bit4,                           // FINAL FLAG
+  fg bit4,                              // FIRST GUESS FLAG
+  depar bit4,                           // DEPARTURE FLAG
+  varQC bit4,                           // VARIATIONAL QUALITY FLAG
+  blacklist bit4,                       // BLACKLIST FLAG
+  ups bit1,                             // d'utilisation par analyse de pression de surface
+  uvt bit1,                             // d'utilisation par analyse de vent et temperature
+  uhu bit1,                             // d'utilisation par analyse d'humidite
+  ut2 bit1,                             // d'utilisation par analyse de temperat ure a 2m
+  uh2 bit1,                             // d'utilisation par analyse d'humidite a 2m
+  uv1 bit1,                             // d'utilisation par analyse de vent a 10m
+  urr bit1,                             // d'utilisation par analyse de precipitations
+  usn bit1,                             // d'utilisation par analyse de neige
+  usst bit1,                            // d'utilisation par analyse de temperature de surface de la mer
+);
+
+CREATE TYPE level_t AS (
+  //id bit9,                              // PILOT LEV. ID.
+  maxwind bit1,                         // MAX WIND LEVEL
+  tropopause bit1,                      // TROPOPAUSE 
+  D_part bit1,                          // D PART
+  C_part bit1,                          // C PART
+  B_part bit1,                          // B PART
+  A_part bit1,                          // A PART
+  surface bit1,                         // SURFACE LEVEL
+  signwind bit1,                        // SIGNIFICANT WIND LEVEL
+  signtemp bit1,                        // SIGNIFICANT TEMPR. LEVEL
+);
+
+CREATE TYPE report_event1_t AS (
+  no_data bit1,                         // no data in the report
+  all_rejected bit1,                    // all data rejected
+  bad_practice bit1,                    // bad reporting practice
+  rdb_rejected bit1,                    // rejected due to RDB flag
+  redundant bit1,                       // redundant report
+  stalt_missing bit1,                   // missing station altitude
+  QC_failed bit1,                       // failed quality control
+  overcast_ir bit1,                     // report overcast IR
+  thinned bit1,                         // wvc thinned out
+  latlon_corrected bit1,                // position corrected using station database value
+  stalt_corrected bit1,                 // station altitude corrected using station database value
+);
+
+CREATE TYPE report_event2_t AS (        // bits are obstype dependent
+);
+
+CREATE TYPE report_blacklist_t AS (
+  obstype bit1,  
+  statid bit1,  
+  codetype bit1,  
+  instype bit1,  
+  date bit1,  
+  time bit1,  
+  lat bit1,  
+  lon bit1,  
+  stalt bit1,
+  scanpos bit1,  
+  retrtype bit1,  
+  QI_fc bit1,  
+  RFF bit1,  
+  QI_nofc bit1,  
+  modoro bit1,  
+  lsmask bit1,  
+  rlsmask bit1,  
+  modPS bit1,  
+  modTS bit1,  
+  modT2M bit1,  
+  modtop bit1,
+  sensor bit1,
+  fov bit1,
+  satza bit1,
+  andate bit1,
+  antime bit1,
+  solar_elevation bit1,
+  quality_retrieval bit1,
+  cloud_cover bit1,
+  cloud_top_pressure bit1,
+  product_type bit1,
+  sonde_type  bit1,
+);
+
+CREATE TYPE datum_event1_t AS (
+  vertco_missing bit1,               // missing vertical coordinate
+  obsvalue_missing bit1,             // missing observed value
+  fg_missing bit1,                   // missing first guess value
+  rdb_rejected bit1,                 // rejected due ti RDB flag
+  assim_cld_flag bit1,               // assim of cloud-affected radiance
+  bad_practice bit1,                 // bad reporting practice
+  vertpos_outrange bit1,             // vertical position out of range
+  fg2big bit1,                       // too big first guess departure
+  depar2big bit1,                    // too big departure in assimilation
+  obs_error2big bit1,                // too big observation error
+  datum_redundant bit1,              // dedundant datum
+  level_redundant bit1,              // redundant level
+  not_analysis_varno bit1,           // not an analysis variable
+  duplicate bit1,                    // duplicated datum/level
+  levels2many bit1,                  // too many surface data/levels
+  level_selection bit1,              // level selection
+  vertco_consistency bit1,           // vertical consistency check
+  vertco_type_changed bit1,          // vertical coordinate changed from Z to P
+  combined_flagging bit1,            // combined flagging
+  report_rejected bit1,              // datum rejected due to rejected report
+  varQC_performed bit1,              // variational QC performed
+  obserror_increased bit1,           // obs error increased
+  contam_cld_flag bit1,              // cloud contamination
+  contam_rain_flag bit1,             // rain contamination
+  contam_aerosol_flag bit1,          // aerosol contamination
+  bad_emissivity bit1,               // missing or not sensible emissivity values
+  model_cld_flag bit1,               // model cloud		       
+);
+
+CREATE TYPE datum_event2_t AS (      // bits are obstype dependent
+);
+
+CREATE TYPE datum_sfc_event_t AS (
+  statid bit1,                       // bad statid (blacklisted, etc.)
+  lsmask bit1,                       // rejection due to land-sea mask
+  stalt_missing bit1,                // missing station altitude
+  obsvalue_missing bit1,             // missing observed value
+  fg_missing bit1,                   // missing first guess value
+  fg2big bit1,                       // too big first guess departure
+  not_analysis_varno bit1,           // not an analysis variable
+  redundant bit1,                    // redundant report
+  report_rejected bit1,              // datum rejected due to rejected report
+);
+
+CREATE TYPE datum_blacklist_t AS (
+  varno bit1,  
+  vertco_type bit1,  
+  press bit1,  
+  press_rl bit1,  
+  ppcode bit1,
+  obsvalue bit1,  
+  fg_depar bit1,  
+  obs_error bit1,  
+  fg_error bit1,  
+  winchan_dep bit1,
+  obs_t bit1,
+  elevation bit1,
+  winchan_dep2 bit1,
+  tausfc bit1,
+  csr_pclear bit1,
+);
+
+CREATE TYPE aeolus_hdrflag_t AS ( 
+  nadir_location    bit1, //  bit#0 = 1 for location at nadir (calibration mode)
+  orbit_predicted   bit1, //      1         location from orbit predictor
+  omit_from_EE      bit1, //      2         predicted location to omit from EE product
+);
diff --git a/odb/src/ddl/update.h b/odb/src/ddl/update.h
new file mode 100644
index 0000000..049e8e1
--- /dev/null
+++ b/odb/src/ddl/update.h
@@ -0,0 +1,16 @@
+// The following declares up to $NMXUPD update-tables with
+// the naming convention update_1, update_2, ..., update_<$NMXUPD>.
+// Each of them has got exactly the same attributes.
+// Note: It is up to the software to decide how many of these tables will
+// actually be filled !!
+
+// To be cleaned!!! These table should be used to make sure we can restart an IFS task
+// without having to store the entire CCMA/ECMAs.
+CREATE TABLE update[1:$NMXUPD] AS (
+  hires pk9real,               // OBS. MINUS UPD. U HIGH RES. VALUE (filled by each trajectory)
+  lores pk9real,               // OBS. MINUS UPD. U LOW RES. VALUE  (filled by each minimisation)
+  datum_tbflag_hires pk1int,         // Status flag for all-sky  - See yommwave.F90 (for backup to avoid CCMA copy)
+  datum_status_hires  TYPEOF(report_status at hdr), // Status flag at hires (for backup to avoid CCMA copy)
+  obs_diags[1:3] pk9real,      // Diagnostics in observation space (Yannick - Note: hardcoded #3 ;-()
+);
+
diff --git a/odb/src/ddl/update_body_3.sql b/odb/src/ddl/update_body_3.sql
new file mode 100644
index 0000000..3ced037
--- /dev/null
+++ b/odb/src/ddl/update_body_3.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'update_body_3.sql'
+//
+//   Last updated:  07-Jul-2005
+//
+//   To be used in concert with 'update_hdr_3.sql'
+//
+
+READONLY;
+
+CREATE VIEW update_body_3 AS
+  SELECT seqno, // Must become first
+	 vertco_reference_1,          
+	 obsvalue,
+	 varno,
+	 obs_error
+    FROM hdr, body, errstat
+;
diff --git a/odb/src/ddl/update_desc_1.sql b/odb/src/ddl/update_desc_1.sql
new file mode 100644
index 0000000..a134928
--- /dev/null
+++ b/odb/src/ddl/update_desc_1.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'update_desc_1.sql'
+//
+//   Last updated:  01-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW update_desc_1 AS
+  SELECT poolmask // @LINK to poolmask
+    FROM desc
+;
diff --git a/odb/src/ddl/update_desc_2.sql b/odb/src/ddl/update_desc_2.sql
new file mode 100644
index 0000000..b90ede6
--- /dev/null
+++ b/odb/src/ddl/update_desc_2.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'update_desc_2.sql'
+//
+//   Last updated:  23-Jan-2004
+//
+
+UPDATED; // Update modification information (for use by CLOSEDB())
+
+CREATE VIEW update_desc_2 AS
+  SELECT moddate, modtime, modby, latlon_rad
+    FROM desc
+;
diff --git a/odb/src/ddl/update_enkf_links.sql b/odb/src/ddl/update_enkf_links.sql
new file mode 100644
index 0000000..2acf89b
--- /dev/null
+++ b/odb/src/ddl/update_enkf_links.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'update_enkf_links.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+UPDATED;
+
+CREATE VIEW update_enkf_links AS
+  SELECT 
+     body READONLY,         // r/o (offset + length)
+     ensemble,                  // updated (offset + length)
+    FROM hdr
+;
diff --git a/odb/src/ddl/update_fcdiag_links.sql b/odb/src/ddl/update_fcdiag_links.sql
new file mode 100644
index 0000000..68094bd
--- /dev/null
+++ b/odb/src/ddl/update_fcdiag_links.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'update_fcdiag_links.sql'
+//
+//   Last updated:  24/07/10
+//   By          :  Anne Fouilloux
+
+UPDATED;
+
+CREATE VIEW update_fcdiag_links AS
+  SELECT 
+     body READONLY,         // r/o (offset + length)
+    FROM hdr
+;
diff --git a/odb/src/ddl/update_hdr_1.sql b/odb/src/ddl/update_hdr_1.sql
new file mode 100644
index 0000000..945d4c0
--- /dev/null
+++ b/odb/src/ddl/update_hdr_1.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'update_hdr_1.sql'
+//
+//   Last updated:  30-Sep-2003
+//
+
+UPDATED;
+
+CREATE VIEW update_hdr_1 AS
+  SELECT body READONLY,         // r/o (offset + length)
+     update[1:$NMXUPD],     // updated (offset + length)
+	 errstat, // updated
+    FROM hdr
+;
diff --git a/odb/src/ddl/update_hdr_2.sql b/odb/src/ddl/update_hdr_2.sql
new file mode 100644
index 0000000..376341b
--- /dev/null
+++ b/odb/src/ddl/update_hdr_2.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'update_hdr_2.sql'
+//
+//   Last updated:  03-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW update_hdr_2 AS
+  SELECT 
+         lat, lon,  // Updated (degrees -> radians)
+         statid,    // Updated (right shifted)
+    FROM hdr
+;
diff --git a/odb/src/ddl/update_hdr_3.sql b/odb/src/ddl/update_hdr_3.sql
new file mode 100644
index 0000000..fc7a8a4
--- /dev/null
+++ b/odb/src/ddl/update_hdr_3.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'update_hdr_3.sql'
+//
+//   Last updated:  07-Jul-2005
+//
+
+UPDATED;
+
+CREATE VIEW update_hdr_3 AS
+  SELECT seqno READONLY, // Must become first
+	 checksum,
+	 stalt READONLY,
+     window_offset,      // updated to its right value (ECMA only)
+    FROM hdr
+;
diff --git a/odb/src/ddl/update_hprior_1.sql b/odb/src/ddl/update_hprior_1.sql
new file mode 100644
index 0000000..8b5055c
--- /dev/null
+++ b/odb/src/ddl/update_hprior_1.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_1.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_1 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,1)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_10.sql b/odb/src/ddl/update_hprior_10.sql
new file mode 100644
index 0000000..82e204e
--- /dev/null
+++ b/odb/src/ddl/update_hprior_10.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_10.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_10 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,10)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_100.sql b/odb/src/ddl/update_hprior_100.sql
new file mode 100644
index 0000000..88d660e
--- /dev/null
+++ b/odb/src/ddl/update_hprior_100.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_100.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_100 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,100)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_101.sql b/odb/src/ddl/update_hprior_101.sql
new file mode 100644
index 0000000..78e0af2
--- /dev/null
+++ b/odb/src/ddl/update_hprior_101.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_101.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_101 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,101)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_102.sql b/odb/src/ddl/update_hprior_102.sql
new file mode 100644
index 0000000..4fe0761
--- /dev/null
+++ b/odb/src/ddl/update_hprior_102.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_102.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_102 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,102)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_103.sql b/odb/src/ddl/update_hprior_103.sql
new file mode 100644
index 0000000..a868432
--- /dev/null
+++ b/odb/src/ddl/update_hprior_103.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_103.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_103 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,103)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_104.sql b/odb/src/ddl/update_hprior_104.sql
new file mode 100644
index 0000000..7d759d3
--- /dev/null
+++ b/odb/src/ddl/update_hprior_104.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_104.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_104 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,104)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_105.sql b/odb/src/ddl/update_hprior_105.sql
new file mode 100644
index 0000000..714f956
--- /dev/null
+++ b/odb/src/ddl/update_hprior_105.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_105.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_105 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,105)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_106.sql b/odb/src/ddl/update_hprior_106.sql
new file mode 100644
index 0000000..f668d16
--- /dev/null
+++ b/odb/src/ddl/update_hprior_106.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_106.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_106 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,106)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_107.sql b/odb/src/ddl/update_hprior_107.sql
new file mode 100644
index 0000000..f899a85
--- /dev/null
+++ b/odb/src/ddl/update_hprior_107.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_107.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_107 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,107)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_108.sql b/odb/src/ddl/update_hprior_108.sql
new file mode 100644
index 0000000..cf635b6
--- /dev/null
+++ b/odb/src/ddl/update_hprior_108.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_108.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_108 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,108)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_109.sql b/odb/src/ddl/update_hprior_109.sql
new file mode 100644
index 0000000..4156ce5
--- /dev/null
+++ b/odb/src/ddl/update_hprior_109.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_109.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_109 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,109)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_11.sql b/odb/src/ddl/update_hprior_11.sql
new file mode 100644
index 0000000..ccfdd87
--- /dev/null
+++ b/odb/src/ddl/update_hprior_11.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_11.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_11 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,11)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_110.sql b/odb/src/ddl/update_hprior_110.sql
new file mode 100644
index 0000000..1579022
--- /dev/null
+++ b/odb/src/ddl/update_hprior_110.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_110.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_110 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,110)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_111.sql b/odb/src/ddl/update_hprior_111.sql
new file mode 100644
index 0000000..111b200
--- /dev/null
+++ b/odb/src/ddl/update_hprior_111.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_111.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_111 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,111)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_112.sql b/odb/src/ddl/update_hprior_112.sql
new file mode 100644
index 0000000..878af80
--- /dev/null
+++ b/odb/src/ddl/update_hprior_112.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_112.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_112 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,112)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_113.sql b/odb/src/ddl/update_hprior_113.sql
new file mode 100644
index 0000000..b3de3db
--- /dev/null
+++ b/odb/src/ddl/update_hprior_113.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_113.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_113 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,113)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_114.sql b/odb/src/ddl/update_hprior_114.sql
new file mode 100644
index 0000000..14f2efc
--- /dev/null
+++ b/odb/src/ddl/update_hprior_114.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_114.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_114 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,114)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_115.sql b/odb/src/ddl/update_hprior_115.sql
new file mode 100644
index 0000000..888b582
--- /dev/null
+++ b/odb/src/ddl/update_hprior_115.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_115.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_115 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,115)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_116.sql b/odb/src/ddl/update_hprior_116.sql
new file mode 100644
index 0000000..7c5b884
--- /dev/null
+++ b/odb/src/ddl/update_hprior_116.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_116.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_116 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,116)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_117.sql b/odb/src/ddl/update_hprior_117.sql
new file mode 100644
index 0000000..775f6e4
--- /dev/null
+++ b/odb/src/ddl/update_hprior_117.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_117.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_117 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,117)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_118.sql b/odb/src/ddl/update_hprior_118.sql
new file mode 100644
index 0000000..16d12b8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_118.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_118.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_118 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,118)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_119.sql b/odb/src/ddl/update_hprior_119.sql
new file mode 100644
index 0000000..116eaf3
--- /dev/null
+++ b/odb/src/ddl/update_hprior_119.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_119.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_119 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,119)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_12.sql b/odb/src/ddl/update_hprior_12.sql
new file mode 100644
index 0000000..d615bf6
--- /dev/null
+++ b/odb/src/ddl/update_hprior_12.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_12.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_12 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,12)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_120.sql b/odb/src/ddl/update_hprior_120.sql
new file mode 100644
index 0000000..511cd1e
--- /dev/null
+++ b/odb/src/ddl/update_hprior_120.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_120.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_120 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,120)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_13.sql b/odb/src/ddl/update_hprior_13.sql
new file mode 100644
index 0000000..62cc8bf
--- /dev/null
+++ b/odb/src/ddl/update_hprior_13.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_13.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_13 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,13)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_14.sql b/odb/src/ddl/update_hprior_14.sql
new file mode 100644
index 0000000..385dc62
--- /dev/null
+++ b/odb/src/ddl/update_hprior_14.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_14.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_14 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,14)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_15.sql b/odb/src/ddl/update_hprior_15.sql
new file mode 100644
index 0000000..1dff9e2
--- /dev/null
+++ b/odb/src/ddl/update_hprior_15.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_15.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_15 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,15)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_16.sql b/odb/src/ddl/update_hprior_16.sql
new file mode 100644
index 0000000..f478752
--- /dev/null
+++ b/odb/src/ddl/update_hprior_16.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_16.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_16 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,16)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_17.sql b/odb/src/ddl/update_hprior_17.sql
new file mode 100644
index 0000000..35e3ec8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_17.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_17.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_17 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,17)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_18.sql b/odb/src/ddl/update_hprior_18.sql
new file mode 100644
index 0000000..de17c6a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_18.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_18.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_18 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,18)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_19.sql b/odb/src/ddl/update_hprior_19.sql
new file mode 100644
index 0000000..bf1894a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_19.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_19.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_19 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,19)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_2.sql b/odb/src/ddl/update_hprior_2.sql
new file mode 100644
index 0000000..a78da0d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_2.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_2.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_2 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,2)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_20.sql b/odb/src/ddl/update_hprior_20.sql
new file mode 100644
index 0000000..f25cf0f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_20.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_20.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_20 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,20)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_21.sql b/odb/src/ddl/update_hprior_21.sql
new file mode 100644
index 0000000..9784048
--- /dev/null
+++ b/odb/src/ddl/update_hprior_21.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_21.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_21 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,21)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_22.sql b/odb/src/ddl/update_hprior_22.sql
new file mode 100644
index 0000000..b066df6
--- /dev/null
+++ b/odb/src/ddl/update_hprior_22.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_22.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_22 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,22)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_23.sql b/odb/src/ddl/update_hprior_23.sql
new file mode 100644
index 0000000..3a206ee
--- /dev/null
+++ b/odb/src/ddl/update_hprior_23.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_23.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_23 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,23)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_24.sql b/odb/src/ddl/update_hprior_24.sql
new file mode 100644
index 0000000..56a9b0c
--- /dev/null
+++ b/odb/src/ddl/update_hprior_24.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_24.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_24 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,24)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_25.sql b/odb/src/ddl/update_hprior_25.sql
new file mode 100644
index 0000000..85d2da3
--- /dev/null
+++ b/odb/src/ddl/update_hprior_25.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_25.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_25 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,25)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_26.sql b/odb/src/ddl/update_hprior_26.sql
new file mode 100644
index 0000000..fe696f6
--- /dev/null
+++ b/odb/src/ddl/update_hprior_26.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_26.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_26 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,26)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_27.sql b/odb/src/ddl/update_hprior_27.sql
new file mode 100644
index 0000000..df8ba25
--- /dev/null
+++ b/odb/src/ddl/update_hprior_27.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_27.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_27 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,27)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_28.sql b/odb/src/ddl/update_hprior_28.sql
new file mode 100644
index 0000000..5fbdb8d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_28.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_28.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_28 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,28)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_29.sql b/odb/src/ddl/update_hprior_29.sql
new file mode 100644
index 0000000..0f171b8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_29.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_29.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_29 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,29)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_3.sql b/odb/src/ddl/update_hprior_3.sql
new file mode 100644
index 0000000..a425715
--- /dev/null
+++ b/odb/src/ddl/update_hprior_3.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_3.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_3 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,3)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_30.sql b/odb/src/ddl/update_hprior_30.sql
new file mode 100644
index 0000000..cd3a5ec
--- /dev/null
+++ b/odb/src/ddl/update_hprior_30.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_30.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_30 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,30)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_31.sql b/odb/src/ddl/update_hprior_31.sql
new file mode 100644
index 0000000..6c2c538
--- /dev/null
+++ b/odb/src/ddl/update_hprior_31.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_31.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_31 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,31)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_32.sql b/odb/src/ddl/update_hprior_32.sql
new file mode 100644
index 0000000..fce9ebc
--- /dev/null
+++ b/odb/src/ddl/update_hprior_32.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_32.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_32 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,32)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_33.sql b/odb/src/ddl/update_hprior_33.sql
new file mode 100644
index 0000000..874a30f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_33.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_33.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_33 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,33)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_34.sql b/odb/src/ddl/update_hprior_34.sql
new file mode 100644
index 0000000..434b26d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_34.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_34.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_34 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,34)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_35.sql b/odb/src/ddl/update_hprior_35.sql
new file mode 100644
index 0000000..b93be86
--- /dev/null
+++ b/odb/src/ddl/update_hprior_35.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_35.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_35 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,35)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_36.sql b/odb/src/ddl/update_hprior_36.sql
new file mode 100644
index 0000000..f8c18ab
--- /dev/null
+++ b/odb/src/ddl/update_hprior_36.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_36.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_36 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,36)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_37.sql b/odb/src/ddl/update_hprior_37.sql
new file mode 100644
index 0000000..108c388
--- /dev/null
+++ b/odb/src/ddl/update_hprior_37.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_37.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_37 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,37)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_38.sql b/odb/src/ddl/update_hprior_38.sql
new file mode 100644
index 0000000..cff0672
--- /dev/null
+++ b/odb/src/ddl/update_hprior_38.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_38.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_38 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,38)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_39.sql b/odb/src/ddl/update_hprior_39.sql
new file mode 100644
index 0000000..1ca3e62
--- /dev/null
+++ b/odb/src/ddl/update_hprior_39.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_39.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_39 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,39)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_4.sql b/odb/src/ddl/update_hprior_4.sql
new file mode 100644
index 0000000..c4b9e0b
--- /dev/null
+++ b/odb/src/ddl/update_hprior_4.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_4.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_4 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,4)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_40.sql b/odb/src/ddl/update_hprior_40.sql
new file mode 100644
index 0000000..1cb4c61
--- /dev/null
+++ b/odb/src/ddl/update_hprior_40.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_40.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_40 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,40)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_41.sql b/odb/src/ddl/update_hprior_41.sql
new file mode 100644
index 0000000..e736d2d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_41.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_41.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_41 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,41)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_42.sql b/odb/src/ddl/update_hprior_42.sql
new file mode 100644
index 0000000..f49d8e9
--- /dev/null
+++ b/odb/src/ddl/update_hprior_42.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_42.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_42 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,42)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_43.sql b/odb/src/ddl/update_hprior_43.sql
new file mode 100644
index 0000000..8016c30
--- /dev/null
+++ b/odb/src/ddl/update_hprior_43.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_43.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_43 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,43)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_44.sql b/odb/src/ddl/update_hprior_44.sql
new file mode 100644
index 0000000..c8016ba
--- /dev/null
+++ b/odb/src/ddl/update_hprior_44.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_44.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_44 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,44)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_45.sql b/odb/src/ddl/update_hprior_45.sql
new file mode 100644
index 0000000..dfa37de
--- /dev/null
+++ b/odb/src/ddl/update_hprior_45.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_45.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_45 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,45)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_46.sql b/odb/src/ddl/update_hprior_46.sql
new file mode 100644
index 0000000..5f0380a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_46.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_46.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_46 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,46)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_47.sql b/odb/src/ddl/update_hprior_47.sql
new file mode 100644
index 0000000..2d2130f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_47.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_47.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_47 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,47)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_48.sql b/odb/src/ddl/update_hprior_48.sql
new file mode 100644
index 0000000..e3b105d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_48.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_48.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_48 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,48)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_49.sql b/odb/src/ddl/update_hprior_49.sql
new file mode 100644
index 0000000..689a287
--- /dev/null
+++ b/odb/src/ddl/update_hprior_49.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_49.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_49 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,49)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_5.sql b/odb/src/ddl/update_hprior_5.sql
new file mode 100644
index 0000000..1dc0fe0
--- /dev/null
+++ b/odb/src/ddl/update_hprior_5.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_5.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_5 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,5)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_50.sql b/odb/src/ddl/update_hprior_50.sql
new file mode 100644
index 0000000..00925d3
--- /dev/null
+++ b/odb/src/ddl/update_hprior_50.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_50.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_50 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,50)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_51.sql b/odb/src/ddl/update_hprior_51.sql
new file mode 100644
index 0000000..319a646
--- /dev/null
+++ b/odb/src/ddl/update_hprior_51.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_51.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_51 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,51)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_52.sql b/odb/src/ddl/update_hprior_52.sql
new file mode 100644
index 0000000..388ef4d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_52.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_52.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_52 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,52)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_53.sql b/odb/src/ddl/update_hprior_53.sql
new file mode 100644
index 0000000..836d04f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_53.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_53.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_53 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,53)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_54.sql b/odb/src/ddl/update_hprior_54.sql
new file mode 100644
index 0000000..6a626a8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_54.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_54.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_54 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,54)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_55.sql b/odb/src/ddl/update_hprior_55.sql
new file mode 100644
index 0000000..68eeb8b
--- /dev/null
+++ b/odb/src/ddl/update_hprior_55.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_55.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_55 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,55)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_56.sql b/odb/src/ddl/update_hprior_56.sql
new file mode 100644
index 0000000..f856d46
--- /dev/null
+++ b/odb/src/ddl/update_hprior_56.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_56.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_56 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,56)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_57.sql b/odb/src/ddl/update_hprior_57.sql
new file mode 100644
index 0000000..93dc44a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_57.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_57.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_57 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,57)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_58.sql b/odb/src/ddl/update_hprior_58.sql
new file mode 100644
index 0000000..4e11a03
--- /dev/null
+++ b/odb/src/ddl/update_hprior_58.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_58.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_58 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,58)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_59.sql b/odb/src/ddl/update_hprior_59.sql
new file mode 100644
index 0000000..d521cb1
--- /dev/null
+++ b/odb/src/ddl/update_hprior_59.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_59.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_59 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,59)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_6.sql b/odb/src/ddl/update_hprior_6.sql
new file mode 100644
index 0000000..469d92f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_6.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_6.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_6 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,6)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_60.sql b/odb/src/ddl/update_hprior_60.sql
new file mode 100644
index 0000000..106d800
--- /dev/null
+++ b/odb/src/ddl/update_hprior_60.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_60.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_60 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,60)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_61.sql b/odb/src/ddl/update_hprior_61.sql
new file mode 100644
index 0000000..0be5f6e
--- /dev/null
+++ b/odb/src/ddl/update_hprior_61.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_61.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_61 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,61)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_62.sql b/odb/src/ddl/update_hprior_62.sql
new file mode 100644
index 0000000..0da8cf7
--- /dev/null
+++ b/odb/src/ddl/update_hprior_62.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_62.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_62 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,62)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_63.sql b/odb/src/ddl/update_hprior_63.sql
new file mode 100644
index 0000000..8fd2682
--- /dev/null
+++ b/odb/src/ddl/update_hprior_63.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_63.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_63 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,63)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_64.sql b/odb/src/ddl/update_hprior_64.sql
new file mode 100644
index 0000000..9720c4c
--- /dev/null
+++ b/odb/src/ddl/update_hprior_64.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_64.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_64 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,64)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_65.sql b/odb/src/ddl/update_hprior_65.sql
new file mode 100644
index 0000000..b5cd210
--- /dev/null
+++ b/odb/src/ddl/update_hprior_65.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_65.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_65 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,65)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_66.sql b/odb/src/ddl/update_hprior_66.sql
new file mode 100644
index 0000000..4229270
--- /dev/null
+++ b/odb/src/ddl/update_hprior_66.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_66.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_66 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,66)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_67.sql b/odb/src/ddl/update_hprior_67.sql
new file mode 100644
index 0000000..b7e6cad
--- /dev/null
+++ b/odb/src/ddl/update_hprior_67.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_67.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_67 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,67)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_68.sql b/odb/src/ddl/update_hprior_68.sql
new file mode 100644
index 0000000..29068fe
--- /dev/null
+++ b/odb/src/ddl/update_hprior_68.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_68.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_68 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,68)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_69.sql b/odb/src/ddl/update_hprior_69.sql
new file mode 100644
index 0000000..1ce8b1a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_69.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_69.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_69 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,69)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_7.sql b/odb/src/ddl/update_hprior_7.sql
new file mode 100644
index 0000000..e0ef07f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_7.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_7.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_7 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,7)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_70.sql b/odb/src/ddl/update_hprior_70.sql
new file mode 100644
index 0000000..4e61039
--- /dev/null
+++ b/odb/src/ddl/update_hprior_70.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_70.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_70 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,70)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_71.sql b/odb/src/ddl/update_hprior_71.sql
new file mode 100644
index 0000000..0cb40fd
--- /dev/null
+++ b/odb/src/ddl/update_hprior_71.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_71.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_71 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,71)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_72.sql b/odb/src/ddl/update_hprior_72.sql
new file mode 100644
index 0000000..564b8e0
--- /dev/null
+++ b/odb/src/ddl/update_hprior_72.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_72.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_72 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,72)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_73.sql b/odb/src/ddl/update_hprior_73.sql
new file mode 100644
index 0000000..900c928
--- /dev/null
+++ b/odb/src/ddl/update_hprior_73.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_73.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_73 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,73)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_74.sql b/odb/src/ddl/update_hprior_74.sql
new file mode 100644
index 0000000..79c39c1
--- /dev/null
+++ b/odb/src/ddl/update_hprior_74.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_74.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_74 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,74)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_75.sql b/odb/src/ddl/update_hprior_75.sql
new file mode 100644
index 0000000..300d62f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_75.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_75.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_75 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,75)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_76.sql b/odb/src/ddl/update_hprior_76.sql
new file mode 100644
index 0000000..78ae2e0
--- /dev/null
+++ b/odb/src/ddl/update_hprior_76.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_76.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_76 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,76)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_77.sql b/odb/src/ddl/update_hprior_77.sql
new file mode 100644
index 0000000..60d48f1
--- /dev/null
+++ b/odb/src/ddl/update_hprior_77.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_77.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_77 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,77)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_78.sql b/odb/src/ddl/update_hprior_78.sql
new file mode 100644
index 0000000..a265ac9
--- /dev/null
+++ b/odb/src/ddl/update_hprior_78.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_78.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_78 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,78)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_79.sql b/odb/src/ddl/update_hprior_79.sql
new file mode 100644
index 0000000..97299f0
--- /dev/null
+++ b/odb/src/ddl/update_hprior_79.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_79.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_79 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,79)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_8.sql b/odb/src/ddl/update_hprior_8.sql
new file mode 100644
index 0000000..3570126
--- /dev/null
+++ b/odb/src/ddl/update_hprior_8.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_8.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_8 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,8)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_80.sql b/odb/src/ddl/update_hprior_80.sql
new file mode 100644
index 0000000..ee7ed4c
--- /dev/null
+++ b/odb/src/ddl/update_hprior_80.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_80.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_80 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,80)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_81.sql b/odb/src/ddl/update_hprior_81.sql
new file mode 100644
index 0000000..012278e
--- /dev/null
+++ b/odb/src/ddl/update_hprior_81.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_81.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_81 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,81)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_82.sql b/odb/src/ddl/update_hprior_82.sql
new file mode 100644
index 0000000..c83747d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_82.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_82.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_82 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,82)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_83.sql b/odb/src/ddl/update_hprior_83.sql
new file mode 100644
index 0000000..0bef348
--- /dev/null
+++ b/odb/src/ddl/update_hprior_83.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_83.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_83 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,83)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_84.sql b/odb/src/ddl/update_hprior_84.sql
new file mode 100644
index 0000000..96af3d6
--- /dev/null
+++ b/odb/src/ddl/update_hprior_84.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_84.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_84 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,84)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_85.sql b/odb/src/ddl/update_hprior_85.sql
new file mode 100644
index 0000000..e7c866c
--- /dev/null
+++ b/odb/src/ddl/update_hprior_85.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_85.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_85 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,85)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_86.sql b/odb/src/ddl/update_hprior_86.sql
new file mode 100644
index 0000000..2e96a19
--- /dev/null
+++ b/odb/src/ddl/update_hprior_86.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_86.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_86 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,86)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_87.sql b/odb/src/ddl/update_hprior_87.sql
new file mode 100644
index 0000000..0688a09
--- /dev/null
+++ b/odb/src/ddl/update_hprior_87.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_87.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_87 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,87)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_88.sql b/odb/src/ddl/update_hprior_88.sql
new file mode 100644
index 0000000..4aef144
--- /dev/null
+++ b/odb/src/ddl/update_hprior_88.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_88.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_88 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,88)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_89.sql b/odb/src/ddl/update_hprior_89.sql
new file mode 100644
index 0000000..82ff4f2
--- /dev/null
+++ b/odb/src/ddl/update_hprior_89.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_89.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_89 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,89)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_9.sql b/odb/src/ddl/update_hprior_9.sql
new file mode 100644
index 0000000..712cde8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_9.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_9.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_9 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,9)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_90.sql b/odb/src/ddl/update_hprior_90.sql
new file mode 100644
index 0000000..6ba328d
--- /dev/null
+++ b/odb/src/ddl/update_hprior_90.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_90.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_90 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,90)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_91.sql b/odb/src/ddl/update_hprior_91.sql
new file mode 100644
index 0000000..ef1101f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_91.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_91.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_91 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,91)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_92.sql b/odb/src/ddl/update_hprior_92.sql
new file mode 100644
index 0000000..e0ba31a
--- /dev/null
+++ b/odb/src/ddl/update_hprior_92.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_92.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_92 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,92)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_93.sql b/odb/src/ddl/update_hprior_93.sql
new file mode 100644
index 0000000..ce72cd8
--- /dev/null
+++ b/odb/src/ddl/update_hprior_93.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_93.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_93 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,93)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_94.sql b/odb/src/ddl/update_hprior_94.sql
new file mode 100644
index 0000000..3b3f14f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_94.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_94.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_94 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,94)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_95.sql b/odb/src/ddl/update_hprior_95.sql
new file mode 100644
index 0000000..0dcaa30
--- /dev/null
+++ b/odb/src/ddl/update_hprior_95.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_95.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_95 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,95)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_96.sql b/odb/src/ddl/update_hprior_96.sql
new file mode 100644
index 0000000..d000b28
--- /dev/null
+++ b/odb/src/ddl/update_hprior_96.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_96.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_96 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,96)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_97.sql b/odb/src/ddl/update_hprior_97.sql
new file mode 100644
index 0000000..120979f
--- /dev/null
+++ b/odb/src/ddl/update_hprior_97.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_97.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_97 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,97)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_98.sql b/odb/src/ddl/update_hprior_98.sql
new file mode 100644
index 0000000..8cc1f78
--- /dev/null
+++ b/odb/src/ddl/update_hprior_98.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_98.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_98 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,98)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_hprior_99.sql b/odb/src/ddl/update_hprior_99.sql
new file mode 100644
index 0000000..f9d5f49
--- /dev/null
+++ b/odb/src/ddl/update_hprior_99.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'update_hprior_99.sql'
+//
+//   Last updated:  24/02/10
+//   By          :  Anne Fouilloux
+
+READONLY;
+
+SET $tslot = -1;
+SET $kset = 0;
+
+CREATE VIEW update_hprior_99 AS
+  SELECT
+    seqno, entryno, 
+    obsvalue,
+    an_depar,
+    hprior UPDATED,
+    FROM   timeslot_index, index, hdr, body, ensemble, enkf[min($NMXENKF,99)]
+    WHERE  (($tslot == -1 AND timeslot at timeslot_index > 0) OR (timeslot at timeslot_index == $tslot))
+    AND  kset = $kset
+
+;
+
diff --git a/odb/src/ddl/update_links_allsky.sql b/odb/src/ddl/update_links_allsky.sql
new file mode 100644
index 0000000..e72f956
--- /dev/null
+++ b/odb/src/ddl/update_links_allsky.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'update_links_allsky.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+UPDATED;
+
+CREATE VIEW update_links_allsky AS
+  SELECT "/LINK.*/"
+    FROM allsky
+;
diff --git a/odb/src/ddl/update_links_auxiliary.sql b/odb/src/ddl/update_links_auxiliary.sql
new file mode 100644
index 0000000..20623cb
--- /dev/null
+++ b/odb/src/ddl/update_links_auxiliary.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'update_links_auxiliary.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+UPDATED;
+
+CREATE VIEW update_links_auxiliary AS
+  SELECT body, auxiliary_body, 
+    FROM hdr, auxiliary
+;
diff --git a/odb/src/ddl/update_links_gbrad.sql b/odb/src/ddl/update_links_gbrad.sql
new file mode 100644
index 0000000..d4fd6b6
--- /dev/null
+++ b/odb/src/ddl/update_links_gbrad.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'update_links_gbrad.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+UPDATED;
+
+CREATE VIEW update_links_gbrad AS
+  SELECT body, gbrad_body, 
+    FROM hdr, gbrad
+    WHERE obstype=$gbrad and codetype=$radrr
+;
diff --git a/odb/src/ddl/update_links_radiance.sql b/odb/src/ddl/update_links_radiance.sql
new file mode 100644
index 0000000..e89e975
--- /dev/null
+++ b/odb/src/ddl/update_links_radiance.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'update_links_radiance.sql'
+//
+//   Last updated:  01-May-2010
+//
+
+SET $codetype = -1;
+
+UPDATED;
+
+CREATE VIEW update_links_radiance AS
+  SELECT "/LINK.*/"
+    FROM radiance
+;
diff --git a/odb/src/ddl/update_links_raingg.sql b/odb/src/ddl/update_links_raingg.sql
new file mode 100644
index 0000000..5e77c5d
--- /dev/null
+++ b/odb/src/ddl/update_links_raingg.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'update_links_raingg.sql'
+//
+//   Last updated:  22-Jul-2010
+//
+
+UPDATED;
+
+CREATE VIEW update_links_raingg AS
+  SELECT body, raingg_body, 
+    FROM hdr, raingg
+    WHERE obstype=$raingg and codetype=$radrr
+;
diff --git a/odb/src/ddl/update_links_ssmi.sql b/odb/src/ddl/update_links_ssmi.sql
new file mode 100644
index 0000000..bf86114
--- /dev/null
+++ b/odb/src/ddl/update_links_ssmi.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'update_links_ssmi.sql'
+//
+//   Last updated:  01-Oct-2001
+//
+
+UPDATED;
+
+CREATE VIEW update_links_ssmi AS
+  SELECT "/LINK.*/"
+    FROM ssmi
+;
diff --git a/odb/src/ddl/update_modstep.sql b/odb/src/ddl/update_modstep.sql
new file mode 100644
index 0000000..8dae0e4
--- /dev/null
+++ b/odb/src/ddl/update_modstep.sql
@@ -0,0 +1,12 @@
+//
+// Created by J. Munoz Sabater - 21/02/2012
+//
+
+UPDATED;
+
+
+CREATE VIEW update_modstep AS
+  SELECT numtsl READONLY,
+         model_timestep,
+FROM   desc, timeslot_index
+;
diff --git a/odb/src/ddl/varbc_airep_robhdr.sql b/odb/src/ddl/varbc_airep_robhdr.sql
new file mode 100644
index 0000000..8a36ddc
--- /dev/null
+++ b/odb/src/ddl/varbc_airep_robhdr.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'varbc_airep_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_airep_robhdr AS
+  SELECT seqno,
+         statid, obstype, codetype,
+         vertco_reference_1,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  obstype == 2 AND varno == 2 and obsvalue IS NOT NULL
+;
diff --git a/odb/src/ddl/varbc_airep_robody.sql b/odb/src/ddl/varbc_airep_robody.sql
new file mode 100644
index 0000000..b262708
--- /dev/null
+++ b/odb/src/ddl/varbc_airep_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_airep_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_airep_robody AS
+  SELECT seqno,
+         vertco_reference_1,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  obstype == 2 AND varno == 2 and obsvalue IS NOT NULL
+;
diff --git a/odb/src/ddl/varbc_allsky_robhdr.sql b/odb/src/ddl/varbc_allsky_robhdr.sql
new file mode 100644
index 0000000..091d1b2
--- /dev/null
+++ b/odb/src/ddl/varbc_allsky_robhdr.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_allsky_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_allsky_robhdr AS
+  SELECT seqno,
+         satellite_identifier at sat,
+         sensor,
+  FROM   index, hdr, sat
+  WHERE  codetype = $ssmi AND obstype == $allsky
+;
diff --git a/odb/src/ddl/varbc_allsky_robody.sql b/odb/src/ddl/varbc_allsky_robody.sql
new file mode 100644
index 0000000..1cab9b9
--- /dev/null
+++ b/odb/src/ddl/varbc_allsky_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_allsky_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_allsky_robody AS
+  SELECT seqno,
+         vertco_reference_1,          
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  codetype = $ssmi AND obstype == $allsky AND varno == 119
+;
diff --git a/odb/src/ddl/varbc_gbrad_robhdr.sql b/odb/src/ddl/varbc_gbrad_robhdr.sql
new file mode 100644
index 0000000..4dbc41a
--- /dev/null
+++ b/odb/src/ddl/varbc_gbrad_robhdr.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_gbrad_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_gbrad_robhdr AS
+  SELECT seqno,
+         subtype at hdr,
+         source at hdr,
+  FROM   index, hdr
+  WHERE  codetype = $radrr AND obstype == $gbrad
+;
diff --git a/odb/src/ddl/varbc_gbrad_robody.sql b/odb/src/ddl/varbc_gbrad_robody.sql
new file mode 100644
index 0000000..859f513
--- /dev/null
+++ b/odb/src/ddl/varbc_gbrad_robody.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'varbc_gbrad_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_gbrad_robody AS
+  SELECT seqno,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  codetype = $radrr AND obstype == $gbrad AND varno == 203
+;
diff --git a/odb/src/ddl/varbc_mode_hist_robhdr.sql b/odb/src/ddl/varbc_mode_hist_robhdr.sql
new file mode 100644
index 0000000..6fc3df0
--- /dev/null
+++ b/odb/src/ddl/varbc_mode_hist_robhdr.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'varbc_mode_hist_robhdr.sql'
+//
+
+READONLY;
+
+CREATE VIEW varbc_mode_hist_robhdr AS
+  SELECT seqno,
+         body.len,
+         codetype at hdr,
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/varbc_mode_hist_robody.sql b/odb/src/ddl/varbc_mode_hist_robody.sql
new file mode 100644
index 0000000..675171c
--- /dev/null
+++ b/odb/src/ddl/varbc_mode_hist_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_mode_hist_robody.sql'
+//
+
+READONLY;
+
+CREATE VIEW varbc_mode_hist_robody AS
+  SELECT seqno,
+         varbc_ix at body, 
+         fg_depar,
+         biascorr,
+  FROM   index, hdr, body
+  WHERE  datum_status at body = 3
+;
diff --git a/odb/src/ddl/varbc_rad_robhdr.sql b/odb/src/ddl/varbc_rad_robhdr.sql
new file mode 100644
index 0000000..72961ea
--- /dev/null
+++ b/odb/src/ddl/varbc_rad_robhdr.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'varbc_rad_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_rad_robhdr AS
+  SELECT seqno,
+         body.len,
+         satellite_identifier at sat,
+         sensor,
+  FROM   index, hdr, sat
+  WHERE  codetype = $rad1c
+;
diff --git a/odb/src/ddl/varbc_rad_robody.sql b/odb/src/ddl/varbc_rad_robody.sql
new file mode 100644
index 0000000..ebaae1b
--- /dev/null
+++ b/odb/src/ddl/varbc_rad_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_rad_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_rad_robody AS
+  SELECT seqno,
+         vertco_reference_1,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  codetype = $rad1c
+;
diff --git a/odb/src/ddl/varbc_setup_robhdr.sql b/odb/src/ddl/varbc_setup_robhdr.sql
new file mode 100644
index 0000000..904b7b1
--- /dev/null
+++ b/odb/src/ddl/varbc_setup_robhdr.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'varbc_setup_robhdr.sql'
+//
+
+READONLY;
+
+CREATE VIEW varbc_setup_robhdr AS
+  SELECT seqno,
+         body.len,
+         codetype at hdr,
+  FROM   index, hdr
+;
diff --git a/odb/src/ddl/varbc_setup_robody.sql b/odb/src/ddl/varbc_setup_robody.sql
new file mode 100644
index 0000000..7b92b82
--- /dev/null
+++ b/odb/src/ddl/varbc_setup_robody.sql
@@ -0,0 +1,12 @@
+//
+//-- ODB/SQL file 'varbc_setup_robody.sql'
+//
+
+READONLY;
+
+CREATE VIEW varbc_setup_robody AS
+  SELECT seqno,
+         varbc_ix at body, 
+         final_obs_error,
+  FROM   index, hdr, body, errstat
+;
diff --git a/odb/src/ddl/varbc_sfcobs_robhdr.sql b/odb/src/ddl/varbc_sfcobs_robhdr.sql
new file mode 100644
index 0000000..e22103f
--- /dev/null
+++ b/odb/src/ddl/varbc_sfcobs_robhdr.sql
@@ -0,0 +1,18 @@
+//
+//-- ODB/SQL file 'varbc_sfcobs_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_sfcobs_robhdr AS
+  SELECT seqno,
+         body.len,
+         statid, reportype, stalt
+  FROM   index, hdr
+  WHERE  obstype in ($synop,$dribu,$paob)
+;
+
+// Note:
+//    if the elements in the SELE.CT are changed, remember to update varbc_sfcobs.F90
+
diff --git a/odb/src/ddl/varbc_sfcobs_robody.sql b/odb/src/ddl/varbc_sfcobs_robody.sql
new file mode 100644
index 0000000..dc4d656
--- /dev/null
+++ b/odb/src/ddl/varbc_sfcobs_robody.sql
@@ -0,0 +1,23 @@
+//
+//-- ODB/SQL file 'varbc_sfcobs_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_sfcobs_robody AS
+  SELECT seqno,
+         entryno,
+         varno,
+         ppcode at conv_body,
+         obsvalue,
+         varbc_ix at body UPDATED,
+  FROM   timeslot_index, index, hdr, body, conv, conv_body
+  WHERE  obstype in ($synop,$dribu,$paob) AND varno in ($ps,$apdss)
+;
+
+// Notes:
+// 1. if the elements in the SELECT are changed, remember to update varbc_sfcobs.F90
+// 2. if the list of varno in the WHERE are changed, remember to update
+//        hdepart.F90, hretr.F90, hop.F90, hoptl.F90, and hopad.F90
+
diff --git a/odb/src/ddl/varbc_tcwv_robhdr.sql b/odb/src/ddl/varbc_tcwv_robhdr.sql
new file mode 100644
index 0000000..635297e
--- /dev/null
+++ b/odb/src/ddl/varbc_tcwv_robhdr.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_tcwv_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_tcwv_robhdr AS
+  SELECT seqno,
+         satellite_identifier at sat,
+         sensor,
+  FROM   index, hdr, sat
+  WHERE  codetype = $tcwc AND obstype == 7 AND sensor == 174
+;
diff --git a/odb/src/ddl/varbc_tcwv_robody.sql b/odb/src/ddl/varbc_tcwv_robody.sql
new file mode 100644
index 0000000..d4521cf
--- /dev/null
+++ b/odb/src/ddl/varbc_tcwv_robody.sql
@@ -0,0 +1,14 @@
+//
+//-- ODB/SQL file 'varbc_tcwv_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_tcwv_robody AS
+  SELECT seqno,
+         vertco_reference_1,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  codetype = $tcwc AND obstype == 7 AND varno == 9 AND sensor == 174
+;
diff --git a/odb/src/ddl/varbc_to3_robhdr.sql b/odb/src/ddl/varbc_to3_robhdr.sql
new file mode 100644
index 0000000..4bda711
--- /dev/null
+++ b/odb/src/ddl/varbc_to3_robhdr.sql
@@ -0,0 +1,16 @@
+//
+//-- ODB/SQL file 'varbc_to3_robhdr.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_to3_robhdr AS
+  SELECT seqno,    
+	 product_type at resat,
+         body.len, 
+         satellite_identifier at sat,
+         sensor,   
+  FROM   index, hdr, sat, resat
+  WHERE  codetype = $resat
+;
diff --git a/odb/src/ddl/varbc_to3_robody.sql b/odb/src/ddl/varbc_to3_robody.sql
new file mode 100644
index 0000000..ab1fe2d
--- /dev/null
+++ b/odb/src/ddl/varbc_to3_robody.sql
@@ -0,0 +1,15 @@
+//
+//-- ODB/SQL file 'varbc_to3_robody.sql'
+//
+//   For setting VarBC group indices
+
+READONLY;
+
+CREATE VIEW varbc_to3_robody AS
+  SELECT seqno,   
+	 nlayer at body,varno at body,
+	 vertco_reference_1 at body, vertco_reference_2 at body,
+         varbc_ix at body UPDATED,
+  FROM   index, hdr, body
+  WHERE  codetype = $resat
+;
diff --git a/odb/src/ddl/varno.h b/odb/src/ddl/varno.h
new file mode 100644
index 0000000..59f7505
--- /dev/null
+++ b/odb/src/ddl/varno.h
@@ -0,0 +1,156 @@
+// Variable numbers (varno at body) :
+SET  $u  =  3 ;                  //   upper air u component     
+SET  $v  =  4 ;                  //   upper air v component     
+SET  $z  =  1 ;                  //   geopotential              
+SET  $dz  =  57 ;                //   thickness                 
+SET  $rh  =  29 ;                //   upper air rel. humidity   
+SET  $pwc  =  9 ;                //   precipitable water content      
+SET  $rh2m  =  58 ;              //   2m rel. humidity          
+SET  $t  =  2 ;                  //   upper air temperature (K)
+SET  $td  =  59 ;                //   upper air dew point (K) 
+SET  $t2m  =  39 ;               //   2m temperature (K)           
+SET  $td2m  =  40 ;              //   2m dew point (K)             
+SET  $ts  =  11 ;                //   surface temperature (K)      
+SET  $ptend  =  30 ;             //   pressure tendency         
+SET  $w  =  60 ;                 //   past weather (w)          
+SET  $ww  =  61 ;                //   present weather (ww)      
+SET  $vv  =  62 ;                //   visibility                
+SET  $ch  =  63 ;                //   type of high clouds (ch)  
+SET  $cm  =  64 ;                //   type of middle clouds (cm)   
+SET  $cl  =  65 ;                //   type of low clouds (cl)   
+SET  $nh  =  66 ;                //   cloud base height (nh)    
+SET  $nn  =  67 ;                //   low cloud amount (n)      
+SET  $hshs  =  68 ;              //   additional cloud group height (hh)   
+SET  $c  =  69 ;                 //   additional cloud group type (c)   
+SET  $ns  =  70 ;                //   additional cloud group amount (ns)   
+SET  $sdepth  =  71 ;            //   snow depth                
+SET  $e  =  72 ;                 //   state of ground (e)       
+SET  $tgtg  =  73 ;              //   ground temperature (tgtg)   
+SET  $spsp1  =  74 ;             //   special phenomena (spsp)#1   
+SET  $spsp2  =  75 ;             //   special phenomena (spsp)#2   
+SET  $rs  =  76 ;                //   ice code type (rs)        
+SET  $eses  =  77 ;              //   ice thickness (eses)      
+SET  $is  =  78 ;                //   ice (is)                  
+SET  $trtr  =  79 ;              //   original time period of rain obs. (trtr)   
+SET  $rr  =  80 ;                //   6hr rain (liquid part)    
+SET  $jj  =  81 ;                //   max. temperature (jj)     
+SET  $vs  =  82 ;                //   ship speed (vs)           
+SET  $ds  =  83 ;                //   ship direction (ds)       
+SET  $hwhw  =  84 ;              //   wave height               
+SET  $pwpw  =  85 ;              //   wave period               
+SET  $dwdw  =  86 ;              //   wave direction            
+SET  $gclg  =  87 ;              //   general cloud group       
+SET  $rhlc  =  88 ;              //   rel. humidity from low clouds      
+SET  $rhmc  =  89 ;              //   rel. humidity from middle clouds   
+SET  $rhhc  =  90 ;              //   rel. humidity from high clouds     
+SET  $n  =  91 ;                 //   total amount of clouds    
+SET  $sfall  =  92 ;             //   6hr snowfall (solid part of rain)   
+SET  $ps  =  110 ;               //   surface pressure          
+SET  $dd  =  111 ;               //   wind direction            
+SET  $ff  =  112 ;               //   wind force                
+SET  $rawbt  =  119 ;            //   brightness temperature (K)
+SET  $rawra  =  120 ;            //   raw radiance              
+SET  $satcl  =  121 ;            //   cloud amount from satellite   
+SET  $scatss  =  122 ;           //   sigma 0   
+SET  $du  =  5 ;                 //   wind shear (du)   
+SET  $dv  =  6 ;                 //   wind shear (dv)   
+SET  $u10m  =  41 ;              //   10m u component (m/s)
+SET  $v10m  =  42 ;              //   10m v component (m/s)  
+SET  $rhlay  =  19 ;             //   layer rel. humidity   
+SET  $cllqw  =  123 ;            //   cloud liquid water   
+SET  $scatv  =  124 ;            //   ambiguous v component   
+SET  $scatu  =  125 ;            //   ambiguous u component   
+SET  $q  =  7 ;                  //   specific humidity (q)   
+SET  $scatwd  =  126 ;           //   ambiguous wind direction   
+SET  $scatws  =  127 ;           //   ambiguous wind speed       
+SET  $vsp  =  8 ;                //   vertical speed   
+SET  $vt  =  56 ;                //   virtual temperature   
+SET  $o3lay  =  206 ;            //   layer ozone   
+SET  $height  =  156 ;           //   height   
+SET  $1dvar  =  215 ;            //   1d-var model level (pseudo)-variable   
+SET  $w2  =  160 ;               //   past weather 2 (used in synoptic maps)   
+SET  $cpt  =  130 ;              //   characteristic of pressure tendency (used in synoptic maps)   
+SET  $tsts  =  12 ;              //   sea water temperature (used in synoptic maps)   
+SET  $refl  =  192 ;             //   radar reflectivity  
+SET  $apdss  =  128 ;            //   atmospheric path delay in satellite signal   
+SET  $bend_angle  =  162 ;       //   radio occultation bending angle   
+SET  $los  =  187 ;              //   horizontal line-of-sight wind component     
+SET  $aerod  =  174 ;            //   aerosol optical depth at 0.55 microns  
+SET  $limb_radiance =  163 ;     //   Limb Radiances  
+SET  $chem1  =  181 ;            //   chem1: no2/nox   
+SET  $chem2  =  182 ;            //   chem2: so2   
+SET  $chem3  =  183 ;            //   chem3: so   
+SET  $chem4  =  184 ;            //   chem4: hcho   
+SET  $chem5  =  185 ;            //   chem5: go3   
+SET  $cod  =  175 ;              //   cloud optical depth   
+SET  $rao  =  176 ;              //   Ratio of fine mode to total aerosol optical depth at 0.55 microns   
+SET  $od  =  177 ;               //   optical depth   
+SET  $rfltnc  =  178 ;           //   Aerosol reflectance multi-channel   
+SET  $nsoilm  =  179 ;           //   normalized soil moisture  (0-100%) 
+SET  $soilm  =  180 ;            //   soil moisture   
+SET  $flgt_phase  =  201 ;       //   phase of aircraft flight  
+SET  $height_assignment_method  =  211 ;                  //  Height assignment method   
+SET  $dopp  =  195 ;             //   radar doppler wind   
+SET  $ghg1  =  186 ;             //   ghg1: carbon dioxide   
+SET  $ghg2  =  188 ;             //   ghg2: methane   
+SET  $ghg3  =  189 ;             //   ghg3: nitrous oxide   
+SET  $bt_real  =  190 ;          //   brightness temperature real part  
+SET  $bt_imaginary  =  191 ;     //   brightness temperature imaginary part  
+SET  $prc  =  202 ;              //   radar rain rate   
+SET  $lnprc  =  203 ;            //   log(radar rain rate mm/h + epsilon)   
+SET  $libksc  =  222 ;           //   lidar backscattering  
+SET  $ralt_swh  =  220 ;         //   significant wave height (m)           
+SET  $ralt_sws  =  221 ;         //   surface wind speed (m/s)              
+SET  $rawbt_clear  =  193 ;      //   brightness temperature for clear  (K) 
+SET  $rawbt_cloudy  =  194 ;     //   brightness temperature for cloudy (K)
+SET  $binary_snow_cover = 223;   //   binary snow cover (0: no snow / 1: presence of snow)
+SET  $salinity = 224;            //   ocean salinity (PSU)
+SET  $potential_temp = 225;      //   potential temperature (Kelvin)
+SET  $humidity_mixing_ratio = 226;    // humidity mixing ratio (kg/kg)
+SET  $airframe_icing = 227;           // airframe icing
+SET  $turbulence_index = 228;         // turbulence index
+SET  $lidar_aerosol_extinction = 236; // lidar aerosol extinction
+SET  $lidar_cloud_backscatter  = 237; // lidar cloud backscatter
+SET  $lidar_cloud_extinction   = 238; // lidar cloud extinction
+SET  $cloud_radar_reflectivity = 239; // cloud radar reflectivity
+
+// Additional variable numbers required by Met Office
+SET $pstation = 107;             // Station pressure (Pa)
+SET $pmsl = 108;                 // Mean sea-level pressure (Pa)
+SET $pstandard = 109;            // Standard level pressure (Pa)
+SET $vert_vv = 218;              // Vertical visibility (m)
+SET $max_wind_shear1 = 219;      // Wind shear above and below 1st maximum wind in sonde profile (s-1)
+SET $tot_zen_delay = 229;        // Total zenith delay (GPS)
+SET $tot_zen_delay_err = 230;    // Total zenith delay error (GPS)
+SET $cloud_top_temp = 231;       // Cloud top temperature (K)
+SET $rawsca = 233;               // Scaled radiance
+SET $cloud_top_press = 235;      // Cloud top pressure (Pa)
+SET $mean_freq = 241;            // GPSRO mean frequency
+SET $u_amb = 242;                // Ambiguous u-wind component (m/s)
+SET $v_amb = 243;                // Ambiguous v-wind component (m/s)
+SET $lwp = 244;                  // Liquid water path
+SET $tcwv = 245;                 // Total column water vapour
+SET $theta = 225;                // [alias to $potential_temp]
+SET $cloud_frac_clear = 247;     // Cloud clear fraction
+SET $rawbt_hirs = 248;           // Raw brightness temperature specific to HIRS (K)
+SET $rawbt_amsu = 249;           // Raw brightness temperature specific to AMSU (K)
+SET $rawbt_hirs20 = 250;         // Raw brightness temperature specific to HIRS (K)
+SET $sea_ice = 253;              // Sea ice fraction
+SET $cloud_frac_covered = 257;   // Cloud covered fraction
+SET $level_mixing_ratio = 258;   // [alias for $humidity_mixing_ratio]
+SET $radial_velocity = 259;      // Radial velocity from doppler radar
+SET $cloud_ice_water = 260;      // Cloud ice water
+SET $wind_gust = 261;            // Maximum wind gust (m/s)
+SET $mass_density = 262;         // Mass density
+SET $atmosphere_number = 263;    // SFERICS number of atmospheres
+SET $lightning = 265;            // Lightning strike observation (ATDNET)
+SET $level_cloud = 266;          // Cloud fraction (multi-level)
+SET $rawbt_amsr_89ghz = 267;     // Raw brightness temperature specific to AMSR 89GHz channels (K)
+SET $max_wind_shear2 = 268;      // Wind shear above and below 2nd maximum wind in sonde profile
+SET $lower_layer_p = 269;        // Pressure at bottom of layer SBUV (Pa)
+SET $upper_layer_p = 270;        // Pressure at top of later SBUV (Pa)
+SET $cloud_cover = 271;          // Total cloud cover
+SET $depth = 272;                // Depth (m)
+SET $ssh = 273;                  // Sea surface height (m)
+SET $rawbt_mwts = 274;           // Raw brightness temperature specific to MWTS (K)
+SET $rawbt_mwhs = 275;           // Raw brightness temperature specific to MWHS (K)
diff --git a/odb/src/ddl/vertco_type.h b/odb/src/ddl/vertco_type.h
new file mode 100644
index 0000000..3998e99
--- /dev/null
+++ b/odb/src/ddl/vertco_type.h
@@ -0,0 +1,17 @@
+// Vertical coordinate types (vertco_type at body) :
+
+SET $pressure = 1;            // vertco_reference_1 at body is a pressure (in Pa)
+SET $gpheight = 2;            // vertco_reference_1 at body is a geopotential height
+SET $tovs_cha = 3;            // vertco_reference_1 at body is a TOVS channel
+SET $scat_cha = 4;            // vertco_reference_1 at body is a Scatterometer channel
+SET $modlevno = 5;            // vertco_reference_1 at body is a model level number
+SET $imp_param = 6;           // vertco_reference_1 at body is an impact parameter
+SET $cha_number = 7;          // vertco_reference_1 at body is a channel number
+SET $cha_wavelength = 8;      // vertco_reference_1 at body is channel wavelength (in metres)
+SET $cha_frequency = 9;       // vertco_reference_1 at body is channel frequency (in Hz)
+SET $ocean_depth = 10;        // vertco_reference_1 at body is depth below surface (in metres)
+SET $derived_pressure = 11;   // vertco_reference_1 at body is a derived pressure (in Pa)
+SET $amb_wind_num = 12;       // vertco_reference_1 at body is an ambivalent wind number
+SET $cloud_top_pressure = 13; // vertco_reference_1 at body is a cloud top pressure (in Pa)
+SET $tangent_height = 14;     // vertco_reference_1 at body is a tangent height (metres) for SBUV
+SET $model_pressure = 15;     // vertco_reference_1 at body is a model level pressure (in Pa)
diff --git a/odb/src/ddl/xcheck.sql b/odb/src/ddl/xcheck.sql
new file mode 100644
index 0000000..e2ad312
--- /dev/null
+++ b/odb/src/ddl/xcheck.sql
@@ -0,0 +1,13 @@
+//
+//-- ODB/SQL file 'xcheck.sql'
+//
+//   Last updated:  18-May-2001
+//
+
+READONLY;
+
+CREATE VIEW xcheck AS
+     SELECT andate, antime, hdr.len, source, version
+       FROM desc
+    SORT BY andate, antime
+;
diff --git a/odb/src/extras/CMakeLists.txt b/odb/src/extras/CMakeLists.txt
new file mode 100644
index 0000000..cdc6333
--- /dev/null
+++ b/odb/src/extras/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(ec)
+add_subdirectory(mpi_serial)
+add_subdirectory(emos)
+add_subdirectory(ifsaux)
diff --git a/odb/src/extras/ec/CMakeLists.txt b/odb/src/extras/ec/CMakeLists.txt
new file mode 100644
index 0000000..5114fb1
--- /dev/null
+++ b/odb/src/extras/ec/CMakeLists.txt
@@ -0,0 +1,15 @@
+list(APPEND _odb_ec_sources
+
+    eclib.h
+    eclib_c.c
+    error.c
+    julian.h
+    julian_lib.c
+    myhdr.h
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    add_definitions(-D_ABI64)
+endif()
+
+ecbuild_add_library(TARGET odbec TYPE ${ODB_LIBS_TYPE} SOURCES ${_odb_ec_sources})
diff --git a/odb/src/extras/ec/eclib.h b/odb/src/extras/ec/eclib.h
new file mode 100644
index 0000000..459a148
--- /dev/null
+++ b/odb/src/extras/ec/eclib.h
@@ -0,0 +1,558 @@
+/*******************************
+ *  Prototypes
+ *******************************/ 
+
+
+/* ECLIB routines */
+
+void     CD2DATE(const _int32_t *const icd, _int32_t *const iy, _int32_t *const im, _int32_t *const id, _int32_t *const iret);
+void     YD2DATE(const _int32_t *const iyd, const _int32_t *const iy, _int32_t *const im, _int32_t *const id, _int32_t *const iret);
+_int32_t IDATE2CD(const _int32_t *const iy, const _int32_t *const im, const _int32_t *const id, _int32_t *const iret);
+_int32_t IDATE2YD(const _int32_t *const iy, const _int32_t *const im, const _int32_t *const id, _int32_t *const iret);
+_int32_t ICD2YMD(const _int32_t *const icd, _int32_t *const iret);
+_int32_t IYMD2CD(const _int32_t *const iymd, _int32_t *const iret);
+
+
+void     DAYDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, _int32_t *const days, _int32_t *const iret);
+void     HOURDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, _int32_t *const hours, _int32_t *const iret);
+void     MINDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const min1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, const _int32_t *const min2, _int32_t *const minutes, _int32_t *const iret);
+void     SECDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const min1, const _int32_t *const sec1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, const _int32_t *const min2, const _int32_t *const sec2, _int32_t *const seconds, _int32_t *const iret);
+
+
+void     HOURINCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const hours,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const iret);
+void     MININCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const min, const _int32_t *const minutes,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const new_min,  _int32_t *const iret);
+void     SECINCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const min, const _int32_t *const sec, const _int32_t *const seconds,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const new_min, _int32_t *const new_sec,  _int32_t *const iret);
+
+
+
+/*******************************
+ *  Functions
+ *******************************/
+
+
+void     
+DAYDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, _int32_t *const days, _int32_t *const iret)
+{
+	yyyymmdd_t        date1_str = {0,0,0}, date2_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+	*days = 0;
+        *iret = 0;
+
+	date1_str.year = *year1;
+	date1_str.month = *month1;
+	date1_str.day = *day1;
+
+       
+	date2_str.year = *year2;
+	date2_str.month = *month2;
+	date2_str.day = *day2;
+
+
+	if ( (exit_status = dateMinusDate(&date1_str, &date2_str, days)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* DAYDIFF */
+
+
+
+
+void     
+HOURDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, _int32_t *const hours, _int32_t *const iret)
+{
+	yyyymmdd_t        date1_str = {0,0,0}, date2_str = {0,0,0};
+	hhmmss_t          hms1_str = {0,0,0}, hms2_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+	*hours = 0;
+        *iret = 0;
+
+	date1_str.year = *year1;
+	date1_str.month = *month1;
+	date1_str.day = *day1;
+
+	hms1_str.hour = *hour1;
+
+       
+	date2_str.year = *year2;
+	date2_str.month = *month2;
+	date2_str.day = *day2;
+
+	hms2_str.hour = *hour2;
+
+
+	if ( (exit_status = hour_dateMinusDate(&date1_str, &hms1_str, &date2_str, &hms2_str, hours)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* HOURDIFF */
+
+
+
+
+void     
+MINDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const min1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, const _int32_t *const min2, _int32_t *const minutes, _int32_t *const iret)
+{
+	yyyymmdd_t        date1_str = {0,0,0}, date2_str = {0,0,0};
+	hhmmss_t          hms1_str = {0,0,0}, hms2_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+	*minutes = 0;
+        *iret = 0;
+
+	date1_str.year = *year1;
+	date1_str.month = *month1;
+	date1_str.day = *day1;
+
+	hms1_str.hour = *hour1;
+	hms1_str.min = *min1;
+
+       
+	date2_str.year = *year2;
+	date2_str.month = *month2;
+	date2_str.day = *day2;
+
+	hms2_str.hour = *hour2;
+	hms2_str.min = *min2;
+
+
+	if ( (exit_status = min_dateMinusDate(&date1_str, &hms1_str, &date2_str, &hms2_str, minutes)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* MINDIFF */
+
+
+
+
+void     
+SECDIFF(const _int32_t *const year1, const _int32_t *const month1, const _int32_t *const day1, const _int32_t *const hour1, const _int32_t *const min1, const _int32_t *const sec1, const _int32_t *const year2, const _int32_t *const month2, const _int32_t *const day2, const _int32_t *const hour2, const _int32_t *const min2, const _int32_t *const sec2, _int32_t *const seconds, _int32_t *const iret)
+{
+	yyyymmdd_t        date1_str = {0,0,0}, date2_str = {0,0,0};
+	hhmmss_t          hms1_str = {0,0,0}, hms2_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+	*seconds = 0;
+        *iret = 0;
+
+	date1_str.year = *year1;
+	date1_str.month = *month1;
+	date1_str.day = *day1;
+
+	hms1_str.hour = *hour1;
+	hms1_str.min = *min1;
+	hms1_str.sec = *sec1;
+	
+	date2_str.year = *year2;
+	date2_str.month = *month2;
+	date2_str.day = *day2;
+
+	hms2_str.hour = *hour2;
+	hms2_str.min = *min2;
+	hms2_str.sec = *sec2;
+
+
+	if ( (exit_status = sec_dateMinusDate(&date1_str, &hms1_str, &date2_str, &hms2_str, seconds)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* SECDIFF */
+
+
+
+
+
+
+void     
+DAYINCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const days, _int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const iret)
+{
+	yyyymmdd_t        date_str = {0,0,0}, new_date_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+        *iret = 0;
+
+
+	date_str.year = *year;
+	date_str.month = *month;
+	date_str.day = *day;
+
+
+	if ( (exit_status = addDays(&date_str, *days, &new_date_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+
+	*new_year = new_date_str.year;
+	*new_month = new_date_str.month;
+	*new_day = new_date_str.day;
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* DAYINCR */
+
+
+
+
+void     
+HOURINCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const hours,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const iret)
+{
+	yyyymmdd_t        date_str = {0,0,0}, new_date_str = {0,0,0};
+	hhmmss_t          hms_str = {0,0,0}, new_hms_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+        *iret = 0;
+
+
+	date_str.year = *year;
+	date_str.month = *month;
+	date_str.day = *day;
+
+	hms_str.hour = *hour;
+
+
+	if ( (exit_status = addHours(&date_str, &hms_str, *hours, &new_date_str, &new_hms_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+
+	*new_year = new_date_str.year;
+	*new_month = new_date_str.month;
+	*new_day = new_date_str.day;
+
+	*new_hour = new_hms_str.hour;
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* HOURINCR */
+
+
+
+void     
+MININCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const min, const _int32_t *const minutes,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const new_min,  _int32_t *const iret)
+{
+	yyyymmdd_t        date_str = {0,0,0}, new_date_str = {0,0,0};
+	hhmmss_t          hms_str = {0,0,0}, new_hms_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+        *iret = 0;
+
+
+	date_str.year = *year;
+	date_str.month = *month;
+	date_str.day = *day;
+
+	hms_str.hour = *hour;
+	hms_str.min = *min;
+
+
+	if ( (exit_status = addMinutes(&date_str, &hms_str, *minutes, &new_date_str, &new_hms_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+	*new_year = new_date_str.year;
+	*new_month = new_date_str.month;
+	*new_day = new_date_str.day;
+
+	*new_hour = new_hms_str.hour;
+	*new_min = new_hms_str.min;
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* MININCR */
+
+
+void     
+SECINCR(const _int32_t *const year, const _int32_t *const month, const _int32_t *const day, const _int32_t *const hour, const _int32_t *const min, const _int32_t *const sec, const _int32_t *const seconds,_int32_t *const new_year, _int32_t *const new_month, _int32_t *const new_day, _int32_t *const new_hour, _int32_t *const new_min, _int32_t *const new_sec,  _int32_t *const iret)
+{
+	yyyymmdd_t        date_str = {0,0,0}, new_date_str = {0,0,0};
+	hhmmss_t          hms_str = {0,0,0}, new_hms_str = {0,0,0};
+	exit_t            exit_status = 0;
+
+
+        /*
+	 *     Initialise variables
+	 */
+
+        *iret = 0;
+
+
+	date_str.year = *year;
+	date_str.month = *month;
+	date_str.day = *day;
+
+	hms_str.hour = *hour;
+	hms_str.min = *min;
+	hms_str.sec = *sec;
+
+
+	if ( (exit_status = addSeconds(&date_str, &hms_str, *seconds, &new_date_str, &new_hms_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;	
+	}
+
+	*new_year = new_date_str.year;
+	*new_month = new_date_str.month;
+	*new_day = new_date_str.day;
+
+	*new_hour = new_hms_str.hour;
+	*new_min = new_hms_str.min;
+	*new_sec = new_hms_str.sec;
+
+
+	*iret = EC_OK;   
+	return ;
+
+
+} /* SECINCR */
+
+
+
+
+void 
+CD2DATE(const _int32_t *const icd, _int32_t *const iy, _int32_t *const im, _int32_t *const id, _int32_t *const iret)
+{
+	yyyymmdd_t       date_str = {0,0,0};
+	exit_t           exit_status = 0;
+
+
+	*iret = 0;
+
+	if ( ( exit_status = centuryToDate(*icd, &date_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;
+	}	
+
+	*id = date_str.day;
+	*im = date_str.month;
+	*iy = date_str.year;
+
+
+	*iret = EC_OK;
+	return ;
+
+
+} /* CD2DATE */
+
+
+void 
+YD2DATE(const _int32_t *const iyd, const _int32_t *const iy, _int32_t *const im, _int32_t *const id, _int32_t *const iret)
+{
+	yyyymmdd_t       date_str = {0,0,0};
+	exit_t           exit_status = 0;
+
+
+	*iret = 0;
+
+	if ( ( exit_status = yeardayToDate(*iyd, *iy, &date_str)) != EC_OK) {
+		*iret = exit_status;
+		return ;
+	}
+
+	
+	*id = date_str.day;
+	*im = date_str.month;
+
+
+	*iret = EC_OK;
+	return ;
+
+
+} /* YD2DATE */
+
+
+
+_int32_t 
+IDATE2CD(const _int32_t *const iy, const _int32_t *const im, const _int32_t *const id, _int32_t *const iret)
+{
+	yyyymmdd_t       date_str = {0,0,0};
+	_int32_t  century = 0;
+	exit_t           exit_status = 0;
+
+
+	*iret = 0;
+
+	date_str.year = *iy;
+	date_str.month = *im;
+	date_str.day = *id;
+
+	if ( ( exit_status = dateToCentury( &date_str, &century)) != EC_OK) {
+		*iret = exit_status;
+		return (0);
+	}
+
+
+	*iret = EC_OK;   
+	return (century);
+
+
+} /* IDATE2CD */
+
+
+_int32_t 
+IDATE2YD(const _int32_t *const iy, const _int32_t *const im, const _int32_t *const id, _int32_t *const iret)
+{
+	yyyymmdd_t       date_str = {0,0,0};
+	_int32_t  yearday = 0;
+	exit_t           exit_status = 0;
+
+
+	*iret = 0;
+
+	date_str.year = *iy;
+	date_str.month = *im;
+	date_str.day = *id;
+
+	if ( ( exit_status = dateToYearday( &date_str, &yearday)) != EC_OK) {
+		*iret = exit_status;
+		return (0);
+	}
+
+	*iret = EC_OK;   
+	return (yearday);
+
+
+} /* IDATE2YD */
+
+
+_int32_t     
+ICD2YMD(const _int32_t *const icd, _int32_t *const iret)
+{
+
+	_int32_t         id, im, iy;
+	_int64_t         ymd = 0;
+	_int32_t  iymd = 0;
+
+	id = 0;
+	im = 0;
+	iy = 0;
+
+	*iret = 0;
+
+	CD2DATE(icd, &iy, &im, &id, iret);
+
+	if (  *iret != EC_OK) {
+		return (0);
+	}
+
+
+	ymd = iy * 10000 + im * 100 + id;
+
+	if ( ymd > LONG_MAX || ymd < LONG_MIN) {
+		err_msg("ICD2YMD: ymd = %lld", ymd);
+		err_msg("Exceeded the allowed range");
+		*iret = EC_RANGE;
+		return (0);
+	}
+
+	iymd = (_int32_t) ymd;
+
+	*iret = EC_OK;   
+	return (iymd);
+	       
+
+} /* ICD2YMD */
+
+
+
+_int32_t     
+IYMD2CD(const _int32_t *const iymd, _int32_t *const iret)
+{
+	_int32_t id, im, iy, ymd;
+	_int32_t icd = 0;
+
+	*iret = 0;
+
+	ymd = *iymd;
+
+	iy = ymd / 10000;
+	ymd %= 10000;
+
+	im = ymd / 100;
+	ymd %= 100;
+
+	id = ymd;
+	
+
+	icd = IDATE2CD(&iy, &im, &id, iret);
+
+	if (  *iret != EC_OK) {
+		return (0);
+	}
+	
+	return (icd);
+
+	       
+} /* IYMD2CD */
diff --git a/odb/src/extras/ec/eclib_c.c b/odb/src/extras/ec/eclib_c.c
new file mode 100644
index 0000000..05d39c4
--- /dev/null
+++ b/odb/src/extras/ec/eclib_c.c
@@ -0,0 +1,30 @@
+#define    CD2DATE                      cd2date
+#define    YD2DATE                      yd2date
+#define    IDATE2CD                     idate2cd
+#define    IDATE2YD                     idate2yd
+#define    ICD2YMD                      icd2ymd
+#define    IYMD2CD                      iymd2cd
+
+
+#define    DAYDIFF                      daydiff
+#define    HOURDIFF                     hourdiff
+#define    MINDIFF                      mindiff
+#define    SECDIFF                      secdiff
+
+#define    DAYINCR                      dayincr
+#define    HOURINCR                     hourincr
+#define    MININCR                      minincr
+#define    SECINCR                      secincr
+
+
+
+#include "julian.h"
+#include "julian_lib.c"
+
+
+/*******************************
+ *  Functions
+ *******************************/
+
+
+#include "eclib.h"
diff --git a/odb/src/extras/ec/error.c b/odb/src/extras/ec/error.c
new file mode 100644
index 0000000..991292c
--- /dev/null
+++ b/odb/src/extras/ec/error.c
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <errno.h>		/* for definition of errno */
+#include <stdarg.h>		/* ANSI C header file */
+#include <signal.h>
+
+/* #include <pfmt.h> */
+
+#include	"myhdr.h"
+
+static void	err_doit(int, const char *, va_list);
+static void	err_ret(const char *fmt, ...);
+static void	err_sys(const char *fmt, ...);
+static void	err_dump(const char *fmt, ...);
+static void	err_msg(const char *fmt, ...);
+static void	err_quit(const char *fmt, ...);
+
+/*static char	*pname = NULL;*/		/* caller can set this from argv[0] */
+
+/* Nonfatal error related to a system call.
+ * Print a message and return. */
+
+static void
+err_ret(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, fmt, ap);
+	va_end(ap);
+	return;
+}
+
+/* Fatal error related to a system call.
+ * Print a message and terminate. */
+
+static void
+err_sys(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+/* Fatal error related to a system call.
+ * Print a message, dump core, and terminate. */
+
+static void
+err_dump(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, fmt, ap);
+	va_end(ap);
+	/* abort(); */		/* dump core and terminate */
+	raise(SIGABRT);         /* Will be caught (better) by Dr.Hook ? */
+	exit(1);		/* shouldn't get here */
+}
+
+/* Nonfatal error unrelated to a system call.
+ * Print a message and return. */
+
+static void
+err_msg(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(0, fmt, ap);
+	va_end(ap);
+	return;
+}
+
+/* Fatal error unrelated to a system call.
+ * Print a message and terminate. */
+
+static void
+err_quit(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(0, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+/* Print a message and return to caller.
+ * Caller specifies "errnoflag". */
+
+/*
+static void
+myerr_doit(int errnoflag, const char *fmt, va_list ap)
+{
+	pfmt(stderr, MM_STD, fmt, ap);
+
+}
+*/
+
+static void
+err_doit(int errnoflag, const char *fmt, va_list ap)
+{
+	int		errno_save;
+	char	buf[MAXLINE];
+
+	errno_save = errno;		/* value caller might want printed */
+	(void) vsprintf(buf, fmt, ap);
+	if (errnoflag)
+		(void) sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
+	(void) strcat(buf, "\n");
+	(void) fflush(stdout);		/* in case stdout and stderr are the same */
+	(void) fputs(buf, stderr);
+	(void) fflush(stderr);		/* SunOS 4.1.* doesn't grok NULL argument */
+	return;
+}
+
diff --git a/odb/src/extras/ec/julian.h b/odb/src/extras/ec/julian.h
new file mode 100644
index 0000000..1b53a77
--- /dev/null
+++ b/odb/src/extras/ec/julian.h
@@ -0,0 +1,219 @@
+/*
+
+$Header: /home/us/usu/dates/my/newdate/RCS/julian.h,v 1.1 1998/03/26 17:49:42 usu Exp usu $
+
+
+$Revision: 1.1 $
+$Date: 1998/03/26 17:49:42 $
+$Source: /home/us/usu/dates/my/newdate/RCS/julian.h,v $
+$Author: usu $
+$Locker: usu $
+
+
+$Log: julian.h,v $
+ * Revision 1.1  1998/03/26  17:49:42  usu
+ * Initial revision
+ *
+
+
+Author: Dr. Umberto Modigliani, User Support.
+
+*/
+
+#ifndef __julian_H__
+#define __julian_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#if !defined(__alpha) && !defined(linux) && !defined(_AIX43) && !defined(CYGWIN)
+#include <pfmt.h>
+#endif
+#include <limits.h>
+
+#include "myhdr.h"
+
+#if defined(linux)
+#include <stdint.h>
+#endif
+
+
+
+/*******************************
+ * Macros
+ *******************************/
+
+
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+
+#ifdef _LANGUAGE_C_PLUS_PLUS
+#define INLINE inline
+#else
+#define INLINE 
+#endif
+
+
+
+/*******************************
+ * Types
+ *******************************/
+
+
+#if defined(POINTER_64) || defined(_ABI64) || defined(__uxpch__) || defined(__alpha)
+	typedef long int _int64_t;
+#else
+	typedef long long int _int64_t;
+#endif
+
+
+#if defined(POINTER_64) || defined(_ABI64) || defined(__uxpch__) || defined(__alpha)
+	typedef int _int32_t;
+#else
+	typedef long int _int32_t;
+#endif
+
+typedef short int _int16_t;
+
+typedef _int32_t exit_t;
+
+/*
+typedef unsigned long int _u_int32_t;
+typedef unsigned short int _uint16_t;
+*/
+
+
+
+typedef struct iso_date_str {
+	_int32_t julian;
+	_int32_t seconds;
+} mydate_t;
+
+
+
+typedef struct  date_str {  
+        _int32_t     day;
+        _int32_t     month;
+        _int32_t     year;
+} yyyymmdd_t;
+
+
+typedef struct  hms_str {  
+        _int32_t     hour;
+        _int32_t     min;
+        _int32_t     sec;
+} hhmmss_t;
+
+
+
+
+/*******************************
+ * Externals
+ *******************************/
+
+/* None */
+
+
+
+/*******************************
+ *  Prototypes
+ *******************************/ 
+
+/* 
+ *
+ * Internal routines: set static
+ *
+ */
+
+
+static exit_t   addDays(const yyyymmdd_t *const date_ptr, const _int32_t days, yyyymmdd_t *const new_date_ptr);
+static exit_t   addHours(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t hours,  yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr);
+static exit_t   addMinutes(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t minutes, yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr);
+static exit_t   addSeconds(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t seconds, yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr);
+
+static exit_t   dateMinusDate(const yyyymmdd_t *const date1_ptr, const yyyymmdd_t *const date2_ptr, _int32_t *const days_ptr); 
+static exit_t   hour_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const hours_ptr);
+static exit_t   min_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const minutes_ptr);
+static exit_t   sec_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const seconds_ptr);
+
+
+
+static exit_t   is_hms(const hhmmss_t *const hms_ptr);
+static exit_t   is_date(const yyyymmdd_t *const date_ptr);
+
+
+
+static exit_t _addHours(const mydate_t *const fulldate_ptr, const _int32_t hours,  mydate_t *const new_fulldate_ptr);
+static exit_t _addMinutes(const mydate_t *const fulldate_ptr, const _int32_t minutes, mydate_t *const new_fulldate_ptr);
+static exit_t _addSeconds(const mydate_t *const fulldate_ptr, const _int32_t seconds, mydate_t *const new_fulldate_ptr);
+
+
+
+static exit_t   julianToDate(const _int32_t julian, yyyymmdd_t *const date_ptr);
+static exit_t   dateToJulian(const yyyymmdd_t *const date_ptr, _int32_t *const julian);
+static exit_t   secondsToHms(const _int32_t seconds, hhmmss_t *const hms_ptr);
+static exit_t   hmsToSeconds(const hhmmss_t *const hms_ptr, _int32_t *const seconds);
+static exit_t   centuryToDate(const _int32_t century, yyyymmdd_t *date_ptr);
+static exit_t   dateToCentury(const yyyymmdd_t *const date_ptr, _int32_t *const century_ptr);
+static exit_t   dateToYearday(const yyyymmdd_t *const date_ptr, _int32_t *const yearday_ptr);
+static exit_t   yeardayToDate(const _int32_t yearday, const _int32_t year, yyyymmdd_t *date_ptr);
+
+
+
+
+
+/*******************************
+ *   Constants
+ *******************************/
+ 
+
+static const _int16_t month_len[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+
+
+
+static const _int32_t MJDSHIFT = 0;
+static const _int32_t CENTURYSHIFT = 2415021;
+
+/*
+static const _int32_t MJDSHIFT = 2400000;
+static const _int32_t CENTURYSHIFT = 15021;
+*/
+
+
+
+static const _int64_t   JULIAN_MIN = 0LL;
+
+
+static const _int32_t   EC_OK       = 0;
+static const _int32_t   EC_FALSE    = -1;
+
+static const _int32_t   EC_WRGOPT   = -2;
+static const _int32_t   EC_WRGPAR   = -3;
+static const _int32_t   EC_WRGLEN   = -4;
+
+static const _int32_t   EC_DATELEN  = -5;
+static const _int32_t   EC_DATEFMT  = -6;
+static const _int32_t   EC_DATEINV  = -7;
+static const _int32_t   EC_TIMEINV  = -8;
+static const _int32_t   EC_NAN      = -9;
+static const _int32_t   EC_RANGE    = -10;
+
+
+static const _int32_t   YEAR_MIN    = 0;
+static const _int32_t   YEAR_MAX    = 9999;
+
+static const _int32_t   SEC_MIN     = 60;
+static const _int32_t   SEC_HOUR    = 3600;
+static const _int32_t   SEC_DAY     = 86400;
+static const _int32_t   MIN_HOUR    = 60;
+static const _int32_t   MIN_DAY     = 1440;
+static const _int32_t   HOUR_DAY    = 24;
+
+
+
+
+#endif /* __julian_H__ */
diff --git a/odb/src/extras/ec/julian_lib.c b/odb/src/extras/ec/julian_lib.c
new file mode 100644
index 0000000..be589d3
--- /dev/null
+++ b/odb/src/extras/ec/julian_lib.c
@@ -0,0 +1,794 @@
+#include "julian.h"
+#include "error.c"
+
+
+/*******************************
+ *  Functions
+ *******************************/
+
+
+static exit_t 
+dateMinusDate(const yyyymmdd_t *const date1_ptr, const yyyymmdd_t *const date2_ptr, _int32_t *const days_ptr)
+{
+	_int32_t         julian1 = 0, julian2 = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date1_ptr, &julian1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = dateToJulian(date2_ptr, &julian2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	*days_ptr = (julian1 - julian2);
+
+	return (EC_OK);
+
+
+} /* dateMinusDate */
+
+
+
+static exit_t 
+hour_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const hours_ptr)
+{
+	_int32_t         julian1 = 0, julian2 = 0;
+	_int32_t         second1 = 0, second2 = 0;
+	_int64_t         hours = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date1_ptr, &julian1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = dateToJulian(date2_ptr, &julian2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms1_ptr, &second1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms2_ptr, &second2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	hours = (julian1 - julian2) * (_int64_t) HOUR_DAY + (second1 - second2) / SEC_HOUR ;
+
+	if ( hours > LONG_MAX || hours < LONG_MIN) {
+#if defined(_ABI64)
+		err_msg("hour_dateMinusDate: hours = %ld", hours);
+#else
+		err_msg("hour_dateMinusDate: hours = %lld", hours);
+#endif
+		err_msg("Exceeded the allowed range");	
+		return (EC_RANGE);
+	}
+
+	*hours_ptr = hours;
+
+	return (EC_OK);
+
+
+} /* hour_dateMinusDate */
+
+
+
+static exit_t 
+min_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const minutes_ptr)
+{
+	_int32_t         julian1 = 0, julian2 = 0;
+	_int32_t         second1 = 0, second2 = 0;
+	_int64_t         minutes = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date1_ptr, &julian1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = dateToJulian(date2_ptr, &julian2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms1_ptr, &second1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms2_ptr, &second2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	minutes = (julian1 - julian2) * (_int64_t) MIN_DAY + (second1 - second2) / SEC_MIN ;
+
+	if ( minutes > LONG_MAX || minutes < LONG_MIN) {
+#if defined(_ABI64)
+		err_msg("min_dateMinusDate: minutes = %ld", minutes);
+#else
+		err_msg("min_dateMinusDate: minutes = %lld", minutes);
+#endif
+		err_msg("Exceeded the allowed range");
+
+		return (EC_RANGE);
+	}
+
+	*minutes_ptr = minutes;
+
+	return (EC_OK);
+
+
+} /* min_dateMinusDate */
+
+
+
+static exit_t 
+sec_dateMinusDate(const yyyymmdd_t *const date1_ptr, const hhmmss_t *const hms1_ptr, const yyyymmdd_t *const date2_ptr, const hhmmss_t *const hms2_ptr, _int32_t *const seconds_ptr)
+{
+	_int32_t         julian1 = 0, julian2 = 0;
+	_int32_t         second1 = 0, second2 = 0;
+	_int64_t         seconds = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date1_ptr, &julian1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = dateToJulian(date2_ptr, &julian2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms1_ptr, &second1) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms2_ptr, &second2) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	seconds = (julian1 - julian2) * (_int64_t) SEC_DAY + (second1 - second2);
+
+	if ( seconds > LONG_MAX || seconds < LONG_MIN) {
+#if defined(_ABI64)
+		err_msg("sec_dateMinusDate: seconds = %lld", seconds);
+#else
+		err_msg("sec_dateMinusDate: seconds = %lld", seconds);
+#endif
+		err_msg("Exceeded the allowed range");	
+		return (EC_RANGE);
+	}
+
+	*seconds_ptr = seconds;
+
+	return (EC_OK);
+
+
+} /* sec_dateMinusDate */
+
+
+
+static exit_t 
+centuryToDate(const _int32_t century, yyyymmdd_t *date_ptr)
+{
+	_int32_t         julian = 0;
+	exit_t           exit_status = 0;
+
+
+	julian = century + CENTURYSHIFT - 1;
+
+	if ( ( exit_status = julianToDate(julian, date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* centuryToDate */
+
+
+
+INLINE static exit_t 
+dateToCentury(const yyyymmdd_t *const date_ptr, _int32_t *const century_ptr)
+{
+	_int32_t         century = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( is_date(date_ptr) != EC_OK ) {
+#if defined(_ABI64)
+		err_msg("Date incorrect (%04d%02d%02d)", date_ptr->year, date_ptr->month, date_ptr->day);
+#else
+		err_msg("Date incorrect (%04ld%02ld%02ld)", date_ptr->year, date_ptr->month, date_ptr->day);
+#endif
+		return (EC_DATEINV);
+	}
+
+	if ( ( exit_status = dateToJulian(date_ptr, &century) ) != EC_OK) {
+		return (exit_status);
+	}	
+
+	*century_ptr = century - CENTURYSHIFT + 1;
+
+	return (EC_OK);
+
+
+} /* dateToCentury */
+
+
+
+static exit_t 
+dateToYearday(const yyyymmdd_t *const date_ptr, _int32_t *const yearday_ptr)
+{
+	_int32_t         century = 0, year = 0;
+	yyyymmdd_t       year_date = {0,0,0};
+	exit_t           exit_status = 0;
+
+
+	
+	if ( is_date(date_ptr) != EC_OK ) {
+#if defined(_ABI64)
+		err_msg("Date incorrect (%04d%02d%02d)", date_ptr->year, date_ptr->month, date_ptr->day);
+#else
+		err_msg("Date incorrect (%04ld%02ld%02ld)", date_ptr->year, date_ptr->month, date_ptr->day);
+#endif
+		return (EC_DATEINV);
+	}
+
+	if ( ( exit_status = dateToJulian(date_ptr, &century) ) != EC_OK) {
+		return (exit_status);
+	}	
+
+	year_date.year = date_ptr->year;
+	year_date.month = 1;
+	year_date.day = 1;
+
+	if ( ( exit_status = dateToJulian(&year_date, &year) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	*yearday_ptr = century - year  + 1;
+
+	return (EC_OK);
+
+
+} /* dateToYearday */
+
+
+
+static exit_t 
+yeardayToDate(const _int32_t yearday, const _int32_t year, yyyymmdd_t *date_ptr)
+{
+	_int32_t         shift = 0, julian = 0;
+	yyyymmdd_t       year_date = {0,0,0};
+	exit_t           exit_status = 0;
+
+
+	year_date.year = year;
+	year_date.month = 1;
+	year_date.day = 1;
+
+	if ( is_date(&year_date) != EC_OK ) {
+#if defined(_ABI64)
+		err_msg("Date incorrect (%04d%02d%02d)", year_date.year, year_date.month, year_date.day);
+#else
+		err_msg("Date incorrect (%04ld%02ld%02ld)", year_date.year, year_date.month, year_date.day);
+#endif
+		return (EC_DATEINV);
+	}
+
+	if ( ( exit_status = dateToJulian(&year_date, &shift) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	julian = yearday + shift - 1;
+
+	if ( ( exit_status = julianToDate(julian, date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* yeardayToDate */
+
+
+
+static exit_t
+addDays(const yyyymmdd_t *const date_ptr, const _int32_t days, yyyymmdd_t *const new_date_ptr)
+{
+	_int64_t         julian = 0;
+	_int32_t         jul = 0;
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date_ptr, &jul) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	julian = jul;
+	julian += days;
+
+	if ( julian > LONG_MAX || julian < LONG_MIN) {
+#if defined(_ABI64)
+		err_msg("addDays: julian = %ld", julian);
+#else
+		err_msg("addDays: julian = %lld", julian);
+#endif
+		err_msg("Exceeded the allowed range");
+		return (EC_RANGE);
+	}
+
+	jul = (_int32_t) julian;
+
+	if ( ( exit_status = julianToDate(jul, new_date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* addDays */
+
+
+
+
+static exit_t 
+addHours(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t hours,  yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr) 
+{
+
+	mydate_t         fulldate_str = {0,0}, new_fulldate_str = {0,0};
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date_ptr, &fulldate_str.julian) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms_ptr, &fulldate_str.seconds) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = _addHours(&fulldate_str, hours, &new_fulldate_str) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = julianToDate(new_fulldate_str.julian, new_date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = secondsToHms(new_fulldate_str.seconds, new_hms_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* addHours */
+
+
+
+static exit_t 
+addMinutes(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t minutes,  yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr) 
+{
+
+	mydate_t         fulldate_str = {0,0}, new_fulldate_str = {0,0};
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date_ptr, &fulldate_str.julian) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms_ptr, &fulldate_str.seconds) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = _addMinutes(&fulldate_str, minutes, &new_fulldate_str) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = julianToDate(new_fulldate_str.julian, new_date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = secondsToHms(new_fulldate_str.seconds, new_hms_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* addMinutes */
+
+
+
+static exit_t 
+addSeconds(const yyyymmdd_t *const date_ptr, const hhmmss_t *const hms_ptr, const _int32_t seconds,  yyyymmdd_t *const new_date_ptr, hhmmss_t *const new_hms_ptr) 
+{
+
+	mydate_t         fulldate_str = {0,0}, new_fulldate_str = {0,0};
+	exit_t           exit_status = 0;
+
+
+	if ( ( exit_status = dateToJulian(date_ptr, &fulldate_str.julian) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = hmsToSeconds(hms_ptr, &fulldate_str.seconds) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	if ( ( exit_status = _addSeconds(&fulldate_str, seconds, &new_fulldate_str) ) != EC_OK) {
+		return (exit_status);
+	}
+
+
+	if ( ( exit_status = julianToDate(new_fulldate_str.julian, new_date_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+
+	if ( ( exit_status = secondsToHms(new_fulldate_str.seconds, new_hms_ptr) ) != EC_OK) {
+		return (exit_status);
+	}
+
+	return (EC_OK);
+
+
+} /* addSeconds */
+
+
+
+static exit_t
+_addHours(const mydate_t *const fulldate_ptr, const _int32_t hours, mydate_t *const new_fulldate_ptr)
+{
+
+	_int32_t         days = 0;
+	_int32_t         new_hours = 0;
+	_int32_t         new_seconds = 0;
+
+
+	new_hours = hours;
+
+	days = new_hours / HOUR_DAY;
+
+	new_fulldate_ptr->julian = fulldate_ptr->julian + days;
+	new_hours %= HOUR_DAY;
+
+	new_seconds = new_hours * SEC_HOUR;
+
+	new_fulldate_ptr->seconds = fulldate_ptr->seconds + new_seconds;
+
+	if ( new_fulldate_ptr->seconds < 0) {
+		new_fulldate_ptr->julian --;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds + SEC_DAY;
+	}
+	
+	if ( new_fulldate_ptr->seconds >= SEC_DAY) {
+		new_fulldate_ptr->julian ++;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds - SEC_DAY;
+	}
+
+	return (EC_OK);
+       
+
+} /* _addHours */
+
+
+
+
+static exit_t
+_addMinutes(const mydate_t *const fulldate_ptr, const _int32_t minutes, mydate_t *const new_fulldate_ptr)
+{
+
+	_int32_t        days = 0;
+	_int32_t        new_minutes = 0;
+	_int32_t        new_seconds = 0;
+
+
+	new_minutes = minutes;
+
+	days = new_minutes / MIN_DAY;
+
+	new_fulldate_ptr->julian = fulldate_ptr->julian + days;
+	new_minutes %= MIN_DAY;
+
+	new_seconds = new_minutes * SEC_MIN;
+
+	new_fulldate_ptr->seconds = fulldate_ptr->seconds + new_seconds;
+
+	if ( new_fulldate_ptr->seconds < 0) {
+		new_fulldate_ptr->julian --;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds + SEC_DAY;
+	}
+	
+
+	if ( new_fulldate_ptr->seconds >= SEC_DAY) {
+		new_fulldate_ptr->julian ++;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds - SEC_DAY;
+	}
+
+	return (EC_OK);
+       
+
+} /* _addMinutes */
+
+
+
+static exit_t
+_addSeconds(const mydate_t *const fulldate_ptr, const _int32_t seconds, mydate_t *const new_fulldate_ptr)
+{
+
+	_int32_t         days = 0;
+	_int32_t         new_seconds = 0;
+
+
+	new_seconds = seconds;
+	days = new_seconds / SEC_DAY;
+
+	new_fulldate_ptr->julian = fulldate_ptr->julian + (_int32_t) days;
+	new_seconds %= SEC_DAY;
+
+	new_fulldate_ptr->seconds = fulldate_ptr->seconds + (_int32_t) new_seconds;
+
+	if ( new_fulldate_ptr->seconds < 0) {
+		new_fulldate_ptr->julian --;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds + SEC_DAY;
+	} else if ( new_fulldate_ptr->seconds >= SEC_DAY) {
+		new_fulldate_ptr->julian ++;
+		new_fulldate_ptr->seconds = new_fulldate_ptr->seconds - SEC_DAY;
+	}
+
+	return (EC_OK);
+       
+
+} /* _addSeconds */
+
+
+
+
+
+INLINE static exit_t
+hmsToSeconds(const hhmmss_t *const hms_ptr, _int32_t *const seconds)
+{
+
+	if ( is_hms(hms_ptr) != EC_OK ) {
+#if defined(_ABI64)
+		err_msg("Time incorrect (%02d%02d%02d)", hms_ptr->hour, hms_ptr->min, hms_ptr->sec);
+#else
+		err_msg("Time incorrect (%02ld%02ld%02ld)", hms_ptr->hour, hms_ptr->min, hms_ptr->sec);
+#endif
+		return (EC_TIMEINV);
+	}  
+
+	*seconds = SEC_HOUR * hms_ptr->hour + SEC_MIN * hms_ptr->min + hms_ptr->sec;
+
+	return (EC_OK);
+
+
+} /* hmsToSeconds */
+
+
+
+static exit_t
+secondsToHms(const _int32_t seconds, hhmmss_t *const hms_ptr)
+{
+	_int32_t        local_sec = 0;
+
+
+	if ( seconds < 0 || seconds > SEC_DAY)
+		return (EC_FALSE);
+		
+	local_sec = seconds;
+
+	hms_ptr->hour =  local_sec / SEC_HOUR;
+	local_sec %= SEC_HOUR;
+	hms_ptr->min  =  local_sec / MIN_HOUR;
+	local_sec %= MIN_HOUR;
+	hms_ptr->sec = local_sec;
+
+	return (EC_OK);
+
+	
+} /* secondsToHms */
+
+
+
+static exit_t
+julianToDate(const _int32_t  julian, yyyymmdd_t *const date_ptr)
+{
+	_int64_t        l = 0, n = 0, i = 0, j = 0;
+	_int64_t        jdate = 0;
+	_int64_t        day = 0;
+	_int64_t        month = 0;
+	_int64_t        year = 0;
+
+
+      /*
+	 * Modified Julian date
+	 */
+	jdate = julian + MJDSHIFT;
+#if defined(linux)
+	if ( (_int32_t) jdate < (_int32_t) JULIAN_MIN ) {
+#else
+	if ( jdate < JULIAN_MIN ) {
+#endif
+
+#if defined(_ABI64)
+		err_msg("Julian = %ld", jdate);
+		err_msg("Julian less than %ld", JULIAN_MIN);
+#else
+		err_msg("Julian = %lld", jdate);
+		err_msg("Julian less than %lld", JULIAN_MIN);
+#endif
+		return (EC_FALSE);
+	}
+
+        /* 
+	   l = julian_day + 68569
+	   n = ( 4 * l ) / 146097
+	   l = l - ( 146097 * n + 3 ) / 4
+	   i = ( 4000 * ( l + 1 ) ) / 1461001     (that's 1,461,001)
+	   l = l - ( 1461 * i ) / 4 + 31
+	   j = ( 80 * l ) / 2447
+	   d = l - ( 2447 * j ) / 80
+	   l = j / 11
+	   m = j + 2 - ( 12 * l )
+	   y = 100 * ( n - 49 ) + i + l      
+
+	*/
+
+	l = jdate + 68569;
+
+	n = ( 4 * l ) / 146097;
+
+	l = l - ( 146097 * n + 3 ) / 4;
+
+	i = ( 4000 * ( l + 1 ) ) / 1461001;  
+
+	l = l - ( 1461 * i ) / 4 + 31;
+
+	j = ( 80 * l ) / 2447;
+
+	day = l - ( 2447 * j ) / 80;
+
+	l = j / 11;
+
+	month = j + 2 - ( 12 * l );
+
+	year = 100 * ( n - 49 ) + i + l;
+
+	if ( year > LONG_MAX || year < LONG_MIN) {
+#if defined(_ABI64)
+		err_msg("julianToDate: Year = %ld", year);
+#else
+		err_msg("julianToDate: Year = %lld", year);
+#endif
+		err_msg("Exceeded the allowed range");
+		return (EC_RANGE);
+	}
+
+	date_ptr->day = day;
+	date_ptr->month = month;
+	date_ptr->year = year;
+
+	return (EC_OK);
+
+
+} /* julianToDate */
+
+
+
+
+static exit_t
+dateToJulian(const yyyymmdd_t *const date_ptr, _int32_t *const julian)
+{
+
+	_int32_t       m1 = 0, m2 = 0, a = 0, b = 0, c = 0;
+/*	_int64_t       jul = 0;*/
+
+	if ( is_date(date_ptr) != EC_OK ) {
+#if defined(_ABI64)
+		err_msg("Date incorrect (%04d%02d%02d)", date_ptr->year, date_ptr->month, date_ptr->day);
+#else
+		err_msg("Date incorrect (%04ld%02ld%02ld)", date_ptr->year, date_ptr->month, date_ptr->day);
+#endif
+		return (EC_DATEINV);
+	}  
+
+
+        /*
+	 * Compute the Julian Day number applying the following formula
+
+	 julian_day = ( 1461 * ( y + 4800 + ( m - 14 ) / 12 ) ) / 4 +
+	              ( 367 * ( m - 2 - 12 * ( ( m - 14 ) / 12 ) ) ) / 12 -
+                      ( 3 * ( ( y + 4900 + ( m - 14 ) / 12 ) / 100 ) ) / 4 +
+                        d - 32075
+	*/
+
+	m1 = (date_ptr->month - 14)/12;
+
+	a = (1461 * (date_ptr->year + 4800 + m1))/4;
+
+	b = (367 * (date_ptr->month - 2 - (12 * m1)))/12;
+
+	m2 = (date_ptr->year + 4900 + m1)/100;
+
+	c = (3 * (m2))/4;
+
+/*
+	jul = a + b - c  + date_ptr->day - 32075 - MJDSHIFT;
+
+	if ( jul > LONG_MAX || jul < LONG_MIN) {
+		err_msg("dateToJulian: Julian = %lld", jul);
+		err_msg("Exceeded the allowed range");
+		return (EC_RANGE);
+	}
+	*/
+
+	*julian = a + b - c  + date_ptr->day - 32075 - MJDSHIFT;
+
+	return (EC_OK);
+     
+
+} /* dateToJulian */
+
+
+
+static exit_t
+is_hms(const hhmmss_t *const hms_ptr)
+{
+
+	if ( hms_ptr->hour < 0 || hms_ptr->hour > HOUR_DAY - 1 ||
+	     hms_ptr->min  < 0 || hms_ptr->min  > MIN_HOUR - 1 ||
+	     hms_ptr->sec  < 0 || hms_ptr->sec  > SEC_MIN - 1 ) 
+		return (EC_TIMEINV);
+	else
+		return (EC_OK);
+
+
+} /* is_hms */
+
+
+
+static exit_t
+is_date(const yyyymmdd_t *const date_ptr)
+{
+
+	if ( date_ptr->year < YEAR_MIN || date_ptr->year > YEAR_MAX) {
+#if defined(_ABI64)
+		err_msg("Year %d out of allowed range", date_ptr->year);
+#else
+
+#endif
+		return(EC_RANGE);
+	}
+
+	if ( date_ptr->month  < 1  || 
+	     date_ptr->month  > 12 ||
+	     date_ptr->day    < 1  || 
+	     date_ptr->day    >  (_int32_t) (date_ptr->month==2?(leap(date_ptr->year)?29:28):month_len[date_ptr->month - 1]) ) {
+		return (EC_DATEINV);
+	} else {
+		return (EC_OK);
+        }
+
+
+} /* is_date */
+
+
+
+
+/*
+	err_msg("Date1 (%04ld%02ld%02ld%02ld%02ld%02ld)", date1_ptr->year, date1_ptr->month, date1_ptr->day, hms1_ptr->hour, hms1_ptr->min, hms1_ptr->sec);
+
+err_msg("Date2 (%04ld%02ld%02ld%02ld%02ld%02ld)", date2_ptr->year, date2_ptr->month, date2_ptr->day, hms2_ptr->hour, hms2_ptr->min, hms2_ptr->sec);
+*/
+
+
+/*
+	err_msg("is_date (%04ld%02ld%02ld)", date_ptr->year, date_ptr->month, date_ptr->day);
+	*/
diff --git a/odb/src/extras/ec/myhdr.h b/odb/src/extras/ec/myhdr.h
new file mode 100644
index 0000000..2f5aa38
--- /dev/null
+++ b/odb/src/extras/ec/myhdr.h
@@ -0,0 +1,46 @@
+/* My own header, to be included *after* all standard system headers */
+
+#ifndef	__myhdr_h
+#define	__myhdr_h
+
+#include	<sys/types.h>	/* required for some of our prototypes */
+#include	<stdio.h>		/* for convenience */
+#include	<stdlib.h>		/* for convenience */
+#include	<string.h>		/* for convenience */
+#include	<unistd.h>		/* for convenience */
+
+#define	MAXLINE	4096			/* max line length */
+
+#define	FILE_MODE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
+					/* default file access permissions for new files */
+#define	DIR_MODE	(FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
+					/* default permissions for new directories */
+
+typedef	void	Sigfunc(int);	/* for signal handlers */
+
+					/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
+#if	defined(SIG_IGN) && !defined(SIG_ERR)
+#define	SIG_ERR	((Sigfunc *)-1)
+#endif
+
+#define	min(a,b)	((a) < (b) ? (a) : (b))
+#define	max(a,b)	((a) > (b) ? (a) : (b))
+
+					/* prototypes for our own functions */
+
+
+Sigfunc	*signal_intr(int, Sigfunc *);  /* {Prog signal_intr_function} */
+
+
+
+
+
+static void	err_dump(const char *, ...);	
+static void	err_msg(const char *, ...);
+static void	err_quit(const char *, ...);
+static void	err_ret(const char *, ...);
+static void	err_sys(const char *, ...);
+
+
+
+#endif	/* __myhdr_h */
diff --git a/odb/src/extras/emos/CMakeLists.txt b/odb/src/extras/emos/CMakeLists.txt
new file mode 100644
index 0000000..2be7690
--- /dev/null
+++ b/odb/src/extras/emos/CMakeLists.txt
@@ -0,0 +1,22 @@
+list(APPEND _odb_emos_sources
+
+  bufrgrib.h
+  fileRead.h
+  fort2c.h
+  pbio.c
+  readprod.c
+  sizeRoutines.h
+)
+
+ecbuild_add_library(TARGET odbemos
+  TYPE ${ODB_LIBS_TYPE}
+  DEFINITIONS INTEGER_IS_INT
+  PRIVATE_INCLUDES ${ODB_INCLUDE_DIRS}
+  SOURCES ${_odb_emos_sources}
+  CONDITION NOT HAVE_ODB_EMOS)
+
+if(NOT HAVE_ODB_EMOS)
+  set(_ODB_EMOS_LIBS odbemos PARENT_SCOPE)
+else()
+  set(_ODB_EMOS_LIBS ${LIBEMOS_LIBRARIES} PARENT_SCOPE)
+endif()
diff --git a/odb/src/extras/emos/bufrgrib.h b/odb/src/extras/emos/bufrgrib.h
new file mode 100644
index 0000000..4432dd3
--- /dev/null
+++ b/odb/src/extras/emos/bufrgrib.h
@@ -0,0 +1,23 @@
+#ifndef BUFRGRIB_H
+#define BUFRGRIB_H
+/*
+  bufrgrib.h
+*/
+#include <stdio.h>
+#include <string.h>
+
+/*	defines for BUFR functions */ 
+#define ARRSIZE 100
+#define TRUE 1
+#define FALSE 0
+#define BOOL int
+#define BOOLEAN int
+
+#ifdef VAX
+#define off_t char *
+#include <types.h>
+#include <file.h>
+#endif
+
+#define BUFSIZE 200
+#endif /* end of  BUFRGRIB_H */
diff --git a/odb/src/extras/emos/fileRead.h b/odb/src/extras/emos/fileRead.h
new file mode 100644
index 0000000..b1e7091
--- /dev/null
+++ b/odb/src/extras/emos/fileRead.h
@@ -0,0 +1,73 @@
+#ifndef FILE_READ_H
+#define FILE_READ_H
+/*
+	fileRead.h
+*/
+#include <stdio.h>
+
+#ifdef FOPEN64
+#define OFF_T off64_t
+#else
+#define OFF_T off_t
+#endif
+
+static fortint fileRead(char * buffer, fortint length, void * file) {
+/*  
+//  buffer = buffer to fill,
+//  length = size of buffer in bytes,
+//  file   = file pointer from fopen().
+//
+//  Returns the number of bytes read.
+//  On END_OF_FILE, returns negative value for number of bytes read .
+*/
+ 
+fortint nbytes;
+
+  nbytes = (fortint) fread( buffer, 1, length, (FILE *) file);
+  if ( feof((FILE *) file ) ) {
+     clearerr( (FILE *) file );
+     return (-nbytes);
+  }
+  return nbytes;
+}
+
+#ifdef FOPEN64
+static OFF_T fileSeek(void * file, OFF_T offset, fortint from) {
+
+  return ( (OFF_T) fseeko64((FILE *) file, offset, from) );
+}
+#else
+static fortint fileSeek(void * file, fortint offset, fortint from) {
+
+  return ( (fortint) fseek((FILE *) file, offset, from) );
+}
+#endif
+
+
+#ifdef FOPEN64
+static OFF_T fileTell(void * file) {
+
+  return ( (OFF_T) ftello64((FILE *) file) );
+}
+#else
+static fortint fileTell(void * file) {
+
+  return ( (fortint) ftell((FILE *) file) );
+}
+#endif
+
+#ifdef FOPEN64
+fortint readprod( char *, char * , fortint * ,
+                  fortint (*fileRead)(char *, fortint, void *),
+                  OFF_T (*fileSeek)(void *, OFF_T, fortint),
+                  OFF_T (*fileTell)(void *),
+                  void * );
+#else
+fortint readprod( char *, char * , fortint * ,
+                  fortint (*fileRead)(char *, fortint, void *),
+                  fortint (*fileSeek)(void *, fortint, fortint),
+                  fortint (*fileTell)(void *),
+                  void * );
+#endif
+
+#endif /* end of FILE_READ_H */
diff --git a/odb/src/extras/emos/fort2c.h b/odb/src/extras/emos/fort2c.h
new file mode 100644
index 0000000..b493f14
--- /dev/null
+++ b/odb/src/extras/emos/fort2c.h
@@ -0,0 +1,98 @@
+#ifndef FORT2C_H
+#define FORT2C_H
+/*
+	fort2c.h
+*/
+#ifdef CRAY
+/*  #include <fortran.h>  */
+typedef	int		_f_int6;	 
+typedef	long		_f_int8;	 
+typedef	_f_int6		_f_int;		 
+typedef	_f_int8		_f_int4;	 
+typedef	_f_int8		_f_int2;	 
+typedef	_f_int8		_f_int1;	 
+typedef	long		_f_log8;	 
+typedef	_f_log8		_f_log;		 
+typedef	_f_log8		_f_log4;	 
+typedef	_f_log8		_f_log2;	 
+typedef	_f_log8		_f_log1;	 
+typedef	double		_f_real8;	 
+typedef	long double	_f_real16;	 
+typedef	_f_real8	_f_real;	 
+typedef	_f_real16	_f_dble;	 
+typedef	_f_real8	_f_real4;	 
+typedef	_Complex double	_f_comp8;	 
+ 	 
+typedef	_f_comp8	_f_comp;	 
+ 
+                                                                                  
+ 
+typedef	union	_FCD	{
+	char	*c_pointer;		 
+	struct	{
+	unsigned bit_offset	:  6,	 
+		 fcd_len	: 26,	 
+		 word_addr	: 32;	 
+	} _F;
+} _dcf;		 
+typedef	void	*_fcd;	 
+ 
+ 
+    
+ 
+typedef void *_GPTR;
+typedef const void *_GPTR2CONST;
+    
+extern	_fcd		_cptofcd (char *_Ccp, unsigned _Len);
+extern	char *		_fcdtocp (_fcd _Fcd);
+extern	unsigned int	_fcdlen (_fcd _Fcd);
+extern	_f_log		_btol (long _BV);
+extern	long		_lvtob (_f_log _LV);
+extern	long		_ltob (_f_log *_LP);
+extern	char *		_f2ccpy (_fcd f, ...);
+extern	char *		_fc_copy (_fcd f, char *s, int slen);
+extern	char *		_fc_acopy (_fcd f);
+extern  int		_c2fcpy(char *c, _fcd f);
+extern	int		_isfcd (long _P);
+
+static	_fcd
+__cptofcd(char *c, unsigned int l);
+#pragma _CRI inline	__cptofcd
+static	_fcd
+__cptofcd(char *c, unsigned int l)
+{
+	_dcf	f;
+ 
+	f.c_pointer	= c;
+	f._F.fcd_len   	= l << 3;
+ 
+	return ((*(_fcd *) &f));
+}
+static	char *
+__fcdtocp(_fcd f);
+#pragma _CRI inline	__fcdtocp
+static	char *
+__fcdtocp(_fcd f)
+{
+	char	*c;
+	_dcf	d;
+	d		= (*(_dcf *) &f);
+	d._F.fcd_len	= 0;
+	c		= d.c_pointer;
+	return (c);
+}
+#else
+#define _fcd char *
+#define _fcdtocp(a) a
+#define _fcdlen(a) strlen(a)
+#endif
+ 
+#ifdef VAX
+typedef struct {short length; short magic; char * address;}DESC;
+#define _fcdtocp(a) fcdtocp(a)
+#define _fcd DESC *
+#endif
+
+char *fcd2char();	/* fortran to c string convertion (alloc memory) */
+
+#endif /* end of  FORT2C_H */
diff --git a/odb/src/extras/emos/pbio.c b/odb/src/extras/emos/pbio.c
new file mode 100644
index 0000000..e7ea7c7
--- /dev/null
+++ b/odb/src/extras/emos/pbio.c
@@ -0,0 +1,1324 @@
+/*
+// pbio.c
+*/
+
+#ifdef PTHREADS
+#include <pthread.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#ifdef FOPEN64
+#define OFF_T off64_t
+#else
+#define OFF_T off_t
+#endif
+
+static FILE** fptable = NULL;
+static int fptableSize = 0;
+
+#ifdef PTHREADS
+static pthread_mutex_t fpTableBusy = PTHREAD_MUTEX_INITIALIZER;
+#endif
+#define BUFFLEN 4096
+
+/*
+// Default buffer size for I/O operations (set via setvbuf)
+*/
+#define SIZE BUFSIZ
+static long size = SIZE;
+static int sizeSet = 0;
+static char * envSize;
+static char** fileBuffer = NULL;
+
+/*
+// Debug flags.
+*/
+#define DEBUGOFF 1
+#define DEBUG (debugSet > DEBUGOFF )
+static char * debugLevel;
+static int debugSet = 0;
+
+#include "bufrgrib.h"
+#include "fort2c.h"
+#include "fortint.h"
+#include "fileRead.h"
+
+#define NAMEBUFFLEN 256
+#define MODEBUFFLEN 10
+
+#define CURRENT_FILE (fptable[*unit])
+
+FILE* pbfp(long index) {
+  if( (fptable == NULL) || ((int)index < 0) || ((int)index >= fptableSize) )
+    return (FILE *) NULL;
+  else
+    return fptable[index];
+}
+
+/*
+//------------------------------------------------------------------------
+// PBOPEN - Open file (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+#if defined hpR64 || defined hpiaR64
+void pbopen_(fortint* unit,_fcd name,_fcd mode,fortint* iret,long l1,long l2) {
+#else
+void pbopen_(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
+#endif
+/*
+// Purpose:
+//  Opens file, returns the index of a UNIX FILE pointer held in 
+//  an internal table (fptable).
+//
+// First time through, reads value in environment variable PBIO_BUFSIZE
+// (if it is set) and uses it as the size to be used for internal file
+// buffers; the value is passed to setvbuf. If PBIO_BUFSIZE is not set,
+// a default value is used.
+//
+// Function  accepts:
+//    name = filename
+//    mode = r, r+, w
+//
+//    Note: l1 and l2 are the lengths of the FORTRAN character strings
+//          in name and mode.
+//
+// Function returns:
+//   INTEGER iret:
+//     -1 = Could not open file.
+//     -2 = Invalid file name.
+//     -3 = Invalid open mode specified
+//      0 = OK.
+*/
+int n;
+char *p;
+char  flags[4];
+
+#if (!defined CRAY) && (!defined VAX)
+char namebuff[NAMEBUFFLEN+1], modebuff[MODEBUFFLEN+1];
+#else
+char * namebuff, * modebuff;
+#endif
+
+/*
+// See if DEBUG switched on.
+*/
+    if( ! debugSet ) {
+      debugLevel = getenv("PBIO_DEBUG");
+      if( debugLevel == NULL )
+        debugSet = DEBUGOFF;              /* off */
+      else {
+        int loop;
+        for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
+          if( ! isdigit(debugLevel[loop]) ) {
+            printf("Invalid number string in PBIO_DEBUG: %s\n", debugLevel);
+            printf("PBIO_DEBUG must comprise only digits [0-9].\n");
+            debugSet = DEBUGOFF;
+          }
+        }
+        debugSet = DEBUGOFF + atol( debugLevel );
+      }
+      if( DEBUG ) printf("PBIO_PBOPEN: debug switched on\n");
+    }
+
+#if (!defined CRAY) && (!defined VAX)
+/*
+// Put the character strings into buffers and ensure that there is a
+// null terminator (for SGI case when FORTRAN CHARACTER variable is full
+// right to end with characters
+*/
+    {
+     int n1, n2;
+
+      n1 = (l1>NAMEBUFFLEN) ? NAMEBUFFLEN : l1;
+      n2 = (l2>MODEBUFFLEN) ? MODEBUFFLEN : l2;
+   
+      strncpy( namebuff, name, n1);
+      strncpy( modebuff, mode, n2);
+      namebuff[n1] = '\0';
+      modebuff[n2] = '\0';
+    }
+#else
+    if(!(namebuff = fcd2char(name))) {
+      *iret = -2;
+      return;
+    }
+    if(!(modebuff = fcd2char(mode))) {
+      free(namebuff);
+      *iret = -2;
+      return;
+    }
+#endif
+
+    strcpy(flags,"");
+
+    *unit = 0;
+    *iret = 0;
+
+/*
+// Strip trailing blanks
+*/
+    p  = namebuff + strlen(namebuff) - 1 ;
+    while(*p == ' ') {
+      *p = 0;
+      p--;
+    }
+    if( DEBUG ) printf("PBIO_PBOPEN: filename = %s\n", namebuff);
+/*
+// Build open flags from "modes"
+*/
+    p = modebuff;
+
+    switch(*p) {
+
+      case 'a':
+      case 'A': strcat(flags, "a");
+                      break;
+
+      case 'c':
+      case 'C':
+      case 'w':
+      case 'W': strcat(flags, "w");
+                break;
+
+      case 'r':
+      case 'R':
+                if( *(p+1) == '+' )
+                  strcat(flags, "r+");
+                else
+                  strcat(flags, "r");
+                break;
+
+      default:  *iret = -3;
+                return;
+
+    }
+    if( DEBUG ) printf("PBIO_PBOPEN: file open mode = %s\n", flags);
+
+/*
+// Look for a free slot in fptable.
+// (Create the table the first time through).
+*/
+#ifdef PTHREADS
+/*
+// Wait if another thread opening a file
+*/
+    pthread_mutex_lock(&fpTableBusy);
+#endif
+
+    n = 0;
+    if( fptableSize == 0 ) {
+      int i;
+      fptableSize = 2;
+      fptable = (FILE **) malloc(fptableSize*sizeof(FILE *));
+      if( fptable == NULL ) {
+        perror("Unable to allocate space for table of FILE pointers");
+        exit(1);
+      }
+
+      fileBuffer = (char **) malloc(fptableSize*sizeof(char *));
+      if( fileBuffer == NULL ) {
+        perror("Unable to allocate space for FILE buffers");
+        exit(1);
+      }
+
+      for( i = 0; i < fptableSize; i++ ) {
+        fptable[i] = 0;
+        fileBuffer[i] = NULL;
+      }
+    }
+    else {
+      while( n < fptableSize ) {
+        if(fptable[n]==0) {
+          *unit = n;
+          break;
+        }
+        n++;
+      }
+    }
+/*
+// If the table overflows, double its size.
+*/
+    if( n == fptableSize) {
+      int i;
+      fptableSize = 2*fptableSize;
+      fptable = (FILE **) realloc(fptable, fptableSize*sizeof(FILE *));
+      if( fptable == NULL ) {
+        perror("Unable to reallocate space for table of FILE pointers");
+        exit(1);
+      }
+      n = fptableSize/2;
+
+      fileBuffer = (char **) realloc(fileBuffer, fptableSize*sizeof(char *));
+      if( fileBuffer == NULL ) {
+        perror("Unable to allocate space for FILE buffers");
+        exit(1);
+      }
+
+      n = fptableSize/2;
+      for( i = n; i < fptableSize; i++ ) {
+        fptable[i] = 0;
+        fileBuffer[i] = NULL;
+      }
+
+      *unit = n;
+    }
+
+    if( DEBUG ) printf("PBIO_PBOPEN: fptable slot = %d\n", *unit);
+
+#ifdef FOPEN64
+    if( DEBUG ) printf("PBIO_PBOPEN: using fopen64\n");
+    fptable[n] = fopen64(namebuff, flags );
+#else
+    if( DEBUG ) printf("PBIO_PBOPEN: using fopen\n");
+    fptable[n] = fopen(namebuff, flags );
+#endif
+
+    if(fptable[n] == NULL) {
+      perror(namebuff);
+      *iret = -1;
+#if (defined CRAY) || (defined VAX)
+      free(namebuff);
+      free(modebuff);
+#endif
+#ifdef PTHREADS
+      pthread_mutex_unlock(&fpTableBusy);
+#endif
+      return;
+    }
+
+/*
+// Now allocate a buffer for the file, if necessary.
+*/
+    if( ! sizeSet ) {
+      envSize = getenv("PBIO_BUFSIZE");
+      if( envSize == NULL )
+        size = SIZE;             /* default */
+      else {
+        int loop;
+        for( loop = 0; loop < strlen(envSize) ; loop++ ) {
+          if( ! isdigit(envSize[loop]) ) {
+            printf("Invalid number string in PBIO_BUFSIZE: %s\n", envSize);
+            printf("PBIO_BUFSIZE must comprise only digits [0-9].\n");
+            exit(1);
+          }
+        }
+        size = atol( envSize );
+      }
+      if( size <= 0 ) {
+        printf("Invalid buffer size in PBIO_BUFSIZE: %s\n", envSize);
+        printf("Buffer size defined by PBIO_BUFSIZE must be positive.\n");
+        exit(1);
+      }
+      sizeSet = 1;
+    }
+
+    if( DEBUG ) printf("PBIO_PBOPEN: file buffer size = %ld\n", size);
+
+    if( fileBuffer[n] == NULL ) {
+      fileBuffer[n] = (char *) malloc(size);
+    }
+    if( setvbuf(CURRENT_FILE, fileBuffer[*unit], _IOFBF, size) ) {
+      perror("setvbuf failed");
+      *iret = -1;
+    }
+
+#ifdef PTHREADS
+    pthread_mutex_unlock(&fpTableBusy);
+#endif
+
+#if (defined CRAY) || (defined VAX)
+    free(namebuff);
+    free(modebuff);
+#endif
+
+}
+
+#if (defined hpR64) || (defined hpiaR64)
+void pbopen(fortint* unit,_fcd name,_fcd mode,fortint* iret,long l1,long l2) {
+#else
+void pbopen(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
+#endif
+
+  pbopen_(unit,name,mode,iret,l1,l2);
+}
+
+/*
+//------------------------------------------------------------------------
+// PBSEEK - Seek (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbseek_(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
+/*
+//
+// Purpose:
+//   Seeks to a specified location in file.
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+//
+//    offset = byte count
+//
+//    whence  = 0, from start of file
+//            = 1, from current position
+//            = 2, from end of file.  
+//
+//  Returns:
+//    iret:
+//      -2 = error in handling file,
+//      -1 = end-of-file
+//      otherwise,  = byte offset from start of file.
+*/
+int my_offset = (int) *offset;
+int my_whence = (int) *whence;
+
+/*
+// Must use negative offset if working from end-of-file
+*/
+    if( DEBUG ) { 
+      printf("PBIO_PBSEEK: fptable slot = %d\n", *unit);
+      printf("PBIO_PBSEEK: Offset = %d\n", my_offset);
+      printf("PBIO_PBSEEK: Type of offset = %d\n", my_whence);
+    }
+
+    if( my_whence == 2) my_offset = - abs(my_offset);
+
+    *iret = fileTell(CURRENT_FILE);
+    if( DEBUG ) printf("PBIO_PBSEEK: current position = %d\n", *iret);
+    if( *iret == my_offset && my_whence == 0)
+      *iret = 0;
+    else
+      *iret = fileSeek(CURRENT_FILE, my_offset, my_whence);
+
+    if( DEBUG ) printf("PBIO_PBSEEK: fileSeek return code = %d\n",*iret);
+
+    if( *iret != 0 ) {
+      if( ! feof(CURRENT_FILE) ) {
+        *iret = -2;             /* error in file-handling */
+        perror("pbseek");
+      }
+      else
+        *iret = -1;             /* end-of-file  */
+
+      clearerr(CURRENT_FILE);
+      return;
+    }
+
+/*
+// Return the byte offset from start of file
+*/
+    *iret = fileTell(CURRENT_FILE);
+
+    if( DEBUG )
+      printf("PBIO_PBSEEK: byte offset from start of file = %d\n",*iret);
+
+    return;
+
+}
+
+void pbseek(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
+
+  pbseek_(unit,offset,whence,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+// PBTELL - Tells current file position (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbtell_(fortint* unit,fortint* iret) {
+/*
+//
+// Purpose:
+//   Tells current byte offset in file.
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+//
+//  Returns:
+//    iret:
+//      -2 = error in handling file,
+//      otherwise,  = byte offset from start of file.
+*/
+
+
+/*
+// Return the byte offset from start of file
+*/
+    *iret = fileTell(CURRENT_FILE);
+
+    if( *iret < 0 ) {
+      if( DEBUG ) {           /* error in file-handling */
+        printf("PBIO_PBTELL: fptable slot = %d. ", *unit);
+        printf("Error status = %d\n", *iret);
+      }
+      perror("pbtell");
+      *iret = -2;
+    }
+
+    if( DEBUG ) {
+      printf("PBIO_PBTELL: fptable slot = %d. ", *unit);
+      printf("Byte offset from start of file = %d\n",*iret);
+    }
+
+    return;
+}
+
+void pbtell(fortint* unit,fortint* iret) {
+
+  pbtell_(unit,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBREAD - Read (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbread_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+/*
+// Purpose:
+//  Reads a block of bytes from a file..
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+//
+//    nbytes = number of bytes to read.
+//
+//  Returns:
+//    iret:
+//      -2 = error in reading file,
+//      -1 = end-of-file,
+//      otherwise, = number of bytes read.
+*/
+    if( DEBUG ) {
+      printf("PBIO_READ: fptable slot = %d. ", *unit);
+      printf("Number of bytes to read = %d\n", *nbytes);
+    }
+
+    if( (*iret = fread(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
+      if( ! feof(CURRENT_FILE) ) {
+        *iret = -2;             /*  error in file-handling  */
+        perror("pbread");
+        clearerr(CURRENT_FILE);
+        return;
+      }
+      else {
+        *iret = -1;             /*  end-of-file */
+        clearerr(CURRENT_FILE);
+      }
+    }
+
+    if( DEBUG ) {
+      printf("PBIO_READ: fptable slot = %d. ", *unit);
+      printf("Number of bytes read = %d\n", *nbytes);
+    }
+
+    return;
+}
+ 
+void pbread(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+
+  pbread_(unit,buffer,nbytes,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBREAD2 - Read (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbread2_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+/*
+// Purpose:
+//  Reads a block of bytes from a file..
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+//
+//    nbytes = number of bytes to read.
+//
+//  Returns:
+//    iret:
+//      -2 = error in reading file,
+//      -1 = end-of-file,
+//      otherwise, = number of bytes read.
+*/
+    if( DEBUG ) {
+      printf("PBIO_READ2: fptable slot = %d. ", *unit);
+      printf("Number of bytes to read = %d\n", *nbytes);
+    }
+
+   if( (*iret = fread(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
+     if( ! feof(CURRENT_FILE) ) {
+       *iret = -2;             /*  error in file-handling  */
+       perror("pbread2");
+       clearerr(CURRENT_FILE);
+     }
+   }
+
+  if( DEBUG )
+    printf("PBIO_READ2: Number of bytes read = %d\n", *iret);
+
+   return;
+}
+
+void pbread2(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+
+  pbread2_(unit,buffer,nbytes,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBWRITE - Write (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbwrite_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+/*
+// Purpose:
+//  Writes a block of bytes to a file.
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+//
+//    nbytes = number of bytes to write.
+//
+//  Returns:
+//    iret:
+//      -1 = Could not write to file.
+//     >=0 = Number of bytes written.
+*/
+    if( DEBUG ) {
+      printf("PBIO_WRITE: fptable slot = %d. ", *unit);
+      printf("Number of bytes to write = %d\n", *nbytes);
+    }
+
+    if( (*iret = fwrite(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
+      perror("pbwrite");
+      *iret = -1;
+    }
+
+    if( DEBUG ) {
+      printf("PBIO_WRITE: fptable slot = %d. ", *unit);
+      printf("PBIO_WRITE: number of bytes written = %d\n", *iret);
+    }
+
+    return;
+}
+
+void pbwrite(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+
+  pbwrite_(unit,buffer,nbytes,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//   PBCLOSE - close (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbclose_(fortint* unit,fortint* iret) {
+/*
+// Purpose:
+//  Closes file.
+//
+//  Function  accepts:
+//    unit = the index of a UNIX FILE pointer held in
+//           an internal table (fptable).
+////  Returns:
+//    iret:
+//      0 = OK.
+//      otherwise = error in handling file.
+*/
+    if( DEBUG )
+      printf("PBIO_CLOSE: fptable slot = %d\n", *unit);
+
+    if( ( *iret = fclose(CURRENT_FILE) ) != 0 ) perror("pbclose");
+    CURRENT_FILE = 0;
+
+    return;
+}
+
+void pbclose(fortint* unit,fortint* iret) {
+
+  pbclose_(unit,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBFLUSH - flush (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbflush_(fortint * unit) {
+/*
+// Purpose:	Flushes file.
+*/
+    if( DEBUG )
+      printf("PBIO_FLUSH: fptable slot = %d\n", *unit);
+
+    fflush(CURRENT_FILE);
+}
+
+void pbflush(fortint * unit) {
+
+  pbflush_(unit);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBREAD3 - read (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbread3_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+/*
+// Purpose:
+//  Reads a block of bytes from a file..
+//
+//  Function returns:
+//    status :   -2 = error in reading file,
+//               -1 = end-of-file,
+//               otherwise, = number of bytes read.
+*/
+    if( DEBUG )
+      printf("PBIO_READ3: number of bytes to read = %d\n", *nbytes);
+
+    *iret = read(*unit, buffer, *nbytes);
+
+    if( DEBUG )
+      printf("PBIO_READ3: number of bytes read = %d\n", *iret);
+/*
+// Error in file-handling
+*/
+    if(*iret == -1) {
+      *iret = -2;
+      perror("pbread3");
+      return;
+    }
+/*
+// Read problem
+*/
+    else if(*iret != *nbytes) {
+      printf("EOF; pbread3; bytes requested %d; read in: %d\n",
+             *nbytes,*iret);
+      *iret = -1;
+      return;
+    }
+ 
+}
+ 
+void pbread3(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+
+  pbread3_(unit,buffer,nbytes,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  oct_bin3
+//------------------------------------------------------------------------
+*/
+static int oct_bin3(int onum) {
+/*
+// Converts an integer to octal digits
+*/
+   char tmp[20];
+   int  rc;
+
+   sprintf(tmp,"%d",onum);
+   sscanf(tmp,"%o",&rc);
+   return rc; 
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBOPEN3 - Open file (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbopen3_(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
+/*
+// Purpose:
+//   Opens file, return UNIX FILE pointer.
+//
+// Function returns:
+//   iret:  -1 = Could not open file.
+//          -2 = Invalid file name.
+//          -3 = Invalid open mode specified
+//           0 = OK.
+//
+// Note: l1 and l2 are the lengths of the character strings in 
+//       name and mode on SGI.
+*/
+char *p;
+int oflag;
+int dmas;
+int filemode;
+char  flags[4];
+
+#if (!defined CRAY) && (!defined VAX)
+char namebuff[NAMEBUFFLEN], modebuff[MODEBUFFLEN];
+#else
+char * namebuff, * modebuff;
+#endif
+
+/*
+// See if DEBUG switched on.
+*/
+    if( ! debugSet ) {
+      debugLevel = getenv("PBIO_DEBUG");
+      if( debugLevel == NULL )
+        debugSet = DEBUGOFF;              /* off */
+      else {
+        int loop;
+        for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
+          if( ! isdigit(debugLevel[loop]) ) {
+            printf("Invalid number string in PBIO_DEBUG: %s\n", debugLevel);
+            printf("PBIO_DEBUG must comprise only digits [0-9].\n");
+            debugSet = DEBUGOFF;
+          }
+        }
+        debugSet = DEBUGOFF + atol( debugLevel );
+      }
+      if( DEBUG ) printf("PBIO_PBOPEN3: debug switched on\n");
+    }
+
+#if (!defined CRAY) && (!defined VAX)
+/*
+// Put the character strings into buffers and ensure that there is a
+// null terminator (for SGI case when FORTRAN CHARACTER variable is full
+// right to end with characters
+*/
+    {
+     int n1, n2;
+
+      n1 = (l1>NAMEBUFFLEN) ? NAMEBUFFLEN : l1;
+      n2 = (l2>MODEBUFFLEN) ? MODEBUFFLEN : l2;
+   
+      strncpy( namebuff, name, n1);
+      strncpy( modebuff, mode, n2);
+      namebuff[n1] = '\0';
+      modebuff[n2] = '\0';
+    }
+#else
+    if(!(namebuff = fcd2char(name))) {
+      *iret = -2;
+      return;
+    }
+    if(!(modebuff = fcd2char(mode))) {
+      free(namebuff);
+      *iret = -2;
+      return;
+    }
+#endif
+
+    strcpy(flags,"");
+
+    *unit = 0;
+    *iret = 0;
+
+/*
+// Strip trailing blanks
+*/
+    p  = namebuff + strlen(namebuff) - 1 ;
+
+    while(*p == ' ') {
+      *p = 0;
+      p--;
+    }
+    if( DEBUG ) printf("PBIO_PBOPEN: filename = %s\n", namebuff);
+            
+/*
+// Build open flags from "modes"
+*/
+    p = modebuff;
+
+    switch(*p) {
+
+      case 'a':
+      case 'A': oflag = 0x100 | 2 | 0x08;
+                filemode = 766;
+                break;
+
+      case 'c':
+      case 'C':
+      case 'w':
+      case 'W': oflag = 0x100 | 1;
+                filemode = 766;
+                break;
+
+      case 'r':
+      case 'R': oflag = 0;
+                filemode = 444;
+                break;
+
+      default:  *iret = -3;
+                return;
+
+    }
+
+    if( DEBUG ) printf("PBIO_PBOPEN: file open mode = %s\n", modebuff);
+
+    dmas = umask(000);
+    *unit = open(namebuff, oflag, oct_bin3(filemode));
+    umask(dmas);
+
+    if(*unit == -1) {
+      perror(namebuff);
+      perror("pbopen3");
+      *iret = -2;
+    }
+
+    if( DEBUG ) printf("PBIO_PBOPEN3: file pointer = %0x\n", *unit);
+
+#if (defined CRAY) || (defined VAX)
+    free(namebuff);
+    free(modebuff);
+#endif
+
+}
+
+void pbopen3(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
+
+  pbopen3_(unit,name,mode,iret,l1,l2);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBCLOSE3 - Close file (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbclose3_(fortint* unit,fortint* iret) {
+/*
+//
+// Purpose:  Closes file.
+//
+// Function returns:
+//   status : non-0 = error in handling file.
+//            0 = OK.
+*/
+    if( DEBUG ) printf("PBIO_PBCLOSE3: file pointer = %0x\n", *unit);
+
+    *iret = close(*unit);
+
+    if(*iret != 0) perror("pbclose3");
+}
+
+void pbclose3(fortint* unit,fortint* iret) {
+
+  pbclose3_(unit,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBSEEK3 - Seek (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbseek3_(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
+/*
+//
+// Purpose:  Seeks to specified location in file.
+//
+// Function returns:
+//   status: -2 = error in handling file,
+//           -1 = end-of-file
+//           otherwise,         = byte offset from start of file.
+//
+//   whence  = 0, from start of file
+//           = 1, from current position
+//           = 2, from end of file.  
+*/
+fortint my_offset = *offset;
+int my_whence;
+
+    if( DEBUG ) {
+      printf("PBIO_PBSEEK3: file pointer = %0x\n", *unit);
+      printf("PBIO_PBSEEK3: offset = %d\n", my_offset);
+      printf("PBIO_PBSEEK3: type of offset = %d\n", *whence);
+    }
+
+/*
+// Must use negative offset if working from end-of-file
+*/
+    if( *whence == 2) {
+      my_offset = - abs(my_offset);
+      my_whence = 2;
+    }
+    else if(*whence == 0)
+    {
+      my_whence = 0;
+    }
+    else
+    {
+      my_whence = 1;
+    }
+
+    if((*iret=lseek(*unit, my_offset, my_whence)) < 0) {
+      perror("pbseek3;");
+      *iret = -1;           /* end-of-file  */
+    }
+
+    if( DEBUG )
+      printf("PBIO_PBSEEK3: byte offset from start of file = %d\n",*iret);
+
+}
+            
+void pbseek3(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
+
+  pbseek3_(unit,offset,whence,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBWRITE3 - Write (from FORTRAN)
+//------------------------------------------------------------------------
+*/
+void pbwrite3_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+/*
+// Purpose:  Writes a block of bytes to a file.
+//
+// Function returns:
+//   status: -1 = Could not write to file.
+//           >=0 = Number of bytes written.
+*/
+
+    if( DEBUG ) {
+      printf("PBIO_PBWRITE3: file pointer = %0x\n", *unit);
+      printf("PBIO_WRITE#: number of bytes to write = %d\n", *nbytes);
+    }
+
+    *iret = write(*unit, buffer, *nbytes);
+    if( DEBUG )
+      printf("PBIO_WRITE3: number of bytes written = %d\n", *iret);
+
+    if( *iret != *nbytes ) {
+      perror("pbwrite3: ");
+      *iret = -1;
+    }
+
+}
+
+void pbwrite3(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
+
+  pbwrite3_(unit,buffer,nbytes,iret);
+}
+
+/*
+//------------------------------------------------------------------------
+//  GRIBREAD
+//------------------------------------------------------------------------
+*/
+void gribread_(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+/*
+//  Called as a FORTRAN subroutine:
+//
+//    CALL GRIBREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
+//
+*/
+fortint holdsize = *buffsize;
+
+/*
+// Read GRIB product
+*/
+
+    *status = readprod("GRIB",buffer,&holdsize,fileRead,fileSeek,fileTell,
+                       CURRENT_FILE);
+    *readsize = abs(holdsize );
+
+    if( DEBUG ) {
+      printf("PBIO_GRIBREAD: fptable slot = %d. ", *unit);
+      printf("Number of bytes read = %d\n", *readsize);
+    }
+
+    return;
+}
+
+void gribread(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+
+  gribread_(buffer,buffsize,readsize,status,unit);
+}
+
+/*
+//------------------------------------------------------------------------
+//  BUFRREAD
+//------------------------------------------------------------------------
+*/
+void bufrread_(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+/*
+//  Called as a FORTRAN subroutine:
+//
+//    CALL BUFRREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
+//
+*/
+fortint holdsize = *buffsize;
+
+/*
+// Read BUFR product
+*/
+    *status = readprod("BUFR",buffer,&holdsize,fileRead,fileSeek,fileTell,
+                       CURRENT_FILE);
+    *readsize =  abs(holdsize );
+
+    if( DEBUG ) {
+      printf("PBIO_BUFRREAD: fptable slot = %d. ", *unit);
+      printf("Number of bytes read = %d\n", *readsize);
+    }
+
+    return;
+}
+
+void bufrread(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+
+  bufrread_(buffer,buffsize,readsize,status,unit);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PSEUREAD
+//------------------------------------------------------------------------
+*/
+void pseuread_(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+/*
+//  Called as a FORTRAN subroutine:
+//
+//    CALL PSEUREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
+//
+*/
+fortint holdsize = *buffsize;
+
+/*
+// Read GRIB product
+*/
+    *status = readprod(NULL,buffer,&holdsize,fileRead,fileSeek,fileTell,
+                       CURRENT_FILE);
+    *readsize = abs(holdsize );
+
+    if( DEBUG ) {
+      printf("PBIO_PSEUREAD: fptable slot = %d. ", *unit);
+      printf("Number of bytes read = %d\n", *readsize);
+    }
+
+    return;
+}
+
+void pseuread(
+char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
+
+  pseuread_(buffer,buffsize,readsize,status,unit);
+}
+
+/*
+//------------------------------------------------------------------------
+//  PBSIZE
+//------------------------------------------------------------------------
+*/
+void pbsize_(fortint* unit,fortint* plen) {
+/*
+//  Returns the size in bytes of the next GRIB, BUFR, TIDE, BUDG, DIAG
+//  product.
+//
+//  Called from FORTRAN:
+//      CALL PBSIZE( KUNIT, LENGTH)
+//
+//  unit  = file id returned from PBOPEN.
+//  plen  = size in bytes of the next product.
+//        = -2 if error allocating memory for internal buffer.
+//
+//  The input file is left positioned where it started.
+*/
+fortint iret;
+char statbuff[BUFFLEN];
+char * buff;
+long offset, loop = 1;
+
+/*
+//  Use a smallish buffer for processing; this should suffice for all cases
+//  except versions -1 and 0 of GRIB and large BUFR products
+*/
+    offset = (fortint) fileTell( CURRENT_FILE);
+    if( DEBUG ) {
+      printf("PBIO_SIZE: fptable slot = %d. ", *unit);
+      printf("Current file position = %ld\n", offset);
+    }
+
+    *plen = BUFFLEN;
+    if( DEBUG )
+      printf("PBIO_SIZE: current buffer size = %d\n", *plen);
+
+    iret = readprod(NULL,statbuff,plen,fileRead,fileSeek,fileTell,CURRENT_FILE);
+    if( iret == -2 ) {
+      printf("readprod error %d\n", iret);
+      *plen = -2;
+      return;
+    }
+/*
+//  If the smallish buffer is too small, progressively increase it until 
+//  big enough
+*/
+    while ( iret == -4 ) {
+      loop++;
+      buff = (char *) malloc( BUFFLEN*loop);
+      if( buff == NULL) {
+        perror("malloc failed in PBSIZE");
+        *plen = -2;
+        return;
+      }
+      *plen = BUFFLEN*loop;
+      if( DEBUG )
+        printf("PBIO_SIZE: buffer size increased to: %d\n", *plen);
+
+      offset = (fortint) fileSeek( CURRENT_FILE, offset, SEEK_SET);
+      offset = (fortint) fileTell( CURRENT_FILE);
+      iret = readprod(NULL,buff,plen,fileRead,fileSeek,fileTell,CURRENT_FILE);
+      free(buff);
+    }
+
+    if( iret == -2 ) {
+      printf("readprod error %d\n", iret);
+      *plen = -2;
+    }
+/*
+//  Put the file pointer back where it started
+*/
+    if( DEBUG ) {
+      printf("PBIO_SIZE: file pointer set back to: %ld\n", offset);
+      printf("PBIO_SIZE: Product size = %d\n", *plen);
+    }
+    offset = (fortint) fileSeek( CURRENT_FILE, offset, SEEK_SET);
+
+    return ;
+}
+
+void pbsize(fortint* unit,fortint* plen) {
+
+  pbsize_(unit,plen);
+}
+
+/*
+//------------------------------------------------------------------------
+//  CREXRD
+//------------------------------------------------------------------------
+*/
+#define END_OF_FILE -1
+#define FILE_READ_ERROR -2
+#define USER_BUFFER_TOO_SMALL -3
+#define FILE_TOO_SMALL -5
+#define MINIMUM_CREX_SIZE 13
+#define CREX 0x43524558
+
+typedef char * String;
+
+void crexrd_(String buffer,int* bufflen,int* size,int* status,fortint * unit) {
+/*
+//  Called from FORTRAN:
+//    CALL CREXRD( KARRAY, KINLEN, NREAD, IRET, KUNIT )
+*/
+int loop;
+OFF_T foundPosition;
+int number, crexFound = 0, endFound = 0;
+String endBuffer;
+String next;
+char plplcrcrlf7777[10] = {0,0,0,0,0,0,0,0,0,0};
+char PlPlCrCrLf7777[10] = {0x2b,0x2b,0x0d,0x0d,0x0a,0x37,0x37,0x37,0x37,0x00};
+
+/*
+// Check buffer big enough for CREX search
+*/
+  if( *bufflen < MINIMUM_CREX_SIZE ) {
+    *status = USER_BUFFER_TOO_SMALL;
+    return;
+  }
+
+/*
+// Look for CREX
+*/
+  for( loop = 0; loop <= 4; loop++) buffer[loop] = '\0';
+
+  while( !crexFound ) {
+    buffer[0] = buffer[1];
+    buffer[1] = buffer[2];
+    buffer[2] = buffer[3];
+    number = fread((buffer+3), 1, 1, CURRENT_FILE);
+    if( feof(CURRENT_FILE) ) {
+      *status = END_OF_FILE;
+      return;
+    }
+    if( (number != 1) || ferror(CURRENT_FILE) ) {
+      perror("crexrd file read error");
+      *status = FILE_READ_ERROR;
+      return;
+    }
+    if( strcmp(buffer,"CREX") == 0 ) {
+      crexFound = 1;
+#ifdef FOPEN64
+      foundPosition = ftello64(CURRENT_FILE) - 4;
+#else
+      foundPosition = ftell(CURRENT_FILE) - 4;
+#endif
+    }
+  }
+
+/*
+// Read some more characters into the buffer
+*/
+  number = fread((buffer+4), 1, ((*bufflen)-4), CURRENT_FILE);
+  if( ferror(CURRENT_FILE) ) {
+    perror("crexrd file read error");
+    *status = FILE_READ_ERROR;
+    return;
+  }
+  endBuffer = buffer + number + 3;
+    
+/*
+// Look for ++CrCrLf7777 at end of product
+*/
+  next = buffer+4;
+  endFound = 0;
+  for( loop = 0; loop < 8; loop++ )
+    plplcrcrlf7777[loop] = *(next++);
+  plplcrcrlf7777[9] = '\0';
+
+  while( (!endFound) && (next<=endBuffer) ) {
+    plplcrcrlf7777[8] = *(next++);
+    if( strcmp(plplcrcrlf7777,PlPlCrCrLf7777) == 0 ) {
+      endFound = 1;
+      *size = (int) (next - buffer);
+    }
+
+    for( loop = 0; loop < 8; loop++ )
+      plplcrcrlf7777[loop] = plplcrcrlf7777[loop+1];
+  }
+
+  if( !endFound ) {
+    if( feof(CURRENT_FILE) ) 
+      *status = END_OF_FILE;
+    else
+      *status = USER_BUFFER_TOO_SMALL;
+    return;
+  }
+
+/*
+// Position file at end of CREX product
+*/
+#ifdef FOPEN64
+  *status = fseeko64(CURRENT_FILE, (foundPosition+(*size)), 0);
+#else
+  *status = fseek(CURRENT_FILE, (foundPosition+(*size)), 0);
+#endif
+
+}
+
+void crexrd(String buffer,int* bufflen,int* size,int* status,fortint * unit) {
+
+  crexrd_(buffer,bufflen,size,status,unit);
+}
diff --git a/odb/src/extras/emos/readprod.c b/odb/src/extras/emos/readprod.c
new file mode 100644
index 0000000..d8069d3
--- /dev/null
+++ b/odb/src/extras/emos/readprod.c
@@ -0,0 +1,846 @@
+/*
+//    readprod.c
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef FOPEN64
+#define OFF_T off64_t
+#else
+#define OFF_T off_t
+#endif
+
+#ifdef sun4
+#include <memory.h>
+#endif
+
+#include "bufrgrib.h"
+#include "fortint.h"
+#include "fileRead.h"
+#include "sizeRoutines.h"
+
+#define THREE_BYTE_LONG(p) ((((*(p))<<16) & 0xff0000) | (((*(p+1))<<8) & 0xff00) | (*(p+2)) & 0xff)
+#define CHECK(stat,message,code) if((stat)) {perror(message);return(code);}
+
+#define WMOBIT1 0x80
+#define WMOBIT2 0x40
+#define WMOBIT7 0x02
+#define WMOBIT8 0x01
+
+#define END_OF_FILE      -1
+#define INTERNAL_ERROR   -2
+#define BUFFER_TOO_SMALL -3
+#define USER_BUFFER_TINY -4
+#define MISPLACED_7777   -5
+
+#define SECT_0_LEN 4
+#define LEN_7777 4
+#define SMALL 40
+#define LARGEBUF 200000
+
+#define GRIB 0x47524942
+#define BUFR 0x42554652
+#define BUDG 0x42554447
+#define TIDE 0x54494445
+#define DIAG 0x44494147
+#define CREX 0x43524558
+#define CODE_7777 0x37373737
+
+static int grab(char * , char * , long ,long ,long * );
+static fortint waveLength(char * );
+
+#ifdef FOPEN64
+fortint readprod( char * prod_id, char * buffer, fortint * size, 
+              fortint (*fileRead)(char *, fortint , void *),
+              OFF_T (*fileSeek)(void *, OFF_T, fortint),
+              OFF_T (*fileTell)(void *),
+              void * stream)
+#else
+fortint readprod( char * prod_id, char * buffer, fortint * size, 
+              fortint (*fileRead)(char *, fortint , void *),
+              fortint (*fileSeek)(void *, fortint, fortint),
+              fortint (*fileTell)(void *),
+              void * stream)
+#endif
+/*
+//  Reads a BUFR, GRIB, BUDG, TIDE, DIAG product.
+//
+//  prod_id = "BUFR", "GRIB", "BUDG", "TIDE", "DIAG" ...
+//  buffer = buffer to hold product,
+//  size = on input, size of buffer in bytes,
+//         on output, number of bytes read.
+//  fileRead = function used to read the product,
+//  fileSeek = function used to reposition within the product byte stream,
+//  fileTell = function used to report the current byte position within
+//             the product byte stream,
+//  stream = data describing the input stream (eg. FILE *).
+//
+//  Returns 
+//    -1 if can't find product  (eg. end-of-file)
+//    -2 if internal processing error (malloc fail, file seek error)
+//    -3 if buffer too small for whole product.
+//    -4 if user buffer too small to even start product processing.
+//    -5 if the 7777 group is in the wrong place
+//
+*/
+{
+static char * shold = NULL;           /* buffer used to read product */
+char * hold = NULL;
+fortint holdsize = SMALL, numread;
+fortint found = 0, length, prodlen;
+fortint given_buflen = *size;
+char p;
+unsigned long code=0, wanted = 0;
+OFF_T status = 0, i, present_position = 0;
+fortint one = 1;
+
+/* See if user gave a buffer for holding the product
+*/
+  if ( buffer == NULL ) {         /* No buffer given, get some */
+    if ( shold == NULL ) {        /* but only first time round */
+      shold = (char *) malloc( LARGEBUF);
+      CHECK((shold == NULL),"malloc failed in readnext",INTERNAL_ERROR);
+    }
+    given_buflen = LARGEBUF;
+    hold = shold;
+  }
+  else                             /* User buffer given */
+    hold = buffer;
+
+/* Make sure the user gave some buffer
+*/
+  if ( given_buflen < holdsize ) return USER_BUFFER_TINY;
+
+/* Look for product identifier
+*/
+  if ( prod_id != NULL )
+    for ( i = 0; i < 4; i++ )
+      wanted = ( (wanted << 8) + *(prod_id+i) ) & 0xFFFFFFFF;
+
+/* Read some bytes from the product
+*/
+  do {
+    numread = fileRead( &p, one, stream );
+    if ( numread <= 0 ) {
+      *size = 0;
+      return END_OF_FILE;
+    }
+
+    code = ( (code << 8) + p ) & 0xFFFFFFFF;
+
+    if ( prod_id == NULL ) {
+      switch(code) {
+        case BUDG:
+        case BUFR:
+        case GRIB:
+        case TIDE:
+        case DIAG:
+        case CREX: found = 1;
+      }
+    }
+    else
+      if ( code == wanted ) found = 1;
+
+  } while ( ! found );
+
+/* Find the product length
+*/
+  prodlen = prodsize( code, hold, given_buflen, &holdsize, fileRead, stream);
+
+  if( prodlen == -4 ) return USER_BUFFER_TINY;
+
+  if( prodlen < -4 ) {           /* special case for very large wave products */
+    fortint estimate; 
+
+    estimate = -prodlen;
+    prodlen = estimate - 128;
+    *size = prodlen;
+
+    present_position = fileTell((FILE *)stream);
+    status = fileSeek( (FILE *)stream, prodlen - holdsize , SEEK_CUR);
+    CHECK(status,"fileSeek error in readprod",INTERNAL_ERROR);
+
+/*  Read bytes from the product upto and including 7777
+*/
+    code = 0;
+    do {
+      numread = fileRead( &p, one, stream );
+      if ( numread <= 0 ) return MISPLACED_7777;
+
+      *size = *size + 1;
+      if( *size > estimate ) return MISPLACED_7777;
+
+      code = ( (code << 8) + p ) & 0xFFFFFFFF;
+
+    } while ( code != CODE_7777 );
+
+    if( given_buflen < *size )
+      return BUFFER_TOO_SMALL;
+    else {
+      status = fileSeek( (FILE *)stream, present_position, SEEK_SET);
+      CHECK(status,"fileSeek error in readprod",INTERNAL_ERROR);
+
+      numread = fileRead(hold+present_position,(*size-present_position),stream);
+      if ( numread <= 0 ) return INTERNAL_ERROR;
+      return 0;
+    }
+  }
+
+/* Move to end of product and check position of 7777 group
+   in the case that the user gave a NULL buffer and zero length
+*/
+  if ( *size == 0 ) {
+    char grp_7777[5];
+
+    *size = prodlen;             /* report the actual product length */
+
+    status = fileSeek( (FILE *)stream, prodlen - holdsize - LEN_7777, SEEK_CUR);
+    CHECK(status,"fileSeek error in readprod",INTERNAL_ERROR);
+
+    numread = fileRead( grp_7777, LEN_7777 ,stream );
+    grp_7777[4] = '\0';
+    if( strcmp(grp_7777,"7777") != 0 ) return MISPLACED_7777;
+
+    return BUFFER_TOO_SMALL;
+  }
+
+/* Otherwise read as much of the product as possible into the buffer, then
+   move to end of product and check position of 7777 group
+*/
+  *size = prodlen;                /* report the actual product length */
+
+  length = (given_buflen > prodlen) ? prodlen : given_buflen ;
+
+  if ( length > holdsize ) {
+
+/*
+//  Before reading rest of product, put zero at end of expected 7777
+//  group to ensure that it is not left over from an earlier product
+//  of the same length
+*/
+    *(hold+length-1) = '\0';
+    numread = fileRead( hold+holdsize, length-holdsize ,stream );
+    if( numread <= 0 ) {
+      *size = holdsize-numread;
+      return END_OF_FILE;
+    }
+
+    if ( given_buflen < prodlen ) {
+      char grp_7777[5];
+
+      status = fileSeek((FILE*)stream,prodlen-given_buflen - LEN_7777,SEEK_CUR);
+      CHECK(status,"fileSeek error in readprod",INTERNAL_ERROR);
+
+      numread = fileRead( grp_7777, LEN_7777 ,stream );
+      if( numread <= 0 ) return END_OF_FILE;
+
+      grp_7777[4] = '\0';
+      if( strcmp(grp_7777,"7777") != 0 ) return MISPLACED_7777;
+
+      return BUFFER_TOO_SMALL;
+    }
+  }
+
+  if(strncmp(hold+prodlen-LEN_7777,"7777",(size_t)4)!=0) return MISPLACED_7777;
+
+  return *size;
+
+}
+
+
+static fortint gribsize(char * hold, fortint leng, fortint * holdsize,
+                     fortint (*fileRead)(), void * stream)
+/*
+//  Calculates the size in bytes of a GRIB product.
+//
+//  hold = buffer to hold product,
+//  leng = length of buffer,
+//  holdsize = number of bytes of the product in the hold buffer.
+//             Note that this increases if necessary as more bytes are read.
+//  fileRead = function used to read the product,
+//  stream = data describing the input stream (eg. FILE *).
+*/
+{
+fortint length, numread, num, hsize = *holdsize;
+fortint section2, section3 ;
+unsigned char * phold = (unsigned char *) hold;
+
+/* Need more bytes to decide on which version of GRIB
+*/
+  if ( leng < 24 ) return USER_BUFFER_TINY;
+
+/* Put first 24 bytes in buffer
+*/
+  num = 24;
+  if ( hsize < num) {
+    numread = fileRead( hold + hsize, num - hsize, stream);
+    if ( numread <= 0 ) {          /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = num;
+  }
+  *holdsize = hsize;
+
+/* See if the GRIB version is 0 ...
+*/
+  if ( THREE_BYTE_LONG(phold+4) == 24 ) {
+    length = 28;		     /* GRIB + section 1 */
+
+/* Check for presence of sections 2 and 3
+*/
+    section2 = ( hold[11] & WMOBIT1 ) ;
+    section3 = ( hold[11] & WMOBIT2 ) ;
+
+/* Add up all lengths of sections
+*/
+    return lentotal(hold, holdsize, leng, length, section2, section3, 
+                    fileRead, stream);
+  }
+
+/* ... or version 1 ...
+*/
+
+  if ( ( hold[21] != 0 ) || ( hold[22] != 0 ) ) {
+
+/* Nightmare fixup for very large GRIB products (eg 2D wave spectra).
+  
+   If the most-significant of the 24 bits is set, this indicates a
+   very large product; the size has to be rescaled by a factor of 120.
+   This is a fixup to get round the GRIB code practice of representing
+   a product length by 24 bits. It is only possible because the
+   (default) rounding for GRIB products is 120 bytes.
+  
+*/
+    fortint fixlen;
+
+    fixlen = THREE_BYTE_LONG(phold+4);
+    if( fixlen <= 0x7fffff )
+      return fixlen;
+    else
+    {
+      fortint largeLen;
+      
+      unsigned long code = 0;
+      fixlen = (fixlen & 0x7fffff)*120;  /* first guess at length */
+     
+      num = fixlen;
+    
+      if( leng < num ) { /* -unsure - apparently test is given buffer is too small */
+        num = fixlen - 128;
+        numread = fileRead( hold + hsize, leng - hsize, stream);
+        if ( numread <= 0 ) {          /* eg. on END_OF_FILE */
+          *holdsize -= numread;
+          return *holdsize;
+        }
+        *holdsize = leng;
+        return (-fixlen);
+      }
+      else {
+		  fortint fileReadResult =0;
+        if ( hsize < num) { /* buffer is big enough */
+	  /* go to the estimate minus 128 bytes to look after the 7777*/
+          numread = fileRead( hold + hsize, num - hsize - 128, stream);
+
+          if ( numread <= 0 ) {          /* eg. on END_OF_FILE */
+            *holdsize -= numread;
+            return *holdsize;
+          }
+        	  /* search byte after byte for the 7777 in the stream and stop when found*/
+  		  do {
+		     if (num<numread) return MISPLACED_7777;
+		     fileReadResult = fileRead( hold + numread + hsize, 1, stream);
+		      
+		      if ( fileReadResult <= 0 ) {          /* eg. on END_OF_FILE ---should not happen*/
+ 		           *holdsize += numread;
+			   *holdsize -= fileReadResult;
+ 		           return *holdsize; /*returns the number of bytes actually read */
+ 		      }     
+ 		     numread += fileReadResult;
+ 		     code = ( (code << 8) + hold[hsize + numread-1] ) & 0xFFFFFFFF;
+		    } while ( code != CODE_7777 );
+          hsize = numread;
+        }
+        *holdsize = hsize;
+        largeLen = waveLength(hold);
+      }
+
+      num = largeLen;
+      *holdsize = num;
+      return num;
+    }
+
+  }
+
+  length = 24;		     /* GRIB + section 1 */
+
+/* Check for presence of sections 2 and 3
+*/
+  section2 = ( hold[7] & WMOBIT8 ) ;
+  section3 = ( hold[7] & WMOBIT7 ) ;
+
+/* Add up all lengths of sections
+*/
+  return lentotal(hold, holdsize, leng, length, section2, section3, 
+                    fileRead, stream);
+
+}
+
+
+static fortint lentotal(char *hold, fortint *holdsize, fortint leng, fortint length,
+                     fortint section2, fortint section3,
+                     fortint (*fileRead)(), void *stream)
+/*
+//  Returns the total length in bytes of all sections of the GRIB product.
+//
+//  hold = buffer to hold product,
+//  leng = length of buffer,
+//  holdsize = number of bytes of the product in the hold buffer.
+//             Note that this increases if necessary as more bytes
+//             are read.
+//  length = length of (section 0 + section 1).
+//  section2 is TRUE if section 2 is present in the product.
+//  section3 is TRUE if section 3 is present in the product.
+//  fileRead = function used to read the product,
+//  stream = data describing the input stream (eg. FILE *).
+*/
+{
+fortint numread, hsize = *holdsize;
+unsigned char * phold = (unsigned char *) hold;
+fortint next, next_sec = 4;
+
+/* Adjust count of sections to check
+*/
+  if ( section2 ) next_sec--;
+  if ( section3 ) next_sec--;
+
+/* Get the size of the next section
+*/
+  if ( leng < length ) return USER_BUFFER_TINY;
+  if ( hsize < length) {
+    numread = fileRead( hold + hsize, length - hsize, stream);
+    if ( numread <= 0 ) {        /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = length;
+  } 
+  *holdsize = hsize;
+
+/* Get the size of remaining sections
+*/
+  for ( next = next_sec; next < 5 ; next++ ) {
+    if ( leng < (length+4) ) return USER_BUFFER_TINY;
+    if ( hsize < (length+4)) {
+      numread = fileRead( hold+hsize, (length+4)-hsize, stream);
+      if ( numread <= 0 ) {    /* eg. on END_OF_FILE */
+        *holdsize -= numread;
+        return *holdsize;
+      }
+      hsize = length + 4;
+    } 
+    *holdsize = hsize;
+    length += THREE_BYTE_LONG(phold+length);
+  }
+
+/* Add on the size of section 5
+*/
+  length += LEN_7777;
+
+  return length;
+}
+
+
+static fortint bufrsize(char * hold, fortint leng, fortint * holdsize,
+                     fortint (*fileRead)(), void * stream)
+/*
+//  Returns the size in bytes of the BUFR code product.
+//
+//  hold = buffer to hold product,
+//  leng = length of buffer,
+//  holdsize = number of bytes of the product in the hold buffer.
+//         Note that this increases if necessary as more bytes are read.
+//  fileRead = function used to read the product,
+//  stream = data describing the input stream (eg. FILE *).
+*/
+{
+unsigned char * phold = (unsigned char *) hold;
+fortint numread, hsize = *holdsize;
+fortint num, length;
+fortint next, next_sec = 3;
+
+
+/* Need more bytes to decide on which version of BUFR
+*/
+  if ( leng < 24 ) return USER_BUFFER_TINY;
+  num = 24;                        /* put first 24 bytes in buffer*/
+  if ( hsize < num) {
+    numread = fileRead( hold + hsize, num - hsize, stream);
+    if ( numread <= 0 ) {        /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = num;
+  }
+  *holdsize = hsize;
+
+/* If it's Edition 2, or later, octets 5-7 give full product size
+*/
+  if ( hold[7] > 1 ) return THREE_BYTE_LONG(phold+4);
+
+/* Otherwise, we have to step through the individual sections
+   adding up the lengths
+*/
+
+/* Add on the length of section 1 and ensure enough of product is in 
+   memory to continue
+*/
+  length = SECT_0_LEN + THREE_BYTE_LONG(phold+4);
+  if ( leng < (length+4) ) return USER_BUFFER_TINY;
+  if ( hsize < (length+4)) {
+    numread = fileRead( hold+hsize, (length+4)-hsize, stream);
+    if ( numread <= 0 ) {        /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = length + 4;
+    *holdsize = hsize;
+  } 
+
+/* Check for presence of section 2
+*/
+  if ( hold[11] & WMOBIT1 ) next_sec = 2;
+
+/* Get the size of remaining sections
+*/
+  for ( next = next_sec; next < 5 ; next++ ) {
+    length += THREE_BYTE_LONG(phold+length);
+    if ( leng < (length+4) ) return USER_BUFFER_TINY;
+    if ( hsize < (length+4)) {
+      numread = fileRead( hold+hsize,(length+4)-hsize, stream);
+      if ( numread <= 0 ) {    /* eg. on END_OF_FILE */
+        *holdsize -= numread;
+        return *holdsize;
+      }
+      hsize = length + 4;
+      *holdsize = hsize;
+    } 
+  }
+
+/* Add on the size of section 5
+*/
+  length += LEN_7777;
+  if ( leng < length ) return USER_BUFFER_TINY;
+
+  return length;
+
+}
+
+static fortint tide_budg_size(char * hold, fortint leng, fortint * holdsize,
+                           fortint (*fileRead)(), void * stream)
+/*
+//  Returns the size in bytes of the TIDE/BUDG/DIAG code product.
+//
+//  hold = buffer to hold product,
+//  leng = length of buffer,
+//  holdsize = number of bytes of the product in the hold buffer.
+//             Note that this increases if necessary as more bytes are read.
+//  fileRead = function used to read the product,
+//  stream = data describing the input stream (eg. FILE *).
+*/
+{
+unsigned char * phold = (unsigned char *) hold;
+fortint numread, hsize = *holdsize;
+fortint num, length;
+
+/* Need more bytes to get length of section 1
+*/
+  num = 8;                        /* put first 8 bytes in buffer */
+  if ( leng < num ) return USER_BUFFER_TINY;
+  if ( hsize < num) {
+    numread = fileRead( hold + hsize, num - hsize, stream);
+    if ( numread <= 0 ) {       /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = num;
+  }
+  *holdsize = hsize;
+
+/* Have to step through individual sections adding up the lengths
+*/
+
+/* Add on the length of section 1 and ensure enough of product is in 
+   memory to continue
+*/
+  length = SECT_0_LEN + THREE_BYTE_LONG(phold+4);
+  if ( leng < (length+4) ) return USER_BUFFER_TINY;
+  if ( hsize < (length+4)) {
+    numread = fileRead( hold+hsize, (length+4)-hsize, stream);
+    if ( numread <= 0 ) {        /* eg. on END_OF_FILE */
+      *holdsize -= numread;
+      return *holdsize;
+    }
+    hsize = length + 4;
+    *holdsize = hsize;
+  } 
+
+/* Get the size of remaining section
+*/
+  length += THREE_BYTE_LONG(phold+length);
+
+/* Add on the size of section 5
+*/
+  length += LEN_7777;
+
+  if ( leng < length ) return USER_BUFFER_TINY;
+  return length;
+}
+
+static fortint prodsize(fortint code, char * hold, fortint leng, fortint * holdsize, 
+                     fortint (*fileRead)(), void * stream)
+/*
+//  Returns size of BUFR, GRIB, BUDG, TIDE, DIAG product in bytes.
+//
+//  hold = buffer holding product,
+//  leng = size of buffer in bytes,
+//  holdsize = number of bytes of product already read into hold.
+//  fileRead = function used to read the product,
+//  stream = data describing the input stream (eg. FILE *).
+*/
+{
+long lcode = code;
+
+  *holdsize = 4;
+  switch( lcode ) 
+  {
+     case BUFR: memcpy(hold,"BUFR",4);
+                return bufrsize( hold, leng, holdsize, fileRead, stream);
+
+     case BUDG: memcpy(hold,"BUDG",4);
+                return tide_budg_size( hold, leng, holdsize, fileRead, stream);
+
+     case GRIB: memcpy(hold,"GRIB",4);
+                return gribsize( hold, leng, holdsize, fileRead, stream);
+
+     case TIDE: memcpy(hold,"TIDE",4);
+                return tide_budg_size( hold, leng, holdsize, fileRead, stream);
+
+     case DIAG: memcpy(hold,"DIAG",4);
+                return tide_budg_size( hold, leng, holdsize, fileRead, stream);
+
+     case CREX: memcpy(hold,"CREX",4);
+                return crex_size( stream);
+
+     default: return 0;
+    }
+}
+
+
+#define BIT1 0x80
+#define BIT2 0x40
+
+static fortint waveLength(char * buffer)
+{
+/*
+//  On entry, buffer contains a GRIB edition 1 product (somewhere).
+//
+//  The value returned is the length of the GRIB product calculated
+//  from the individual lengths of sections 0, 1, 2, 3, 4 and 5;
+//  sections 2 and 3 are optional and may or may not be present.
+//
+//  If there is a problem processing the product, or if GRIB edition
+//  -1 or 0 is encountered, the return value is -1.
+*/
+int found = 0;
+int code = 0;
+long bytes_read = 0, advance;
+char p, edit_num, flag23;
+char size[3];
+int section0 = 8, section1, section2, section3, section4, section5 = 4;
+long total;
+long s0;
+
+/*  Read bytes until "GRIB" found */
+
+    do
+    {
+        if( grab(buffer, &p, 1, 1, &bytes_read) != 0) return (-1);
+        code = ( (code << 8) + p ) & 0xFFFFFFFF;
+        if (code == GRIB ) found = 1;
+    } while ( ! found );
+    s0 = bytes_read - 4;
+    bytes_read = 4;
+
+    if( grab(buffer, size, 3, 1, &bytes_read) != 0) return (-1);
+    total = THREE_BYTE_LONG(size);
+
+    if( total > 0x800000 ) {
+        total = (total&0x7fffff) * 120;
+    }
+
+/*  Check the edition number */
+
+    if( grab(buffer, &edit_num, 1, 1, &bytes_read) != 0) return (-1);
+    if( edit_num != 1 ) {
+      printf("Cannot handle GRIB edition 0\n");
+      return (-1);
+    }                             /* reject edition 0 */
+
+    if( (*(buffer+21-s0) == '\0') && (*(buffer+22-s0) == '\0') ) {
+      printf("Cannot handle GRIB edition -1\n");
+      return (-1);
+    }                             /* reject edition -1 */
+
+/*  Read length of section 1 */
+    if( grab(buffer, size, 3, 1, &bytes_read) != 0) return (-1);
+    section1 = THREE_BYTE_LONG(size);
+
+/*  Now figure out if sections 2/3 are present */
+
+    advance = 4;
+    bytes_read += advance;
+    if( grab(buffer, &flag23, 1, 1, &bytes_read) != 0) return (-1);
+    section2 = flag23 & BIT1;
+    section3 = flag23 & BIT2;
+
+/*  Advance to end of section 1 */
+
+    advance = section1 - (bytes_read - section0);
+    bytes_read += advance;
+
+/*  Read section 2 length if it is given*/
+
+    if( section2 )
+    {
+        if( grab(buffer, size, 3, 1, &bytes_read) != 0) return (-1);
+        section2 = THREE_BYTE_LONG(size);
+        advance = section2 - (bytes_read - section0 - section1);
+        bytes_read += advance;
+    }
+
+/*  Read section 3 length if it is given*/
+
+    if( section3 )
+    {
+        if( grab(buffer, size, 3, 1, &bytes_read) != 0) return (-1);
+        section3 = THREE_BYTE_LONG(size);
+        advance = section3 - (bytes_read - section0 - section1 - section2);
+        bytes_read += advance;
+    }
+
+/*  Read section 4 length */
+
+    if( grab(buffer, size, 3, 1, &bytes_read) != 0) return (-1);
+    section4 = total + 3 - bytes_read - THREE_BYTE_LONG(size);
+
+    return (section0+section1+section2+section3+section4+section5);
+}
+
+static int grab(char * buffer, char * where, long size,long cnt,long * num_bytes_read)
+{
+long number = size*cnt;
+
+    memcpy(where, (buffer+(*num_bytes_read)), number);
+    *num_bytes_read += number;
+
+    return 0;
+}
+
+
+#define BUFFLEN 1000
+
+static fortint crex_size( void * stream) {
+/*
+//  Returns the size in bytes of the TIDE/BUDG/DIAG code product.
+//
+//  stream = data describing the input stream (eg. FILE *).
+*/
+char buffer[BUFFLEN];
+int startPosition, inBuffer;
+char * next, * endBuffer;
+char plplcrcrlf7777[10] = {0,0,0,0,0,0,0,0,0,0};
+char PlPlCrCrLf7777[10] = {0x2b,0x2b,0x0d,0x0d,0x0a,0x37,0x37,0x37,0x37,0x00};
+int endFound, loop, status, size = 0;
+int size7777 = sizeof(PlPlCrCrLf7777) - 1;
+
+/*
+// Record current file position
+*/
+  startPosition = fileTell((FILE *) stream);
+  if( startPosition < 0 ) {
+    perror("crex_size: error recording current file position.");
+    exit(1);
+  }
+/*
+// Read some bytes to start with
+*/
+  inBuffer = fileRead(buffer, BUFFLEN, (FILE *) stream);
+  if( ferror((FILE *) stream) ) {
+    perror("crex_size: file read error");
+    exit(1);
+  }
+  next = buffer;
+  endBuffer = next + abs(inBuffer);
+/*
+// Look for ++CrCrLf7777 at end of product
+*/
+  endFound = 0;
+  while( !endFound ) {
+    for( loop = 0; loop < 8; loop++ )
+      plplcrcrlf7777[loop] = *(next++);
+      plplcrcrlf7777[9] = '\0';
+
+    while( next<=endBuffer ) {
+      plplcrcrlf7777[8] = *(next++);
+      if( strcmp(plplcrcrlf7777,PlPlCrCrLf7777) == 0 ) {
+        endFound = 1;
+/*
+//      Position file where it started
+*/
+        status = fileSeek(stream, startPosition, SEEK_SET);
+        if( status != 0 ) {
+          perror("crex_size: file repositioning error");
+          exit(1);
+        }
+        return ( (int) (next - buffer + size + 4) );
+      }
+
+      for( loop = 0; loop < 8; loop++ )
+        plplcrcrlf7777[loop] = plplcrcrlf7777[loop+1];
+    }
+
+    if( !endFound ) {
+      if( feof((FILE *) stream) ) {
+        printf("crex_size: end-of-file hit before end of CREX found\n");
+        exit(1);
+      }
+      else {
+        size += (BUFFLEN - size7777);
+        memmove(buffer, (buffer+(BUFFLEN-size7777)), size7777);
+        inBuffer = fileRead((buffer+size7777),
+                            (BUFFLEN-size7777),
+                            (FILE *) stream);
+        if( ferror((FILE *) stream) ) {
+          perror("crex_size: file read error");
+          exit(1);
+        }
+        if( inBuffer == 0 ) return 0;
+        next = buffer;
+        endBuffer = next + abs(inBuffer);
+      }
+    }
+  }
+
+/*
+// Position file where it started
+*/
+  status = fileSeek(stream, startPosition, SEEK_SET);
+  if( status != 0 ) {
+    perror("crex_size: file repositioning error");
+    exit(1);
+  }
+  return 0;
+}
diff --git a/odb/src/extras/emos/sizeRoutines.h b/odb/src/extras/emos/sizeRoutines.h
new file mode 100644
index 0000000..c70894d
--- /dev/null
+++ b/odb/src/extras/emos/sizeRoutines.h
@@ -0,0 +1,18 @@
+#ifndef SIZE_ROUTINES_H
+#define SIZE_ROUTINES_H
+
+static fortint prodsize(fortint, char *, fortint, fortint *,
+                        fortint (*fileRead)(), void *);
+static fortint gribsize(char * , fortint, fortint * , 
+                        fortint (*fileRead)(), void * );
+static fortint bufrsize(char * , fortint, fortint * , 
+                        fortint (*fileRead)(), void * );
+static fortint tide_budg_size(char *, fortint, fortint *,
+                        fortint (*fileRead)(), void *);
+static fortint lentotal(char *, fortint *, fortint, fortint , fortint ,
+                        fortint , fortint (*fileRead)(), void *);
+static fortint waveLength(char *);
+
+static fortint crex_size( void * );
+
+#endif /* end of  SIZE_ROUTINES_H */
diff --git a/odb/src/extras/ifsaux/CMakeLists.txt b/odb/src/extras/ifsaux/CMakeLists.txt
new file mode 100644
index 0000000..0aa33ed
--- /dev/null
+++ b/odb/src/extras/ifsaux/CMakeLists.txt
@@ -0,0 +1,129 @@
+
+list(APPEND _odb_ifsaux_includes
+
+    include/cargs.h
+    include/crc.h
+    include/dr_hook_util.h
+    include/dr_hook_util_multi.h
+    include/drhook.h
+    include/ecsort_shared.h
+    include/getstatm.h
+    include/intercept_alloc.h
+    include/raise.h
+    include/user_clock.h
+)
+
+list(APPEND _odb_ifsaux_sources
+
+    module/parkind1.F90
+    module/parkind2.F90
+    module/dr_hook_watch_mod.F90
+    module/ecsort_mix.F90
+    module/f90_unix_env.F90
+    module/f90_unix_io.F90
+    module/f90_unix_proc.F90
+    module/local_trafos.F90
+    module/mpi4to8.F90
+    module/mpi4to8_m.F90
+    module/mpi4to8_s.F90
+    module/mpl_abort_mod.F90
+    module/mpl_allgather_mod.F90
+    module/mpl_allgatherv_mod.F90
+    module/mpl_allreduce_mod.F90
+    module/mpl_alltoallv_mod.F90
+    module/mpl_arg_mod.F90
+    module/mpl_barrier_mod.F90
+    module/mpl_broadcast_mod.F90
+    module/mpl_buffer_method_mod.F90
+    module/mpl_close_mod.F90
+    module/mpl_comm_create_mod.F90
+    module/mpl_data_module.F90
+    module/mpl_end_mod.F90
+    module/mpl_gatherv_mod.F90
+    module/mpl_groups.F90
+    module/mpl_init_mod.F90
+    module/mpl_ioinit_mod.F90
+    module/mpl_locomm_create_mod.F90
+    module/mpl_message_mod.F90
+    module/mpl_module.F90
+    module/mpl_mpif.F90
+    module/mpl_mygatherv_mod.F90
+    module/mpl_myrank_mod.F90
+    module/mpl_nproc_mod.F90
+    module/mpl_open_mod.F90
+    module/mpl_probe_mod.F90
+    module/mpl_read_mod.F90
+    module/mpl_recv_mod.F90
+    module/mpl_scatterv_mod.F90
+    module/mpl_send_mod.F90
+    module/mpl_setdflt_comm_mod.F90
+    module/mpl_tour_table_mod.F90
+    module/mpl_wait_mod.F90
+    module/mpl_write_mod.F90
+    module/oml_mod.F90
+    module/sdl_mod.F90
+    module/strhandler_mod.F90
+    module/yomabrt.F90
+    module/yomerrtrap.F90
+    module/yomgstats.F90
+    module/yomhook.F90
+    module/yomhookstack.F90
+    module/yomlun_ifsaux.F90
+    module/yommpi.F90
+    parallel/cmpl_binding.F90
+    parallel/coml_binding.F90
+    support/abor1.F90
+    support/cargs.c
+    support/cdrhookinit.F90
+    support/clock.F
+    support/convin.F90
+    support/convout.F90
+    support/cptime.F
+    support/crc.c
+    support/dr_hook_procinfo.F90
+    support/dr_hook_prt.F90
+    support/dr_hook_util.F90
+    support/dr_hook_util_multi.F90
+    support/drhook.c
+    support/endian.c
+    support/env.c
+    support/gstats.F90
+    support/mpe_locking.c
+    support/my_sync.c
+    support/timef.F
+    support/user_clock.F90
+    utilities/addrdiff.c
+    utilities/countingsort.c
+    utilities/ecqsort.c
+    utilities/fnecsx.c
+    utilities/gentrbk.F90
+    utilities/get_max_threads.F90
+    utilities/get_num_threads.F90
+    utilities/get_thread_id.F90
+    utilities/getcurheap.c
+    utilities/getheapstat.F90
+    utilities/gethwm.c
+    utilities/getmemstat.F90
+    utilities/getmemvals.F90
+    utilities/getpag.c
+    utilities/getrss.c
+    utilities/getstackusage.c
+    utilities/getstatm.c
+    utilities/getstk.c
+    utilities/gnomesort.c
+    utilities/iusrcl.F
+    utilities/jsort.F
+    utilities/linuxtrbk.c
+    utilities/rsort32.c
+    utilities/rsort64.c
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+ecbuild_add_library(TARGET odbifsaux
+    TYPE ${ODB_LIBS_TYPE}
+    SOURCES ${_odb_ifsaux_sources}
+    PRIVATE_INCLUDES ${_ODB_MPI_INCLUDE_DIRS}
+    LIBS ${_ODB_MPI_LIBS} ${_ODB_EMOS_LIBS})
+
+install(FILES ${_odb_ifsaux_includes} DESTINATION include)
diff --git a/odb/src/extras/ifsaux/include/cargs.h b/odb/src/extras/ifsaux/include/cargs.h
new file mode 100644
index 0000000..13d82cf
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/cargs.h
@@ -0,0 +1,59 @@
+/* cargs.h */
+
+/* prototypes for ifsaux/support/cargs.c */
+
+/* Author: Sami Saarinen, ECMWF, 27-Apr-2006 */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void ec_PutArgs(int argc, char *argv[]);
+const char *ec_GetArgs(int argno);
+int ec_NumArgs(void);
+
+/* The following two as in C-main : "int main(int argc, char *argv[])" */
+
+int ec_argc(void);
+char **ec_argv(void);
+
+/* Fortran interface */
+
+int iargc_c_(void);
+int iargc_c (void);
+
+void getarg_c_(const int *argno, char *arg
+	       /* Hidden argument */
+	       , const int arg_len);
+
+void getarg_c (const int *argno, char *arg
+	       /* Hidden argument */
+	       , const int arg_len);
+
+void putarg_c_(const int *argno, const char *arg
+	       /* Hidden argument */
+	       , int arg_len);
+
+void putarg_c (const int *argno, const char *arg
+	       /* Hidden argument */
+	       , int arg_len);
+
+void putarg_info_(const int *argc, const char *cterm
+		  /* Hidden argument */
+		  , int cterm_len);
+
+void putarg_info (const int *argc, const char *cterm
+		  /* Hidden argument */
+		  , int cterm_len);
+
+/* From ifsaux/support/cmpl_binding.F90 */
+
+void cmpl_getarg_(const int *argno, char *arg
+		  /* Hidden argument */
+		  , const int arg_len);
+
+int cmpl_iargc_(); 
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/odb/src/extras/ifsaux/include/crc.h b/odb/src/extras/ifsaux/include/crc.h
new file mode 100644
index 0000000..0230189
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/crc.h
@@ -0,0 +1,35 @@
+/* crc.h */
+/* Calculates 32-bit  Cyclic Redundancy Check as in Unix cksum command */
+/* Also calculates 64-bit  Cyclic Redundancy Check */
+
+/* Sami Saarinen, 17-Feb-2005 : crc32       */
+/*                24-Jun-2005 : Added crc64 */
+/*                29-Dec-2005 : Added protos for direct C-calls */
+/*                29-Dec-2005 : Length argument for crc64 now 64-bit int */
+
+/* C callables */
+
+extern unsigned int 
+pp_cksum32(int nbuf, unsigned int nCRC);
+
+extern unsigned int 
+pp_cksum32but64len(long long int nbuf, unsigned int nCRC);
+
+extern unsigned long long int 
+pp_cksum64(long long int nbuf, unsigned long long int nCRC);
+
+extern unsigned int 
+cksum32(const char *buf, int nbuf, unsigned int nCRC);
+
+extern unsigned long long int
+cksum64(const char *buf, long long int nbuf, unsigned long long int nCRC);
+
+/* Fortran callable */
+
+extern void 
+crc32_(const void *vbuf, const int *pnbuf, 
+       unsigned int *pnCRC /* Note: An in & out -variable */);
+
+extern void 
+crc64_(const void *vbuf, const long long int *pnbuf, 
+       unsigned long long int *pnCRC /* Note: An in & out -variable */);
diff --git a/odb/src/extras/ifsaux/include/dr_hook_util.h b/odb/src/extras/ifsaux/include/dr_hook_util.h
new file mode 100644
index 0000000..b411bb5
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/dr_hook_util.h
@@ -0,0 +1,7 @@
+SUBROUTINE DR_HOOK_UTIL(CDNAME,KCASE,PKEY,CDFILENAME,KSIZEINFO)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+IMPLICIT NONE
+CHARACTER(LEN=*),INTENT(IN) :: CDNAME,CDFILENAME
+INTEGER(KIND=JPIM),INTENT(IN) :: KCASE,KSIZEINFO
+REAL(KIND=JPRB),INTENT(INOUT) :: PKEY
+END SUBROUTINE DR_HOOK_UTIL
diff --git a/odb/src/extras/ifsaux/include/dr_hook_util_multi.h b/odb/src/extras/ifsaux/include/dr_hook_util_multi.h
new file mode 100644
index 0000000..05bb6ab
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/dr_hook_util_multi.h
@@ -0,0 +1,7 @@
+SUBROUTINE DR_HOOK_UTIL_MULTI(CDNAME,KCASE,PKEY,KPKEY,CDFILENAME,KSIZEINFO)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+IMPLICIT NONE
+CHARACTER(LEN=*),INTENT(IN) :: CDNAME,CDFILENAME
+INTEGER(KIND=JPIM),INTENT(IN) :: KPKEY, KCASE,KSIZEINFO
+REAL(KIND=JPRB),INTENT(INOUT) :: PKEY(KPKEY)
+END SUBROUTINE DR_HOOK_UTIL_MULTI
diff --git a/odb/src/extras/ifsaux/include/drhook.h b/odb/src/extras/ifsaux/include/drhook.h
new file mode 100644
index 0000000..889085f
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/drhook.h
@@ -0,0 +1,175 @@
+#ifndef _DRHOOK_H_
+#define _DRHOOK_H_
+
+#ifdef _DRHOOK_C_
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <math.h>
+
+#ifdef RS6K
+#include <fptrap.h>
+#endif
+
+#ifdef VPP
+#include <ucontext.h>
+#endif
+
+int drhook_lhook = 1;
+#else
+extern int drhook_lhook;
+#endif
+
+#ifndef O_LOCK_DONE
+#define O_LOCK_DONE
+
+/* OpenMP/ODB lock type */
+/* Keep consistent with "odb/include/privpub.h" */
+/* Be ALSO consistent with OML_LOCK_KIND in ifsaux/module/oml_mod.F90 */
+
+typedef long long int o_lock_t; /* i.e. 64-bit integer */
+
+#define INIT_LOCKID_WITH_NAME(mylock, lockname) \
+  coml_init_lockid_with_name_(mylock, lockname, strlen(lockname))
+
+extern void coml_set_debug_(const int *konoff, int *kret);
+extern void coml_init_lock_();
+extern void coml_init_lockid_(o_lock_t *mylock);
+extern void coml_init_lockid_with_name_(o_lock_t *mylock, const char *name, int name_len);
+extern void coml_set_lock_();
+extern void coml_set_lockid_(o_lock_t *mylock);
+extern void coml_unset_lock_();
+extern void coml_unset_lockid_(o_lock_t *mylock);
+extern void coml_test_lock_(int *is_set);
+extern void coml_test_lockid_(int *is_set, o_lock_t *mylock);
+extern void coml_in_parallel_(int *is_parallel_region);
+
+#endif
+
+/* drhook.c external interfaces */
+
+extern void
+c_drhook_getenv_(const char *s,
+                 char *value,
+                 /* Hidden arguments */
+                 int slen,
+                 const int valuelen);
+
+extern void
+c_drhook_memcounter_(const int *thread_id,
+                     const long long int *size,
+                     long long int *keyptr_addr);
+
+extern void
+c_drhook_raise_(const int *sig);
+
+extern void
+c_drhook_print_(const int *ftnunitno,
+                const int *thread_id,
+                const int *print_option, /* 
+                                            1=raw call counts 
+                                            2=calling tree
+                                            3=profiling info
+                                         */
+                int *level);
+
+extern void
+c_drhook_init_signals_(const int *enforce);
+
+extern void
+c_drhook_set_lhook_(const int *lhook);
+
+extern void 
+c_drhook_init_(const char *progname,
+               const int *num_threads
+               /* Hidden length */
+               ,int progname_len);
+
+extern void
+c_drhook_start_(const char *name, 
+                const int *thread_id, 
+                double *key,
+                const char *filename,
+                const int *sizeinfo
+                /* Hidden length */
+                ,int name_len, int filename_len);
+
+extern void
+c_drhook_end_(const char *name,
+              const int *thread_id,
+              const double *key,
+              const char *filename,
+              const int *sizeinfo
+              /* Hidden length */
+              ,int name_len, int filename_len);
+
+extern void
+c_drhook_watch_(const int *onoff,
+                const char *array_name,
+                const void *array_ptr,
+                const int *nbytes,
+                const int *abort_if_changed
+                /* Hidden length */
+                , int array_name_len);
+
+/**** C-interface to Dr.Hook ****/
+
+extern void
+Dr_Hook(const char *name, int option, double *handle, 
+        const char *filename, int sizeinfo,
+        int name_len, int filename_len);
+
+#define DRHOOK_START_RECUR(name,recur) \
+  static const char *drhook_name = #name; \
+  static const int drhook_name_len = sizeof(#name) - 1; /* Compile time eval */ \
+  static const char *drhook_filename = __FILE__; \
+  static const int drhook_filename_len = sizeof(__FILE__) - 1; /* Compile time eval */ \
+  double zhook_handle; \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 0, &zhook_handle, \
+                                      drhook_filename, 0, \
+                                      drhook_name_len, drhook_filename_len); {
+
+#define DRHOOK_START(name) DRHOOK_START_RECUR(name,0)
+
+#define DRHOOK_START_BY_STRING_RECUR(name, recur) \
+  static const char *drhook_name = name; \
+  static const int drhook_name_len = sizeof(name) - 1; /* Compile time eval */ \
+  static const char *drhook_filename = __FILE__; \
+  static const int drhook_filename_len = sizeof(__FILE__) - 1; /* Compile time eval */ \
+  double zhook_handle; \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 0, &zhook_handle, \
+                                      drhook_filename, 0, \
+                                      drhook_name_len, drhook_filename_len); {
+
+#define DRHOOK_START_BY_STRING(name) DRHOOK_START_BY_STRING_RECUR(name,0)
+
+#define DRHOOK_RETURN_RECUR(sizeinfo,recur) \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 1, &zhook_handle, \
+                                      drhook_filename, sizeinfo, \
+                                      drhook_name_len, drhook_filename_len)
+
+#define DRHOOK_RETURN(sizeinfo) DRHOOK_RETURN_RECUR(sizeinfo,0)
+
+#define DRHOOK_END_RECUR(sizeinfo,recur) ; } DRHOOK_RETURN_RECUR(sizeinfo,recur)
+
+#define DRHOOK_END(sizeinfo) DRHOOK_END_RECUR(sizeinfo,0) 
+
+/* Fortran routines */
+
+extern void
+dr_hook_prt_(const int *ftnunitno,
+             const char *s
+             /* Hidden arguments */
+             , int s_len);
+
+extern void
+dr_hook_procinfo_(int *myproc, int *nproc);
+
+#endif  /* _DRHOOK_H_ */
diff --git a/odb/src/extras/ifsaux/include/ecsort_shared.h b/odb/src/extras/ifsaux/include/ecsort_shared.h
new file mode 100644
index 0000000..6539521
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/ecsort_shared.h
@@ -0,0 +1,681 @@
+!*** ecsort_shared.h ***
+
+#if INT_VERSION == 4
+
+#define DATA_TYPE            INTEGER(KIND=JPIM)
+#define SIZEOF_ME            sizeof_int4
+#define KEYSORT_1D           INT4_KEYSORT_1D
+#define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:INT4_KEYSORT_1D'
+#define KEYSORT_2D           INT4_KEYSORT_2D
+#define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:INT4_KEYSORT_2D'
+#define KEYSORT_NUMBER       11
+#define RSORT_DRHOOKSTR      'ECSORT_MIX:RSORT32_FUNC_11'
+#define USE_RSORT64          0
+#define HEAPSORT             INT4_HEAPSORT
+#define HEAPSORT_DRHOOKSTR   'ECSORT_MIX:INT4_HEAPSORT'
+#define DBGPRINT             INT4_DBGPRINT
+#define DBGFMTNUM            1011
+#define ECQSORT_DRHOOKSTR    'ECSORT_MIX:INT4_ECQSORT'
+#define COUNT_DRHOOKSTR      'ECSORT_MIX:INT4_COUNT'
+#define GNOME_DRHOOKSTR      'ECSORT_MIX:INT4_GNOME'
+
+#elif REAL_VERSION == 8
+
+#define DATA_TYPE            REAL(KIND=JPRB)
+#define SIZEOF_ME            sizeof_real8
+#define KEYSORT_1D           REAL8_KEYSORT_1D
+#define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:REAL8_KEYSORT_1D'
+#define KEYSORT_2D           REAL8_KEYSORT_2D
+#define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:REAL8_KEYSORT_2D'
+#define KEYSORT_NUMBER       12
+#define RSORT_DRHOOKSTR      'ECSORT_MIX:RSORT64_12'
+#define USE_RSORT64          1
+#define HEAPSORT             REAL8_HEAPSORT
+#define HEAPSORT_DRHOOKSTR   'ECSORT_MIX:REAL8_HEAPSORT'
+#define DBGPRINT             REAL8_DBGPRINT
+#define DBGFMTNUM            1012
+#define ECQSORT_DRHOOKSTR    'ECSORT_MIX:REAL8_ECQSORT'
+#define COUNT_DRHOOKSTR      'ECSORT_MIX:REAL8_COUNT'
+#define GNOME_DRHOOKSTR      'ECSORT_MIX:REAL8_GNOME'
+
+#elif REAL_VERSION == 4
+
+#define DATA_TYPE            REAL(KIND=JPRM)
+#define SIZEOF_ME            sizeof_real4
+#define KEYSORT_1D           REAL4_KEYSORT_1D
+#define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:REAL4_KEYSORT_1D'
+#define KEYSORT_2D           REAL4_KEYSORT_2D
+#define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:REAL4_KEYSORT_2D'
+#define KEYSORT_NUMBER       13
+#define RSORT_DRHOOKSTR      'ECSORT_MIX:RSORT32_FUNC_13'
+#define USE_RSORT64          0
+#define HEAPSORT             REAL4_HEAPSORT
+#define HEAPSORT_DRHOOKSTR   'ECSORT_MIX:REAL4_HEAPSORT'
+#define DBGPRINT             REAL4_DBGPRINT
+#define DBGFMTNUM            1013
+#define ECQSORT_DRHOOKSTR    'ECSORT_MIX:REAL4_ECQSORT'
+#define COUNT_DRHOOKSTR      'ECSORT_MIX:REAL4_COUNT'
+#define GNOME_DRHOOKSTR      'ECSORT_MIX:REAL4_GNOME'
+
+#elif INT_VERSION == 8
+
+#define DATA_TYPE            INTEGER(KIND=JPIB)
+#define SIZEOF_ME            sizeof_int8
+#define KEYSORT_1D           INT8_KEYSORT_1D
+#define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:INT8_KEYSORT_1D'
+#define KEYSORT_2D           INT8_KEYSORT_2D
+#define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:INT8_KEYSORT_2D'
+#define KEYSORT_NUMBER       14
+#define RSORT_DRHOOKSTR      'ECSORT_MIX:RSORT64_14'
+#define USE_RSORT64          1
+#define HEAPSORT             INT8_HEAPSORT
+#define HEAPSORT_DRHOOKSTR   'ECSORT_MIX:INT8_HEAPSORT'
+#define DBGPRINT             INT8_DBGPRINT
+#define DBGFMTNUM            1014
+#define ECQSORT_DRHOOKSTR    'ECSORT_MIX:INT8_ECQSORT'
+#define COUNT_DRHOOKSTR      'ECSORT_MIX:INT8_COUNT'
+#define GNOME_DRHOOKSTR      'ECSORT_MIX:INT8_GNOME'
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+!----------------------------
+!--   Public subroutines   --
+!----------------------------
+
+
+SUBROUTINE KEYSORT_1D(rc, a, n, method, descending, index, init)
+!-- Please note that we assume that a(:) occupies consecutive memory locations
+INTEGER(KIND=JPIM), intent(out)           :: rc
+DATA_TYPE         , intent(inout)         :: a(:)
+INTEGER(KIND=JPIM), intent(in)            :: n
+INTEGER(KIND=JPIM), intent(in), OPTIONAL  :: method
+logical, intent(in), OPTIONAL  :: descending
+INTEGER(KIND=JPIM), intent(inout), TARGET, OPTIONAL :: index(:)
+logical, intent(in), OPTIONAL  :: init
+! === END OF INTERFACE BLOCK ===
+DATA_TYPE          , allocatable :: aa(:,:)
+INTEGER(KIND=JPIM) :: imethod, irev, idummy, index_adj
+logical :: LLfast, LLdescending, LLomp_okay, LLinit
+INTEGER(KIND=JPIM) :: ITID, ichunk, iret, inumt
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK(KEYSORT_1D_DRHOOKSTR,0,ZHOOK_HANDLE)
+
+rc = 0
+if (n <= 0 .or. size(a) <= 0) goto 99
+
+if (present(descending)) then
+  LLdescending = descending
+else
+  LLdescending = .FALSE.
+endif
+
+irev = 0
+if (LLdescending) irev = 1
+
+ITID = OML_MY_THREAD()
+imethod = current_method(ITID)
+if (present(method)) then
+  imethod = min(max(min_method,method),max_method)
+endif
+
+if (imethod /= quicksort_method .and. &
+   &imethod /= countingsort_method) then
+  LLfast = .FALSE.
+else if (imethod == quicksort_method) then
+  !-- hasn't been implemented if index is present ;-(
+  LLfast = (&
+       & .not.present(index) .and. &
+       & .not.present(init))
+else if (imethod == countingsort_method) then
+  !-- index-presence is ok
+  LLfast = .TRUE.
+endif
+
+if (LLfast) then
+  !- Only Quick-sort & CountingSort covered
+
+  if (imethod == quicksort_method) then
+    inumt = OML_MAX_THREADS()
+    LLomp_okay = (inumt > 1 .and. nomp >= inumt .and. n >= nomp)
+    LLomp_okay = (LLomp_okay .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
+    if (LLomp_okay) then
+      !-- Max 2-way OpenMP parallelism for now ...
+      ichunk = n/2
+!$OMP PARALLEL PRIVATE(iret)
+!$OMP SECTIONS
+!$OMP SECTION
+      CALL ecqsortfast(KEYSORT_NUMBER, ichunk, a(1), irev, iret)
+!$OMP SECTION
+      CALL ecqsortfast(KEYSORT_NUMBER, n-ichunk, a(ichunk+1), irev, iret)
+!$OMP END SECTIONS
+!$OMP END PARALLEL
+      CALL ecmerge2(KEYSORT_NUMBER, 1, ichunk, n-ichunk, a(1), &
+           & idummy, 0, 1, irev, idummy, rc)
+    else
+      CALL ecqsortfast(KEYSORT_NUMBER, n, a(1), irev, rc)
+    endif
+    GOTO 99
+
+  else if (imethod == countingsort_method) then
+    if (.not.present(index)) then
+      CALL ec_countingsort(KEYSORT_NUMBER, n, 1, 1, a(1), idummy, 0, 1, irev, rc)
+    else
+      LLinit = .FALSE.
+      if (present(init)) LLinit = init
+      if (LLinit) then
+        CALL init_index(index, index_adj=-1)
+        index_adj = 0
+      else
+        index_adj = 1
+      endif
+      CALL ec_countingsort(KEYSORT_NUMBER, n, 1, 1, a(1), index(1), size(index), index_adj, irev, rc)
+      if (index_adj == 0) CALL adjust_index(index, +1)
+    endif
+    GOTO 99
+
+  else
+    LLfast = .false.
+  endif
+endif
+
+!-- LLfast == .FALSE. :
+
+allocate(aa(n,1))
+
+if (LLdescending) then
+  aa(1:n,1) = -a(1:n)
+else
+  aa(1:n,1) = a(1:n)
+endif
+
+CALL keysort(rc, aa, n, method=method, index=index, init=init)
+
+if (LLdescending) then
+  a(1:n) = -aa(1:n,1)
+else
+  a(1:n) = aa(1:n,1)
+endif
+
+deallocate(aa)
+
+99 continue
+IF (LHOOK) CALL DR_HOOK(KEYSORT_1D_DRHOOKSTR,1,ZHOOK_HANDLE,n)
+END SUBROUTINE
+
+
+SUBROUTINE KEYSORT_2D(&
+     &rc, a, n,&
+     &key, multikey, method,&
+     &index, init, transposed)
+
+INTEGER(KIND=JPIM), intent(out)           :: rc
+DATA_TYPE         , intent(inout)         :: a(:,:)
+INTEGER(KIND=JPIM), intent(in)            :: n
+INTEGER(KIND=JPIM), intent(in), OPTIONAL  :: key, method
+INTEGER(KIND=JPIM), intent(in), OPTIONAL  :: multikey(:)
+logical, intent(in), OPTIONAL  :: transposed
+INTEGER(KIND=JPIM), intent(inout), TARGET, OPTIONAL :: index(:)
+logical, intent(in), OPTIONAL  :: init
+! === END OF INTERFACE BLOCK ===
+INTEGER(KIND=JPIM), POINTER :: iindex(:)
+INTEGER(KIND=JPIM) :: ikey, istride, imethod, inumkeys, imethod_1st, imethod_rest
+INTEGER(KIND=JPIM) :: lda, iptr, i, j, sda, idiff, irev, inumt, jkey, jj, ilastkey
+INTEGER(KIND=JPIM) :: j1, j2, jmid, inum, imax, iadd, imod, iret, inc, iamax, ibmax
+DATA_TYPE         , allocatable :: data(:)
+INTEGER(KIND=JPIM), allocatable :: ikeys(:), ista(:), ichunk(:), irank(:)
+logical LLinit, LLdescending, LLtrans, LLomp_okay, LLadjusted, LLdebug, LLomp_prefix
+character(len=1) clenv
+REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_SUBHANDLE
+REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE0
+REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE1
+REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE2
+REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE3
+INTEGER(KIND=JPIM) :: ITID
+
+IF (LHOOK) CALL DR_HOOK(KEYSORT_2D_DRHOOKSTR,0,ZHOOK_HANDLE)
+
+rc = 0
+lda = size(a, dim=1)
+sda = size(a, dim=2)
+if (n <= 0 .or. lda <= 0 .or. sda <= 0) goto 99
+
+inumt = OML_MAX_THREADS()
+ITID = OML_MY_THREAD()
+imethod = current_method(ITID)
+if (present(method)) then
+  imethod = min(max(min_method,method),max_method)
+endif
+imethod_1st = imethod
+imethod_rest = imethod
+
+ikey = 1
+if (present(key)) ikey = key
+
+if (present(multikey)) then
+  allocate(ikeys(size(multikey)))
+  ikeys(:) = multikey(:)
+else
+  allocate(ikeys(1))
+  ikeys(1) = ikey
+endif
+inumkeys = size(ikeys)
+
+!-- Only the RADIX-sort & now also QUICK-sort & CountingSort give the result we want with multiple keys
+if (inumkeys > 1 .and. &
+    imethod /= radixsort_method .and. &
+    imethod /= quicksort_method .and. &
+    imethod /= countingsort_method) then
+   imethod = default_method
+   imethod_1st = imethod
+   imethod_rest = imethod
+   !-- Since "default_method" may now be [overridden as] HEAP-sort, make sure its then "radixsort_method"
+   !   Note: The first sweep may still be e.g. HEAP-sort
+   if (imethod /= radixsort_method .and. &
+       imethod /= quicksort_method .and. &
+       imethod /= countingsort_method) then
+     imethod = radixsort_method
+     imethod_rest = imethod
+   endif
+endif
+
+LLinit = .FALSE.
+if (present(init)) LLinit = init
+
+if (present(index)) then
+  iindex => index(1:n)
+else
+  allocate(iindex(n))
+  LLinit = .TRUE.
+endif
+
+if (LLinit) CALL init_index(iindex)
+
+istride = 1
+LLtrans = .FALSE.
+if (present(transposed)) LLtrans = transposed
+if (LLtrans) then
+  istride = lda
+else if (sda >= 2 .and. lda >= 1) then
+!-- Check for presence of sub-array and adjust lda automatically
+  call addrdiff(a(1,1),a(1,2),idiff)
+  ! lda below: The true leading dimension; overrides sub-arrays one
+  lda = idiff/SIZEOF_ME
+endif
+
+ilastkey = 0
+LLadjusted = .FALSE.
+LLomp_prefix = .FALSE.
+!$ LLomp_prefix = (istride == 1 .and. nomp >= inumt .and. n >= nomp)
+if (LLomp_prefix) then
+  call ec_getenv('EC_SORTING_DEBUG',clenv)
+  LLdebug = (clenv == '1' .and. n < 10000)
+  if (LLdebug) write(0,*)'>> EC_SORTING_DEBUG=1'
+else
+  LLdebug = .FALSE.
+endif
+
+1000 format(1x,a,2i12,:,/,(10i5))
+1001 format(1x,'[#',i2,']:',a,(10i5))
+1002 format(1x,'[#',i2,']:',a,:,/,(10i5))
+1003 format(1x,'[#',i2,']:',a,2i12,:,/,(10i5))
+1004 format(1x,a,:,(10i5))
+1005 format(1x,a,i2,1x,a)
+
+imethod = imethod_1st
+KEYLOOP: do jkey=inumkeys,1,-1
+!--   Sort by the least significant key first
+  ikey = abs(ikeys(jkey))
+  if (ikey == 0) cycle KEYLOOP
+
+  if (istride == 1) then
+    iptr = lda * (ikey - 1) + 1
+  else
+    iptr = ikey
+  endif
+
+  if (LLdebug) then
+    write(0,1000) '<BEGIN>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
+    if (LLadjusted) then
+      CALL DBGPRINT(-jkey,'<BEGIN>',a,iindex,n,ikey,1,n,1)
+    else
+      CALL DBGPRINT(-jkey,'<BEGIN>',a,iindex,n,ikey,1,n,0)
+    endif
+    ilastkey = ikey
+  endif
+
+  LLdescending = (ikeys(jkey) < 0)
+  irev = 0
+  if (LLdescending) irev = 1
+
+  !-- Since "irev" is passed into the ecqsort, no explicit reversing is needed --> savings
+  if (imethod == quicksort_method .or. &
+      imethod == countingsort_method) LLdescending = .FALSE.
+
+  if (LLdescending) then
+    if (istride == 1) then
+      a(1:n,ikey) = -a(1:n,ikey)
+    else
+      a(ikey,1:n) = -a(ikey,1:n)
+    endif
+    irev = 0 ! prevents use of "reverse" algorithm in ecmerge2 for radix-sort
+  endif
+
+  LLomp_okay = LLomp_prefix .and. (inumt > 1) .and. (&
+       & imethod == radixsort_method .or. &
+       & imethod == quicksort_method .or. &
+       & imethod == countingsort_method)
+  LLomp_okay = LLomp_okay .and. (.not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
+
+  if (.not.LLomp_okay) then
+    select case (imethod)
+    case (radixsort_method)
+      IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
+#if USE_RSORT64 == 1
+      CALL rsort64(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, rc)
+#else
+      CALL rsort32_func(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, rc)
+#endif
+      IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0, n)
+    case (heapsort_method)
+      if (istride == 1) then
+        CALL HEAPSORT(KEYSORT_NUMBER, n, a(1:n, ikey), rc, irev, istride, iindex)
+      else
+        CALL HEAPSORT(KEYSORT_NUMBER, n, a(ikey, 1:n), rc, irev, istride, iindex)
+      endif
+    case (quicksort_method)
+      IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
+      CALL ecqsort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, irev, rc)
+      IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
+    case (countingsort_method)
+      IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
+      CALL ec_countingsort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), n, 1, irev, rc)
+      IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
+    case (gnomesort_method)
+      IF (LHOOK) CALL DR_HOOK(GNOME_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
+      CALL ecgnomesort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), n, 1, rc)
+      IF (LHOOK) CALL DR_HOOK(GNOME_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
+    end select
+
+  else ! i.e. LLomp_okay ; radix, quick & counting -sorts only
+    if (.not.allocated(ista)) then
+      allocate(ista(inumt+1),ichunk(inumt))
+      inc = n/inumt
+      iadd = 1
+      imod = mod(n,inumt)
+      if (imod == 0) iadd = 0
+      ista(1) = 1
+      do j=2,inumt
+        ista(j) = ista(j-1) + inc + iadd
+        if (iadd > 0 .and. j > imod) iadd = 0
+      enddo
+      ista(inumt+1) = n + 1
+      do j=1,inumt
+        ichunk(j) = ista(j+1) - ista(j)
+      enddo
+      if (LLdebug) then
+        write(0,1005) '>> imethod,name=',imethod,method_name(imethod)
+        write(0,1004) '>> inumt,n,nomp=',inumt,n,nomp
+        write(0,1004) '>> ista(1:inumt+1)=',ista(1:inumt+1)
+        write(0,1004) '>> ichunk(1:inumt)=',ichunk(1:inumt)
+      endif
+      allocate(irank(n))
+    endif
+
+    if (LLdebug) write(0,1004) '>>KEYLOOP: jkey,ikey,irev,iptr=',jkey,ikey,irev,iptr
+
+    if (.not.LLadjusted) then ! only once
+      if (LLdebug) write(0,1000) '<1>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
+      call adjust_index(iindex, -1) ! Fortran -> C
+      if (LLdebug) write(0,1000) '<2>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
+      LLadjusted = .TRUE.
+    endif
+
+    if (LLdebug) write(0,*)'>> Sorting inumt-chunks in parallel'
+!$OMP PARALLEL PRIVATE(j,j1,j2,inum,iret,inc,ITID,ZHOOK_SUBHANDLE1,ZHOOK_SUBHANDLE2)
+    IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPSORT',0,ZHOOK_SUBHANDLE1)
+    ITID = OML_MY_THREAD()
+!$OMP DO SCHEDULE(DYNAMIC,1)
+    do j=1,inumt
+      j1 = ista(j)
+      inum = ichunk(j)
+      j2 = j1 + inum - 1
+      inc = j1
+      if (LLdebug) write(0,1001) ITID,'j,j1,j2,inum,inc=',j,j1,j2,inum,inc
+      if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) > ',iindex(j1:j2)
+      select case (imethod)
+      case (radixsort_method)
+        IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
+#if USE_RSORT64 == 1
+        CALL rsort64(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, iret)
+#else
+        CALL rsort32_func(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, iret)
+#endif
+        IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2, inum)
+      case (quicksort_method)
+        IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
+        CALL ecqsort(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, irev, iret)
+        IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2,inum)
+      case (countingsort_method)
+        IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
+        CALL ec_countingsort(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), inum, 0, irev, iret)
+        IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2,inum)
+      end select
+      if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) < ',iindex(j1:j2)
+    enddo
+!$OMP END DO
+    IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPSORT',1,ZHOOK_SUBHANDLE1)
+!$OMP END PARALLEL
+
+    if (LLdebug) write(0,1000) '<after_sort>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
+    if (LLdebug) CALL DBGPRINT(0,'<after_sort>',a,iindex,n,ikey,1,n,1)
+    CALL get_rank(iindex, irank, index_adj=+1)
+
+    if (LLdebug) write(0,*) '>> Merge neighbouring chunks in parallel as much as possible'
+    inc = 2
+    imax = (inumt+inc-1)/inc
+    do jj=1,imax
+      if (LLdebug) write(0,1001) jj,'<before_merge> jj,inc,imax,inumt=',jj,inc,imax,inumt
+!$OMP PARALLEL PRIVATE(j,j1,j2,inum,iamax,ibmax,jmid,iret,ZHOOK_SUBHANDLE3,ITID)
+      IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPMERGE',0,ZHOOK_SUBHANDLE3)
+      ITID = OML_MY_THREAD()
+!$OMP DO SCHEDULE(DYNAMIC,1)
+      do j=1,inumt,inc
+        j1 = j
+        j2 = j + inc - 1
+        jmid = (j1 + j2)/2 + 1
+        j2 = min(j2,inumt)
+        jmid = min(jmid,inumt)
+        if (LLdebug) write(0,1001) ITID,'j,j1,j2,jmid=',j,j1,j2,jmid
+        iamax = ista(jmid) - ista(j1)
+        inum = sum(ichunk(j1:j2))
+        ibmax = inum - iamax
+        if (LLdebug) write(0,1001) ITID,'j,iamax,ibmax,inum=',j,iamax,ibmax,inum
+        if (iamax == 0 .or. ibmax == 0 .or. inum == 0) cycle
+        j1 = ista(j1)
+        j2 = ista(j2+1) - 1
+        if (LLdebug) write(0,1001) ITID,'j,j1,j2,inum=',j,j1,j2,inum
+        if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) > ',iindex(j1:j2)
+        call ecmerge2(KEYSORT_NUMBER, iptr, iamax, ibmax, a(1,1), &
+             & iindex(j1), inum, 0, irev, irank(1), iret)
+        if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) < ',iindex(j1:j2)
+      enddo ! do j=1,inumt,inc
+!$OMP END DO
+      IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPMERGE',1,ZHOOK_SUBHANDLE3)
+!$OMP END PARALLEL
+
+      if (LLdebug) write(0,1003) jj,'<after_merge>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
+      if (LLdebug) CALL DBGPRINT(jj,'<after_merge>',a,iindex,n,ikey,1,n,1)
+
+      inc = inc * 2
+    enddo ! do jj=1,imax
+    rc = n
+  endif ! if (LLomp_okay)
+
+  if (LLdescending) then
+    if (istride == 1) then
+      a(1:n,ikey) = -a(1:n,ikey)
+    else
+      a(ikey,1:n) = -a(ikey,1:n)
+    endif
+  endif
+
+  if (LLadjusted .and. imethod /= imethod_rest) then ! Restore back immediately
+    if (LLdebug) write(0,1000) '<3a>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
+    call adjust_index(iindex, +1) ! C -> Fortran
+    if (LLdebug) write(0,1000) '<4a>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
+    LLadjusted = .FALSE.
+  endif
+
+  imethod = imethod_rest
+enddo KEYLOOP
+
+deallocate(ikeys)
+if (allocated(ista)) deallocate(ista)
+if (allocated(ichunk)) deallocate(ichunk)
+if (allocated(irank)) deallocate(irank)
+
+if (LLadjusted) then ! Restore back
+  if (LLdebug) write(0,1000) '<3b>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
+  call adjust_index(iindex, +1) ! C -> Fortran
+  if (LLdebug) write(0,1000) '<4b>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
+  LLadjusted = .FALSE.
+endif
+
+if (LLdebug) write(0,1000) '<END>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
+if (LLdebug) CALL DBGPRINT(0,'<END>',a,iindex,n,ilastkey,1,n,0)
+
+if (.not.present(index)) then
+  LLomp_okay = (nomp >= inumt .and. n >= nomp)
+  if (istride == 1) then
+    LLomp_okay = (LLomp_okay .and. sda >= inumt .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
+!$OMP PARALLEL PRIVATE(j,data) IF (LLomp_okay)
+    allocate(data(n))
+!$OMP DO SCHEDULE(DYNAMIC,1)
+    do j=1,sda
+      data(1:n) = a(iindex(1:n),j)
+      a(1:n,j) = data(1:n)
+    enddo
+!$OMP END DO
+    deallocate(data)
+!$OMP END PARALLEL
+  else
+    LLomp_okay = (LLomp_okay .and. lda >= inumt .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
+!$OMP PARALLEL PRIVATE(i,data) IF (LLomp_okay)
+    allocate(data(n))
+!$OMP DO SCHEDULE(DYNAMIC,1)
+    do i=1,lda
+      data(1:n) = a(i,iindex(1:n))
+      a(i,1:n) = data(1:n)
+    enddo
+!$OMP END DO
+    deallocate(data)
+!$OMP END PARALLEL
+  endif
+
+  deallocate(iindex)
+endif
+
+99 continue
+IF (LHOOK) CALL DR_HOOK(KEYSORT_2D_DRHOOKSTR,1,ZHOOK_HANDLE,n*inumkeys)
+END SUBROUTINE
+
+!-----------------------------
+!--   Private subroutines   --
+!-----------------------------
+
+SUBROUTINE DBGPRINT(jj, cdstr, a, index, n, key, k1, k2, kadd)
+character(len=*), intent(in) :: cdstr
+INTEGER(KIND=JPIM), intent(in) :: jj, n, key, k1, k2, kadd
+INTEGER(KIND=JPIM), intent(in) :: index(:)
+DATA_TYPE, intent(in) :: a(:,:)
+INTEGER(KIND=JPIM) :: i,j
+1000 FORMAT(i3,a,5i5)
+1011 FORMAT((5i12)) ! integer*4
+1012 FORMAT(1p,(5g20.12)) ! real*8
+1013 FORMAT(1p,(5g20.12)) ! real*4
+1014 FORMAT((5i12)) ! integer*8
+WRITE(0,1000) jj,cdstr//': n,key,k1,k2,kadd,a(index(k1:k2)+kadd,:)=',&
+     &                     n,key,k1,k2,kadd
+do j=k1,k2
+  i = index(j)+kadd
+  WRITE(0,'(2i6)',advance='no') j,i-kadd
+  WRITE(0,DBGFMTNUM) a(i,:)
+enddo
+END SUBROUTINE
+
+SUBROUTINE HEAPSORT(id, n, a, rc, irev, istride, index)
+INTEGER(KIND=JPIM), intent(in) :: id, n, irev, istride
+DATA_TYPE, intent(in) :: a(:)
+INTEGER(KIND=JPIM), intent(out) :: rc
+INTEGER(KIND=JPIM), intent(inout) :: index(:)
+INTEGER(KIND=JPIM) :: i,j,right,left,idx
+DATA_TYPE :: tmp
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(HEAPSORT_DRHOOKSTR,0,ZHOOK_HANDLE)
+rc = 0
+if (n <= 0 .or. size(a) <= 0) goto 99
+left  = n/2+1
+right = n
+LOOP: do
+  if (left > 1) then
+    left = left - 1
+    idx  = index(left)
+  else
+    idx = index(right)
+    index(right) = index(1)
+    right = right - 1
+    if (right == 1) then
+      index(1) = idx
+      exit LOOP
+    endif
+  endif
+  tmp = a(idx)
+  i = left
+  j = 2*left
+  do while (j <= right)
+    if (j < right) then
+      if (a(index(j)) < a(index(j+1))) j = j + 1
+    endif
+    if (tmp < a(index(j))) then
+      index(i) = index(j)
+      i = j
+      j = 2*j
+    else
+      j = right + 1
+    endif
+  enddo
+  index(i) = idx
+enddo LOOP
+rc = n
+99 continue
+IF (LHOOK) CALL DR_HOOK(HEAPSORT_DRHOOKSTR,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+
+
+#ifndef NO_UNDEF
+
+#undef DATA_TYPE
+#undef SIZEOF_ME
+#undef KEYSORT_1D
+#undef KEYSORT_1D_DRHOOKSTR
+#undef KEYSORT_2D
+#undef KEYSORT_2D_DRHOOKSTR
+#undef KEYSORT_NUMBER
+#undef RSORT_DRHOOKSTR
+#undef USE_RSORT64
+#undef QSORTFAST_DRHOOKSTR
+#undef HEAPSORT
+#undef HEAPSORT_DRHOOKSTR
+#undef DBGPRINT
+#undef DBGFMTNUM
+#undef ECQSORT_DRHOOKSTR
+#undef COUNT_DRHOOKSTR
+#undef GNOME_DRHOOKSTR
+
+#endif
diff --git a/odb/src/extras/ifsaux/include/getstatm.h b/odb/src/extras/ifsaux/include/getstatm.h
new file mode 100644
index 0000000..376bcdf
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/getstatm.h
@@ -0,0 +1,31 @@
+#ifndef _GETSTATM_H_
+#define _GETSTATM_H_
+
+/* statm format: (/proc/self/mem under LINUX)
+
+   in units of pages (4096 bytes)
+
+size       total program size
+resident   size of in memory portions
+shared     number of the pages that are shared
+trs        number of pages that are 'code'
+drs        number of pages of data/stack
+lrs        number of pages of library
+dt         number of dirty pages
+
+*/
+
+struct statm
+{
+    int size;
+    int resident;
+    int shared;
+    int trs;
+    int drs;
+    int lrs;
+    int dt;
+};
+
+int getstatm(struct statm *sm);
+
+#endif
diff --git a/odb/src/extras/ifsaux/include/intercept_alloc.h b/odb/src/extras/ifsaux/include/intercept_alloc.h
new file mode 100644
index 0000000..01784d6
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/intercept_alloc.h
@@ -0,0 +1,50 @@
+#ifndef _INTERCEPT_ALLOC_H_
+#define _INTERCEPT_ALLOC_H_
+
+/* intercept_alloc.h */
+
+#if defined(INTERCEPT_ALLOC)
+
+#if defined(RS6K) && defined(__64BIT__)
+
+#define EC_free     __free
+#define EC_malloc   __malloc
+#define EC_calloc   __calloc
+#define EC_realloc  __realloc
+#define EC_strdup   __strdup
+
+#elif defined(NECSX)
+/* Do nothing */
+#else
+/* Illegal to have -DINTERCEPT_ALLOC */
+#undef INTERCEPT_ALLOC
+#endif
+
+#endif
+
+#if defined(INTERCEPT_ALLOC)
+
+/* For reference, see also ifsaux/utilities/getcurheap.c */
+
+#define THEmalloc  EC_malloc
+extern void *EC_malloc(long long int size);
+#define THEcalloc  EC_calloc
+extern void *EC_calloc(long long int nelem, long long int elsize);
+#define THErealloc EC_realloc
+extern void *EC_realloc(void *p, long long int size);
+#define THEstrdup  EC_strdup
+extern char *EC_strdup(const char *s);
+#define THEfree    EC_free
+extern void EC_free(void *p);
+
+#else /* i.e. !defined(INTERCEPT_ALLOC) */
+
+#define THEmalloc  malloc
+#define THEcalloc  calloc
+#define THErealloc realloc
+#define THEstrdup  strdup
+#define THEfree    free
+
+#endif
+
+#endif /* _INTERCEPT_ALLOC_H_ */
diff --git a/odb/src/extras/ifsaux/include/raise.h b/odb/src/extras/ifsaux/include/raise.h
new file mode 100644
index 0000000..baee536
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/raise.h
@@ -0,0 +1,33 @@
+#ifndef _RAISE_H_
+#define _RAISE_H_
+
+/* raise.h */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+extern void abor1fl_(const char *filename, const int *linenum, 
+		     const char *s, 
+		     int filenamelen, int slen);
+extern void abor1_(const char *s, int slen);
+
+#define ABOR1(txt) { const char *t = (txt); t ? abor1_(t, strlen(t)) : abor1_("",0); }
+
+#define ABOR1FL(txt) { \
+  const char *t = (txt); \
+  int linenum=__LINE__; \
+  t ? abor1fl_(__FILE__, &linenum,  t, sizeof(__FILE__)-1, strlen(t)) \
+    : abor1fl_(__FILE__, &linenum, "", sizeof(__FILE__)-1, 0); \
+  _exit(1); /* Should never end up here */ }
+
+#define RAISE(x) { \
+  if ((x) == SIGABRT) { \
+    ABOR1FL("*** Fatal error; aborting (SIGABRT) ..."); \
+    _exit(1); /* Should never end up here */ \
+  } \
+  else raise(x); \
+}
+
+#endif /* _RAISE_H_ */
diff --git a/odb/src/extras/ifsaux/include/user_clock.h b/odb/src/extras/ifsaux/include/user_clock.h
new file mode 100644
index 0000000..f5d63d3
--- /dev/null
+++ b/odb/src/extras/ifsaux/include/user_clock.h
@@ -0,0 +1,49 @@
+SUBROUTINE USER_CLOCK(PELAPSED_TIME,PELAPSED_TIME_SINCE,PVECTOR_CP,PTOTAL_CP)
+
+!**** *USER_CLOCK* - interface to system dependent timer routines
+
+!     Purpose.
+!     --------
+!        Returns elapsed and CP from the start of execution.
+!        Elapsed time is made relative to the first call to USER_CLOCK.
+
+!**   Interface.
+!     ----------
+!        ZTIME=USER_CLOCK(PELAPSED_TIME,PELAPSED_TIME_SINCE,
+!                         PVECTOR_CP,PTOTAL_CP)
+
+!        Explicit arguments: (All are optional arguments)
+!                           PELAPSED_TIME=wall clock time (seconds)
+!                           PELAPSED_TIME_SINCE=wall clock time (seconds)
+!                             change from input value of this parameter
+!                           PVECTOR_CP=CP vector time  (seconds)
+!                           PTOTAL_CP=total CP time   (seconds)
+
+!     Author.
+!     -------
+!        D.Dent      *ECMWF*
+
+!     External References:
+!     -------------------
+
+!        TIMEF,CPTIME
+
+!     Modifications.
+!     --------------
+!        Original  : 97-09-25
+!     ----------------------------------------------------------
+
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+REAL(KIND=JPRB),INTENT(OUT) :: PELAPSED_TIME,PVECTOR_CP,PTOTAL_CP
+REAL(KIND=JPRB),INTENT(INOUT) :: PELAPSED_TIME_SINCE
+OPTIONAL            PELAPSED_TIME,PELAPSED_TIME_SINCE
+OPTIONAL            PVECTOR_CP,PTOTAL_CP
+REAL(KIND=JPRB)      :: ZVECTOR_CP,ZTOTAL_CP,ZWALL
+REAL(KIND=JPRB),EXTERNAL :: TIMEF
+
+
+END SUBROUTINE USER_CLOCK
diff --git a/odb/src/extras/ifsaux/module/.parkind1.F90.un~ b/odb/src/extras/ifsaux/module/.parkind1.F90.un~
new file mode 100644
index 0000000..9893e1c
Binary files /dev/null and b/odb/src/extras/ifsaux/module/.parkind1.F90.un~ differ
diff --git a/odb/src/extras/ifsaux/module/dr_hook_watch_mod.F90 b/odb/src/extras/ifsaux/module/dr_hook_watch_mod.F90
new file mode 100644
index 0000000..df771f0
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/dr_hook_watch_mod.F90
@@ -0,0 +1,365 @@
+MODULE dr_hook_watch_mod
+
+USE PARKIND1  ,ONLY : JPIM, JPIB, JPRM, JPRB
+
+!-- Watch point creation interface for Dr.Hook
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+INTERFACE DR_HOOK_WATCH
+MODULE PROCEDURE &
+  DR_HOOK_WATCH_CHARACTER, &
+  DR_HOOK_WATCH_LOGICAL_SCALAR, &
+  DR_HOOK_WATCH_LOGICAL_1D, &
+  DR_HOOK_WATCH_LOGICAL_2D, &
+  DR_HOOK_WATCH_I4_SCALAR, &
+  DR_HOOK_WATCH_I4_1D, &
+  DR_HOOK_WATCH_I4_2D, &
+  DR_HOOK_WATCH_I8_SCALAR, &
+  DR_HOOK_WATCH_I8_1D, &
+  DR_HOOK_WATCH_I8_2D, &
+  DR_HOOK_WATCH_R4_SCALAR, &
+  DR_HOOK_WATCH_R4_1D, &
+  DR_HOOK_WATCH_R4_2D, &
+  DR_HOOK_WATCH_R8_SCALAR, &
+  DR_HOOK_WATCH_R8_1D, &
+  DR_HOOK_WATCH_R8_2D
+END INTERFACE 
+
+PUBLIC :: DR_HOOK_WATCH
+
+CONTAINS
+
+SUBROUTINE DR_HOOK_WATCH_CHARACTER(CDNAME, PTR, &
+          &                        LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 1
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+CHARACTER(LEN=*), INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = LEN(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1:1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_CHARACTER
+
+SUBROUTINE DR_HOOK_WATCH_LOGICAL_SCALAR(CDNAME, PTR, &
+          &                             LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+LOGICAL, INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = JP_BYTES_PER_ELEM
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR, IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_LOGICAL_SCALAR
+
+SUBROUTINE DR_HOOK_WATCH_LOGICAL_1D(CDNAME, PTR, &
+          &                         LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+LOGICAL, INTENT(IN) :: PTR(:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_LOGICAL_1D
+
+SUBROUTINE DR_HOOK_WATCH_LOGICAL_2D(CDNAME, PTR, &
+          &                         LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+LOGICAL, INTENT(IN) :: PTR(:,:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1,1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_LOGICAL_2D
+
+SUBROUTINE DR_HOOK_WATCH_I4_SCALAR(CDNAME, PTR, &
+          &                        LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM), INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = JP_BYTES_PER_ELEM
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR, IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I4_SCALAR
+
+SUBROUTINE DR_HOOK_WATCH_I4_1D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM), INTENT(IN) :: PTR(:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I4_1D
+
+SUBROUTINE DR_HOOK_WATCH_I4_2D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM), INTENT(IN) :: PTR(:,:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1,1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I4_2D
+
+SUBROUTINE DR_HOOK_WATCH_I8_SCALAR(CDNAME, PTR, &
+          &                        LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIB), INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = JP_BYTES_PER_ELEM
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR, IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I8_SCALAR
+
+SUBROUTINE DR_HOOK_WATCH_I8_1D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIB), INTENT(IN) :: PTR(:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I8_1D
+
+SUBROUTINE DR_HOOK_WATCH_I8_2D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIB), INTENT(IN) :: PTR(:,:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1,1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_I8_2D
+
+SUBROUTINE DR_HOOK_WATCH_R4_SCALAR(CDNAME, PTR, &
+          &                        LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRM), INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = JP_BYTES_PER_ELEM
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR, IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R4_SCALAR
+
+SUBROUTINE DR_HOOK_WATCH_R4_1D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRM), INTENT(IN) :: PTR(:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R4_1D
+
+SUBROUTINE DR_HOOK_WATCH_R4_2D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 4
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRM), INTENT(IN) :: PTR(:,:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1,1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R4_2D
+
+SUBROUTINE DR_HOOK_WATCH_R8_SCALAR(CDNAME, PTR, &
+          &                        LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRB), INTENT(IN) :: PTR
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = JP_BYTES_PER_ELEM
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR, IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R8_SCALAR
+
+SUBROUTINE DR_HOOK_WATCH_R8_1D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRB), INTENT(IN) :: PTR(:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R8_1D
+
+SUBROUTINE DR_HOOK_WATCH_R8_2D(CDNAME, PTR, &
+          &                    LDABORT, LDACTIVE)
+INTEGER(KIND=JPIM), PARAMETER :: JP_BYTES_PER_ELEM = 8
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+REAL(KIND=JPRB), INTENT(IN) :: PTR(:,:)
+LOGICAL, INTENT(IN), OPTIONAL :: LDABORT, LDACTIVE
+LOGICAL :: LLABORT, LLACTIVE
+INTEGER(KIND=JPIM) :: IBYTES, IABORT, IACTIVE
+IBYTES = SIZE(PTR) * JP_BYTES_PER_ELEM
+IF (IBYTES <= 0) RETURN
+IABORT = 0
+LLABORT = .TRUE.
+IF (PRESENT(LDABORT)) LLABORT = LDABORT
+IF (LLABORT) IABORT = 1
+IACTIVE = 0
+LLACTIVE = .TRUE.
+IF (PRESENT(LDACTIVE)) LLACTIVE = LDACTIVE
+IF (LLACTIVE) IACTIVE = 1
+CALL C_DRHOOK_WATCH(IACTIVE, CDNAME, PTR(1,1), IBYTES, IABORT)
+END SUBROUTINE DR_HOOK_WATCH_R8_2D
+
+END MODULE dr_hook_watch_mod
diff --git a/odb/src/extras/ifsaux/module/ecsort_mix.F90 b/odb/src/extras/ifsaux/module/ecsort_mix.F90
new file mode 100644
index 0000000..fe9da94
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/ecsort_mix.F90
@@ -0,0 +1,330 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE ecsort_mix
+USE PARKIND1   , ONLY : JPIM     ,JPIB     ,JPRB     ,JPRM
+USE YOMHOOK    , ONLY : LHOOK, DR_HOOK
+USE OML_MOD     , ONLY : OML_MAX_THREADS, OML_MY_THREAD, OML_IN_PARALLEL
+USE STRHANDLER_MOD , ONLY : TOUPPER
+USE MPL_MODULE , ONLY : MPL_MYRANK, MPL_NPROC
+
+!$
+!..   Author: Sami Saarinen, ECMWF, 10/02/98
+!     Fixes : Sami Saarinen, ECMWF, 08/11/99 : Sub-arrays go now correctly (look for addrdiff)
+!                                              Genuine real(4) sort "re-habilitated"
+!                                              sizeof_int, _real4 & _real8 HARDCODED !
+!             Sami Saarinen, ECMWF, 11/10/00 : REAL*4 version included (REAL_M)
+!             Sami Saarinen, ECMWF, 28/11/03 : Calls to DR_HOOK added manually (on top of CY28)
+!             Sami Saarinen, ECMWF, 18/02/05 : 64-bit integer sorting introduced (for CY30)
+!             Sami Saarinen, ECMWF, 22/02/05 : Using genuine 64-bit rsort64() => one-pass through data
+!             Sami Saarinen, ECMWF, 06/07/05 : "current_method" made OpenMP-thread aware (for max. # of threads = NTHRDS)
+!             Sami Saarinen, ECMWF, 07/07/05 : Quick-sort method finally arrived (and applicable to multikeys, too)
+!                                              Quick-sort the default for scalar machines ("non-VPP"), VPPs is radix-sort
+!             Sami Saarinen, ECMWF, 03/07/07 : Quick-sort method uses stable approach (was not guaranteed so before)
+!             Sami Saarinen, ECMWF, 15/10/07 : Subroutines put into a common file ../include/ecsort_shared.h and
+!                                              preprocessed from there
+!             Sami Saarinen, ECMWF, 15/10/07 : NTHRDS increased from 32 to 64
+!             Sami Saarinen, ECMWF, 16/10/07 : The default sorting method can be overriden via export EC_SORTING_METHOD=[<number>|<string>]
+!             Sami Saarinen, ECMWF, 30/10/07 : Support for CountingSort added as part of QuickSort speedup
+!             Sami Saarinen, ECMWF, 31/10/07 : CALL SORTING_METHOD() now prints the prevailing method from EC_SORTING_METHOD
+!             Sami Saarinen, ECMWF, 01/11/07 : CountingSort implemented as independent method
+!             Sami Saarinen, ECMWF, 06/11/07 : index_adj added as an optional argument to init_index ; new routine adjust_index()
+!             Sami Saarinen, ECMWF, 07/11/07 : threshold length "nomp" (see below). Override with EC_SORTING_NOMP.
+!             Sami Saarinen, ECMWF, 12/11/07 : Gnome-sort -- the easiest sort on Earth (and very slow for large arrays)
+!             Sami Saarinen, ECMWF, 15/11/07 : OpenMP-sorting still under development. Do NOT override the EC_SORTING_NOMP yet.
+!             Sami Saarinen, ECMWF, 05/12/07 : When export EC_SORTING_INFO=0, then no info messages are printed from CALL sorting_method()
+!             Sami Saarinen, ECMWF, 20/12/07 : export EC_SORTING_INFO=0, rather than =1 is now the default --> less hassling output
+
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+INTEGER(KIND=JPIM), parameter :: NTHRDS = 64 ! ***Note: A hardcoded max number of threads !!!
+
+INTEGER(KIND=JPIM), parameter :: sizeof_int4  = 4
+INTEGER(KIND=JPIM), parameter :: sizeof_int8  = 8
+INTEGER(KIND=JPIM), parameter :: sizeof_real4 = 4
+INTEGER(KIND=JPIM), parameter :: sizeof_real8 = 8
+
+INTEGER(KIND=JPIM), parameter :: min_method = 1
+INTEGER(KIND=JPIM), parameter :: max_method = 5
+
+INTEGER(KIND=JPIM), parameter :: radixsort_method = 1
+INTEGER(KIND=JPIM), parameter :: heapsort_method  = 2
+INTEGER(KIND=JPIM), parameter :: quicksort_method = 3
+INTEGER(KIND=JPIM), parameter :: countingsort_method = 4
+INTEGER(KIND=JPIM), parameter :: gnomesort_method = 5
+
+CHARACTER(LEN=12), parameter :: method_name(min_method:max_method) = &
+     & (/&
+     &   'RADIXSORT   ' &
+     &  ,'HEAPSORT    ' &
+     &  ,'QUICKSORT   ' &
+     &  ,'COUNTINGSORT' &
+     &  ,'GNOMESORT   ' &
+     &  /)
+
+!-- Select such method for default_method, which also works for multikey sorts
+!   Vector machines should choose radixsort_method, others quicksort_method (oh, sorry, countingsort_method!)
+!
+!   Note: Occasionally radixsort_method may be faster on non-vector machines, too
+#if defined(VPP) || defined(NECSX)
+INTEGER(KIND=JPIM) :: default_method = radixsort_method
+INTEGER(KIND=JPIM) :: current_method(NTHRDS) = radixsort_method
+#else
+INTEGER(KIND=JPIM) :: default_method = countingsort_method
+INTEGER(KIND=JPIM) :: current_method(NTHRDS) = countingsort_method
+#endif
+
+!-- A threshold length after which OpenMP in sorting, merging, copying may kick in.
+!   Override with EC_SORTING_NOMP. Detected while initializing/calling SORTING_METHOD
+!   Non-positive values (<= 0) indicate that OpenMP will NOT be attempted at all
+INTEGER(KIND=JPIM) :: nomp = -1
+
+!-- EC_SORTING_INFO = MPL-proc id [1..$NPES] to print the info message when CALL sorting_method()
+!                   : 0 (no print; the default)
+!                   : 1 (print on MPL-task one)
+!                   : > 1 and <= $NPES (some other MPL-task than 1 prints)
+INTEGER(KIND=JPIM) :: nsinfo = 0
+
+INTERFACE keysort
+MODULE PROCEDURE &
+     &int4_keysort_1D, int4_keysort_2D, &
+     &int8_keysort_1D, int8_keysort_2D, &
+     &real8_keysort_1D, real8_keysort_2D, &
+     &real4_keysort_1D, real4_keysort_2D
+END INTERFACE
+
+INTERFACE sorting_method
+MODULE PROCEDURE int_sorting_method, str_sorting_method
+END INTERFACE
+
+PUBLIC :: keysort
+PUBLIC :: init_index, get_rank, adjust_index
+PUBLIC :: sorting_method
+
+CONTAINS
+
+!----------------------------
+!--   Public subroutines   --
+!----------------------------
+
+SUBROUTINE int_sorting_method(inew, iold)
+INTEGER(KIND=JPIM), OPTIONAL, intent(in)  :: inew
+INTEGER(KIND=JPIM), OPTIONAL, intent(out) :: iold
+INTEGER(KIND=JPIM) :: itmp, imyproc, inpes
+INTEGER(KIND=JPIM) :: ITID
+character(len=20) clenv
+logical, save :: LLfirst = .TRUE.
+logical LLomp, LLhook_ok
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+!-- This maybe called from the very first call of DR_HOOK_UTIL ...
+LLhook_ok = LHOOK .and. (present(inew) .or. present(iold))
+IF (LLhook_ok) CALL DR_HOOK('ECSORT_MIX:INT_SORTING_METHOD',0,ZHOOK_HANDLE)
+ITID = OML_MY_THREAD()
+LLomp = OML_IN_PARALLEL()
+if (present(iold)) iold = current_method(ITID)
+itmp = -1
+if (present(inew)) then
+  itmp = inew
+else if (.not.LLomp) then ! Override the default method (only if outside the OpenMP)
+  itmp = -1 ! no change
+  if (LLfirst) then ! Do once per execution only
+    inpes = MPL_NPROC()
+    CALL ec_getenv('EC_SORTING_INFO',clenv) ! ../support/env.c
+    if (clenv /= ' ') then
+      itmp = nsinfo
+      read(clenv,'(i20)',end=89,err=89) itmp
+      goto 88
+89    continue
+      itmp = nsinfo ! no change
+88    continue
+      if (itmp <= 0) then
+        nsinfo = 0
+      else if (itmp >= 1 .and. itmp <= inpes) then
+        nsinfo = itmp
+      endif
+    endif
+    imyproc = MPL_MYRANK()
+    CALL ec_getenv('EC_SORTING_METHOD',clenv) ! ../support/env.c
+    if (clenv /= ' ') then
+       if (imyproc == nsinfo) write(0,'(a)')'<EC_SORTING_METHOD='//trim(clenv)
+       CALL toupper(clenv)
+       select case (clenv)
+       case ('RADIX', 'RADIXSORT')
+          itmp = radixsort_method
+       case ('HEAP', 'HEAPSORT')
+          itmp = heapsort_method
+       case ('QUICK', 'QUICKSORT', 'QSORT')
+          itmp = quicksort_method
+       case ('COUNT', 'COUNTINGSORT', 'COUNTSORT')
+          itmp = countingsort_method
+       case ('GNOME', 'GNOMESORT')
+          itmp = gnomesort_method
+       case ('DEFAULT', 'DEF')
+          itmp = -1 ! no change
+       case default
+          read(clenv,'(i20)',end=99,err=99) itmp
+          goto 98
+99        continue
+          itmp = -1 ! no change
+98        continue
+       end select
+    endif
+
+    if (itmp < min_method .or. itmp > max_method) itmp = default_method
+    default_method = itmp
+    current_method(:) = itmp
+    if (imyproc == nsinfo) &
+         & write(0,'(a,i1,a)')'>EC_SORTING_METHOD=',default_method,&
+         & ' # '//method_name(default_method)
+
+    CALL ec_getenv('EC_SORTING_NOMP',clenv)
+    if (clenv /= ' ') then
+       if (imyproc == nsinfo) write(0,'(a)')'<EC_SORTING_NOMP='//trim(clenv)
+       read(clenv,'(i20)',end=199,err=199) itmp
+       goto 198
+199    continue
+       itmp = nomp ! no change
+198    continue
+       nomp = itmp
+    endif
+
+    if (imyproc == nsinfo) then
+      write(clenv,'(i20)') nomp
+      write(0,'(a)')'>EC_SORTING_NOMP='//trim(adjustl(clenv))
+    endif
+
+    itmp = default_method
+    LLfirst = .FALSE.
+  endif
+endif
+
+if (itmp < min_method .or. itmp > max_method) itmp = default_method
+if (LLomp) then ! Only this thread sees the change
+  current_method(ITID) = itmp
+else ! All threads see the change
+  current_method(:) = itmp
+endif
+IF (LLhook_ok) CALL DR_HOOK('ECSORT_MIX:INT_SORTING_METHOD',1,ZHOOK_HANDLE)
+END SUBROUTINE int_sorting_method
+
+
+SUBROUTINE str_sorting_method(cdnew, iold)
+character(len=*), intent(in) :: cdnew
+INTEGER(KIND=JPIM), OPTIONAL, intent(out) :: iold
+character(len=len(cdnew)) clnew
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:STR_SORTING_METHOD',0,ZHOOK_HANDLE)
+clnew = cdnew
+CALL toupper(clnew)
+select case (clnew)
+case ('RADIX', 'RADIXSORT')
+  CALL sorting_method(radixsort_method, iold)
+case ('HEAP', 'HEAPSORT')
+  CALL sorting_method(heapsort_method, iold)
+case ('QUICK', 'QUICKSORT', 'QSORT')
+  CALL sorting_method(quicksort_method, iold)
+case ('COUNT', 'COUNTINGSORT', 'COUNTSORT')
+  CALL sorting_method(countingsort_method, iold)
+case ('GNOME', 'GNOMESORT')
+  CALL sorting_method(gnomesort_method, iold)
+case ('DEFAULT', 'DEF')
+  CALL sorting_method(default_method, iold)
+case default
+  CALL sorting_method(default_method, iold)
+end select
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:STR_SORTING_METHOD',1,ZHOOK_HANDLE)
+END SUBROUTINE str_sorting_method
+
+
+SUBROUTINE init_index(index, index_adj)
+INTEGER(KIND=JPIM), intent(out):: index(:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: index_adj
+INTEGER(KIND=JPIM) :: i, n
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:INIT_INDEX',0,ZHOOK_HANDLE)
+n = size(index)
+if (present(index_adj)) then
+  do i=1,n
+    index(i) = i + index_adj
+  enddo
+else
+  do i=1,n
+    index(i) = i
+  enddo
+endif
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:INIT_INDEX',1,ZHOOK_HANDLE)
+END SUBROUTINE init_index
+
+
+SUBROUTINE adjust_index(index, index_adj)
+INTEGER(KIND=JPIM), intent(inout):: index(:)
+INTEGER(KIND=JPIM), intent(in) :: index_adj
+INTEGER(KIND=JPIM) :: i, n
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:ADJUST_INDEX',0,ZHOOK_HANDLE)
+if (index_adj /= 0) then
+  n = size(index)
+  do i=1,n
+    index(i) = index(i) + index_adj
+  enddo
+endif
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:ADJUST_INDEX',1,ZHOOK_HANDLE)
+END SUBROUTINE adjust_index
+
+
+SUBROUTINE get_rank(index, rank, index_adj)
+INTEGER(KIND=JPIM), intent(in) :: index(:)
+INTEGER(KIND=JPIM), intent(out):: rank(:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: index_adj
+INTEGER(KIND=JPIM) :: i, n
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:GET_RANK',0,ZHOOK_HANDLE)
+n = min(size(index),size(rank))
+if (present(index_adj)) then
+  do i=1,n
+    rank(index(i)+index_adj) = i
+  enddo
+else
+  do i=1,n
+    rank(index(i)) = i
+  enddo
+endif
+IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:GET_RANK',1,ZHOOK_HANDLE)
+END SUBROUTINE get_rank
+
+
+#undef INT_VERSION
+#undef REAL_VERSION
+
+!-- Create version for INTEGER(KIND=JPIM)
+#define INT_VERSION   4
+#define REAL_VERSION  0
+#include "ecsort_shared.h"
+#undef INT_VERSION
+#undef REAL_VERSION
+
+!-- Create version for INTEGER(KIND=JPIB)
+#define INT_VERSION   8
+#define REAL_VERSION  0
+#include "ecsort_shared.h"
+#undef INT_VERSION
+#undef REAL_VERSION
+
+!-- Create version for REAL(KIND=JPRM)
+#define INT_VERSION   0
+#define REAL_VERSION  4
+#include "ecsort_shared.h"
+#undef INT_VERSION
+#undef REAL_VERSION
+
+!-- Create version for REAL(KIND=JPRB)
+#define INT_VERSION   0
+#define REAL_VERSION  8
+#include "ecsort_shared.h"
+#undef INT_VERSION
+#undef REAL_VERSION
+
+END MODULE ecsort_mix
diff --git a/odb/src/extras/ifsaux/module/f90_unix_env.F90 b/odb/src/extras/ifsaux/module/f90_unix_env.F90
new file mode 100644
index 0000000..45fd390
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/f90_unix_env.F90
@@ -0,0 +1,9 @@
+#ifdef NAG
+!-- The NAG-compiler has its own proper F90_UNIX_* modules
+!   We need this for non-NAG compilers to satisfy some
+!   make/build-environments only
+#define F90_UNIX_ENV NAGDUMMY_F90_UNIX_ENV
+#endif
+MODULE F90_UNIX_ENV
+LOGICAL L_NAGDUMMY
+END MODULE F90_UNIX_ENV
diff --git a/odb/src/extras/ifsaux/module/f90_unix_io.F90 b/odb/src/extras/ifsaux/module/f90_unix_io.F90
new file mode 100644
index 0000000..593de2e
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/f90_unix_io.F90
@@ -0,0 +1,9 @@
+#ifdef NAG
+!-- The NAG-compiler has its own proper F90_UNIX_* modules
+!   We need this for non-NAG compilers to satisfy some
+!   make/build-environments only
+#define F90_UNIX_IO NAGDUMMY_F90_UNIX_IO
+#endif
+MODULE F90_UNIX_IO
+LOGICAL L_NAGDUMMY
+END MODULE F90_UNIX_IO
diff --git a/odb/src/extras/ifsaux/module/f90_unix_proc.F90 b/odb/src/extras/ifsaux/module/f90_unix_proc.F90
new file mode 100644
index 0000000..307a4f5
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/f90_unix_proc.F90
@@ -0,0 +1,9 @@
+#ifdef NAG
+!-- The NAG-compiler has its own proper F90_UNIX_* modules
+!   We need this for non-NAG compilers to satisfy some
+!   make/build-environments only
+#define F90_UNIX_PROC NAGDUMMY_F90_UNIX_PROC
+#endif
+MODULE F90_UNIX_PROC
+LOGICAL L_NAGDUMMY
+END MODULE F90_UNIX_PROC
diff --git a/odb/src/extras/ifsaux/module/local_trafos.F90 b/odb/src/extras/ifsaux/module/local_trafos.F90
new file mode 100644
index 0000000..84073aa
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/local_trafos.F90
@@ -0,0 +1,120 @@
+MODULE LOCAL_TRAFOS
+!**** LOCAL_TRAFOS transform localized quantities to other quantities
+
+!     Purpose.
+!     --------
+!     Transform wind speed, direction to components and vice versa
+!     Other functions also: value extracted from an array with an index
+!        defined from a second array
+
+!**   Interface.
+!     ----------
+!        USE LOCAL_TRAFOS
+
+!     Author.
+!     -------
+!        H. Hersbach     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2007-04-11
+
+!        2009-09-04 C. Payan IVALFROMIDX added
+!            allows to match an integer in an array from the index of an 
+!            other integer's array
+
+!     ------------------------------------------------------------------
+
+
+USE PARKIND1  ,ONLY : JPIM, JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+IMPLICIT NONE
+
+PRIVATE
+PUBLIC UCOM, VCOM, UV2FF, UV2DD, IVALFROMIDX
+
+REAL(KIND=JPRB) ,   PARAMETER :: PARC=360._JPRB
+REAL(KIND=JPRB) ,   PARAMETER :: DEGCON=3.14159265358979_JPRB/180._JPRB
+
+
+CONTAINS
+
+!***********************************************************************
+FUNCTION UCOM(PDD,PFF)
+REAL(KIND=JPRB)                  :: UCOM 
+REAL(KIND=JPRB)   ,INTENT(IN)    :: PDD,PFF 
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UCOM',0,ZHOOK_HANDLE)
+UCOM = -PFF * SIN(PDD*DEGCON)
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UCOM',1,ZHOOK_HANDLE)
+END FUNCTION UCOM
+
+
+!***********************************************************************
+FUNCTION VCOM(PDD,PFF)
+REAL(KIND=JPRB)                  :: VCOM 
+REAL(KIND=JPRB)   ,INTENT(IN)    :: PDD,PFF 
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:VCOM',0,ZHOOK_HANDLE)
+VCOM = -PFF * COS(PDD*DEGCON)
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:VCOM',1,ZHOOK_HANDLE)
+END FUNCTION VCOM
+
+
+!***********************************************************************
+FUNCTION UV2FF(PUU,PVV)
+REAL(KIND=JPRB)                  :: UV2FF 
+REAL(KIND=JPRB)   ,INTENT(IN)    :: PUU,PVV
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UV2FF',0,ZHOOK_HANDLE)
+UV2FF =SQRT(PUU*PUU+PVV*PVV)
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UV2FF',1,ZHOOK_HANDLE)
+END FUNCTION UV2FF
+
+
+!***********************************************************************
+FUNCTION UV2DD(PUU,PVV)
+REAL(KIND=JPRB)                  :: UV2DD
+REAL(KIND=JPRB)   ,INTENT(IN)    :: PUU,PVV
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UV2DD',0,ZHOOK_HANDLE)
+
+IF (PUU == 0._JPRB .AND. PVV == 0._JPRB) THEN
+   UV2DD = 0.5_JPRB*PARC
+ELSE
+   UV2DD =MOD(PARC+ATAN2(-PUU,-PVV)/DEGCON,PARC)
+ENDIF
+      
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:UV2DD',1,ZHOOK_HANDLE)
+END FUNCTION UV2DD
+
+!***********************************************************************
+FUNCTION IVALFROMIDX(KTABVAL,KTABIDX,KCOND,KDEFAULT)
+INTEGER(KIND=JPIM)               :: IVALFROMIDX
+INTEGER(KIND=JPIM) ,DIMENSION(:) ,INTENT(IN)  :: KTABVAL ,KTABIDX
+INTEGER(KIND=JPIM) ,INTENT(IN)   :: KCOND ,KDEFAULT
+INTEGER(KIND=JPIM)               :: JJ ,IMXIDX
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:IVALFROMIDX',0,ZHOOK_HANDLE)
+
+IVALFROMIDX=KDEFAULT
+IMXIDX=MIN(SIZE(KTABIDX),SIZE(KTABVAL))
+
+DO JJ=1,IMXIDX
+  IF (KTABIDX(JJ)==KCOND) THEN
+    IVALFROMIDX=KTABVAL(JJ)
+    EXIT
+  ENDIF
+ENDDO
+
+IF (LHOOK) CALL DR_HOOK('LOCAL_TRAFOS:IVALFROMIDX',1,ZHOOK_HANDLE)
+END FUNCTION IVALFROMIDX
+
+!***********************************************************************
+END MODULE LOCAL_TRAFOS
diff --git a/odb/src/extras/ifsaux/module/mpi4to8.F90 b/odb/src/extras/ifsaux/module/mpi4to8.F90
new file mode 100644
index 0000000..420d29f
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpi4to8.F90
@@ -0,0 +1,6 @@
+Module MPI4TO8
+
+Use MPI4TO8_S
+Use MPI4TO8_M
+
+End Module MPI4TO8
diff --git a/odb/src/extras/ifsaux/module/mpi4to8_m.F90 b/odb/src/extras/ifsaux/module/mpi4to8_m.F90
new file mode 100644
index 0000000..b5217ac
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpi4to8_m.F90
@@ -0,0 +1,3300 @@
+Module MPI4TO8_M
+#ifdef USE_8_BYTE_WORDS
+
+Use PARKIND1, Only : JPIM, JPRM, JPRB
+USE MPL_MPIF
+
+Implicit None
+
+Private :: STATUS8
+  Integer(Kind=8), Dimension(MPI_STATUS_SIZE) :: STATUS8
+
+Interface MPI_ALLGATHERV8
+  Module Procedure MPI_ALLGATHERV8_R4, MPI_ALLGATHERV8_R8, &
+                   MPI_ALLGATHERV8_I4, MPI_ALLGATHERV8_I1
+End Interface MPI_ALLGATHERV8
+
+Interface MPI_ALLREDUCE8
+  Module Procedure MPI_ALLREDUCE8_R4, MPI_ALLREDUCE8_R8, &
+                   MPI_ALLREDUCE8_I4
+End Interface MPI_ALLREDUCE8
+
+Interface MPI_ALLTOALLV8
+  Module Procedure MPI_ALLTOALLV8_R8, MPI_ALLTOALLV8_I4
+End Interface MPI_ALLTOALLV8
+
+Interface MPI_BCAST8
+  Module Procedure MPI_BCAST8_R4, MPI_BCAST8_R8, &
+                   MPI_BCAST8_I4, MPI_BCAST8_I1, &
+                   MPI_BCAST8_CH
+End Interface MPI_BCAST8
+
+Interface MPI_BSEND8
+  Module Procedure MPI_BSEND8_R4, MPI_BSEND8_R8, &
+                   MPI_BSEND8_R42, MPI_BSEND8_R82, &
+                   MPI_BSEND8_I4, MPI_BSEND8_I1, &
+                   MPI_BSEND8_CH, MPI_BSEND8_I42, &
+                   MPI_BSEND8_R4_1, MPI_BSEND8_R8_1
+End Interface MPI_BSEND8
+
+Interface MPI_ISEND8
+  Module Procedure MPI_ISEND8_R4, MPI_ISEND8_R8, &
+                   MPI_ISEND8_R42, MPI_ISEND8_R82, &
+                   MPI_ISEND8_I4, MPI_ISEND8_I1, &
+                   MPI_ISEND8_CH, MPI_ISEND8_I42, &
+                   MPI_ISEND8_R4_1, MPI_ISEND8_R8_1
+End Interface MPI_ISEND8
+
+Interface MPI_SEND8
+  Module Procedure MPI_SEND8_R4, MPI_SEND8_R8, &
+                   MPI_SEND8_R42, MPI_SEND8_R82, &
+                   MPI_SEND8_I4, MPI_SEND8_I1, &
+                   MPI_SEND8_CH, MPI_SEND8_I42, &
+                   MPI_SEND8_R4_1, MPI_SEND8_R8_1
+End Interface MPI_SEND8
+
+Interface MPI_FILE_IREAD_SHARED8
+  Module Procedure MPI_FILE_IREAD_SHARED8_R8, MPI_FILE_IREAD_SHARED8_I4
+End Interface MPI_FILE_IREAD_SHARED8
+
+Interface MPI_FILE_IWRITE_SHARED8
+  Module Procedure MPI_FILE_IWRITE_SHARED8_R8, MPI_FILE_IWRITE_SHARED8_I4
+End Interface MPI_FILE_IWRITE_SHARED8
+
+Interface MPI_FILE_READ_ORDERED8
+  Module Procedure MPI_FILE_READ_ORDERED8_R8, MPI_FILE_READ_ORDERED8_I4
+End Interface MPI_FILE_READ_ORDERED8
+
+Interface MPI_FILE_READ_ORDERED_BEGIN8
+  Module Procedure MPI_FREAD_ORDERED_BEGIN8_R8, MPI_FREAD_ORDERED_BEGIN8_I4
+End Interface MPI_FILE_READ_ORDERED_BEGIN8
+
+Interface MPI_FILE_READ_ORDERED_END8
+  Module Procedure MPI_FREAD_ORDERED_END8_R8, MPI_FREAD_ORDERED_END8_I4
+End Interface MPI_FILE_READ_ORDERED_END8
+
+Interface MPI_FILE_READ_SHARED8
+  Module Procedure MPI_FILE_READ_SHARED8_R8, MPI_FILE_READ_SHARED8_I4
+End Interface MPI_FILE_READ_SHARED8
+
+Interface MPI_FILE_WRITE_ORDERED8
+  Module Procedure MPI_FILE_WRITE_ORDERED8_R8, MPI_FILE_WRITE_ORDERED8_I4
+End Interface MPI_FILE_WRITE_ORDERED8
+
+Interface MPI_FILE_WRITE_ORDERED_BEGIN8
+  Module Procedure MPI_FWRITE_ORDERED_BEGIN8_R8, MPI_FWRITE_ORDERED_BEGIN8_I4
+End Interface MPI_FILE_WRITE_ORDERED_BEGIN8
+
+Interface MPI_FILE_WRITE_ORDERED_END8
+  Module Procedure MPI_FWRITE_ORDERED_END8_R8, MPI_FWRITE_ORDERED_END8_I4
+End Interface MPI_FILE_WRITE_ORDERED_END8
+
+Interface MPI_FILE_WRITE_SHARED8
+  Module Procedure MPI_FILE_WRITE_SHARED8_R8, MPI_FILE_WRITE_SHARED8_I4
+End Interface MPI_FILE_WRITE_SHARED8
+
+Interface MPI_GATHER8
+  Module Procedure MPI_GATHER8_I1, MPI_GATHER8_R8_1
+End Interface MPI_GATHER8
+
+Interface MPI_GATHERV8
+  Module Procedure MPI_GATHERV8_R4, MPI_GATHERV8_R8, &
+                   MPI_GATHERV8_R4S, MPI_GATHERV8_R8S, &
+                   MPI_GATHERV8_I4, MPI_GATHERV8_I1, &
+                   MPI_GATHERV8_I4S, MPI_GATHERV8_I4S_1, &
+                   MPI_GATHERV8_R8_1, MPI_GATHERV8_R8S_1
+End Interface MPI_GATHERV8
+
+Interface MPI_RECV8
+  Module Procedure MPI_RECV8_R4, MPI_RECV8_R8, &
+                   MPI_RECV8_R42, MPI_RECV8_R82, &
+                   MPI_RECV8_I4, MPI_RECV8_I1, &
+                   MPI_RECV8_R4_1, MPI_RECV8_R8_1, &
+                   MPI_RECV8_CH, MPI_RECV8_I42
+End Interface MPI_RECV8
+
+Interface MPI_IRECV8
+  Module Procedure MPI_IRECV8_R4, MPI_IRECV8_R8, &
+                   MPI_IRECV8_R42, MPI_IRECV8_R82, &
+                   MPI_IRECV8_I4, MPI_IRECV8_I1, &
+                   MPI_IRECV8_I42, &
+                   MPI_IRECV8_R4_1, MPI_IRECV8_R8_1, &
+                   MPI_IRECV8_CH
+End Interface MPI_IRECV8
+
+Interface MPI_SCATTERV8
+  Module Procedure MPI_SCATTERV8_R8, MPI_SCATTERV8_I4, &
+                   MPI_SCATTERV8_R8S, MPI_SCATTERV8_I4S
+End Interface MPI_SCATTERV8
+
+Public
+
+Contains
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ALLREDUCE8_R4(SENDDATA, RECVDATA, COUNT, DATATYPE, OP, &
+                             COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    SENDDATA(:)
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, OP, COMM
+  Real(Kind=JPRM), Dimension(:), Intent(OUT) :: &
+    RECVDATA(:)
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8, RECVDATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, OP8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDDATA8 = SENDDATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  OP8 = OP
+  COMM8 = COMM
+
+  Call MPI_ALLREDUCE(SENDDATA8, RECVDATA8, COUNT8, DATATYPE8, OP8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_ALLREDUCE8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLREDUCE8_R8(SENDDATA, RECVDATA, COUNT, DATATYPE, OP, &
+                             COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDDATA(:)
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, OP, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVDATA(:)
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, OP8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  OP8 = OP
+  COMM8 = COMM
+
+  Call MPI_ALLREDUCE(SENDDATA, RECVDATA, COUNT8, DATATYPE8, OP8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_ALLREDUCE8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLREDUCE8_I4(SENDDATA, RECVDATA, COUNT, DATATYPE, OP, &
+                              COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDDATA(:)
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, OP, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVDATA(:)
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8, RECVDATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, OP8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDDATA8 = SENDDATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  OP8 = OP
+  COMM8 = COMM
+
+  Call MPI_ALLREDUCE(SENDDATA8, RECVDATA8, COUNT8, DATATYPE8, OP8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_ALLREDUCE8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ALLGATHERV8_R4(SENDAREA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                              RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, COMM
+  Real(Kind=JPRM), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    SENDAREA8, RECVAREA8
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(SENDAREA8(SIZE(SENDAREA)))
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLGATHERV(SENDAREA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                      RECVCOUNTS8, DISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDAREA8)
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_ALLGATHERV8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLGATHERV8_R8(SENDAREA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                              RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLGATHERV(SENDAREA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                      RECVCOUNTS8, DISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_ALLGATHERV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLGATHERV8_I4(SENDAREA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                               RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDAREA, RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDAREA8, RECVAREA8, RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(SENDAREA8(SIZE(SENDAREA)))
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLGATHERV(SENDAREA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                      RECVCOUNTS8, DISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDAREA8)
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_ALLGATHERV8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLGATHERV8_I1(SENDAREA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                               RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVAREA8, RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDAREA8, SENDCOUNT8, SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLGATHERV(SENDAREA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                      RECVCOUNTS8, DISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_ALLGATHERV8_I1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ALLTOALLV8_R8(SENDAREA, SENDCOUNTS, SDISPLS, SENDTYPE, &
+                             RECVAREA, RECVCOUNTS, RDISPLS, RECVTYPE, &
+                             COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDCOUNTS, SDISPLS, RECVCOUNTS, RDISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVTYPE, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDCOUNTS8, SDISPLS8, RECVCOUNTS8, RDISPLS8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(SENDCOUNTS8(SIZE(SENDCOUNTS)))
+  Allocate(SDISPLS8(SIZE(SDISPLS)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(RDISPLS8(SIZE(RDISPLS)))
+
+  SENDCOUNTS8 = SENDCOUNTS
+  SDISPLS8 = SDISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  RDISPLS8 = RDISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLTOALLV(SENDAREA, SENDCOUNTS8, SDISPLS8, SENDTYPE8, RECVAREA, &
+                     RECVCOUNTS8, RDISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(SENDCOUNTS8)
+  Deallocate(SDISPLS8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(RDISPLS8)
+
+End Subroutine MPI_ALLTOALLV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_ALLTOALLV8_I4(SENDAREA, SENDCOUNTS, SDISPLS, SENDTYPE, &
+                              RECVAREA, RECVCOUNTS, RDISPLS, RECVTYPE, &
+                              COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDAREA, SENDCOUNTS, SDISPLS, RECVCOUNTS, RDISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVTYPE, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDAREA8, SENDCOUNTS8, SDISPLS8, RECVAREA8, RECVCOUNTS8, RDISPLS8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVTYPE8, COMM8, IERROR8
+
+  Allocate(SENDAREA8(SIZE(SENDAREA)))
+  Allocate(SENDCOUNTS8(SIZE(SENDCOUNTS)))
+  Allocate(SDISPLS8(SIZE(SDISPLS)))
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(RDISPLS8(SIZE(RDISPLS)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNTS8 = SENDCOUNTS
+  SDISPLS8 = SDISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  RDISPLS8 = RDISPLS
+  RECVTYPE8 = RECVTYPE
+  COMM8 = COMM
+
+  Call MPI_ALLTOALLV(SENDAREA8, SENDCOUNTS8, SDISPLS8, SENDTYPE8, RECVAREA8, &
+                     RECVCOUNTS8, RDISPLS8, RECVTYPE8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDAREA8)
+  Deallocate(SENDCOUNTS8)
+  Deallocate(SDISPLS8)
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(RDISPLS8)
+
+End Subroutine MPI_ALLTOALLV8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BCAST8_R4(DATA, COUNT, DATATYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(INOUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_BCAST(DATA8, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8)
+
+  DATA = DATA8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BCAST8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_BCAST8_R8(DATA, COUNT, DATATYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(INOUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_BCAST(DATA, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BCAST8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_BCAST8_I4(DATA, COUNT, DATATYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(INOUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_BCAST(DATA8, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8)
+
+  DATA = DATA8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BCAST8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_BCAST8_I1(DATA, COUNT, DATATYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(INOUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_BCAST(DATA8, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8)
+
+  DATA = DATA8
+  IERROR = IERROR8
+
+End Subroutine MPI_BCAST8_I1
+
+! ---------------------------------------------------------
+Subroutine MPI_BCAST8_CH(DATA, COUNT, DATATYPE, ROOT, COMM, IERROR)
+
+  Character(Len=*), Intent(INOUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_BCAST(DATA, COUNT8, DATATYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BCAST8_CH
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_R4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BSEND8_R4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_R8(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_R42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BSEND8_R42
+
+! =========================================================
+Subroutine MPI_BSEND8_I42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPRM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BSEND8_I42
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_R82(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_R82
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_I4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_BSEND8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_I1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_I1
+
+! =========================================================
+Subroutine MPI_BSEND8_R4_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_R4_1
+
+! =========================================================
+Subroutine MPI_BSEND8_R8_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_R8_1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_BSEND8_CH(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Character(Len=*), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_BSEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BSEND8_CH
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_R4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_ISEND8_R4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_R8(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_R42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_ISEND8_R42
+
+! =========================================================
+Subroutine MPI_ISEND8_I42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPRM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_ISEND8_I42
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_R82(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRB), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_R82
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_I4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_ISEND8_I4
+
+! =========================================================
+Subroutine MPI_ISEND8_R4_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8):: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_R4_1
+
+! =========================================================
+Subroutine MPI_ISEND8_R8_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8) :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_R8_1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_I1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_I1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_ISEND8_CH(DATA, COUNT, DATATYPE, DEST, TAG, COMM, REQUEST, IERROR)
+
+  Character(Len=*), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_ISEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_ISEND8_CH
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_R4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_SEND8_R4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_R8(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_R42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_SEND8_R42
+
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_I42(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_SEND8_I42
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_R82(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:,:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_R82
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_I4(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_SEND8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_I1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_I1
+
+! =========================================================
+Subroutine MPI_SEND8_R4_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRM), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8) :: DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_R4_1
+
+! =========================================================
+Subroutine MPI_SEND8_R8_1(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8) :: DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  DATA8 = DATA
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA8, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_R8_1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SEND8_CH(DATA, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
+
+  Character(Len=*), Intent(IN) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, DEST, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  DEST8 = DEST
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_SEND(DATA, COUNT8, DATATYPE8, DEST8, TAG8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_SEND8_CH
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_IREAD_SHARED8_R8(FH, BUF, COUNT, DATATYPE, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, REQUEST8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_IREAD_SHARED(FH8, BUF, COUNT8, DATATYPE8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_IREAD_SHARED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_IREAD_SHARED8_I4(FH, BUF, COUNT, DATATYPE, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, REQUEST8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_IREAD_SHARED(FH8, BUF8, COUNT8, DATATYPE8, REQUEST8, IERROR8)
+
+  BUF = BUF8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_IREAD_SHARED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_IWRITE_SHARED8_R8(FH, BUF, COUNT, DATATYPE, REQUEST, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, REQUEST8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_IWRITE_SHARED(FH8, BUF, COUNT8, DATATYPE8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_IWRITE_SHARED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_IWRITE_SHARED8_I4(FH, BUF, COUNT, DATATYPE, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, BUF(:), COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, REQUEST8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  BUF8 = BUF
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_IWRITE_SHARED(FH8, BUF8, COUNT8, DATATYPE8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_IWRITE_SHARED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_READ_ORDERED8_R8(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_ORDERED(FH8, BUF, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_READ_ORDERED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_READ_ORDERED8_I4(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), STATUS(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_ORDERED(FH8, BUF8, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  BUF = BUF8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_READ_ORDERED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FREAD_ORDERED_BEGIN8_R8(FH, BUF, COUNT, DATATYPE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_ORDERED_BEGIN(FH8, BUF, COUNT8, DATATYPE8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_FREAD_ORDERED_BEGIN8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FREAD_ORDERED_BEGIN8_I4(FH, BUF, COUNT, DATATYPE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_ORDERED_BEGIN(FH8, BUF8, COUNT8, DATATYPE8, IERROR8)
+
+  BUF = BUF8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FREAD_ORDERED_BEGIN8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FREAD_ORDERED_END8_R8(FH, BUF, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    FH8, IERROR8
+
+  FH8 = FH
+
+  Call MPI_FILE_READ_ORDERED_END(FH8, BUF, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_FREAD_ORDERED_END8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FREAD_ORDERED_END8_I4(FH, BUF, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), STATUS(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+
+  Call MPI_FILE_READ_ORDERED_END(FH8, BUF8, STATUS8, IERROR8)
+
+  BUF = BUF8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FREAD_ORDERED_END8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_READ_SHARED8_R8(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_SHARED(FH8, BUF, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_READ_SHARED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_READ_SHARED8_I4(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), STATUS(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_READ_SHARED(FH8, BUF8, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  BUF = BUF8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_READ_SHARED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_WRITE_ORDERED8_R8(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_ORDERED(FH8, BUF, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_WRITE_ORDERED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_WRITE_ORDERED8_I4(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, BUF(:), COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  BUF8 = BUF
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_ORDERED(FH8, BUF8, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_WRITE_ORDERED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FWRITE_ORDERED_BEGIN8_R8(FH, BUF, COUNT, DATATYPE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_ORDERED_BEGIN(FH8, BUF, COUNT8, DATATYPE8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_FWRITE_ORDERED_BEGIN8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FWRITE_ORDERED_BEGIN8_I4(FH, BUF, COUNT, DATATYPE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_ORDERED_BEGIN(FH8, BUF8, COUNT8, DATATYPE8, IERROR8)
+
+  BUF = BUF8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FWRITE_ORDERED_BEGIN8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FWRITE_ORDERED_END8_R8(FH, BUF, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, STATUS(:)
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    FH8, IERROR8
+
+  FH8 = FH
+  STATUS8 = STATUS
+
+  Call MPI_FILE_WRITE_ORDERED_END(FH8, BUF, STATUS8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_FWRITE_ORDERED_END8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FWRITE_ORDERED_END8_I4(FH, BUF, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, STATUS(:)
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    BUF(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  STATUS8 = STATUS
+
+  Call MPI_FILE_WRITE_ORDERED_END(FH8, BUF8, STATUS8, IERROR8)
+
+  BUF = BUF8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FWRITE_ORDERED_END8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_FILE_WRITE_SHARED8_R8(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    BUF
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  FH8 = FH
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_SHARED(FH8, BUF, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_WRITE_SHARED8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_WRITE_SHARED8_I4(FH, BUF, COUNT, DATATYPE, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH, BUF(:), COUNT, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUF8
+  Integer(Kind=8) :: &
+    FH8, COUNT8, DATATYPE8, IERROR8
+
+  Allocate(BUF8(SIZE(BUF)))
+
+  FH8 = FH
+  BUF8 = BUF
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+
+  Call MPI_FILE_WRITE_SHARED(FH8, BUF8, COUNT8, DATATYPE8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(BUF8)
+
+End Subroutine MPI_FILE_WRITE_SHARED8_I4
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_GATHER8_R8_1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                            RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHER(SENDDATA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                  RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_GATHER8_R8_1
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHER8_I1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                          RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDDATA, SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RECVAREA, IERROR
+
+  Integer(Kind=8) :: &
+    SENDDATA8, RECVAREA8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHER(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                  RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+End Subroutine MPI_GATHER8_I1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_R8(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_GATHERV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_R8S(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_GATHERV8_R8S
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_R4(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRM), Dimension(:), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8, RECVAREA8
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_GATHERV8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_R4S(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRM), Dimension(:), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRM), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8
+  Real(Kind=8) :: RECVAREA8
+  Integer(Kind=8) :: RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+
+End Subroutine MPI_GATHERV8_R4S
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_I4(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDDATA, RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RECVAREA(:), IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8, RECVAREA8, RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+  Allocate(RECVAREA8(SIZE(RECVAREA)))
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+  Deallocate(RECVAREA8)
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_GATHERV8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_I4S(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM, RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RECVAREA, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDDATA8
+  Integer(Kind=8) :: &
+    RECVAREA8, RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDDATA8(SIZE(SENDDATA)))
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(SENDDATA8)
+
+End Subroutine MPI_GATHERV8_I4S
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_I4S_1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM, RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RECVAREA, IERROR
+
+  Integer(Kind=8) :: &
+    SENDDATA8
+  Integer(Kind=8) :: &
+    RECVAREA8, RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+End Subroutine MPI_GATHERV8_I4S_1
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_I1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                           RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDDATA, SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RECVAREA, IERROR
+
+  Integer(Kind=8) :: &
+    SENDDATA8, RECVAREA8
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDDATA8 = SENDDATA
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA8, SENDCOUNT8, SENDTYPE8, RECVAREA8, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVAREA = RECVAREA8
+  IERROR = IERROR8
+
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_GATHERV8_I1
+
+! ---------------------------------------------------------
+Subroutine MPI_GATHERV8_R8_1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                             RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(RECVCOUNTS8(SIZE(RECVCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(RECVCOUNTS8)
+  Deallocate(DISPLS8)
+
+End Subroutine MPI_GATHERV8_R8_1
+
+! =========================================================
+Subroutine MPI_GATHERV8_R8S_1(SENDDATA, SENDCOUNT, SENDTYPE, RECVAREA, &
+                             RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERROR)
+
+  Real(Kind=JPRB), Intent(IN) :: &
+    SENDDATA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    RECVCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDCOUNT, SENDTYPE, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Intent(OUT) :: &
+    RECVAREA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    RECVCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDCOUNT8, SENDTYPE8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  SENDCOUNT8 = SENDCOUNT
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNTS8 = RECVCOUNTS
+  DISPLS8 = DISPLS
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_GATHERV(SENDDATA, SENDCOUNT8, SENDTYPE8, RECVAREA, &
+                   RECVCOUNTS8, DISPLS8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_GATHERV8_R8S_1
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R4(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRM), Dimension(:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_RECV8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R8(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R42(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRM), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_RECV8_R42
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_I42(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_RECV8_I42
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R82(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRB), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_R82
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_I4(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    DATA, STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_RECV8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_I1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    DATA, IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_I1
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R4_1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Real(Kind=JPRM), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8) :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  DATA = DATA8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_R4_1
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_R8_1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Real(Kind=JPRB), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_R8_1
+
+! ---------------------------------------------------------
+Subroutine MPI_RECV8_CH(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    STATUS
+  Character(Len=*), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_RECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_RECV8_CH
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R4(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRM), Dimension(:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_IRECV8_R4
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R8(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R42(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRM), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_IRECV8_R42
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R82(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRB), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_R82
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_I4(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    DATA(:), REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_IRECV8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_I42(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Dimension(:,:), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  Allocate(DATA8(SIZE(DATA,Dim=1),SIZE(DATA,Dim=2)))
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+  Deallocate(DATA8)
+
+End Subroutine MPI_IRECV8_I42
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_I1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    DATA, REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_I1
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R4_1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRM), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Real(Kind=8) :: &
+    DATA8
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA8, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  DATA = DATA8
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_R4_1
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_R8_1(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Real(Kind=JPRB), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_R8_1
+
+! ---------------------------------------------------------
+Subroutine MPI_IRECV8_CH(DATA, COUNT, DATATYPE, SOURCE, TAG, COMM, REQUEST, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT, DATATYPE, SOURCE, TAG, COMM
+  Character(Len=*), Intent(OUT) :: &
+    DATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    REQUEST, IERROR
+
+  Integer(Kind=8) :: &
+    COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8
+
+  COUNT8 = COUNT
+  DATATYPE8 = DATATYPE
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IRECV(DATA, COUNT8, DATATYPE8, SOURCE8, TAG8, COMM8, REQUEST8, IERROR8)
+
+  REQUEST = REQUEST8
+  IERROR = IERROR8
+
+End Subroutine MPI_IRECV8_CH
+
+! =========================================================
+! ---------------------------------------------------------
+Subroutine MPI_SCATTERV8_R8(SENDAREA, SENDCOUNTS, DISPLS, SENDTYPE, &
+                            RECVDATA, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+  
+  Real(Kind=JPRB), Dimension(:), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVDATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    SENDAREA8, RECVDATA8
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDAREA8(SIZE(SENDAREA)))
+  Allocate(SENDCOUNTS8(SIZE(SENDCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNTS8 = SENDCOUNTS
+  DISPLS8 = DISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_SCATTERV(SENDAREA8, SENDCOUNTS8, DISPLS8, SENDTYPE8, &
+                    RECVDATA8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(SENDAREA8)
+  Deallocate(SENDCOUNTS8)
+  Deallocate(DISPLS8)
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_SCATTERV8_R8
+
+! ---------------------------------------------------------
+Subroutine MPI_SCATTERV8_R8S(SENDAREA, SENDCOUNTS, DISPLS, SENDTYPE, &
+                            RECVDATA, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+  
+  Real(Kind=JPRB), Intent(IN) :: &
+    SENDAREA
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM, SENDCOUNTS, DISPLS
+  Real(Kind=JPRB), Dimension(:), Intent(OUT) :: &
+    RECVDATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Real(Kind=8), Dimension(:), Allocatable :: &
+    RECVDATA8
+  Real(Kind=8) :: &
+    SENDAREA8
+  Integer(Kind=8) :: &
+    SENDCOUNTS8, DISPLS8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNTS8 = SENDCOUNTS
+  DISPLS8 = DISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_SCATTERV(SENDAREA8, SENDCOUNTS8, DISPLS8, SENDTYPE8, &
+                    RECVDATA8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_SCATTERV8_R8S
+
+! ---------------------------------------------------------
+Subroutine MPI_SCATTERV8_I4(SENDAREA, SENDCOUNTS, DISPLS, SENDTYPE, &
+                            RECVDATA, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+  
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    SENDAREA, SENDCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVDATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    SENDAREA8, SENDCOUNTS8, DISPLS8, RECVDATA8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(SENDAREA8(SIZE(SENDAREA)))
+  Allocate(SENDCOUNTS8(SIZE(SENDCOUNTS)))
+  Allocate(DISPLS8(SIZE(DISPLS)))
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNTS8 = SENDCOUNTS
+  DISPLS8 = DISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_SCATTERV(SENDAREA8, SENDCOUNTS8, DISPLS8, SENDTYPE8, &
+                    RECVDATA8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(SENDAREA8)
+  Deallocate(SENDCOUNTS8)
+  Deallocate(DISPLS8)
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_SCATTERV8_I4
+
+! =========================================================
+Subroutine MPI_SCATTERV8_I4S(SENDAREA, SENDCOUNTS, DISPLS, SENDTYPE, &
+                            RECVDATA, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
+  
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDAREA, SENDCOUNTS, DISPLS
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    RECVDATA
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    SENDAREA8, SENDCOUNTS8, DISPLS8
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RECVDATA8
+  Integer(Kind=8) :: &
+    SENDTYPE8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8
+
+  Allocate(RECVDATA8(SIZE(RECVDATA)))
+
+  SENDAREA8 = SENDAREA
+  SENDCOUNTS8 = SENDCOUNTS
+  DISPLS8 = DISPLS
+  SENDTYPE8 = SENDTYPE
+  RECVCOUNT8 = RECVCOUNT
+  RECVTYPE8 = RECVTYPE
+  ROOT8 = ROOT
+  COMM8 = COMM
+
+  Call MPI_SCATTERV(SENDAREA8, SENDCOUNTS8, DISPLS8, SENDTYPE8, &
+                    RECVDATA8, RECVCOUNT8, RECVTYPE8, ROOT8, COMM8, IERROR8)
+
+  RECVDATA = RECVDATA8
+  IERROR = IERROR8
+
+  Deallocate(RECVDATA8)
+
+End Subroutine MPI_SCATTERV8_I4S
+
+! =========================================================
+! =========================================================
+! =========================================================
+
+#endif
+End Module MPI4TO8_M
diff --git a/odb/src/extras/ifsaux/module/mpi4to8_s.F90 b/odb/src/extras/ifsaux/module/mpi4to8_s.F90
new file mode 100644
index 0000000..0fa4168
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpi4to8_s.F90
@@ -0,0 +1,708 @@
+Module MPI4TO8_S
+#ifdef USE_8_BYTE_WORDS
+
+Use PARKIND1, Only : JPIM
+USE MPL_MPIF
+
+Implicit None
+
+Private :: STATUS8
+  Integer(Kind=8), Dimension(MPI_STATUS_SIZE) :: STATUS8
+
+Interface MPI_GET_COUNT8
+  Module Procedure MPI_GET_COUNT8_I4, MPI_GET_COUNT8_I4_1
+End Interface MPI_GET_COUNT8
+
+Interface MPI_WAITALL8
+  Module Procedure MPI_WAITALL8_I4, MPI_WAITALL8_I4_1
+End Interface MPI_WAITALL8
+
+Interface MPI_WAIT8
+  Module Procedure MPI_WAIT8_I4, MPI_WAIT8_I4_1
+End Interface MPI_WAIT8
+
+Public
+
+Contains
+
+! ---------------------------------------------------------
+Subroutine MPI_ABORT8(COMM, ERRORCODE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM, ERRORCODE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, ERRORCODE8, IERROR8
+
+  COMM8 = COMM
+  ERRORCODE8 = ERRORCODE
+
+  Call MPI_ABORT(COMM8, ERRORCODE8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_ABORT8
+
+! ---------------------------------------------------------
+Subroutine MPI_BARRIER8(COMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, IERROR8
+
+  COMM8 = COMM
+
+  Call MPI_BARRIER(COMM8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_BARRIER8
+
+! ---------------------------------------------------------
+Subroutine MPI_BUFFER_DETACH8(BUFFER_ADDR, SZ, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: &
+    BUFFER_ADDR
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    SZ, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUFFER_ADDR8
+  Integer(Kind=8) :: &
+    SZ8, IERROR8
+
+  Allocate(BUFFER_ADDR8(SIZE(BUFFER_ADDR)))
+
+  Call MPI_BUFFER_DETACH(BUFFER_ADDR8, SZ8, IERROR8)
+
+  BUFFER_ADDR = BUFFER_ADDR8
+  SZ = SZ8
+  IERROR = IERROR8
+
+  Deallocate(BUFFER_ADDR8)
+
+End Subroutine MPI_BUFFER_DETACH8
+
+! ---------------------------------------------------------
+Subroutine MPI_BUFFER_ATTACH8(BUFFER_ADDR, SZ, IERROR)
+
+  Integer(Kind=JPIM), Dimension(:), Intent(IN) :: &
+    BUFFER_ADDR
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SZ
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    BUFFER_ADDR8
+  Integer(Kind=8) :: &
+    SZ8, IERROR8
+
+  Allocate(BUFFER_ADDR8(SIZE(BUFFER_ADDR)))
+
+  BUFFER_ADDR8 = BUFFER_ADDR
+  SZ8 = SZ
+
+  Call MPI_BUFFER_ATTACH(BUFFER_ADDR8, SZ8, IERROR8)
+
+  IERROR = IERROR8
+
+  Deallocate(BUFFER_ADDR8)
+
+End Subroutine MPI_BUFFER_ATTACH8
+
+! ---------------------------------------------------------
+Subroutine MPI_CART_COORDS8(COMM, RANK, MAXDIMS, COORDS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM, RANK, MAXDIMS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+  Integer(Kind=JPIM), Dimension(:), Intent(OUT) :: COORDS
+
+  Integer(Kind=8), Dimension(:), Allocatable :: COORDS8
+  Integer(Kind=8) :: &
+    COMM8, RANK8, MAXDIMS8, IERROR8
+
+  Allocate(COORDS8(Size(COORDS)))
+
+  COMM8 = COMM
+  RANK8 = RANK
+  MAXDIMS8 = MAXDIMS
+
+  Call MPI_CART_COORDS(COMM8, RANK8, MAXDIMS8, COORDS8, IERROR8)
+
+  COORDS = COORDS8
+  IERROR = IERROR8
+
+  Deallocate(COORDS8)
+
+End Subroutine MPI_CART_COORDS8
+
+! ---------------------------------------------------------
+Subroutine MPI_CART_CREATE8(COMM_OLD, NDIMS, DIMS, PERIODS, REORDER, COMM_CART, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM_OLD, NDIMS, DIMS(:)
+  Logical(Kind=JPIM), Intent(IN) :: &
+    PERIODS(:), REORDER
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    COMM_CART, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    DIMS8
+  Integer(Kind=8) :: &
+    COMM_OLD8, NDIMS8, COMM_CART8, IERROR8
+  Logical(Kind=8), Dimension(:), Allocatable :: &
+    PERIODS8
+  Logical(Kind=8) :: &
+    REORDER8
+
+  Allocate(DIMS8(SIZE(DIMS)))
+  Allocate(PERIODS8(SIZE(PERIODS)))
+
+  COMM_OLD8 = COMM_OLD
+  NDIMS8 = NDIMS
+  DIMS8 = DIMS
+  PERIODS8 = PERIODS
+  REORDER8 = REORDER
+
+  Call MPI_CART_CREATE(COMM_OLD8, NDIMS8, DIMS8, PERIODS8, REORDER8, COMM_CART8, IERROR8)
+
+  COMM_CART =  COMM_CART8
+  IERROR  = IERROR8
+
+  Deallocate(DIMS8)
+  Deallocate(PERIODS8)
+
+End Subroutine MPI_CART_CREATE8
+
+! ---------------------------------------------------------
+Subroutine MPI_CART_RANK8(COMM, COORDS, RANK, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Integer(Kind=JPIM), Intent(IN), Dimension(:) :: COORDS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RANK, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: COORDS8
+  Integer(Kind=8) :: &
+    COMM8, RANK8, IERROR8
+
+  Allocate(COORDS8(Size(COORDS)))
+
+  COMM8 = COMM
+  COORDS8 = COORDS
+
+  Call MPI_CART_RANK(COMM8, COORDS8, RANK8, IERROR8)
+
+  RANK = RANK8
+  IERROR = IERROR8
+
+  Deallocate(COORDS8)
+
+End Subroutine MPI_CART_RANK8
+
+! ---------------------------------------------------------
+Subroutine MPI_CART_SUB8(COMM, REMAIN_DIMS, NEWCOMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Logical(Kind=JPIM), Intent(IN), Dimension(:) :: &
+    REMAIN_DIMS
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    NEWCOMM, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, NEWCOMM8, IERROR8
+  Logical(Kind=8), Dimension(:), Allocatable :: &
+    REMAIN_DIMS8
+
+  Allocate(REMAIN_DIMS8(Size(REMAIN_DIMS)))
+
+  COMM8 = COMM
+  REMAIN_DIMS8 = REMAIN_DIMS
+
+  Call MPI_CART_SUB(COMM8, REMAIN_DIMS8, NEWCOMM8, IERROR8)
+
+  NEWCOMM = NEWCOMM8
+  IERROR = IERROR8
+
+  Deallocate(REMAIN_DIMS8)
+
+End Subroutine MPI_CART_SUB8
+
+! ---------------------------------------------------------
+Subroutine MPI_COMM_CREATE8(COMM, GROUP, NEWCOMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM, GROUP
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    NEWCOMM, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, GROUP8, NEWCOMM8, IERROR8
+
+  COMM8 = COMM
+  GROUP8 = GROUP
+
+  Call MPI_COMM_CREATE(COMM8, GROUP8, NEWCOMM8, IERROR8)
+
+  NEWCOMM = NEWCOMM8
+  IERROR = IERROR8
+
+End Subroutine MPI_COMM_CREATE8
+
+! ---------------------------------------------------------
+Subroutine MPI_COMM_GROUP8(COMM, GROUP, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    GROUP, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, GROUP8, IERROR8
+
+  COMM8 = COMM
+
+  Call MPI_COMM_GROUP(COMM8, GROUP8, IERROR8)
+
+  GROUP = GROUP8
+  IERROR = IERROR8
+
+End Subroutine MPI_COMM_GROUP8
+
+! ---------------------------------------------------------
+Subroutine MPI_COMM_RANK8(COMM, RANK, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RANK, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, RANK8, IERROR8
+
+  COMM8 = COMM
+
+  Call MPI_COMM_RANK(COMM8, RANK8, IERROR8)
+
+  RANK = RANK8
+  IERROR = IERROR8
+
+End Subroutine MPI_COMM_RANK8
+
+! ---------------------------------------------------------
+Subroutine MPI_COMM_SIZE8(COMM, SIZE, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    SIZE, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, SIZE8, IERROR8
+
+  COMM8 = COMM
+
+  Call MPI_COMM_SIZE(COMM8, SIZE8, IERROR8)
+
+  SIZE = SIZE8
+  IERROR = IERROR8
+
+End Subroutine MPI_COMM_SIZE8
+
+! ---------------------------------------------------------
+Subroutine MPI_COMM_SPLIT8(COMM, COLOR, KEY, NEWCOMM, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM, COLOR, KEY
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    NEWCOMM, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, COLOR8, KEY8, NEWCOMM8, IERROR8
+
+  COMM8 = COMM
+  COLOR8 = COLOR
+  KEY8 = KEY
+
+  Call MPI_COMM_SPLIT(COMM8, COLOR8, KEY8, NEWCOMM8, IERROR8)
+
+  NEWCOMM = NEWCOMM8
+  IERROR = IERROR8
+
+End Subroutine MPI_COMM_SPLIT8
+
+! ---------------------------------------------------------
+Subroutine MPI_ERROR_STRING8(ERRORCODE, STRING, RESULTLEN, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    ERRORCODE
+  Character(Len=*), Intent(OUT) :: &
+    STRING
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    RESULTLEN, IERROR
+
+  Integer(Kind=8) :: &
+    ERRORCODE8, RESULTLEN8, IERROR8
+
+  ERRORCODE8 = ERRORCODE
+
+  Call MPI_ERROR_STRING(ERRORCODE8, STRING, RESULTLEN8, IERROR8)
+
+  RESULTLEN = RESULTLEN8
+  IERROR = IERROR8
+
+End Subroutine MPI_ERROR_STRING8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_CLOSE8(FH, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    FH
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    FH8, IERROR8
+
+  FH8 = FH
+
+  Call MPI_FILE_CLOSE(FH8, IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_CLOSE8
+
+! ---------------------------------------------------------
+Subroutine MPI_FILE_OPEN8(COMM, FILENAME, AMODE, INFO, FH, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COMM, AMODE, INFO
+  Character(Len=*), Intent(IN) :: &
+    FILENAME
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    FH, IERROR
+
+  Integer(Kind=8) :: &
+    COMM8, AMODE8, INFO8, FH8, IERROR8
+
+  COMM8 = COMM
+  AMODE8 = AMODE
+  INFO8 = INFO
+
+  Call MPI_FILE_OPEN(COMM8, FILENAME, AMODE8, INFO8, FH8, IERROR8)
+
+  FH = FH8
+  IERROR = IERROR8
+
+End Subroutine MPI_FILE_OPEN8
+
+! ---------------------------------------------------------
+Subroutine MPI_FINALIZE8(IERROR)
+
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    IERROR8
+
+  Call MPI_FINALIZE(IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_FINALIZE8
+
+! ---------------------------------------------------------
+Subroutine MPI_GET_COUNT8_I4(STATUS, DATATYPE, COUNT, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    STATUS(:), DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    COUNT, IERROR
+
+  Integer(Kind=8) :: &
+    DATATYPE8, COUNT8, IERROR8
+
+  STATUS8 = STATUS
+  DATATYPE8 = DATATYPE
+
+  Call MPI_GET_COUNT(STATUS8, DATATYPE8, COUNT8, IERROR8)
+
+  COUNT = COUNT8
+  IERROR = IERROR8
+
+End Subroutine MPI_GET_COUNT8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_GET_COUNT8_I4_1(STATUS, DATATYPE, COUNT, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    STATUS, DATATYPE
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    COUNT, IERROR
+
+  Integer(Kind=8) :: &
+    DATATYPE8, COUNT8, IERROR8, STATUS8
+
+  STATUS8 = STATUS
+  DATATYPE8 = DATATYPE
+
+  Call MPI_GET_COUNT(STATUS8, DATATYPE8, COUNT8, IERROR8)
+
+  COUNT = COUNT8
+  IERROR = IERROR8
+
+End Subroutine MPI_GET_COUNT8_I4_1
+
+! ---------------------------------------------------------
+Subroutine MPI_GROUP_INCL8(GROUP1, N, RANKS, NEWGROUP, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    GROUP1, N, RANKS(:)
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    NEWGROUP, IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    RANKS8
+  Integer(Kind=8) :: &
+    GROUP18, N8, NEWGROUP8, IERROR8
+
+  Allocate(RANKS8(SIZE(RANKS)))
+
+  GROUP18 = GROUP1
+  N8 = N
+  RANKS8 = RANKS
+
+  Call MPI_GROUP_INCL(GROUP18, N8, RANKS8, NEWGROUP8, IERROR8)
+
+  NEWGROUP = NEWGROUP8
+  IERROR = IERROR8
+
+  Deallocate(RANKS8)
+
+End Subroutine MPI_GROUP_INCL8
+
+! ---------------------------------------------------------
+Subroutine MPI_INIT8(IERROR)
+
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    IERROR8
+
+  Call MPI_INIT(IERROR8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_INIT8
+
+! ---------------------------------------------------------
+Subroutine MPI_INITIALIZED8(FLAG, IERROR)
+
+  Logical(Kind=JPIM), Intent(OUT) :: &
+    FLAG
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Logical(Kind=8) :: &
+    FLAG8
+  Integer(Kind=8) :: &
+    IERROR8
+
+
+  Call MPI_INITIALIZED(FLAG8, IERROR8)
+
+  FLAG = FLAG8
+  IERROR = IERROR8
+
+End Subroutine MPI_INITIALIZED8
+
+! ---------------------------------------------------------
+Subroutine MPI_IPROBE8(SOURCE, TAG, COMM, FLAG, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SOURCE, TAG, COMM
+  Logical(Kind=JPIM), Intent(OUT) :: &
+    FLAG
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    SOURCE8, TAG8, COMM8, IERROR8
+  Logical(Kind=8) :: &
+    FLAG8
+
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_IPROBE(SOURCE8, TAG8, COMM8, FLAG8, STATUS8, IERROR8)
+
+  FLAG = FLAG8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_IPROBE8
+
+! ---------------------------------------------------------
+Subroutine MPI_PROBE8(SOURCE, TAG, COMM, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    SOURCE, TAG, COMM
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    SOURCE8, TAG8, COMM8, IERROR8
+
+  SOURCE8 = SOURCE
+  TAG8 = TAG
+  COMM8 = COMM
+
+  Call MPI_PROBE(SOURCE8, TAG8, COMM8, STATUS8, IERROR8)
+
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_PROBE8
+
+! ---------------------------------------------------------
+Subroutine MPI_WAIT8_I4(REQUEST, STATUS, IERROR)
+
+  Integer(Kind=JPIM), Intent(INOUT) :: &
+    REQUEST
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS(:), IERROR
+
+  Integer(Kind=8) :: &
+    REQUEST8, IERROR8
+  Integer(Kind=8), Dimension(:), Allocatable :: STATUS8
+
+  Allocate(STATUS8(Size(STATUS)))
+
+  REQUEST8 = REQUEST
+
+  Call MPI_WAIT(REQUEST8, STATUS8, IERROR8)
+
+  REQUEST = REQUEST8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+  Deallocate(STATUS8)
+
+End Subroutine MPI_WAIT8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_WAIT8_I4_1(REQUEST, STATUS, IERROR)
+
+  Integer(Kind=JPIM) :: &
+    REQUEST
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    STATUS, IERROR
+
+  Integer(Kind=8) :: &
+    REQUEST8, IERROR8, STATUS8
+
+  REQUEST8 = REQUEST
+
+  Call MPI_WAIT(REQUEST8, STATUS8, IERROR8)
+
+  REQUEST = REQUEST8
+  STATUS = STATUS8
+  IERROR = IERROR8
+
+End Subroutine MPI_WAIT8_I4_1
+
+! ---------------------------------------------------------
+Subroutine MPI_WAITALL8_I4(COUNT, ARRAY_OF_REQUESTS, ARRAY_OF_STATUSES, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT
+  Integer(Kind=JPIM), Dimension(:), Intent(INOUT) :: &
+    ARRAY_OF_REQUESTS
+  Integer(Kind=JPIM), Dimension(:,:), Intent(OUT) :: &
+    ARRAY_OF_STATUSES
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8), Dimension(:), Allocatable :: &
+    ARRAY_OF_REQUESTS8
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    ARRAY_OF_STATUSES8
+  Integer(Kind=8) :: &
+    COUNT8, IERROR8
+
+  Integer :: N
+
+  COUNT8 = COUNT
+
+  Allocate(ARRAY_OF_REQUESTS8(SIZE(ARRAY_OF_REQUESTS)))
+  N = SIZE(ARRAY_OF_STATUSES) / MPI_STATUS_SIZE
+  Allocate(ARRAY_OF_STATUSES8(MPI_STATUS_SIZE,N))
+
+  ARRAY_OF_REQUESTS8 = ARRAY_OF_REQUESTS
+
+  Call MPI_WAITALL(COUNT8, ARRAY_OF_REQUESTS8, ARRAY_OF_STATUSES8, IERROR8)
+
+  ARRAY_OF_REQUESTS = ARRAY_OF_REQUESTS8
+  ARRAY_OF_STATUSES = ARRAY_OF_STATUSES8
+
+  Deallocate(ARRAY_OF_REQUESTS8)
+  Deallocate(ARRAY_OF_STATUSES8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_WAITALL8_I4
+
+! ---------------------------------------------------------
+Subroutine MPI_WAITALL8_I4_1(COUNT, ARRAY_OF_REQUESTS, ARRAY_OF_STATUSES, IERROR)
+
+  Integer(Kind=JPIM), Intent(IN) :: &
+    COUNT
+  Integer(Kind=JPIM) :: &
+    ARRAY_OF_REQUESTS
+  Integer(Kind=JPIM), Dimension(:,:), Intent(OUT) :: &
+    ARRAY_OF_STATUSES
+  Integer(Kind=JPIM), Intent(OUT) :: &
+    IERROR
+
+  Integer(Kind=8) :: &
+    ARRAY_OF_REQUESTS8
+  Integer(Kind=8), Dimension(:,:), Allocatable :: &
+    ARRAY_OF_STATUSES8
+  Integer(Kind=8) :: &
+    COUNT8, IERROR8
+
+  Integer :: N
+
+  COUNT8 = COUNT
+
+  N = SIZE(ARRAY_OF_STATUSES) / MPI_STATUS_SIZE
+  Allocate(ARRAY_OF_STATUSES8(MPI_STATUS_SIZE,N))
+
+  ARRAY_OF_REQUESTS8 = ARRAY_OF_REQUESTS
+
+  Call MPI_WAITALL(COUNT8, ARRAY_OF_REQUESTS8, ARRAY_OF_STATUSES8, IERROR8)
+
+  ARRAY_OF_REQUESTS = ARRAY_OF_REQUESTS8
+  ARRAY_OF_STATUSES = ARRAY_OF_STATUSES8
+
+  Deallocate(ARRAY_OF_STATUSES8)
+
+  IERROR = IERROR8
+
+End Subroutine MPI_WAITALL8_I4_1
+
+#endif
+End Module MPI4TO8_S
diff --git a/odb/src/extras/ifsaux/module/mpl_abort_mod.F90 b/odb/src/extras/ifsaux/module/mpl_abort_mod.F90
new file mode 100644
index 0000000..20b12a3
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_abort_mod.F90
@@ -0,0 +1,48 @@
+MODULE MPL_ABORT_MOD
+
+USE MPL_DATA_MODULE
+USE MPL_MPIF
+USE OML_MOD
+USE YOMABRT
+USE SDL_MOD, ONLY : SDL_TRACEBACK, SDL_DISABORT
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+PUBLIC MPL_ABORT
+
+CONTAINS 
+
+SUBROUTINE MPL_ABORT(CDMESSAGE)
+
+IMPLICIT NONE
+
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDMESSAGE
+INTEGER(KIND=JPIM) :: IRETURN_CODE,IERROR,ITID
+ITID=OML_MY_THREAD()
+
+CLOSE(MPL_UNIT)
+CALL FLUSH(0)
+CALL ec_sleep(1) ! This rather than 'CALL SYSTEM("sleep 1")' ; see code ../support/env.c
+
+!------Traceback from only one thread
+CALL OML_SET_LOCK(MYLOCK=MAB_LOCK(1))
+IF(MAB_CNT == 0) THEN
+  WRITE(MPL_ERRUNIT,'(A,I6,A,I6)') 'MPL_ABORT: CALLED FROM PROCESSOR ',MPL_RANK,' THRD',ITID
+  IF(PRESENT(CDMESSAGE)) THEN
+    WRITE(MPL_ERRUNIT,*) 'MPL_ABORT: THRD',ITID,"  ",CDMESSAGE
+  ENDIF
+  MAB_CNT=1
+  CALL SDL_TRACEBACK(ITID)
+  CALL FLUSH(0)
+  CALL ec_sleep(1) ! This rather than 'CALL SYSTEM("sleep 1")' ; see code ../support/env.c
+ENDIF
+CALL OML_UNSET_LOCK(MYLOCK=MAB_LOCK(1))
+! ------All threads wait till traceback done
+CALL FLUSH(0)
+CALL ec_sleep(1) ! This rather than 'CALL SYSTEM("sleep 1")' ; see code ../support/env.c
+
+CALL SDL_DISABORT(MPL_COMM_OML(ITID))
+
+END SUBROUTINE MPL_ABORT
+
+END MODULE MPL_ABORT_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_allgather_mod.F90 b/odb/src/extras/ifsaux/module/mpl_allgather_mod.F90
new file mode 100644
index 0000000..fdbd6fd
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_allgather_mod.F90
@@ -0,0 +1,79 @@
+MODULE MPL_ALLGATHER_MOD
+
+!**** MPL_ALLGATHER Send data to all processes
+
+!     Purpose.
+!     --------
+!     Send a message to all processes from a buffer.
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
+!                     REAL*4,or REAL*8, two dimensional array
+!                  or INTEGER scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_ALLGATHER
+
+!        Input required arguments :
+!        -------------------------
+!           PSENDBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           PRECVBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KRECVCOUNTS-number of elements received from each process
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KRECVDISPL -displacements in PRECVBUF at which to place 
+!                       the incoming data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_ALLGATHER aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-11-23
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_BARRIER_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITAG
+LOGICAL :: LLBARRIER
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+
+PUBLIC MPL_ALLGATHER
+
+CONTAINS
+
+SUBROUTINE MPL_ALLGATHER()
+return
+end SUBROUTINE MPL_ALLGATHER
+end MODULE MPL_ALLGATHER_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_allgatherv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_allgatherv_mod.F90
new file mode 100644
index 0000000..7499b92
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_allgatherv_mod.F90
@@ -0,0 +1,667 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE MPL_ALLGATHERV_MOD
+
+!**** MPL_ALLGATHERV Send data to all processes
+
+!     Purpose.
+!     --------
+!     Send a message to all processes from a buffer.
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
+!                     REAL*4,or REAL*8, two dimensional array
+!                  or INTEGER scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_ALLGATHERV
+
+!        Input required arguments :
+!        -------------------------
+!           PSENDBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           PRECVBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KRECVCOUNTS-number of elements received from each process
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KRECVDISPL -displacements in PRECVBUF at which to place 
+!                       the incoming data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_ALLGATHERV aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original:   2000-11-23
+!        Threadsafe: 2004-12-15  J.Hague
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_BARRIER_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+LOGICAL   :: LLABORT=.TRUE.
+LOGICAL   :: LLBARRIER
+
+INTERFACE MPL_ALLGATHERV
+MODULE PROCEDURE MPL_ALLGATHERV_REAL8,MPL_ALLGATHERV_REAL4,&
+                 MPL_ALLGATHERV_INT,  MPL_ALLGATHERV_INT_SCALAR
+END INTERFACE
+
+PUBLIC MPL_ALLGATHERV
+
+CONTAINS
+
+SUBROUTINE MPL_ALLGATHERV_PREAMB(KRECVCOUNTS,KCOMM,KRECVDISPL,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT
+INTEGER(KIND=JPIM) :: ITAG
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC
+INTEGER(KIND=JPIM) :: ITID
+INTEGER(KIND=JPIM),ALLOCATABLE :: IRECVDISPL(:)
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLGATHERV: MPL NOT INITIALISED ',LDABORT=LLABORT)
+ 
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+IF(SIZE(KRECVCOUNTS)  < IPL_NUMPROC) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_ALLGATHERV: ERROR KRECVCOUNTS dimension=',&
+   & SIZE(KRECVCOUNTS)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_ALLGATHERV: ERROR KRECVCOUNTS dimension is wrong',LDABORT=LLABORT)
+ENDIF
+
+ALLOCATE(IRECVDISPL(IPL_NUMPROC))
+
+IF(PRESENT(KRECVDISPL)) THEN
+  IRECVDISPL(:) = KRECVDISPL(:)
+ELSE
+  IRECVDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    IRECVDISPL(IR) = IRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+
+DO IR=1, IPL_NUMPROC
+  IF(IRECVDISPL(IR)+KRECVCOUNTS(IR) > IRECVCOUNT) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_ALLGATHERV:RECV BUFFER TOO SMALL  ', &
+     & IR,IRECVDISPL(IR),KRECVCOUNTS(IR),IRECVCOUNT
+    CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ENDDO
+
+DEALLOCATE(IRECVDISPL)
+
+END SUBROUTINE MPL_ALLGATHERV_PREAMB
+
+SUBROUTINE MPL_ALLGATHERV_REAL4(PSENDBUF,PRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_ALLGATHERV => MPI_ALLGATHERV8
+#endif
+
+
+
+REAL(KIND=JPRM)            :: PSENDBUF(:)
+REAL(KIND=JPRM)            :: PRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT
+INTEGER(KIND=JPIM) :: ITAG
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC
+INTEGER(KIND=JPIM) :: ITID
+INTEGER(KIND=JPIM),ALLOCATABLE :: IRECVDISPL(:)
+ITID = OML_MY_THREAD()
+ISENDCOUNT = SIZE(PSENDBUF)
+ISENDCOUNT = MAX(0,ISENDCOUNT)  ! Bug? on IBM
+IRECVCOUNT = SIZE(PRECVBUF)
+
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 4*(IRECVCOUNT - 1) .AND. &
+  & IRECVCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+!--------- Preamble repeated for threadsafe--------------
+! CALL MPL_ALLGATHERV_PREAMB(KRECVCOUNTS,KCOMM,KRECVDISPL,CDSTRING)
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+ALLOCATE(IRECVDISPL(IPL_NUMPROC))
+IF(PRESENT(KRECVDISPL)) THEN
+  IRECVDISPL(:) = KRECVDISPL(:)
+ELSE
+  IRECVDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    IRECVDISPL(IR) = IRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+!--------- End of Preamble --------------
+
+!Tournament table exchange
+
+IF(ICOMM == MPL_COMM .AND. .NOT. LUSEHLMPI) THEN
+  IERROR = 0
+  PRECVBUF(IRECVDISPL(MPL_RANK)+1:IRECVDISPL(MPL_RANK)+KRECVCOUNTS(MPL_RANK)) = &
+   & PSENDBUF(:)
+  ILIMIT = 0.9*MPL_MBX_SIZE/4
+  IMAXMSG = ILIMIT/2
+  LLBARRIER = IRECVCOUNT>ILIMIT
+  IBARRFREQ = MAX(1,ILIMIT/MAX(1,MAXVAL(KRECVCOUNTS))-1)
+  CALL MPL_BARRIER(ICOMM,CDSTRING)
+  DO JK=1,IPL_NUMPROC
+    IMYPAIR = MPL_OPPONENT(JK)
+    IF(JK > 1 .AND. LLBARRIER) THEN
+      IF(MOD(JK,IBARRFREQ) == 0) THEN
+        CALL MPL_BARRIER(ICOMM,CDSTRING)
+      ENDIF
+    ENDIF
+    IF(IMYPAIR == MPL_RANK .OR. IMYPAIR > IPL_NUMPROC) THEN
+      CYCLE
+    ENDIF
+    ICHUNKS = (MAX(ISENDCOUNT,KRECVCOUNTS(IMYPAIR))-1)/IMAXMSG+1
+    ISTS = 1
+    ISTR = IRECVDISPL(IMYPAIR)+1
+    DO JMESS=1,ICHUNKS
+      ITAG = 1900+JMESS
+      ILENS = MIN(ISENDCOUNT-ISTS+1,IMAXMSG)
+      IENS  = ISTS+ILENS-1
+      IF(ILENS > 0) THEN
+        CALL MPL_SEND(PSENDBUF(ISTS:IENS),KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        ISTS = ISTS+ILENS
+      ELSE
+        CALL MPL_SEND(IDUM,KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/SEND)',&
+       & CDSTRING,LDABORT=LLABORT)
+      IF(ISTR <= IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+        CALL MPL_RECV(PRECVBUF(ISTR:),KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(ISTR+IOUNT-1 > IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+          WRITE(MPL_ERRUNIT,'(A,5I10)')'WRONG  RECEIVE ', &
+           & IMYPAIR,ISTR,IOUNT,IRECVDISPL(IMYPAIR),KRECVCOUNTS(IMYPAIR)
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+        ISTR = ISTR+IOUNT
+      ELSE
+        CALL MPL_RECV(IDUM,KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+        & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(IOUNT /= 1) THEN
+          WRITE(MPL_ERRUNIT,'(A,4I10)')'WRONG DUMMY RECEIVE ', &
+           & IMYPAIR,IOUNT
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/RECV)',&
+       & CDSTRING,LDABORT=LLABORT)
+    ENDDO
+  ENDDO
+ELSE
+
+  IF(IPL_NUMPROC > 1) THEN
+    CALL MPI_ALLGATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL4),PRECVBUF(1),&
+     & KRECVCOUNTS,IRECVDISPL,INT(MPI_REAL4),ICOMM,IERROR)
+  ELSE
+    PRECVBUF(1:ISENDCOUNT) = PSENDBUF(1:ISENDCOUNT)
+    IERROR=0
+  ENDIF
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLGATHERV ',ISENDCOUNT,IRECVCOUNT,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+DEALLOCATE(IRECVDISPL)
+
+END SUBROUTINE MPL_ALLGATHERV_REAL4
+
+SUBROUTINE MPL_ALLGATHERV_REAL8(PSENDBUF,PRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_ALLGATHERV => MPI_ALLGATHERV8
+#endif
+
+
+
+REAL(KIND=JPRB)            :: PSENDBUF(:)
+REAL(KIND=JPRB)            :: PRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT
+INTEGER(KIND=JPIM) :: ITAG
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC
+INTEGER(KIND=JPIM) :: ITID,J
+INTEGER(KIND=JPIM),ALLOCATABLE :: IRECVDISPL(:)
+ITID = OML_MY_THREAD()
+ISENDCOUNT = SIZE(PSENDBUF)
+ISENDCOUNT = MAX(0,ISENDCOUNT)  ! Bug? on IBM
+IRECVCOUNT = SIZE(PRECVBUF)
+
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 8*(IRECVCOUNT - 1) .AND. &
+  & IRECVCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+!--------- Preamble repeated for threadsafe--------------
+! CALL MPL_ALLGATHERV_PREAMB(KRECVCOUNTS,KCOMM,KRECVDISPL,CDSTRING)
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+ALLOCATE(IRECVDISPL(IPL_NUMPROC))
+IF(PRESENT(KRECVDISPL)) THEN
+  DO J=1,MIN(SIZE(IRECVDISPL),SIZE(KRECVDISPL))
+    IRECVDISPL(J) = KRECVDISPL(J)
+  ENDDO
+ELSE
+  IRECVDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    IRECVDISPL(IR) = IRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+!--------- End of Preamble --------------
+
+!Tournament table exchange
+IERROR=0
+IF(ICOMM == MPL_COMM .AND. .NOT. LUSEHLMPI) THEN
+  IERROR = 0
+  PRECVBUF(IRECVDISPL(MPL_RANK)+1:IRECVDISPL(MPL_RANK)+KRECVCOUNTS(MPL_RANK)) = &
+   & PSENDBUF(:)
+  ILIMIT = 0.9*MPL_MBX_SIZE/8
+  IMAXMSG = ILIMIT/2
+  LLBARRIER = IRECVCOUNT>ILIMIT
+  IBARRFREQ = MAX(1,ILIMIT/MAX(1,MAXVAL(KRECVCOUNTS))-1)
+  CALL MPL_BARRIER(ICOMM,CDSTRING)
+  DO JK=1,IPL_NUMPROC
+    IMYPAIR = MPL_OPPONENT(JK)
+    IF(JK > 1 .AND. LLBARRIER) THEN
+      IF(MOD(JK,IBARRFREQ) == 0) THEN
+        CALL MPL_BARRIER(ICOMM,CDSTRING)
+      ENDIF
+    ENDIF
+    IF(IMYPAIR == MPL_RANK .OR. IMYPAIR > IPL_NUMPROC) THEN
+      CYCLE
+    ENDIF
+    ICHUNKS = (MAX(ISENDCOUNT,KRECVCOUNTS(IMYPAIR))-1)/IMAXMSG+1
+    ISTS = 1
+    ISTR = IRECVDISPL(IMYPAIR)+1
+    DO JMESS=1,ICHUNKS
+      ITAG = 1900+JMESS
+      ILENS = MIN(ISENDCOUNT-ISTS+1,IMAXMSG)
+      IENS  = ISTS+ILENS-1
+      IF(ILENS > 0) THEN
+        CALL MPL_SEND(PSENDBUF(ISTS:IENS),KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        ISTS = ISTS+ILENS
+      ELSE
+        CALL MPL_SEND(IDUM,KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/SEND)',& 
+       & CDSTRING,LDABORT=LLABORT)
+      IF(ISTR <= IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+        CALL MPL_RECV(PRECVBUF(ISTR:),KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(ISTR+IOUNT-1 > IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+          WRITE(MPL_ERRUNIT,'(A,5I10)')'WRONG  RECEIVE ', &
+           & IMYPAIR,ISTR,IOUNT,IRECVDISPL(IMYPAIR),KRECVCOUNTS(IMYPAIR)
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+        ISTR = ISTR+IOUNT
+      ELSE
+        CALL MPL_RECV(IDUM,KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+        & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(IOUNT /= 1) THEN
+          WRITE(MPL_ERRUNIT,'(A,4I10)')'WRONG DUMMY RECEIVE ', &
+           & IMYPAIR,IOUNT
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/RECV)',&
+       & CDSTRING,LDABORT=LLABORT)
+    ENDDO
+  ENDDO
+ELSE
+  IF(IPL_NUMPROC > 1) THEN
+    CALL MPI_ALLGATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL8),PRECVBUF(1),&
+     & KRECVCOUNTS,IRECVDISPL,INT(MPI_REAL8),ICOMM,IERROR)
+  ELSE
+    PRECVBUF(1:ISENDCOUNT) = PSENDBUF(1:ISENDCOUNT)
+    IERROR=0
+  ENDIF
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLGATHERV ',ISENDCOUNT,IRECVCOUNT,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,&
+   & LDABORT=LLABORT)
+ENDIF
+DEALLOCATE(IRECVDISPL)
+
+END SUBROUTINE MPL_ALLGATHERV_REAL8
+
+SUBROUTINE MPL_ALLGATHERV_INT(KSENDBUF,KRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_ALLGATHERV => MPI_ALLGATHERV8
+#endif
+
+
+
+INTEGER(KIND=JPIM)         :: KSENDBUF(:)
+INTEGER(KIND=JPIM)         :: KRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT
+INTEGER(KIND=JPIM) :: ITAG
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC
+INTEGER(KIND=JPIM) :: ITID
+INTEGER(KIND=JPIM),ALLOCATABLE :: IRECVDISPL(:)
+ITID = OML_MY_THREAD()
+ISENDCOUNT = SIZE(KSENDBUF)
+ISENDCOUNT = MAX(0,ISENDCOUNT)  ! Bug? on IBM
+IRECVCOUNT = SIZE(KRECVBUF)
+
+IF( (LOC(KSENDBUF(UBOUND(KSENDBUF,1))) - LOC(KSENDBUF(LBOUND(KSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(KRECVBUF(UBOUND(KRECVBUF,1))) - LOC(KRECVBUF(LBOUND(KRECVBUF,1)))) /= 4*(IRECVCOUNT - 1) .AND. &
+  & IRECVCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLGATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+!--------- Preamble repeated for threadsafe--------------
+! CALL MPL_ALLGATHERV_PREAMB(KRECVCOUNTS,KCOMM,KRECVDISPL,CDSTRING)
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+ALLOCATE(IRECVDISPL(IPL_NUMPROC))
+IF(PRESENT(KRECVDISPL)) THEN
+  IRECVDISPL(:) = KRECVDISPL(:)
+ELSE
+  IRECVDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    IRECVDISPL(IR) = IRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+!--------- End of Preamble --------------
+
+!Tournament table exchange
+IERROR=0
+IF(ICOMM == MPL_COMM .AND. .NOT. LUSEHLMPI) THEN
+  IERROR = 0
+  KRECVBUF(IRECVDISPL(MPL_RANK)+1:IRECVDISPL(MPL_RANK)+KRECVCOUNTS(MPL_RANK)) = &
+   & KSENDBUF(:)
+
+  ILIMIT = 0.9*MPL_MBX_SIZE/4
+  IMAXMSG = ILIMIT/2
+  LLBARRIER = IRECVCOUNT>ILIMIT
+  IBARRFREQ = MAX(1,ILIMIT/MAX(1,MAXVAL(KRECVCOUNTS))-1)
+  CALL MPL_BARRIER(ICOMM,CDSTRING)
+  DO JK=1,IPL_NUMPROC
+    IMYPAIR = MPL_OPPONENT(JK)
+    IF(JK > 1 .AND. LLBARRIER) THEN
+      IF(MOD(JK,IBARRFREQ) == 0) THEN
+        CALL MPL_BARRIER(ICOMM,CDSTRING)
+      ENDIF
+    ENDIF
+    IF(IMYPAIR == MPL_RANK .OR. IMYPAIR > IPL_NUMPROC) THEN
+      CYCLE
+    ENDIF
+    ICHUNKS = (MAX(ISENDCOUNT,KRECVCOUNTS(IMYPAIR))-1)/IMAXMSG+1
+    ISTS = 1
+    ISTR = IRECVDISPL(IMYPAIR)+1
+    DO JMESS=1,ICHUNKS
+      ITAG = 1900+JMESS
+      ILENS = MIN(ISENDCOUNT-ISTS+1,IMAXMSG)
+      IENS  = ISTS+ILENS-1
+      IF(ILENS > 0) THEN
+        CALL MPL_SEND(KSENDBUF(ISTS:IENS),KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        ISTS = ISTS+ILENS
+      ELSE
+        CALL MPL_SEND(IDUM,KTAG=ITAG,KDEST=IMYPAIR,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/SEND)', &
+       & CDSTRING,LDABORT=LLABORT)
+      IF(ISTR <= IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+        CALL MPL_RECV(KRECVBUF(ISTR:),KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+         & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(ISTR+IOUNT-1 > IRECVDISPL(IMYPAIR)+KRECVCOUNTS(IMYPAIR)) THEN
+          WRITE(MPL_ERRUNIT,'(A,5I10)')'WRONG  RECEIVE ', &
+           & IMYPAIR,ISTR,IOUNT,IRECVDISPL(IMYPAIR),KRECVCOUNTS(IMYPAIR)
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+        ISTR = ISTR+IOUNT
+      ELSE
+        CALL MPL_RECV(IDUM,KTAG=ITAG,KSOURCE=IMYPAIR,KOUNT=IOUNT,&
+        & KERROR=IERROR,CDSTRING=CDSTRING)
+        IF(IOUNT /= 1) THEN
+          WRITE(MPL_ERRUNIT,'(A,4I10)')'WRONG DUMMY RECEIVE ', &
+           & IMYPAIR,IOUNT
+          CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+        ENDIF
+      ENDIF
+      IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV(TT/RECV)',&
+       & CDSTRING,LDABORT=LLABORT)
+    ENDDO
+  ENDDO
+ELSE
+  IF(IPL_NUMPROC > 1) THEN
+    CALL MPI_ALLGATHERV(KSENDBUF(1),ISENDCOUNT,INT(MPI_INTEGER),KRECVBUF(1),&
+     & KRECVCOUNTS,IRECVDISPL,INT(MPI_INTEGER),ICOMM,IERROR)
+  ELSE
+    KRECVBUF(1:ISENDCOUNT) = KSENDBUF(1:ISENDCOUNT)
+    IERROR=0
+  ENDIF
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLGATHERV ',ISENDCOUNT,IRECVCOUNT,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+DEALLOCATE(IRECVDISPL)
+
+END SUBROUTINE MPL_ALLGATHERV_INT
+
+SUBROUTINE MPL_ALLGATHERV_INT_SCALAR(KSENDBUF,KRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_ALLGATHERV => MPI_ALLGATHERV8
+#endif
+
+
+
+INTEGER(KIND=JPIM)         :: KSENDBUF
+INTEGER(KIND=JPIM)         :: KRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVCOUNTS(:) ! Not used; for compatibility only
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IR,ISENDCOUNT,IRECVCOUNT
+INTEGER(KIND=JPIM) :: ITAG
+INTEGER(KIND=JPIM) :: IMAXMSG,JK,IMYPAIR,ICHUNKS,ISTS,ISTR,JMESS,ILENS,IENS,IOUNT
+INTEGER(KIND=JPIM) :: ILIMIT,IBARRFREQ,IDUM
+INTEGER(KIND=JPIM) :: IRECVCOUNTS(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC
+INTEGER(KIND=JPIM) :: ITID
+INTEGER(KIND=JPIM),ALLOCATABLE :: IRECVDISPL(:)
+ITID = OML_MY_THREAD()
+ISENDCOUNT = 1
+IRECVCOUNT = SIZE(KRECVBUF)
+
+IRECVCOUNTS(:) = 1
+!--------- Preamble repeated for threadsafe--------------
+! CALL MPL_ALLGATHERV_PREAMB(IRECVCOUNTS,KCOMM,KRECVDISPL,CDSTRING)
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+ALLOCATE(IRECVDISPL(IPL_NUMPROC))
+IF(PRESENT(KRECVDISPL)) THEN
+  IRECVDISPL(:) = KRECVDISPL(:)
+ELSE
+  IRECVDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    IRECVDISPL(IR) = IRECVDISPL(IR-1) + IRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+!--------- End of Preamble --------------
+
+IF(IPL_NUMPROC > 1) THEN
+  CALL MPI_ALLGATHERV(KSENDBUF,ISENDCOUNT,INT(MPI_INTEGER),KRECVBUF(1),IRECVCOUNTS,&
+   &  IRECVDISPL,INT(MPI_INTEGER),ICOMM,IERROR)
+ELSE
+  KRECVBUF(1) = KSENDBUF
+  IERROR=0
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLGATHERV ',ISENDCOUNT,IRECVCOUNT,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLGATHERV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+DEALLOCATE(IRECVDISPL)
+
+END SUBROUTINE MPL_ALLGATHERV_INT_SCALAR
+
+END MODULE MPL_ALLGATHERV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_allreduce_mod.F90 b/odb/src/extras/ifsaux/module/mpl_allreduce_mod.F90
new file mode 100644
index 0000000..a95e35a
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_allreduce_mod.F90
@@ -0,0 +1,514 @@
+MODULE MPL_ALLREDUCE_MOD
+
+!**** MPL_ALLREDUCE Perform collective communication
+
+!     Purpose.
+!     --------
+!     To calculate global MIN,MAX,SUM or IEOR and return result to all processes.
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array or scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_ALLREDUCE
+
+!        Input required arguments :
+!        -------------------------
+!           PSENDBUF -  buffer containing message to be collectively communicated
+!                       (can be type REAL*4, REAL*8 or INTEGER) (also output)
+!           CDOPER   -  Global operation to be performed : 'MAX', 'MIN', 'SUM' or 'IEOR'
+
+!        Input optional arguments :
+!        -------------------------
+!           LDREPROD -  Reproducibility flag for SUMmation-operator.
+!                       Meaningful only for REAL-numbers.
+!                       Three modes (applicable for REAL-number only):
+!                       1) Not provided at all (the default) ==> MPL_ABORT
+!                       2) Provided and .TRUE. ==> Use home-written binary tree
+!                          No MPI_ALLREDUCE used.
+!                       3) Provided, but .FALSE. ==> let MPI_ALLREDUCE do the summation.
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!                       the incoming data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_ALLREDUCE aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud, S.Saarinen     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2001-02-02
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM,  JPIB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_WAIT_MOD
+USE MPL_BROADCAST_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+LOGICAL :: LLABORT=.TRUE.
+
+INTERFACE MPL_ALLREDUCE
+MODULE PROCEDURE MPL_ALLREDUCE_REAL8, MPL_ALLREDUCE_REAL4, MPL_ALLREDUCE_INT, &
+  MPL_ALLREDUCE_INT8, &
+  MPL_ALLREDUCE_REAL8_SCALAR, MPL_ALLREDUCE_REAL4_SCALAR, &
+  MPL_ALLREDUCE_INT_SCALAR, MPL_ALLREDUCE_INT8_SCALAR
+END INTERFACE
+
+PUBLIC MPL_ALLREDUCE
+
+CONTAINS
+
+SUBROUTINE MPL_ALLREDUCE_INT_SCALAR(KSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+
+INTEGER(KIND=JPIM),INTENT(INOUT)     :: KSENDBUF
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM) ISENDBUF(1)
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+
+ISENDBUF(1) = KSENDBUF
+CALL MPL_ALLREDUCE(ISENDBUF,CDOPER,LDREPROD,KCOMM,KERROR,CDSTRING)
+KSENDBUF = ISENDBUF(1)
+
+END SUBROUTINE MPL_ALLREDUCE_INT_SCALAR
+
+SUBROUTINE MPL_ALLREDUCE_INT8_SCALAR(KSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+INTEGER(KIND=JPIB),INTENT(INOUT)     :: KSENDBUF
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIB) ISENDBUF(1)
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+
+ISENDBUF(1) = KSENDBUF
+CALL MPL_ALLREDUCE(ISENDBUF,CDOPER,LDREPROD,KCOMM,KERROR,CDSTRING)
+KSENDBUF = ISENDBUF(1)
+
+END SUBROUTINE MPL_ALLREDUCE_INT8_SCALAR
+
+
+
+SUBROUTINE MPL_ALLREDUCE_REAL8_SCALAR(PSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+REAL(KIND=JPRB),INTENT(INOUT)     :: PSENDBUF
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+REAL(KIND=JPRB) ZSENDBUF(1)
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+
+ZSENDBUF(1) = PSENDBUF
+CALL MPL_ALLREDUCE(ZSENDBUF,CDOPER,LDREPROD,KCOMM,KERROR,CDSTRING)
+PSENDBUF = ZSENDBUF(1)
+
+END SUBROUTINE MPL_ALLREDUCE_REAL8_SCALAR
+
+
+SUBROUTINE MPL_ALLREDUCE_REAL4_SCALAR(PSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+REAL(KIND=JPRM),INTENT(INOUT)     :: PSENDBUF
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+REAL(KIND=JPRM) ZSENDBUF(1)
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+
+ZSENDBUF(1) = PSENDBUF
+CALL MPL_ALLREDUCE(ZSENDBUF,CDOPER,LDREPROD,KCOMM,KERROR,CDSTRING)
+PSENDBUF = ZSENDBUF(1)
+
+END SUBROUTINE MPL_ALLREDUCE_REAL4_SCALAR
+
+
+SUBROUTINE MPL_ALLREDUCE_INT(KSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLREDUCE => MPI_ALLREDUCE8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(INOUT)     :: KSENDBUF(:)
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM) :: IRECVBUF(SIZE(KSENDBUF))
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLREDUCE: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(CDOPER(1:3) == 'MAX' .OR. CDOPER(1:3) == 'max' ) THEN
+  IOPER = MPI_MAX
+ELSEIF(CDOPER(1:3) == 'MIN' .OR. CDOPER(1:3) == 'min' ) THEN
+  IOPER = MPI_MIN
+ELSEIF(CDOPER(1:3) == 'SUM' .OR. CDOPER(1:3) == 'sum' ) THEN
+  IOPER = MPI_SUM
+ELSEIF(CDOPER(1:4) == 'IEOR' .OR. CDOPER(1:4) == 'ieor' ) THEN
+  IOPER = MPI_BXOR
+ELSEIF(CDOPER(1:4) == 'XOR' .OR. CDOPER(1:4) == 'xor' ) THEN
+  IOPER = MPI_BXOR
+ELSE
+  CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE: ERROR UNKNOWN OPERATOR',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+ISENDCOUNT = SIZE(KSENDBUF)
+IF( (LOC(KSENDBUF(UBOUND(KSENDBUF,1)))-LOC(KSENDBUF(LBOUND(KSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLREDUCE: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPI_ALLREDUCE(KSENDBUF,IRECVBUF,ISENDCOUNT,INT(MPI_INTEGER), &
+                &  IOPER,ICOMM,IERROR)
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLREDUCE ',ISENDCOUNT,ICOMM,IOPER
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+KSENDBUF(:) = IRECVBUF(:)
+
+END SUBROUTINE MPL_ALLREDUCE_INT
+
+SUBROUTINE MPL_ALLREDUCE_INT8(KSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+INTEGER(KIND=JPIB),INTENT(INOUT)     :: KSENDBUF(:)
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIB) :: IRECVBUF(SIZE(KSENDBUF))
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER,JJ
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLREDUCE: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(CDOPER(1:3) == 'MAX' .OR. CDOPER(1:3) == 'max' ) THEN
+  IOPER = MPI_MAX
+ELSEIF(CDOPER(1:3) == 'MIN' .OR. CDOPER(1:3) == 'min' ) THEN
+  IOPER = MPI_MIN
+ELSEIF(CDOPER(1:3) == 'SUM' .OR. CDOPER(1:3) == 'sum' ) THEN
+  IOPER = MPI_SUM
+ELSEIF(CDOPER(1:4) == 'IEOR' .OR. CDOPER(1:4) == 'ieor' ) THEN
+  IOPER = MPI_BXOR
+ELSEIF(CDOPER(1:4) == 'XOR' .OR. CDOPER(1:4) == 'xor' ) THEN
+  IOPER = MPI_BXOR
+ELSE
+  CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE: ERROR UNKNOWN OPERATOR',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+ISENDCOUNT = SIZE(KSENDBUF)
+IF( (LOC(KSENDBUF(UBOUND(KSENDBUF,1)))-LOC(KSENDBUF(LBOUND(KSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLREDUCE: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPI_ALLREDUCE(KSENDBUF,IRECVBUF,ISENDCOUNT,MPI_INTEGER8, &
+                &  IOPER,ICOMM,IERROR)
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLREDUCE ',ISENDCOUNT,ICOMM,IOPER
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+KSENDBUF(:) = IRECVBUF(:)
+
+END SUBROUTINE MPL_ALLREDUCE_INT8
+
+
+SUBROUTINE MPL_ALLREDUCE_REAL8(PSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLREDUCE => MPI_ALLREDUCE8
+#endif
+
+REAL(KIND=JPRB),INTENT(INOUT)        :: PSENDBUF(:)
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+REAL(KIND=JPRB)            :: ZRECVBUF(SIZE(PSENDBUF))
+INTEGER(KIND=JPIM) IPROC, ITAG, ICOUNT
+LOGICAL LLREPRODSUM
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+INTEGER(KIND=JPIM) :: IP2,II,IHALF,JSTAGE,JJ,ISEND,IRECV,IMSENT
+INTEGER(KIND=JPIM) :: ISREQ(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+LLREPRODSUM = .FALSE.
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLREDUCE: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(CDOPER(1:3) == 'MAX' .OR. CDOPER(1:3) == 'max' ) THEN
+  IOPER = MPI_MAX
+ELSEIF(CDOPER(1:3) == 'MIN' .OR. CDOPER(1:3) == 'min' ) THEN
+  IOPER = MPI_MIN
+ELSEIF(CDOPER(1:3) == 'SUM' .OR. CDOPER(1:3) == 'sum' ) THEN
+  IOPER = MPI_SUM
+  IF (PRESENT(LDREPROD)) THEN
+    LLREPRODSUM = LDREPROD
+  ELSE
+    CALL MPL_MESSAGE(IERROR,&
+     & 'MPL_ALLREDUCE: SUMMATION OPERATOR NOT REPRODUCIBLE IN REAL MODE',&
+     & CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ELSE
+  CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE: ERROR UNKNOWN OPERATOR',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+ISENDCOUNT = SIZE(PSENDBUF)
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1)))-LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLREDUCE: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF (LLREPRODSUM) THEN
+!-- Near reproducible summation (independent of number of threads)
+
+  IP2=0
+  DO
+    IP2=IP2+1
+    IF(2**IP2 >= MPL_NUMPROC) EXIT
+  ENDDO
+
+  IMSENT=0
+  DO JSTAGE=IP2,1,-1
+!    WRITE(0,*) 'STAGE ',JSTAGE
+    ITAG  = 2001+JSTAGE
+    II    = 2**JSTAGE
+    IHALF = II/2
+    ISEND = MPL_RANK - IHALF
+    IF(ISEND > 0 .AND. MPL_RANK <= II) THEN
+      IMSENT=IMSENT+1
+      CALL MPL_SEND(PSENDBUF,KDEST=ISEND,KCOMM=ICOMM,KTAG=ITAG,KERROR=IERROR,&
+       &KMP_TYPE=JP_NON_BLOCKING_STANDARD,KREQUEST=ISREQ(IMSENT),CDSTRING='MPLS_SEND')
+!      write(0,*) 'I SEND TO ',MPL_RANK,ISEND
+    ENDIF
+    IRECV=MPL_RANK + IHALF
+    IF(IRECV <=MPL_NUMPROC .AND. MPL_RANK <= IHALF) THEN
+      CALL MPL_RECV(ZRECVBUF,KSOURCE=IRECV,KCOMM=ICOMM,KTAG=ITAG,&
+       &KERROR=IERROR,KOUNT=ICOUNT)
+!      write(0,*) 'I RECV FROM ',MPL_RANK,IRECV
+      PSENDBUF(:) = PSENDBUF(:) + ZRECVBUF(:)
+    ENDIF
+  ENDDO
+  IF(IMSENT > 0) THEN
+    CALL MPL_WAIT(PSENDBUF,KREQUEST=ISREQ(1:IMSENT),CDSTRING='MPLS_SEND')
+  ENDIF
+  IF (MPL_RANK == 1) THEN
+    ZRECVBUF(:) = PSENDBUF(:)
+  ENDIF
+!  write(0,*) 'enter broadcast '
+  CALL MPL_BROADCAST(ZRECVBUF,KTAG=ITAG,KCOMM=ICOMM,KROOT=1,KERROR=IERROR)
+!  write(0,*) 'exit broadcast '
+
+!!$  IMSENT=0
+!!$  DO JSTAGE=1,IP2
+!!$    ITAG = 2001+JSTAGE
+!!$    WRITE(0,*) 'STAGE BACK  ',JSTAGE
+!!$    II = 2**JSTAGE
+!!$    IHALF = II/2
+!!$    ISEND=MPL_RANK + IHALF
+!!$    IF(ISEND <=MPL_NUMPROC .AND. MPL_RANK <= IHALF) THEN
+!!$      IMSENT=IMSENT+1
+!!$      CALL MPL_SEND(PSENDBUF,KDEST=ISEND,KCOMM=ICOMM,KTAG=ITAG,KERROR=IERROR,&
+!!$       &KMP_TYPE=JP_NON_BLOCKING_STANDARD,KREQUEST=ISREQ(IMSENT),CDSTRING='MPLS_SEND')
+!!$      WRITE(0,*) 'I SEND BACK TO ',MPL_RANK,ISEND
+!!$    ENDIF
+!!$    IRECV=MPL_RANK - IHALF
+!!$    IF(IRECV > 0 .AND. MPL_RANK <= II) THEN
+!!$      WRITE(0,*) 'I RECV BACK FROM ',MPL_RANK,IRECV
+!!$      CALL MPL_RECV(ZRECVBUF,KSOURCE=IRECV,KCOMM=ICOMM,KTAG=ITAG,&
+!!$       &KERROR=IERROR,KOUNT=ICOUNT)
+!!$    ENDIF
+!!$  ENDDO
+!!$  IF(IMSENT > 0) THEN
+!!$    CALL MPL_WAIT(PSENDBUF,KREQUEST=ISREQ(1:IMSENT),CDSTRING='MPLS_SEND')
+!!$  ENDIF
+  
+ELSE  
+  CALL MPI_ALLREDUCE(PSENDBUF,ZRECVBUF,ISENDCOUNT,INT(MPI_REAL8), &
+                  &  IOPER,ICOMM,IERROR)
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLREDUCE ',ISENDCOUNT,ICOMM,IOPER
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+PSENDBUF(:) = ZRECVBUF(:)
+
+END SUBROUTINE MPL_ALLREDUCE_REAL8
+
+
+SUBROUTINE MPL_ALLREDUCE_REAL4(PSENDBUF,CDOPER,LDREPROD, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLREDUCE => MPI_ALLREDUCE8
+#endif
+
+REAL(KIND=JPRM),INTENT(INOUT)        :: PSENDBUF(:)
+CHARACTER(LEN=*),INTENT(IN)    :: CDOPER
+logical,INTENT(IN),OPTIONAL :: LDREPROD
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING
+REAL(KIND=JPRM)            :: ZRECVBUF(SIZE(PSENDBUF))
+INTEGER(KIND=JPIM) IPROC, ITAG, ICOUNT
+LOGICAL LLREPRODSUM
+INTEGER(KIND=JPIM) :: ISENDCOUNT,ICOMM,IERROR,IOPER
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+LLREPRODSUM = .FALSE.
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLREDUCE: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(CDOPER(1:3) == 'MAX' .OR. CDOPER(1:3) == 'max' ) THEN
+  IOPER = MPI_MAX
+ELSEIF(CDOPER(1:3) == 'MIN' .OR. CDOPER(1:3) == 'min' ) THEN
+  IOPER = MPI_MIN
+ELSEIF(CDOPER(1:3) == 'SUM' .OR. CDOPER(1:3) == 'sum' ) THEN
+  IOPER = MPI_SUM
+  IF (PRESENT(LDREPROD)) THEN
+    LLREPRODSUM = LDREPROD
+  ELSE
+    CALL MPL_MESSAGE(IERROR,&
+     & 'MPL_ALLREDUCE: SUMMATION OPERATOR NOT REPRODUCIBLE IN REAL MODE',&
+     & CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ELSE
+  CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE: ERROR UNKNOWN OPERATOR',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+ISENDCOUNT = SIZE(PSENDBUF)
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1)))-LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLREDUCE: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF (LLREPRODSUM) THEN
+!-- Near reproducible summation
+  ITAG = 2001
+  IF (MPL_RANK == 1) THEN
+    DO IPROC=2,MPL_NUMPROC
+      CALL MPL_RECV(ZRECVBUF,KSOURCE=IPROC,KCOMM=ICOMM,KTAG=ITAG,&
+        &KERROR=IERROR,KOUNT=ICOUNT)
+      IF (ICOUNT /= ISENDCOUNT) THEN
+        WRITE(MPL_ERRUNIT,'(A,I10,A,I6,A,I10)')&
+        & 'MPL_ALLREDUCE: RECEIVED UNEXPECTED NUMBER OF ELEMENTS ', &
+        & ICOUNT,' FROM PROC ',IPROC,'. EXPECTED=',ISENDCOUNT
+        CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE',CDSTRING,LDABORT=LLABORT)
+      ENDIF
+      PSENDBUF(:) = PSENDBUF(:) + ZRECVBUF(:)
+    ENDDO
+    ZRECVBUF(:) = PSENDBUF(:)
+  ELSE
+    CALL MPL_SEND(PSENDBUF,KDEST=1,KCOMM=ICOMM,KTAG=ITAG,KERROR=IERROR,&
+      &KMP_TYPE=JP_BLOCKING_STANDARD,CDSTRING='MPLS_SEND')
+  ENDIF
+  ITAG = ITAG + 1
+  CALL MPL_BROADCAST(ZRECVBUF,KTAG=ITAG,KCOMM=ICOMM,KROOT=1,KERROR=IERROR)
+ELSE  
+  CALL MPI_ALLREDUCE(PSENDBUF,ZRECVBUF,ISENDCOUNT,INT(MPI_REAL4), &
+                  &  IOPER,ICOMM,IERROR)
+ENDIF
+
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_ALLREDUCE ',ISENDCOUNT,ICOMM,IOPER
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_ALLREDUCE',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+PSENDBUF(:) = ZRECVBUF(:)
+
+END SUBROUTINE MPL_ALLREDUCE_REAL4
+
+END MODULE MPL_ALLREDUCE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_alltoallv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_alltoallv_mod.F90
new file mode 100644
index 0000000..cb0c12c
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_alltoallv_mod.F90
@@ -0,0 +1,327 @@
+MODULE MPL_ALLTOALLV_MOD
+
+!**** MPL_ALLTOALLV - Everyone sends different data to everyone
+
+!     Purpose.
+!     --------
+!     Interface to MPI_ALLTOALLV
+ 
+!     The data may be REAL*8,or INTEGER
+
+!**   Interface.
+!     ----------
+!        CALL MPL_ALLTOALLV
+
+!        Input required arguments :
+!        -------------------------
+!           PSENDBUF -  buffer containing message
+!                       (can be type  REAL*8 or INTEGER)
+!           PRECVBUF -  buffer containing message
+!                       (can be type REAL*8 or INTEGER)
+!           KRECVCOUNTS-number of elements received from each process
+!           KSENDCOUNTS-number of elements to be sent to each process
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KRECVDISPL -displacements in PRECVBUF at which to place 
+!                       the incoming data
+!           KSENDDISPL -displacements in PSENDBUF from which to send
+!                       the data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_ALLTOALLV aborts when an error is detected.
+
+!     Author.
+!     -------
+!       Y. Tremolet
+
+!     Modifications.
+!     --------------
+!       Original: 02-03-21
+!       Modified : 25-09-02 M.Hamrud - generalize
+! ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB, JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+PRIVATE
+
+LOGICAL :: LLABORT=.true.
+INTEGER(KIND=JPIM) :: ICOMM,IERROR,IPL_NUMPROC,IRECVCOUNT,ISENDCOUNT,IR
+LOGICAL :: LLSCALAR
+
+INTERFACE MPL_ALLTOALLV
+MODULE PROCEDURE MPL_ALLTOALLV_REAL8,MPL_ALLTOALLV_INTEGER,MPL_ALLTOALLV_REAL4
+END INTERFACE
+
+PUBLIC MPL_ALLTOALLV
+
+CONTAINS
+! ------------------------------------------------------------------
+
+SUBROUTINE MPL_ALLTOALLV_PREAMB(KSENDCOUNTS,KISENDDISPL,&
+ & KRECVCOUNTS,KIRECVDISPL,KSENDDISPL,KRECVDISPL,KCOMM,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:),KSENDCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(OUT) :: KISENDDISPL(:),KIRECVDISPL(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KSENDDISPL(:),KRECVDISPL(:),KCOMM
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM) :: ITID,J
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_ALLTOALLV: MPL NOT INITIALISED ',LDABORT=LLABORT)
+ 
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+ENDIF
+
+IF(SIZE(KRECVCOUNTS)  < IPL_NUMPROC) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_ALLTOALLV: ERROR KRECVCOUNTS dimension=',&
+   & SIZE(KRECVCOUNTS)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_ALLTOALLV: ERROR KRECVCOUNTS dimension is wrong',LDABORT=LLABORT)
+ENDIF
+
+IF(SIZE(KSENDCOUNTS)  < IPL_NUMPROC) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_ALLTOALLV: ERROR KSENDCOUNTS dimension=',&
+   & SIZE(KSENDCOUNTS)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_ALLTOALLV: ERROR KSENDCOUNTS dimension is wrong',LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KRECVDISPL)) THEN
+  DO J=1,MIN(SIZE(KRECVDISPL),SIZE(KIRECVDISPL))
+    KIRECVDISPL(J) = KRECVDISPL(J)
+  ENDDO
+ELSE
+  KIRECVDISPL(:) = 0
+  IF(LLSCALAR) THEN
+    DO IR=2, IPL_NUMPROC
+      KIRECVDISPL(IR) = KIRECVDISPL(IR-1) + 1
+    ENDDO
+  ELSE
+    DO IR=2, IPL_NUMPROC
+      KIRECVDISPL(IR) = KIRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+    ENDDO
+  ENDIF
+ENDIF
+
+DO IR=1, IPL_NUMPROC
+  IF(KIRECVDISPL(IR) < 0 .OR. KRECVCOUNTS(IR) < 0) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_ALLTOALLV: RECV.. < 0 ',&
+     & IR,KIRECVDISPL(IR),KRECVCOUNTS(IR)
+    CALL MPL_MESSAGE(IERROR,'MPL_ALLTOALLV',CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  IF(KIRECVDISPL(IR)+KRECVCOUNTS(IR) > IRECVCOUNT) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_ALLTOALLV:RECV BUFFER TOO SMALL  ', &
+     & IR,KIRECVDISPL(IR),KRECVCOUNTS(IR),IRECVCOUNT
+    CALL MPL_MESSAGE(IERROR,'MPL_ALLTOALLV',CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ENDDO
+
+IF(PRESENT(KSENDDISPL)) THEN
+  DO J=1,MIN(SIZE(KSENDDISPL),SIZE(KISENDDISPL))
+    KISENDDISPL(J) = KSENDDISPL(J)
+  ENDDO
+ELSE
+  KISENDDISPL(:) = 0
+  IF(LLSCALAR) THEN
+    DO IR=2, IPL_NUMPROC
+      KISENDDISPL(IR) = KISENDDISPL(IR-1) + 1
+    ENDDO
+  ELSE
+    DO IR=2, IPL_NUMPROC
+      KISENDDISPL(IR) = KISENDDISPL(IR-1) + KSENDCOUNTS(IR-1)
+    ENDDO
+  ENDIF
+ENDIF
+DO IR=1, IPL_NUMPROC
+  IF(KISENDDISPL(IR) < 0 .OR. KSENDCOUNTS(IR) < 0) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_ALLTOALLV:SEND.. <0 ',&
+     & IR,KISENDDISPL(IR),KSENDCOUNTS(IR)
+    CALL MPL_MESSAGE(IERROR,'MPL_ALLTOALLV',CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  IF(KISENDDISPL(IR)+KSENDCOUNTS(IR) > ISENDCOUNT) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_ALLTOALLV:SEND BUFFER TOO SMALL  ', &
+     & IR,KISENDDISPL(IR),KSENDCOUNTS(IR),ISENDCOUNT
+    CALL MPL_MESSAGE(IERROR,'MPL_ALLTOALLV',CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ENDDO
+
+END SUBROUTINE MPL_ALLTOALLV_PREAMB
+
+SUBROUTINE MPL_ALLTOALLV_REAL8(PSENDBUF,KSENDCOUNTS,PRECVBUF,KRECVCOUNTS,&
+ &KSENDDISPL,KRECVDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLTOALLV => MPI_ALLTOALLV8
+#endif
+
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN) :: KSENDCOUNTS(:), KRECVCOUNTS(:)
+REAL(KIND=JPRB), INTENT(IN)  :: PSENDBUF(:)
+REAL(KIND=JPRB), INTENT(OUT) :: PRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDDISPL(:), KRECVDISPL(:), KCOMM 
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC),ISENDDISPL(MPL_NUMPROC)
+
+ISENDCOUNT=SIZE(PSENDBUF)
+IRECVCOUNT=SIZE(PRECVBUF)
+
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 8*(IRECVCOUNT - 1) .AND. &
+  & IRECVCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+LLSCALAR=.FALSE.
+
+IERROR=0
+CALL MPL_ALLTOALLV_PREAMB(KSENDCOUNTS,ISENDDISPL,&
+ & KRECVCOUNTS,IRECVDISPL,KSENDDISPL,KRECVDISPL,KCOMM,CDSTRING)
+CALL MPI_ALLTOALLV(PSENDBUF(1),KSENDCOUNTS,ISENDDISPL,INT(MPI_REAL8), &
+                 & PRECVBUF(1),KRECVCOUNTS,IRECVDISPL,INT(MPI_REAL8),ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'ERROR IN MPL_ALLTOALLV',&
+   &LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_ALLTOALLV_REAL8
+
+SUBROUTINE MPL_ALLTOALLV_REAL4(PSENDBUF,KSENDCOUNTS,PRECVBUF,KRECVCOUNTS,&
+ &KSENDDISPL,KRECVDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLTOALLV => MPI_ALLTOALLV8
+#endif
+
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN) :: KSENDCOUNTS(:), KRECVCOUNTS(:)
+REAL(KIND=JPRM), INTENT(IN)  :: PSENDBUF(:)
+REAL(KIND=JPRM), INTENT(OUT) :: PRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDDISPL(:), KRECVDISPL(:), KCOMM 
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC),ISENDDISPL(MPL_NUMPROC)
+
+ISENDCOUNT=SIZE(PSENDBUF)
+IRECVCOUNT=SIZE(PRECVBUF)
+
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 8*(IRECVCOUNT - 1) ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+LLSCALAR=.FALSE.
+
+IERROR=0
+CALL MPL_ALLTOALLV_PREAMB(KSENDCOUNTS,ISENDDISPL,&
+ & KRECVCOUNTS,IRECVDISPL,KSENDDISPL,KRECVDISPL,KCOMM,CDSTRING)
+CALL MPI_ALLTOALLV(PSENDBUF(1),KSENDCOUNTS,ISENDDISPL,INT(MPI_REAL4), &
+                 & PRECVBUF(1),KRECVCOUNTS,IRECVDISPL,INT(MPI_REAL4),ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'ERROR IN MPL_ALLTOALLV',&
+   &LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_ALLTOALLV_REAL4
+
+
+SUBROUTINE MPL_ALLTOALLV_INTEGER(KSENDBUF,KSENDCOUNTS,KRECVBUF,KRECVCOUNTS,&
+ &KSENDDISPL,KRECVDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ALLTOALLV => MPI_ALLTOALLV8
+#endif
+
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN) :: KSENDCOUNTS(:), KRECVCOUNTS(:)
+INTEGER(KIND=JPIM), INTENT(IN)  :: KSENDBUF(:)
+INTEGER(KIND=JPIM), INTENT(OUT) :: KRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDDISPL(:), KRECVDISPL(:), KCOMM 
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC),ISENDDISPL(MPL_NUMPROC)
+
+ISENDCOUNT=SIZE(KSENDBUF)
+IRECVCOUNT=SIZE(KRECVBUF)
+
+IF( (LOC(KSENDBUF(UBOUND(KSENDBUF,1))) - LOC(KSENDBUF(LBOUND(KSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+IF( (LOC(KRECVBUF(UBOUND(KRECVBUF,1))) - LOC(KRECVBUF(LBOUND(KRECVBUF,1)))) /= 8*(IRECVCOUNT - 1) .AND. &
+  & IRECVCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_ALLTOALLV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+LLSCALAR=.FALSE.
+
+IERROR=0
+CALL MPL_ALLTOALLV_PREAMB(KSENDCOUNTS,ISENDDISPL,&
+ & KRECVCOUNTS,IRECVDISPL,KSENDDISPL,KRECVDISPL,KCOMM,CDSTRING)
+CALL MPI_ALLTOALLV(KSENDBUF(1),KSENDCOUNTS,ISENDDISPL,INT(MPI_INTEGER), &
+                 & KRECVBUF(1),KRECVCOUNTS,IRECVDISPL,INT(MPI_INTEGER),ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'ERROR IN MPL_ALLTOALLV',&
+   &LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_ALLTOALLV_INTEGER
+
+! ------------------------------------------------------------------
+
+END MODULE MPL_ALLTOALLV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_arg_mod.F90 b/odb/src/extras/ifsaux/module/mpl_arg_mod.F90
new file mode 100644
index 0000000..78b31f5
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_arg_mod.F90
@@ -0,0 +1,189 @@
+MODULE mpl_arg_mod
+
+!**** MPL_GETARG : A substitute for GETARG for MPL applications
+!     MPL_IARGC  : A substitute for function IARGC for MPL applications
+
+!     Purpose.
+!     --------
+!     MPL-task#1 calls getarg until iargc() arguments read
+!     or until the argument is a terminating argument
+!     Then arguments are passed on to other processors
+!     If MPL has not been initialized, it will be done now.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_GETARG(KARG, CDARG)
+
+!        Input required arguments :
+!        -------------------------
+!           KARG     -  The argument number requested (INTEGER(4))
+!                       Range : [ 0 .. MPL_IARGC() ]
+
+!        Output required arguments :
+!        ---------------------------
+!           CDARG    -  Return argument value (CHARACTER(LEN=*))
+!
+!**   Interface.
+!     ----------
+!        INUM_ARGS = MPL_IARGC()
+!
+!     where INUM_ARGS is INTEGER(4)
+
+!     Author.
+!     -------
+!        S.Saarinen, G.Mozdzynski  ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2006-03-15
+
+USE PARKIND1  ,ONLY : JPIM
+USE MPL_MPIF
+USE MPL_DATA_MODULE, ONLY : MPL_NUMPROC, LINITMPI_VIA_MPL
+USE MPL_DATA_MODULE, ONLY : LMPLUSERCOMM, MPLUSERCOMM
+
+
+#ifdef NAG
+use f90_unix_env, only: getarg, iargc
+#endif
+
+IMPLICIT NONE
+
+PRIVATE
+
+CHARACTER(LEN=10), SAVE :: CL_TERMINATE = '-^' ! terminating argument
+
+INTEGER(KIND=JPIM), PARAMETER :: JP_ARGLEN = 1024
+CHARACTER(LEN=JP_ARGLEN), ALLOCATABLE, SAVE :: CL_ARGS(:)
+INTEGER(KIND=JPIM), SAVE :: N_ARGS = -1
+
+PUBLIC :: MPL_GETARG
+PUBLIC :: MPL_IARGC
+PUBLIC :: MPL_ARG_SET_CL_TERMINATE
+PUBLIC :: MPL_ARG_GET_CL_TERMINATE
+
+CONTAINS
+
+SUBROUTINE MPL_ARG_SET_CL_TERMINATE(CDTERM)
+CHARACTER(LEN=*), INTENT(IN) :: CDTERM
+CL_TERMINATE = CDTERM
+END SUBROUTINE MPL_ARG_SET_CL_TERMINATE
+
+SUBROUTINE MPL_ARG_GET_CL_TERMINATE(CDTERM)
+CHARACTER(LEN=*), INTENT(OUT) :: CDTERM
+CDTERM = CL_TERMINATE
+END SUBROUTINE MPL_ARG_GET_CL_TERMINATE
+
+SUBROUTINE INIT_ARGS()
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_INITIALIZED => MPI_INITIALIZED8, MPI_COMM_SIZE => MPI_COMM_SIZE8, &
+    MPI_COMM_RANK => MPI_COMM_RANK8, MPI_BCAST => MPI_BCAST8, &
+    MPI_INIT => MPI_INIT8
+#endif
+
+INTEGER(KIND=JPIM) :: IARGS
+INTEGER(KIND=JPIM) :: IERROR, IROOT, ICOUNT
+INTEGER(KIND=JPIM) :: IRANK, INUMPROC, IRET, J
+INTEGER(KIND=JPIM) :: IARGC
+INTEGER(KIND=JPIM) :: IARGC_C
+CHARACTER(LEN=LEN(CL_TERMINATE)) :: ENV_CL_TERMINATE
+CHARACTER(LEN=JP_ARGLEN) :: CLARG0
+LOGICAL LLINIT, LLCARGS
+INTEGER(KIND=JPIM) :: ICOMM
+
+IF (N_ARGS == -1) THEN
+  IF (MPL_NUMPROC == -1) THEN
+    ! This is complicated, but I hope it works:
+    ! MPI has not yet been initialized, when this routines was called.
+    ! Initialize MPI, but NOT via MPL_INIT to avoid recursion in MPL_IARGC()
+    ! However, must pretend that MPL_INIT has actually initialized it, but 
+    ! MPL_NUMPROC will not be set
+    CALL MPI_INITIALIZED(LLINIT,IRET)
+    IF (.not.LLINIT) THEN
+      CALL MPI_INIT(IERROR)
+      LINITMPI_VIA_MPL = .TRUE.
+      CALL ec_mpi_atexit() ! ifsaux/support/endian.c: to make sure MPI_FINALIZE gets called
+    ENDIF
+  ENDIF
+
+  ! If LMPLUSERCOMM is not set use MPI_COMM_WORLD
+  IF (LMPLUSERCOMM) THEN
+    ICOMM = MPLUSERCOMM
+  ELSE
+    ICOMM = MPI_COMM_WORLD
+  ENDIF
+
+  CALL MPI_COMM_SIZE(ICOMM,INUMPROC,IERROR)
+  CALL MPI_COMM_RANK(ICOMM,IRANK,IERROR)
+  IRANK=IRANK+1
+
+  IF (IRANK == 1 .OR. INUMPROC == 1) THEN
+    CALL EC_GETENV('MPL_CL_TERMINATE',ENV_CL_TERMINATE)
+    IF (ENV_CL_TERMINATE /= ' ') CL_TERMINATE = ENV_CL_TERMINATE
+    IARGS = IARGC()
+    LLCARGS = (IARGS < 0) ! Should be true for non-F90 main programs
+    IF (LLCARGS) THEN
+      IARGS = IARGC_C()
+      LLCARGS = (IARGS >= 0)
+      CALL GETARG_C(0,CLARG0) ! The executable name (see ifsaux/support/cargs.c)
+    ELSE
+      CALL PUTARG_INFO(IARGS, TRIM(CL_TERMINATE)) ! (see ifsaux/support/cargs.c)
+      CALL GETARG(0,CLARG0)                       ! The executable name (normal F90 way)
+      CALL PUTARG_C(0,TRIM(CLARG0))               ! (see ifsaux/support/cargs.c)
+    ENDIF
+    IF (IARGS < 0) IARGS = 0
+    ALLOCATE(CL_ARGS(0:IARGS))
+    N_ARGS = 0
+    CL_ARGS(0) = CLARG0
+    DO J=1,IARGS ! Other args (repeat until end of loop or terminating argument found)
+      IF (LLCARGS) THEN
+        CALL GETARG_C(J,CL_ARGS(J))
+      ELSE
+        CALL GETARG(J,CL_ARGS(J))
+        CALL PUTARG_C(J,TRIM(CL_ARGS(J)))
+      ENDIF
+      IF (CL_ARGS(J) == CL_TERMINATE) EXIT
+      N_ARGS = N_ARGS + 1
+    ENDDO
+  ENDIF
+
+  IF (INUMPROC > 1) THEN
+    IROOT = 0
+    IARGS = 0
+    IF (IRANK == 1) IARGS = N_ARGS
+    ! The following broadcast does not use "mailbox" nor attached buffer, both potentially yet to be allocated
+    CALL MPI_BCAST(IARGS,1,MPI_INTEGER,IROOT,ICOMM,IERROR)
+    ICOUNT = JP_ARGLEN
+    IF (IRANK > 1) ALLOCATE(CL_ARGS(0:IARGS))
+    IF (IRANK > 1) CALL PUTARG_INFO(IARGS, TRIM(CL_TERMINATE))
+    DO J=0,IARGS
+     ! The following broadcast does not use "mailbox" nor attached buffer, both potentially yet to be allocated
+      CALL MPI_BCAST(CL_ARGS(J),ICOUNT,MPI_BYTE,IROOT,ICOMM,IERROR)
+      IF (IRANK > 1) CALL PUTARG_C(J,TRIM(CL_ARGS(J)))
+    ENDDO
+    IF (IRANK > 1) N_ARGS = IARGS
+  ENDIF
+ENDIF
+END SUBROUTINE INIT_ARGS
+
+SUBROUTINE MPL_GETARG(KARG, CDARG)
+INTEGER(KIND=JPIM), INTENT(IN) :: KARG
+CHARACTER(LEN=*), INTENT(OUT)  :: CDARG
+INTEGER(KIND=JPIM) :: IARGC
+IF (N_ARGS == -1) CALL INIT_ARGS()
+IF (KARG >= 0 .AND. KARG <= N_ARGS) THEN
+  CDARG = CL_ARGS(KARG)
+ELSE
+  CDARG = ' '
+ENDIF
+END SUBROUTINE MPL_GETARG
+
+FUNCTION MPL_IARGC() RESULT(IRET)
+INTEGER(KIND=JPIM) :: IRET
+IF (N_ARGS == -1) CALL INIT_ARGS()
+IRET = N_ARGS
+END FUNCTION MPL_IARGC
+
+END MODULE mpl_arg_mod
diff --git a/odb/src/extras/ifsaux/module/mpl_barrier_mod.F90 b/odb/src/extras/ifsaux/module/mpl_barrier_mod.F90
new file mode 100644
index 0000000..890683f
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_barrier_mod.F90
@@ -0,0 +1,101 @@
+MODULE MPL_BARRIER_MOD
+
+!**** MPL_BARRIER - Barrier synchronisation
+
+!     Purpose.
+!     --------
+!     Blocks the caller until all group members have called it.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_BARRIER
+
+!        Input required arguments :
+!        -------------------------
+!           none
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_BARRIER aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+!        Threadsafe: 2004-12-15, J.Hague
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+
+PRIVATE
+
+LOGICAL :: LLABORT=.TRUE.
+
+PUBLIC MPL_BARRIER
+
+CONTAINS
+
+SUBROUTINE MPL_BARRIER(KCOMM,CDSTRING,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_BARRIER => MPI_BARRIER8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL   :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL  :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER :: ICOMM,IERROR,ITID
+IERROR = 0
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE(CDSTRING=CDSTRING,&
+  & CDMESSAGE='MPL_BARRIER: MPL NOT INITIALISED ',LDABORT=LLABORT)
+ 
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(MPL_NUMPROC > 1) THEN
+#ifdef VPP
+  CALL VPP_Barrier
+#else
+  CALL MPI_BARRIER(ICOMM,IERROR)
+#endif
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BARRIER',CDSTRING,LDABORT=LLABORT)
+ENDIF
+  
+RETURN
+END SUBROUTINE MPL_BARRIER
+
+END MODULE MPL_BARRIER_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_broadcast_mod.F90 b/odb/src/extras/ifsaux/module/mpl_broadcast_mod.F90
new file mode 100644
index 0000000..c967f2d
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_broadcast_mod.F90
@@ -0,0 +1,836 @@
+MODULE MPL_BROADCAST_MOD
+
+!**** MPL_BROADCAST Message broadcast
+
+!     Purpose.
+!     --------
+!     Broadcasts a message from the process with rank root
+!     to all processes in the group.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_BROADCAST
+
+!        Input required arguments :
+!        -------------------------
+!           PBUF     -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KTAG     -  message tag
+
+!        Input optional arguments :
+!        -------------------------
+!           KROOT    -  number of root process (default=1)
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+!                   
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_BROADCAST aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud, S.Saarinen    ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_BARRIER_MOD
+USE MPL_MYRANK_MOD
+
+IMPLICIT NONE
+PRIVATE
+
+!--- Move to reoutines to make thread safe ----------------
+! INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+! INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+! INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+
+LOGICAL :: LLABORT=.TRUE.
+
+INTERFACE MPL_BROADCAST
+MODULE PROCEDURE MPL_BROADCAST_REAL4,MPL_BROADCAST_REAL8, &
+     & MPL_BROADCAST_REAL42,MPL_BROADCAST_REAL82,MPL_BROADCAST_REAL83,&
+     & MPL_BROADCAST_REAL84,MPL_BROADCAST_REAL8_SCALAR, &
+     & MPL_BROADCAST_INT,MPL_BROADCAST_INT2,MPL_BROADCAST_INT_SCALAR, &
+     & MPL_BROADCAST_CHAR_SCALAR
+END INTERFACE
+
+PUBLIC MPL_BROADCAST
+
+CONTAINS
+
+SUBROUTINE MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_PREAMB1
+
+SUBROUTINE MPL_BROADCAST_REAL4(PBUF,KTAG,KROOT,&
+                               KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+REAL(KIND=JPRM)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = SIZE(PBUF)
+
+CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL4
+
+SUBROUTINE MPL_BROADCAST_REAL8(PBUF,KTAG,KROOT,&
+                               KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+REAL(KIND=JPRB)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = SIZE(PBUF)
+
+CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL8
+
+
+SUBROUTINE MPL_BROADCAST_REAL42(PBUF,KTAG,KROOT,KCOMM,KERROR,CDSTRING)
+
+REAL(KIND=JPRM)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+IROWS=SIZE(PBUF,DIM=1)
+ICOLS=SIZE(PBUF,DIM=2)
+DO JCOL=1,ICOLS
+  CALL MPL_BROADCAST(PBUF(1:IROWS,JCOL),KTAG,KROOT,KCOMM,KERROR,CDSTRING)
+ENDDO
+
+END SUBROUTINE MPL_BROADCAST_REAL42
+
+
+SUBROUTINE MPL_BROADCAST_REAL82(PBUF,KTAG,KROOT,&
+                                KCOMM,KERROR,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+REAL(KIND=JPRB)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+
+ICOUNT = SIZE(PBUF)
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
+   & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 8*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+CALL MPI_BCAST(PBUF(1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL82
+
+SUBROUTINE MPL_BROADCAST_REAL83(PBUF,KTAG,KROOT,&
+                                KCOMM,KERROR,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+REAL(KIND=JPRB)            :: PBUF(:,:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+
+ICOUNT = SIZE(PBUF)
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2),UBOUND(PBUF,3))) - &
+  &  LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2),LBOUND(PBUF,3)))) /= 8*(ICOUNT - 1) .AND. &
+  & ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+CALL MPI_BCAST(PBUF(1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL83
+
+SUBROUTINE MPL_BROADCAST_REAL84(PBUF,KTAG,KROOT,&
+                                KCOMM,KERROR,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+REAL(KIND=JPRB)            :: PBUF(:,:,:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+
+ICOUNT = SIZE(PBUF)
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2),UBOUND(PBUF,3),UBOUND(PBUF,4))) - &
+  &  LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2),LBOUND(PBUF,3),LBOUND(PBUF,4)))) /= 8*(ICOUNT - 1) .AND. &
+  & ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+CALL MPI_BCAST(PBUF(1,1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL84
+
+
+SUBROUTINE MPL_BROADCAST_REAL8_SCALAR(PBUF,KTAG,KROOT,&
+                                      KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+REAL(KIND=JPRB)            :: PBUF
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = 1
+
+CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_REAL8_SCALAR
+
+
+SUBROUTINE MPL_BROADCAST_INT(KBUF,KTAG,KROOT,&
+                             KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+INTEGER(KIND=JPIM)           :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = SIZE(KBUF)
+
+CALL MPI_BCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_INT
+
+
+SUBROUTINE MPL_BROADCAST_INT2(KBUF,KTAG,KROOT,&
+                              KCOMM,KERROR,CDSTRING)
+
+INTEGER(KIND=JPIM)           :: KBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+IROWS=SIZE(KBUF,DIM=1)
+ICOLS=SIZE(KBUF,DIM=2)
+DO JCOL=1,ICOLS
+  CALL MPL_BROADCAST(KBUF(1:IROWS,JCOL),KTAG,KROOT,KCOMM,KERROR,CDSTRING)
+ENDDO
+
+END SUBROUTINE MPL_BROADCAST_INT2
+
+
+SUBROUTINE MPL_BROADCAST_INT_SCALAR(KBUF,KTAG,KROOT,&
+                                    KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+INTEGER(KIND=JPIM)           :: KBUF
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = 1
+
+
+CALL MPI_BCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_INT_SCALAR
+
+
+SUBROUTINE MPL_BROADCAST_CHAR_SCALAR(CDBUF,KTAG,KROOT,&
+                                    KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
+#endif
+
+
+CHARACTER*(*)                          :: CDBUF
+INTEGER(KIND=JPIM),INTENT(IN)          :: KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IPROC,IROOT,IOUNT,IPL_NUMPROC,IPL_MYRANK
+INTEGER(KIND=JPIM) :: IMAXMSG, ICHUNKS, ISTS, IENS, ILENS, ITAG, IDUM, JMESS
+INTEGER(KIND=JPIM) :: JCOL, IROWS, ICOLS
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF (MPL_NUMPROC == 1) THEN
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  RETURN
+ENDIF
+
+CALL MPL_BROADCAST_PREAMB1(KCOMM,KROOT)
+
+!----- Repeat Preamble to make threadsafe----------
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BROADCAST: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+!----- End Preamble ----------------------------
+
+ICOUNT = LEN(CDBUF)
+
+
+CALL MPI_BCAST(CDBUF,ICOUNT,INT(MPI_BYTE),IROOT-1,ICOMM,IERROR)
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+
+END SUBROUTINE MPL_BROADCAST_CHAR_SCALAR
+
+
+END MODULE MPL_BROADCAST_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_buffer_method_mod.F90 b/odb/src/extras/ifsaux/module/mpl_buffer_method_mod.F90
new file mode 100644
index 0000000..72b695a
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_buffer_method_mod.F90
@@ -0,0 +1,137 @@
+MODULE MPL_BUFFER_METHOD_MOD
+
+!**** MPL_BUFFER_METHOD Establish message passing default method
+
+!     Purpose.
+!     --------
+!     Setup the message passing buffering 
+!     by allocating an attached buffer if required.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_BUFFER_METHOD
+
+!        Input required arguments :
+!        -------------------------
+!           KMP_TYPE -  buffering type
+!                       possible values are :
+!                       JP_BLOCKING_STANDARD, JP_BLOCKING_BUFFERED
+!                       defined as parameters in MPL_DATA_MODULE
+
+!        Input optional arguments :
+!        -------------------------
+!           KMBX_SIZE - Size (in bytes) of attached buffer 
+!                       if KMP_TYPE=JP_BLOCKING_BUFFERED
+!           KPROCIDS  - array of processor ids
+!           LDINFO   -  = .TRUE.  : Print informative msgs from MPL_INIT (default) 
+!                       = .FALSE. : Do not print
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_BUFFER_METHOD aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_BUFFER_METHOD
+
+CONTAINS 
+
+SUBROUTINE MPL_BUFFER_METHOD(KMP_TYPE,KMBX_SIZE,KERROR,KPROCIDS,LDINFO)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_BUFFER_DETACH => MPI_BUFFER_DETACH8, MPI_BUFFER_ATTACH => MPI_BUFFER_ATTACH8
+#endif
+
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+INTEGER(KIND=JPIM),INTENT(IN) ::  KMP_TYPE
+INTEGER(KIND=JPIM),OPTIONAL,INTENT(IN)  :: KMBX_SIZE
+INTEGER(KIND=JPIM),OPTIONAL,INTENT(IN)  :: KPROCIDS(:)
+INTEGER(KIND=JPIM),OPTIONAL,INTENT(OUT) :: KERROR
+LOGICAL,INTENT(IN),OPTIONAL :: LDINFO
+INTEGER(KIND=JPIM) :: IMBX_DEFAULT_SIZE = 1000000
+INTEGER(KIND=JPIM) :: IBUFFMPI,IERROR,ILEN
+LOGICAL :: LLABORT=.TRUE., LLINFO
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_BUFFER_METHOD: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF (ALLOCATED(MPL_ATTACHED_BUFFER)) THEN
+  CALL MPI_BUFFER_DETACH(MPL_ATTACHED_BUFFER,MPL_MBX_SIZE,IERROR)
+  DEALLOCATE(MPL_ATTACHED_BUFFER)
+ENDIF
+
+IF(PRESENT(LDINFO)) THEN
+  LLINFO = LDINFO
+ELSE
+  LLINFO = .TRUE.
+ENDIF
+
+if(KMP_TYPE == JP_BLOCKING_STANDARD) then
+  IBUFFMPI=MPL_MBX_SIZE
+ELSE IF(KMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  IF(MPL_NUMPROC > 1) then
+    IBUFFMPI=KMBX_SIZE
+    IF(IBUFFMPI == 0) IBUFFMPI=IMBX_DEFAULT_SIZE
+!    convert to bytes
+    ILEN = (IBUFFMPI-1)/JP_ATTACHED_BUFFER_BYTES+1
+    ALLOCATE(MPL_ATTACHED_BUFFER(ILEN))
+    CALL MPI_BUFFER_ATTACH(MPL_ATTACHED_BUFFER,IBUFFMPI,IERROR)
+    IF(PRESENT(KERROR)) THEN
+      KERROR=IERROR
+    ELSE
+      IF( IERROR /= 0 )THEN
+        CALL MPL_MESSAGE(IERROR,'MPL_BUFFER_METHOD ','MPI_BUFFER_ATTACH ERROR',LDABORT=LLABORT)
+      ENDIF
+    ENDIF
+  ELSE
+    IBUFFMPI=0
+  ENDIF
+ELSE
+!    invalid type
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KMP_TYPE,'MPL_BUFFER_METHOD','INVALID KMP_TYPE=',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+
+MPL_MBX_SIZE=IBUFFMPI
+MPL_METHOD=KMP_TYPE
+
+IF (MPL_RANK == 1) THEN
+  IF (LLINFO) WRITE(MPL_UNIT,'(A,I2,I12)') 'MPL_BUFFER_METHOD: ',MPL_METHOD,MPL_MBX_SIZE
+ENDIF
+
+IF(PRESENT(KPROCIDS)) THEN
+  IF(SIZE(KPROCIDS) < MPL_NUMPROC) THEN
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_BUFFER_METHOD: KPROCIDS NOT CORRECT',LDABORT=LLABORT)
+  ELSE
+    MPL_IDS=KPROCIDS
+  ENDIF
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_BUFFER_METHOD
+
+END MODULE MPL_BUFFER_METHOD_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_close_mod.F90 b/odb/src/extras/ifsaux/module/mpl_close_mod.F90
new file mode 100644
index 0000000..7beec03
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_close_mod.F90
@@ -0,0 +1,107 @@
+MODULE MPL_CLOSE_MOD
+!
+!     Purpose.  close an MPIIO file 
+!     --------
+!
+!
+!     Interface.
+!     ----------
+!        call mpl_close(...)
+!
+!        Explicit arguments :
+!        --------------------
+!
+!        input arguments:
+!        kfptr   - handle for file pointer
+!        output arguments:
+!        kerror  - error code
+!
+!        Implicit arguments :
+!        --------------------
+!
+!     Method.
+!     -------
+!     MPL supports 4 styles of MPIIO
+!
+!     kop = 1    -  Blocking, non collective, shared file pointer
+!                   using MPI_FILE_WRITE_SHARED,
+!                         MPI_FILE_READ_SHARED
+!     kop = 2    -  Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED,
+!                         MPI_FILE_READ_ORDERED
+!     kop = 3    -  Non Blocking, non collective, shared file pointer
+!                   using MPI_FILE_IWRITE_SHARED,
+!                         MPI_FILE_IREAD_SHARED
+!                   and MPI_WAIT
+!     kop = 4    -  Non Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED_BEGIN/END,
+!                         MPI_FILE_READ_ORDERED_BEGIN/END
+!
+!     Externals.
+!     ----------
+!
+!     Reference.
+!     ----------
+!        none yet
+!
+!     Author.
+!     -------
+!        G.Mozdzynski
+!
+!     Modifications.
+!     --------------
+!        Original : 2000-12-08 (Based on MPE_CLOSE)
+!
+!     -----------------------------------------------------------------
+!
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_IOINIT_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_CLOSE
+
+CONTAINS
+
+SUBROUTINE MPL_CLOSE(KFPTR,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_CLOSE => MPI_FILE_CLOSE8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KFPTR
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+!
+#ifdef MPI2
+
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble
+!           --------
+IF( MPL_RANK > MPL_NUMIO ) THEN
+  KERROR = -1
+  RETURN
+ENDIF
+!
+!     -----------------------------------------------------------------
+!
+!     1.    Close the File
+!           --------------
+CALL MPI_FILE_CLOSE(KFPTR,KERROR)
+!
+!     -----------------------------------------------------------------
+#else
+
+CALL ABOR1('MPI_CLOSE not built with MPI2')
+
+#endif
+!
+RETURN
+END SUBROUTINE MPL_CLOSE
+
+END MODULE MPL_CLOSE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_comm_create_mod.F90 b/odb/src/extras/ifsaux/module/mpl_comm_create_mod.F90
new file mode 100644
index 0000000..0b4ab41
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_comm_create_mod.F90
@@ -0,0 +1,59 @@
+MODULE MPL_COMM_CREATE_MOD
+
+!**** MPL_COMM_CREATE Create a new communicator
+
+!     Purpose.
+!     --------
+!     Create a new communicator and set as default
+
+!**   Interface.
+!     ----------
+!        CALL MPL_COMM_CREATE
+
+!        Input required arguments :
+!        -------------------------
+
+!        Input optional arguments :
+!        -------------------------
+
+!        Output required arguments :
+!        -------------------------
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_COMM_CREATE aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_COMM_CREATE
+
+CONTAINS 
+
+SUBROUTINE MPL_COMM_CREATE(KERROR)
+INTEGER(KIND=JPIM),OPTIONAL,INTENT(OUT) :: KERROR
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+!   this line to be replaced
+MPL_COMM_OML(ITID)=MPL_COMM
+KERROR=0
+
+RETURN
+END SUBROUTINE MPL_COMM_CREATE
+
+END MODULE MPL_COMM_CREATE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_data_module.F90 b/odb/src/extras/ifsaux/module/mpl_data_module.F90
new file mode 100644
index 0000000..334065b
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_data_module.F90
@@ -0,0 +1,71 @@
+MODULE MPL_DATA_MODULE
+
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+!      variables controlling the execution of MPL
+
+!  MPL_METHOD   : buffering type
+!  MPL_MBX_SIZE : size of application mailbox, (bytes)
+!                 used when MPL_METHOD=JP_BLOCKING_BUFFERED
+!  MPL_COMM     : default communicator in use
+!  MPL_COMM_OML : communicators for messages between corresponding OML-threads
+!  MPL_UNIT     : Fortran I/O unit for messages (default=6)
+!  MPL_ERRUNIT  : Fortran I/O unit for error messages (default=0)
+!  MPL_OUTPUT   : controls contents of Output (see mpl_init_mod.F90 for values/default)
+!  MPL_RANK     : rank of the process within MPL_COMM_OML(1)
+!  MPL_NUMPROC  : number of processes in MPL_COMM_OML(1)
+!  MPL_IDS      : array of processor numbers
+!  LUSEHLMPI    : always use high level MPI calls (collective comm.)
+!  LINITMPI_VIA_MPL : true if MPI has been initialized from within MPL_INIT()
+!  LTHSAFEMPI   : Thread safe MPI, if .TRUE. (default)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE OML_MOD    ,ONLY : OML_MAX_THREADS, OML_MY_THREAD
+
+IMPLICIT NONE
+
+SAVE
+
+PUBLIC 
+
+INTEGER(KIND=JPIM) :: MPL_METHOD, MPL_MBX_SIZE, MPL_UNIT=6, MPL_OUTPUT=1
+INTEGER(KIND=JPIM) :: MPL_RANK=0,MPL_NUMPROC = -1,MPL_ERRUNIT=0
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_IDS(:)
+INTEGER(KIND=JPIM) :: MPL_COMM
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_COMM_OML(:)
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_OPPONENT(:)
+INTEGER(KIND=JPIM) :: MPL_NCPU_PER_NODE=1
+INTEGER(KIND=JPIM) :: MPL_MAX_TASK_PER_NODE
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_TASK_PER_NODE(:)
+INTEGER(KIND=JPIM) :: MPL_NNODES
+LOGICAL :: LFULLNODES
+INTEGER(KIND=JPIM) :: MPL_MYNODE=0
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_NODE(:)
+INTEGER(KIND=JPIM),ALLOCATABLE :: MPL_NODE_TASKS(:,:)
+!INTEGER_M,ALLOCATABLE :: MPL_ATTACHED_BUFFER(:)
+!   needs to ge a TARGET for coexistence with MPE
+INTEGER(KIND=JPIM),ALLOCATABLE,TARGET :: MPL_ATTACHED_BUFFER(:)
+LOGICAL :: LUSEHLMPI
+LOGICAL :: LINITMPI_VIA_MPL = .FALSE.
+LOGICAL :: LTHSAFEMPI = .TRUE.
+INTEGER(KIND=JPIM),PARAMETER :: JP_ATTACHED_BUFFER_BYTES    = JPIM
+INTEGER(KIND=JPIM),PARAMETER :: JP_BLOCKING_STANDARD        = 1
+INTEGER(KIND=JPIM),PARAMETER :: JP_BLOCKING_BUFFERED        = 2
+INTEGER(KIND=JPIM),PARAMETER :: JP_BLOCKING_SYNCHRONOUS     = 3
+INTEGER(KIND=JPIM),PARAMETER :: JP_BLOCKING_READY           = 4
+INTEGER(KIND=JPIM),PARAMETER :: JP_NON_BLOCKING_STANDARD    = 5
+INTEGER(KIND=JPIM),PARAMETER :: JP_NON_BLOCKING_BUFFERED    = 6
+INTEGER(KIND=JPIM),PARAMETER :: JP_NON_BLOCKING_SYNCHRONOUS = 7
+INTEGER(KIND=JPIM),PARAMETER :: JP_NON_BLOCKING_READY       = 8
+LOGICAL :: LMPLUSERCOMM = .FALSE.
+INTEGER(KIND=JPIM) :: MPLUSERCOMM = -1
+
+END MODULE MPL_DATA_MODULE
diff --git a/odb/src/extras/ifsaux/module/mpl_end_mod.F90 b/odb/src/extras/ifsaux/module/mpl_end_mod.F90
new file mode 100644
index 0000000..eafdef9
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_end_mod.F90
@@ -0,0 +1,112 @@
+MODULE MPL_END_MOD
+
+!**** MPL_END - Terminates the message passing environment
+
+!     Purpose.
+!     --------
+!     Cleans up all of the MPI state. 
+!     Subsequently, no MPI routine can be called
+
+!**   Interface.
+!     ----------
+!        CALL MPL_END
+
+!        Input required arguments :
+!        -------------------------
+!           none
+
+!        Input optional arguments :
+!        -------------------------
+!           none
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_END aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_END
+PRIVATE
+
+INTEGER :: IERROR
+
+CONTAINS 
+
+SUBROUTINE MPL_END(KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_BUFFER_DETACH => MPI_BUFFER_DETACH8, MPI_FINALIZE => MPI_FINALIZE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM)                      :: IERROR
+LOGICAL                      :: LLABORT=.TRUE.
+
+IF(MPL_NUMPROC < 1) THEN
+  IF(MPL_NUMPROC == -1) THEN
+    IF (.not.LINITMPI_VIA_MPL) THEN
+      ! Neither MPL_INIT_MOD nor MPL_ARG_MOD -modules were called before this
+      CALL MPL_MESSAGE(CDMESSAGE=' MPL_END CALLED BEFORE MPL_INIT ')
+    ENDIF
+!!-- we do not want the following message to appear, since its non-fatal
+!!  ELSEIF(MPL_NUMPROC == -2) THEN
+!!    CALL MPL_MESSAGE(CDMESSAGE=' MPL_END CALLED MULTIPLE TIMES ')
+  ENDIF
+  IF(PRESENT(KERROR)) THEN
+    IERROR=0
+    KERROR=IERROR
+  ENDIF
+  RETURN
+ENDIF
+
+IF (ALLOCATED(MPL_ATTACHED_BUFFER)) THEN
+  CALL MPI_BUFFER_DETACH(MPL_ATTACHED_BUFFER,MPL_MBX_SIZE,IERROR)
+  IF(PRESENT(KERROR)) THEN
+    KERROR=IERROR
+  ELSE
+    IF( IERROR /= 0 )THEN
+      CALL MPL_MESSAGE(IERROR,'MPL_END ',LDABORT=LLABORT)
+    ENDIF
+  ENDIF
+  DEALLOCATE(MPL_ATTACHED_BUFFER)
+ENDIF
+
+IF (LINITMPI_VIA_MPL) THEN
+  CALL MPI_FINALIZE(IERROR)
+ELSE
+  IERROR = 0
+ENDIF
+
+MPL_NUMPROC = -2
+LINITMPI_VIA_MPL = .FALSE.
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_END
+
+END MODULE MPL_END_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_gatherv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_gatherv_mod.F90
new file mode 100644
index 0000000..0a5e29e
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_gatherv_mod.F90
@@ -0,0 +1,495 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE MPL_GATHERV_MOD
+
+!**** MPL_GATHERV Gather data to specific processor
+
+!     Purpose.
+!     --------
+!     Gather data to specific processor
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
+!                     REAL*4,or REAL*8, two dimensional array
+!                  or INTEGER scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_GATHERV
+
+!        Input required arguments :
+!        -------------------------
+!           PSENDBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           PRECVBUF -  buffer containing message (required from kroot)
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KRECVCOUNTS-number of elements received from each process
+!                       (required from kroot processor)
+
+!        Input optional arguments :
+!        -------------------------
+!           KROOT    -  rank of receiveing processor (default 1) 
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KRECVDISPL -displacements in PRECVBUF at which to place 
+!                       the incoming data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_GATHERV aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-11-23
+
+! --- *NOT* THREAD SAFE YET ---
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_MYRANK_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+
+!INTEGER(KIND=JPIM) :: ISENDCOUNT,IRECVBUFSIZE
+INTEGER(KIND=JPIM),PARAMETER :: ITAG=22222
+
+LOGICAL   :: LLABORT=.TRUE.
+REAL(KIND=JPRB)    :: ZDUM_JPRB
+REAL(KIND=JPRM)    :: ZDUM_JPRM
+INTEGER(KIND=JPIM)    :: ZDUM_INT
+
+INTERFACE MPL_GATHERV
+MODULE PROCEDURE MPL_GATHERV_REAL8,MPL_GATHERV_REAL4,MPL_GATHERV_INT,&
+               & MPL_GATHERV_INT_SCALAR
+END INTERFACE
+
+PUBLIC MPL_GATHERV
+
+CONTAINS
+
+SUBROUTINE MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT, &
+     & KCOMM,KROOT)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(OUT) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_GATHERV: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+
+
+END SUBROUTINE MPL_GATHERV_PREAMB1
+
+SUBROUTINE MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+     & KRECVCOUNTS,KIRECVDISPL,KRECVDISPL,CDSTRING)
+
+INTEGER(KIND=JPIM),INTENT(IN) :: IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT
+INTEGER(KIND=JPIM),INTENT(IN)  :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(OUT) :: KIRECVDISPL(:) 
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:)
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM) :: IR
+
+
+IF(SIZE(KRECVCOUNTS)  < IPL_NUMPROC) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_GATHERV: ERROR KRECVCOUNTS DIMENSION=',&
+   & SIZE(KRECVCOUNTS)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_GATHERV: ERROR KRECVCOUNTS DIMENSION IS WRONG',LDABORT=LLABORT)
+ENDIF
+IF(ISENDCOUNT /= KRECVCOUNTS(IPL_MYRANK)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_GATHERV: ERROR KRECVCOUNTS INCONSISTENCY ',&
+   & ISENDCOUNT,KRECVCOUNTS(IPL_MYRANK)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_GATHERV: ERROR ISENDCOUNT /= KRECVCOUNTS(MPL_RANK) ',LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KRECVDISPL)) THEN
+  KIRECVDISPL(1:IPL_NUMPROC) = KRECVDISPL(1:IPL_NUMPROC)
+ELSE
+  KIRECVDISPL(1:IPL_NUMPROC) = 0
+  DO IR=2, IPL_NUMPROC
+    KIRECVDISPL(IR) = KIRECVDISPL(IR-1) + KRECVCOUNTS(IR-1)
+  ENDDO
+ENDIF
+DO IR=1, IPL_NUMPROC
+  IF(KIRECVDISPL(IR)+KRECVCOUNTS(IR) > IRECVBUFSIZE) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_GATHERV:RECV BUFFER TOO SMALL  ', &
+     & IR,KIRECVDISPL(IR),KRECVCOUNTS(IR),IRECVBUFSIZE
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV',CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ENDDO
+
+END SUBROUTINE MPL_GATHERV_PREAMB2
+
+SUBROUTINE MPL_GATHERV_REAL4(PSENDBUF,KROOT,PRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8
+#endif
+
+
+
+REAL(KIND=JPRM),INTENT(IN) :: PSENDBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+REAL(KIND=JPRM),INTENT(OUT),OPTIONAL  :: PRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM) :: IRECVBUFSIZE,ISENDCOUNT
+
+
+ISENDCOUNT = SIZE(PSENDBUF)
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT,KCOMM,KROOT)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(PRECVBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_GATHERV:RECVBUF MISSING',CDSTRING=CDSTRING,LDABORT=LLABORT)
+
+  IRECVBUFSIZE = SIZE(PRECVBUF)
+  IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 4*(IRECVBUFSIZE - 1) .AND. &
+    & IRECVBUFSIZE > 0 ) THEN
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+  ENDIF
+
+  CALL MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+       & KRECVCOUNTS,IRECVDISPL,KRECVDISPL,CDSTRING)
+  CALL MPI_GATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL4),PRECVBUF(1),KRECVCOUNTS, &
+   &  IRECVDISPL,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
+ELSE
+  CALL MPI_GATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL4),ZDUM_JPRM,1, &
+   &  1,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_GATHERV',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_GATHERV_REAL4
+
+SUBROUTINE MPL_GATHERV_REAL8(PSENDBUF,KROOT,PRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8
+#endif
+
+
+
+REAL(KIND=JPRB)            :: PSENDBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+REAL(KIND=JPRB),OPTIONAL   :: PRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM) :: IRECVBUFSIZE,ISENDCOUNT
+INTEGER(KIND=JPIM) :: IDUM,IST,IEND,JK
+
+
+ISENDCOUNT = SIZE(PSENDBUF)
+IF( (LOC(PSENDBUF(UBOUND(PSENDBUF,1))) - LOC(PSENDBUF(LBOUND(PSENDBUF,1)))) /= 8*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT,KCOMM,KROOT)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(PRECVBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_GATHERV:RECVBUF MISSING',CDSTRING=CDSTRING,LDABORT=LLABORT)
+  IRECVBUFSIZE = SIZE(PRECVBUF)
+  IF( (LOC(PRECVBUF(UBOUND(PRECVBUF,1))) - LOC(PRECVBUF(LBOUND(PRECVBUF,1)))) /= 8*(IRECVBUFSIZE - 1) .AND. &
+    & IRECVBUFSIZE > 0 ) THEN
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+  ENDIF
+  CALL MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+       & KRECVCOUNTS,IRECVDISPL,KRECVDISPL,CDSTRING)
+  IF(LUSEHLMPI .OR. ICOMM /= MPL_COMM)THEN
+    CALL MPI_GATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL8),PRECVBUF(1),KRECVCOUNTS,&
+     &  IRECVDISPL,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ELSE
+    DO JK=1,IPL_NUMPROC
+      IST = IRECVDISPL(JK)+1
+      IEND = IST+KRECVCOUNTS(JK)-1
+      IF(JK /= MPL_RANK) THEN
+        CALL MPL_SEND(MPL_RANK,KTAG=ITAG,KDEST=JK)
+        CALL MPL_RECV(PRECVBUF(IST:IEND),KTAG=ITAG,KSOURCE=JK)
+      ELSE
+        PRECVBUF(IST:IEND) = PSENDBUF(1:ISENDCOUNT)
+      ENDIF
+    ENDDO
+  ENDIF
+ELSE
+  IF(LUSEHLMPI .OR. ICOMM /= MPL_COMM)THEN
+    CALL MPI_GATHERV(PSENDBUF(1),ISENDCOUNT,INT(MPI_REAL8),ZDUM_JPRB,1, &
+     &  1,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ELSE
+    CALL MPL_RECV(IDUM,KTAG=ITAG,KSOURCE=IROOT)
+    CALL MPL_SEND(PSENDBUF(1:ISENDCOUNT),KTAG=ITAG,KDEST=IROOT)
+  ENDIF
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_GATHERV',CDSTRING,&
+   & LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_GATHERV_REAL8
+
+SUBROUTINE MPL_GATHERV_INT(KSENDBUF,KROOT,KRECVBUF,KRECVCOUNTS,KRECVDISPL, &
+                            & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+INTEGER(KIND=JPIM),INTENT(IN)         :: KSENDBUF(:)
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECVCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM) :: IRECVBUFSIZE,ISENDCOUNT
+
+ISENDCOUNT = SIZE(KSENDBUF)
+IF( (LOC(KSENDBUF(UBOUND(KSENDBUF,1))) - LOC(KSENDBUF(LBOUND(KSENDBUF,1)))) /= 4*(ISENDCOUNT - 1) .AND. &
+  & ISENDCOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: SENDBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT,KCOMM,KROOT)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(KRECVBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_GATHERV:RECVBUF MISSING',CDSTRING=CDSTRING,LDABORT=LLABORT)
+
+  IRECVBUFSIZE = SIZE(KRECVBUF)
+  IF( (LOC(KRECVBUF(UBOUND(KRECVBUF,1))) - LOC(KRECVBUF(LBOUND(KRECVBUF,1)))) /= 4*(IRECVBUFSIZE - 1) .AND. &
+    & IRECVBUFSIZE > 0 ) THEN
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV: RECVBUF NOT CONTIGUOUS ',LDABORT=LLABORT)
+  ENDIF
+
+  CALL MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+       & KRECVCOUNTS,IRECVDISPL,KRECVDISPL,CDSTRING)
+  CALL MPI_GATHERV(KSENDBUF(1),ISENDCOUNT,INT(MPI_INTEGER),KRECVBUF(1),&
+   & KRECVCOUNTS,IRECVDISPL,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+ELSE
+  CALL MPI_GATHERV(KSENDBUF(1),ISENDCOUNT,INT(MPI_INTEGER),ZDUM_INT,1, &
+   &  1,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_GATHERV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_GATHERV_INT
+
+SUBROUTINE MPL_GATHERV_INT_SCALAR(KSENDBUF,KROOT,KRECVBUF,KRECVCOUNTS,&
+ & KRECVDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8, MPI_GATHER => MPI_GATHER8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KSENDBUF
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVCOUNTS(:) ! Not used; for compatibility only
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC),IRECVCOUNTS(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM) :: IRECVBUFSIZE,ISENDCOUNT
+
+ISENDCOUNT = 1
+CALL MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT,KCOMM,KROOT)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(KRECVBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_GATHERV:RECVBUF MISSING',CDSTRING=CDSTRING,LDABORT=LLABORT)
+  IRECVBUFSIZE = SIZE(KRECVBUF)
+  IF(PRESENT(KRECVDISPL)) THEN
+    IRECVCOUNTS(:) = 1
+    CALL MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+         & IRECVCOUNTS,IRECVDISPL,KRECVDISPL,CDSTRING)
+    CALL MPI_GATHERV(KSENDBUF,ISENDCOUNT,INT(MPI_INTEGER),KRECVBUF(1),&
+     & IRECVCOUNTS,IRECVDISPL,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+  ELSE
+    IF(IRECVBUFSIZE < IPL_NUMPROC) THEN
+      CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV:IRECVBUFSIZE < IPL_NUMPROC',&
+       & CDSTRING=CDSTRING,LDABORT=LLABORT)
+    ENDIF
+    CALL MPI_GATHER(KSENDBUF,ISENDCOUNT,INT(MPI_INTEGER),KRECVBUF(1),&
+     & ISENDCOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+  ENDIF
+ELSE
+  IF(PRESENT(KRECVDISPL)) THEN
+    CALL MPI_GATHERV(KSENDBUF,ISENDCOUNT,INT(MPI_INTEGER),ZDUM_INT,1, &
+     &  1,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+  ELSE
+    CALL MPI_GATHER(KSENDBUF,ISENDCOUNT,INT(MPI_INTEGER),ZDUM_INT,&
+     & 1,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+  ENDIF
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_GATHERV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_GATHERV_INT_SCALAR
+
+SUBROUTINE MPL_GATHERV_REAL8_SCALAR(PSENDBUF,KROOT,PRECVBUF,KRECVCOUNTS,&
+ & KRECVDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8, MPI_GATHER => MPI_GATHER8
+#endif
+
+
+
+REAL(KIND=JPRB),INTENT(IN) :: PSENDBUF
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+REAL(KIND=JPRB),INTENT(OUT),OPTIONAL :: PRECVBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVCOUNTS(:) ! Not used; for compatibility only
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KRECVDISPL(:),KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECVDISPL(MPL_NUMPROC),IRECVCOUNTS(MPL_NUMPROC)
+INTEGER(KIND=JPIM) :: IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT
+INTEGER(KIND=JPIM) :: IRECVBUFSIZE,ISENDCOUNT
+
+ISENDCOUNT = 1
+CALL MPL_GATHERV_PREAMB1(IERROR,IPL_NUMPROC,IPL_MYRANK,ICOMM,IROOT,KCOMM,KROOT)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(PRECVBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_GATHERV:RECVBUF MISSING',CDSTRING=CDSTRING,LDABORT=LLABORT)
+  IRECVBUFSIZE = SIZE(PRECVBUF)
+  IF(PRESENT(KRECVDISPL)) THEN
+    IRECVCOUNTS(:) = 1
+    CALL MPL_GATHERV_PREAMB2(IPL_NUMPROC,IPL_MYRANK,IRECVBUFSIZE,ISENDCOUNT,&
+         & IRECVCOUNTS,IRECVDISPL,KRECVDISPL,CDSTRING)
+    CALL MPI_GATHERV(PSENDBUF,ISENDCOUNT,INT(MPI_REAL8),PRECVBUF(1),&
+     & IRECVCOUNTS,IRECVDISPL,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ELSE
+    IF(IRECVBUFSIZE < IPL_NUMPROC) THEN
+      CALL MPL_MESSAGE(CDMESSAGE='MPL_GATHERV:IRECVBUFSIZE < IPL_NUMPROC',&
+       & CDSTRING=CDSTRING,LDABORT=LLABORT)
+    ENDIF
+    CALL MPI_GATHER(PSENDBUF,ISENDCOUNT,INT(MPI_REAL8),PRECVBUF(1),&
+     & ISENDCOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ENDIF
+ELSE
+  IF(PRESENT(KRECVDISPL)) THEN
+    CALL MPI_GATHERV(PSENDBUF,ISENDCOUNT,INT(MPI_REAL8),ZDUM_JPRB,1, &
+     &  1,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ELSE
+    CALL MPI_GATHER(PSENDBUF,ISENDCOUNT,INT(MPI_REAL8),ZDUM_JPRB,&
+     & 1,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+  ENDIF
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_GATHERV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_GATHERV_REAL8_SCALAR
+
+END MODULE MPL_GATHERV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_groups.F90 b/odb/src/extras/ifsaux/module/mpl_groups.F90
new file mode 100644
index 0000000..c1d0453
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_groups.F90
@@ -0,0 +1,138 @@
+MODULE MPL_GROUPS
+
+!     Purpose.
+!     --------
+!       Use MPI groups for easier to read code (and more efficient
+!       communications, at least on IBM).
+
+!     Author.
+!     -------
+!       Y. Tremolet
+
+!     Modifications.
+!     --------------
+!       Original: 02-03-13
+! ------------------------------------------------------------------
+
+! --- *NOT* THREAD SAFE YET ---
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+PRIVATE
+PUBLIC MPL_COMM_GRID, MPL_ALL_LEVS_COMM, MPL_ALL_MS_COMM, &
+     & MPL_GROUPS_CREATE, MPL_CART_RANK, MPL_CART_COORDS
+
+INTEGER(KIND=JPIM) :: MPL_COMM_GRID, MPL_ALL_LEVS_COMM, MPL_ALL_MS_COMM, &
+           & MPL_GP_GRID
+LOGICAL,SAVE :: LGROUPSETUP=.FALSE.
+CONTAINS
+! ------------------------------------------------------------------
+
+SUBROUTINE MPL_GROUPS_CREATE(kprocw, kprocv)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_CART_CREATE => MPI_CART_CREATE8, MPI_COMM_GROUP => MPI_COMM_GROUP8, &
+    MPI_CART_SUB => MPI_CART_SUB8
+#endif
+
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN) :: kprocw, kprocv
+
+INTEGER(KIND=JPIM) :: idims(2), ierr
+LOGICAL :: ltorus(2), ldims(2), lreorder
+
+IF(LGROUPSETUP) RETURN
+
+idims(1)=kprocw
+idims(2)=kprocv
+ltorus(1)=.false.
+ltorus(2)=.false.
+lreorder=.false.
+
+CALL MPI_CART_CREATE(MPL_COMM_OML(1), 2, idims, ltorus, lreorder, &
+                   & MPL_COMM_GRID, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_GROUPS_CREATE: MPI_CART_CREATE')
+
+CALL MPI_COMM_GROUP(MPL_COMM_GRID, MPL_GP_GRID, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_GROUPS_CREATE: mpi_comm_group')
+
+! Group all levels for same Ms
+! ----------------------------
+ldims(1)=.false.
+ldims(2)=.true.
+CALL MPI_CART_SUB(MPL_COMM_GRID, ldims, MPL_ALL_LEVS_COMM, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_GROUPS_CREATE: mpi_cart_sub 1')
+
+! Group all Ms for same levels
+! ----------------------------
+ldims(1)=.true.
+ldims(2)=.false.
+CALL MPI_CART_SUB(MPL_COMM_GRID, ldims, MPL_ALL_MS_COMM, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_GROUPS_CREATE: mpi_cart_sub 2')
+
+LGROUPSETUP=.TRUE.
+
+END SUBROUTINE MPL_GROUPS_CREATE
+
+! ------------------------------------------------------------------
+
+FUNCTION MPL_CART_RANK(kprocw, kprocv)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_CART_RANK => MPI_CART_RANK8
+#endif
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)  :: kprocw, kprocv
+INTEGER(KIND=JPIM) :: MPL_CART_RANK
+
+INTEGER(KIND=JPIM) :: idims(2), iproc, ierr
+
+idims(1)=kprocw-1
+idims(2)=kprocv-1
+
+CALL MPI_CART_RANK(MPL_COMM_GRID, idims, iproc, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_CART_RANK: mpi_cart_rank')
+
+MPL_CART_RANK=iproc+1
+
+END FUNCTION MPL_CART_RANK
+
+! ------------------------------------------------------------------
+
+SUBROUTINE MPL_CART_COORDS(kproc, kprocw, kprocv)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_CART_COORDS => MPI_CART_COORDS8
+#endif
+
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN)   :: kproc
+INTEGER(KIND=JPIM), INTENT(OUT)  :: kprocw, kprocv
+
+INTEGER(KIND=JPIM) :: idims(2), iproc, ierr
+
+iproc=kproc-1
+
+CALL MPI_CART_COORDS(MPL_COMM_GRID, iproc, 2, idims, ierr)
+IF (ierr/=0) CALL mpl_message(ierr,'MPL_CART_COORDS: mpi_cart_coords')
+
+kprocw=idims(1)+1
+kprocv=idims(2)+1
+
+END SUBROUTINE MPL_CART_COORDS
+
+! ------------------------------------------------------------------
+
+END MODULE MPL_GROUPS
diff --git a/odb/src/extras/ifsaux/module/mpl_init_mod.F90 b/odb/src/extras/ifsaux/module/mpl_init_mod.F90
new file mode 100644
index 0000000..14d6849
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_init_mod.F90
@@ -0,0 +1,347 @@
+MODULE MPL_INIT_MOD
+
+!**** MPL_INIT - Initialises the Message passing environment
+
+!     Purpose.
+!     --------
+!     Must be called before any other MPL routine.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_INIT
+
+!        Input required arguments :
+!        -------------------------
+!           none
+
+!        Input optional arguments :
+!        -------------------------
+!           KOUTPUT  -  Level of printing for MPL routines
+!                       =0: none
+!                       =1: intermediate (default)
+!                       =2: full trace
+!           KUNIT    -  Fortran Unit to receive printed trace
+!           LDINFO   -  = .TRUE.  : Print informative msgs from MPL_INIT (default) 
+!                       = .FALSE. : Do not print
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_INIT aborts when an error is detected.
+!           KPROCS   -  Number of processes which have been initialised
+!                       in the MPI_COMM_WORLD communicator
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+!        R. El Khatib  14-May-2007 Do not propagate environment if NECSX
+!        S. Saarinen 04-Oct-2009 Reduced output & redefined MPL_COMM_OML(1)
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE OML_MOD, ONLY : OML_INIT, OML_MAX_THREADS
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_BUFFER_METHOD_MOD
+USE MPL_TOUR_TABLE_MOD
+USE MPL_LOCOMM_CREATE_MOD
+USE MPL_ARG_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_INIT
+
+PRIVATE
+
+CONTAINS 
+
+SUBROUTINE MPL_INIT(KOUTPUT,KUNIT,KERROR,KPROCS,LDINFO)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_INITIALIZED => MPI_INITIALIZED8, MPI_INIT => MPI_INIT8, &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8,     MPI_COMM_RANK => MPI_COMM_RANK8, &
+    MPI_BCAST => MPI_BCAST8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KOUTPUT,KUNIT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR,KPROCS
+LOGICAL,INTENT(IN),OPTIONAL :: LDINFO
+INTEGER(KIND=JPIM) :: IERROR,IP,ICOMM,IRANK,JNODE,JROC,ISTA
+INTEGER(KIND=JPIM) :: IMAX_THREADS, IRET, IROOT, INUM(2), ICOUNT
+INTEGER(KIND=JPIM) :: IREQUIRED,IPROVIDED
+LOGICAL            :: LLABORT=.TRUE., LLINIT, LLINFO
+CHARACTER(LEN=12)  :: CL_MBX_SIZE
+CHARACTER(LEN=12)  :: CL_ARCH
+CHARACTER(LEN=1024) :: CLENV
+CHARACTER(LEN=20)  :: CL_METHOD,CL_HOST
+
+IF(PRESENT(KOUTPUT)) THEN
+  MPL_OUTPUT=MAX(0,KOUTPUT)
+ELSE
+  MPL_OUTPUT=1
+ENDIF
+
+IF(PRESENT(KUNIT)) THEN
+  MPL_UNIT=MAX(0,KUNIT)
+ELSE
+  MPL_UNIT=6
+ENDIF
+
+IF(PRESENT(LDINFO)) THEN
+  LLINFO = LDINFO
+ELSE
+  LLINFO = .TRUE.
+ENDIF
+
+
+! If LMPLUSERCOMM is not set use MPI_COMM_WORLD
+IF(LMPLUSERCOMM) THEN
+   MPL_COMM = MPLUSERCOMM
+   IF (LLINFO) THEN
+      WRITE(MPL_UNIT,'(A)')'MPL_INIT : LMPLUSERCOMM used'
+      WRITE(MPL_UNIT,'(A,I8)')'Communicator : ',MPL_COMM
+   ENDIF
+ELSE
+   MPL_COMM = MPI_COMM_WORLD
+   IF (LLINFO) THEN
+      WRITE(MPL_UNIT,'(A)')'MPL_INIT : LMPLUSERCOMM not used'
+      WRITE(MPL_UNIT,'(A,I8)')'Communicator : ',MPL_COMM
+   ENDIF
+ENDIF
+
+IF(MPL_NUMPROC /= -1) THEN
+!!  We do not want this extra message
+!!  CALL MPL_MESSAGE(CDMESSAGE=' MPL_INIT CALLED MULTIPLE TIMES ')
+  IF(PRESENT(KERROR)) THEN
+    KERROR=0
+  ENDIF
+  IF(PRESENT(KPROCS)) THEN
+    KPROCS=MPL_NUMPROC
+  ENDIF
+  RETURN
+ENDIF
+
+CALL MPI_INITIALIZED(LLINIT, IRET)
+
+IF (.NOT.LLINIT) THEN
+
+  CALL EC_GETENV('ARCH',CL_ARCH)
+
+#ifdef RS6K
+  if(CL_ARCH(1:10)=='ibm_power6')then
+    write(0,*)'POWER6: CALLING EC_BIND BEFORE MPI_INIT'
+    CALL EC_BIND()
+  endif
+#endif
+
+#ifdef MPI2
+  IREQUIRED = MPI_THREAD_MULTIPLE
+  IPROVIDED = MPI_THREAD_SINGLE
+  CALL MPI_INIT_THREAD(IREQUIRED,IPROVIDED,IERROR)
+  LTHSAFEMPI = (IPROVIDED >= IREQUIRED)
+#else
+  CALL MPI_INIT(IERROR)
+  LTHSAFEMPI = .TRUE.
+#endif
+
+#ifdef RS6K
+  if(CL_ARCH(1:10)=='ibm_power4')then
+    write(0,*)'POWER5: CALLING EC_BIND AFTER MPI_INIT'
+    CALL EC_BIND()
+  endif
+#endif
+
+  LINITMPI_VIA_MPL = .TRUE.
+  CALL ec_mpi_atexit() ! ifsaux/support/endian.c: to make sure MPI_FINALIZE gets called
+
+ELSE
+  IERROR = 0
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0) THEN
+    CALL MPL_MESSAGE(IERROR,CDMESSAGE=' MPL_INIT ERROR ',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+
+CALL MPI_COMM_SIZE(MPL_COMM,MPL_NUMPROC,IERROR)
+
+IF(PRESENT(KPROCS)) THEN
+  KPROCS=MPL_NUMPROC
+ENDIF
+
+ALLOCATE (MPL_IDS(MPL_NUMPROC))
+DO IP=1,MPL_NUMPROC
+  MPL_IDS(IP)=IP
+ENDDO
+
+CALL MPI_COMM_RANK(MPL_COMM, IRANK, IERROR)
+MPL_RANK=IRANK+1
+
+#ifndef NECSX
+
+!-- Propagate environment variables & argument lists
+!   Here we have to be careful and use MPI_BCAST directly (not MPL_BROADCAST) since
+!   1) MPL_BUFFER_METHOD has not been called
+!   2) MPL_COMM_OML has not been initialized since it is possible that only the 
+!      master proc knows the # of threads (i.e. OMP_NUM_THREADS may be set only for master)
+
+! Do not propagate on nec machine because the environment variables could be mpi-task-specific.
+
+IF (MPL_NUMPROC > 1) THEN
+  IROOT = 0
+  !-- Progate environment variables
+  INUM(1) = 0 ! The number of environment variables
+  INUM(2) = 0 ! Do not (=0) or do (=1) overwrite if particular environment variable already exists (0 = default)
+  IF (MPL_RANK == 1) THEN ! Master proc inquires
+    CALL EC_NUMENV(INUM(1))        ! ../support/env.c
+    CALL EC_OVERWRITE_ENV(INUM(2)) ! ../support/env.c
+  ENDIF
+  ! The following broadcast does not use "mailbox" nor attached buffer, both potentially yet to be allocated
+  CALL MPI_BCAST(INUM(1),2,INT(MPI_INTEGER),IROOT,MPL_COMM,IERROR)
+  ICOUNT = LEN(CLENV)
+  DO IP=1,INUM(1)
+    IF (MPL_RANK == 1) CALL EC_STRENV(IP,CLENV)
+    ! The following broadcast does not use "mailbox" nor attached buffer, both potentially yet to be allocated
+    CALL MPI_BCAST(CLENV,ICOUNT,INT(MPI_BYTE),IROOT,MPL_COMM,IERROR)
+    IF (MPL_RANK > 1) THEN
+      IF (INUM(2) == 1) THEN
+        CALL EC_PUTENV(CLENV) ! ../support/env.c ; Unconditionally overwrite, even if already exists
+      ELSE
+        CALL EC_PUTENV_NOOVERWRITE(CLENV) ! ../support/env.c ; Do not overwrite, if exists
+      ENDIF
+    ENDIF
+  ENDDO
+  !-- Redo some env. variables (see ../utilities/fnecsx.c)
+  CALL EC_ENVREDO()
+  !-- Propagate argument list (all under the bonnet using MPL_ARG_MOD-module)
+  INUM = MPL_IARGC()
+ENDIF
+
+#endif
+
+CALL OML_INIT()
+IMAX_THREADS = OML_MAX_THREADS()
+ALLOCATE(MPL_COMM_OML(IMAX_THREADS))
+
+IF (LMPLUSERCOMM) THEN
+   MPL_COMM_OML(1) = MPLUSERCOMM
+   ISTA = 2
+ELSE
+   ISTA = 1
+ENDIF
+
+DO IP=ISTA,IMAX_THREADS
+  CALL MPL_LOCOMM_CREATE(MPL_NUMPROC,MPL_COMM_OML(IP))
+ENDDO
+MPL_COMM = MPL_COMM_OML(1) ! i.e. not necessary MPI_COMM_WORLD anymore
+
+#ifdef VPP
+MPL_METHOD=JP_BLOCKING_STANDARD
+MPL_MBX_SIZE=4000000
+CL_MBX_SIZE=' '
+CALL EC_GETENV('VPP_MBX_SIZE',CL_MBX_SIZE)
+IF(CL_MBX_SIZE == ' ') THEN
+  CALL EC_GETENV('MPL_MBX_SIZE',CL_MBX_SIZE)
+ENDIF
+IF(CL_MBX_SIZE /= ' ') THEN
+  READ(CL_MBX_SIZE,*) MPL_MBX_SIZE
+ENDIF
+IF (LLINFO) WRITE(MPL_UNIT,'(A)')'MPL_INIT : MPL_METHOD=JP_BLOCKING_STANDARD'
+IF (LLINFO) WRITE(MPL_UNIT,'(A,I12)')'MPL_INIT : MAILBOX SIZE=',MPL_MBX_SIZE
+LUSEHLMPI = .FALSE.
+
+!#elif defined (LINUX)
+!MPL_METHOD=JP_BLOCKING_STANDARD
+!MPL_MBX_SIZE=4000000
+!CL_MBX_SIZE=' '
+!CALL EC_GETENV('VPP_MBX_SIZE',CL_MBX_SIZE)
+!IF(CL_MBX_SIZE == ' ') THEN
+!  CALL EC_GETENV('MPL_MBX_SIZE',CL_MBX_SIZE)
+!ENDIF
+!IF(CL_MBX_SIZE /= ' ') THEN
+!  READ(CL_MBX_SIZE,*) MPL_MBX_SIZE
+!ENDIF
+!IF (LLINFO) WRITE(MPL_UNIT,'(A)')'MPL_INIT : MPL_METHOD=JP_BLOCKING_STANDARD'
+!IF (LLINFO) WRITE(MPL_UNIT,'(A,I12)')'MPL_INIT : MAILBOX SIZE=',MPL_MBX_SIZE
+!LUSEHLMPI = .FALSE.
+
+#else
+CL_METHOD=' '
+CALL EC_GETENV('MPL_METHOD',CL_METHOD)
+IF (CL_METHOD == 'JP_BLOCKING_STANDARD' ) THEN
+  MPL_METHOD=JP_BLOCKING_STANDARD
+ELSE
+  MPL_METHOD=JP_BLOCKING_BUFFERED
+ENDIF
+MPL_MBX_SIZE=1000000
+CL_MBX_SIZE=' '
+CALL EC_GETENV('MPL_MBX_SIZE',CL_MBX_SIZE)
+IF (CL_MBX_SIZE /= ' ') THEN
+  READ(CL_MBX_SIZE,*) MPL_MBX_SIZE
+ENDIF
+IF (CL_METHOD == 'JP_BLOCKING_STANDARD' ) THEN
+  IF (LLINFO) WRITE(MPL_UNIT,'(A)')'MPL_INIT : MPL_METHOD=JP_BLOCKING_STANDARD'
+ELSE
+  IF (LLINFO) WRITE(MPL_UNIT,'(A)')'MPL_INIT : MPL_METHOD=JP_BLOCKING_BUFFERED'
+ENDIF
+IF (LLINFO) WRITE(MPL_UNIT,'(A,I12)')'MPL_INIT : MAILBOX SIZE=',MPL_MBX_SIZE
+
+CALL MPL_BUFFER_METHOD(kmp_type=MPL_METHOD,kmbx_size=MPL_MBX_SIZE,LDINFO=LLINFO)
+LUSEHLMPI = .TRUE.
+#endif
+
+!!!! If you are not at ECMWF this may need changing!!!!
+CALL EC_GETENV('HOST',CL_HOST)
+IF(CL_HOST(1:2) == 'c1') THEN
+  MPL_NCPU_PER_NODE=64
+ELSEIF(CL_HOST(1:3) == 'hpc') THEN
+  MPL_NCPU_PER_NODE=32
+ELSE
+  MPL_NCPU_PER_NODE=1
+ENDIF
+MPL_MAX_TASK_PER_NODE=MAX(1, MPL_NCPU_PER_NODE/IMAX_THREADS)
+LFULLNODES=MOD(MPL_NUMPROC,MPL_MAX_TASK_PER_NODE) == 0
+MPL_NNODES=(MPL_NUMPROC-1)/MPL_MAX_TASK_PER_NODE+1
+ALLOCATE(MPL_TASK_PER_NODE(MPL_NNODES))
+ALLOCATE(MPL_NODE(MPL_NUMPROC))
+ALLOCATE(MPL_NODE_TASKS(MPL_NNODES,MPL_MAX_TASK_PER_NODE))
+MPL_NODE_TASKS(:,:)=-99
+ICOUNT=0
+DO JNODE=1,MPL_NNODES
+  DO JROC=1,MPL_MAX_TASK_PER_NODE
+    ICOUNT=ICOUNT+1
+    IF (ICOUNT<=MPL_NUMPROC) THEN
+       MPL_NODE(ICOUNT)=JNODE
+       MPL_TASK_PER_NODE(JNODE) = JROC
+       MPL_NODE_TASKS(JNODE,JROC) = ICOUNT
+    ENDIF
+  ENDDO
+ENDDO
+MPL_MYNODE=(MPL_RANK-1)/MPL_MAX_TASK_PER_NODE+1
+!WRITE(MPL_UNIT,*) 'MPL_INIT : NCPU_PER_NODE,MPL_MAX_TASK_PER_NODE,MPL_NNODES,MPL_MYNODE ',&
+! & MPL_NCPU_PER_NODE,MPL_MAX_TASK_PER_NODE,MPL_NNODES,MPL_MYNODE
+!WRITE(MPL_UNIT,*) 'MPL_INIT : MPL_NODE_TASKS(MPL_MYNODE,1:MPL_TASK_PER_NODE(MPL_MYNODE)) ', &
+! & MPL_NODE_TASKS(MPL_MYNODE,1:MPL_TASK_PER_NODE(MPL_MYNODE))
+
+ALLOCATE(MPL_OPPONENT(MPL_NUMPROC+1))
+CALL MPL_TOUR_TABLE(MPL_OPPONENT)
+
+RETURN
+END SUBROUTINE MPL_INIT
+
+END MODULE MPL_INIT_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_ioinit_mod.F90 b/odb/src/extras/ifsaux/module/mpl_ioinit_mod.F90
new file mode 100644
index 0000000..84b0b76
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_ioinit_mod.F90
@@ -0,0 +1,128 @@
+MODULE MPL_IOINIT_MOD
+
+!
+!     Purpose.  initialise parallel IO environment
+!     --------
+!
+!
+!     Interface.
+!     ----------
+!        call mpl_ioinit(...)
+!
+!        Explicit arguments :
+!        --------------------
+!
+!        input arguments:
+!        kop     -  Style of parallel IO
+!        kstrout - Number of output processors
+!        output arguments:
+!        kerror  - error code
+!
+!        Implicit arguments :
+!        --------------------
+!
+!     Method.
+!     -------
+!     MPL supports 4 styles of MPIIO
+!
+!     kop = 1    -  Blocking, non collective, shared file pointer
+!                   using MPI_FILE_WRITE_SHARED,
+!                         MPI_FILE_READ_SHARED
+!     kop = 2    -  Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED,
+!                         MPI_FILE_READ_ORDERED
+!     kop = 3    -  Non Blocking, non collective, shared file pointer
+!                   using MPI_FILE_IWRITE_SHARED,
+!                         MPI_FILE_IREAD_SHARED
+!                   and MPI_WAIT
+!     kop = 4    -  Non Blocking, collective, ordered, shared file pointer 
+!                   using MPI_FILE_WRITE_ORDERED_BEGIN/END,
+!                         MPI_FILE_READ_ORDERED_BEGIN/END
+!
+!     Externals.
+!     ----------
+!
+!     Reference.
+!     ----------
+!        none yet
+!
+!     Author.
+!     -------
+!        G.Mozdzynski
+!
+!     Modifications.
+!     --------------
+!        Original : 2000-12-08 (Based on MPE_IOINIT)
+!
+!     -----------------------------------------------------------------
+!
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPl_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+
+INTEGER(KIND=JPIM) :: MPL_NUMIO
+INTEGER(KIND=JPIM) :: MPL_IOP
+INTEGER(KIND=JPIM) :: MPL_COMM_IO
+
+PUBLIC MPL_IOINIT
+
+CONTAINS
+
+SUBROUTINE MPL_IOINIT(KOP,KSTROUT,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SPLIT => MPI_COMM_SPLIT8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KOP,KSTROUT
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+INTEGER(KIND=JPIM) :: COLOR,KEY
+
+!
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble
+!           --------
+
+IF(KOP < 1 .OR. KOP > 4) THEN
+
+  KERROR = -1
+  RETURN
+
+ENDIF
+
+!
+!     -----------------------------------------------------------------
+!
+!     2. Check Style of Operation and take appropriate action
+!     -------------------------------------------------------
+
+MPL_NUMIO = KSTROUT
+
+MPL_IOP = KOP
+
+IF(MPL_RANK <= KSTROUT) THEN
+  COLOR = 1
+ELSE
+  COLOR = MPI_UNDEFINED
+ENDIF
+
+KEY = 0
+
+CALL MPI_COMM_SPLIT(MPL_COMM,COLOR,KEY,MPL_COMM_IO,KERROR)
+
+!
+!
+!     -----------------------------------------------------------------
+RETURN
+END SUBROUTINE MPL_IOINIT
+
+END MODULE MPL_IOINIT_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_locomm_create_mod.F90 b/odb/src/extras/ifsaux/module/mpl_locomm_create_mod.F90
new file mode 100644
index 0000000..5ad11fc
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_locomm_create_mod.F90
@@ -0,0 +1,85 @@
+MODULE MPL_LOCOMM_CREATE_MOD
+
+!**** MPL_LOCOMM_CREATE Create a new communicator
+
+!     Purpose.
+!     --------
+!     Create a new communicator from lowest N tasks in MPI_COMM_WORLD 
+!     and set as default
+                                                                                
+!**   Interface.
+!     ----------
+!        CALL MPL_LOCOMM_CREATE
+
+!        Input required arguments :
+!        -------------------------
+!           N     -  Number of tasks in New Communicator
+
+!        Input optional arguments :
+!        -------------------------
+
+!        Output required arguments :
+!        -------------------------
+!           KCOMM -  New Communicator
+
+!        Output optional arguments :
+!        -------------------------
+!           MPL_LOCOMM_CREATE aborts when an error is detected.
+ 
+!     Author.
+!     -------
+!        J.Hague        
+
+!     Modifications.
+!     --------------
+!        Original: 21/07/2003
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_LOCOMM_CREATE
+
+CONTAINS 
+
+
+SUBROUTINE MPL_LOCOMM_CREATE(N,KCOMM)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_GROUP => MPI_COMM_GROUP8, MPI_GROUP_INCL => MPI_GROUP_INCL8, MPI_COMM_CREATE => MPI_COMM_CREATE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(OUT) :: KCOMM
+INTEGER(KIND=JPIM),INTENT(IN)  :: N
+
+INTEGER(KIND=JPIM) :: IRANK(N)
+INTEGER(KIND=JPIM) :: J, IER, IGROUP, MPI_GROUP_WORLD
+LOGICAL   :: LLABORT=.TRUE.
+
+DO J=1,N
+  IRANK(J)=J-1
+ENDDO
+
+CALL MPI_COMM_GROUP(MPL_COMM,MPI_GROUP_WORLD,IER)
+IF (IER/=0) CALL MPL_MESSAGE(IER,'MPL_LOCOMM_CREATE: MPI_COMM_GROUP',LDABORT=LLABORT)
+
+CALL MPI_GROUP_INCL(MPI_GROUP_WORLD,N,IRANK,IGROUP,IER)
+IF (IER/=0) CALL MPL_MESSAGE(IER,'MPL_LOCOMM_CREATE: MPI_GROUP_INCL',LDABORT=LLABORT)
+
+CALL MPI_COMM_CREATE(MPL_COMM,IGROUP,KCOMM,IER)
+IF (IER/=0) CALL MPL_MESSAGE(IER,'MPL_LOCOMM_CREATE: MPI_COMM_CREATE',LDABORT=LLABORT)
+
+RETURN
+
+END SUBROUTINE MPL_LOCOMM_CREATE
+
+END MODULE MPL_LOCOMM_CREATE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_message_mod.F90 b/odb/src/extras/ifsaux/module/mpl_message_mod.F90
new file mode 100644
index 0000000..186b5db
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_message_mod.F90
@@ -0,0 +1,100 @@
+MODULE MPL_MESSAGE_MOD
+
+!**** MPL_MESSAGE - Prints message
+
+!     Purpose.
+!     --------
+!     Creates an ASCII message for printing and optionally aborts
+
+!**   Interface.
+!     ----------
+!        CALL MPL_MESSAGE
+
+!        Input required arguments :
+!        -------------------------
+!           CDMESSAGE-  character string for message
+
+!        Input optional arguments :
+!        -------------------------
+!           KERROR   -  Error number
+!           CDSTRING -  Optional additional message 
+!                       prepended to CDMESSAGE
+!           LDABORT  -  forces ABORT if true
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           none
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_ABORT_MOD
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+PRIVATE
+
+PUBLIC MPL_MESSAGE
+
+CONTAINS 
+
+SUBROUTINE MPL_MESSAGE(KERROR,CDMESSAGE,CDSTRING,LDABORT)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_ERROR_STRING => MPI_ERROR_STRING8
+#endif
+
+
+IMPLICIT NONE
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL     :: KERROR
+CHARACTER*(*),INTENT(IN)          :: CDMESSAGE
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+LOGICAL      ,INTENT(IN),OPTIONAL :: LDABORT
+
+CHARACTER*(MPI_MAX_ERROR_STRING)  :: CLMPI_ERROR
+CHARACTER*10                      :: CLERROR
+INTEGER(KIND=JPIM)                         :: IRESULTLEN,IERROR
+
+IF(PRESENT(KERROR)) THEN
+  WRITE(CLERROR,'(I10)') KERROR
+ELSE
+  CLERROR=' '
+ENDIF
+IF(PRESENT(CDSTRING)) THEN
+  WRITE(MPL_UNIT,'(4A,I8)') CDSTRING,CDMESSAGE,CLERROR, &
+                               & ' FROM PROCESSOR ',MPL_RANK
+ELSE
+  WRITE(MPL_UNIT,'(3A,I8)') CDMESSAGE,CLERROR, &
+                               & ' FROM PROCESSOR ',MPL_RANK
+ENDIF
+
+IF(PRESENT(KERROR)) THEN
+  CALL MPI_ERROR_STRING(KERROR,CLMPI_ERROR,IRESULTLEN,IERROR)
+  WRITE(MPL_UNIT,'(2A,I8)') CLMPI_ERROR(1:IRESULTLEN),' in process ',MPL_RANK
+ENDIF
+
+IF(PRESENT(LDABORT)) THEN
+  IF(LDABORT) THEN
+    WRITE(0,'(2A,I8)') CLMPI_ERROR(1:IRESULTLEN),' in process ',MPL_RANK
+    CALL MPL_ABORT('ABORT')
+  ENDIF
+ENDIF
+RETURN
+END SUBROUTINE MPL_MESSAGE
+
+END MODULE MPL_MESSAGE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_module.F90 b/odb/src/extras/ifsaux/module/mpl_module.F90
new file mode 100644
index 0000000..c7c90cd
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_module.F90
@@ -0,0 +1,44 @@
+MODULE MPL_MODULE
+!
+!    Message Passing Library (MPL)
+!
+!    Interface between parallel applications and the
+!    Message Passing Interface (MPI standard) provided by the computer vendors
+!    This version requires only MPI release 1.
+!
+!    designed and developed by
+!      Mats Hamrud and David Dent,      ECMWF,      September 2000
+!
+!    all routines which wish to call MPL routines must contain:
+!    USE MPL_MODULE
+
+USE MPL_INIT_MOD
+USE MPL_BUFFER_METHOD_MOD
+USE MPL_SEND_MOD
+USE MPL_RECV_MOD
+USE MPL_WAIT_MOD
+USE MPL_BARRIER_MOD
+USE MPL_BROADCAST_MOD
+USE MPL_PROBE_MOD
+USE MPL_END_MOD
+USE MPL_MESSAGE_MOD
+USE MPL_ABORT_MOD
+USE MPL_COMM_CREATE_MOD
+USE MPL_ALLGATHER_MOD
+USE MPL_MYRANK_MOD
+USE MPL_NPROC_MOD
+USE MPL_IOINIT_MOD
+USE MPL_OPEN_MOD
+USE MPL_CLOSE_MOD
+USE MPL_READ_MOD
+USE MPL_WRITE_MOD
+USE MPL_ALLREDUCE_MOD
+USE MPL_GATHERV_MOD
+USE MPL_TOUR_TABLE_MOD
+USE MPL_ALLGATHERV_MOD
+USE MPL_ALLTOALLV_MOD
+USE MPL_SCATTERV_MOD
+USE MPL_GROUPS
+USE MPL_ARG_MOD
+
+END MODULE MPL_MODULE
diff --git a/odb/src/extras/ifsaux/module/mpl_mpif.F90 b/odb/src/extras/ifsaux/module/mpl_mpif.F90
new file mode 100644
index 0000000..c422a17
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_mpif.F90
@@ -0,0 +1,3 @@
+MODULE MPL_MPIF
+#include "mpif.h"
+END MODULE MPL_MPIF
diff --git a/odb/src/extras/ifsaux/module/mpl_mygatherv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_mygatherv_mod.F90
new file mode 100644
index 0000000..9e28625
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_mygatherv_mod.F90
@@ -0,0 +1,41 @@
+MODULE MPL_MYGATHERV_MOD
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+PRIVATE
+PUBLIC MPL_MYGATHERV
+
+LOGICAL :: LLABORT=.TRUE.
+
+CONTAINS
+
+! ------------------------------------------------------------------
+SUBROUTINE MPL_MYGATHERV(PSEND,KSEND,PRECV,KRECV,KDISPL,KROOT,KCOMM)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_GATHERV => MPI_GATHERV8
+#endif
+
+
+REAL(KIND=JPRB), INTENT(IN)  :: PSEND(:)
+REAL(KIND=JPRB), INTENT(OUT) :: PRECV(:)
+INTEGER(KIND=JPIM), INTENT(IN) :: KSEND, KRECV(:), KDISPL(:)
+INTEGER(KIND=JPIM), INTENT(IN) :: KROOT, KCOMM
+INTEGER(KIND=JPIM) :: ierr
+
+CALL MPI_GATHERV(PSEND,KSEND,INT(MPI_REAL8), &
+               & PRECV,KRECV,KDISPL,INT(MPI_REAL8),KROOT-1,KCOMM,ierr)
+
+IF (ierr/=0) CALL MPL_MESSAGE(ierr,'MPL_MYGATHERV',LDABORT=LLABORT)
+
+END SUBROUTINE MPL_MYGATHERV
+! ------------------------------------------------------------------
+
+END MODULE MPL_MYGATHERV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_myrank_mod.F90 b/odb/src/extras/ifsaux/module/mpl_myrank_mod.F90
new file mode 100644
index 0000000..d9db2af
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_myrank_mod.F90
@@ -0,0 +1,80 @@
+MODULE MPL_MYRANK_MOD
+
+!**** MPL_MYRANK - Find rank
+
+!     Purpose.
+!     --------
+!     Returns the rank of the calling process 
+!     in the currently active communicator
+
+!**   Interface.
+!     ----------
+!        IRANK=MPL_MYRANK(KCOMM)
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+
+!        Input required arguments :
+!        -------------------------
+
+!        Input optional arguments :
+!        -------------------------
+!           none
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           none
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+PRIVATE
+PUBLIC MPL_MYRANK
+
+CONTAINS 
+
+FUNCTION MPL_MYRANK(KCOMM)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_RANK => MPI_COMM_RANK8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM) :: MPL_MYRANK
+
+INTEGER(KIND=JPIM) IRANK,IERROR,ICOMM
+LOGICAL :: LLABORT=.TRUE.
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_MYRANK: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  CALL MPI_COMM_RANK(KCOMM, IRANK, IERROR)
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,&
+   &'MPL_MYRANK: ERROR FROM MPI_COMM_RANK')
+  MPL_MYRANK=IRANK+1
+ELSE
+  MPL_MYRANK=MPL_RANK
+ENDIF
+
+END FUNCTION MPL_MYRANK
+
+END MODULE MPL_MYRANK_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_nproc_mod.F90 b/odb/src/extras/ifsaux/module/mpl_nproc_mod.F90
new file mode 100644
index 0000000..48ce4f6
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_nproc_mod.F90
@@ -0,0 +1,52 @@
+MODULE MPL_NPROC_MOD
+!**** MPL_NPROC - return Number of processes 
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+PRIVATE
+PUBLIC MPL_NPROC
+
+CONTAINS 
+FUNCTION MPL_NPROC(KCOMM)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM) :: MPL_NPROC
+
+INTEGER(KIND=JPIM) :: IERROR,IPROC
+LOGICAL   :: LLABORT=.TRUE.
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_MYRANK: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+IF(PRESENT(KCOMM)) THEN
+  CALL MPI_COMM_SIZE(KCOMM,IPROC,IERROR)
+  MPL_NPROC = IPROC
+ELSE
+  MPL_NPROC = MPL_NUMPROC 
+ENDIF
+
+  
+END FUNCTION MPL_NPROC
+END MODULE MPL_NPROC_MOD
+
diff --git a/odb/src/extras/ifsaux/module/mpl_open_mod.F90 b/odb/src/extras/ifsaux/module/mpl_open_mod.F90
new file mode 100644
index 0000000..6a59dc5
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_open_mod.F90
@@ -0,0 +1,128 @@
+MODULE MPL_OPEN_MOD
+!
+!     Purpose.  open an MPIIO file 
+!     --------
+!
+!
+!     Interface.
+!     ----------
+!        call mpl_open(...)
+!
+!        Explicit arguments :
+!        --------------------
+!
+!        input arguments:
+!        ktype   - 1 = open for reading , 2 = writing
+!        kname   - Name of the file
+!        output arguments:
+!        kfptr   - handle for file pointer
+!        kerror  - error code
+!
+!        Implicit arguments :
+!        --------------------
+!
+!     Method.
+!     -------
+!     MPL supports 4 styles of MPIIO
+!
+!     kop = 1    -  Blocking, non collective, shared file pointer
+!                   using MPI_FILE_WRITE_SHARED,
+!                         MPI_FILE_READ_SHARED
+!     kop = 2    -  Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED,
+!                         MPI_FILE_READ_ORDERED
+!     kop = 3    -  Non Blocking, non collective, shared file pointer
+!                   using MPI_FILE_IWRITE_SHARED,
+!                         MPI_FILE_IREAD_SHARED
+!                   and MPI_WAIT
+!     kop = 4    -  Non Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED_BEGIN/END,
+!                         MPI_FILE_READ_ORDERED_BEGIN/END
+!    
+!
+!     Externals.
+!     ----------
+!
+!     Reference.
+!     ----------
+!        none yet
+!
+!     Author.
+!     -------
+!        G.Mozdzynski
+!
+!     Modifications.
+!     --------------
+!        Original : 2000-12-08 (Based on MPE_OPEN)
+!
+!     -----------------------------------------------------------------
+!
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_IOINIT_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_OPEN
+
+CONTAINS
+
+SUBROUTINE MPL_OPEN(KFPTR,KTYPE,KNAME,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_OPEN => MPI_FILE_OPEN8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: ktype
+INTEGER(KIND=JPIM),INTENT(OUT) :: kfptr,kerror
+CHARACTER*(*) KNAME
+INTEGER(KIND=JPIM) :: mode,info
+
+#ifdef MPI2
+
+!
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble
+!           --------
+!
+IF( MPL_RANK > MPL_NUMIO ) then
+  KERROR = -1
+  RETURN
+ENDIF
+
+IF( KTYPE == 1 ) THEN
+   MODE = MPI_MODE_RDONLY
+ELSEIF( KTYPE == 2 ) THEN
+   MODE = MPI_MODE_WRONLY + MPI_MODE_CREATE
+ELSE
+   KERROR = -1
+   RETURN
+ENDIF
+
+INFO = MPI_INFO_NULL
+    
+!     -----------------------------------------------------------------
+!
+!     2.    open the file
+!           ----------------------
+
+CALL MPI_FILE_OPEN(MPL_COMM_IO,KNAME,MODE,INFO,KFPTR,KERROR)
+!
+!
+!     -----------------------------------------------------------------
+#else
+
+CALL ABOR1('MPL_OPEN not built with MPI2')
+
+#endif
+
+RETURN
+END SUBROUTINE MPL_OPEN
+
+END MODULE MPL_OPEN_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_probe_mod.F90 b/odb/src/extras/ifsaux/module/mpl_probe_mod.F90
new file mode 100644
index 0000000..3c91856
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_probe_mod.F90
@@ -0,0 +1,133 @@
+MODULE MPL_PROBE_MOD
+
+!**** MPL_PROBE - Check for incoming message
+
+!     Purpose.
+!     --------
+!     Look for existence of an incoming message.
+
+!**   Interface.
+!     ----------
+!        CALL MPL_PROBE
+
+!        Input required arguments :
+!        -------------------------
+!           none
+
+!        Input optional arguments :
+!        -------------------------
+!           KSOURCE  -  rank of process sending the message
+!                       default is MPI_ANY_SOURCE
+!           KTAG     -  tag of incoming message
+!                       default is MPI_ANY_TAG
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!           LDWAIT   -  = TRUE : waits for a message to be available
+!                       = FALSE: return immediately and set
+!                                LDFLAG to indicate if a message exists
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_PROBE aborts when an error is detected.
+!           LDFLAG   -  must be supplied if LDWAIT=false
+!                       = TRUE if a message exists
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_PROBE
+
+PRIVATE
+
+!--- Moved into subroutine to make thrreadsafe----
+! INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+! INTEGER(KIND=JPIM) :: ICOMM,ITAG,ISOURCE,IERROR
+! LOGICAL :: LLWAIT,LLABORT=.TRUE.
+
+CONTAINS
+
+SUBROUTINE MPL_PROBE(KSOURCE,KTAG,KCOMM,LDWAIT,LDFLAG,CDSTRING,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_PROBE => MPI_PROBE8, MPI_IPROBE => MPI_IPROBE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(IN), OPTIONAL  :: KSOURCE,KTAG,KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL  :: KERROR
+LOGICAL,INTENT(IN), OPTIONAL  :: LDWAIT
+LOGICAL,INTENT(OUT),OPTIONAL  :: LDFLAG
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+INTEGER(KIND=JPIM) :: ICOMM,ITAG,ISOURCE,IERROR
+LOGICAL :: LLWAIT,LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_PROBE: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(PRESENT(KSOURCE)) THEN
+  ISOURCE=KSOURCE-1
+ELSE
+  ISOURCE=MPI_ANY_SOURCE
+ENDIF
+IF(PRESENT(KTAG)) THEN
+  ITAG=KTAG
+ELSE
+  ITAG=MPI_ANY_TAG
+ENDIF
+
+IF(PRESENT(LDWAIT)) THEN
+  LLWAIT=LDWAIT
+ELSE
+  LLWAIT=.TRUE.
+ENDIF
+
+IF(LLWAIT) THEN
+  CALL MPI_PROBE(ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSE
+  IF(PRESENT(LDFLAG)) THEN
+    CALL MPI_IPROBE(ISOURCE,ITAG,ICOMM,LDFLAG,IRECV_STATUS,IERROR)
+  ELSE
+    CALL MPL_MESSAGE(IERROR,'MPL_PROBE: MUST PROVIDE LDFLAG ',CDSTRING, &
+                    & LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_PROBE',CDSTRING,LDABORT=LLABORT)
+ENDIF
+  
+RETURN
+END SUBROUTINE MPL_PROBE
+
+END MODULE MPL_PROBE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_read_mod.F90 b/odb/src/extras/ifsaux/module/mpl_read_mod.F90
new file mode 100644
index 0000000..f0006aa
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_read_mod.F90
@@ -0,0 +1,319 @@
+MODULE MPL_READ_MOD
+
+!
+!     Purpose.  read from an MPIIO file 
+!     --------
+!
+!
+!     Interface.
+!     ----------
+!        call mpl_read(...)
+!
+!        Explicit arguments :
+!        --------------------
+!
+!        input arguments:
+!        kfptr   - handle for file
+!        kop     - requested operation 
+!        kbuf    - buffer containing data to be written
+!        klen    - length of buffer in words
+!        input/output arguements:
+!        kreq    - request handle for non-blocking operations
+!        output arguments:
+!        kerror  - error code
+!
+!        Implicit arguments :
+!        --------------------
+!
+!     Method.
+!     -------
+!     MPL supports 4 styles of MPIIO
+!
+!     kop = 1    -  Blocking, non collective, shared file pointer
+!                   using MPI_FILE_WRITE_SHARED,
+!                         MPI_FILE_READ_SHARED
+!     kop = 2    -  Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED,
+!                         MPI_FILE_READ_ORDERED
+!     kop = 3    -  Non Blocking, non collective, shared file pointer
+!                   using MPI_FILE_IWRITE_SHARED,
+!                         MPI_FILE_IREAD_SHARED
+!                   and MPI_WAIT
+!     kop = 4    -  Non Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED_BEGIN/END,
+!                         MPI_FILE_READ_ORDERED_BEGIN/END
+!
+!     Externals.
+!     ----------
+!
+!     Reference.
+!     ----------
+!        none yet
+!
+!     Author.
+!     -------
+!        G.Mozdzynski
+!
+!     Modifications.
+!     --------------
+!        Original : 2000-12-11
+!
+!     -----------------------------------------------------------------
+!
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_IOINIT_MOD
+
+IMPLICIT NONE
+
+INTERFACE MPL_READ
+MODULE PROCEDURE MPL_READ_INT,MPL_READ_REAL8
+END INTERFACE
+
+PUBLIC MPL_READ
+
+CONTAINS
+
+SUBROUTINE MPL_READ_INT(KFPTR,KOP,KBUF,KLEN,KREQ,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_READ_SHARED => MPI_FILE_READ_SHARED8, &
+    MPI_FILE_READ_ORDERED => MPI_FILE_READ_ORDERED8, &
+    MPI_FILE_IREAD_SHARED => MPI_FILE_IREAD_SHARED8, &
+    MPI_FILE_READ_ORDERED_BEGIN => MPI_FILE_READ_ORDERED_BEGIN8, &
+    MPI_WAIT => MPI_WAIT8, MPI_FILE_READ_ORDERED_END => MPI_FILE_READ_ORDERED_END8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KFPTR,KOP,KLEN
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+INTEGER(KIND=JPIM) KBUF(:)
+INTEGER(KIND=JPIM) KREQ
+
+
+INTEGER(KIND=JPIM) status(MPI_STATUS_SIZE)
+!
+#ifdef MPI2
+
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble 
+!           --------
+
+IF( MPL_RANK > MPL_NUMIO ) THEN
+  KERROR = -1
+  RETURN
+ENDIF
+
+IF( KOP >= 1.AND.KOP <= 4 ) THEN
+
+  IF( KOP /= MPL_IOP ) THEN
+    KERROR = -1
+    RETURN
+  ENDIF
+
+ENDIF
+!     -----------------------------------------------------------------
+!
+!     2.    Check style and take appropriate action 
+!           ---------------------------------------
+
+
+IF( KOP == 1 ) THEN
+
+! blocking read, non collective, shared file pointer
+        
+  CALL MPI_FILE_READ_SHARED(KFPTR,&
+                           & KBUF,&
+                           & KLEN,&
+                           & MPI_INTEGER,&
+                           & STATUS,&
+                           & KERROR)
+
+ELSEIF( KOP == 2 ) THEN
+
+! blocking read, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_READ_ORDERED(KFPTR,&
+                            & KBUF,&
+                            & KLEN,&
+                            & MPI_INTEGER,&
+                            & STATUS,&
+                            & KERROR)
+
+ELSEIF( KOP == 3 ) THEN
+
+! non blocking read, non collective, shared file pointer
+
+  CALL MPI_FILE_IREAD_SHARED(KFPTR,&
+                            & KBUF,&
+                            & KLEN,&
+                            & MPI_INTEGER,&
+                            & KREQ,&
+                            & KERROR)
+
+ELSEIF( KOP == 4 ) THEN
+
+! non blocking read, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_READ_ORDERED_BEGIN(KFPTR,&
+                                  & KBUF,&
+                                  & KLEN,&
+                                  & MPI_INTEGER,&
+                                  & KERROR)
+
+ELSEIF( KOP == 5 ) THEN
+
+  CALL MPI_WAIT(KREQ,&
+              & STATUS,&
+              & KERROR )
+
+ELSEIF( KOP == 6 ) THEN
+
+  CALL MPI_FILE_READ_ORDERED_END(KFPTR,&
+                                & KBUF,&
+                                & STATUS,&
+                                & KERROR)
+ 
+ELSE
+
+  KERROR =-1
+  RETURN
+
+ENDIF
+
+#else
+
+CALL ABOR1('MPL_READ_INT not build with MPI2')
+
+#endif
+!
+!     -----------------------------------------------------------------
+RETURN
+END SUBROUTINE MPL_READ_INT
+
+SUBROUTINE MPL_READ_REAL8(KFPTR,KOP,PBUF,KLEN,KREQ,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_READ_SHARED => MPI_FILE_READ_SHARED8, &
+    MPI_FILE_READ_ORDERED => MPI_FILE_READ_ORDERED8, &
+    MPI_FILE_IREAD_SHARED => MPI_FILE_IREAD_SHARED8, &
+    MPI_FILE_READ_ORDERED_BEGIN => MPI_FILE_READ_ORDERED_BEGIN8, &
+    MPI_WAIT => MPI_WAIT8, MPI_FILE_READ_ORDERED_END => MPI_FILE_READ_ORDERED_END8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KFPTR,KOP,KLEN
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+REAL(KIND=JPRM) PBUF(:)
+INTEGER(KIND=JPIM) KREQ
+
+
+INTEGER(KIND=JPIM) status(MPI_STATUS_SIZE)
+!
+#ifdef MPI2
+
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble 
+!           --------
+
+IF( MPL_RANK > MPL_NUMIO ) THEN
+  KERROR = -1
+  RETURN
+ENDIF
+
+IF( KOP >= 1.AND.KOP <= 4 ) THEN
+
+  IF( KOP /= MPL_IOP ) THEN
+    KERROR = -1
+    RETURN
+  ENDIF
+
+ENDIF
+!     -----------------------------------------------------------------
+!
+!     2.    Check style and take appropriate action 
+!           ---------------------------------------
+
+
+IF( KOP == 1 ) THEN
+
+! blocking read, non collective, shared file pointer
+        
+  CALL MPI_FILE_READ_SHARED(KFPTR,&
+                           & PBUF,&
+                           & KLEN,&
+                           & MPI_REAL8,&
+                           & STATUS,&
+                           & KERROR)
+
+ELSEIF( KOP == 2 ) THEN
+
+! blocking read, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_READ_ORDERED(KFPTR,&
+                            & PBUF,&
+                            & KLEN,&
+                            & MPI_REAL8,&
+                            & STATUS,&
+                            & KERROR)
+
+ELSEIF( KOP == 3 ) THEN
+
+! non blocking read, non collective, shared file pointer
+
+  CALL MPI_FILE_IREAD_SHARED(KFPTR,&
+                            & PBUF,&
+                            & KLEN,&
+                            & MPI_REAL8,&
+                            & KREQ,&
+                            & KERROR)
+
+ELSEIF( KOP == 4 ) THEN
+
+! non blocking read, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_READ_ORDERED_BEGIN(KFPTR,&
+                                  & PBUF,&
+                                  & KLEN,&
+                                  & MPI_REAL8,&
+                                  & KERROR)
+
+ELSEIF( KOP == 5 ) THEN
+
+  CALL MPI_WAIT(KREQ,&
+              & STATUS,&
+              & KERROR )
+
+ELSEIF( KOP == 6 ) THEN
+
+  CALL MPI_FILE_READ_ORDERED_END(KFPTR,&
+                                & PBUF,&
+                                & STATUS,&
+                                & KERROR)
+ 
+ELSE
+
+  KERROR =-1
+  RETURN
+
+ENDIF
+
+!
+!     -----------------------------------------------------------------
+#else
+
+CALL ABOR1('MPL_READ_REAL8 not build with MPI2')
+
+#endif
+
+RETURN
+END SUBROUTINE MPL_READ_REAL8
+
+END MODULE MPL_READ_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_recv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_recv_mod.F90
new file mode 100644
index 0000000..849289a
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_recv_mod.F90
@@ -0,0 +1,993 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE MPL_RECV_MOD
+
+!**** MPL_RECV Receive a message
+
+!     Purpose.
+!     --------
+!     Receive a message from a named source into a buffer.
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
+!                     REAL*4,or REAL*8, two dimensional array
+!                  or REAL or INTEGER scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_RECV
+
+!        Input required arguments :
+!        -------------------------
+!           PBUF     -  buffer to receive the message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+
+!        Input optional arguments :
+!        -------------------------
+!           KTAG     -  message tag
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!           KMP_TYPE -  buffering type (see MPL_BUFFER_METHOD)
+!                       overrides value provided to MPL_BUFFER_METHOD
+!           KSOURCE  -  rank of process sending the message
+!                       default is MPI_ANY_SOURCE
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KREQUEST -  Communication request
+!                       required when buffering type is non-blocking
+!           KFROM    -  rank of process sending the message
+!           KRECVTAG -  tag of received message
+!           KOUNT    -  number of items in received message
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_RECV aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIB, JPIM, JPRB, JPRM
+
+USE MPl_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_NPROC_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+
+!---Moved into subroutines to keep threadsafe----
+! INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR
+! INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+! INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+! LOGICAL :: LLABORT=.TRUE.
+!------------------------------------------------
+
+INTERFACE MPL_RECV
+MODULE PROCEDURE MPL_RECV_REAL4,  MPL_RECV_REAL8, &
+               & MPL_RECV_INT,    MPL_RECV_REAL42, &
+               & MPL_RECV_REAL82, MPL_RECV_INT_SCALAR, &
+               & MPL_RECV_INT2,   MPL_RECV_REAL4_SCALAR, &
+               & MPL_RECV_REAL8_SCALAR, MPL_RECV_CHAR_SCALAR, &
+               & MPL_RECV_INT8, MPL_RECV_CHAR
+END INTERFACE
+
+PUBLIC MPL_RECV
+
+CONTAINS
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KMP_TYPE,KCOMM,KSOURCE,KTAG
+INTEGER(KIND=JPIM),OPTIONAL :: KREQUEST
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE(&
+  & CDMESSAGE='MPL_RECV: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+!-----------------Moved into subroutines to keep threadsafe----
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  IF( .NOT. PRESENT(KREQUEST)) THEN
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:KREQUEST MISSING ',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(PRESENT(KSOURCE)) THEN
+  IF(KSOURCE < 1 .OR. KSOURCE >MPL_NPROC(ICOMM)) THEN
+    WRITE(MPL_ERRUNIT,*)'MPL_RECV: ERROR KSOURCE=',KSOURCE
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL KSOURCE ',LDABORT=LLABORT)
+  ENDIF
+  ISOURCE=KSOURCE-1
+ELSE
+  ISOURCE=MPI_ANY_SOURCE
+ENDIF
+
+IF(PRESENT(KTAG)) THEN
+  ITAG=KTAG
+ELSE
+  ITAG=MPI_ANY_TAG
+ENDIF
+!--------------------------------------------------------------
+
+END SUBROUTINE MPL_RECV_PREAMB
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_TAIL(KRECV_STATUS,KTYPE,KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KRECV_STATUS(MPI_STATUS_SIZE)
+INTEGER(KIND=JPIM),INTENT(IN) :: KTYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+LOGICAL :: LLABORT=.TRUE.
+
+IFROM=KRECV_STATUS(MPI_SOURCE)+1
+IF(PRESENT(KFROM)) THEN
+  KFROM=IFROM
+ENDIF
+CALL MPI_GET_COUNT(KRECV_STATUS,KTYPE,IRECVCOUNT,IERROR)
+IF(PRESENT(KOUNT)) THEN
+  KOUNT=IRECVCOUNT
+ENDIF
+IRECVTAG=KRECV_STATUS(MPI_TAG)
+IF(PRESENT(KRECVTAG)) THEN
+  KRECVTAG=IRECVTAG
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_RECV ',IRECVCOUNT,IMP_TYPE,IFROM,IRECVTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_RECV',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_RECV_TAIL
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL4(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+
+REAL(KIND=JPRM)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 4*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL4  
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL8(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+! real_b,intent(in) :: PBUF(:)
+REAL(KIND=JPRB)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 8*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL8
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_INT(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,KOUNT,&
+ &KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+INTEGER(KIND=JPIM)           :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(KBUF)
+
+IF( (LOC(KBUF(UBOUND(KBUF,1)))-LOC(KBUF(LBOUND(KBUF,1)))) /= 4*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_INT
+
+SUBROUTINE MPL_RECV_INT8(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,KOUNT,&
+ &KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+INTEGER(KIND=JPIB)           :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(KBUF)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+
+END SUBROUTINE MPL_RECV_INT8
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_INT2(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+INTEGER(KIND=JPIM)           :: KBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(KBUF)
+
+IF( (LOC(KBUF(UBOUND(KBUF,1),UBOUND(KBUF,2))) - &
+   & LOC(KBUF(LBOUND(KBUF,1),LBOUND(KBUF,2)))) /= 4*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_INT2
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_INT_SCALAR(KINT,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+INTEGER(KIND=JPIM)           :: KINT
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = 1
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_INT_SCALAR
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL4_SCALAR(PREAL4,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+
+REAL(KIND=JPRM)           :: PREAL4
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = 1
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL4_SCALAR
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL8_SCALAR(PREAL8,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+REAL(KIND=JPRB)           :: PREAL8
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = 1
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
+   & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL8_SCALAR
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL42(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8, MPI_IRECV => MPI_IRECV8
+#endif
+
+
+REAL(KIND=JPRM)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
+   & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 4*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL42  
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_REAL82(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+REAL(KIND=JPRB)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
+   & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 8*(IBUFFSIZE - 1) .AND. IBUFFSIZE > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_REAL82
+
+!     ------------------------------------------------------------------
+
+SUBROUTINE MPL_RECV_CHAR_SCALAR(CDCHAR,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+CHARACTER*(*) :: CDCHAR
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = LEN(CDCHAR)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+ENDIF
+
+END SUBROUTINE MPL_RECV_CHAR_SCALAR
+
+SUBROUTINE MPL_RECV_CHAR(CDCHAR,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
+ &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
+#endif
+
+CHARACTER*(*) :: CDCHAR(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
+INTEGER(KIND=JPIM) :: ISOURCE,IFROM,IRECVTAG,IRECVCOUNT,ITAG
+INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+CALL MPL_RECV_PREAMB(KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
+!------------- Repeat Preamb to make thread safe--------------
+  IF(PRESENT(KMP_TYPE)) THEN
+    IMP_TYPE=KMP_TYPE
+  ELSE
+    IMP_TYPE=MPL_METHOD
+  ENDIF
+  IF(PRESENT(KCOMM)) THEN
+    ICOMM=KCOMM
+  ELSE
+    ICOMM=MPL_COMM_OML(ITID)
+  ENDIF
+  IF(PRESENT(KSOURCE)) THEN
+    ISOURCE=KSOURCE-1
+  ELSE
+    ISOURCE=MPI_ANY_SOURCE
+  ENDIF
+  IF(PRESENT(KTAG)) THEN
+    ITAG=KTAG
+  ELSE
+    ITAG=MPI_ANY_TAG
+  ENDIF
+!------------ End Preamb Repeat------------------------
+
+IBUFFSIZE = LEN(CDCHAR) * SIZE(CDCHAR)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_RECV(CDCHAR(1),IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_RECV(CDCHAR(1),IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
+ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_IRECV(CDCHAR(1),IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
+ENDIF
+
+CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
+
+END SUBROUTINE MPL_RECV_CHAR
+
+!     ------------------------------------------------------------------
+
+END MODULE MPL_RECV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_scatterv_mod.F90 b/odb/src/extras/ifsaux/module/mpl_scatterv_mod.F90
new file mode 100644
index 0000000..3ce2afe
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_scatterv_mod.F90
@@ -0,0 +1,297 @@
+MODULE MPL_SCATTERV_MOD
+
+!**** MPL_SCATTERV Scatter data from specific processor
+
+!     Purpose.
+!     --------
+!     Scatter data from specific processor
+!     The data may be REAL*8,or INTEGER, one dimensional array
+!
+!**   Interface.
+!     ----------
+!        CALL MPL_SCATTERV
+
+!        Input required arguments :
+!        -------------------------
+!           PRECVBUF -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           PSENDBUF -  buffer containing message 
+!                       (required from kroot)
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KSENDCOUNTS-number of elements to be sent to each process
+!                       (required from kroot processor)
+
+!        Input optional arguments :
+!        -------------------------
+!           KROOT    -  rank of sending processor (default 1) 
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KSENDDISPL -displacements in PRECVBUF at which to place 
+!                       the incoming data
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_SCATTERV aborts when an error is detected.
+!     Author.
+!     -------
+!        Y. Tremolet, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 02-03-13
+
+! --- *NOT* THREAD SAFE YET ---
+
+!     ----------------------------------------------------------------
+USE PARKIND1  ,ONLY : JPIM     ,JPRB, JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_MYRANK_MOD
+
+IMPLICIT NONE
+PRIVATE
+PUBLIC MPL_SCATTERV
+
+INTEGER(KIND=JPIM) :: ICOMM,IROOT,IPL_NUMPROC,IRECVCOUNT,ISENDBUFSIZE,IR,IPL_MYRANK
+LOGICAL   :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: IERROR,IDUM
+REAL(KIND=JPRB)    :: ZDUM
+REAL(KIND=JPRM)    :: ZDUM_4
+INTEGER(KIND=JPIM)    :: ZDUM_INT
+
+INTERFACE MPL_SCATTERV
+MODULE PROCEDURE MPL_SCATTERV_REAL8,MPL_SCATTERV_REAL4,MPL_SCATTERV_INTEGER
+END INTERFACE
+
+CONTAINS
+
+SUBROUTINE MPL_SCATTERV_PREAMB1(KCOMM,KROOT)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SCATTERV => MPI_SCATTERV8, MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KROOT
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IERROR = 0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SCATTERV: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+
+IF(ICOMM == MPL_COMM_OML(ITID)) THEN
+  IPL_NUMPROC = MPL_NUMPROC
+  IPL_MYRANK  = MPL_RANK
+ELSE
+  CALL MPI_COMM_SIZE(ICOMM,IPL_NUMPROC,IERROR)
+  IPL_MYRANK  = MPL_MYRANK(ICOMM)
+ENDIF
+
+IF(PRESENT(KROOT)) THEN
+  IROOT=KROOT
+ELSE
+  IROOT=1
+ENDIF
+
+END SUBROUTINE MPL_SCATTERV_PREAMB1
+
+SUBROUTINE MPL_SCATTERV_PREAMB2(KSENDCOUNTS,KISENDDISPL,KSENDDISPL,CDSTRING)
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KSENDCOUNTS(:)
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KSENDDISPL(:)
+INTEGER(KIND=JPIM),INTENT(OUT) :: KISENDDISPL(:) 
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+
+IF(SIZE(KSENDCOUNTS)  < IPL_NUMPROC) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SCATTERV: ERROR KSENDCOUNTS DIMENSION=',&
+   & SIZE(KSENDCOUNTS)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_SCATTERV: ERROR KSENDCOUNTS DIMENSION IS WRONG',LDABORT=LLABORT)
+ENDIF
+IF(IRECVCOUNT /= KSENDCOUNTS(IPL_MYRANK)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SCATTERV: ERROR KSENDCOUNTS INCONSISTENCY ',&
+   & IRECVCOUNT,KSENDCOUNTS(IPL_MYRANK)
+  CALL MPL_MESSAGE(CDMESSAGE=&
+   & 'MPL_SCATTERV: ERROR IRECVCOUNT /= KSENDCOUNTS(MPL_RANK) ',LDABORT=LLABORT)
+ENDIF
+
+IF(PRESENT(KSENDDISPL)) THEN
+  KISENDDISPL(:) = KSENDDISPL(:)
+ELSE
+  KISENDDISPL(:) = 0
+  DO IR=2, IPL_NUMPROC
+    KISENDDISPL(IR) = KISENDDISPL(IR-1) + KSENDCOUNTS(IR-1)
+  ENDDO
+ENDIF
+DO IR=1, IPL_NUMPROC
+  IF(KISENDDISPL(IR)+KSENDCOUNTS(IR) > ISENDBUFSIZE) THEN
+    WRITE(MPL_ERRUNIT,'(A,4I10)')'MPL_SCATTERV:SEND BUFFER TOO SMALL  ', &
+     & IR,KISENDDISPL(IR),KSENDCOUNTS(IR),ISENDBUFSIZE
+    CALL MPL_MESSAGE(CDMESSAGE='MPL_SCATTERV',CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+ENDDO
+
+END SUBROUTINE MPL_SCATTERV_PREAMB2
+! ------------------------------------------------------------------
+SUBROUTINE MPL_SCATTERV_REAL8(PRECVBUF,KROOT,PSENDBUF,KSENDCOUNTS,KSENDDISPL,&
+ & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SCATTERV => MPI_SCATTERV8
+#endif
+
+
+REAL(KIND=JPRB), INTENT(OUT) :: PRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN) :: KROOT
+REAL(KIND=JPRB), INTENT(IN),OPTIONAL  :: PSENDBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDCOUNTS(:), KSENDDISPL(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ISENDDISPL(MPL_NUMPROC)
+
+CALL MPL_SCATTERV_PREAMB1(KCOMM,KROOT)
+IRECVCOUNT=SIZE(PRECVBUF)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(PSENDBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_SCATTERV:SENDBUF MISSING',CDSTRING=CDSTRING,&
+   & LDABORT=LLABORT)
+  ISENDBUFSIZE=SIZE(PSENDBUF)
+  CALL MPL_SCATTERV_PREAMB2(KSENDCOUNTS,ISENDDISPL,KSENDDISPL,CDSTRING)
+  CALL MPI_SCATTERV(PSENDBUF,KSENDCOUNTS,ISENDDISPL,INT(MPI_REAL8), &
+   & PRECVBUF,IRECVCOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+ELSE
+  CALL MPI_SCATTERV(ZDUM,1,1,INT(MPI_REAL8), &
+   & PRECVBUF,IRECVCOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
+ENDIF  
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'MPL_SCATTERV',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SCATTERV_REAL8
+! ------------------------------------------------------------------
+SUBROUTINE MPL_SCATTERV_REAL4(PRECVBUF,KROOT,PSENDBUF,KSENDCOUNTS,KSENDDISPL,&
+ & KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SCATTERV => MPI_SCATTERV8
+#endif
+
+
+REAL(KIND=JPRM), INTENT(OUT) :: PRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN) :: KROOT
+REAL(KIND=JPRM), INTENT(IN),OPTIONAL  :: PSENDBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDCOUNTS(:), KSENDDISPL(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ISENDDISPL(MPL_NUMPROC)
+
+CALL MPL_SCATTERV_PREAMB1(KCOMM,KROOT)
+IRECVCOUNT=SIZE(PRECVBUF)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(PSENDBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_SCATTERV:SENDBUF MISSING',CDSTRING=CDSTRING,&
+   & LDABORT=LLABORT)
+  ISENDBUFSIZE=SIZE(PSENDBUF)
+  CALL MPL_SCATTERV_PREAMB2(KSENDCOUNTS,ISENDDISPL,KSENDDISPL,CDSTRING)
+  CALL MPI_SCATTERV(PSENDBUF,KSENDCOUNTS,ISENDDISPL,INT(MPI_REAL4), &
+   & PRECVBUF,IRECVCOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
+ELSE
+  CALL MPI_SCATTERV(ZDUM_4,1,1,INT(MPI_REAL4), &
+   & PRECVBUF,IRECVCOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
+ENDIF  
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'MPL_SCATTERV',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SCATTERV_REAL4
+
+
+SUBROUTINE MPL_SCATTERV_INTEGER(KRECVBUF,KROOT,KSENDBUF,KSENDCOUNTS,&
+ & KSENDDISPL,KCOMM,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SCATTERV => MPI_SCATTERV8
+#endif
+
+
+INTEGER(KIND=JPIM), INTENT(OUT) :: KRECVBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN) :: KROOT
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDBUF(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KSENDCOUNTS(:), KSENDDISPL(:)
+INTEGER(KIND=JPIM), INTENT(IN),OPTIONAL :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ISENDDISPL(MPL_NUMPROC)
+
+CALL MPL_SCATTERV_PREAMB1(KCOMM,KROOT)
+IRECVCOUNT=SIZE(KRECVBUF)
+
+IF(IPL_MYRANK == IROOT) THEN
+  IF( .NOT. PRESENT(KSENDBUF)) CALL MPL_MESSAGE(&
+   & CDMESSAGE='MPL_SCATTERV:SENDBUF MISSING',CDSTRING=CDSTRING,&
+   & LDABORT=LLABORT)
+  ISENDBUFSIZE=SIZE(KSENDBUF)
+  CALL MPL_SCATTERV_PREAMB2(KSENDCOUNTS,ISENDDISPL,KSENDDISPL,&
+   & CDSTRING)
+  CALL MPI_SCATTERV(KSENDBUF,KSENDCOUNTS,ISENDDISPL,INT(MPI_INTEGER), &
+   & KRECVBUF,IRECVCOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+ELSE
+  CALL MPI_SCATTERV(ZDUM_INT,1,1,INT(MPI_INTEGER), &
+   & KRECVBUF,IRECVCOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
+ENDIF  
+
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF (IERROR/=0) CALL MPL_MESSAGE(IERROR,'MPL_SCATTERV',&
+   & CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SCATTERV_INTEGER
+! ------------------------------------------------------------------
+
+END MODULE MPL_SCATTERV_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_send_mod.F90 b/odb/src/extras/ifsaux/module/mpl_send_mod.F90
new file mode 100644
index 0000000..5be3302
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_send_mod.F90
@@ -0,0 +1,866 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE MPL_SEND_MOD
+
+!**** MPL_SEND Send a message
+
+!     Purpose.
+!     --------
+!     Send a message to a named source from a buffer.
+!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
+!                     REAL*4,or REAL*8, two dimensional array
+!                  or INTEGER scalar
+
+!**   Interface.
+!     ----------
+!        CALL MPL_SEND
+
+!        Input required arguments :
+!        -------------------------
+!           PBUF     -  buffer containing message
+!                       (can be type REAL*4, REAL*8 or INTEGER)
+!           KTAG     -  message tag
+!           KDEST    -  rank of process to receive the message
+
+!        Input optional arguments :
+!        -------------------------
+!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
+!                       or from that established as the default 
+!                       by an MPL communicator routine
+!           KMP_TYPE -  buffering type (see MPL_BUFFER_METHOD)
+!                       overrides value provided to MPL_BUFFER_METHOD
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KREQUEST -  Communication request
+!                       required when buffering type is non-blocking
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_SEND aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM, JPIB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_NPROC_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+!---Moved into subroutines to keep threadsafe----
+! INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+! LOGICAL :: LLABORT=.TRUE.
+
+INTERFACE MPL_SEND
+MODULE PROCEDURE MPL_SEND_REAL4, MPL_SEND_REAL8,&
+               & MPL_SEND_INT,   MPL_SEND_REAL42, &
+               & MPL_SEND_REAL82,MPL_SEND_INT_SCALAR, &
+               & MPL_SEND_INT2,  MPL_SEND_CHAR_SCALAR, &
+               & MPL_SEND_REAL8_SCALAR, &
+               & MPL_SEND_INT8,  MPL_SEND_CHAR
+END INTERFACE
+
+PUBLIC MPL_SEND
+
+CONTAINS
+
+SUBROUTINE MPL_SEND_REAL4(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+
+! real_m,intent(in) :: PBUF(:)
+REAL(KIND=JPRM)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+  
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 4*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_REAL4  
+
+SUBROUTINE MPL_SEND_REAL8(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+! real_b,intent(in) :: PBUF(:)
+REAL(KIND=JPRB)            :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 8*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_REAL8
+
+SUBROUTINE MPL_SEND_INT(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+INTEGER(KIND=JPIM)           :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(KBUF)
+
+IF( (LOC(KBUF(UBOUND(KBUF,1)))-LOC(KBUF(LBOUND(KBUF,1)))) /= 4*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_INT
+
+SUBROUTINE MPL_SEND_INT2(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+INTEGER(KIND=JPIM)           :: KBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(KBUF)
+
+IF( (LOC(KBUF(UBOUND(KBUF,1),UBOUND(KBUF,2))) - &
+   & LOC(KBUF(LBOUND(KBUF,1),LBOUND(KBUF,2)))) /= 4*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_INT2
+
+SUBROUTINE MPL_SEND_INT8(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+INTEGER(KIND=JPIB)            :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(KBUF)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_INT8
+
+SUBROUTINE MPL_SEND_INT_SCALAR(KINT,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+INTEGER(KIND=JPIM)           :: KINT     
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = 1
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_INT_SCALAR
+
+SUBROUTINE MPL_SEND_REAL42(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+! real_m,intent(in) :: PBUF(:,:)
+REAL(KIND=JPRM)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
+   & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 4*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_REAL42  
+
+SUBROUTINE MPL_SEND_REAL82(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+! real_b,intent(in) :: PBUF(:,:)
+REAL(KIND=JPRB)            :: PBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = SIZE(PBUF)
+
+IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
+   & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 8*(ICOUNT - 1) .AND. ICOUNT > 0 ) THEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
+ENDIF
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_REAL82
+
+SUBROUTINE MPL_SEND_CHAR_SCALAR(CDCHAR,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+CHARACTER*(*) :: CDCHAR
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = LEN(CDCHAR)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_CHAR_SCALAR
+
+SUBROUTINE MPL_SEND_CHAR(CDCHAR,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+CHARACTER*(*) :: CDCHAR(:)
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = LEN(CDCHAR) * SIZE(CDCHAR)
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(CDCHAR(1),ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(CDCHAR(1),ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(CDCHAR(1),ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(CDCHAR(1),ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(CDCHAR(1),ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_CHAR
+
+SUBROUTINE MPL_SEND_REAL8_SCALAR(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
+#endif
+
+REAL(KIND=JPRB)              :: PBUF
+INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
+INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+
+INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
+LOGICAL :: LLABORT=.TRUE.
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IF(PRESENT(KMP_TYPE)) THEN
+  IMP_TYPE=KMP_TYPE
+ELSE
+  IMP_TYPE=MPL_METHOD
+ENDIF
+IF(PRESENT(KCOMM)) THEN
+  ICOMM=KCOMM
+ELSE
+  ICOMM=MPL_COMM_OML(ITID)
+ENDIF
+IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
+ENDIF
+
+ICOUNT = 1
+
+IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
+  CALL MPI_SEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
+  CALL MPI_BSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
+  CALL MPI_ISEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
+  CALL MPI_IBSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
+    & KREQUEST,IERROR)
+ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
+  CALL MPI_SSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
+ELSE
+  IF(PRESENT(KERROR)) THEN
+    KERROR=1
+  ELSE
+    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
+  ENDIF
+ENDIF
+IF(MPL_OUTPUT > 1 )THEN
+  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
+ENDIF
+IF(PRESENT(KERROR)) THEN
+  KERROR=IERROR
+ELSE
+  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+END SUBROUTINE MPL_SEND_REAL8_SCALAR
+
+END MODULE MPL_SEND_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_setdflt_comm_mod.F90 b/odb/src/extras/ifsaux/module/mpl_setdflt_comm_mod.F90
new file mode 100644
index 0000000..ce32008
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_setdflt_comm_mod.F90
@@ -0,0 +1,74 @@
+MODULE MPL_SETDFLT_COMM_MOD
+
+!**** MPL_SETDFLT_COMM Set new default communicator
+
+!     Purpose.
+!     --------
+!     Set new communicator as default, and return old communicator
+
+!**   Interface.
+!     ----------
+!        CALL MPL_SETDFLT_COMM(KCOMM,KCOMM_OLD)
+
+!        Input required arguments :
+!        -------------------------
+!           KCOMM    -  New communicator
+
+!        Input optional arguments :
+!        -------------------------
+
+!        Output required arguments :
+!        -------------------------
+!           KCOMM_OLD    -  Old communicator
+
+!        Output optional arguments :
+!        -------------------------
+
+!     Author.
+!     -------
+!        J.Hague        
+
+!     Modifications.
+!     --------------
+!        Original: 2003-16-07
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PUBLIC MPL_SETDFLT_COMM
+
+CONTAINS 
+
+
+SUBROUTINE MPL_SETDFLT_COMM(KCOMM,KCOMM_OLD)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_COMM_SIZE => MPI_COMM_SIZE8
+#endif
+
+
+INTEGER(KIND=JPIM),INTENT(IN)  :: KCOMM
+INTEGER(KIND=JPIM),INTENT(OUT) :: KCOMM_OLD
+
+INTEGER(KIND=JPIM) :: IER
+INTEGER(KIND=JPIM) :: ITID
+ITID = OML_MY_THREAD()
+
+KCOMM_OLD=MPL_COMM_OML(ITID)
+MPL_COMM_OML(ITID)=KCOMM
+
+CALL MPI_COMM_SIZE(KCOMM,MPL_NUMPROC,IER)
+
+RETURN
+END SUBROUTINE MPL_SETDFLT_COMM
+
+END MODULE MPL_SETDFLT_COMM_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_tour_table_mod.F90 b/odb/src/extras/ifsaux/module/mpl_tour_table_mod.F90
new file mode 100644
index 0000000..10a3700
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_tour_table_mod.F90
@@ -0,0 +1,50 @@
+MODULE MPL_TOUR_TABLE_MOD
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE MPL_DATA_MODULE, ONLY : MPL_NUMPROC, MPL_RANK, MPL_ERRUNIT
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+PUBLIC MPL_TOUR_TABLE
+
+CONTAINS
+SUBROUTINE MPL_TOUR_TABLE(KOPPONENT, KEVEN)
+INTEGER(KIND=JPIM),INTENT(OUT)::KOPPONENT(:)
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL::KEVEN
+
+INTEGER(KIND=JPIM) :: ICIRCULAR(MPL_NUMPROC+1)
+INTEGER(KIND=JPIM) :: IEVEN,IMYPOS,ITMP,JK,JI
+LOGICAL :: LLABORT=.TRUE.
+
+IEVEN = ((MPL_NUMPROC+1)/2)*2
+IF(SIZE(KOPPONENT)  < IEVEN) THEN
+  WRITE(MPL_ERRUNIT,*)'MPL_TOUR_TABLE: ERROR KOPPONENT dimension=',&
+   & SIZE(KOPPONENT),'. MUST BE AT LEAST=',IEVEN
+  CALL MPL_MESSAGE(CDMESSAGE='MPL_TOUR_TABLE: ERROR KOPPONENT dimension wrong',&
+   & LDABORT=LLABORT)
+ENDIF
+
+DO JK = 1,IEVEN
+  ICIRCULAR(JK) = JK
+ENDDO
+KOPPONENT(:) = -1
+IMYPOS = MPL_RANK
+DO JK=1,IEVEN-1
+  KOPPONENT(JK) = ICIRCULAR(IEVEN-IMYPOS+1)
+  ITMP = ICIRCULAR(IEVEN-1)
+  DO JI=IEVEN-2,1,-1
+    ICIRCULAR(JI+1) = ICIRCULAR(JI)
+  ENDDO
+  ICIRCULAR(1) = ITMP
+  IF(MPL_RANK < IEVEN) IMYPOS = MOD(IMYPOS,IEVEN-1)+1
+ENDDO
+
+KOPPONENT(IEVEN) = MPL_RANK
+
+if (present(KEVEN)) KEVEN = IEVEN
+
+END SUBROUTINE MPL_TOUR_TABLE
+END MODULE MPL_TOUR_TABLE_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_wait_mod.F90 b/odb/src/extras/ifsaux/module/mpl_wait_mod.F90
new file mode 100644
index 0000000..7691b1e
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_wait_mod.F90
@@ -0,0 +1,494 @@
+MODULE MPL_WAIT_MOD
+
+!**** MPL_WAIT Waits for completion
+
+!     Purpose.
+!     --------
+!     Returns control when the operation(s) identified by the request
+!     is completed.
+!     Normally used in conjunction with non-blocking buffering type
+
+!**   Interface.
+!     ----------
+!        CALL MPL_WAIT
+
+!        Input required arguments :
+!        -------------------------
+!           PBUF     -  array with same size and shape as buffer
+!                       used for MPL_SEND or MPL_RECV
+!           KREQUEST -  array or scalar containing
+!                       Communication request(s)
+!                       as provided by MPL_RECV or MPL_SEND
+
+!        Input optional arguments :
+!        -------------------------
+!           CDSTRING -  Character string for ABORT messages
+!                       used when KERROR is not provided
+
+!        Output required arguments :
+!        -------------------------
+!           none
+
+!        Output optional arguments :
+!        -------------------------
+!           KOUNT    -  must be the same size and shape as KREQUEST
+!                       contains number of items sent/received
+!           KERROR   -  return error code.     If not supplied, 
+!                       MPL_WAIT aborts when an error is detected.
+!     Author.
+!     -------
+!        D.Dent, M.Hamrud     ECMWF
+
+!     Modifications.
+!     --------------
+!        Original: 2000-09-01
+!        J. Hague: 2005-04-25  WAITALL replaced by WAIT loop
+
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM, JPIB
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+
+IMPLICIT NONE
+
+PRIVATE
+
+INTERFACE MPL_WAIT
+MODULE PROCEDURE MPL_WAITS_REAL4,MPL_WAITS_REAL8,MPL_WAITS_INT, &
+               & MPL_WAIT1_REAL4,MPL_WAIT1_REAL8,MPL_WAIT1_INT, &
+               & MPL_WAITS_INT2,MPL_WAIT1_INT2,MPL_WAIT1_INT8
+END INTERFACE
+
+PUBLIC MPL_WAIT
+
+CONTAINS 
+
+
+SUBROUTINE MPL_WAITS_REAL4(PBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8, &
+    MPI_WAIT => MPI_WAIT8
+#endif
+
+REAL(KIND=JPRM)                        :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST(:)
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT(SIZE(KREQUEST))
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT,IW
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,SIZE(KREQUEST))
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=SIZE(KREQUEST)
+!CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+DO JL=1,IREQLEN
+  CALL MPI_WAIT(KREQUEST(JL),IWAIT_STATUS(1,JL),IW)
+  IWAITERR=MAX(IWAITERR,IW)
+ENDDO
+
+IF(PRESENT(KOUNT))THEN
+  IF(SIZE(KOUNT) /= IREQLEN) THEN
+    CALL MPL_MESSAGE( &
+    & CDMESSAGE='MPL_WAIT: KOUNT AND KREQUEST INCONSISTENT ', &
+    & CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  DO JL=1,IREQLEN
+    CALL MPI_GET_COUNT(IWAIT_STATUS(1,JL),INT(MPI_REAL4),KOUNT(JL),ICOUNTERR)
+  ENDDO
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAITS_REAL4
+
+
+SUBROUTINE MPL_WAIT1_REAL4(PBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+REAL(KIND=JPRM)                      :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,1)
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=1
+CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+
+IF(PRESENT(KOUNT))THEN
+  CALL MPI_GET_COUNT(IWAIT_STATUS(1,1),INT(MPI_REAL4),KOUNT,ICOUNTERR)
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAIT1_REAL4
+
+
+SUBROUTINE MPL_WAITS_REAL8(PBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8, &
+    MPI_WAIT => MPI_WAIT8
+#endif
+
+REAL(KIND=JPRB)                      :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST(:)
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT(SIZE(KREQUEST))
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT,IW
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,SIZE(KREQUEST))
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=SIZE(KREQUEST)
+!CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+DO JL=1,IREQLEN
+  CALL MPI_WAIT(KREQUEST(JL),IWAIT_STATUS(1,JL),IW)
+  IWAITERR=MAX(IWAITERR,IW)
+ENDDO
+
+IF(PRESENT(KOUNT))THEN
+  IF(SIZE(KOUNT) /= IREQLEN) THEN
+    CALL MPL_MESSAGE( &
+    & CDMESSAGE='MPL_WAIT: KOUNT AND KREQUEST INCONSISTENT ', &
+    & CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  DO JL=1,IREQLEN
+    CALL MPI_GET_COUNT(IWAIT_STATUS(1,JL),INT(MPI_REAL8),KOUNT(JL),ICOUNTERR)
+  ENDDO
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAITS_REAL8
+
+
+SUBROUTINE MPL_WAIT1_REAL8(PBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+REAL(KIND=JPRB)                      :: PBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,1)
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=1
+CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+
+IF(PRESENT(KOUNT))THEN
+  CALL MPI_GET_COUNT(IWAIT_STATUS(1,1),INT(MPI_REAL8),KOUNT,ICOUNTERR)
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAIT1_REAL8
+
+
+SUBROUTINE MPL_WAITS_INT(KBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8, &
+    MPI_WAIT => MPI_WAIT8
+#endif
+
+INTEGER(KIND=JPIM)                     :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST(:)
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT(SIZE(KREQUEST))
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT,IW
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,SIZE(KREQUEST))
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=SIZE(KREQUEST)
+!CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+DO JL=1,IREQLEN
+  CALL MPI_WAIT(KREQUEST(JL),IWAIT_STATUS(1,JL),IW)
+  IWAITERR=MAX(IWAITERR,IW)
+ENDDO
+
+IF(PRESENT(KOUNT))THEN
+  IF(SIZE(KOUNT) /= IREQLEN) THEN
+    CALL MPL_MESSAGE( &
+    & CDMESSAGE='MPL_WAIT: KOUNT AND KREQUEST INCONSISTENT ', &
+    & CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  DO JL=1,IREQLEN
+    CALL MPI_GET_COUNT(IWAIT_STATUS(1,JL),INT(MPI_INTEGER),KOUNT(JL),ICOUNTERR)
+  ENDDO
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAITS_INT
+
+
+SUBROUTINE MPL_WAIT1_INT(KBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+INTEGER(KIND=JPIM)                     :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,1)
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=1
+CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+
+IF(PRESENT(KOUNT))THEN
+  CALL MPI_GET_COUNT(IWAIT_STATUS(1,1),INT(MPI_INTEGER),KOUNT,ICOUNTERR)
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAIT1_INT
+
+SUBROUTINE MPL_WAIT1_INT8(KBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+INTEGER(KIND=JPIB)                     :: KBUF(:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,1)
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=1
+CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+
+IF(PRESENT(KOUNT))THEN
+  CALL MPI_GET_COUNT(IWAIT_STATUS(1,1),INT(MPI_INTEGER8),KOUNT,ICOUNTERR)
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAIT1_INT8
+
+
+SUBROUTINE MPL_WAITS_INT2(KBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8, &
+    MPI_WAIT => MPI_WAIT8
+#endif
+
+INTEGER(KIND=JPIM)                     :: KBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST(:)
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT(SIZE(KREQUEST))
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT,IW
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,SIZE(KREQUEST))
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=SIZE(KREQUEST)
+!CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+DO JL=1,IREQLEN
+  CALL MPI_WAIT(KREQUEST(JL),IWAIT_STATUS(1,JL),IW)
+  IWAITERR=MAX(IWAITERR,IW)
+ENDDO
+
+IF(PRESENT(KOUNT))THEN
+  IF(SIZE(KOUNT) /= IREQLEN) THEN
+    CALL MPL_MESSAGE( &
+    & CDMESSAGE='MPL_WAIT: KOUNT AND KREQUEST INCONSISTENT ', &
+    & CDSTRING=CDSTRING,LDABORT=LLABORT)
+  ENDIF
+  DO JL=1,IREQLEN
+    CALL MPI_GET_COUNT(IWAIT_STATUS(1,JL),INT(MPI_INTEGER),KOUNT(JL),ICOUNTERR)
+  ENDDO
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAITS_INT2
+
+
+SUBROUTINE MPL_WAIT1_INT2(KBUF,KREQUEST,KOUNT,KERROR,CDSTRING)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_WAITALL => MPI_WAITALL8, MPI_GET_COUNT => MPI_GET_COUNT8
+#endif
+
+INTEGER(KIND=JPIM)                     :: KBUF(:,:)
+INTEGER(KIND=JPIM),INTENT(IN)          :: KREQUEST
+CHARACTER*(*),INTENT(IN),OPTIONAL :: CDSTRING
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KOUNT
+INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
+INTEGER(KIND=JPIM) :: IWAITERR,ICOUNTERR,JL,IREQLEN,ICOUNT
+INTEGER(KIND=JPIM) :: IWAIT_STATUS(MPI_STATUS_SIZE,1)
+LOGICAL :: LLABORT
+LLABORT=.TRUE.
+IWAITERR=0
+ICOUNTERR=0
+
+IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
+  & CDMESSAGE='MPL_WAIT: MPL NOT INITIALISED ',LDABORT=LLABORT) 
+
+IREQLEN=1
+CALL MPI_WAITALL(IREQLEN,KREQUEST,IWAIT_STATUS,IWAITERR)
+
+IF(PRESENT(KOUNT))THEN
+  CALL MPI_GET_COUNT(IWAIT_STATUS(1,1),INT(MPI_INTEGER),KOUNT,ICOUNTERR)
+ENDIF
+
+IF(PRESENT(KERROR))THEN
+  KERROR=IWAITERR+ICOUNTERR
+ELSE IF(IWAITERR /= 0) THEN
+  CALL MPL_MESSAGE(IWAITERR,'MPL_WAIT_WAITING',CDSTRING,LDABORT=LLABORT)
+ELSE IF(ICOUNTERR /= 0) THEN
+  CALL MPL_MESSAGE(ICOUNTERR,'MPL_WAIT_COUNT',CDSTRING,LDABORT=LLABORT)
+ENDIF
+
+RETURN
+END SUBROUTINE MPL_WAIT1_INT2
+
+END MODULE MPL_WAIT_MOD
diff --git a/odb/src/extras/ifsaux/module/mpl_write_mod.F90 b/odb/src/extras/ifsaux/module/mpl_write_mod.F90
new file mode 100644
index 0000000..322da2b
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/mpl_write_mod.F90
@@ -0,0 +1,321 @@
+MODULE MPL_WRITE_MOD
+
+!
+!     Purpose.  write to an MPIIO file 
+!     --------
+!
+!
+!     Interface.
+!     ----------
+!        call mpl_write(...)
+!
+!        Explicit arguments :
+!        --------------------
+!
+!        input arguments:
+!        kfptr   - handle for file
+!        kop     - requested operation 
+!        kbuf    - buffer containing data to be written
+!        klen    - length of buffer in words
+!        input/output arguements:
+!        kreq    - request handle for non-blocking operations
+!        output arguments:
+!        kerror  - error code
+!
+!        Implicit arguments :
+!        --------------------
+!
+!     Method.
+!     -------
+!     MPL supports 4 styles of MPIIO
+!
+!     kop = 1    -  Blocking, non collective, shared file pointer
+!                   using MPI_FILE_WRITE_SHARED,
+!                         MPI_FILE_READ_SHARED
+!     kop = 2    -  Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED,
+!                         MPI_FILE_READ_ORDERED
+!     kop = 3    -  Non Blocking, non collective, shared file pointer
+!                   using MPI_FILE_IWRITE_SHARED,
+!                         MPI_FILE_IREAD_SHARED
+!                   and MPI_WAIT
+!     kop = 4    -  Non Blocking, collective, ordered, shared file pointer
+!                   using MPI_FILE_WRITE_ORDERED_BEGIN/END,
+!                         MPI_FILE_READ_ORDERED_BEGIN/END
+!
+!     Externals.
+!     ----------
+!
+!     Reference.
+!     ----------
+!        none yet
+!
+!     Author.
+!     -------
+!        G.Mozdzynski
+!
+!     Modifications.
+!     --------------
+!        Original : 2000-12-08 (Based on MPE_WRITE)
+!
+!     -----------------------------------------------------------------
+!
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPRM
+
+USE MPL_MPIF
+USE MPL_DATA_MODULE
+USE MPL_MESSAGE_MOD
+USE MPL_IOINIT_MOD
+
+IMPLICIT NONE
+
+INTERFACE MPL_WRITE
+MODULE PROCEDURE MPL_WRITE_INT,MPL_WRITE_REAL8
+END INTERFACE
+
+PUBLIC MPL_WRITE
+
+CONTAINS
+
+SUBROUTINE MPL_WRITE_INT(KFPTR,KOP,KBUF,KLEN,KREQ,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_WRITE_SHARED => MPI_FILE_WRITE_SHARED8, &
+    MPI_FILE_WRITE_ORDERED => MPI_FILE_WRITE_ORDERED8, &
+    MPI_FILE_IWRITE_SHARED => MPI_FILE_IWRITE_SHARED8, &
+    MPI_FILE_WRITE_ORDERED_BEGIN => MPI_FILE_WRITE_ORDERED_BEGIN8, &
+    MPI_WAIT => MPI_WAIT8, &
+    MPI_FILE_WRITE_ORDERED_END => MPI_FILE_WRITE_ORDERED_END8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KFPTR,KOP,KLEN
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+INTEGER(KIND=JPIM) KBUF(:)
+INTEGER(KIND=JPIM) KREQ
+
+
+INTEGER(KIND=JPIM) status(MPI_STATUS_SIZE)
+!
+#ifdef MPI2
+
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble 
+!           --------
+
+IF( MPL_RANK > MPL_NUMIO ) THEN
+  KERROR = -1
+  RETURN
+ENDIF
+
+IF( KOP >= 1.AND.KOP <= 4 ) THEN
+
+  IF( KOP /= MPL_IOP ) THEN
+    KERROR = -1
+    RETURN
+  ENDIF
+
+ENDIF
+!     -----------------------------------------------------------------
+!
+!     2.    Check style and take appropriate action 
+!           ---------------------------------------
+
+
+IF( KOP == 1 ) THEN
+
+! blocking write, non collective, shared file pointer
+        
+  CALL MPI_FILE_WRITE_SHARED(KFPTR,&
+                           & KBUF,&
+                           & KLEN,&
+                           & MPI_INTEGER,&
+                           & STATUS,&
+                           & KERROR)
+
+ELSEIF( KOP == 2 ) THEN
+
+! blocking write, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_WRITE_ORDERED(KFPTR,&
+                            & KBUF,&
+                            & KLEN,&
+                            & MPI_INTEGER,&
+                            & STATUS,&
+                            & KERROR)
+
+ELSEIF( KOP == 3 ) THEN
+
+! non blocking write, non collective, shared file pointer
+
+  CALL MPI_FILE_IWRITE_SHARED(KFPTR,&
+                            & KBUF,&
+                            & KLEN,&
+                            & MPI_INTEGER,&
+                            & KREQ,&
+                            & KERROR)
+
+ELSEIF( KOP == 4 ) THEN
+
+! non blocking write, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_WRITE_ORDERED_BEGIN(KFPTR,&
+                                  & KBUF,&
+                                  & KLEN,&
+                                  & MPI_INTEGER,&
+                                  & KERROR)
+
+ELSEIF( KOP == 5 ) THEN
+
+  CALL MPI_WAIT(KREQ,&
+              & STATUS,&
+              & KERROR )
+
+ELSEIF( KOP == 6 ) THEN
+
+  CALL MPI_FILE_WRITE_ORDERED_END(KFPTR,&
+                                & KBUF,&
+                                & STATUS,&
+                                & KERROR)
+ 
+ELSE
+
+  KERROR =-1
+  RETURN
+
+ENDIF
+
+#else
+
+CALL ABOR1('MPL_WRITE_INT not built with MPI2')
+
+#endif
+!
+!     -----------------------------------------------------------------
+RETURN
+END SUBROUTINE MPL_WRITE_INT
+
+SUBROUTINE MPL_WRITE_REAL8(KFPTR,KOP,PBUF,KLEN,KREQ,KERROR)
+
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : &
+    MPI_FILE_WRITE_SHARED => MPI_FILE_WRITE_SHARED8, &
+    MPI_FILE_WRITE_ORDERED => MPI_FILE_WRITE_ORDERED8, &
+    MPI_FILE_IWRITE_SHARED => MPI_FILE_IWRITE_SHARED8, &
+    MPI_FILE_WRITE_ORDERED_BEGIN => MPI_FILE_WRITE_ORDERED_BEGIN8, &
+    MPI_WAIT => MPI_WAIT8, &
+    MPI_FILE_WRITE_ORDERED_END => MPI_FILE_WRITE_ORDERED_END8
+#endif
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KFPTR,KOP,KLEN
+INTEGER(KIND=JPIM),INTENT(OUT) :: KERROR
+REAL(KIND=JPRM) PBUF(:)
+INTEGER(KIND=JPIM) KREQ
+
+
+INTEGER(KIND=JPIM) status(MPI_STATUS_SIZE)
+!
+#ifdef MPI2
+
+!     -----------------------------------------------------------------
+!
+!     1.    Preamble 
+!           --------
+
+IF( MPL_RANK > MPL_NUMIO ) THEN
+  KERROR = -1
+  RETURN
+ENDIF
+
+IF( KOP >= 1.AND.KOP <= 4 ) THEN
+
+  IF( KOP /= MPL_IOP ) THEN
+    KERROR = -1
+    RETURN
+  ENDIF
+
+ENDIF
+!     -----------------------------------------------------------------
+!
+!     2.    Check style and take appropriate action 
+!           ---------------------------------------
+
+
+IF( KOP == 1 ) THEN
+
+! blocking write, non collective, shared file pointer
+        
+  CALL MPI_FILE_WRITE_SHARED(KFPTR,&
+                           & PBUF,&
+                           & KLEN,&
+                           & MPI_REAL8,&
+                           & STATUS,&
+                           & KERROR)
+
+ELSEIF( KOP == 2 ) THEN
+
+! blocking write, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_WRITE_ORDERED(KFPTR,&
+                            & PBUF,&
+                            & KLEN,&
+                            & MPI_REAL8,&
+                            & STATUS,&
+                            & KERROR)
+
+ELSEIF( KOP == 3 ) THEN
+
+! non blocking write, non collective, shared file pointer
+
+  CALL MPI_FILE_IWRITE_SHARED(KFPTR,&
+                            & PBUF,&
+                            & KLEN,&
+                            & MPI_REAL8,&
+                            & KREQ,&
+                            & KERROR)
+
+ELSEIF( KOP == 4 ) THEN
+
+! non blocking write, collective, ordered with shared file pointer
+
+  CALL MPI_FILE_WRITE_ORDERED_BEGIN(KFPTR,&
+                                  & PBUF,&
+                                  & KLEN,&
+                                  & MPI_REAL8,&
+                                  & KERROR)
+
+ELSEIF( KOP == 5 ) THEN
+
+  CALL MPI_WAIT(KREQ,&
+              & STATUS,&
+              & KERROR )
+
+ELSEIF( KOP == 6 ) THEN
+
+  CALL MPI_FILE_WRITE_ORDERED_END(KFPTR,&
+                                & PBUF,&
+                                & STATUS,&
+                                & KERROR)
+ 
+ELSE
+
+  KERROR =-1
+  RETURN
+
+ENDIF
+
+#else
+
+CALL ABOR1('MPL_WRITE_REAL8 not built with MPI2')
+
+#endif
+
+!
+!     -----------------------------------------------------------------
+RETURN
+END SUBROUTINE MPL_WRITE_REAL8
+
+END MODULE MPL_WRITE_MOD
diff --git a/odb/src/extras/ifsaux/module/oml_mod.F90 b/odb/src/extras/ifsaux/module/oml_mod.F90
new file mode 100644
index 0000000..d281d31
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/oml_mod.F90
@@ -0,0 +1,297 @@
+MODULE OML_MOD
+
+!-- the following system specific omp_lib-module is not always available (e.g. pgf90)
+!! use omp_lib
+
+USE PARKIND1  ,ONLY : JPIM, JPIB
+
+!**SS/18-Feb-2005
+!--Dr.Hook references removed, because these locks may also be
+!  called from within drhook.c itself !! 
+!--Also, there could be considerable & unjustified overhead
+!  when using Dr.Hook in such a low level
+
+!**SS/15-Dec-2005
+!--The size of lock-variables are now OMP_LOCK_KIND as of in OMP_LIB,
+!  and OMP_LOCK_KIND is aliased to OML_LOCK_KIND
+!  OMP_LOCK_KIND is usually 4 in 32-bit addressing mode
+!                           8 in 64-bit addressing mode
+!--M_OML_LOCK changed to M_EVENT and kept as 32-bit int
+!--OML_FUNCT changed to OML_TEST_EVENT
+!--M_LOCK initialized to -1
+!--M_EVENT initialized to 0
+!--Added intent(s)
+!--Support for omp_lib (but not always available)
+!--Locks can now also be set/unset OUTSIDE the parallel regions
+!--Added routine OML_TEST_LOCK (attempts to set lock, but if *un*successful, does NOT  block)
+!--Buffer-zone for M_LOCK; now a vector of 2 elements in case problems/inconsistencies with OMP_LOCK_KIND 4/8
+
+!**SS/22-Feb-2006
+!--Locking routines are doing nothing unless OMP_GET_MAX_THREADS() > 1
+!  This is to avoid unacceptable deadlocks/timeouts with signal handlers when
+!  the only thread receives signal while inside locked region
+!--Affected routines: OML_TEST_LOCK()  --> always receives .TRUE.
+!                     OML_SET_LOCK()   --> sets nothing
+!                     OML_UNSET_LOCK() --> unsets nothing
+!                     OML_INIT_LOCK()  --> inits nothing
+
+!**SS/11-Sep-2006
+!--Added OML_DEBUG feature
+
+!**REK/18-Jul-2007
+!--Protected OML_DESTROY_LOCK
+
+!**REK/07-Sep-2007
+!--Add OMP FLUSH feature
+
+!**SS/05-Dec-2007
+!--Added routine OML_NUM_THREADS([optional_new_number_of_threads])
+! 1) To adjust [reduce] the number of threads working in concert
+!    Accepts only # of threads between 1 and the max # of threads (i.e. from export OMP_NUM_THREADS=<value>)
+! 2) Returns the previous active number of threads
+! 3) Can be called from outside the OpenMP-parallel region only
+
+!**SS/14-Dec-2007
+!--The routine OML_NUM_THREADS() now also accepts character string (= environment variable)
+!  as the sole argumentoz
+!--You could now set effective number of threads (<= $OMP_NUM_THREADS) to the value of
+!  particular environment variable; f.ex.:
+!  export OML_MSGPASS_OBSDATA_READ=8 and call to OML_NUM_THREADS('OML_MSGPASS_OBSDATA_READ')
+!  would set the effective no. of threads to (max) 8 when reading obs. wiz msgpass_obsdata
+
+!**SS/09-May-2008
+!-- OML_NUM_THREADS() did not work as expected since I misinterpreted the meaning of 
+!   the OpenMP-function OMP_NUM_THREADS()
+!-- With two PRIVATE [to this module] variables the bug will get sorted out
+!   + a new routine OML_INIT() was added (to be called from MPL_INIT or so)
+
+!**FV/27-May-2009
+!-- OML_GET_NUM_THREADS()
+
+IMPLICIT NONE
+
+SAVE
+
+PRIVATE
+
+LOGICAL :: OML_DEBUG = .FALSE.
+
+INTERFACE OML_NUM_THREADS
+MODULE PROCEDURE &
+     & OML_NUM_THREADS_INT, &
+     & OML_NUM_THREADS_STR
+END INTERFACE
+
+PUBLIC OML_WAIT_EVENT, OML_SET_EVENT, OML_INCR_EVENT, &
+   &   OML_MY_THREAD,  OML_MAX_THREADS , OML_OMP, &
+   &   OML_IN_PARALLEL, OML_TEST_EVENT, &
+   &   OML_UNSET_LOCK, OML_INIT_LOCK, OML_SET_LOCK, OML_DESTROY_LOCK, &
+   &   OML_LOCK_KIND, OML_TEST_LOCK, OML_DEBUG, OML_NUM_THREADS, &
+   &   OML_INIT, OML_GET_NUM_THREADS
+
+!-- The following should normally be 4 in 32-bit addressing mode
+!                                    8 in 64-bit addressing mode
+! Since system specific omp_lib-module is not always available (e.g. pgf90)
+! we hardcode OML_LOCK_KIND to JPIB (usually 8) for now
+!!INTEGER(KIND=JPIM), PARAMETER :: OML_LOCK_KIND = OMP_LOCK_KIND
+INTEGER(KIND=JPIM), PARAMETER :: OML_LOCK_KIND = JPIB
+
+!-- Note: Still JPIM !!
+INTEGER(KIND=JPIM) :: M_EVENT = 0
+
+!-- Note: OML_LOCK_KIND, not JPIM !!
+INTEGER(KIND=OML_LOCK_KIND) :: M_LOCK(2) = (/-1, -1/)
+
+!-- The two PRIVATE [to this module] variables
+INTEGER(KIND=JPIM) :: N_OML_MAX_THREADS = -1
+
+CONTAINS
+
+SUBROUTINE OML_INIT()
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+IF (N_OML_MAX_THREADS == -1) THEN
+   N_OML_MAX_THREADS = 1
+!$ N_OML_MAX_THREADS = OMP_GET_MAX_THREADS()
+ENDIF
+END SUBROUTINE OML_INIT
+
+FUNCTION OML_OMP()
+LOGICAL :: OML_OMP
+OML_OMP=.FALSE.
+!$ OML_OMP=.TRUE.
+END FUNCTION OML_OMP
+
+FUNCTION OML_IN_PARALLEL()
+LOGICAL :: OML_IN_PARALLEL
+!$ LOGICAL :: OMP_IN_PARALLEL
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+OML_IN_PARALLEL=.FALSE.
+!$ OML_IN_PARALLEL=((OMP_GET_MAX_THREADS() > 1).AND.OMP_IN_PARALLEL())
+END FUNCTION OML_IN_PARALLEL
+
+FUNCTION OML_TEST_LOCK(MYLOCK)
+INTEGER(KIND=OML_LOCK_KIND),intent(inout),optional :: MYLOCK
+LOGICAL :: OML_TEST_LOCK
+!$ LOGICAL :: OMP_TEST_LOCK
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+OML_TEST_LOCK = .TRUE.
+!$ IF(OMP_GET_MAX_THREADS() > 1) THEN
+!$   IF(PRESENT(MYLOCK))THEN
+!$     OML_TEST_LOCK = OMP_TEST_LOCK(MYLOCK)
+!$   ELSE
+!$     OML_TEST_LOCK = OMP_TEST_LOCK(M_LOCK(1))
+!$   ENDIF
+!$ ENDIF
+END FUNCTION OML_TEST_LOCK
+
+SUBROUTINE OML_UNSET_LOCK(MYLOCK)
+INTEGER(KIND=OML_LOCK_KIND),intent(inout),optional :: MYLOCK
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+!$ IF(OMP_GET_MAX_THREADS() > 1) THEN
+!$   IF(PRESENT(MYLOCK))THEN
+!$     CALL OMP_UNSET_LOCK(MYLOCK)
+!$   ELSE
+!$     CALL OMP_UNSET_LOCK(M_LOCK(1))
+!$   ENDIF
+!$ ENDIF
+END SUBROUTINE OML_UNSET_LOCK
+
+SUBROUTINE OML_SET_LOCK(MYLOCK)
+INTEGER(KIND=OML_LOCK_KIND),intent(inout),optional :: MYLOCK
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+!$ IF(OMP_GET_MAX_THREADS() > 1) THEN
+!$   IF(PRESENT(MYLOCK))THEN
+!$     CALL OMP_SET_LOCK(MYLOCK)
+!$   ELSE
+!$     CALL OMP_SET_LOCK(M_LOCK(1))
+!$   ENDIF
+!$ ENDIF
+END SUBROUTINE OML_SET_LOCK
+
+SUBROUTINE OML_INIT_LOCK(MYLOCK)
+INTEGER(KIND=OML_LOCK_KIND),intent(inout),optional :: MYLOCK
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+!$ IF(OMP_GET_MAX_THREADS() > 1) THEN
+!$   IF(PRESENT(MYLOCK))THEN
+!$     CALL OMP_INIT_LOCK(MYLOCK)
+!$   ELSE
+!$     CALL OMP_INIT_LOCK(M_LOCK(1))
+!$   ENDIF
+!$ ENDIF
+END SUBROUTINE OML_INIT_LOCK
+
+SUBROUTINE OML_DESTROY_LOCK(MYLOCK)
+INTEGER(KIND=OML_LOCK_KIND),intent(inout),optional :: MYLOCK
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+!$ IF(OMP_GET_MAX_THREADS() > 1) THEN
+!$   IF(PRESENT(MYLOCK))THEN
+!$     CALL OMP_DESTROY_LOCK(MYLOCK)
+!$   ELSE
+!$     CALL OMP_DESTROY_LOCK(M_LOCK(1))
+!$   ENDIF
+!$ ENDIF
+END SUBROUTINE OML_DESTROY_LOCK
+
+FUNCTION OML_TEST_EVENT(K,MYEVENT)
+LOGICAL :: OML_TEST_EVENT
+INTEGER(KIND=JPIM),intent(in) :: K,MYEVENT
+!$OMP FLUSH
+IF(K.EQ.MYEVENT) THEN
+ OML_TEST_EVENT =.TRUE.
+ELSE
+ OML_TEST_EVENT=.FALSE.
+ENDIF
+END FUNCTION OML_TEST_EVENT
+
+SUBROUTINE OML_WAIT_EVENT(K,MYEVENT)
+INTEGER(KIND=JPIM),intent(in) :: K
+INTEGER(KIND=JPIM),intent(in),OPTIONAL :: MYEVENT
+IF(PRESENT(MYEVENT))THEN
+  DO
+    IF(OML_TEST_EVENT(K,MYEVENT)) EXIT
+  ENDDO
+ELSE
+  DO
+    IF(OML_TEST_EVENT(K,M_EVENT)) EXIT
+  ENDDO
+ENDIF
+END SUBROUTINE OML_WAIT_EVENT
+
+SUBROUTINE OML_SET_EVENT(K,MYEVENT)
+INTEGER(KIND=JPIM),intent(in) :: K
+INTEGER(KIND=JPIM),intent(out),OPTIONAL :: MYEVENT
+IF(PRESENT(MYEVENT))THEN
+  MYEVENT=K
+ELSE
+  M_EVENT=K
+ENDIF
+END SUBROUTINE OML_SET_EVENT
+
+SUBROUTINE OML_INCR_EVENT(K,MYEVENT)
+INTEGER(KIND=JPIM) :: K
+INTEGER(KIND=JPIM),intent(inout),OPTIONAL :: MYEVENT
+call my_sync() 
+IF(PRESENT(MYEVENT))THEN
+  MYEVENT=MYEVENT+K
+ELSE
+  M_EVENT=M_EVENT+K
+ENDIF
+!$OMP FLUSH
+END SUBROUTINE OML_INCR_EVENT
+
+FUNCTION OML_MY_THREAD()
+INTEGER(KIND=JPIM) :: OML_MY_THREAD
+!$ INTEGER(KIND=JPIM) OMP_GET_THREAD_NUM
+OML_MY_THREAD = 1
+!$ OML_MY_THREAD = OMP_GET_THREAD_NUM() + 1
+END FUNCTION OML_MY_THREAD
+
+FUNCTION OML_MAX_THREADS()
+INTEGER(KIND=JPIM) :: OML_MAX_THREADS
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+OML_MAX_THREADS = 1
+!$ OML_MAX_THREADS = OMP_GET_MAX_THREADS()
+END FUNCTION OML_MAX_THREADS
+
+FUNCTION OML_GET_NUM_THREADS()
+INTEGER(KIND=JPIM) :: OML_GET_NUM_THREADS
+!$ INTEGER(KIND=JPIM) OMP_GET_NUM_THREADS
+OML_GET_NUM_THREADS = 1
+!$ OML_GET_NUM_THREADS = OMP_GET_NUM_THREADS()
+END FUNCTION OML_GET_NUM_THREADS
+
+FUNCTION OML_NUM_THREADS_INT(KOMP_SET_THREADS)
+INTEGER(KIND=JPIM) :: OML_NUM_THREADS_INT
+INTEGER(KIND=JPIM),intent(in),OPTIONAL :: KOMP_SET_THREADS
+!$ LOGICAL :: OMP_IN_PARALLEL
+!$ INTEGER(KIND=JPIM) OMP_GET_MAX_THREADS
+OML_NUM_THREADS_INT = 1
+!$ OML_NUM_THREADS_INT = OMP_GET_MAX_THREADS()
+!$ IF (PRESENT(KOMP_SET_THREADS)) THEN
+!$   IF (KOMP_SET_THREADS >= 1 .AND. KOMP_SET_THREADS <= N_OML_MAX_THREADS) THEN
+!- This is the absolute max no. of threads available --> ^^^^^^^^^^^^^^^^^ <--
+!$     IF (.NOT.OMP_IN_PARALLEL()) THEN ! Change only if called from OUTSIDE the OpenMP-parallel region
+!$       CALL OMP_SET_NUM_THREADS(KOMP_SET_THREADS)
+!$     ENDIF
+!$   ENDIF
+!$ ENDIF
+END FUNCTION OML_NUM_THREADS_INT
+
+FUNCTION OML_NUM_THREADS_STR(CD_ENV)
+INTEGER(KIND=JPIM) :: OML_NUM_THREADS_STR
+character(len=*),intent(in) :: CD_ENV
+!$ character(len=20) CLvalue
+!$ INTEGER(KIND=JPIM) :: itmp
+OML_NUM_THREADS_STR = 1
+!$ OML_NUM_THREADS_STR = OML_NUM_THREADS_INT()
+!$ IF (LEN(CD_ENV) > 0) THEN
+!$   CALL EC_GETENV(CD_ENV,CLvalue)
+!$   IF (CLvalue /= ' ') THEN
+!$     READ(CLvalue,'(i20)',end=99,err=99) itmp
+!$     OML_NUM_THREADS_STR = OML_NUM_THREADS_INT(itmp)
+!$   ENDIF
+!$ 99 continue
+!$ ENDIF
+END FUNCTION OML_NUM_THREADS_STR
+
+END MODULE OML_MOD
diff --git a/odb/src/extras/ifsaux/module/parkind1.F90 b/odb/src/extras/ifsaux/module/parkind1.F90
new file mode 100644
index 0000000..e8c02c3
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/parkind1.F90
@@ -0,0 +1,39 @@
+MODULE PARKIND1
+!
+!     *** Define usual kinds for strong typing ***
+!
+IMPLICIT NONE
+SAVE
+!
+!     Integer Kinds
+!     -------------
+!
+INTEGER, PARAMETER :: JPIT = SELECTED_INT_KIND(2)
+INTEGER, PARAMETER :: JPIS = SELECTED_INT_KIND(4)
+INTEGER, PARAMETER :: JPIM = SELECTED_INT_KIND(9)
+INTEGER, PARAMETER :: JPIB = SELECTED_INT_KIND(12)
+
+!Special integer type to be used for sensative adress calculations
+!should be *8 for a machine with 8byte adressing for optimum performance
+#ifdef ADDRESS64
+INTEGER, PARAMETER :: JPIA = JPIB
+#else
+INTEGER, PARAMETER :: JPIA = JPIM
+#endif
+
+!
+!     Real Kinds
+!     ----------
+!
+INTEGER, PARAMETER :: JPRT = SELECTED_REAL_KIND(2,1)
+INTEGER, PARAMETER :: JPRS = SELECTED_REAL_KIND(4,2)
+INTEGER, PARAMETER :: JPRM = SELECTED_REAL_KIND(6,37)
+INTEGER, PARAMETER :: JPRB = SELECTED_REAL_KIND(13,300)
+INTEGER, PARAMETER :: JPRD = SELECTED_REAL_KIND(13,300)
+!
+
+! Logical Kinds for RTTOV....
+
+INTEGER, PARAMETER :: JPLM = JPIM   !Standard logical type
+
+END MODULE PARKIND1
diff --git a/odb/src/extras/ifsaux/module/parkind2.F90 b/odb/src/extras/ifsaux/module/parkind2.F90
new file mode 100644
index 0000000..bc678da
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/parkind2.F90
@@ -0,0 +1,22 @@
+MODULE PARKIND2
+!
+!     *** Define huge kinds for strong typing ***
+!
+IMPLICIT NONE
+SAVE
+!
+!     Integer Kinds
+!     -------------
+!
+INTEGER, PARAMETER :: JPIH = SELECTED_INT_KIND(18)
+!
+!     Real Kinds
+!     ----------
+!
+#ifdef REALHUGE
+INTEGER, PARAMETER :: JPRH = SELECTED_REAL_KIND(31,291)
+#else
+INTEGER, PARAMETER :: JPRH = SELECTED_REAL_KIND(13,300)
+#endif
+!
+END MODULE PARKIND2
diff --git a/odb/src/extras/ifsaux/module/sdl_mod.F90 b/odb/src/extras/ifsaux/module/sdl_mod.F90
new file mode 100644
index 0000000..a07b3f1
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/sdl_mod.F90
@@ -0,0 +1,134 @@
+MODULE SDL_MOD
+
+!    Interface between user applications and system-dependent intrinsic
+!    routines, provided by the computer vendors.
+
+!    All routines which wish to call these routines must contain:
+!    USE SDL_MOD
+
+! Author :
+! ------
+!   11-Apr-2005 R. El Khatib  *METEO-FRANCE*
+!   26-Apr-2006 S.T.Saarinen  Dr.Hook trace, calls to EC_RAISE, Intel/ifort traceback
+
+USE PARKIND1  ,ONLY : JPIM  ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK ,DR_HOOK
+USE OML_MOD, ONLY : OML_MY_THREAD
+
+IMPLICIT NONE
+
+SAVE
+
+PRIVATE
+
+INTEGER, parameter :: SIGABRT = 6 ! Hardcoded
+
+PUBLIC :: SDL_SRLABORT, SDL_DISABORT, SDL_TRACEBACK
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+SUBROUTINE SDL_TRACEBACK(KTID)
+
+! Purpose :
+! -------
+!   Traceback
+
+!   KTID : thread 
+
+INTEGER(KIND=JPIM), INTENT(IN), OPTIONAL :: KTID
+INTEGER(KIND=JPIM) ITID, IPRINT_OPTION, ILEVEL
+#ifdef NECSX
+CHARACTER(LEN=*), PARAMETER :: CLNECMSG = '*** Calling NEC traceback ***'
+#endif
+
+IF (PRESENT(KTID)) THEN
+  ITID = KTID
+ELSE
+  ITID = OML_MY_THREAD()
+ENDIF
+
+IF (LHOOK) THEN
+  IPRINT_OPTION = 2
+  ILEVEL = 0
+  CALL C_DRHOOK_PRINT(0, ITID, IPRINT_OPTION, ILEVEL) ! from drhook.c
+ENDIF
+
+#ifdef VPP
+  CALL ERRTRA
+  IF (PRESENT(KTID)) CALL SLEEP(28)
+#elif RS6K
+  WRITE(0,*)'SDL_TRACEBACK: Calling XL_TRBK, THRD = ',ITID
+  CALL XL__TRBK()
+  WRITE(0,*)'SDL_TRACEBACK: Done XL_TRBK, THRD = ',ITID
+#elif __INTEL_COMPILER
+  WRITE(0,*)'SDL_TRACEBACK: Calling INTEL_TRBK, THRD = ',ITID
+  CALL INTEL_TRBK() ! See ifsaux/utilities/gentrbk.F90
+  WRITE(0,*)'SDL_TRACEBACK: Done INTEL_TRBK, THRD = ',ITID
+#elif defined(LINUX) || defined(SUN4)
+  WRITE(0,*)'SDL_TRACEBACK: Calling LINUX_TRBK, THRD = ',ITID
+  CALL LINUX_TRBK() ! See ifsaux/utilities/linuxtrbk.c
+  WRITE(0,*)'SDL_TRACEBACK: Done LINUX_TRBK, THRD = ',ITID
+#elif defined(NECSX)
+! MESPUT writes out onto unit 6
+  WRITE(6,*)'SDL_TRACEBACK: Calling NEC/MESPUT, THRD = ',ITID
+  CALL NECSX_TRBK(CLNECMSG)
+  CALL FLUSH(6)
+  WRITE(6,*)'SDL_TRACEBACK: Done NEC/MESPUT, THRD = ',ITID
+#else
+  WRITE(0,*)'SDL_TRACEBACK: No proper traceback implemented.'
+  ! A traceback using dbx-debugger, if available AND 
+  ! activated via 'export DBXDEBUGGER=1'
+  WRITE(0,*)'SDL_TRACEBACK: Calling DBX_TRBK, THRD = ',ITID
+  CALL DBX_TRBK() ! See ifsaux/utilities/linuxtrbk.c
+  WRITE(0,*)'SDL_TRACEBACK: Done DBX_TRBK, THRD = ',ITID
+  ! A traceback using gdb-debugger, if available AND 
+  ! activated via 'export GDBDEBUGGER=1'
+  WRITE(0,*)'SDL_TRACEBACK: Calling GDB_TRBK, THRD = ',ITID
+  CALL GDB_TRBK() ! See ifsaux/utilities/linuxtrbk.c
+  WRITE(0,*)'SDL_TRACEBACK: Done GDB_TRBK, THRD = ',ITID
+#endif
+
+END SUBROUTINE SDL_TRACEBACK
+!-----------------------------------------------------------------------------
+SUBROUTINE SDL_SRLABORT
+
+! Purpose :
+! -------
+!   To abort in serial environment
+
+CALL EC_RAISE(SIGABRT)
+STOP 'SDL_SRLABORT'
+
+END SUBROUTINE SDL_SRLABORT
+!-----------------------------------------------------------------------------
+SUBROUTINE SDL_DISABORT(KCOMM)
+
+! Purpose :
+! -------
+!   To abort in distributed environment
+
+!   KCOMM : communicator
+
+INTEGER(KIND=JPIM), INTENT(IN) :: KCOMM
+
+INTEGER(KIND=JPIM) :: IRETURN_CODE,IERROR
+
+#ifdef VPP
+
+CALL VPP_ABORT()
+
+#else
+
+IRETURN_CODE=1
+CALL MPI_ABORT(KCOMM,IRETURN_CODE,IERROR)
+
+#endif
+
+CALL EC_RAISE(SIGABRT) ! In case ever ends up here
+STOP 'SDL_DISABORT'
+
+END SUBROUTINE SDL_DISABORT
+!-----------------------------------------------------------------------------
+
+END MODULE SDL_MOD
diff --git a/odb/src/extras/ifsaux/module/strhandler_mod.F90 b/odb/src/extras/ifsaux/module/strhandler_mod.F90
new file mode 100644
index 0000000..3b84628
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/strhandler_mod.F90
@@ -0,0 +1,212 @@
+!OPTIONS NOOPT
+MODULE strhandler_mod
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+PRIVATE
+
+PUBLIC :: tolower, toupper, expand_string
+PUBLIC :: sadjustl, sadjustr
+PUBLIC :: stransfer
+
+INTERFACE stransfer
+MODULE PROCEDURE &
+  stransfer_r8_to_str, &
+  stransfer_str_to_r8
+END INTERFACE
+
+
+CONTAINS
+
+
+FUNCTION stransfer_r8_to_str(source, mold) result(c)
+REAL(KIND=JPRB) , intent(in) :: source
+character(len=*), intent(in) :: mold
+character(len=8) :: c
+call ecmwf_transfer(c,MIN(8,len(mold)),source,8)
+END FUNCTION stransfer_r8_to_str
+
+
+FUNCTION stransfer_str_to_r8(source, mold) result(z)
+character(len=*), intent(in) :: source
+REAL(KIND=JPRB) , intent(in) :: mold
+REAL(KIND=JPRB) :: z
+call ecmwf_transfer(z,8,source,len(source))
+END FUNCTION stransfer_str_to_r8
+
+
+FUNCTION sadjustl(s) RESULT(c)
+character(len=*), intent(in) :: s
+character(len=max(1,len(s))) c
+c = ' '
+if (len(s) > 0) then
+  if (s /= ' ') c = adjustl(s)
+endif
+END FUNCTION sadjustl
+
+
+FUNCTION sadjustr(s) RESULT(c)
+character(len=*), intent(in) :: s
+character(len=max(1,len(s))) c
+c = ' '
+if (len(s) > 0) then
+  if (s /= ' ') c = adjustr(s)
+endif
+END FUNCTION sadjustr
+
+
+SUBROUTINE tolower(cds)
+character(len=*), intent(inout) :: cds
+INTEGER(KIND=JPIM), parameter :: ich_a = ichar('a')
+INTEGER(KIND=JPIM), parameter :: ichA  = ichar('A')
+INTEGER(KIND=JPIM), parameter :: ichZ  = ichar('Z')
+INTEGER(KIND=JPIM) :: i, ich, new_ich
+character(len=1) ch
+do i=1,len(cds)
+  ch = cds(i:i)
+  ich = ichar(ch)
+  if ( ich >= ichA .and. ich <= ichZ ) then
+    new_ich = ich + (ich_a - ichA)
+    ch = char(new_ich)
+    cds(i:i) = ch
+  endif
+enddo
+END SUBROUTINE tolower
+
+
+SUBROUTINE toupper(cds)
+character(len=*), intent(inout) :: cds
+INTEGER(KIND=JPIM), parameter :: ich_A = ichar('A')
+INTEGER(KIND=JPIM), parameter :: icha  = ichar('a')
+INTEGER(KIND=JPIM), parameter :: ichz  = ichar('z')
+INTEGER(KIND=JPIM) :: i, ich, new_ich
+character(len=1) ch
+do i=1,len(cds)
+  ch = cds(i:i)
+  ich = ichar(ch)
+  if ( ich >= icha .and. ich <= ichz ) then
+    new_ich = ich + (ich_A - icha)
+    ch = char(new_ich)
+    cds(i:i) = ch
+  endif
+enddo
+END SUBROUTINE toupper
+
+
+SUBROUTINE expand_string(&
+     &myproc,               &! %p
+     &nproc,                &! %n
+     &timestep,             &! %t
+     &max_timestep,&
+     &s)                   ! %s
+
+INTEGER(KIND=JPIM), intent(in)          :: myproc, nproc
+INTEGER(KIND=JPIM), intent(in)          :: timestep, max_timestep
+character(len=*), intent(inout) :: s(:)
+character(len=2*len(s))  t
+character(len=2*len(s)) tt
+INTEGER(KIND=JPIM) :: i, j, jj, loc_p, len_t, n
+INTEGER(KIND=JPIM) :: ndigs(4), num(4)
+character(len=6) fmt(4)
+
+n = size(s)
+
+if (n < 1) return
+
+!*    Setup output formats
+num(1) = myproc
+num(2) = max(nproc,myproc)
+num(3) = n
+num(4) = max(max_timestep,timestep)
+
+!*    Count number of digits in each integer
+do j=1,4
+  ndigs(j) = 1
+  if (num(j) /= 0) then
+    ndigs(j) = 1 + log10(dble(abs(num(j))))
+    if (num(j) < 0) ndigs(j) = ndigs(j) + 1 ! Room for minus sign
+  endif
+  ndigs(j) = min(ndigs(j),9)   ! Max 9 digits supported; i.e. '999999999'
+  write(fmt(j),'("(i",i1,")")') ndigs(j)
+enddo
+
+
+!*    Expand fields '%s', '%p', '%n' and '%t' with their values
+
+
+!*    A special treatment with the sequence numbering
+if (n>1) then
+  loc_p = index(s(1),'%s')
+  if (loc_p > 0) then
+    s(2:) = s(1)
+  endif
+endif
+
+do i=1,n
+  t = adjustl(s(i))//' '
+  loc_p = index(t,'%')
+
+  if (loc_p > 0) then
+    len_t = len_trim(t)
+    j = loc_p
+    tt(:j-1) = t(:j-1)
+    tt(j:) = ' '
+    jj = j-1
+
+    do while (j <= len_t)
+      if (t(j:j) == '%') then
+        j = j + 1
+        if (j <= len_t) then
+          select case ( t(j:j) )
+          case ( 'p' )   ! myproc
+          write(tt(jj+1:jj+ndigs(1)),fmt(1)) myproc
+          jj = jj + ndigs(1)
+          case ( 'n' )   ! nproc
+          write(tt(jj+1:jj+ndigs(2)),fmt(2)) nproc
+          jj = jj + ndigs(2)
+          case ( 's' )   ! sequence number i=[1..n]
+          write(tt(jj+1:jj+ndigs(3)),fmt(3)) i
+          jj = jj + ndigs(3)
+          case ( 't' )   ! timestep
+          write(tt(jj+1:jj+ndigs(4)),fmt(4)) timestep
+          jj = jj + ndigs(4)
+          case default
+          tt(jj+1:jj+2) = '%'//t(j:j)
+          jj = jj + 2
+          end select
+        else
+          tt(jj+1:jj+1) = '%'
+          jj = jj + 1
+        endif
+      else
+        tt(jj+1:jj+1) = t(j:j)
+        jj = jj + 1
+      endif
+      j = j + 1
+    enddo
+
+    t = adjustl(tt)
+
+!*   Get also rid of any blanks in the middle of the string
+
+    len_t = len_trim(t)
+    j = 1
+    do while (j < len_t)
+      if (t(j:j) == ' ') then
+        t(j:) = t(j+1:)
+        len_t = len_trim(t)
+      else
+        j = j + 1
+      endif
+    enddo
+
+  endif
+
+  s(i) = t
+enddo
+
+END SUBROUTINE expand_string
+
+END MODULE strhandler_mod
diff --git a/odb/src/extras/ifsaux/module/yomabrt.F90 b/odb/src/extras/ifsaux/module/yomabrt.F90
new file mode 100644
index 0000000..cf966e6
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomabrt.F90
@@ -0,0 +1,10 @@
+MODULE YOMABRT
+USE PARKIND1, ONLY: JPIM
+USE OML_MOD, ONLY : OML_LOCK_KIND
+IMPLICIT NONE
+SAVE
+PUBLIC
+INTEGER(KIND=JPIM) :: MAB_CNT = 0
+INTEGER(KIND=OML_LOCK_KIND) :: MAB_LOCK(2) = (/-1,-1/)
+END MODULE YOMABRT
+
diff --git a/odb/src/extras/ifsaux/module/yomerrtrap.F90 b/odb/src/extras/ifsaux/module/yomerrtrap.F90
new file mode 100644
index 0000000..7827471
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomerrtrap.F90
@@ -0,0 +1,15 @@
+MODULE YOMERRTRAP
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+IMPLICIT NONE
+CONTAINS
+
+SUBROUTINE SET_ERR_TRAP()
+#ifdef RS6K
+INTEGER(KIND=JPIM) SIGNAL_TRAP, SIGS(1),IRES
+
+SIGS(1)  = 0
+IRES     = SIGNAL_TRAP(0, SIGS)
+#endif
+END SUBROUTINE SET_ERR_TRAP
+
+END MODULE YOMERRTRAP
diff --git a/odb/src/extras/ifsaux/module/yomgstats.F90 b/odb/src/extras/ifsaux/module/yomgstats.F90
new file mode 100644
index 0000000..5b8177f
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomgstats.F90
@@ -0,0 +1,123 @@
+MODULE YOMGSTATS
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+SAVE
+
+!     ------------------------------------------------------------------
+! Module for timing statistics. Module is internal to the GSTATS package -
+! routines GSTATS, SUSTATS and STATS_OUTPUT. The logical switches are
+! re-initialized in SUMPINI
+
+! LSTATS - TRUE for gathering timing statistics
+! LSTATSCPU - TRUE for gathering CPU timing  statistics
+! LSYNCSTATS - TRUE for syncronization (call to barrier) at the 
+!              start of timing event
+! LDETAILED_STATS - TRUE for more detail in output
+! LXML_STATS - TRUE for stats output in XML
+! LSTATS_OMP - TRUE for gathering timing statistics on OpenMP regions
+!                 1001-1999
+! LSTATS_COMMS - TRUE for gathering detailed timing of Message passing
+!                 501-1000
+! NTRACE_STATS    - max number of entries in trace
+! LTRACE_STATS    - True for trace of all calls to gstats
+! LGSTATS_LABEL   - True after GSTATS-labels have been set
+! JPMAXSTAT - max number of separate  timers in gstats
+! JPOBCOUNT_BASE - first counter for obs types
+! NCALLS - number of times a timer has been switched on
+! TIMESUM - total time spent with timer on
+! TIMESQSUM - sum of the squares of times
+! TIMEMAX - max time of all calls
+! TIMESUMB - sum of times between previous timer was invoked and this
+!            timer was switched on ( to be used for finding out which parts
+!            of the code that is not being timed)
+! TIMELCALL - time when event was switched on or resumed
+! TTCPUSUM - total cpu time
+! TVCPUSUM - total vector cpu time
+! THISTIME - total accumulated time for this call to timing event (necessary
+!            to be able to suspend and resume timer and still have it counted
+!            as one timing event)
+! THISTCPU - as THISTIME but for CPU time
+! THISVCPU - as THISTIME but for vector CPU time
+! TTCPULCALL - as TIMELCALL but for CPU time
+! TVCPULCALL - as TIMELCALL but for vector CPU time
+! TIME_LAST_CALL - last time GSTATS was called
+! TIME_START - used for recording parallel startup time
+!
+! NSWITCHVAL - for detecting overlapping counters
+
+
+LOGICAL :: LSTATS = .TRUE.
+LOGICAL :: LSTATS_OMP = .FALSE.
+LOGICAL :: LSTATS_COMMS = .FALSE.
+LOGICAL :: LSTATS_MEM = .FALSE.
+LOGICAL :: LSTATS_ALLOC = .FALSE.
+LOGICAL :: LSTATSCPU = .TRUE.
+LOGICAL :: LSYNCSTATS = .FALSE.
+LOGICAL :: LXML_STATS = .FALSE.
+LOGICAL :: LDETAILED_STATS = .TRUE.
+LOGICAL :: LBARRIER_STATS = .FALSE.
+LOGICAL :: LBARRIER_STATS2 = .FALSE.
+LOGICAL :: LTRACE_STATS = .FALSE.
+LOGICAL :: LGSTATS_LABEL = .FALSE.
+
+INTEGER(KIND=JPIM),PARAMETER :: JBMAXBASE=2500
+INTEGER(KIND=JPIM),PARAMETER :: JPMAXBARS=500
+INTEGER(KIND=JPIM),PARAMETER :: JPMAXSTAT=JBMAXBASE+JPMAXBARS
+
+INTEGER(KIND=JPIM),PARAMETER :: JPOBCOUNT_BASE=201
+INTEGER(KIND=JPIM) :: NTRACE_STATS=0
+INTEGER(KIND=JPIM) :: NCALLS(0:JPMAXSTAT)
+INTEGER(KIND=JPIM) :: NSWITCHVAL(0:JPMAXSTAT)
+INTEGER(KIND=JPIM) :: NCALLS_TOTAL=0
+INTEGER(KIND=JPIM) :: LAST_KSWITCH=0
+INTEGER(KIND=JPIM) :: LAST_KNUM=0
+INTEGER(KIND=JPIM) :: NHOOK_MESSAGES=0
+INTEGER(KIND=JPIM) :: NBAR_PTR(0:JPMAXSTAT)=0
+INTEGER(KIND=JPIM) :: NBAR2=JBMAXBASE+1
+INTEGER(KIND=JPIM),ALLOCATABLE :: NCALL_TRACE(:)
+
+REAL(KIND=JPRB) :: TIMESUM(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TIMESQSUM(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TIMEMAX(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TIMESUMB(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TIMELCALL(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TTCPUSUM(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TVCPUSUM(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: THISTIME(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: THISTCPU(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: THISVCPU(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TTCPULCALL(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TVCPULCALL(0:JPMAXSTAT)
+REAL(KIND=JPRB) :: TIME_LAST_CALL
+
+REAL(KIND=JPRB),ALLOCATABLE :: TIME_START(:)
+REAL(KIND=JPRB),ALLOCATABLE :: TIME_TRACE(:)
+INTEGER(KIND=JPIM),PARAMETER :: JPERR=0
+INTEGER(KIND=JPIM),PARAMETER :: JPTAGSTAT=20555
+
+INTEGER(KIND=JPIM),PARAMETER :: JPMAXDELAYS=1000
+INTEGER(KIND=JPIM) :: NDELAY_COUNTER(1:JPMAXDELAYS)
+REAL(KIND=JPRB)    :: TDELAY_VALUE(1:JPMAXDELAYS)
+CHARACTER*10       :: CDELAY_TIME(1:JPMAXDELAYS)
+INTEGER(KIND=JPIM) :: NDELAY_INDEX = 0
+
+CHARACTER*50 :: CCDESC(0:JPMAXSTAT) = ""
+CHARACTER*3  :: CCTYPE(0:JPMAXSTAT) = ""
+
+INTEGER(KIND=JPIM) :: NPROC_STATS = 1
+INTEGER(KIND=JPIM) :: MYPROC_STATS = 1
+INTEGER(KIND=JPIM),ALLOCATABLE :: NPRCIDS_STATS(:)
+
+INTEGER(KIND=JPIM) :: NTMEM(0:JPMAXSTAT,5)
+INTEGER(KIND=JPIM) :: NSTATS_MEM=0
+
+INTEGER(KIND=JPIM) :: NPRNT_STATS=3
+
+END MODULE YOMGSTATS
+
+
+
+
diff --git a/odb/src/extras/ifsaux/module/yomhook.F90 b/odb/src/extras/ifsaux/module/yomhook.F90
new file mode 100644
index 0000000..73665e0
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomhook.F90
@@ -0,0 +1,106 @@
+MODULE YOMHOOK
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+! Used by "hook" function
+! LHOOK = true implies "hook" function will be called
+! Altough initialized to TRUE it will be reset by first call to 
+! DR_HOOK unless we really want to use the hook function
+
+SAVE
+PUBLIC
+
+LOGICAL :: LHOOK=.TRUE.
+
+INTERFACE
+#include "dr_hook_util.h"
+#include "dr_hook_util_multi.h"
+END INTERFACE
+
+INTERFACE DR_HOOK  
+! We want compile time mapping of DR_HOOK-arguments and not
+! to test OPTIONAL-arguments with PRESENT()-function, since
+! it costs more.
+! However, this "unrolling" approach cannot be streched much more
+! than this without making number of member-functions too large
+! (i.e. all the possible permutations of these "optional" args;
+!  arguments that are not present in the DR_HOOK_DEFAULT -version)
+
+MODULE PROCEDURE &
+  DR_HOOK_DEFAULT, &
+  DR_HOOK_FILE, &
+  DR_HOOK_SIZE, &
+  DR_HOOK_FILE_SIZE, &
+  DR_HOOK_MULTI_DEFAULT, &
+  DR_HOOK_MULTI_FILE, &
+  DR_HOOK_MULTI_SIZE, &
+  DR_HOOK_MULTI_FILE_SIZE
+END INTERFACE
+
+CONTAINS 
+
+SUBROUTINE DR_HOOK_DEFAULT(CDNAME,KSWITCH,PKEY)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY
+CALL DR_HOOK_UTIL(CDNAME,KSWITCH,PKEY,'',0)
+END SUBROUTINE DR_HOOK_DEFAULT
+
+SUBROUTINE DR_HOOK_MULTI_DEFAULT(CDNAME,KSWITCH,PKEY)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY(:)
+CALL DR_HOOK_UTIL_MULTI(CDNAME,KSWITCH,PKEY,SIZE(PKEY),'',0)
+END SUBROUTINE DR_HOOK_MULTI_DEFAULT
+
+
+
+SUBROUTINE DR_HOOK_FILE(CDNAME,KSWITCH,PKEY,CDFILE)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY
+CALL DR_HOOK_UTIL(CDNAME,KSWITCH,PKEY,CDFILE,0)
+END SUBROUTINE DR_HOOK_FILE
+
+SUBROUTINE DR_HOOK_MULTI_FILE(CDNAME,KSWITCH,PKEY,CDFILE)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY(:)
+CALL DR_HOOK_UTIL_MULTI(CDNAME,KSWITCH,PKEY,SIZE(PKEY),CDFILE,0)
+END SUBROUTINE DR_HOOK_MULTI_FILE
+
+
+
+SUBROUTINE DR_HOOK_SIZE(CDNAME,KSWITCH,PKEY,KSIZEINFO)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY
+CALL DR_HOOK_UTIL(CDNAME,KSWITCH,PKEY,'',KSIZEINFO)
+END SUBROUTINE DR_HOOK_SIZE
+
+SUBROUTINE DR_HOOK_MULTI_SIZE(CDNAME,KSWITCH,PKEY,KSIZEINFO)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY(:)
+CALL DR_HOOK_UTIL_MULTI(CDNAME,KSWITCH,PKEY,SIZE(PKEY),'',KSIZEINFO)
+END SUBROUTINE DR_HOOK_MULTI_SIZE
+
+
+
+SUBROUTINE DR_HOOK_FILE_SIZE(CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY
+CALL DR_HOOK_UTIL(CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
+END SUBROUTINE DR_HOOK_FILE_SIZE
+
+SUBROUTINE DR_HOOK_MULTI_FILE_SIZE(CDNAME,KSWITCH,PKEY,CDFILE,KSIZEINFO)
+CHARACTER(LEN=*), INTENT(IN) :: CDNAME,CDFILE
+INTEGER(KIND=JPIM),        INTENT(IN) :: KSWITCH,KSIZEINFO
+REAL(KIND=JPRB),        INTENT(INOUT) :: PKEY(:)
+CALL DR_HOOK_UTIL_MULTI(CDNAME,KSWITCH,PKEY,SIZE(PKEY),CDFILE,KSIZEINFO)
+END SUBROUTINE DR_HOOK_MULTI_FILE_SIZE
+
+END MODULE YOMHOOK
diff --git a/odb/src/extras/ifsaux/module/yomhookstack.F90 b/odb/src/extras/ifsaux/module/yomhookstack.F90
new file mode 100644
index 0000000..64d391f
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomhookstack.F90
@@ -0,0 +1,18 @@
+MODULE YOMHOOKSTACK
+
+! Used by dr_hook_util to monitor thread stack usage 
+! Need "export STACKCHECK=yes"
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB,      JPIB
+
+IMPLICIT NONE
+
+SAVE
+
+INTEGER(KIND=JPIB), ALLOCATABLE :: isave(:) 
+INTEGER(KIND=JPIB), ALLOCATABLE :: imaxstack(:) 
+LOGICAL,   ALLOCATABLE :: ll_thread_first(:)
+CHARACTER(LEN=3)       :: cstack
+
+END MODULE YOMHOOKSTACK
+
diff --git a/odb/src/extras/ifsaux/module/yomlun_ifsaux.F90 b/odb/src/extras/ifsaux/module/yomlun_ifsaux.F90
new file mode 100644
index 0000000..79ce50f
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yomlun_ifsaux.F90
@@ -0,0 +1,20 @@
+MODULE YOMLUN_IFSAUX
+
+USE PARKIND1  ,ONLY : JPIM
+
+IMPLICIT NONE
+
+SAVE
+
+!     ------------------------------------------------------------------
+
+!*    Logical units used by code
+
+!     NULOUT :   output unit
+!     NULERR :   unit number for comparison with reference run
+
+INTEGER(KIND=JPIM) :: NULOUT = 6
+INTEGER(KIND=JPIM) :: NULERR = 0
+
+!     ------------------------------------------------------------------
+END MODULE YOMLUN_IFSAUX
diff --git a/odb/src/extras/ifsaux/module/yommpi.F90 b/odb/src/extras/ifsaux/module/yommpi.F90
new file mode 100644
index 0000000..c574eae
--- /dev/null
+++ b/odb/src/extras/ifsaux/module/yommpi.F90
@@ -0,0 +1,19 @@
+MODULE YOMMPI
+
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+SAVE
+
+!     ------------------------------------------------------------------
+!*    Contains identifiers used by MPI (Message Passing Interface)
+
+
+INTEGER(KIND=JPIM), PARAMETER :: MINTET = 1
+INTEGER(KIND=JPIM), PARAMETER :: MREALT = 2
+INTEGER(KIND=JPIM), PARAMETER :: MLOGIT = 3
+INTEGER(KIND=JPIM), PARAMETER :: MCHART = 4
+
+END MODULE YOMMPI
diff --git a/odb/src/extras/ifsaux/parallel/cmpl_binding.F90 b/odb/src/extras/ifsaux/parallel/cmpl_binding.F90
new file mode 100644
index 0000000..6c1d1ab
--- /dev/null
+++ b/odb/src/extras/ifsaux/parallel/cmpl_binding.F90
@@ -0,0 +1,129 @@
+subroutine cmpl_recv(kbuf,kcount,ktype,ksource,ktag,kcomm,&
+ &ksync,kblock,krcount,krfrom,krtag,kerror)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE MPL_MODULE
+implicit none
+integer kcount,ktype,ksource,ktag,kcomm
+integer krcount,krfrom,krtag,kerror,ksync,kblock
+INTEGER(KIND=JPIM) :: kbuf(*)
+INTEGER,EXTERNAL :: convin,convout
+integer ilenb,ilen
+ilenb=convin(kcount,ktype)
+if(ksource > 0) then
+  if(ktag /= -1) then
+    call mpl_recv(kbuf(1:ilenb),KSOURCE=ksource,KTAG=ktag,&
+     KFROM=krfrom,KRECVTAG=krtag,KOUNT=ilen,KERROR=kerror)
+  else
+    call mpl_recv(kbuf(1:ilenb),KSOURCE=ksource,&
+     KFROM=krfrom,KRECVTAG=krtag,KOUNT=ilen,KERROR=kerror)
+  endif
+else
+  if(ktag /= -1) then
+    call mpl_recv(kbuf(1:ilenb),KTAG=ktag,&
+     KFROM=krfrom,KRECVTAG=krtag,KOUNT=ilen,KERROR=kerror)
+  else
+    call mpl_recv(kbuf(1:ilenb),&
+     KFROM=krfrom,KRECVTAG=krtag,KOUNT=ilen,KERROR=kerror)
+  endif
+endif
+krcount=convout(ilen,ktype)
+end subroutine cmpl_recv
+
+subroutine cmpl_send(kbuf,kcount,ktype,kdest,ktag,kcomm,&
+ &ksync,kblock,kerror)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE MPL_MODULE
+implicit none
+integer kcount,ktype,ktag,kcomm,ksync,kblock,kdest
+integer kerror
+integer kbuf(*)
+INTEGER,EXTERNAL :: convin,convout
+integer ilen
+ilen=convin(kcount,ktype)
+call mpl_send(kbuf(1:ilen),KDEST=kdest,KTAG=ktag,KERROR=kerror)
+end subroutine cmpl_send
+
+subroutine cmpl_broadcast(kbuf,kcount,ktype,kroot,ktag,kcomm,&
+ &ksync,kblock,kerror)
+USE MPL_MODULE
+implicit none
+integer kcount,ktype,ktag,kcomm,ksync,kblock,kroot
+integer kerror
+integer kbuf(*)
+INTEGER,EXTERNAL :: convin,convout
+integer ilen
+ilen=convin(kcount,ktype)
+call mpl_broadcast(kbuf(1:ilen),KROOT=kroot,KTAG=ktag,KERROR=kerror)
+end subroutine cmpl_broadcast
+
+subroutine cmpl_abort(cdmess)
+USE MPL_MODULE
+implicit none
+character(len=*) cdmess
+call mpl_abort(cdmess)
+end subroutine cmpl_abort
+
+subroutine cmpl_init(ldtrmsg,kerror)
+USE MPL_MODULE
+implicit none
+logical ldtrmsg
+integer kerror
+call mpl_init(KERROR=kerror,LDINFO=.FALSE.)
+end subroutine cmpl_init
+
+function cmpl_nproc()
+USE MPL_MODULE
+implicit none
+integer cmpl_nproc
+cmpl_nproc=mpl_nproc()
+end function cmpl_nproc
+
+function cmpl_myrank()
+USE MPL_MODULE
+implicit none
+integer cmpl_myrank
+cmpl_myrank=mpl_myrank()
+end function cmpl_myrank
+
+subroutine cmpl_barrier(kerror)
+USE MPL_MODULE
+implicit none
+integer kerror
+call mpl_barrier(KERROR=kerror)
+end subroutine cmpl_barrier
+
+subroutine cmpl_end(kerror)
+USE MPL_MODULE
+implicit none
+integer kerror
+call mpl_end(KERROR=kerror)
+end subroutine cmpl_end
+
+subroutine cmpl_getarg(kargno, cdarg)
+USE MPL_MODULE
+implicit none
+integer kargno
+character(len=*) cdarg
+CALL mpl_getarg(kargno, cdarg)
+end subroutine cmpl_getarg
+
+function cmpl_iargc()
+USE MPL_MODULE
+implicit none
+integer cmpl_iargc
+cmpl_iargc = mpl_iargc()
+end function cmpl_iargc
+
+function mpe_myrank()
+USE MPL_MODULE
+implicit none
+integer mpe_myrank
+mpe_myrank=mpl_myrank()
+end function mpe_myrank
+
+subroutine mpei_abort(cdmess)
+USE MPL_MODULE
+implicit none
+character(len=*) cdmess
+call mpl_abort()
+end subroutine mpei_abort
diff --git a/odb/src/extras/ifsaux/parallel/coml_binding.F90 b/odb/src/extras/ifsaux/parallel/coml_binding.F90
new file mode 100644
index 0000000..37b4bff
--- /dev/null
+++ b/odb/src/extras/ifsaux/parallel/coml_binding.F90
@@ -0,0 +1,111 @@
+subroutine coml_set_debug(konoff, kret)
+USE OML_MOD, ONLY : OML_DEBUG
+USE PARKIND1, ONLY : JPIM
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: konoff
+INTEGER(KIND=JPIM), intent(out) :: kret
+kret = 0
+if (OML_DEBUG) kret = 1
+if (konoff == 0) then 
+  OML_DEBUG = .FALSE.
+else
+  OML_DEBUG = .TRUE.
+endif
+end subroutine coml_set_debug
+
+subroutine coml_init_lockid_with_name(kmylock,cdlockname)
+USE OML_MOD, ONLY : OML_INIT_LOCK, OML_LOCK_KIND, OML_DEBUG
+USE PARKIND1, ONLY : JPIB
+implicit none
+INTEGER(KIND=OML_LOCK_KIND), intent(inout) :: kmylock
+CHARACTER(LEN=*), intent(in) :: cdlockname
+INTEGER(KIND=JPIB), external :: loc_addr
+CALL OML_INIT_LOCK(kmylock)
+IF (OML_DEBUG) write(0,'(1x,a,2i20)') &
+     & 'coml_init_lockid_with_name "'//cdlockname//'" :',kmylock,loc_addr(kmylock)
+end subroutine coml_init_lockid_with_name
+
+subroutine coml_init_lockid(kmylock)
+USE OML_MOD, ONLY : OML_INIT_LOCK, OML_LOCK_KIND, OML_DEBUG
+USE PARKIND1, ONLY : JPIB
+implicit none
+INTEGER(KIND=OML_LOCK_KIND), intent(inout) :: kmylock
+INTEGER(KIND=JPIB), external :: loc_addr
+CALL OML_INIT_LOCK(kmylock)
+IF (OML_DEBUG) write(0,'(1x,2i20)') &
+     & 'coml_init_lockid :',kmylock,loc_addr(kmylock)
+end subroutine coml_init_lockid
+
+subroutine coml_init_lock()
+USE OML_MOD, ONLY : OML_INIT_LOCK
+implicit none
+CALL OML_INIT_LOCK()
+end subroutine coml_init_lock
+
+subroutine coml_test_lockid(kisset,kmylock)
+USE PARKIND1, ONLY : JPIM
+USE OML_MOD, ONLY : OML_TEST_LOCK, OML_LOCK_KIND
+implicit none
+INTEGER(KIND=JPIM), intent(out) :: kisset
+INTEGER(KIND=OML_LOCK_KIND), intent(inout) :: kmylock
+kisset = 1
+IF (.not.OML_TEST_LOCK(kmylock)) kisset = 0
+end subroutine coml_test_lockid
+
+subroutine coml_test_lock(kisset)
+USE PARKIND1, ONLY : JPIM
+USE OML_MOD, ONLY : OML_TEST_LOCK
+implicit none
+INTEGER(KIND=JPIM), intent(out) :: kisset
+kisset = 1
+IF (.not.OML_TEST_LOCK()) kisset = 0
+end subroutine coml_test_lock
+
+subroutine coml_set_lockid(kmylock)
+USE OML_MOD, ONLY : OML_SET_LOCK, OML_LOCK_KIND, OML_MY_THREAD, OML_DEBUG
+USE PARKIND1, ONLY : JPIB, JPRB
+implicit none
+INTEGER(KIND=OML_LOCK_KIND), intent(inout) :: kmylock
+INTEGER(KIND=JPIB), external :: loc_addr
+REAL(KIND=JPRB), external :: util_walltime
+IF (OML_DEBUG) write(0,'(1x,f20.6,1x,i3,a,2i20)') &
+     & util_walltime(),OML_MY_THREAD(),': coml_SET_lockid >>',kmylock,loc_addr(kmylock)
+CALL OML_SET_LOCK(kmylock)
+IF (OML_DEBUG) write(0,'(1x,f20.6,1x,i3,a,2i20)') &
+     & util_walltime(),OML_MY_THREAD(),': coml_SET_lockid <<',kmylock,loc_addr(kmylock)
+end subroutine coml_set_lockid
+
+subroutine coml_set_lock()
+USE OML_MOD, ONLY : OML_SET_LOCK
+implicit none
+CALL OML_SET_LOCK()
+end subroutine coml_set_lock
+
+subroutine coml_unset_lockid(kmylock)
+USE OML_MOD, ONLY : OML_UNSET_LOCK, OML_LOCK_KIND, OML_MY_THREAD, OML_DEBUG
+USE PARKIND1, ONLY : JPIB, JPRB
+implicit none
+INTEGER(KIND=OML_LOCK_KIND), intent(inout) :: kmylock
+INTEGER(KIND=JPIB), external :: loc_addr
+REAL(KIND=JPRB), external :: util_walltime
+IF (OML_DEBUG) write(0,'(1x,f20.6,1x,i3,a,2i20)') &
+     & util_walltime(),OML_MY_THREAD(),': coml_UNSET_lockid >>',kmylock,loc_addr(kmylock)
+CALL OML_UNSET_LOCK(kmylock)
+IF (OML_DEBUG) write(0,'(1x,f20.6,1x,i3,a,2i20)') &
+     & util_walltime(),OML_MY_THREAD(),': coml_UNSET_lockid <<',kmylock,loc_addr(kmylock)
+end subroutine coml_unset_lockid
+
+subroutine coml_unset_lock()
+USE OML_MOD, ONLY : OML_UNSET_LOCK
+implicit none
+CALL OML_UNSET_LOCK()
+end subroutine coml_unset_lock
+
+subroutine coml_in_parallel(kispar_region)
+USE PARKIND1, ONLY : JPIM
+USE OML_MOD, ONLY : OML_IN_PARALLEL
+implicit none
+INTEGER(KIND=JPIM), intent(out) :: kispar_region
+kispar_region = 0
+if (OML_IN_PARALLEL()) kispar_region = 1
+end subroutine coml_in_parallel
diff --git a/odb/src/extras/ifsaux/support/abor1.F90 b/odb/src/extras/ifsaux/support/abor1.F90
new file mode 100644
index 0000000..e7bf285
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/abor1.F90
@@ -0,0 +1,55 @@
+SUBROUTINE ABOR1(CDTEXT)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMLUN_IFSAUX, ONLY : NULOUT,NULERR
+USE MPL_MODULE, ONLY : MPL_ABORT, MPL_RANK, MPL_NUMPROC
+USE SDL_MOD, ONLY : SDL_TRACEBACK, SDL_SRLABORT
+
+IMPLICIT NONE
+
+CHARACTER(LEN=*), INTENT(IN) :: CDTEXT
+INTEGER(KIND=JPIM) :: ILEN
+
+ILEN=LEN(CDTEXT)
+IF (NULOUT >= 0) WRITE(NULOUT,'(1X,A)') 'ABOR1 CALLED'
+
+IF(ILEN <= 512) THEN
+  IF (NULOUT >= 0) WRITE(NULOUT,'(1X,A)') CDTEXT
+  IF (NULERR >= 0) WRITE(NULERR,'(1X,A,1X,I3,1X,A)') 'ABORT! ',MPL_RANK,CDTEXT
+ELSE
+  IF (NULERR >= 0) WRITE(NULERR,'(1X,A,1X,I3,1X,A)') 'ABORT! ',MPL_RANK,&
+   & 'ABOR1 CALLED WITHOUT TEXT STRING'  
+ENDIF
+
+IF (NULOUT >= 0) THEN
+  CALL FLUSH(NULOUT)
+  IF (NULOUT /= 0 .and. NULOUT /= 6) CLOSE(NULOUT)
+ENDIF
+
+IF (MPL_NUMPROC > 1) THEN
+  IF(ILEN <= 512) THEN
+    CALL MPL_ABORT(CDTEXT)
+  ELSE
+    CALL MPL_ABORT
+  ENDIF
+ELSE
+  CALL SDL_TRACEBACK
+  CALL FLUSH(0)
+  CALL SDL_SRLABORT
+ENDIF
+
+END SUBROUTINE ABOR1
+
+SUBROUTINE ABOR1FL(CDFILE, KLINENUM, CDTEXT)
+USE PARKIND1  ,ONLY : JPIM
+USE YOMLUN_IFSAUX, ONLY : NULOUT,NULERR
+IMPLICIT NONE
+CHARACTER(LEN=*), INTENT(IN) :: CDFILE,CDTEXT
+INTEGER(KIND=JPIM), INTENT(IN) :: KLINENUM
+IF (LEN(CDFILE) > 0 .AND. KLINENUM > 0 .AND. NULERR >= 0) THEN
+ 1000 FORMAT(1X,A,A,":",I6.6)
+  WRITE(NULERR,1000) 'ABOR1FL HAS BEEN CALLED AT ',CDFILE,KLINENUM
+  CALL FLUSH(NULERR)
+ENDIF
+CALL ABOR1(CDTEXT)
+END SUBROUTINE ABOR1FL
diff --git a/odb/src/extras/ifsaux/support/cargs.c b/odb/src/extras/ifsaux/support/cargs.c
new file mode 100644
index 0000000..7bf584c
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/cargs.c
@@ -0,0 +1,256 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "cargs.h"
+
+typedef struct {
+  char *name;
+  int len;
+} arg_t;
+
+static arg_t *args = NULL;
+static int numargs = -1;
+static char *cl_terminate = NULL;
+static char *a_out = NULL;
+
+#if !defined(PSCMD)
+#define PSCMD "/bin/ps"
+#endif /* !defined(PSCMD) */
+
+#if !defined(TAILCMD)
+#define TAILCMD "/usr/bin/tail"
+#endif /* !defined(TAILCMD) */
+
+static const char *get_a_out()
+{
+  /* progname is a blank string;
+     this is most likely due to a Fortran-call to getarg
+     from program that has a C-main program, thus Fortran getarg
+     may return a blank string */
+  
+  /* Using an alternative method of getting a.out :
+     
+  ps -p<pid> | tail -1 | awk '{print $NF}' 
+
+  This can give false positives, as we search the path for the binary: we may have
+  executed ./MASTER rather than the first MASTER in the path.
+
+  Naturally this cannot be the nicest method around ;-(
+  So, a competition is launched: make this better and 
+  you may win a week in Bahamas!!
+
+  */
+
+#if defined(LINUX)
+   /* On Linux, the following is more reliable, if /proc is available. 
+    */
+  if (!a_out) {
+     int len;
+     char symlink[NAME_MAX], real_exe[NAME_MAX];
+     snprintf(symlink, NAME_MAX, "/proc/%d/exe", getpid());
+     if ((len = readlink(symlink, real_exe, NAME_MAX)) > 0)  {
+	a_out = malloc((len+1)*sizeof(*a_out));
+        strncpy(a_out, real_exe, len);
+	a_out[len] = '\0';
+     }
+  }
+#endif
+  if (!a_out && (access(PSCMD,X_OK) == 0)) {
+    char cmd[sizeof(PSCMD) + sizeof(TAILCMD) + 100];
+    FILE *fp = NULL;
+    pid_t pid = getpid();
+    sprintf(cmd,"%s -p%d | %s -1 | awk '{print $NF}'", PSCMD, (int)pid, TAILCMD);
+    fp = popen(cmd, "r");
+    if (fp) {
+      char c[65536];
+      if (fscanf(fp,"%s",c) == 1) {
+	if (!strchr(c,'/')) { 
+	  /* The file path was NOT embedded in the name 
+	     ==> Must search from $PATH f.ex. /bin:/usr/bin:/some/thing/else:/etc/bin */
+	  char *path = getenv("PATH");
+	  if (path) {
+	    int lenc = strlen(c);
+	    char *saved = strdup(path);
+	    char *start = saved;
+	    char *token = strtok(saved,":");
+	    do {
+	      int lenf = strlen(start) + 1 + lenc + 1;
+	      char *fullpath = malloc(lenf * sizeof(*fullpath));
+	      snprintf(fullpath,lenf,"%s/%s",start,c);
+	      if (access(fullpath,X_OK) == 0) { /* It's this one!! */
+		a_out = fullpath;
+		break; /* do { ... } while (token) */
+	      }
+	      free(fullpath);
+	      start = token;
+	      token = strtok(NULL,":");
+	    } while (token);
+	    free(saved);
+	  }
+	} /* if (!strchr(c,'/')) */
+	if (!a_out) a_out = strdup(c);
+      }
+      pclose(fp);
+    }
+  }
+  if (!a_out) a_out = strdup("/unknown/executable");
+  return a_out;
+}
+
+  
+void ec_PutArgs(int argc, char *argv[])
+{
+  if (numargs == -1 && !args) {
+    if (argc > 0) {
+      int j;
+      args = calloc(argc, sizeof(arg_t));
+      /* cl_terminate: see ifsaux/module/mpl_arg_mod.F90 */
+      if (!cl_terminate) {
+	char *env = getenv("MPL_CL_TERMINATE");
+	cl_terminate = env ? strdup(env) : strdup("-^");
+      }
+      numargs = 0;
+      for (j=0; j<argc; j++) {
+	if (!argv[j] || strcmp(argv[j],cl_terminate) == 0) break;
+	args[j].name = strdup(argv[j]);
+	args[j].len = strlen(argv[j]);
+	numargs++;
+      }
+      if (numargs == 0) {
+	const char *arg0 = get_a_out();
+	args[0].name = strdup(arg0);
+	args[0].len = strlen(arg0);
+      }
+      else {
+	if (a_out) free(a_out);
+	a_out = strdup(args[0].name);
+	numargs--; /* Fortran # of args == C # of args - 1 */
+      }
+    } /* if (argc > 0) */
+  } /* if (numargs == -1 && !args) */
+}
+
+
+const char *ec_GetArgs(int argno)
+{
+  const char *arg = NULL;
+  if (argno == 0 && !args) {
+    arg = get_a_out();
+  }
+  else if (argno >= 0 && argno <= numargs && args) {
+    arg = args[argno].name;
+  }
+  return arg;
+}
+
+
+int ec_NumArgs(void) { return numargs; }
+
+int ec_argc(void) { return 1 + ec_NumArgs(); }
+
+char **ec_argv(void)
+{
+  int j, argc = ec_argc();
+  char **argv = NULL;
+  argv = calloc((argc + 1), sizeof(*argv));
+  for (j=0; j<argc; j++) {
+    argv[j] = (char *)ec_GetArgs(j);
+  }
+  argv[argc] = NULL;
+  return argv;
+}
+
+
+/* Fortran interface */
+
+int iargc_c_(void) { return numargs; }
+int iargc_c (void) { return numargs; }
+
+
+void getarg_c_(const int *argno, char *arg
+	       /* Hidden argument */
+	       , const int arg_len)
+{
+  int Argno = argno ? *argno : -1;
+  if (arg && arg_len > 0 && 
+      Argno >= 0 && Argno <= numargs && args && args[Argno].name) {
+    const char *s = args[Argno].name;
+    int len = args[Argno].len;
+    if (arg_len < len) len = arg_len;
+    strncpy(arg,s,len);
+    if (arg_len > len) memset(&arg[len],' ',arg_len-len);
+  }
+}
+
+
+void getarg_c (const int *argno, char *arg
+	       /* Hidden argument */
+	       , const int arg_len)
+{
+  getarg_c_(argno, arg, arg_len);
+}
+
+
+void putarg_c_(const int *argno, const char *arg
+	       /* Hidden argument */
+	       , int arg_len)
+{
+  int Argno = argno ? *argno : -1;
+  if (arg && arg_len >= 0 && 
+      Argno >= 0 && Argno <= numargs && args) {
+    char *s = calloc(arg_len+1,sizeof(*s));
+    strncpy(s,arg,arg_len);
+    s[arg_len] = '\0';
+    if (args[Argno].name) free(args[Argno].name);
+    args[Argno].name = s;
+    args[Argno].len = arg_len;
+  }
+}
+
+
+void putarg_c (const int *argno, const char *arg
+	       /* Hidden argument */
+	       , int arg_len)
+{
+  putarg_c_(argno, arg, arg_len);
+}
+
+
+void putarg_info_(const int *argc, const char *cterm
+		  /* Hidden argument */
+		  , int cterm_len)
+{
+  int Argc = argc ? *argc : 0;
+  if (cterm && cterm_len >= 0) {
+    if (cl_terminate) free(cl_terminate);
+    cl_terminate = calloc(cterm_len+1,sizeof(*cl_terminate));
+    strncpy(cl_terminate,cterm,cterm_len);
+    cl_terminate[cterm_len] = '\0';
+  }
+  if (numargs >= 0 || args) {
+    if (args) {
+      int j;
+      for (j=0; j<=numargs; j++) { /* note:  "j<=", not "j<" */
+	if (args[j].name) free(args[j].name);
+      }
+      free(args);
+      args = NULL;
+    } /* if (args) */
+    numargs = -1;
+  }
+  /* Re-initialize args & numargs */
+  if (Argc < 0) Argc = 0;
+  numargs = Argc;
+  args = calloc(1 + numargs, sizeof(arg_t));
+}
+
+void putarg_info (const int *argc, const char *cterm
+		  /* Hidden argument */
+		  , int cterm_len)
+{
+  putarg_info_(argc, cterm, cterm_len);
+}
diff --git a/odb/src/extras/ifsaux/support/cdrhookinit.F90 b/odb/src/extras/ifsaux/support/cdrhookinit.F90
new file mode 100644
index 0000000..f6e6589
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/cdrhookinit.F90
@@ -0,0 +1,15 @@
+SUBROUTINE CDRHOOKINIT(KRET)
+!-- Makes sure Dr.Hook gets properly initialized from C-main program, too
+USE PARKIND1  ,ONLY  : JPIM, JPRB
+USE YOMHOOK   ,ONLY  : LHOOK, DR_HOOK
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(OUT) :: KRET
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('CDRHOOKINIT',0,ZHOOK_HANDLE)
+IF (LHOOK) THEN
+  KRET = 1 ! Dr.Hook is ON
+ELSE
+  KRET = 0 ! Dr.Hook is OFF
+ENDIF
+IF (LHOOK) CALL DR_HOOK('CDRHOOKINIT',1,ZHOOK_HANDLE)
+END SUBROUTINE CDRHOOKINIT
diff --git a/odb/src/extras/ifsaux/support/clock.F b/odb/src/extras/ifsaux/support/clock.F
new file mode 100644
index 0000000..0187f11
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/clock.F
@@ -0,0 +1,26 @@
+      INTEGER FUNCTION CLOCK()
+C
+C     clock() returns the amount of CPU time (in microseconds) used since
+C     the first call to clock().  The time reported is the sum of the user
+C     and system times of the calling process and its terminated child
+C     processes for which it has executed wait() or system() (see wait(2)
+C     and system(3S)).  To determine the time in seconds, the value returned
+C     by clock() should be divided by the value of the macro CLOCKS_PER_SEC.
+C
+C     INTRODUCE A PROPER CLCOK ROUTINE HERE
+C
+      IMPLICIT LOGICAL (L)
+C
+      call system_clock(ic,icr,icm)
+      if(icm.eq.0) then
+        print *,' no system clock'
+        clock=-99.
+      else
+#ifdef VPP
+        clock=ic
+#else
+        clock=1000.*ic/icr
+#endif
+      endif
+      RETURN
+      END
diff --git a/odb/src/extras/ifsaux/support/convin.F90 b/odb/src/extras/ifsaux/support/convin.F90
new file mode 100644
index 0000000..d8f75af
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/convin.F90
@@ -0,0 +1,7 @@
+integer function convin(kcount,ktype)
+real zconv(0:5)
+integer kcount,ktype
+zconv=(/0.25,1.0,2.0,2.0,1.0,1.0/)
+convin=ceiling(kcount*zconv(ktype))
+return
+end function convin
diff --git a/odb/src/extras/ifsaux/support/convout.F90 b/odb/src/extras/ifsaux/support/convout.F90
new file mode 100644
index 0000000..6e63d1a
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/convout.F90
@@ -0,0 +1,7 @@
+integer function convout(kcount,ktype)
+real zconv(0:5)
+integer kcount,ktype
+zconv=(/0.25,1.0,2.0,2.0,1.0,1.0/)
+convout=ceiling(kcount/zconv(ktype))
+return
+end function convout
diff --git a/odb/src/extras/ifsaux/support/cptime.F b/odb/src/extras/ifsaux/support/cptime.F
new file mode 100644
index 0000000..8bf88ef
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/cptime.F
@@ -0,0 +1,40 @@
+#if defined (VPP)
+      SUBROUTINE CPTIME(PVCP,PTCP)
+C     Fujitsu function
+      call clockv(PVCP,PTCP,0,2)
+      return
+      END
+#elif defined (RS6K)
+      SUBROUTINE CPTIME(PVCP,PTCP)
+      data ifirst/0/
+      save ifirst,zfirst
+      if(ifirst.eq.0) then
+         ifirst=1
+         zfirst=second()
+         pvcp=0.0
+         ptcp=pvcp
+      else
+         ZSEC=SECOND()
+         PVCP=ZSEC-ZFIRST
+         PTCP=PVCP
+      endif
+      return
+      END
+#else
+      SUBROUTINE CPTIME(PVCP,PTCP)
+      data ifirst/0/
+      save ifirst,zfirst
+c     Usage of Fortran90 intrinsic function for CPU timing.
+      if(ifirst.eq.0) then
+         ifirst=1
+         call cpu_time(zfirst)
+         pvcp=0.0
+         ptcp=pvcp
+      else
+         call cpu_time(ZSEC)
+         PVCP=ZSEC-ZFIRST
+         PTCP=PVCP
+      endif
+      return
+      END
+#endif
diff --git a/odb/src/extras/ifsaux/support/crc.c b/odb/src/extras/ifsaux/support/crc.c
new file mode 100644
index 0000000..3efa5f7
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/crc.c
@@ -0,0 +1,171 @@
+/* crc.c : in fact equivalent to Unix cksum (when crc32) */
+/* Calculates 32-bit  Cyclic Redundancy Check as in Unix cksum command */
+/* Also calculates 64-bit  Cyclic Redundancy Check */
+
+/* Sami Saarinen, 17-Feb-2005 : crc32       */
+/*                24-Jun-2005 : Added crc64 */
+/*                29-Dec-2005 : Removed static in front of C-callable cksum32() */
+/*                29-Dec-2005 : Length argument for crc64 now 64-bit int */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "crc.h"
+
+static const unsigned int crctab[256] =
+{
+  0x0,
+  0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
+  0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
+  0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
+  0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
+  0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
+  0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
+  0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
+  0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
+  0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
+  0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
+  0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
+  0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
+  0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
+  0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
+  0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
+  0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
+  0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
+  0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
+  0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
+  0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
+  0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
+  0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
+  0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
+  0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
+  0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
+  0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
+  0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
+  0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
+  0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
+  0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
+  0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
+  0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
+  0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
+  0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
+  0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
+  0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
+  0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
+  0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
+  0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
+  0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
+  0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
+  0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
+  0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
+  0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
+  0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
+  0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
+  0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
+  0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
+  0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
+  0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
+  0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
+};
+
+unsigned int 
+cksum32(const char *buf, int nbuf, unsigned int nCRC)
+{
+  while (nbuf--) {
+    nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ *(buf++)) & 0xFF];
+  }
+  return nCRC;
+}
+
+unsigned long long int
+cksum64(const char *buf, long long int nbuf, unsigned long long int nCRC)
+{
+  unsigned char c;
+  while (nbuf--) {
+    c = ((unsigned char)nCRC ^ *(buf++)) & 0xFF;
+    nCRC >>= 8;
+    nCRC ^= (unsigned long long int)crctab[c] << 32;
+  }
+  return nCRC;
+}
+
+unsigned int 
+pp_cksum32(int nbuf, unsigned int nCRC)
+{
+    while (nbuf > 0) {
+	nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ nbuf) & 0xFF];
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFF;
+    return nCRC;
+}
+
+unsigned int 
+pp_cksum32but64len(long long int nbuf, unsigned int nCRC)
+{
+    while (nbuf > 0) {
+	nCRC = (nCRC << 8) ^ crctab[((nCRC >> 24) ^ nbuf) & 0xFF];
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFF;
+    return nCRC;
+}
+
+unsigned long long int 
+pp_cksum64(long long int nbuf, unsigned long long int nCRC)
+{
+    while (nbuf > 0) {
+	unsigned char c = ((unsigned char)nCRC ^ nbuf) & 0xFF;
+	nCRC >>= 8;
+	nCRC ^= (unsigned long long int)crctab[c] << 32;
+	nbuf >>= 8;
+    }
+    nCRC = ~nCRC & 0xFFFFFFFFFFFFFFFFull;
+    return nCRC;
+}
+
+/* Fortran callable */
+
+void 
+crc32_(const void *vbuf, const int *pnbuf, 
+       unsigned int *pnCRC /* Note: An in & out -variable */)
+{
+  if (vbuf && pnbuf && *pnbuf > 0 && pnCRC) {
+    const char *buf = vbuf;
+    unsigned int nCRC = *pnCRC;
+    int nbuf = *pnbuf;
+    /* checksum the data */
+    nCRC = cksum32(buf, nbuf, nCRC);
+    /* checksum the length */
+    *pnCRC = pp_cksum32(nbuf, nCRC);
+  }
+}
+
+void 
+crc64_(const void *vbuf, const long long int *pnbuf, 
+       unsigned long long int *pnCRC /* Note: An in & out -variable */)
+{
+  if (vbuf && pnbuf && *pnbuf > 0 && pnCRC) {
+    const char *buf = vbuf;
+    unsigned long long int nCRC = *pnCRC;
+    long long int nbuf = *pnbuf;
+    /* checksum the data */
+    nCRC = cksum64(buf, nbuf, nCRC);
+    /* checksum the length */
+    *pnCRC = pp_cksum64(nbuf, nCRC);
+  }
+}
+
+/* Not related to crc at all ;-( */
+/* Used in module strhandler (stransfer) */
+
+void
+ecmwf_transfer_(void *out, const int *Len_out,
+		const void *in, const int *Len_in
+		/* Possible hidden argument (not referred) */
+		, int Sta_lin)
+{
+  size_t len = *Len_out;
+  if (*Len_in < len) len = *Len_in;
+  if (len > 0) memcpy(out,in,len);
+}
diff --git a/odb/src/extras/ifsaux/support/dr_hook_procinfo.F90 b/odb/src/extras/ifsaux/support/dr_hook_procinfo.F90
new file mode 100644
index 0000000..147b3bd
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/dr_hook_procinfo.F90
@@ -0,0 +1,8 @@
+subroutine dr_hook_procinfo(kmyproc, knproc)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+use mpl_data_module, only : MPL_RANK,MPL_NUMPROC
+implicit none
+INTEGER(KIND=JPIM),intent(out) :: kmyproc, knproc
+kmyproc = mpl_rank
+knproc = mpl_numproc
+end subroutine dr_hook_procinfo
diff --git a/odb/src/extras/ifsaux/support/dr_hook_prt.F90 b/odb/src/extras/ifsaux/support/dr_hook_prt.F90
new file mode 100644
index 0000000..519c454
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/dr_hook_prt.F90
@@ -0,0 +1,13 @@
+SUBROUTINE DR_HOOK_PRT(KUNIT, CDSTR)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+IMPLICIT NONE
+INTEGER(KIND=JPIM), INTENT(IN) :: KUNIT
+CHARACTER(LEN=*), INTENT(IN) :: CDSTR
+
+IF (KUNIT < 0) THEN
+  WRITE(*,'(A)') CDSTR
+ELSE
+  WRITE(KUNIT,'(A)') CDSTR
+ENDIF
+
+END SUBROUTINE DR_HOOK_PRT
diff --git a/odb/src/extras/ifsaux/support/dr_hook_util.F90 b/odb/src/extras/ifsaux/support/dr_hook_util.F90
new file mode 100644
index 0000000..6459960
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/dr_hook_util.F90
@@ -0,0 +1,171 @@
+SUBROUTINE DR_HOOK_UTIL(CDNAME,KCASE,PKEY,CDFILENAME,KSIZEINFO)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK,ONLY : LHOOK
+USE OML_MOD,ONLY : OML_MAX_THREADS,OML_MY_THREAD,OML_INIT
+USE MPL_INIT_MOD
+USE MPL_ARG_MOD
+USE YOMGSTATS
+USE YOMHOOKSTACK   ! For monitoring thread stack usage
+
+IMPLICIT NONE
+CHARACTER(LEN=*),INTENT(IN) :: CDNAME,CDFILENAME
+INTEGER(KIND=JPIM),INTENT(IN) :: KCASE,KSIZEINFO
+REAL(KIND=JPRB),INTENT(INOUT) :: PKEY
+#ifdef RS6K
+INTEGER(KIND=JPIM) :: INEWMASK, IOLDMASK, UMASK
+#endif
+#ifdef CRAYXT
+INTEGER(KIND=JPIM) :: IRET, SETVBUF3F
+#endif
+LOGICAL,SAVE :: LL_FIRST_TIME = .TRUE.
+CHARACTER(LEN=512) :: CLENV
+INTEGER(KIND=JPIM) INUMTIDS, IMYTID
+LOGICAL :: LLMPI
+INTEGER*8 :: MAXMEM=0
+INTEGER*8 :: GETMAXMEM
+INTEGER*8 getmaxloc
+LOGICAL :: LLFINDSUMB=.FALSE.
+REAL(KIND=JPRB) :: ZCLOCK,ZDIFF
+CHARACTER(LEN=7) CLSTR
+
+INTEGER*8 ILOC         ! For monitoring thread stack usage
+CHARACTER(LEN=3) CHEAP ! For monitoring heap usage
+INTEGER          JHEAP ! For monitoring heap usage
+DATA JHEAP/0/
+
+INTERFACE
+#include "user_clock.h"
+END INTERFACE
+
+! -----------------------------------------------------------------
+
+IF (.NOT.LHOOK) RETURN
+
+IMYTID = OML_MY_THREAD()
+INUMTIDS = OML_MAX_THREADS()
+IF (LL_FIRST_TIME) THEN
+  LL_FIRST_TIME = .FALSE.
+#ifdef CRAYXT
+  IRET = SETVBUF3F(0, 1, 0) ! Set unit#0 into line-buffering mode to avoid messy output
+#endif
+  CALL OML_INIT()
+  CALL EC_GETENV('DR_HOOK_NOT_MPI',CLENV)
+  IF (CLENV == ' ' .OR. CLENV == '0' .OR. &
+    & CLENV == 'false' .OR. CLENV == 'FALSE') THEN
+    LLMPI=.TRUE.
+    CALL MPL_INIT(LDINFO=.FALSE.) ! Do not produce any output
+  ELSE
+    LLMPI=.FALSE.
+  ENDIF
+  CALL EC_GETENV('DR_HOOK',CLENV)
+  IF (CLENV == ' ' .OR. CLENV == '0' .OR. &
+    & CLENV == 'false' .OR. CLENV == 'FALSE') THEN
+    LHOOK = .FALSE.
+    CALL C_DRHOOK_SET_LHOOK(0)
+  ENDIF
+  IF (LLMPI) THEN
+    CALL MPL_GETARG(0, CLENV)  ! Get executable name & also propagate args
+  ELSE
+    CALL GETARG(0, CLENV)
+  ENDIF
+  IF (.not.LHOOK) RETURN
+  
+  CALL C_DRHOOK_INIT(CLENV, INUMTIDS)
+
+!JFH---Initialisation to monitor stack usage by threads-------------
+  CALL EC_GETENV('DR_HOOK_STACKCHECK',CSTACK)
+  if (CSTACK == 'yes' .or. CSTACK == 'YES' ) THEN
+    IF(IMYTID == 1 ) THEN
+      ALLOCATE(LL_THREAD_FIRST(INUMTIDS))
+      ALLOCATE(ISAVE(INUMTIDS))
+      ALLOCATE(IMAXSTACK(INUMTIDS))
+      LL_THREAD_FIRST=.TRUE.
+      ISAVE=0
+      IMAXSTACK=0
+    ENDIf
+  ENDIF
+!JFH------------ End ---------------------------------------------
+!JFH---Initialisation to monitor heap usage-----------------------
+  JHEAP=0
+  CALL EC_GETENV('DR_HOOK_HEAPCHECK',CHEAP)
+  if (CHEAP == 'yes' .or. CHEAP == 'YES' ) JHEAP=1
+  if (CHEAP == 'trb' .or. CHEAP == 'TRB' ) JHEAP=2
+  IF(IMYTID == 1) THEN
+    IF(JHEAP>0) THEN
+!     write(0,*) "HEAPCHECK=",CHEAP,JHEAP
+      CALL SETHEAPCHECK()
+    ENDIF
+  ENDIF
+!JFH------------ End ---------------------------------------------
+
+ENDIF
+
+!JFH---Code to monitor stack usage by threads---------------------
+IF (CSTACK == 'yes' .or. CSTACK == 'YES' ) THEN
+  IF(IMYTID > 1) THEN
+    IF(LL_THREAD_FIRST(IMYTID))THEN 
+      LL_THREAD_FIRST(IMYTID)=.FALSE.
+      ISAVE(IMYTID)=LOC(LLMPI)
+    ENDIF
+    ILOC=LOC(LLMPI)
+    IF(ISAVE(IMYTID)-ILOC > IMAXSTACK(IMYTID)) THEN
+      IMAXSTACK(IMYTID)=ISAVE(IMYTID)-ILOC
+      WRITE(0,'(A,I3,A,I12,2X,A)')"STACKCHECK Max stack usage by thread",imytid," =",IMAXSTACK(IMYTID),CDNAME
+    ENDIF
+  ENDIF
+ENDIF
+!JFH------------ End ---------------------------------------------
+
+IF (KCASE == 0) THEN
+  CALL C_DRHOOK_START(CDNAME, IMYTID, PKEY, CDFILENAME, KSIZEINFO)
+!JFH---Code to monitor heap usage -------------------------
+  if(IMYTID == 1 .and. MYPROC_STATS == 1 .and. JHEAP>0) THEN
+    GETMAXMEM=getmaxloc()
+    if(GETMAXMEM .gt. MAXMEM) then
+      MAXMEM = GETMAXMEM
+      write(0,*) "HEAPCHECK Max heap at beg of routine =",MAXMEM," ",CDNAME
+#ifdef RS6K
+      IF(JHEAP == 2) call xl__trbk()
+#endif
+    endif
+  endif
+!JFH------------ End ---------------------------------------------
+ELSE IF (KCASE == 1) THEN
+!JFH---Code to monitor heap usage -------------------------
+  if(IMYTID == 1 .and. MYPROC_STATS == 1 .and. JHEAP>0) THEN
+    GETMAXMEM=getmaxloc()
+    if(GETMAXMEM .gt. MAXMEM) then
+      MAXMEM = GETMAXMEM
+      write(0,*) "HEAPCHECK Max heap at end of routine =",MAXMEM," ",CDNAME
+#ifdef RS6K
+      IF(JHEAP == 2) call xl__trbk()
+#endif
+    endif
+  endif
+!JFH------------ End ---------------------------------------------
+  CALL C_DRHOOK_END  (CDNAME, IMYTID, PKEY, CDFILENAME, KSIZEINFO)
+ENDIF
+
+!GM---Code to find gstats SUMB time-------------------------------
+IF( LDETAILED_STATS .AND. LLFINDSUMB )THEN
+  IF( IMYTID==1 .AND. LAST_KNUM>=500 .AND. MYPROC_STATS <= 2 )THEN
+    IF( LAST_KSWITCH==1 .OR. LAST_KSWITCH==2 )THEN
+      CALL USER_CLOCK(PELAPSED_TIME=ZCLOCK)
+      ZDIFF=ZCLOCK-TIME_LAST_CALL
+      IF( ZDIFF > 0.1_JPRB )THEN
+        IF( KCASE == 0 )THEN
+          CLSTR='ENTERED'
+        ELSE
+          CLSTR='EXITED'
+        ENDIF
+        IF( NHOOK_MESSAGES < 100000 )THEN
+          WRITE(0,'("DR_HOOK_UTIL: ",A,2X,A," TIMESUMB=",F10.6)')CDNAME,CLSTR,ZDIFF
+          NHOOK_MESSAGES=NHOOK_MESSAGES+1
+        ENDIF
+      ENDIF
+    ENDIF
+  ENDIF
+ENDIF
+!GM------------ End ---------------------------------------------
+
+END SUBROUTINE DR_HOOK_UTIL
diff --git a/odb/src/extras/ifsaux/support/dr_hook_util_multi.F90 b/odb/src/extras/ifsaux/support/dr_hook_util_multi.F90
new file mode 100644
index 0000000..aba4a57
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/dr_hook_util_multi.F90
@@ -0,0 +1,33 @@
+SUBROUTINE DR_HOOK_UTIL_MULTI(CDNAME,KCASE,PKEY,KPKEY,CDFILENAME,KSIZEINFO)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK,ONLY : LHOOK
+USE OML_MOD,ONLY : OML_MAX_THREADS,OML_MY_THREAD
+IMPLICIT NONE
+CHARACTER(LEN=*),INTENT(IN) :: CDNAME,CDFILENAME
+INTEGER(KIND=JPIM),INTENT(IN) :: KPKEY, KCASE,KSIZEINFO
+REAL(KIND=JPRB),INTENT(INOUT) :: PKEY(KPKEY)
+
+LOGICAL,SAVE :: LL_FIRST_TIME = .TRUE.
+REAL(KIND=JPRB) :: ZDUMMY
+INTEGER(KIND=JPIM) :: IMYTID
+
+! -----------------------------------------------------------------
+
+IF (.NOT.LHOOK) RETURN
+IF (LL_FIRST_TIME) THEN
+  LL_FIRST_TIME = .FALSE.
+  CALL DR_HOOK_UTIL('',-1,ZDUMMY)
+ENDIF
+
+!$OMP PARALLEL DO SCHEDULE(STATIC,1)&
+!$OMP&PRIVATE(IMYTID)
+DO IMYTID=1,KPKEY
+  IF (KCASE == 0) THEN
+    CALL C_DRHOOK_START(CDNAME, IMYTID, PKEY(IMYTID), CDFILENAME, KSIZEINFO)
+  ELSE IF (KCASE == 1) THEN
+    CALL C_DRHOOK_END  (CDNAME, IMYTID, PKEY(IMYTID), CDFILENAME, KSIZEINFO)
+  ENDIF
+ENDDO ! IMYTID=1,KPKEY
+!$OMP END PARALLEL DO
+
+END SUBROUTINE DR_HOOK_UTIL_MULTI
diff --git a/odb/src/extras/ifsaux/support/drhook.c b/odb/src/extras/ifsaux/support/drhook.c
new file mode 100644
index 0000000..f702cb8
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/drhook.c
@@ -0,0 +1,4201 @@
+#define _DRHOOK_C_   1
+
+/* 
+   drhook.c
+
+   Author: Sami Saarinen, ECMWF, 14..24-Nov-2003
+
+   Thanks to Bob Walkup & John Hague for IBM Power4 version
+   Thanks to Bob Carruthers for Cray X1 (SV2), XD1 and XT3 versions,
+   as well as David Tanqueray for the flop routines
+
+   Also thanks to Roland Richter for suggesting the use
+   of "call tracebackqq()" function.
+   In our environment this is accomplished by calling fortran
+   routine intel_trbk() from ifsaux/utilities/gentrbk.F90.
+   This source must be compiled with -DINTEL flag, too.
+
+*/
+
+/*
+If intending to run on IBM P4+ or newer systems the following definition
+should be activated to use pm_initialize() instead of pm_init() of PMAPI-lib ($LIBHPM)
+#define PMAPI_POST_P4
+*/
+
+/*
+If *ALSO* intending to run on IBM P5+ systems, then set also BOTH
+#define PMAPI_POST_P4
+#define PMAPI_P5_PLUS
+*/
+
+/* Thanks to John Hague (IBM) 
+ If intending to run on IBM p6 systems, then set also BOTH
+#define PMAPI_POST_P4
+#define PMAPI_P6
+ */
+
+#if defined(PMAPI_P6)
+#define ENTRY_4 5
+#define ENTRY_6 4
+#elif defined(PMAPI_P5_PLUS)
+#define ENTRY_4 5
+#define ENTRY_6 4
+#else
+#define ENTRY_4 4
+#define ENTRY_6 6
+#endif
+
+#if defined(SV2) || defined(XD1) || defined(XT3)
+#define DT_FLOP
+#define HPM
+#define MAX_COUNTERS 6
+#endif
+
+#if defined(__GNUC__)
+#define _GNU_SOURCE /* must be defined before *any* standard header is included */
+#endif
+
+#ifdef RS6K
+#pragma options opt=3 halt=e
+#include <pthread.h>
+#endif
+
+/* === This doesn't handle recursive calls correctly (yet) === */
+
+#include "drhook.h"
+
+int drhook_memtrace = 0; /* set to 1, if opt_memprof or opt_timeline ; used in getcurheap.c to lock stuff */
+
+#if !defined(CACHELINESIZE)
+#define CACHELINESIZE 128 /* ***Note: A hardcoded cache line size in bytes !!! */
+#endif
+
+#include "crc.h"
+#include <time.h>
+
+static char *start_stamp = NULL;
+static char *end_stamp = NULL;
+
+#if defined(NECSX)
+#pragma cdir options -Nv -Csopt
+extern void necsx_trbk_(const char *msg, int msglen); /* from ../utilities/gentrbk.F90 */
+#endif
+
+#if defined(LINUX) && !defined(XT3) && !defined(XD1) && !defined(CYGWIN)
+
+#if defined(__GNUC__) && !defined(NO_TRAPFPE)
+
+#if defined(CYGWIN)
+#include <mingw/fenv.h>
+#else
+#include <fenv.h>
+#endif
+#if defined(DARWIN)
+  /*  A temporary fix to link on MacIntosh. Something more clever will be done later -REK. */
+void feenableexcept() { }
+void fedisableexcept() { }
+#endif
+
+
+static void trapfpe(void)
+{
+  /* Enable some exceptions. At startup all exceptions are masked. */
+  (void) feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
+}
+
+static void untrapfpe(void)
+{
+  /* Disable some exceptions. At startup all exceptions are masked. */
+  (void)fedisableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
+}
+
+#endif /* defined(__GNUC__) */
+
+#endif /* defined(LINUX) && !defined(XT3) && !defined(XD1) */
+
+#if (!defined(LINUX) || defined(CYGWIN) || defined(NO_TRAPFPE)) && defined(__GNUC__)
+/* For example Solaris with gcc */
+#define trapfpe()
+#define untrapfpe()
+#endif
+
+static int any_memstat = 0;
+static int opt_gethwm = 0;
+static int opt_getstk = 0;
+static int opt_getrss = 0;
+static int opt_getpag = 0;
+static int opt_walltime = 0;
+static int opt_cputime = 0;
+static int opt_wallprof = 0;
+static int opt_cpuprof = 0;
+static int opt_hpmprof = 0;
+static int opt_memprof = 0;
+static int opt_trim = 0;
+static int opt_calls = 0;
+static int opt_self = 1; /* 0=exclude drhook altogether, 
+			    1=include, but don't print, 
+			    2=also print */
+static int opt_propagate_signals = 1;
+static int opt_sizeinfo = 1;
+static int opt_clusterinfo = 0;
+static int opt_callpath = 0;
+#define callpath_indent_default 2
+static int callpath_indent = callpath_indent_default;
+#define callpath_depth_default 50
+static int callpath_depth = callpath_depth_default;
+
+static int opt_calltrace = 0;
+
+static int opt_timeline = 0; /* myproc or -1 [or 0 for --> timeline feature off (default)] */
+static int opt_timeline_thread = 1; /* thread-id control : 
+				    <= 0 print for all threads
+				       1 -> #1 only [but curheap still SUM of all threads] (default), 
+				       n -> print for increasing number of threads separately : [1..n] */
+static int opt_timeline_format = 1; /* if 1, print only {wall,hwm,rss,curheap} w/o labels "wall=" etc.; else fully expanded fmt */
+static int opt_timeline_unitno = 6; /* Fortran unit number : default = 6 i.e. stdout */
+static long long int opt_timeline_freq = 1000000; /* How often to print : every n-th call : default = every 10^6 th call or ... */
+static double opt_timeline_MB = 1.0; /* ... rss or curheap jumps up/down by more than this many MBytes (default = 1) : unit MBytes */
+
+static int opt_gencore = 0;
+static int opt_gencore_signal = 0;
+
+typedef struct drhook_timeline_t {
+  unsigned long long int calls[2]; /* 0=drhook_begin , 1=drhook_end */
+  double last_curheap_MB;
+  double last_rss_MB;
+  char pad[CACHELINESIZE - (2*sizeof(unsigned long long int) + 2*sizeof(double))]; /* padding : e.g. 128 bytes - 4*8 bytes */
+} drhook_timeline_t; /* cachelinesize optimized --> less false sharing when running with OpenMP */
+
+static drhook_timeline_t *timeline = NULL;
+
+/* HPM-specific */
+
+static long long int opt_hpmstop_threshold = -1;
+static        double opt_hpmstop_mflops    =  1000000.0; /* Yes, 1 PetaFlop/s !! */
+
+
+#define DRHOOK_STRBUF 1000
+
+#ifndef SA_SIGINFO
+#define SA_SIGINFO 0
+#define SIG_EXTRA_ARGS       /* empty */
+#define SIG_PASS_EXTRA_ARGS  /* empty */
+#else 
+#define SIG_EXTRA_ARGS       , siginfo_t *sigcode, void *sigcontextptr
+#define SIG_PASS_EXTRA_ARGS  , sigcode, sigcontextptr
+#endif
+
+#define NIL "(nil)"
+
+#undef MIN
+#define MIN(a,b) ( (a) < (b) ? (a) :  (b) )
+
+#undef MAX
+#define MAX(a,b) ( (a) > (b) ? (a) :  (b) )
+
+#undef ABS
+#define ABS(x)   ( (x) >= 0  ? (x) : -(x) )
+
+#define strequ(s1,s2)     ((void *)s1 && (void *)s2 && strcmp(s1,s2) == 0)
+#define strnequ(s1,s2,n)  ((void *)s1 && (void *)s2 && memcmp(s1,s2,n) == 0)
+
+extern long long int getstk_();
+extern long long int getmaxstk_();
+extern long long int gethwm_();
+extern long long int getrss_();
+extern long long int getcurheap_();
+extern long long int getmaxcurheap_();
+extern long long int getcurheap_thread_(const int *tidnum);    /* *tidnum >= 1 && <= max_threads */
+extern long long int getmaxcurheap_thread_(const int *tidnum); /* *tidnum >= 1 && <= max_threads */
+extern long long int getpag_();
+
+extern void ec_set_umask_();
+
+#if defined(DT_FLOP)
+extern double flop_();
+#endif
+
+extern double util_cputime_();
+extern double util_walltime_();
+
+#ifdef RS6K
+static long long int irtc_start = 0;
+extern long long int irtc();
+#define WALLTIME() ((double)(irtc() - irtc_start)*1.0e-9)
+#define CPUTIME() util_cputime_()
+#elif defined(CRAYXT)
+/* Cray XT3/XT4 with catamount microkernel */
+#include <catamount/dclock.h>
+static double dclock_start = 0;
+#define WALLTIME() (dclock() - dclock_start)
+#define CPUTIME()  WALLTIME()
+#else
+#if defined(SV2)
+#include <intrinsics.h>
+#endif
+#if defined(XD1) || defined(XT3)
+extern long long int irtc_();             /* integer*8 irtc() */
+extern long long int irtc_rate_();        /* integer*8 irtc_rate() */
+#endif
+#if defined(SV2) || defined(XD1) || defined(XT3)
+static long long int irtc_start = 0;
+static double my_irtc_rate = 0;
+static double my_inv_irtc_rate = 0;
+#if defined(SV2)
+#define WALLTIME() ((double)(_rtc() - irtc_start)*my_inv_irtc_rate)
+#else
+#define WALLTIME() ((double)(irtc_() - irtc_start)*my_inv_irtc_rate)
+#endif
+#define CPUTIME() util_cputime_()
+#else
+#define WALLTIME() util_walltime_()
+#define CPUTIME() util_cputime_()
+#endif
+#endif
+
+/* #define RAISE(x) { int tmp = x; c_drhook_raise_(&tmp); } */
+#include "raise.h"
+#include "cargs.h"
+
+extern int get_thread_id_();
+extern void LinuxTraceBack(void *sigcontextptr);
+
+/*** typedefs ***/
+
+typedef union {
+  struct drhook_key_t *keyptr;
+  double d;
+  unsigned long long int ull;
+} equivalence_t;
+
+typedef struct drhook_key_t {
+  char *name;
+  unsigned short name_len;
+  const equivalence_t *callpath; /* parent's tree down to callpath_depth */
+  int callpath_len;
+  unsigned int callpath_fullhash;
+  unsigned short status; /* 0=inactive, >1 active */
+  unsigned long long int calls;
+  long long int hwm, maxrss, rssnow, stack, maxstack, paging;
+  double wall_in, delta_wall_all, delta_wall_child;
+  double cpu_in, delta_cpu_all, delta_cpu_child;
+#ifdef HPM
+  unsigned char hpm_stopped, counter_stopped;
+  double this_delta_wall_child;
+  double avg_mipsrate, avg_mflops;
+  unsigned long long int hpm_calls;
+  double mip_count_in, mflop_count_in;
+  long long int *counter_in, *counter_sum;
+#endif
+  char *filename;         /* the filename where the 1st call (on this routine-name) 
+			     to dr_hook() occurred */
+  long long int sizeinfo; /* # of data elements, bytes, etc. */
+  long long int min_sizeinfo, max_sizeinfo; /* min & max of # of data elements, bytes, etc. */
+  /* memprof specific */
+  long long int mem_seenmax;
+  long long int mem_child, mem_curdelta;
+  long long int maxmem_selfdelta, maxmem_alldelta;
+  long long int mem_maxhwm, mem_maxrss, mem_maxstk, mem_maxpagdelta;
+  long long int paging_in;
+  unsigned long long int alloc_count, free_count;
+  struct drhook_key_t *next;
+} drhook_key_t;
+
+typedef struct drhook_calltree_t {
+  int active;
+  drhook_key_t *keyptr;
+  struct drhook_calltree_t *next;
+  struct drhook_calltree_t *prev;
+} drhook_calltree_t;
+
+typedef struct drhook_sig_t {
+  int active;
+  char name[32];
+  struct sigaction new;
+  struct sigaction old;
+  int ignore_atexit;
+} drhook_sig_t;
+
+typedef union {
+  void (*func1args)(int sig);
+  void (*func3args)(int sig SIG_EXTRA_ARGS);
+} drhook_sigfunc_t;
+
+typedef struct drhook_prof_t {
+  double pc;
+  double total;
+  double self;
+  unsigned long long int calls;
+  double percall_ms_self;
+  double percall_ms_total;
+  double mipsrate, mflops, divpc;
+  int index;
+  int tid;
+  int cluster;
+  double *maxval;
+  unsigned char is_max;
+  char *name;
+  char *filename;
+  long long int sizeinfo;
+  long long int min_sizeinfo, max_sizeinfo;
+  double sizespeed, sizeavg;
+  const equivalence_t *callpath; /* parent's tree down to callpath_depth */
+  int callpath_len;
+} drhook_prof_t;
+
+typedef struct drhook_memprof_t {
+  double pc;
+  long long int self;
+  long long int children;
+  long long int hwm, rss, stk, pag, leaked;
+  unsigned long long int calls, alloc_count, free_count;
+  int index;
+  int tid;
+  int cluster;
+  long long int *maxval;
+  unsigned char is_max;
+  char *name;
+  char *filename;
+  const equivalence_t *callpath; /* parent's tree down to callpath_depth */
+  int callpath_len;
+} drhook_memprof_t;
+
+#define MAX_WATCH_FIRST_NBYTES 8
+
+typedef struct drhook_watch_t {
+  char *name;
+  int tid;
+  int active;
+  int abort_if_changed;
+  const char *ptr;
+  int nbytes;
+  int watch_first_nbytes;
+  char first_nbytes[MAX_WATCH_FIRST_NBYTES];
+  unsigned int crc32;
+  struct drhook_watch_t *next;
+} drhook_watch_t;
+
+/*** static (local) variables ***/
+
+static o_lock_t DRHOOK_lock = 0;
+static int numthreads = 0;
+static int myproc = 1;
+static int nproc = -1;
+static int max_threads = 1;
+static pid_t pid = -1;
+static drhook_key_t      **keydata  = NULL;
+static drhook_calltree_t **calltree = NULL;
+static drhook_calltree_t **thiscall = NULL;
+static int signals_set = 0;
+static int signal_handler_called = 0;
+static int signal_handler_ignore_atexit = 0;
+static drhook_sig_t siglist[1+NSIG] = { 0 };
+static char *a_out = NULL;
+static char *mon_out = NULL;
+static int mon_out_procs = -1;
+static double percent_limit = -10; /* Lowest percentage accepted into the printouts */
+static drhook_key_t **keyself = NULL; /* pointers to itself (per thread) */
+static double *overhead; /* Total Dr.Hook-overhead for every thread in either WALL or CPU secs */
+static drhook_key_t **curkeyptr = NULL; /* pointers to current keyptr (per thread) */
+static drhook_watch_t *watch = NULL;
+static drhook_watch_t *last_watch = NULL;
+static int watch_count = 0; /* No. of *active* watch points */
+
+#define HASHSIZE(n) ((unsigned int)1<<(n))
+#define HASHMASK(n) (HASHSIZE(n)-1)
+
+#define NHASH    16
+#define NHASHMAX 24
+static int nhash = NHASH;
+static unsigned int hashsize = HASHSIZE(NHASH);
+static unsigned int hashmask = HASHMASK(NHASH);
+
+#ifdef HPM
+/* HPM-specific (static) protos */
+
+static void stopstart_hpm(int tid, drhook_key_t *pstop, drhook_key_t *pstart);
+static void stop_only_hpm(int tid, drhook_key_t *pstop);
+static void init_hpm(int tid);
+static double mflops_hpm(const drhook_key_t *keyptr);
+static double mips_hpm(const drhook_key_t *keyptr);
+static double divpc_hpm(const drhook_key_t *keyptr);
+static double mflop_count(const drhook_key_t *keyptr);
+static double mip_count(const drhook_key_t *keyptr);
+
+#else
+/* Dummies for HPM as macros that do nothing */
+
+#define stopstart_hpm(tid, pstop, pstart)
+#define stop_only_hpm(tid, pstop)
+#define init_hpm(tid)
+#define mflops_hpm(keyptr)  0
+#define mips_hpm(keyptr)    0
+#define divpc_hpm(keyptr)   0
+#define mflop_count(keyptr) 0
+#define mip_count(keyptr)   0
+
+#endif
+
+/*--- malloc_drhook ---*/
+
+static void *
+malloc_drhook(size_t size)
+{
+  size_t size1 = MAX(1,size);
+  void *p = malloc(size1);
+  if (!p) {
+    fprintf(stderr,"***Error in malloc_drhook(): Unable to allocate space for %d bytes\n", size1);
+    RAISE(SIGABRT);
+  }
+  return p;
+}
+
+/*--- calloc_drhook ---*/
+
+static void *
+calloc_drhook(size_t nmemb, size_t size)
+{
+  size_t n = nmemb * size;
+  void *p = malloc_drhook(n);
+  memset(p,0,n);
+  return p;
+}
+
+/*--- free_drhook ---*/
+
+#define free_drhook(x) { if (x) { free(x); x = NULL; } }
+
+/*--- strdup_drhook ---*/
+
+static char *
+strdup_drhook(const char *s)
+{
+  int n = strlen(s);
+  char *p = malloc_drhook(n+1);
+  memcpy(p,s,n);
+  p[n] = 0;
+  return p;
+}
+
+/*--- strdup2_drhook ---*/
+
+static char *
+strdup2_drhook(const char *s, int s_len)
+{
+  int n = s_len;
+  char *p = malloc_drhook(n+1);
+  memcpy(p,s,n);
+  p[n] = 0;
+  return p;
+}
+
+/*--- timestamp ---*/
+
+static char *
+timestamp()
+{
+  time_t tp;
+  const int bufsize = 80;
+  char *buf = malloc_drhook(bufsize+1);
+  time(&tp);
+  strftime(buf, bufsize, "%Y%m%d %H%M%S", localtime(&tp));
+  return buf;
+}
+
+/*--- hashfunc ---*/
+
+unsigned int
+hashfunc(const char *s, int s_len)
+{
+  unsigned int hashval;
+  if (opt_trim) {
+    for (hashval = 0; s_len>0 ; s++, s_len--) {
+      unsigned char c = islower(*s) ? toupper(*s) : *s;
+      hashval = (hashval<<4)^(hashval>>28)^(c);
+    }
+  }
+  else {
+    for (hashval = s_len; s_len>0 ; s_len--) {
+      hashval = (hashval<<4)^(hashval>>28)^(*s++);
+    }
+  }
+  hashval = (hashval ^ (hashval>>10) ^ (hashval>>20)) & hashmask;
+  return hashval;
+}
+
+/*--- callpath_hashfunc ---*/
+
+unsigned int
+callpath_hashfunc(unsigned int inithash, /* from hashfunc() */
+		  const equivalence_t *callpath, int callpath_len,
+		  unsigned int *fullhash)
+{
+  unsigned int hashval;
+  for (hashval = inithash; callpath_len>0 ; callpath++, callpath_len--) {
+    hashval = (hashval<<4)^(hashval>>28)^(callpath->ull);
+  }
+  if (fullhash) *fullhash = hashval;
+  hashval = (hashval ^ (hashval>>10) ^ (hashval>>20)) & hashmask;
+  return hashval;
+}
+
+/*--- insert_calltree ---*/
+
+static void
+insert_calltree(int tid, drhook_key_t *keyptr)
+{
+  if (tid >= 1 && tid <= numthreads) {
+    drhook_calltree_t *treeptr = thiscall[tid-1];
+    while (treeptr->active) {
+      if (!treeptr->next) {
+	treeptr->next = calloc_drhook(1,sizeof(drhook_calltree_t));
+	treeptr->next->prev = treeptr;
+      }
+      treeptr = treeptr->next;
+    }
+    treeptr->keyptr = keyptr;
+    treeptr->active = 1;
+    thiscall[tid-1] = treeptr;
+#ifdef HPM
+    if (opt_hpmprof) {
+      drhook_key_t *kptr = treeptr->keyptr;
+      if (!kptr->hpm_stopped) {
+	stopstart_hpm(tid,
+		      treeptr->prev ? treeptr->prev->keyptr : NULL, /* stop current (i.e. my parent) */
+		      kptr);                             /* start to gather for me */
+	kptr->this_delta_wall_child = 0;
+	kptr->mip_count_in = mip_count(kptr);
+	kptr->mflop_count_in = mflop_count(kptr);
+#ifdef DEBUG
+	fprintf(stderr,"insert[%.*s@%d]: this_delta_wall_child=%.15g, mip#%.15g, mflop#%.15g\n",
+		kptr->name_len,kptr->name,
+		tid,kptr->this_delta_wall_child,
+		kptr->mip_count_in,kptr->mflop_count_in);
+#endif
+      }
+      else {
+	stop_only_hpm(tid,
+		      treeptr->prev ? treeptr->prev->keyptr : NULL /* stop current (i.e. my parent) */);
+      } /* if (!kptr->hpm_stopped) else */
+    } /* if (opt_hpmprof) */
+#endif
+  }
+}
+
+/*--- remove_calltree ---*/
+
+static void 
+remove_calltree(int tid, drhook_key_t *keyptr, 
+		const double *delta_wall, const double *delta_cpu)
+{
+  if (tid >= 1 && tid <= numthreads) {
+    drhook_calltree_t *treeptr = thiscall[tid-1];
+    if (treeptr->active && treeptr->keyptr == keyptr) {
+      treeptr->active = 0;
+      if (treeptr->prev) {
+	drhook_key_t *parent_keyptr = treeptr->prev->keyptr;
+	if (parent_keyptr) { /* extra security */
+	  if (opt_walltime) {
+	    parent_keyptr->delta_wall_child += (*delta_wall);
+#ifdef HPM
+	    if (opt_hpmprof) parent_keyptr->this_delta_wall_child += (*delta_wall);
+#endif
+	  }
+	  if (opt_cputime)  {
+	    parent_keyptr->delta_cpu_child  += (*delta_cpu);
+	  }
+	  if (opt_memprof) {
+	    /*
+	    const long long int size = 0;
+	    c_drhook_memcounter_(&tid, &size, NULL);
+	    fprintf(stderr,
+		    ">parent(%.*s)->mem_child = %lld ; this(%.*s)->alldelta = %lld, mem_child = %lld\n",
+		    parent_keyptr->name_len, parent_keyptr->name, parent_keyptr->mem_child,
+		    keyptr->name_len, keyptr->name, keyptr->maxmem_alldelta, keyptr->mem_child);
+	    */
+	    parent_keyptr->mem_child = MAX(parent_keyptr->mem_child, keyptr->maxmem_alldelta);
+	    /*
+	    fprintf(stderr,
+		    "<parent(%.*s)->mem_child = %lld ; this(%.*s)->alldelta = %lld, mem_child = %lld\n",
+		    parent_keyptr->name_len, parent_keyptr->name, parent_keyptr->mem_child,
+		    keyptr->name_len, keyptr->name, keyptr->maxmem_alldelta, keyptr->mem_child);
+	    */
+	  }
+	} /* if (parent_keyptr) */
+	thiscall[tid-1] = treeptr->prev;
+      }
+      else {
+	thiscall[tid-1] = calltree[tid-1];
+      }
+#ifdef HPM
+      if (opt_hpmprof) {
+	drhook_key_t *kptr = treeptr->keyptr;
+	if (!kptr->hpm_stopped) {
+	  double this_delta_wall_self = *delta_wall - kptr->this_delta_wall_child;
+	  stopstart_hpm(tid, 
+			kptr, 
+			thiscall[tid-1]->keyptr); /* stop current, (re-)start previous */
+	  /* Calculate moving average of mipsrate & mflops ; divpc we don't bother */
+#ifdef DEBUG
+	  fprintf(stderr,"remove[%.*s@%d]: this_delta_wall_self=%.15g i.e. %.15g - %.15g",
+		  kptr->name_len,kptr->name,
+		  tid,this_delta_wall_self,
+		  *delta_wall,kptr->this_delta_wall_child);
+#endif
+	  if (this_delta_wall_self > 0) {
+	    long long int hpm_calls = ++kptr->hpm_calls;
+	    double mipsrate, mflops;
+	    kptr->mip_count_in = mip_count(kptr) - kptr->mip_count_in;
+	    kptr->mflop_count_in = mflop_count(kptr) - kptr->mflop_count_in;
+	    mipsrate = kptr->mip_count_in/this_delta_wall_self;
+	    kptr->avg_mipsrate = ((hpm_calls-1)*kptr->avg_mipsrate + mipsrate)/hpm_calls;
+	    mflops = kptr->mflop_count_in/this_delta_wall_self;
+	    kptr->avg_mflops = ((hpm_calls-1)*kptr->avg_mflops + mflops)/hpm_calls;
+#ifdef DEBUG
+	    fprintf(stderr,
+		    ", mip#%.15g, mflop#%.15g : mipsrate=%.15g, avg=%.15g; mflops=%.15g, avg=%.15g",
+		    kptr->mip_count_in,kptr->mflop_count_in,
+		    mipsrate, kptr->avg_mipsrate,
+		    mflops, kptr->avg_mflops);
+#endif
+	  }
+#ifdef DEBUG
+	  fprintf(stderr,"\n");
+#endif
+	  if (opt_hpmstop_threshold > 0 && kptr->calls == opt_hpmstop_threshold) {
+	    /* check whether hpm should anymore be called for this routine */
+	    if (kptr->avg_mflops < opt_hpmstop_mflops) kptr->hpm_stopped = 1;
+	  }
+	}
+	else {
+	  stop_only_hpm(tid,kptr);
+	} /* if (!kptr->hpm_stopped) else ... */
+      } /* if (opt_hpmprof) */
+#endif
+      curkeyptr[tid-1] = thiscall[tid-1]->keyptr;
+    }
+    else {
+      curkeyptr[tid-1] = NULL;
+    } /* if (treeptr->active && treeptr->keyptr == keyptr) else ... */
+  }
+}
+
+/*--- memstat ---*/
+
+static void
+memstat(drhook_key_t *keyptr, const int *thread_id, int in_getkey)
+{
+  if (any_memstat && keyptr) {
+    if (opt_gethwm) keyptr->hwm = gethwm_();
+    if (opt_getrss) {
+      keyptr->maxrss = getrss_();
+      keyptr->rssnow = getcurheap_thread_(thread_id);
+    }
+    if (opt_getstk) {
+      long long int stk = getstk_();
+      keyptr->stack = stk;
+      keyptr->maxstack = MAX(keyptr->maxstack,stk);
+    }
+    if (opt_getpag) keyptr->paging = getpag_();
+    if (opt_memprof) {
+      keyptr->mem_seenmax = getmaxcurheap_thread_(thread_id);
+      if (in_getkey) { /* Upon enter of a Dr.Hook'ed routine */
+	/* A note for "keyptr->mem_curdelta": 
+	   1) do not reset to 0
+	   2) initially calloc'ed to 0 while initializing the keydata[] ~ alias keyptr
+	   3) remember the previous value --> catches memory leaks, too !! */
+	/* keyptr->mem_curdelta = 0; */
+	/* Nearly the same holds for "keyptr->mem_child"; 
+	   we need to capture the maximum/hwm for child */
+	/* keyptr->mem_child = 0; */
+	keyptr->paging_in = keyptr->paging;
+      }
+      else { /* Upon exit of a Dr.Hook'ed routine */
+	long long int alldelta = keyptr->mem_curdelta + keyptr->mem_child;
+	if (alldelta > keyptr->maxmem_alldelta) keyptr->maxmem_alldelta = alldelta;
+	if (keyptr->paging - keyptr->paging_in > keyptr->mem_maxpagdelta)
+	  keyptr->mem_maxpagdelta = keyptr->paging - keyptr->paging_in;
+      }
+      if (keyptr->hwm      > keyptr->mem_maxhwm) keyptr->mem_maxhwm = keyptr->hwm;
+      if (keyptr->maxrss   > keyptr->mem_maxrss) keyptr->mem_maxrss = keyptr->maxrss;
+      if (keyptr->maxstack > keyptr->mem_maxstk) keyptr->mem_maxstk = keyptr->maxstack;
+    }
+  }
+}
+
+/*--- flptrap ---*/
+
+/*
+  -----------------------------------------------------------------------
+  If we are trapping Floating-Point Error, then set the processor in SYNC
+  modes and enable TRP_INVALID, TRP_DIV_BY_ZERO and TRP_OVERFLOW.
+  -----------------------------------------------------------------------
+*/
+
+#ifdef RS6K
+static void
+flptrap(int sig)
+{
+  if (sig == SIGFPE) {
+    /* From John Hague, IBM, UK (--> thanks a lot, John !!)*/
+    int ret = fp_trap(FP_TRAP_FASTMODE);
+    if ((ret == FP_TRAP_UNIMPL) || (ret == FP_TRAP_ERROR)) {
+      char errmsg[4096];
+      sprintf(errmsg, 
+      "flptrap(): Call to 'fp_trap' in signal_trap failed (return code = %d)\n (line %d in file %s)\n",
+      ret, __LINE__, __FILE__);
+      perror(errmsg);
+      RAISE(SIGABRT);
+    }
+    fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
+  }
+}
+#elif defined(__GNUC__) && !defined(NO_TRAPFPE)
+static void
+flptrap(int sig)
+{
+  if (sig == SIGFPE) {
+    /* Adapted from www.twinkle.ws/arnaud/CompilerTricks.html#Glibc_FP */
+    trapfpe(); /* No need for pgf90's -Ktrap=fp  now ? */
+  }
+}
+#else
+static void
+flptrap(int sig)
+{
+  return; /* A dummy */
+}
+#endif
+
+/*--- catch_signals ---*/
+
+static void signal_gencore(int sig SIG_EXTRA_ARGS);
+static void signal_harakiri(int sig SIG_EXTRA_ARGS);
+static void signal_drhook(int sig SIG_EXTRA_ARGS);
+
+#define CATCHSIG(x) {\
+  drhook_sig_t *sl = &siglist[x];\
+  if (sl->active == 0) {\
+    drhook_sigfunc_t u;\
+    u.func3args = signal_drhook;\
+    sl->active = 1;\
+    sigemptyset(&sl->new.sa_mask);\
+    sl->new.sa_handler = u.func1args;\
+    sl->new.sa_flags = SA_SIGINFO;\
+    sigaction(x,&sl->new,&sl->old);\
+    flptrap(x);\
+    if (!silent && myproc == 1) {\
+      fprintf(stderr,\
+	      ">>%s(): DR_HOOK also catches signal#%d; new handler installed at 0x%x; old preserved at 0x%x\n",\
+              "catch_signals", x, sl->new.sa_handler, sl->old.sa_handler);\
+    }\
+  }\
+}
+
+static void
+catch_signals(int silent)
+{
+  char *env = getenv("DR_HOOK_CATCH_SIGNALS");
+  if (env) {
+    const char delim[] = ", \t/";
+    char *p, *s = strdup_drhook(env);
+    p = strtok(s,delim);
+    while (p) {
+      int sig = atoi(p);
+      if (sig >= 1 && sig <= NSIG) {
+	CATCHSIG(sig);
+      }
+      else if (sig == -1) { /* Makes ALL (catchable) signals available to DR_HOOK */
+	int j;
+	for (j=1; j<=NSIG; j++) {
+	  CATCHSIG(j);
+	} /* for (j=1; j<=NSIG; j++) */
+	break;
+      }
+      p = strtok(NULL,delim);
+    }
+    free_drhook(s);
+  }
+}
+
+/*--- ignore_signals ---*/
+
+static void
+ignore_signals(int silent)
+{
+  char *env = getenv("DR_HOOK_IGNORE_SIGNALS");
+  if (env) {
+    const char delim[] = ", \t/";
+    char *p, *s = strdup_drhook(env);
+    p = strtok(s,delim);
+    while (p) {
+      int sig = atoi(p);
+      if (sig >= 1 && sig <= NSIG) {
+	drhook_sig_t *sl = &siglist[sig];
+	if (!silent && myproc == 1) {
+	  fprintf(stderr,
+		  ">>>ignore_signals(): DR_HOOK will ignore signal#%d altogether\n", sig);
+	}
+#if defined(__GNUC__) && !defined(NO_TRAPFPE)
+	if (sig == SIGFPE) untrapfpe(); /* Turns off a possible -Ktrap=fp from pgf90 */
+#endif
+	sl->active = -1;
+      }
+      else if (sig == -1) { /* Switches off ALL signals from DR_HOOK */
+	int j;
+	for (j=1; j<=NSIG; j++) {
+	  drhook_sig_t *sl = &siglist[j];
+	  if (!silent && myproc == 1) {
+	    fprintf(stderr,
+		    ">>>ignore_signals(): DR_HOOK will ignore signal#%d altogether\n", j);
+	  }
+#if defined(__GNUC__) && !defined(NO_TRAPFPE)
+	  if (sig == SIGFPE) untrapfpe(); /* Turns off a possible -Ktrap=fp from pgf90 */
+#endif
+	  sl->active = -1;
+	} /* for (j=1; j<=NSIG; j++) */
+	break;
+      }
+      p = strtok(NULL,delim);
+    }
+    free_drhook(s);
+  }
+}
+
+/*--- gdb__sigdump ---*/
+
+#if (defined(LINUX) || defined(SUN4)) && !defined(XT3) && !defined(XD1)
+static void gdb__sigdump(int sig SIG_EXTRA_ARGS)
+{
+  static int who = 0; /* Current owner of the lock, if > 0 */
+  int is_set = 0;
+  int it = get_thread_id_(); 
+  drhook_sig_t *sl = &siglist[sig];
+
+  coml_test_lockid_(&is_set, &DRHOOK_lock);
+  if (is_set && who == it) {
+    fprintf(stderr,"[gdb__sigdump] : Received (another) signal#%d(%s), pid=%d\n",sig,sl->name,pid);
+    fprintf(stderr,"[gdb__sigdump] : Recursive calls by the same thread#%d not allowed. Bailing out\n",it);
+    return;
+  }
+  if (!is_set) coml_set_lockid_(&DRHOOK_lock);
+  who = it;
+  fprintf(stderr,"[gdb__sigdump] : Received signal#%d(%s), pid=%d\n",sig,sl->name,pid);
+  LinuxTraceBack(sigcontextptr);
+  who = 0;
+  coml_unset_lockid_(&DRHOOK_lock);
+}
+#endif
+
+/*--- signal_drhook ---*/
+
+#define SETSIG5(x,ignore_flag,handler_name,preserve_old,xstr) {\
+  drhook_sig_t *sl = &siglist[x];\
+  if (sl->active == 0) {\
+    drhook_sigfunc_t u;\
+    u.func3args = handler_name;\
+    sl->active = 1;\
+    strcpy(sl->name,xstr);\
+    sigemptyset(&sl->new.sa_mask);\
+    sl->new.sa_handler = u.func1args;\
+    sl->new.sa_flags = SA_SIGINFO;\
+    sigaction(x,&sl->new,preserve_old ? &sl->old : NULL);\
+    sl->ignore_atexit = ignore_flag;\
+    flptrap(x);\
+    if (!silent && myproc == 1) {\
+      const char *fmt = "%s(%s=%d): New handler installed at 0x%llx; old %spreserved at 0x%llx\n"; \
+      if (sizeof(void *) == 4) { \
+                  fmt = "%s(%s=%d): New handler installed at 0x%x; old %spreserved at 0x%x\n"; \
+      } \
+      fprintf(stderr,fmt,\
+            #handler_name, sl->name, x, \
+            sl->new.sa_handler, \
+            preserve_old ? "" : "NOT ", \
+            preserve_old ? sl->old.sa_handler : NULL);\
+    }\
+  }\
+}
+
+#define SETSIG(x,ignore_flag) SETSIG5(x,ignore_flag,signal_drhook,1,#x)
+
+#define JSETSIG(x,ignore_flag) {\
+  drhook_sig_t *sl = &siglist[x];\
+  drhook_sigfunc_t u;\
+  fprintf(stderr,"JSETSIG: sl->active = %d\n",sl->active);\
+  u.func3args = signal_harakiri;\
+  sl->active = 1;\
+  strcpy(sl->name,#x);\
+  sigemptyset(&sl->new.sa_mask);\
+  sl->new.sa_handler = u.func1args;\
+  sl->new.sa_flags = SA_SIGINFO;\
+  sigaction(x,&sl->new,&sl->old);\
+  sl->ignore_atexit = ignore_flag;\
+  flptrap(x);\
+  { \
+    const char *fmt = "%s(%s=%d): New handler installed at 0x%llx; old preserved at 0x%llx\n"; \
+    if (sizeof(void *) == 4) { \
+                fmt = "%s(%s=%d): New handler installed at 0x%x; old preserved at 0x%x\n"; \
+    } \
+    fprintf(stderr,fmt,\
+            "signal_harakiri", sl->name, x, \
+            sl->new.sa_handler, \
+            sl->old.sa_handler);\
+  } \
+}
+
+#if defined(RS6K) && defined(__64BIT__)
+#define DRH_STRUCT_RLIMIT struct rlimit64
+#define DRH_GETRLIMIT getrlimit64
+#define DRH_SETRLIMIT setrlimit64
+#else
+#define DRH_STRUCT_RLIMIT struct rlimit
+#define DRH_GETRLIMIT getrlimit
+#define DRH_SETRLIMIT setrlimit
+#endif
+
+static void 
+signal_gencore(int sig SIG_EXTRA_ARGS)
+{
+  if (opt_gencore > 0) { 
+    opt_gencore = 0; /* A tiny chance for a race condition between threads */
+    if (sig == opt_gencore_signal && sig >= 1 && sig <= NSIG) {
+      signal(sig, SIG_IGN);
+      signal(SIGABRT, SIG_DFL);
+      { /* Enable unlimited cores (up to hard-limit) and call abort() --> generates core dump */
+	DRH_STRUCT_RLIMIT r;
+	if (DRH_GETRLIMIT(RLIMIT_CORE, &r) == 0) {
+	  r.rlim_cur = r.rlim_max;
+	  if (DRH_SETRLIMIT(RLIMIT_CORE, &r) == 0) {
+	    int tid = get_thread_id_();
+	    fprintf(stderr,"signal_gencore(sig=%d): pid#%d, tid#%d : Calling abort() ...\n",
+		    sig, pid, tid);
+	    abort(); /* Dump core, too */
+	  }
+	}
+      }
+      /* Should never end up here */
+      _exit(1);
+    } /* if (sig >= 1 && sig <= NSIG && sig == opt_gencore_signal) */
+  }
+}
+
+static void 
+signal_harakiri(int sig SIG_EXTRA_ARGS)
+{
+  /* A signal handler that will force to exit the current thread immediately for sure */
+  raise(SIGKILL); /* Use raise, not RAISE here */
+  _exit(1); /* Should never reach here, bu' in case it does, then ... */
+}
+
+static void 
+signal_drhook(int sig SIG_EXTRA_ARGS)
+{
+  /* signal(sig, SIG_IGN); */
+  if (signals_set && sig >= 1 && sig <= NSIG) { 
+    /* Signal catching */
+    int nsigs = (++signal_handler_called); /* A tiny chance for a race condition between threads */
+    drhook_sig_t *sl = &siglist[sig];
+    drhook_sigfunc_t u;
+    sigset_t newmask, oldmask;
+    int tid = 0;
+
+    /*------------------------------------------------------------ 
+      Strategy:
+      - drhook intercepts most interrupts.
+      - 1st interupt will 
+        - call alarm(10) to try to make sure 2nd interrupt received
+        - try to call tracebacks and exit (which includes atexits)
+      - 2nd (and subsequent) interupts will 
+        - spin for 20 sec (to give 1st interrupt time to complete tracebacks) 
+        - and then call _exit (bypassing atexit)
+    ------------------------------------------------------------*/
+      
+    /* if (sig != SIGTERM) signal(SIGTERM, SIG_DFL); */  /* Let the default SIGTERM to occur */
+
+    if (nsigs == 1) {
+      /*---- First call to signal handler: call alarm(10), tracebacks,  exit ------*/
+      
+      JSETSIG(SIGALRM,1); /* This will now set another signal handler than signal_drhook */
+      alarm(10);
+      fprintf(stderr,
+	      "***Received signal = %d and ActivatED SIGALRM=%d and calling alarm(10), time =%8.2f\n",
+	      sig,SIGALRM,WALLTIME());
+      fflush(NULL);
+
+      { /* Enjoy some output (only from the first guy that came in) */
+	long long int hwm = gethwm_();
+	long long int rss = getrss_();
+	long long int maxstack = getmaxstk_();
+	long long int pag = getpag_();
+	rss /= 1048576;
+	hwm /= 1048576;
+	maxstack /= 1048576;
+	tid = get_thread_id_();
+	fprintf(stderr,
+		"[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Received signal :: %lldMB (heap),"
+		" %lldMB (rss), %lldMB (stack), %lld (paging), nsigs %d, time %8.2f\n",
+		myproc,tid,pid,sig,sl->name, hwm, rss, maxstack, pag, nsigs, WALLTIME());
+	fflush(NULL);
+      }
+    }
+    else if (nsigs > max_threads) {
+      signal_harakiri(sig SIG_PASS_EXTRA_ARGS);
+    }
+
+    /*----- 2nd (and subsequent) calls to signal handler: spin 20 sec,  _exit ---------*/
+    if (nsigs > 1) {
+      if (nsigs < max_threads) {
+	double tt, ttt=0;
+	int is;
+	tt=WALLTIME();
+	while ( ttt < 20.0 ) {
+	  for ( is=0; is<100000000; is++) {
+	    tt=tt+0.01; 
+	    tt=tt-0.01;
+	  }
+	  ttt=WALLTIME()-tt;
+	}
+	fprintf(stderr,"tid#%d calling _exit with sig=%d, time =%8.2f\n",tid,sig,WALLTIME());
+	fflush(NULL);
+      }
+      signal_harakiri(sig SIG_PASS_EXTRA_ARGS);
+    }
+
+#ifdef RS6K
+    /*-- llcancel attempted but sometimes hangs ---
+    {
+      char *env = getenv("LOADL_STEP_ID");
+      if (env) {
+        char *cancel = "delayed_llcancel ";
+	char cmd[80];
+	sprintf(cmd,"%s %s &",cancel,env);
+	fprintf(stderr,"tid#%d issuing command: %s, time =%8.2f\n",tid,cmd,WALLTIME());
+	fflush(NULL);
+	system(cmd);
+      }
+    }
+    ------------------------------------*/
+#endif
+
+    u.func3args = signal_drhook;
+
+    sigfillset(&newmask);
+    /*
+    sigemptyset(&newmask);
+    sigaddset(&newmask, sig);
+    */
+
+    /* Start critical region (we don't want any signals to interfere while doing this) */
+    /* sigprocmask(SIG_BLOCK, &newmask, &oldmask); */
+
+    if (sl->ignore_atexit) signal_handler_ignore_atexit++;
+
+    { /* Print Dr.Hook traceback */
+      const int ftnunitno = 0; /* stderr */
+      const int print_option = 2; /* calling tree */
+      int level = 0;
+      int is;
+      fprintf(stderr,"tid#%d starting drhook traceback, time =%8.2f\n",tid,WALLTIME());
+      fflush(NULL);
+      c_drhook_print_(&ftnunitno, &tid, &print_option, &level);
+      fflush(NULL);
+      fprintf(stderr,"tid#%d starting sigdump traceback, time =%8.2f\n",tid,WALLTIME());
+      fflush(NULL);
+#ifdef RS6K
+      xl__sigdump(sig SIG_PASS_EXTRA_ARGS); /* Can't use xl__trce(...), since it also stops */
+#endif
+#ifdef INTEL
+      intel_trbk_(); /* from ../utilities/gentrbk.F90 */
+#endif
+#if defined(NECSX)
+      necsx_trbk_("signal_drhook",13); /* from ../utilities/gentrbk.F90 */
+#endif
+#ifdef VPP
+#if defined(SA_SIGINFO) && SA_SIGINFO > 0
+      _TraceCalls(sigcontextptr); /* Need VPP's libmp.a by Pierre Lagier */
+#endif
+#endif
+#if (defined(LINUX) || defined(SUN4)) && !defined(XT3) && !defined(XD1)
+      gdb__sigdump(sig SIG_PASS_EXTRA_ARGS);
+#endif
+      fflush(NULL);
+      fprintf(stderr,"Done tracebacks, calling exit with sig=%d, time =%8.2f\n",sig,WALLTIME());
+      fflush(NULL);
+      if (sig != SIGABRT && sig != SIGTERM) ABOR1("Dr.Hook calls ABOR1 ...");
+      _exit(1);
+    }
+    /* sigprocmask(SIG_SETMASK, &oldmask, 0); */
+    /* End critical region : the original signal state restored */
+
+#if 1
+    /*-------------- Following code currently redundant---------------*/
+    if (opt_propagate_signals &&
+	sl->old.sa_handler != SIG_DFL && 
+	sl->old.sa_handler != SIG_IGN && 
+	sl->old.sa_handler != u.func1args) {
+      /*
+      fprintf(stderr,
+	      ">>%s(at 0x%x): Calling previous signal handler in chain at 0x%x (if possible)\n",
+	      "signal_drhook",signal_drhook,sl->old.sa_handler); 
+      u.func1args = sl->old.sa_handler;
+      u.func3args(sig SIG_PASS_EXTRA_ARGS);
+      */
+      fprintf(stderr,
+              ">>%s(at 0x%x): Do not call previous signal handler in chain at 0x%x\n",
+              "signal_drhook",signal_drhook,sl->old.sa_handler);
+    }
+    /* Make sure that the process really exits now */
+    fprintf(stderr,
+	    "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Error exit due to this signal\n",
+	    myproc,tid,pid,sig,sl->name);
+    fflush(NULL);
+    _exit(1);
+    /*---------------- End of redundant code---------------------*/
+#endif
+
+  }
+  else {
+    fprintf(stderr,
+	    "%s(at 0x%x): Invalid signal#%d or signals/this signal not set (%d)\n",
+	    "signal_drhook",signal_drhook,sig,signals_set);
+#ifdef RS6K
+    xl__sigdump(sig SIG_PASS_EXTRA_ARGS);
+#endif
+#ifdef INTEL
+    intel_trbk_(); /* from ../utilities/gentrbk.F90 */
+#endif
+#ifdef VPP
+#if defined(SA_SIGINFO) && SA_SIGINFO > 0
+    _TraceCalls(sigcontextptr); /* Need VPP's libmp.a by Pierre Lagier */
+#endif
+#endif
+#if (defined(LINUX) || defined(SUN4)) && !defined(XT3) && !defined(XD1)
+    gdb__sigdump(sig SIG_PASS_EXTRA_ARGS);
+#endif
+    fflush(NULL);
+    _exit(1);
+  }
+}
+
+void
+c_drhook_set_mpi_()
+{
+  dr_hook_procinfo_(&myproc, &nproc);
+}
+
+void
+c_drhook_not_mpi_()
+{
+  /* Emulates in a one call : export DR_HOOK_NOT_MPI=1" */
+  /* To have a desired effect, call BEFORE the very first call to DR_HOOK */
+  static char s[] = "DR_HOOK_NOT_MPI=1"; /* note: must be static */
+  putenv(s);
+}
+
+
+/*--- signal_drhook_init ---*/
+
+static void 
+signal_drhook_init(int enforce)
+{
+  char *env = getenv("DR_HOOK_SILENT");
+  int silent = env ? atoi(env) : 0;
+  int j;
+  dr_hook_procinfo_(&myproc, &nproc);
+  if (myproc < 1) myproc = 1; /* Just to enable output as if myproc was == 1 */
+  /* Signals may not yet been set, since MPI not initialized 
+     Only enforce-parameter can enforce to set these => no output on myproc=1 */
+  if (!enforce && (myproc < 1 || nproc < 0)) return; 
+  if (signals_set) return; /* Extra safety */
+  for (j=1; j<=NSIG; j++) { /* Initialize */
+    drhook_sig_t *sl = &siglist[j];
+    sl->active = 0;
+    sprintf(sl->name, "DR_HOOK_SIG#%d", j);
+    sl->ignore_atexit = 0;
+  }
+  ignore_signals(silent); /* These signals will not be seen by DR_HOOK */
+  SETSIG(SIGABRT,0); /* Good to be first */
+  SETSIG(SIGBUS,0);
+  SETSIG(SIGSEGV,0);
+#if defined(SIGEMT)
+  SETSIG(SIGEMT,0);
+#endif
+#if defined(SIGSTKFLT)
+  SETSIG(SIGSTKFLT,0); /* Stack fault */
+#endif
+#if !defined(NECSX)
+  /* For the moment turn off these on NEC SX ... */
+  SETSIG(SIGFPE,0);
+  SETSIG(SIGILL,0);
+#endif
+  SETSIG(SIGTRAP,0); /* should be switched off when used with debuggers */
+  SETSIG(SIGINT,0);
+  SETSIG(SIGQUIT,0);
+  SETSIG(SIGTERM,0);
+#if defined(SIGIOT)
+  SETSIG(SIGIOT,0);  /* Same as SIGABRT; Used to be a typo SIGIO ;-( */
+#endif
+  SETSIG(SIGXCPU,1); /* ignore_atexit == 1 i.e. no profile info via atexit() */
+#if defined(SIGDANGER)
+  SETSIG(SIGDANGER,1); /* To catch the place where paging space gets dangerously low */
+#endif
+  SETSIG(SIGSYS,0);
+  /* SETSIG(SIGCHLD); we may not want to catch this either; may interfere parallel processing */
+  /* -- not active
+  SETSIG(SIGCHLD);
+  SETSIG(SIGHUP);
+  SETSIG(SIGCONT);
+  */
+#if defined(SIGCORE)
+  SETSIG(SIGCORE,0); /* NEC SX core dumping */
+#endif
+#if defined(SIGDEAD)
+  SETSIG(SIGDEAD,0); /* NEC SX dead lock */
+#endif
+#if defined(SIGXMEM)
+  SETSIG(SIGXMEM,0); /* NEC SX exceeded memory size limit */
+#endif
+#if defined(SIGXDSZ)
+  SETSIG(SIGXDSZ,0); /* NEC SX exceeded data size limit */
+#endif
+#if defined(SIGMEM32)
+  SETSIG(SIGMEM32,0); /* NEC SX exceeded memory size limit of 32KB */
+#endif
+#if defined(SIGNMEM)
+  SETSIG(SIGNMEM,0); /* NEC SX exce error for no memory */
+#endif
+#if defined(SIGXABT)
+  SETSIG(SIGXABT,0); /* NEC SX distributed parallel program aborted */
+#endif
+  /*
+    #if defined(SIG)
+    SETSIG(SIG,0);
+    #endif
+  */
+  catch_signals(silent); /* Additional signals to be seen by DR_HOOK */
+  if (opt_gencore > 0 && opt_gencore_signal >= 1 && opt_gencore_signal <= NSIG) {
+    drhook_sigfunc_t u;
+    u.func3args = signal_gencore;
+    signal(opt_gencore_signal, u.func1args); /* A facility to dump core */
+  }
+  signals_set = 1; /* Signals are set now */
+}
+
+/*--- get_mon_out ---*/
+
+static char *
+get_mon_out(int me)
+{
+  char *s = mon_out;
+  if (mon_out_procs == me || (mon_out_procs == -1 && me >= 1 && me <= nproc)) {
+    if (!mon_out) mon_out = strdup_drhook("drhook.prof.%d");
+    s = malloc_drhook((strlen(mon_out) + 20) * sizeof(*s));
+    sprintf(s,mon_out,me);
+  }
+  if (!s) s = strdup_drhook("drhook.prof.0");
+  return s;
+}
+
+/*--- get_memmon_out ---*/
+
+static char *
+get_memmon_out(int me)
+{
+  char *s = NULL;
+  char *p = get_mon_out(me);
+  if (p) {
+    s = malloc_drhook((strlen(p) + 5) * sizeof(*s));
+    sprintf(s,"%s-mem",p);
+  }
+  if (!s) s = strdup_drhook("drhook.prof.0-mem");
+  return s;
+}
+
+/*--- process_options ---*/
+
+static void do_prof();
+
+static void process_options();
+
+void /* Fortran callable */
+c_drhook_process_options_(const int *lhook, const int *Myproc, const int *Nproc)
+{
+    c_drhook_set_lhook_(lhook);
+    if (Myproc) myproc = *Myproc;
+    if (Nproc)  nproc  = *Nproc;
+    process_options();
+}
+
+static void
+process_options()
+{
+  char *env;
+  FILE *fp = stderr;
+  static int processed = 0;
+
+  if (processed) return;
+
+  env = getenv("DR_HOOK_SHOW_PROCESS_OPTIONS");
+  if (env) {
+    int ienv = atoi(env);
+    if (ienv == 0) fp = NULL;
+  }
+
+  env = getenv("DR_HOOK_PROFILE");
+  if (env) {
+    char *s = calloc_drhook(strlen(env) + 10, sizeof(*s));
+    strcpy(s,env);
+    if (!strchr(env,'%')) strcat(s,".%d");
+    mon_out = strdup_drhook(s);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_PROFILE=%s\n",mon_out);
+    free_drhook(s);
+  }
+
+  env = getenv("DR_HOOK_PROFILE_PROC");
+  if (env) {
+    mon_out_procs = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_PROFILE_PROC=%d\n",mon_out_procs);
+  }
+
+  env = getenv("DR_HOOK_PROFILE_LIMIT");
+  if (env) {
+    percent_limit = atof(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_PROFILE_LIMIT=%.3f\n",percent_limit);
+  }
+
+  env = getenv("DR_HOOK_CALLPATH_INDENT");
+  if (env) {
+    callpath_indent = atoi(env);
+    if (callpath_indent < 1 || callpath_indent > 8) callpath_indent = callpath_indent_default;
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_CALLPATH_INDENT=%d\n",callpath_indent);
+  }
+
+  env = getenv("DR_HOOK_CALLPATH_DEPTH");
+  if (env) {
+    callpath_depth = atoi(env);
+    if (callpath_depth < 0) callpath_depth = callpath_depth_default;
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_CALLPATH_DEPTH=%d\n",callpath_depth);
+  }
+
+  env = getenv("DR_HOOK_CALLTRACE");
+  if (env) {
+    opt_calltrace = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_CALLTRACE=%d\n",opt_calltrace);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE");
+  if (env) {
+    opt_timeline = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE=%d\n",opt_timeline);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE_THREAD");
+  if (env) {
+    opt_timeline_thread = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE_THREAD=%d\n",opt_timeline_thread);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE_FORMAT");
+  if (env) {
+    opt_timeline_format = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE_FORMAT=%d\n",opt_timeline_format);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE_UNITNO");
+  if (env) {
+    opt_timeline_unitno = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE_UNITNO=%d\n",opt_timeline_unitno);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE_FREQ");
+  if (env) {
+    opt_timeline_freq = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE_FREQ=%lld\n",opt_timeline_freq);
+  }
+
+  env = getenv("DR_HOOK_TIMELINE_MB");
+  if (env) {
+    opt_timeline_MB = atof(env);
+    if (opt_timeline_MB < 0) opt_timeline_MB = 1.0;
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_TIMELINE_MB=%d\n",opt_timeline_MB);
+  }
+
+  env = getenv("DR_HOOK_HASHBITS");
+  if (env) {
+    int value = atoi(env);
+    if (value < 1) value = 1;
+    else if (value > NHASHMAX) value = NHASHMAX;
+    nhash = value;
+    hashsize = HASHSIZE(nhash);
+    hashmask = HASHMASK(nhash);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_HASHBITS=%d\n",nhash);
+  }
+
+  env = getenv("DR_HOOK_GENCORE");
+  if (env) {
+    opt_gencore = atoi(env);
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_GENCORE=%d\n",opt_gencore);
+  }
+
+  env = getenv("DR_HOOK_GENCORE_SIGNAL");
+  if (env) {
+    int itmp = atoi(env);
+    if (itmp >= 1 && itmp <= NSIG && itmp != SIGABRT) {
+      opt_gencore_signal = itmp;
+    }
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_GENCORE_SIGNAL=%d\n",opt_gencore_signal);
+  }
+
+  env = getenv("DR_HOOK_HPMSTOP");
+  if (env) {
+    char *s = strdup_drhook(env);
+    long long int a;
+    double b;
+    int n = 0;
+    env = s;
+    while (*env) {
+      if (isspace(*env) || *env == ',') *env = ' ';
+      env++;
+    }
+    n = sscanf(s,"%lld %lf",&a,&b);
+    if (n >= 1) opt_hpmstop_threshold = a;
+    if (n >= 2) opt_hpmstop_mflops = b;
+    if (fp) fprintf(fp,">>>process_options(): DR_HOOK_HPMSTOP=%lld,%.15g\n",
+	    opt_hpmstop_threshold,opt_hpmstop_mflops);
+    free_drhook(s);
+  }
+
+  env = getenv("DR_HOOK_OPT");
+  if (env) {
+    const char delim[] = ", \t/";
+    char *comma = ">>>process_options(): DR_HOOK_OPT=\"";
+    char *s = strdup_drhook(env);
+    char *p = s;
+    while (*p) {
+      if (islower(*p)) *p = toupper(*p);
+      p++;
+    } 
+    p = strtok(s,delim);
+    /* if (p) if (fp) fprintf(fp,">>>process_options(): DR_HOOK_OPT=\""); */
+    while (p) {
+      /* Assume that everything is OFF by default */
+      if (strequ(p,"ALL")) { /* all except profiler data */
+	opt_gethwm = opt_getstk = opt_getrss = opt_getpag = opt_walltime = opt_cputime = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"ALL"); comma = ",";
+      }
+      else if (strequ(p,"MEM") || strequ(p,"MEMORY")) {
+	opt_gethwm = opt_getstk = opt_getrss = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"MEMORY"); comma = ",";
+      }
+      else if (strequ(p,"TIME") || strequ(p,"TIMES")) {
+	opt_walltime = opt_cputime = 1;
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"TIMES"); comma = ",";
+      }
+      else if (strequ(p,"HWM") || strequ(p,"HEAP")) {
+	opt_gethwm = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"HEAP"); comma = ",";
+      }
+      else if (strequ(p,"STK") || strequ(p,"STACK")) {
+	opt_getstk = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"STACK"); comma = ",";
+      }
+      else if (strequ(p,"RSS")) {
+	opt_getrss = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"RSS"); comma = ",";
+      }
+      else if (strequ(p,"PAG") || strequ(p,"PAGING")) {
+	opt_getpag = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"PAGING"); comma = ",";
+      }
+      else if (strequ(p,"WALL") || strequ(p,"WALLTIME")) {
+	opt_walltime = 1;
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"WALLTIME"); comma = ",";
+      }
+      else if (strequ(p,"CPU") || strequ(p,"CPUTIME")) {
+	opt_cputime = 1;
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"CPUTIME"); comma = ",";
+      }
+      else if (strequ(p,"CALLS") || strequ(p,"COUNT")) {
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"CALLS"); comma = ",";
+      }
+      else if (strequ(p,"MEMPROF")) {
+	opt_memprof = 1;
+	drhook_memtrace = 1;
+	opt_gethwm = opt_getstk = opt_getrss = 1;
+	opt_getpag = 1;
+	opt_calls = 1;
+	any_memstat++;
+	if (fp) fprintf(fp,"%s%s",comma,"MEMPROF"); comma = ",";
+      }
+      else if (strequ(p,"PROF") || strequ(p,"WALLPROF")) {
+	opt_wallprof = 1;
+	opt_walltime = 1;
+	opt_cpuprof = 0; /* Note: Switches cpuprof OFF */
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"WALLPROF"); comma = ",";
+      }
+      else if (strequ(p,"CPUPROF")) {
+	opt_cpuprof = 1;
+	opt_cputime = 1;
+	opt_wallprof = 0; /* Note: Switches walprof OFF */
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"CPUPROF"); comma = ",";
+      }
+      else if (strequ(p,"HPM") || strequ(p,"HPMPROF") || strequ(p,"MFLOPS")) {
+	opt_hpmprof = 1;
+	opt_wallprof = 1; /* Note: Implies wallprof (or prof), not cpuprof */
+	opt_walltime = 1;
+	opt_cpuprof = 0;  /* Note: Switches cpuprof OFF */
+	opt_calls = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"HPMPROF"); comma = ",";
+      }
+      else if (strequ(p,"TRIM")) {
+	opt_trim = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"TRIM"); comma = ",";
+      }
+      else if (strequ(p,"SELF")) {
+	opt_self = 2;
+	if (fp) fprintf(fp,"%s%s",comma,"SELF"); comma = ",";
+      }
+      else if (strequ(p,"NOSELF")) {
+	opt_self = 0;
+	if (fp) fprintf(fp,"%s%s",comma,"NOSELF"); comma = ",";
+      }
+      else if (strequ(p,"NOPROP") || strequ(p,"NOPROPAGATE") ||
+	       strequ(p,"NOPROPAGATE_SIGNALS")) {
+	opt_propagate_signals = 0;
+	if (fp) fprintf(fp,"%s%s",comma,"NOPROPAGATE_SIGNALS"); comma = ",";
+      }
+      else if (strequ(p,"NOSIZE") || strequ(p,"NOSIZEINFO")) {
+	opt_sizeinfo = 0;
+	if (fp) fprintf(fp,"%s%s",comma,"NOSIZEINFO"); comma = ",";
+      }
+      else if (strequ(p,"CLUSTER") || strequ(p,"CLUSTERINFO")) {
+	opt_clusterinfo = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"CLUSTERINFO"); comma = ",";
+      }
+      else if (strequ(p,"CALLPATH")) {
+	opt_callpath = 1;
+	if (fp) fprintf(fp,"%s%s",comma,"CALLPATH"); comma = ",";
+      }
+      p = strtok(NULL,delim);
+    }
+    free_drhook(s);
+    if (*comma == ',') if (fp) fprintf(fp,"\"\n");
+    if (opt_wallprof || opt_cpuprof || opt_memprof || opt_timeline) {
+      atexit(do_prof);
+    }
+  }
+  else {
+    if (opt_timeline) atexit(do_prof);
+  } /* if (env) */
+
+  processed = 1;
+}
+
+/*--- trim ---*/
+
+static const char *
+trim(const char *name, int *n)
+{
+  const char *from;
+  int len;
+  int name_len = *n;
+  while (*name && isspace(*name) && name_len > 0) {
+    /* skip leading blanks */
+    name++;
+    name_len--;
+  }
+  len = 0;
+  from = name;
+  while (*from && !isspace(*from) && name_len > 0) {
+    /* find first space point, if any */
+    from++;
+    len++;
+    name_len--;
+  }
+  *n = len;
+  if (!name) {
+    /* Never actually called (unless a true fatality) */
+    ABOR1("***Fatal error in drhook.c:trim()-function");
+  }
+  return name;
+}
+
+/*--- insertkey ---*/
+
+static drhook_key_t *
+insertkey(int tid, const drhook_key_t *keyptr_in)
+{
+  drhook_key_t *keyptr = NULL;
+  if (tid >= 1 && tid <= numthreads) {
+    /* no trimming available for this; just raw eval & insert */
+    unsigned int hash = hashfunc(keyptr_in->name, keyptr_in->name_len);
+    keyptr = &keydata[tid-1][hash];
+    for (;;) {
+      if (!keyptr->name) { /* A free slot */
+	memcpy(keyptr,keyptr_in,sizeof(*keyptr));
+	keyptr->next = NULL;
+	break;
+      }
+      else {
+	if (!keyptr->next) {
+	  keyptr->next = calloc_drhook(1, sizeof(drhook_key_t)); /* chaining */
+	}
+	keyptr = keyptr->next;
+      }  /* if (!keyptr->name) ... else ... */
+    } /* for (;;) */
+  } /* if (tid >= 1 && tid <= numthreads) */
+  return keyptr;
+}
+
+/*--- getkey ---*/
+
+static drhook_key_t *
+getkey(int tid, const char *name, int name_len,
+       const char *filename, int filename_len,
+       const double *walltime, const double *cputime,
+       const equivalence_t *callpath, int callpath_len,
+       int *free_callpath)
+{
+  drhook_key_t *keyptr = NULL;
+  if (tid >= 1 && tid <= numthreads) {
+    unsigned int hash, fullhash;
+    if (opt_trim) name = trim(name, &name_len);
+    hash = hashfunc(name, name_len);
+    if (callpath) {
+      callpath_hashfunc(hash, callpath, callpath_len, &fullhash);
+#ifdef DEBUG
+      fprintf(stderr,
+	      "getkey: name='%.*s', name_len=%d, callpath_len=%d, fullhash=%u\n",
+	      name_len, name, name_len, callpath_len, fullhash);
+#endif
+    }
+    keyptr = &keydata[tid-1][hash];
+    for (;;) {
+      int found = 0;
+      if (!keyptr->name) { /* A free slot */
+	keyptr->name = malloc_drhook((name_len+1)*sizeof(*name));
+	keyptr->name_len = name_len;
+	if (opt_trim) {
+	  const char *from = name;
+	  char *to = keyptr->name;
+	  int len = name_len;
+	  for (; len>0; from++, len--) {
+	    *to++ = islower(*from) ? toupper(*from) : *from;
+	  }
+	  *to = 0;
+	}
+	else {
+	  memcpy(keyptr->name, name, name_len);
+	  keyptr->name[name_len] = 0;
+	}
+	if (filename && *filename && filename_len > 0) {
+	  char *psave = NULL;
+	  char *p = psave = malloc_drhook((filename_len+1)*sizeof(*filename));
+	  memcpy(p, filename, filename_len);
+	  p[filename_len] = 0;
+	  { /* Strip out dirname */
+	    char *s = strrchr(p,'/');
+	    if (s) p = s+1;
+	  }
+	  keyptr->filename = strdup_drhook(p);
+	  free_drhook(psave);
+	}
+	if (callpath) {
+	  if (free_callpath) *free_callpath = 0;
+	  keyptr->callpath = callpath;
+	  keyptr->callpath_len = callpath_len;
+	  keyptr->callpath_fullhash = fullhash;
+	}
+	found = 1;
+      }
+      if (found || 
+	  (keyptr->name_len == name_len &&
+	   (!callpath || (callpath && keyptr->callpath && 
+			  keyptr->callpath_len == callpath_len &&
+			  keyptr->callpath_fullhash == fullhash)) &&
+	   ((!opt_trim && *keyptr->name == *name && strnequ(keyptr->name, name, name_len)) ||
+	    (opt_trim && strncasecmp(keyptr->name, name, name_len) == 0)))) {
+	if (opt_walltime) keyptr->wall_in = walltime ? *walltime : WALLTIME();
+	if (opt_cputime) keyptr->cpu_in  = cputime ? *cputime : CPUTIME();
+	if (any_memstat) memstat(keyptr,&tid,1);
+	if (opt_calls) {
+	  keyptr->calls++;
+	  keyptr->status++;
+	}
+	insert_calltree(tid, keyptr);
+	break; /* for (;;) */
+      }
+      else {
+	if (!keyptr->next) {
+	  keyptr->next = calloc_drhook(1, sizeof(drhook_key_t)); /* chaining */
+	}
+	keyptr = keyptr->next;
+      }  /* if (found ...) else ... */
+    } /* for (;;) */
+    curkeyptr[tid-1] = keyptr;
+  } /* if (tid >= 1 && tid <= numthreads) */
+  return keyptr;
+}
+
+/*--- putkey ---*/
+
+static void
+putkey(int tid, drhook_key_t *keyptr, const char *name, int name_len,
+       int sizeinfo,
+       double *walltime, double *cputime)
+{
+  const int sig = SIGABRT;
+  const char sl_name[] = "SIGABRT";
+  drhook_calltree_t *treeptr = (tid >= 1 && tid <= numthreads) ? thiscall[tid-1] : NULL;
+  if (!treeptr || !treeptr->active || treeptr->keyptr != keyptr) {
+    char *s;
+    unsigned int hash;
+    if (opt_trim) name = trim(name, &name_len);
+    hash = hashfunc(name, name_len);
+    s = strdup2_drhook(name,name_len);
+    if (opt_trim) {
+      char *p = s;
+      while (*p) {
+	if (islower(*p)) *p = toupper(*p);
+	p++;
+      }
+    }
+    fprintf(stderr,
+	    "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Dr.Hook has detected an invalid"
+	    " key-pointer/handle while leaving the routine '%s' [hash=%u]\n",
+	    myproc,tid,pid,sig,sl_name,s,hash);
+
+    if (treeptr) {
+      equivalence_t u;
+
+      u.keyptr = treeptr->keyptr;
+      hash = (u.keyptr && u.keyptr->name) ? hashfunc(u.keyptr->name,u.keyptr->name_len) : 0;
+      fprintf(stderr,
+	      "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Expecting the key-pointer=0x%llx"
+	      " and treeptr->active-flag = 1\n",
+	      myproc,tid,pid,sig,sl_name,u.ull);
+      fprintf(stderr,
+	      "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: A probable routine missing the closing"
+	      " DR_HOOK-call is '%s' [hash=%u]\n",
+	      myproc,tid,pid,sig,sl_name,
+	      (u.keyptr && u.keyptr->name) ? u.keyptr->name : NIL, hash);
+
+      u.keyptr = keyptr;
+      hash = (u.keyptr && u.keyptr->name) ? hashfunc(u.keyptr->name,u.keyptr->name_len) : 0;
+      fprintf(stderr,
+	      "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Got a key-pointer=0x%llx"
+	      " and treeptr->active-flag = %d\n",
+	      myproc,tid,pid,sig,sl_name,u.ull,treeptr->active);
+      fprintf(stderr,
+	      "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: This key-pointer maybe associated with"
+	      " the routine '%s' [hash=%u]\n",
+	      myproc,tid,pid,sig,sl_name,
+	      (u.keyptr && u.keyptr->name) ? u.keyptr->name : NIL, hash);
+
+      u.keyptr = curkeyptr[tid-1];
+      hash = (u.keyptr && u.keyptr->name) ? hashfunc(u.keyptr->name,u.keyptr->name_len) : 0;
+      fprintf(stderr,
+	      "[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: The current key-pointer (=0x%llx) thinks"
+	      " it maybe associated with the routine '%s' [hash=%u]\n",
+	      myproc,tid,pid,sig,sl_name,
+	      u.ull,
+	      (u.keyptr && u.keyptr->name) ? u.keyptr->name : NIL, hash);
+    }
+    free_drhook(s);
+    fprintf(stderr,"[myproc#%d,tid#%d,pid#%d,signal#%d(%s)]: Aborting...\n",myproc,tid,pid,sig,sl_name);
+    RAISE(SIGABRT);
+  }
+  else if (tid >= 1 && tid <= numthreads) {
+    double delta_wall = 0;
+    double delta_cpu  = 0;
+    if (any_memstat) memstat(keyptr,&tid,0);
+    if (opt_calls)   keyptr->status--;
+    if (opt_sizeinfo && sizeinfo > 0) {
+      if (keyptr->sizeinfo == 0) { /* First time */
+	keyptr->min_sizeinfo = sizeinfo;
+	keyptr->max_sizeinfo = sizeinfo;
+      }
+      else {
+	keyptr->min_sizeinfo = MIN(keyptr->min_sizeinfo, sizeinfo);
+	keyptr->max_sizeinfo = MAX(keyptr->max_sizeinfo, sizeinfo);
+      }
+      keyptr->sizeinfo += sizeinfo;
+    }
+    if (opt_cputime && cputime) {
+      *cputime = CPUTIME();
+      delta_cpu = *cputime - keyptr->cpu_in;
+    }
+    if (opt_walltime && walltime) {
+      *walltime = WALLTIME();
+      delta_wall = *walltime - keyptr->wall_in;
+    }
+    if (opt_walltime) keyptr->delta_wall_all += delta_wall;
+    if (opt_cputime)  keyptr->delta_cpu_all  += delta_cpu;
+    remove_calltree(tid, keyptr, &delta_wall, &delta_cpu);
+  }
+}
+    
+/*--- init_drhook ---*/
+
+static void
+init_drhook(int ntids)
+{
+  if (numthreads == 0 || !keydata || !calltree || !keyself || !overhead || !curkeyptr) {
+    int j;
+    if (pid == -1) { /* Ensure that just called once */
+      {
+	/* Invoke once : timers, memory counters etc. to "wake them up" */
+	(void) WALLTIME();
+	(void) CPUTIME();
+	(void) gethwm_();
+	(void) getrss_();
+	(void) getstk_();
+	(void) getmaxstk_();
+	(void) getpag_();
+      }
+#ifdef RS6K
+      irtc_start = irtc();
+#endif
+#ifdef CRAYXT
+      dclock_start = dclock();
+#endif
+#if defined(SV2) || defined(XD1) || defined(XT3)
+#if defined(SV2)
+      irtc_start = _rtc();
+#else
+      irtc_start = irtc_();
+#endif
+      my_irtc_rate = irtc_rate_();
+      my_inv_irtc_rate = 1.0/my_irtc_rate;
+#endif
+      start_stamp = timestamp();
+      {
+	char *env = getenv("DR_HOOK_SHOW_LOCK"); /* export DR_HOOK_SHOW_LOCK=1 to show the lock-info */
+	int konoff = env ? atoi(env) : 0;
+	int kret = 0;
+	if (konoff == 1) coml_set_debug_(&konoff, &kret);
+	INIT_LOCKID_WITH_NAME(&DRHOOK_lock,"drhook.c:DRHOOK_lock");
+	if (kret != 0) {
+	  konoff = 0;
+	  coml_set_debug_(&konoff, &kret);
+	}
+      }
+#if defined(NECSX)
+      { /* If C-programs compiled with -traceback, then NEC/F90 
+	   MESPUT-call will also includes C-routines in the traceback if 
+	   in addition 'export C_TRACEBACK=YES' */
+	char *env = getenv("C_TRACEBACK");
+	if (!env) {
+	  /* Override only if C_TRACEBACK hadn't already been defined */
+	  static char s[] = "C_TRACEBACK=YES"; /* note: must be static */
+	  putenv(s);
+	}
+      }
+#endif
+      ec_set_umask_();
+      pid = getpid();
+      process_options();
+      drhook_lhook = 1;
+    }
+    if (!keydata) {
+      keydata = malloc_drhook(sizeof(**keydata) * ntids);
+      for (j=0; j<ntids; j++) {
+	keydata[j] = calloc_drhook(hashsize, sizeof(drhook_key_t));
+      }
+    }
+    if (!calltree) {
+      calltree = malloc_drhook(sizeof(**calltree) * ntids);
+      thiscall = malloc_drhook(sizeof(**thiscall) * ntids);
+      for (j=0; j<ntids; j++) {
+	thiscall[j] = calltree[j] = calloc_drhook(1,sizeof(drhook_calltree_t));
+      }
+    }
+    if (!keyself && opt_self && (opt_wallprof || opt_cpuprof || opt_hpmprof)) {
+      const char *name = "$drhook";
+      int name_len = strlen(name);
+      keyself = malloc_drhook(sizeof(**keyself) * ntids);
+      for (j=0; j<ntids; j++) {
+	drhook_key_t *keyptr = keyself[j] = calloc_drhook(1,sizeof(drhook_key_t));
+	keyptr->name = strdup_drhook(name);
+	keyptr->name_len = name_len;
+      }
+    }
+    if (!overhead) {
+      overhead = calloc_drhook(ntids,sizeof(*overhead));
+    }
+    if (!curkeyptr) {
+      curkeyptr = malloc_drhook(sizeof(**curkeyptr) * ntids);
+      for (j=0; j<ntids; j++) {
+	curkeyptr[j] = NULL;
+      }
+    }
+    numthreads = ntids;
+    signal_drhook_init(1);
+    if (!timeline) {
+      if (opt_timeline_unitno >= 0 && opt_timeline_freq >= 1 &&
+	  (opt_timeline == myproc || opt_timeline == -1)) {
+	timeline = calloc_drhook(ntids, sizeof(*timeline));
+      }
+      if (timeline) drhook_memtrace = 1;
+      if (timeline) {
+	/* The first timeline-call */
+	const int ftnunitno = opt_timeline_unitno;
+	const int master = 1;
+	const int print_option = +7;
+	int initlev = 0;
+	c_drhook_print_(&ftnunitno, &master, &print_option, &initlev);
+      }
+    }
+    init_hpm(1); /* First thread */
+  }
+}
+
+/*-- overhead-macro --*/
+
+#define OVERHEAD(tid,walltime_in,cputime_in,delta,calc_delta) \
+if (overhead && tid >= 1 && tid <= numthreads) { \
+  if (calc_delta) { \
+    if      (opt_walltime) delta = WALLTIME() - walltime_in; \
+    else if (opt_cputime)  delta = CPUTIME()  - cputime_in; \
+    else                   delta = 0; \
+  } \
+  overhead[tid-1] += delta; \
+}
+/*--- itself ---*/
+
+#define ITSELF_0 \
+  double delta = 0; \
+  drhook_key_t *keyptr_self = keyself ? itself(NULL,*thread_id,0,NULL,&walltime,&cputime) : NULL;
+
+#define ITSELF_1 \
+  if (keyptr_self) { \
+    (void) itself(keyptr_self,*thread_id,1,&delta,&walltime,&cputime); \
+    if (opt_wallprof) u.keyptr->delta_wall_child += delta; \
+    else              u.keyptr->delta_cpu_child  += delta; \
+    OVERHEAD(*thread_id,walltime,cputime,delta,0); \
+  } \
+  else { \
+    OVERHEAD(*thread_id,walltime,cputime,delta,1); \
+  }
+
+static drhook_key_t *
+itself(drhook_key_t *keyptr_self, 
+       int tid, int opt, double *delta_time, 
+       const double *walltime, const double *cputime) 
+{
+  drhook_key_t *keyptr = NULL;
+  if (keyself) {
+    keyptr = keyptr_self ? keyptr_self : keyself[tid-1];
+    if (opt == 0) {
+      if (opt_wallprof) keyptr->wall_in = walltime ? *walltime : WALLTIME();
+      else              keyptr->cpu_in = cputime ? *cputime : CPUTIME();
+      keyptr->calls++;
+    }
+    else if (opt == 1) {
+      double delta = 0;
+      if (opt_wallprof) {
+	delta = walltime ? (*walltime - keyptr->wall_in) : (WALLTIME() - keyptr->wall_in);
+	keyptr->delta_wall_all += delta;
+      }
+      else {
+	delta = cputime ? (*cputime - keyptr->cpu_in) : (CPUTIME() - keyptr->cpu_in);
+	keyptr->delta_cpu_all += delta;
+      }
+      if (delta_time) *delta_time = delta;
+    }
+  }
+  return keyptr;
+}
+
+/*--- commie -routines : adds "," i.e. comma after each 3 digit, e.g.:
+  1234567890 becomes more readable 1,234,567,890 */
+
+static void 
+lld_commie(long long int n, char sd[])
+{
+  const char comma = ',';
+  char s[DRHOOK_STRBUF];
+  char *p;
+  int len, ncommas;
+  sprintf(s,"%lld",n);
+  len = strlen(s);
+  ncommas = (len-1)/3;
+  if (ncommas > 0) {
+    char *pd = sd + len + ncommas;
+    *pd-- = 0;
+    p = s + len - 1;
+    len = 0;
+    while (p-s >= 0) {
+      *pd-- = *p--;
+      len++;
+      if (p-s >= 0 && len%3 == 0) *pd-- = comma;
+    }
+  }
+  else {
+    strcpy(sd,s);
+  }
+}
+
+static void 
+dbl_commie(double n, char sd[])
+{
+  const char comma = ',';
+  char s[DRHOOK_STRBUF];
+  char *p;
+  int len, ncommas;
+  sprintf(s,"%.0f",n);
+  len = strlen(s);
+  ncommas = (len-1)/3;
+  if (ncommas > 0) {
+    char *pd = sd + len + ncommas;
+    *pd-- = 0;
+    p = s + len - 1;
+    len = 0;
+    while (p-s >= 0) {
+      *pd-- = *p--;
+      len++;
+      if (p-s >= 0 && len%3 == 0) *pd-- = comma;
+    }
+  }
+  else {
+    strcpy(sd,s);
+  }
+}
+
+/*--- callpath as a "pathname" ---*/
+
+static void
+unroll_callpath(FILE *fp, int len, 
+		const equivalence_t *callpath, int callpath_len)
+{
+  if (fp && callpath && callpath_len > 0) {
+    int j;
+    for (j=0; j<callpath_len; callpath++, j++) {
+      if (callpath && callpath->keyptr && callpath->keyptr->name) {
+	const char *name = callpath->keyptr->name;
+	int name_len = callpath->keyptr->name_len;
+	len -= callpath_indent;
+	if (len < 0) len = 0;
+	fprintf(fp,"\n%*s%.*s",len," ",name_len,name);
+      }
+#ifdef DEBUG
+      else {
+	fprintf(fp,
+		"\n????callpath=0x%x, callpath->keyptr=0x%x,  callpath->keyptr->name='%s'",
+		callpath, callpath ? callpath->keyptr : 0,
+		(callpath && callpath->keyptr && callpath->keyptr->name) ?
+		callpath->keyptr->name : NIL);
+      }
+#endif
+    }
+  } /* if (fp) */
+}
+
+
+static equivalence_t *
+get_callpath(int tid, int *callpath_len)
+{
+  int depth = 0;
+  equivalence_t *callpath = NULL;
+  if (tid >= 1 && tid <= numthreads) {
+    const drhook_calltree_t *treeptr = thiscall[tid-1];
+    while (treeptr && treeptr->active && depth < callpath_depth) {
+      depth++;
+      treeptr = treeptr->prev;
+    }
+    if (depth > 0) {
+      int j = 0;
+      callpath = malloc_drhook(sizeof(*callpath) * depth);
+      treeptr = thiscall[tid-1];
+      while (treeptr && treeptr->active && j < callpath_depth) {
+	callpath[j].keyptr = treeptr->keyptr;
+	j++;
+	treeptr = treeptr->prev;
+      }
+    } /* if (depth > 0) */
+  } /* if (tid >= 1 && tid <= numthreads) */
+  if (callpath_len) *callpath_len = depth;
+  return callpath;
+}
+
+/*--- profiler output ---*/
+
+static int do_prof_off = 0;
+
+static void
+do_prof()
+{
+
+  /* to avoid recursive signals while atexit() (e.g. SIGXCPU) */
+  if (signal_handler_ignore_atexit) return; 
+
+  if (!do_prof_off && (opt_wallprof || opt_cpuprof)) {
+    /* CPU, wall-clock and/or MFlop/s profiling */
+    const int ftnunitno = 0;
+    const int master = 1;
+    const int print_option = 3;
+    int initlev = 0;
+    c_drhook_print_(&ftnunitno, &master, &print_option, &initlev);
+  }
+
+  if (!do_prof_off && opt_memprof) {
+    /* Memory profiling */
+    const int ftnunitno = 0;
+    const int master = 1;
+    const int print_option = 4;
+    int initlev = 0;
+    c_drhook_print_(&ftnunitno, &master, &print_option, &initlev);
+  }
+
+  if (!do_prof_off && timeline) {
+    /* The last timeline-call */
+    const int ftnunitno = opt_timeline_unitno;
+    const int master = 1;
+    const int print_option = -7;
+    int initlev = 0;
+    c_drhook_print_(&ftnunitno, &master, &print_option, &initlev);
+  }
+}
+
+/*--- Check watch points ---*/
+
+static void 
+check_watch(const char *label,
+	    const char *name,
+	    int name_len)
+{
+  if (watch) {
+    drhook_watch_t *p;
+    coml_set_lockid_(&DRHOOK_lock);
+    p = watch;
+    while (p) {
+      if (p->active) {
+	unsigned int crc32 = 0;
+	int calc_crc = 0;
+	const char *first_nbytes = p->ptr;
+	int changed = memcmp(first_nbytes,p->ptr,p->watch_first_nbytes);
+	if (!changed) {
+	  /* The first nbytes the same; checking if crc has changed ... */
+	  crc32_(p->ptr, &p->nbytes, &crc32);
+	  changed = (crc32 != p->crc32);
+	  calc_crc = 1;
+	}
+	if (changed) {
+	  int tid = get_thread_id_();
+	  if (!calc_crc) crc32_(p->ptr, &p->nbytes, &crc32);
+	  fprintf(stderr,
+		  "***%s: Watch point '%s' at address 0x%x on myproc#%d has changed"
+		  " (detected in tid#%d when %s routine %.*s) : new crc32=%u\n",
+		  p->abort_if_changed ? "Error" : "Warning",
+		  p->name, p->ptr, myproc, tid,
+		  label, name_len, name, crc32);
+	  if (p->abort_if_changed) {
+	    coml_unset_lockid_(&DRHOOK_lock); /* An important unlocking on Linux; otherwise hangs (until time-out) */
+	    RAISE(SIGABRT);
+	  }
+	  p->active = 0; /* No more these messages for this array */
+	  watch_count--;
+	}
+      }
+      p = p->next;
+    } /* while (p) */
+    coml_unset_lockid_(&DRHOOK_lock);
+  }
+}
+
+/*** PUBLIC ***/
+
+#define TIMERS \
+double walltime = opt_walltime ? WALLTIME() : 0; \
+double cputime  = opt_cputime ? CPUTIME()  : 0
+
+
+/*=== c_drhook_set_lhook_ ===*/
+
+void
+c_drhook_set_lhook_(const int *lhook)
+{
+  if (lhook) drhook_lhook = *lhook;
+}
+
+/*=== c_drhook_getenv_ ===*/
+
+void 
+c_drhook_getenv_(const char *s, 
+		 char *value,
+		 /* Hidden arguments */
+		 int slen,
+		 const int valuelen) 
+{
+  char *env = NULL;
+  char *p = malloc_drhook(slen+1);
+  if (!p) {
+    fprintf(stderr,"c_drhook_getenv_(): Unable to allocate %d bytes of memory\n", slen+1);
+    RAISE(SIGABRT);
+  }
+  memcpy(p,s,slen); 
+  p[slen]='\0';
+  memset(value, ' ', valuelen);
+  env = getenv(p);
+  if (env) {
+    int len = strlen(env);
+    if (valuelen < len) len = valuelen;
+    memcpy(value,env,len); 
+  }
+  free_drhook(p);
+}
+
+
+/*=== c_drhook_init_ ===*/
+
+void 
+c_drhook_init_(const char *progname,
+	       const int *num_threads
+	       /* Hidden length */
+	       ,int progname_len)
+{
+  init_drhook(*num_threads);
+  max_threads = MAX(1,*num_threads);
+  if (a_out) free_drhook(a_out);
+  progname = trim(progname, &progname_len);  
+  if (progname_len > 0) {
+    a_out = calloc_drhook(progname_len+1,sizeof(*progname));
+    memcpy(a_out, progname, progname_len);
+  }
+  else {
+    /* progname is a blank string;
+       this is most likely due to a Fortran-call to getarg
+       from program that has a C-main program, thus Fortran getarg
+       may return a blank string */
+
+    const char *arg0 = ec_GetArgs(0);
+    if (arg0) {
+      const char *pc = arg0;
+      progname_len = strlen(pc);
+      pc = trim(pc, &progname_len);
+      a_out = strdup_drhook(pc);
+    }
+  }
+  if (!a_out) {
+    a_out = strdup_drhook("a.out"); /* Failed to obtain the name of the executing program */
+  }
+}
+
+
+/*=== c_drhook_watch_ ===*/
+
+void
+c_drhook_watch_(const int *onoff,
+		const char *array_name,
+		const void *array_ptr,
+		const int *nbytes,
+		const int *abort_if_changed
+		/* Hidden length */
+		,int array_name_len)
+{
+  int tid = get_thread_id_();
+  drhook_watch_t *p = NULL;
+  if (!drhook_lhook) return; 
+
+  coml_set_lockid_(&DRHOOK_lock);
+
+  /* check whether this array_ptr is already registered, but maybe inactive */
+  p = watch;
+  while (p) {
+    if (p->ptr == array_ptr) {
+      if (p->active) watch_count--;
+      free_drhook(p->name);
+      break;
+    }
+    p = p->next;
+  }
+
+  if (!p) {
+    /* create new branch */
+    p = calloc_drhook(1, sizeof(*p)); /* Implies p->next = NULL */
+    if (!last_watch) {
+      last_watch = watch = p;
+    }
+    else {
+      last_watch->next = p;
+      last_watch = p;
+    }
+  }
+
+  p->name = strdup2_drhook(array_name,array_name_len);
+  p->tid = tid;
+  p->active = *onoff;
+  if (p->active) watch_count++;
+  p->abort_if_changed = *abort_if_changed;
+  p->ptr = array_ptr;
+  p->nbytes = *nbytes;
+  p->watch_first_nbytes = MIN(p->nbytes, MAX_WATCH_FIRST_NBYTES);
+  memcpy(p->first_nbytes,p->ptr,p->watch_first_nbytes);
+  p->crc32 = 0;
+  crc32_(p->ptr, &p->nbytes, &p->crc32);
+  fprintf(stderr,
+  "***Warning: Watch point '%s' was created for address 0x%x (%d bytes, on myproc#%d, tid#%d) : crc32=%u\n",
+          p->name, p->ptr, p->nbytes, myproc, p->tid, p->crc32);
+
+  coml_unset_lockid_(&DRHOOK_lock);
+}
+
+/*=== c_drhook_start_ ===*/
+
+void 
+c_drhook_start_(const char *name, 
+		const int *thread_id, 
+		double *key,
+		const char *filename,
+		const int *sizeinfo
+		/* Hidden length */
+		,int name_len, int filename_len)
+{
+  TIMERS;
+  equivalence_t u;
+  ITSELF_0;
+  if (!signals_set) signal_drhook_init(1);
+  if (watch && watch_count > 0) check_watch("entering", name, name_len);
+  if (!opt_callpath) {
+    u.keyptr = getkey(*thread_id, name, name_len, 
+		      filename, filename_len,
+		      &walltime, &cputime,
+		      NULL, 0, NULL);
+  }
+  else { /* (Much) more overhead */
+    int free_callpath = 1;
+    int callpath_len = 0;
+    equivalence_t *callpath = get_callpath(*thread_id, &callpath_len);
+    u.keyptr = getkey(*thread_id, name, name_len, 
+		      filename, filename_len,
+		      &walltime, &cputime,
+		      callpath, callpath_len, &free_callpath);
+    if (free_callpath) free_drhook(callpath);
+  }
+  *key = u.d;
+  ITSELF_1;
+  if (opt_calltrace) {      
+    coml_set_lockid_(&DRHOOK_lock);
+    {
+      const int ftnunitno = 0; /* stderr */
+      const int print_option = 2; /* calling tree */
+      int level = 0;
+      c_drhook_print_(&ftnunitno, thread_id, &print_option, &level);
+      /* fprintf(stderr,"%d#%d> %*.*s [%llu]\n",myproc,*thread_id,name_len,name_len,name,u.ull); */
+    }
+    coml_unset_lockid_(&DRHOOK_lock);
+  }
+  if (timeline) {
+    int tid = *thread_id;
+    if (opt_timeline_thread <= 0 || tid <= opt_timeline_thread) {
+      drhook_timeline_t *tl = &timeline[tid-1];
+      int bigjump = 1;
+      unsigned long long int mod = (tl->calls[0]++)%opt_timeline_freq;
+      double rss = (double)(getrss_()/1048576.0); /* in MBytes */
+      double curheap = (opt_timeline_thread == 1 && tid == 1) ?
+	(double)(getcurheap_()/1048576.0) : (double)(getcurheap_thread_(&tid)/1048576.0); /* in MBytes */
+      if (mod != 0) {
+	double inc_MB;
+	inc_MB = tl->last_rss_MB - rss;
+	if (ABS(inc_MB) < opt_timeline_MB) {
+	  inc_MB = tl->last_curheap_MB - curheap;
+	}
+	if (ABS(inc_MB) < opt_timeline_MB) bigjump = 0;
+      }
+      if (mod == 0 || bigjump) {
+	coml_set_lockid_(&DRHOOK_lock);
+	{
+	  int ftnunitno = opt_timeline_unitno;
+	  const int print_option = 5; /* calling "tree" with just the current entry */
+	  int level = 0;
+	  tl->last_rss_MB = rss;
+	  tl->last_curheap_MB = curheap;
+	  c_drhook_print_(&ftnunitno, &tid, &print_option, &level);
+	}
+	coml_unset_lockid_(&DRHOOK_lock);
+      }
+    } /* if (opt_timeline_thread <= 0 || tid <= opt_timeline_thread) */
+  }
+}
+
+/*=== c_drhook_end_ ===*/
+
+void 
+c_drhook_end_(const char *name,
+	      const int *thread_id,
+	      const double *key,
+	      const char *filename,
+	      const int *sizeinfo
+	      /* Hidden length */
+	      ,int name_len, int filename_len)
+{
+  TIMERS;
+  equivalence_t u;
+  ITSELF_0;
+  u.d = *key;
+  /*
+  if (opt_calltrace) {
+    coml_set_lockid_(&DRHOOK_lock);
+    fprintf(stderr,"%d#%d< %*.*s [%llu]\n",myproc,*thread_id,name_len,name_len,name,u.ull);
+    coml_unset_lockid_(&DRHOOK_lock);
+  }
+  */
+  if (timeline) {
+    int tid = *thread_id;
+    if (opt_timeline_thread <= 0 || tid <= opt_timeline_thread) {
+      drhook_timeline_t *tl = &timeline[tid-1];
+      int bigjump = 1;
+      unsigned long long int mod = (tl->calls[1]++)%opt_timeline_freq;
+      double rss = (double)(getrss_()/1048576.0); /* in MBytes */
+      double curheap = (opt_timeline_thread == 1 && tid == 1) ?
+	(double)(getcurheap_()/1048576.0) : (double)(getcurheap_thread_(&tid)/1048576.0); /* in MBytes */
+      if (mod != 0) {
+	double inc_MB;
+	inc_MB = tl->last_rss_MB - rss;
+	if (ABS(inc_MB) < opt_timeline_MB) {
+	  inc_MB = tl->last_curheap_MB - curheap;
+	}
+	if (ABS(inc_MB) < opt_timeline_MB) bigjump = 0;
+      }
+      if (mod == 0 || bigjump) {
+	coml_set_lockid_(&DRHOOK_lock);
+	{
+	  int ftnunitno = opt_timeline_unitno;
+	  const int print_option = -5; /* calling "tree" with just the current entry */
+	  int level = 0;
+	  tl->last_rss_MB = rss;
+	  tl->last_curheap_MB = curheap;
+	  c_drhook_print_(&ftnunitno, &tid, &print_option, &level);
+	}
+	coml_unset_lockid_(&DRHOOK_lock);
+      }
+    } /* if (opt_timeline_thread <= 0 || tid <= opt_timeline_thread) */
+  }
+  if (watch && watch_count > 0) check_watch("leaving", name, name_len);
+  putkey(*thread_id, u.keyptr, name, name_len, 
+	 *sizeinfo,
+	 &walltime, &cputime);
+  ITSELF_1;
+}
+
+/*=== c_drhook_memcounter_ ===*/
+
+void
+c_drhook_memcounter_(const int *thread_id,
+		     const long long int *size,
+		     long long int *keyptr_addr)
+{
+  int tid = (thread_id && (*thread_id >= 1) && (*thread_id <= numthreads))
+    ? *thread_id : get_thread_id_();
+  int has_timeline = (timeline && size) ? opt_timeline : 0;
+  if (has_timeline) {
+    if (opt_timeline_thread <= 1 || tid <= opt_timeline_thread) {
+      double size_MB = (double)((*size)/1048576.0); /* In MBytes */
+      if (ABS(size_MB) < opt_timeline_MB) has_timeline = 0; /* Do not report */
+    }
+    else {
+      has_timeline = 0; /* Do not report */
+    }
+  } /* if (has_timeline) */
+  if (opt_memprof) {
+    if (size) {
+      union {
+	long long int keyptr_addr;
+	drhook_key_t *keyptr;
+      } u;
+      long long int alldelta;
+      if (*size > 0) { /* Memory is being allocated */
+	if (curkeyptr[tid-1]) {
+	  drhook_key_t *keyptr = curkeyptr[tid-1];
+	  keyptr->mem_curdelta += *size;
+	  alldelta = keyptr->mem_curdelta + keyptr->mem_child;
+	  if (alldelta > keyptr->maxmem_alldelta) keyptr->maxmem_alldelta = alldelta;
+	  if (keyptr->mem_curdelta > keyptr->maxmem_selfdelta) 
+	    keyptr->maxmem_selfdelta = keyptr->mem_curdelta;
+	  if (keyptr_addr) {
+	    u.keyptr = keyptr;
+	    *keyptr_addr = u.keyptr_addr;
+	  }
+	  keyptr->alloc_count++;
+	}
+	else {
+	  if (keyptr_addr) *keyptr_addr = 0;
+	} /* if (curkeyptr[tid-1]) */
+	/*
+	fprintf(stderr,
+		"memcounter: allocated %lld bytes ; *keyptr_addr = %lld\n",
+		*size, *keyptr_addr);
+	 */
+      }
+      else { /* Memory is being freed */
+	drhook_key_t *keyptr;
+	if (keyptr_addr && (*keyptr_addr)) {
+	  u.keyptr_addr = *keyptr_addr;
+	  keyptr = u.keyptr;
+	}
+	else 
+	  keyptr = curkeyptr[tid-1];
+	/*
+	fprintf(stderr,
+		"memcounter: DE-allocated %lld bytes ; *keyptr_addr = %lld\n",
+		*size, *keyptr_addr);
+	 */
+	if (keyptr) {
+	  long long int prev_curdelta = keyptr->mem_curdelta;
+	  keyptr->mem_curdelta += *size;
+	  alldelta = prev_curdelta + keyptr->mem_child;
+	  if (alldelta > keyptr->maxmem_alldelta) keyptr->maxmem_alldelta = alldelta;
+	  if (*size < 0) keyptr->free_count++;
+	} /* if (keyptr) */
+      } /* if (*size > 0) ... else */
+    } /* if (size) */
+  } /* if (opt_memprof) */
+  if (has_timeline) {
+    double curheap = (opt_timeline_thread == 1 && tid == 1) ?
+      (double)(getcurheap_()/1048576.0) : (double)(getcurheap_thread_(&tid)/1048576.0); /* in MBytes */
+    double rss = (double)(getrss_()/1048576.0); /* in MBytes */
+    coml_set_lockid_(&DRHOOK_lock);
+    {
+      int ftnunitno = opt_timeline_unitno;
+      double size_MB = (double)((*size)/1048576.0); /* In MBytes */
+      int print_option = (size_MB > 0) ? 6 : -6; /* timeline upon c_drhook_memcounter_ & (big) ALLOCATE or DEALLOCATE */
+      int level = 0;
+      drhook_timeline_t *tl = &timeline[tid-1];
+      tl->last_curheap_MB = curheap;
+      tl->last_rss_MB = rss;
+      c_drhook_print_(&ftnunitno, &tid, &print_option, &level);
+    }
+    coml_unset_lockid_(&DRHOOK_lock);
+  } /* if (has_timeline) */
+}
+
+/*=== c_drhook_print_ ===*/
+
+#define PRINT_HWM() \
+if (opt_gethwm) { sprintf(s,",hwm=%lldK",keyptr->hwm/1024); s += strlen(s); }
+
+#define PRINT_RSS() \
+if (opt_getrss) { \
+  sprintf(s,",rss/max=%lldK/%lldK",keyptr->rssnow/1024, keyptr->maxrss/1024); \
+  s += strlen(s); \
+}
+
+#define PRINT_STK() \
+if (opt_getstk) { \
+  sprintf(s,",stack/max=%lldK/%lldK",keyptr->stack/1024, keyptr->maxstack/1024); \
+  s += strlen(s); \
+}
+
+#define PRINT_PAG() \
+if (opt_getpag) { \
+  sprintf(s,",pag=%lld",keyptr->paging); \
+  s += strlen(s); \
+}
+
+#define PRINT_WALL() \
+if (opt_walltime) { \
+  double self = keyptr->delta_wall_all-keyptr->delta_wall_child; \
+  if (self < 0) self = 0; \
+  sprintf(s,",wall=%.3fs/%.3fs", \
+	  keyptr->delta_wall_all, self); \
+  s += strlen(s); \
+}
+
+#define PRINT_CPU() \
+if (opt_cputime) { \
+  double self = keyptr->delta_cpu_all-keyptr->delta_cpu_child; \
+  if (self < 0) self = 0; \
+  sprintf(s,",cpu=%.3fs/%.3fs", \
+	  keyptr->delta_cpu_all, self); \
+  s += strlen(s); \
+}
+
+#define PRINT_CALLS() \
+if (opt_calls) { \
+  sprintf(s,",#%llu,st=%d",keyptr->calls,keyptr->status); \
+  s += strlen(s); \
+}
+
+static int
+prof_name_comp(const void *v1, const void *v2)
+{
+  const drhook_prof_t *p1 = v1;
+  const drhook_prof_t *p2 = v2;
+  return strcmp(p1->name,p2->name);
+}
+
+static int
+memprof_name_comp(const void *v1, const void *v2)
+{
+  const drhook_memprof_t *p1 = v1;
+  const drhook_memprof_t *p2 = v2;
+  return strcmp(p1->name,p2->name);
+}
+
+static int
+prof_pc_comp_desc(const void *v1, const void *v2)
+{
+  const drhook_prof_t *p1 = v1;
+  const drhook_prof_t *p2 = v2;
+  if (p1->pc < p2->pc) return 1;
+  else if (p1->pc > p2->pc) return -1;
+  else return 0;
+}
+
+static int
+memprof_pc_comp_desc(const void *v1, const void *v2)
+{
+  const drhook_memprof_t *p1 = v1;
+  const drhook_memprof_t *p2 = v2;
+  if (p1->pc < p2->pc) return 1;
+  else if (p1->pc > p2->pc) return -1;
+  else return 0;
+}
+
+static const char *
+trim_and_adjust_left(const char *p, int *name_len)
+{
+  int len = strlen(p);
+  if (len > 0) {
+    const char *back = &p[len-1];
+    while (len > 0 && *back-- == ' ') len--;
+    while (len > 0 && *p == ' ') { p++; len--; }
+  }
+  if (name_len) *name_len = len;
+  return p;
+}
+
+#define print_routine_name(fp, p, len, cluster_size) \
+  if (fp && p) { \
+    int name_len = 0; \
+    const char *name = trim_and_adjust_left(p->name,&name_len); \
+    fprintf(fp,"%.*s@%d%s%s", \
+	    name_len, name, \
+	    p->tid, \
+	    p->filename ? ":" : "", \
+	    p->filename ? p->filename : ""); \
+    \
+    if (opt_clusterinfo) { \
+      fprintf(fp," [%d,%d]", \
+	      p->cluster, ABS(cluster_size)); \
+    } \
+    \
+    unroll_callpath(fp, len, p->callpath, p->callpath_len); \
+  } /* if (fp && p) */
+
+
+#ifdef NECSX
+/* We need this because NEC SX refuses to write no more than 132 character for Fortran unit = 0 */
+static void
+DrHookPrint(int ftnunitno, const char *line)
+{
+  if (line) {
+    FILE *fp = NULL;
+    if (ftnunitno <= 0) 
+      fp = stderr;
+    else if (ftnunitno == 6) 
+      fp = stdout;
+    else
+      dr_hook_prt_(&ftnunitno, line, strlen(line));
+    if (fp) fprintf(fp,"%s\n",line);
+  }
+}
+#endif
+
+void 
+c_drhook_print_(const int *ftnunitno,
+		const int *thread_id,
+		const int *print_option, /* 
+					    1=raw call counts 
+					    2=calling tree
+					    3=profiling info
+					    4=memory profiling
+					    5=timeline upon entering the routine
+					   -5=timeline upon leaving the routine
+					    6=timeline upon c_drhook_memcounter_ & (big) ALLOCATE
+					   -6=timeline upon c_drhook_memcounter_ & (big) DEALLOCATE
+					    7=timeline : the very first call (upon setup or dr.hook)
+					   -7=timeline : the very last call (in atexit())
+					 */
+		int *level
+		)
+{
+  int tid = (thread_id && (*thread_id >= 1) && (*thread_id <= numthreads))
+    ? *thread_id : get_thread_id_();
+  if (ftnunitno && keydata && calltree) {
+    char line[4096];
+    int abs_print_option = ABS(*print_option);
+    int j;
+
+    if (*print_option == 1) { /* raw call counts */
+      for (j=0; j<hashsize; j++) {
+	int nestlevel = 0;
+	drhook_key_t *keyptr = &keydata[tid-1][j];
+	while (keyptr) {
+	  if (keyptr->name) {
+	    char *s = line;
+	    sprintf(s,
+		    "[myproc#%d,tid#%d,pid#%d,hash#%d,nest=%d]: '%s'",
+		    myproc,tid,pid,j,nestlevel,keyptr->name);
+	    s += strlen(s);
+	    PRINT_CALLS();
+	    PRINT_HWM();
+	    PRINT_RSS();
+	    PRINT_STK();
+	    PRINT_PAG();
+	    PRINT_WALL();
+	    PRINT_CPU();
+	    *s = 0;
+#ifdef NECSX
+	    DrHookPrint(*ftnunitno, line);
+#else
+	    dr_hook_prt_(ftnunitno, line, strlen(line));
+#endif
+	  }
+	  keyptr = keyptr->next;
+	  nestlevel++;
+	} /* while (keyptr) */
+      } /* for (j=0; j<hashsize; j++) */
+    }
+
+    else if (*print_option == 2 || 
+	     abs_print_option == 5 || 
+	     abs_print_option == 6 || 
+	     abs_print_option == 7
+	     ) { /* the current calling tree */
+      drhook_calltree_t *treeptr = calltree[tid-1];
+
+      if (tid > 1) {
+	if (*print_option == 2) { 
+	  /* I'm not a master thread, but my master has the beginning of the calltree */
+	  int initlev = 0;
+	  const int master = 1;
+	  c_drhook_print_(ftnunitno, &master, print_option, &initlev);
+	  *level += initlev;
+	}
+	else if (tid > opt_timeline_thread) {
+	  return;
+	}
+      }
+
+      if (abs_print_option == 7) {
+	treeptr = NULL;
+      }
+      else if (abs_print_option == 5 || abs_print_option == 6) {
+	treeptr = thiscall[tid-1];
+      }
+      else {
+	treeptr = calltree[tid-1];
+      }
+
+      while (abs_print_option == 7 || (treeptr && treeptr->active)) {
+	int do_print = (*print_option == 2 || 
+			abs_print_option == 7 ||
+			abs_print_option == 5 || abs_print_option == 6);
+	if (do_print) {
+	  drhook_key_t *keyptr = (abs_print_option == 7) ? NULL : treeptr->keyptr;
+	  char *s = line;
+	  char is_timeline = 1, kind;
+	  switch (*print_option) {
+	  case -5: kind = '<'; break;
+	  case -6: kind = '-'; break;
+	  case -7: kind = 'E'; break;
+	  case  5: kind = '>'; break;
+	  case  6: kind = '+'; break;
+	  case  7: kind = 'B'; break;
+	  default:
+	  case 2: kind = ':'; is_timeline = 0; break;
+	  }
+	  if (*print_option == 2 || 
+	      (is_timeline && tid > 1 && tid <= opt_timeline_thread))  {
+	    sprintf(s,"%s[myproc#%d,tid#%d,pid#%d]%c ",
+		    is_timeline ? "tl:" : "",
+		    myproc,tid,pid,kind);
+	  }
+	  else if (is_timeline && opt_timeline_thread == 1 && tid == 1) {
+	    sprintf(s,"%s[#%d]%c ",
+		    is_timeline ? "tl:" : "",
+		    myproc,kind);
+	  }
+	  s += strlen(s);
+	  (*level)++;
+	  for (j=0; j<(*level); j++) *s++ = ' ';
+	  if (*print_option == 2) {
+	    sprintf(s,"%s ",keyptr->name);
+	    s += strlen(s);
+	  }
+	  if (is_timeline) {
+	    double wall = WALLTIME();
+	    double rss, curheap;
+	    drhook_timeline_t *tl = &timeline[tid-1];
+	    if (abs_print_option == 5 || abs_print_option == 6) { /* when called via drhook_begin/_end or memcounter */
+	      curheap = tl->last_curheap_MB;
+	      rss = tl->last_rss_MB;
+	    }
+	    else {
+	      rss = (double)(getrss_()/1048576.0); /* in MBytes */
+	      curheap = (opt_timeline_thread == 1 && tid == 1) ?
+		(double)(getcurheap_()/1048576.0) : (double)(getcurheap_thread_(&tid)/1048576.0); /* in MBytes */
+	      tl->last_curheap_MB = curheap;
+	      tl->last_rss_MB = rss;
+	    }
+	    if (opt_timeline_format == 1) {
+	      if (wall < 10000) {
+		sprintf(s, "%.4g %.4g %.4g", wall, rss, curheap);
+	      }
+	      else {
+		sprintf(s, "%.7g %.4g %.4g", wall, rss, curheap);
+	      }
+	    }
+	    else {
+	      sprintf(s,
+		      "wall=%.4g cpu=%.4g hwm=%.4g rss=%.4g curheap=%.4g stack=%.4g pag=%lld",
+		      wall, CPUTIME(),
+		      (double)(gethwm_()/1048576.0), rss,
+		      curheap,
+		      (double)(getstk_()/1048576.0),
+		      getpag_());
+	    }
+	    s += strlen(s);
+	    *s++ = ' ';
+	    if (keyptr) {
+	      sprintf(s,"'%s'",keyptr->name);
+	    }
+	    else {
+	      sprintf(s,"'#PROGRAM %s'",(*print_option == 7) ? "BEGIN" : "END");
+	    }
+	    s += strlen(s);
+	  }
+	  else {
+	    PRINT_CALLS();
+	    PRINT_HWM();
+	    PRINT_RSS();
+	    PRINT_STK();
+	    PRINT_PAG();
+	    PRINT_WALL();
+	    PRINT_CPU();
+	  }
+	  *s = 0;
+#ifdef NECSX
+	  DrHookPrint(*ftnunitno, line);
+#else
+	  dr_hook_prt_(ftnunitno, line, strlen(line));
+#endif
+	}
+	if (abs_print_option == 7 || abs_print_option == 5 || abs_print_option == 6) break;
+	if (treeptr) treeptr = treeptr->next;
+      } /* while (abs_print_option == 7 || (treeptr && treeptr->active)) */
+    }
+
+    else if (*print_option == 3) { /* profiling (CPU, wall-clock and/or MFlop/s) */
+      int len;
+      int t;
+      double cumul;
+      double tottime = 0, max_overhead_pc = 0;
+      double *tot = NULL;
+      int nprof = 0;
+      drhook_prof_t *prof = NULL;
+      drhook_prof_t *p;
+      double flop_tot = 0, instr_tot = 0;
+      double *flop = NULL, *instr = NULL;
+
+      if (!opt_wallprof && !opt_cpuprof) return; /* no profiling info available */
+      if (tid > 1) return; /* just master thread allowed ; takes care of siblings, too */
+      if (numthreads<=0) return;
+      if (do_prof_off) return;
+      do_prof_off = 1;
+
+      /* Insert "$drhook" */
+      if (keyself && opt_self > 1) {
+	for (t=0; t<numthreads; t++) (void) insertkey(t+1,keyself[t]);
+      }
+
+      flop = calloc_drhook(numthreads, sizeof(*flop));
+      instr = calloc_drhook(numthreads, sizeof(*instr));
+      tot = calloc_drhook(numthreads, sizeof(*tot));
+
+      for (t=0; t<numthreads; t++) {
+	for (j=0; j<hashsize; j++) {
+	  drhook_key_t *keyptr = &keydata[t][j];
+	  while (keyptr) {
+	    if (keyptr->name && (keyptr->status == 0 || signal_handler_called)) {
+	      double self;
+	      if (opt_wallprof) {
+		self = keyptr->delta_wall_all - keyptr->delta_wall_child;
+	      }
+	      else {
+		self = keyptr->delta_cpu_all - keyptr->delta_cpu_child;
+	      }
+	      /* if (self < 0) self = 0; */
+	      tot[t] += self;
+#ifdef HPM
+	      flop[t] += keyptr->avg_mflops * self; /* mflop_count(keyptr); */
+	      instr[t] += keyptr->avg_mipsrate * self; /* mip_count(keyptr); */
+#endif
+	      nprof++;
+	    }
+	    keyptr = keyptr->next;
+	  } /* while (keyptr && keyptr->status == 0) */
+	} /* for (t=0; t<numthreads; t++) */
+      } /* for (j=0; j<hashsize; j++) */
+
+      if (opt_wallprof) { /* a bit unreliable; had not taken max. value of threads wall yet; will be recalculated */
+	tottime = tot[0] + ((keyself && opt_self > 1) ? keyself[0]->delta_wall_all : 0);
+	for (t=1; t<numthreads; t++) {
+	  double tmp = tot[t] + ((keyself && opt_self > 1) ? keyself[t]->delta_wall_all : 0);
+	  tottime = MAX(tottime,tmp);
+	}
+      }
+      else { /* ok & reliable (for cpuprof) */
+	tottime = 0;
+	for (t=0; t<numthreads; t++) tottime += (tot[t] + ((keyself && opt_self > 1) ? keyself[t]->delta_cpu_all : 0));
+      }
+
+      if (tottime <= 0) tottime = 1e-10;
+
+      p = prof = calloc_drhook(nprof + 1, sizeof(*prof)); /* Make sure there is at least one entry */
+
+      for (t=0; t<numthreads; t++) {
+	for (j=0; j<hashsize; j++) {
+	  drhook_key_t *keyptr = &keydata[t][j];
+	  while (keyptr) {
+	    if (keyptr->name && (keyptr->status == 0 || signal_handler_called)) {
+	      p->self = opt_wallprof ?
+		keyptr->delta_wall_all - keyptr->delta_wall_child :
+		keyptr->delta_cpu_all - keyptr->delta_cpu_child;
+	      p->total = opt_wallprof ?
+		keyptr->delta_wall_all :
+		keyptr->delta_cpu_all;
+	      p->calls = keyptr->calls;
+	      p->name = keyptr->name;
+	      p->pc = (p->self/tottime) * 100.0;
+	      if (p->calls > 0) {
+		p->percall_ms_self = (p->self/p->calls) * 1000.0;
+		p->percall_ms_total = (p->total/p->calls) * 1000.0;
+	      }
+	      p->tid = t+1;
+	      p->index = p - prof;
+#ifdef HPM
+	      if (opt_hpmprof) {
+		p->mflops = keyptr->avg_mflops; /* mflops_hpm(keyptr); */
+		p->mipsrate = keyptr->avg_mipsrate; /* mips_hpm(keyptr); */
+		p->divpc = divpc_hpm(keyptr);
+	      }
+#endif
+	      p->filename = keyptr->filename;
+	      p->sizeinfo = keyptr->sizeinfo;
+	      p->min_sizeinfo = keyptr->min_sizeinfo;
+	      p->max_sizeinfo = keyptr->max_sizeinfo;
+	      p->sizespeed = (p->self > 0 && p->sizeinfo > 0) ? p->sizeinfo/p->self : 0;
+	      p->sizeavg = (p->calls > 0 && p->sizeinfo > 0) ? p->sizeinfo/p->calls : 0;
+	      p->callpath = keyptr->callpath;
+	      p->callpath_len = keyptr->callpath_len;
+	      p++;
+	    }
+	    keyptr = keyptr->next;
+	  } /* while (keyptr && keyptr->status == 0) */
+	} /* for (j=0; j<hashsize; j++) */
+      } /* for (t=0; t<numthreads; t++) */
+
+      do {
+	double mflop_rate = 0;
+	double mip_rate = 0;
+	int numroutines = 0;
+	int cluster;
+	double *maxval = calloc_drhook(nprof+1, sizeof(*maxval)); /* make sure at least 1 element */
+	int *clusize = calloc_drhook(nprof+1, sizeof(*clusize)); /* make sure at least 1 element */
+	char *prevname = NULL;
+	const char *fmt1 = "%5d %8.2f %12.3f %12.3f %12.3f %14llu %11.2f %11.2f   %s";
+	const char *fmt2 = "%5d %8.2f %12.3f %12.3f %12.3f %14llu %7.0f %7.0f %7.1f   %s";
+	const char *fmt = opt_hpmprof ? fmt2 : fmt1;
+	char *filename = get_mon_out(myproc);
+	FILE *fp = NULL;
+
+	if (!filename) break;
+
+	if ((myproc == 1 && mon_out_procs == -1) || mon_out_procs == myproc) {
+	  fprintf(stderr,"Writing profiling information of proc#%d into file '%s'\n",myproc,filename);
+	}
+
+	fp = fopen(filename,"w");
+	if (!fp) goto finish_3;
+	
+	/* alphanumerical sorting to find out clusters of the same routine but on different threads */
+	/* also find out total wall clock time */
+	/* calculate percentage values */
+	
+	p = prof;
+	qsort(p, nprof, sizeof(*p), prof_name_comp);
+
+	cluster = 0;
+	maxval[cluster] = p->self;
+	p->maxval = &maxval[cluster];
+	clusize[cluster] = 1;
+	prevname = p->name;
+	p++;
+	for (j=1; j<nprof; j++) {
+	  if (!strequ(prevname,p->name)) {
+	    (p-1)->cluster = cluster;
+	    (p-1)->maxval = &maxval[cluster];
+	    prevname = p->name;
+	    cluster++;
+	  }
+	  if (p->self > maxval[cluster]) maxval[cluster] = p->self;
+	  p->cluster = cluster;
+	  p->maxval = &maxval[cluster];
+	  clusize[cluster]++;
+	  p++;
+	} /* for (j=1; j<nprof; j++) */
+
+	numroutines = (nprof > 0) ? (cluster + 1) : 0; /* Active no. of routines */
+
+	if (opt_wallprof) tottime = 0;
+	p = prof;
+	for (j=0; j<nprof; j++) {
+	  int use_this = 0;
+	  cluster = p->cluster;
+	  if (clusize[cluster] > 1) { /* multiple threads <= numthreads indeed called this routine */
+	    p->is_max = (p->self == *p->maxval);
+	    if (p->is_max) { /* first max found will be used for total time */
+	      clusize[cluster] = -clusize[cluster]; /* ensures that max has been found for this cluster */
+	      use_this = opt_wallprof;
+	    }
+	  }
+	  else if (clusize[cluster] == 1) {
+	    use_this = opt_wallprof;
+	  }
+	  if (use_this && opt_wallprof) tottime += p->self;
+	  p++;
+	}
+
+        if (tottime <= 0) tottime = 1e-10;
+
+	if (opt_wallprof) { /* use re-calculated tottime to define percentages */
+	  p = prof;
+	  for (j=0; j<nprof; j++) {
+	    p->pc = (p->self/tottime) * 100.0;
+	    p++;
+	  }
+	}
+
+	/* sorting with respect to percentage value */
+
+	p = prof;
+	qsort(p, nprof, sizeof(*p), prof_pc_comp_desc);
+
+	flop_tot = 0;
+	instr_tot = 0;
+	max_overhead_pc = 0;
+	for (t=0; t<numthreads; t++) {
+	  flop_tot += flop[t];
+	  instr_tot += instr[t];
+	  if (overhead) {
+	    max_overhead_pc = MAX(max_overhead_pc,overhead[t]);
+#ifdef DEBUG
+	    fprintf(fp,"tid#%d: overhead = %.15g s\n",t+1,overhead[t]);
+#endif
+	  }
+	}
+#ifdef DEBUG
+	fprintf(fp,"max overhead = %.15g s, tottime = %.15g s\n",
+		max_overhead_pc, tottime);
+#endif
+	if (tottime - max_overhead_pc > 0) {
+	  max_overhead_pc = 100.0*(max_overhead_pc/(tottime - max_overhead_pc));
+	}
+	else {
+	  max_overhead_pc = 100;
+	}
+
+	fprintf(fp,
+		"Profiling information for program='%s', proc#%d:\n",a_out, myproc);
+	fprintf(fp,"\tNo. of instrumented routines called : %d\n", numroutines);
+	fprintf(fp,"\tInstrumentation started : %s\n",start_stamp ? start_stamp : "N/A");
+	end_stamp = timestamp();
+	fprintf(fp,"\tInstrumentation   ended : %s\n",end_stamp ? end_stamp : "N/A");
+	fprintf(fp,"\tInstrumentation overhead: %.2f%%\n",max_overhead_pc);
+	{
+	  long long int hwm = gethwm_()/1048576;
+	  long long int rss = getrss_()/1048576;
+	  long long int maxstack = getmaxstk_()/1048576;
+	  long long int pag = getpag_();
+	  fprintf(fp,
+	  "\tMemory usage : %lld MBytes (heap), %lld MBytes (rss), %lld MBytes (stack), %lld (paging)\n",
+		  hwm,rss,maxstack,pag);
+	}
+	if (opt_hpmprof) {
+	  mflop_rate = flop_tot / tottime;
+	  mip_rate = instr_tot / tottime;
+	  fprintf(fp,
+		  "\t%s-time is %.2f sec on proc#%d, %.0f MFlops (ops#%.0f*10^6), %.0f MIPS (ops#%.0f*10^6) (%d procs, %d threads)\n",
+		  opt_wallprof ? "Wall" : "Total CPU", tottime, myproc,
+		  mflop_rate, flop_tot, mip_rate, instr_tot,
+		  nproc, numthreads);
+	}
+	else {
+	  fprintf(fp,
+		  "\t%s-time is %.2f sec on proc#%d (%d procs, %d threads)\n",
+		  opt_wallprof ? "Wall" : "Total CPU", tottime, myproc,
+		  nproc, numthreads);
+	}
+
+	if (myproc == 1) {
+	  fprintf(stderr,
+		  "Profiling information for program='%s', proc#%d:\n",a_out, myproc);
+	  fprintf(stderr,"\tNo. of instrumented routines called : %d\n", numroutines);
+	  fprintf(stderr,"\tInstrumentation started : %s\n",start_stamp ? start_stamp : "N/A");
+	  fprintf(stderr,"\tInstrumentation   ended : %s\n",end_stamp ? end_stamp : "N/A");
+	  fprintf(stderr,"\tInstrumentation overhead: %.2f%%\n",max_overhead_pc);
+	  if (opt_hpmprof) {
+	    fprintf(stderr,
+		  "\t%s-time is %.2f sec on proc#%d, %.0f MFlops (ops#%.0f*10^6), %.0f MIPS (ops#%.0f*10^6) (%d procs, %d threads)\n",
+		  opt_wallprof ? "Wall" : "Total CPU", tottime, myproc,
+		  mflop_rate, flop_tot, mip_rate, instr_tot,
+		  nproc, numthreads);
+	  }
+	  else {
+	    fprintf(stderr,
+		    "\t%s-time is %.2f sec on proc#%d (%d procs, %d threads)\n",
+		    opt_wallprof ? "Wall" : "Total CPU", tottime, myproc,
+		    nproc, numthreads);
+	  }
+	} /* if (myproc == 1) */
+
+	free_drhook(end_stamp);
+
+	for (t=0; t<numthreads; t++) {
+	  double tmp = 100.0*(tot[t]/tottime);
+	  if (opt_hpmprof && tot[t] > 0) {
+	    mflop_rate = flop[t]/tot[t];
+	    mip_rate = instr[t]/tot[t];
+	  }
+	  else {
+	    mflop_rate = 0;
+	    mip_rate = 0;
+	  }
+	  fprintf(    fp,"\tThread#%d: %11.2f sec (%.2f%%)",t+1,tot[t],tmp);
+	  if (opt_hpmprof) fprintf(    fp,", %.0f MFlops (ops#%.0f*10^6), %.0f MIPS (ops#%.0f*10^6)", mflop_rate, flop[t], mip_rate, instr[t]);
+	  fprintf(    fp,"\n");
+	  if (myproc == 1) {
+	    fprintf(stderr,"\tThread#%d: %11.2f sec (%.2f%%)",t+1,tot[t],tmp);
+	    if (opt_hpmprof) fprintf(stderr,", %.0f MFlops (ops#%.0f*10^6), %.0f MIPS (ops#%.0f*10^6)", mflop_rate, flop[t], mip_rate, instr[t]);
+	    fprintf(stderr,"\n");
+	  }
+	}
+
+	fprintf(fp,"\n");
+	if (opt_hpmprof) {
+	  len = 
+	    fprintf(fp,"    #  %% Time         Cumul         Self        Total     # of calls    MIPS  MFlops   Div-%%    ");
+	}
+	else {
+	  len = 
+	    fprintf(fp,"    #  %% Time         Cumul         Self        Total     # of calls        Self       Total    ");
+	}
+	fprintf(fp,"Routine@<thread-id>");
+	if (opt_clusterinfo) fprintf(fp," [Cluster:(id,size)]");
+	fprintf(fp,"\n");
+	if (opt_sizeinfo) fprintf(fp,"%*s %s\n",len-20," ","(Size; Size/sec; Size/call; MinSize; MaxSize)");
+	if (opt_hpmprof) {
+	  fprintf(fp,  "        (self)        (sec)        (sec)        (sec)                                       \n");
+	}
+	else {
+	  fprintf(fp,  "        (self)        (sec)        (sec)        (sec)                    ms/call     ms/call\n");
+	}
+	fprintf(fp,"\n");
+
+	cumul = 0;
+	for (j=0; j<nprof; ) {
+	  int cluster_size = clusize[p->cluster];
+	  if (p->pc < percent_limit) break;
+	  if (opt_cputime) {
+	    cumul += p->self;
+	  }
+	  else {
+	    if (p->is_max || cluster_size == 1) cumul += p->self;
+	  }
+	  if (opt_hpmprof) {
+	    fprintf(fp, fmt,
+		    ++j, p->pc, cumul, p->self, p->total, p->calls,
+		    p->mipsrate, p->mflops, p->divpc,
+		    p->is_max ? "*" : " ");
+	  }
+	  else {
+	    fprintf(fp, fmt,
+		    ++j, p->pc, cumul, p->self, p->total, p->calls,
+		    p->percall_ms_self, p->percall_ms_total, 
+		    p->is_max ? "*" : " ");
+	  }
+
+	  print_routine_name(fp, p, len, cluster_size);
+	    
+	  if (opt_sizeinfo && p->sizeinfo > 0) {
+	    char s1[DRHOOK_STRBUF], s2[DRHOOK_STRBUF], s3[DRHOOK_STRBUF];
+	    char s4[DRHOOK_STRBUF], s5[DRHOOK_STRBUF];
+	    lld_commie(p->sizeinfo,s1);
+	    dbl_commie(p->sizespeed,s2);
+	    dbl_commie(p->sizeavg,s3);
+	    lld_commie(p->min_sizeinfo,s4);
+	    lld_commie(p->max_sizeinfo,s5);
+	    fprintf(fp,"\n%*s (%s; %s; %s; %s; %s)",len-20," ",s1,s2,s3,s4,s5);
+	  }
+	  fprintf(fp,"\n");
+	  p++;
+	} /* for (j=0; j<nprof; ) */
+	
+	fclose(fp);
+      finish_3:
+	free_drhook(filename);
+	free_drhook(maxval);
+	free_drhook(clusize);
+      } while (0);
+
+      free_drhook(instr);
+      free_drhook(flop);
+      free_drhook(tot);
+      free_drhook(prof);
+      do_prof_off = 0;
+    }
+
+    else if (*print_option == 4) { /* Memory profiling */
+      int t, len;
+      int nprof = 0;
+      drhook_memprof_t *prof = NULL;
+      drhook_memprof_t *p;
+      long long int *tot;
+      long long int *maxseen_tot;
+      double totmaxmem_delta;
+
+      if (!opt_memprof) return; /* no profiling info available */
+      if (tid > 1) return; /* just master thread allowed ; takes care of siblings, too */
+      if (numthreads<=0) return;
+      if (do_prof_off) return;
+      do_prof_off = 1;
+
+      tot = calloc_drhook(numthreads, sizeof(*tot));
+      maxseen_tot = calloc_drhook(numthreads, sizeof(*maxseen_tot));
+
+      for (t=0; t<numthreads; t++) {
+	for (j=0; j<hashsize; j++) {
+	  drhook_key_t *keyptr = &keydata[t][j];
+	  while (keyptr) {
+	    if (keyptr->name && (keyptr->status == 0 || signal_handler_called)) {
+
+	      long long int self;
+	      self = keyptr->maxmem_selfdelta;
+	      if (self < 0) self = 0;
+	      tot[t] += self;
+	      maxseen_tot[t] = MAX(maxseen_tot[t], keyptr->mem_seenmax);
+	      nprof++;
+	    }
+	    keyptr = keyptr->next;
+	  } /* while (keyptr && keyptr->status == 0) */
+	} /* for (t=0; t<numthreads; t++) */
+      } /* for (j=0; j<hashsize; j++) */
+
+      totmaxmem_delta = tot[0];
+      for (t=1; t<numthreads; t++) {
+	long long int tmp = tot[t];
+	totmaxmem_delta = MAX(totmaxmem_delta,tmp);
+      }
+
+      if (totmaxmem_delta <= 0) totmaxmem_delta = 1e-10; /* To avoid divide-by-zero */
+
+      p = prof = calloc_drhook(nprof + 1, sizeof(*prof)); /* Make sure there is at least one entry */
+
+      for (t=0; t<numthreads; t++) {
+	for (j=0; j<hashsize; j++) {
+	  drhook_key_t *keyptr = &keydata[t][j];
+	  while (keyptr) {
+	    if (keyptr->name && (keyptr->status == 0 || signal_handler_called)) {
+	      p->self = keyptr->maxmem_selfdelta;
+	      p->children = keyptr->mem_child;
+	      p->hwm = keyptr->mem_maxhwm;
+	      p->rss = keyptr->mem_maxrss;
+	      p->stk = keyptr->mem_maxstk;
+	      p->pag = keyptr->mem_maxpagdelta;
+	      p->leaked = keyptr->mem_curdelta;
+	      p->calls = keyptr->calls;
+	      p->alloc_count += keyptr->alloc_count;
+	      p->free_count += keyptr->free_count;
+	      p->name = keyptr->name;
+	      p->pc = (p->self/totmaxmem_delta) * 100.0;
+	      p->tid = t+1;
+	      p->index = p - prof;
+	      p->filename = keyptr->filename;
+	      p->callpath = keyptr->callpath;
+	      p->callpath_len = keyptr->callpath_len;
+	      p++;
+	    }
+	    keyptr = keyptr->next;
+	  } /* while (keyptr && keyptr->status == 0) */
+	} /* for (t=0; t<numthreads; t++) */
+      } /* for (j=0; j<hashsize; j++) */
+
+      do {
+	int numroutines = 0;
+	int cluster;
+	long long int *maxval = calloc_drhook(nprof+1, sizeof(*maxval)); /* make sure at least 1 element */
+	int *clusize = calloc_drhook(nprof+1, sizeof(*clusize)); /* make sure at least 1 element */
+	char *prevname = NULL;
+	const char *fmt1 = "%5d %9.2f  %14lld %14lld %14lld %14lld %14lld %10lld %10llu %10llu%s%10llu   %s";
+	const char *fmt = fmt1;
+	char *filename = get_memmon_out(myproc);
+	FILE *fp = NULL;
+
+	if (!filename) break;
+
+	if ((myproc == 1 && mon_out_procs == -1) || mon_out_procs == myproc) {
+	  fprintf(stderr,"Writing memory-profiling information of proc#%d into file '%s'\n",myproc,filename);
+	}
+
+	fp = fopen(filename,"w");
+	if (!fp) goto finish_4;
+	
+	/* alphanumerical sorting to find out clusters of the same routine but on different threads */
+	
+	p = prof;
+	qsort(p, nprof, sizeof(*p), memprof_name_comp);
+
+	cluster = 0;
+	maxval[cluster] = p->self;
+	p->maxval = &maxval[cluster];
+	clusize[cluster] = 1;
+	prevname = p->name;
+	p++;
+	for (j=1; j<nprof; j++) {
+	  if (!strequ(prevname,p->name)) {
+	    (p-1)->cluster = cluster;
+	    (p-1)->maxval = &maxval[cluster];
+	    prevname = p->name;
+	    cluster++;
+	  }
+	  if (p->self > maxval[cluster]) maxval[cluster] = p->self;
+	  p->cluster = cluster;
+	  p->maxval = &maxval[cluster];
+	  clusize[cluster]++;
+	  p++;
+	} /* for (j=1; j<nprof; j++) */
+
+	numroutines = (nprof > 0) ? (cluster + 1) : 0; /* Active no. of routines */
+
+	totmaxmem_delta = 0;
+	p = prof;
+	for (j=0; j<nprof; j++) {
+	  int use_this = 0;
+	  cluster = p->cluster;
+	  if (clusize[cluster] > 1) { /* multiple threads <= numthreads indeed called this routine */
+	    p->is_max = (p->self == *p->maxval);
+	    if (p->is_max) { /* first max found will be used for total time */
+	      clusize[cluster] = -clusize[cluster]; /* ensures that max has been found for this cluster */
+	      use_this = 1;
+	    }
+	  }
+	  else if (clusize[cluster] == 1) {
+	    use_this = 1;
+	  }
+	  if (use_this) totmaxmem_delta += p->self;
+	  p++;
+	}
+
+        if (totmaxmem_delta <= 0) totmaxmem_delta = 1e-10; /* To avoid divide-by-zero */
+
+	/* use re-calculated totmaxmem_delta to define percentages */
+	p = prof;
+	for (j=0; j<nprof; j++) {
+	  p->pc = (p->self/totmaxmem_delta) * 100.0;
+	  p++;
+	}
+
+	/* sorting with respect to percentage value */
+
+	p = prof;
+	qsort(p, nprof, sizeof(*p), memprof_pc_comp_desc);
+
+	fprintf(fp,
+		"Memory-profiling information for program='%s', proc#%d:\n",a_out, myproc);
+	fprintf(fp,"\tNo. of instrumented routines called : %d\n", numroutines);
+	fprintf(fp,"\tInstrumentation started : %s\n",start_stamp ? start_stamp : "N/A");
+	end_stamp = timestamp();
+	fprintf(fp,"\tInstrumentation   ended : %s\n",end_stamp ? end_stamp : "N/A");
+	{
+	  long long int hwm = gethwm_()/1048576;
+	  long long int rss = getrss_()/1048576;
+	  long long int maxstack = getmaxstk_()/1048576;
+	  long long int pag = getpag_();
+	  long long int maxseen = 0;
+	  long long int leaked = 0;
+	  p = prof;
+	  for (j=0; j<nprof; j++) {
+	    if (p->leaked > 0) leaked += p->leaked;
+	    p++;
+	  }
+	  for (t=0; t<numthreads; t++) {
+	    maxseen += maxseen_tot[t];
+	  }
+	  maxseen /= 1048576;
+	  leaked /= 1048576;
+	  fprintf(fp,
+	  "\tMemory usage : %lld MBytes (max.seen), %lld MBytes (leaked), %lld MBytes (heap), %lld MBytes (max.rss), %lld MBytes (max.stack), %lld (paging)\n",
+		  maxseen,leaked,hwm,rss,maxstack,pag);
+	  fprintf(fp,"\tNo. of procs/threads: %d procs, %d threads\n",nproc,numthreads);
+	}
+
+	if (myproc == 1) {
+	  fprintf(stderr,
+		  "Memory-profiling information for program='%s', proc#%d:\n",a_out, myproc);
+	  fprintf(stderr,"\tNo. of instrumented routines called : %d\n", numroutines);
+	  fprintf(stderr,"\tInstrumentation started : %s\n",start_stamp ? start_stamp : "N/A");
+	  fprintf(stderr,"\tInstrumentation   ended : %s\n",end_stamp ? end_stamp : "N/A");
+	} /* if (myproc == 1) */
+
+	free_drhook(end_stamp);
+
+	fprintf(fp,"\n");
+	len = 
+	  fprintf(fp,"    #  Memory-%%      Self-alloc     + Children    Self-Leaked          Heap       Max.Stack     Paging     #Calls    #Allocs     #Frees   ");
+                   /*"12345-1234567899-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-123456789012-123456789012"*/
+	fprintf(fp,"Routine@<thread-id>");
+	if (opt_clusterinfo) fprintf(fp," [Cluster:(id,size)]");
+	fprintf(fp,"\n");
+	fprintf(fp,  "         (self)         (bytes)        (bytes)        (bytes)        (bytes)        (bytes)    (delta)");
+                   /*"12345-1234567899-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-12345678901234-123456789012-123456789012"*/
+	fprintf(fp,"\n");
+
+	p = prof;
+	for (j=0; j<nprof; ) {
+	  int cluster_size = clusize[p->cluster];
+	  if (p->pc < percent_limit) break;
+	  t = p->tid - 1;
+	  if (p->children > maxseen_tot[t]) p->children = maxseen_tot[t]; /* adjust */
+	  fprintf(fp, fmt,
+		  ++j, p->pc, 
+		  p->self, p->children, p->leaked,
+		  p->hwm, p->stk, p->pag,
+		  p->calls, p->alloc_count, 
+		  (p->alloc_count - p->free_count != 0) ? "*" : " ", p->free_count,
+		  p->is_max ? "*" : " ");
+
+	  print_routine_name(fp, p, len, cluster_size);
+
+	  fprintf(fp,"\n");
+	  p++;
+	} /* for (j=0; j<nprof; ) */
+	
+	fclose(fp);
+      finish_4:
+	free_drhook(filename);
+	free_drhook(maxval);
+	free_drhook(clusize);
+      } while (0);
+
+      free_drhook(tot);
+      free_drhook(maxseen_tot);
+      free_drhook(prof);
+      do_prof_off = 0;
+    }
+  }
+}
+
+/*=== c_drhook_init_signals_ ===*/
+
+void
+c_drhook_init_signals_(const int *enforce)
+{
+  /* To present sumpini.F90 (f.ex.) initializing DrHook-signals in case of 
+     DR_HOOK was turned off (=0), then set also export DR_HOOK_INIT_SIGNALS=0 */
+  char *env = getenv("DR_HOOK_INIT_SIGNALS");
+  if (env && *env == '0') return; /* Never initialize signals for DrHook (dangerous, but sometimes necessary) */
+  signal_drhook_init(*enforce);
+}
+
+/*=== c_drhook_raise_ ===*/
+
+/* 
+   Just a convenience function for Fortran90 which may not have raise()-signal function
+   CALL c_drhook_raise(10)  ! Raise signal#10
+*/
+
+void 
+c_drhook_raise_(const int *sig) 
+{ 
+  fflush(NULL);
+  raise(*sig);
+} 
+
+/**** C-interface to Dr.Hook ****/
+
+void
+Dr_Hook(const char *name, int option, double *handle, 
+	const char *filename, int sizeinfo,
+	int name_len, int filename_len)
+{
+  static int first_time = 1;
+  static int value = 1; /* ON by default */
+  if (first_time) { /* Not thread safe */
+    extern void *cdrhookinit_(int *value); /* from ifsaux/support/cdrhookinit.F90 */
+    cdrhookinit_(&value);
+    first_time = 0;
+  }
+  if (value == 0) return; /* Immediate return if OFF */
+  if (value != 0) {
+    int tid = get_thread_id_();
+    if (option == 0) {
+      c_drhook_start_(name, &tid, handle, 
+		      filename, &sizeinfo,
+		      name_len > 0 ? name_len : strlen(name),
+		      filename_len > 0 ? filename_len : strlen(filename));
+    }
+    else if (option == 1) {
+      c_drhook_end_(name, &tid, handle, 
+		    filename, &sizeinfo,
+		    name_len > 0 ? name_len : strlen(name),
+		    filename_len > 0 ? filename_len : strlen(filename));
+    }
+  }
+}
+
+
+/**** Interface to HPM ****/
+
+/*<<< experimental >>>*/
+
+#ifdef HPM
+
+#ifdef RS6K
+/**** Interface to HPM (RS6K) ****/
+
+#include <pmapi.h>
+
+static pthread_mutex_t hpm_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int *hpm_tid_init = NULL;
+static double cycles = 1300000000.0; /* 1.3GHz ; changed via pm_cycles() in init_hpm() */
+
+#define MCYCLES (cycles * 1e-6)
+
+#define TEST_PM_ERROR(name, rc) \
+  if (rc != 0) { \
+    fprintf(stderr,"PM_ERROR(tid#%d, pthread_self()=%d): rc=%d at %s(), line=%d, file=%s\n",\
+	    tid,pthread_self(),rc,name,__LINE__,__FILE__); \
+    pm_error((char *)name, rc); \
+    sleep(tid); \
+    RAISE(SIGABRT); \
+  }
+
+static void
+init_hpm(int tid)
+{
+  const char *name = "init_hpm";
+  int rc;
+
+  if (!hpm_tid_init) {
+    hpm_tid_init = calloc_drhook(numthreads, sizeof(*hpm_tid_init));
+    cycles = pm_cycles();
+  }
+
+  if (!hpm_tid_init[tid-1]) {
+#ifdef PMAPI_POST_P4
+    pm_info2_t pminfo;
+#else
+    pm_info_t pminfo;
+#endif
+    pm_groups_info_t pmgroupsinfo;
+    
+    /*------------------------------------*/
+    /* initialize the performance monitor */
+    /*------------------------------------*/
+#ifdef PMAPI_POST_P4
+    rc = pm_initialize(PM_VERIFIED | PM_UNVERIFIED | PM_CAVEAT | PM_GET_GROUPS, 
+		 &pminfo, &pmgroupsinfo, PM_CURRENT);
+#else
+    rc = pm_init(PM_VERIFIED | PM_UNVERIFIED | PM_CAVEAT | PM_GET_GROUPS, 
+		 &pminfo, &pmgroupsinfo);
+#endif
+    TEST_PM_ERROR((char *)name, rc);
+
+    if (myproc <= 1) fprintf(stderr,
+			     ">>>pm_init() for ECMWF/OpenMP-tid#%d, pthread_self()=%d\n",
+			     tid,pthread_self());
+  }
+
+  if (!hpm_tid_init[tid-1]) {
+#if defined(PMAPI_P6)
+    const int group = 186; /* pm_hpm1 */
+    /*-- counters --
+     case 186:
+       strcpy(group_label, "HPM group");
+       strcpy(label[0], "FPU executed one flop instruction (PM_FPU_1FLOP)");
+       strcpy(label[1], "FPU executed multiply-add instruction (PM_FPU_FMA)");
+       strcpy(label[2], "FPU executed FSQRT or FDIV instruction (PM_FPU_SQRT_FDIV)");
+       strcpy(label[3], "Processor Cycles (PM_CYC [shared chip])");
+       strcpy(label[4], "Run instructions completed(PM_RUN_INST_CMPL)");
+       strcpy(label[5], "Run cycles (PM_RUN_CYC)");
+       strcpy(label[6], "Nothing");
+       strcpy(label[7], "Nothing");
+    */
+#elif defined(PMAPI_P5_PLUS)
+    /* IBM Power 5+ specific */
+    const int group = 150; /* pm_hpmcount2 */
+    /*-- counters -- (from John Hague, IBM/UK, 22-Aug-2006 : Thanx!!)
+     case 150:
+       strcpy(group_label, "pm_flop, Floating point operations");
+       strcpy(label[0], "FPU executed FDIV instruction (PM_FPU_FDIV)");
+       strcpy(label[1], "FPU executed multiply-add instruction (PM_FPU_FMA)");
+       strcpy(label[2], "FPU executed FSQRT instruction (PM_FPU_SQRT)");
+       strcpy(label[3], "FPU executed one flop instruction (PM_FPU_1FLOP)");
+       strcpy(label[4], "Run instructions completed(PM_RUN_INST_CMPL)");
+       strcpy(label[5], "Run cycles (PM_RUN_CYC)");
+       strcpy(label[6], "Nothing");
+       strcpy(label[7], "Nothing");
+    */
+#else
+    const int group = 60; /* pm_hpmcount2 */
+    /*-- counters --
+     case 60:
+       strcpy(group_label, "pm_hpmcount2, Hpmcount group for computation intensity analysis");
+       strcpy(label[0], "FPU executed FDIV instruction (PM_FPU_FDIV)");
+       strcpy(label[1], "FPU executed multiply-add instruction (PM_FPU_FMA)");
+       strcpy(label[2], "FPU0 produced a result (PM_FPU0_FIN)");
+       strcpy(label[3], "FPU1 produced a result (PM_FPU1_FIN)");
+       strcpy(label[4], "Processor cycles (PM_CYC)");
+       strcpy(label[5], "FPU executed store instruction (PM_FPU_STF)");
+       strcpy(label[6], "Instructions completed (PM_INST_CMPL)");
+       strcpy(label[7], "LSU executed Floating Point load instruction (PM_LSU_LDF)");
+    */
+#endif
+
+    fprintf(stderr,"group = %d\n",group);
+
+    pm_prog_t pmprog;
+    pm_data_t pmdata;
+    int i;
+
+    /*---------------------*/
+    /* set a default group */
+    /*---------------------*/
+    for (i=0; i<MAX_COUNTERS; i++) {
+      pmprog.events[i] = COUNT_NOTHING;
+    }
+    pmprog.events[0] = group;
+    
+    /*-------------------------------------------------------------*/
+    /* set the mode for user (not kernel) and thread (not process) */
+    /*-------------------------------------------------------------*/
+    pmprog.mode.w = 0;
+    pmprog.mode.b.user = 1;
+    pmprog.mode.b.process = 0;
+    /* pmprog.mode.b.process = 1; */
+    
+    /*------------------------------------------*/
+    /* for power-4 you have to use event groups */
+    /*------------------------------------------*/
+    pmprog.mode.b.is_group = 1;
+    
+    /*---------------------------------------------------*/
+    /* set the mode to not to start counting immediately */
+    /*---------------------------------------------------*/
+    /* pmprog.mode.b.count = 1; */
+    pmprog.mode.b.count = 0;
+    
+    /*-----------------------------------------*/
+    /* initialize the group and start counting */
+    /*-----------------------------------------*/
+    hpm_tid_init[tid-1] = pthread_self(); /* Always > 0 */
+
+    rc = pm_set_program_mythread(&pmprog); 
+    TEST_PM_ERROR((char *)name, rc);
+
+    rc = pm_start_mythread();
+    TEST_PM_ERROR((char *)name, rc);
+  }
+}
+
+static void
+stop_only_hpm(int tid, drhook_key_t *pstop) 
+{
+  const char *name = "stop_only_hpm";
+  pm_data_t pmdata;
+  int i, rc;
+
+  /* if (numthreads > 1) pthread_mutex_lock(&hpm_lock); */
+
+  if (!hpm_tid_init || !hpm_tid_init[tid-1]) init_hpm(tid);
+
+  /*
+  rc = pm_stop_mythread();
+  TEST_PM_ERROR((char *)name, rc);
+  */
+
+  if (pstop && !pstop->counter_stopped) {
+    rc = pm_get_data_mythread(&pmdata);
+    TEST_PM_ERROR((char *)name, rc);
+    
+    if (pstop && pstop->counter_in && !pstop->counter_stopped) {
+      for (i=0; i<MAX_COUNTERS; i++) {
+	pstop->counter_sum[i] += (pmdata.accu[i] - pstop->counter_in[i]);
+      }
+      pstop->counter_stopped = 1;
+    }
+  }
+
+  /*
+  rc = pm_start_mythread();
+  TEST_PM_ERROR((char *)name, rc);
+  */
+
+  /* if (numthreads > 1) pthread_mutex_unlock(&hpm_lock); */
+}
+
+static void
+stopstart_hpm(int tid, drhook_key_t *pstop, drhook_key_t *pstart)
+{
+  const char *name = "stopstart_hpm";
+  pm_data_t pmdata;
+  int i, rc;
+
+  /* if (numthreads > 1) pthread_mutex_lock(&hpm_lock); */
+
+  if (!hpm_tid_init || !hpm_tid_init[tid-1]) init_hpm(tid);
+
+  /*
+  rc = pm_stop_mythread();
+  TEST_PM_ERROR((char *)name, rc);
+  */
+
+  rc = pm_get_data_mythread(&pmdata);
+  TEST_PM_ERROR((char *)name, rc);
+
+  if (pstop && pstop->counter_in && !pstop->counter_stopped) {
+    for (i=0; i<MAX_COUNTERS; i++) {
+      pstop->counter_sum[i] += (pmdata.accu[i] - pstop->counter_in[i]);
+    }
+    pstop->counter_stopped = 1;
+  }
+
+  if (pstart) {
+    if (!pstart->counter_in ) pstart->counter_in  = calloc_drhook(MAX_COUNTERS, sizeof(*pstart->counter_in ));
+    if (!pstart->counter_sum) pstart->counter_sum = calloc_drhook(MAX_COUNTERS, sizeof(*pstart->counter_sum));
+     for (i=0; i<MAX_COUNTERS; i++) {
+       pstart->counter_in[i] = pmdata.accu[i];
+     }
+     pstart->counter_stopped = 0;
+  }
+
+  /*
+  rc = pm_start_mythread();
+  TEST_PM_ERROR((char *)name, rc);
+  */
+
+  /* if (numthreads > 1) pthread_mutex_unlock(&hpm_lock); */
+}
+
+#else
+
+/**** Interface to HPM (CRAY SV2, XD1 and XT3) ****/
+
+static int *hpm_tid_init = NULL;
+static double cycles = 0;
+
+#define MCYCLES (cycles * 1e-6)
+
+#define TEST_PM_ERROR(name, rc) \
+  if (rc != 0) { \
+    fprintf(stderr,"PM_ERROR(tid#%d, pthread_self()=%d): rc=%d at %s(), line=%d, file=%s\n",\
+            tid,pthread_self(),rc,name,__LINE__,__FILE__); \
+    pm_error((char *)name, rc); \
+    sleep(tid); \
+    RAISE(SIGABRT); \
+  }
+
+static void
+init_hpm(int tid)
+{
+  const char *name = "init_hpm";
+  int rc;
+
+  cycles = irtc_rate_();
+}
+
+static void
+stop_only_hpm(int tid, drhook_key_t *pstop)
+{
+  const char *name = "stop_only_hpm";
+  int i, rc;
+
+  if (!hpm_tid_init || !hpm_tid_init[tid-1]) init_hpm(tid);
+
+  if (pstop && !pstop->counter_stopped) {
+
+    if (pstop && pstop->counter_in && !pstop->counter_stopped) {
+#if defined(DT_FLOP)
+      pstop->counter_sum[0] += ((long long int) flop_() - pstop->counter_in[0]);
+#if defined(SV2)
+      pstop->counter_sum[ENTRY_4] += (_rtc() - pstop->counter_in[ENTRY_4]);
+#else
+      pstop->counter_sum[ENTRY_4] += (irtc_() - pstop->counter_in[ENTRY_4]);
+#endif
+#endif
+      pstop->counter_stopped = 1;
+    }
+  }
+}
+
+
+static void
+stopstart_hpm(int tid, drhook_key_t *pstop, drhook_key_t *pstart)
+{
+  const char *name = "stopstart_hpm";
+  int i, rc;
+
+  if (!hpm_tid_init || !hpm_tid_init[tid-1]) init_hpm(tid);
+
+  if (pstop && pstop->counter_in && !pstop->counter_stopped) {
+#if defined(DT_FLOP)
+      pstop->counter_sum[0] += ((long long int) flop_() - pstop->counter_in[0]);
+#if defined(SV2)
+      pstop->counter_sum[ENTRY_4] += (_rtc() - pstop->counter_in[ENTRY_4]);
+#else
+      pstop->counter_sum[ENTRY_4] += (irtc_() - pstop->counter_in[ENTRY_4]);
+#endif
+#endif
+    pstop->counter_stopped = 1;
+  }
+
+  if (pstart) {
+    if (!pstart->counter_in ) pstart->counter_in  = calloc_drhook(MAX_COUNTERS, sizeof(*pstart->counter_in ));
+    if (!pstart->counter_sum) pstart->counter_sum = calloc_drhook(MAX_COUNTERS, sizeof(*pstart->counter_sum));
+#if defined(DT_FLOP)
+      pstart->counter_in[0] = (long long int) flop_();
+#if defined(SV2)
+      pstart->counter_in[ENTRY_4] = _rtc();
+#else
+      pstart->counter_in[ENTRY_4] = irtc_();
+#endif
+#endif
+     pstart->counter_stopped = 0;
+  }
+}
+
+#endif /*Interface to RS6K and SV2, XD1, XT3 */
+
+static double
+mflops_hpm(const drhook_key_t *keyptr)
+{
+  double mflops = 0;
+  if (keyptr && keyptr->counter_sum && keyptr->counter_sum[ENTRY_4] > 0) {
+    long long int sum = 0;
+#if defined(DT_FLOP)
+    sum = keyptr->counter_sum[0];
+#elif defined(PMAPI_P6)
+    /* IBM Power 6 specific */
+    sum = keyptr->counter_sum[0] + 2 * keyptr->counter_sum[1];
+#elif defined(PMAPI_P5_PLUS)
+    /* IBM Power 5+ specific */
+    sum = 2 * keyptr->counter_sum[1] + keyptr->counter_sum[3];
+#else
+    sum = keyptr->counter_sum[1] + keyptr->counter_sum[2] + keyptr->counter_sum[3] - keyptr->counter_sum[5];
+#endif
+    if (sum > 0)
+      mflops = (sum * MCYCLES)/keyptr->counter_sum[ENTRY_4];
+  }
+  return mflops;
+}
+
+static double
+mips_hpm(const drhook_key_t *keyptr)
+{
+  double mipsrate = 0;
+#if defined(DT_FLOP)
+  mipsrate = 0;
+#else
+  if (keyptr && keyptr->counter_sum && keyptr->counter_sum[ENTRY_4] > 0) {
+    mipsrate = (keyptr->counter_sum[ENTRY_6] * MCYCLES)/keyptr->counter_sum[ENTRY_4];
+  }
+#endif
+  return mipsrate;
+}
+
+static double
+divpc_hpm(const drhook_key_t *keyptr)
+{
+  double divpc = 0;
+#if defined(DT_FLOP)
+  divpc = 0;
+#else
+  if (keyptr && keyptr->counter_sum) {
+    long long int sum = 0;
+#if defined(PMAPI_P6)
+    /* IBM Power 6 specific */
+    sum = keyptr->counter_sum[0] + 2 * keyptr->counter_sum[1];
+    if (sum > 0) divpc = (keyptr->counter_sum[2]*100.0)/sum;
+#elif defined(PMAPI_P5_PLUS)
+    /* IBM Power 5+ specific */
+    sum = 2 * keyptr->counter_sum[1] + keyptr->counter_sum[3];
+    if (sum > 0) divpc = (keyptr->counter_sum[0]*100.0)/sum;
+#else
+    sum = keyptr->counter_sum[1] + keyptr->counter_sum[2] + keyptr->counter_sum[3] - keyptr->counter_sum[5];
+    if (sum > 0) divpc = (keyptr->counter_sum[0]*100.0)/sum;
+#endif
+  }
+#endif
+  return divpc;
+}
+
+static double
+mflop_count(const drhook_key_t *keyptr)
+{
+  double sum = 0;
+  if (keyptr && keyptr->counter_sum && keyptr->counter_sum[ENTRY_4] > 0) {
+#if defined(DT_FLOP)
+    sum = (keyptr->counter_sum[0]) * 1e-6;
+#elif defined(PMAPI_P6)
+    /* IBM Power 6 specific */
+    sum = (keyptr->counter_sum[0] + 2 * keyptr->counter_sum[1]) * 1e-6;
+#elif defined(PMAPI_P5_PLUS)
+    /* IBM Power 5+ specific */
+    sum = (2 * keyptr->counter_sum[1] + keyptr->counter_sum[3]) * 1e-6;
+#else
+    sum = (keyptr->counter_sum[1] + keyptr->counter_sum[2] + keyptr->counter_sum[3] - keyptr->counter_sum[5]) * 1e-6;
+#endif
+    if (sum < 0) sum = 0;
+  }
+  return sum;
+}
+
+static double
+mip_count(const drhook_key_t *keyptr)
+{
+  double sum = 0;
+#if defined(DT_FLOP)
+  sum = 0;
+#else
+  if (keyptr && keyptr->counter_sum && keyptr->counter_sum[ENTRY_4] > 0) {
+    sum = keyptr->counter_sum[ENTRY_6] * 1e-6;
+  }
+#endif
+  return sum;
+}
+
+#endif /* HPM */
+
+
+/* 
+   this is result of moving some code from libodb.a
+   (odb/aux/util_ccode.c) for use by libifsaux.a
+   directly ; simplifies linking sequences.
+*/
+
+#include <stdio.h>
+#include <string.h>
+/* #include <malloc.h> */
+#include <stdlib.h>
+#include <signal.h>
+
+#define FORTRAN_CALL
+
+#if defined(CRAY) && !defined(SV2)
+#define util_cputime_  UTIL_CPUTIME
+#define util_walltime_ UTIL_WALLTIME
+#endif
+
+/* Portable CPU-timer (User + Sys) ; also WALL CLOCK-timer */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#undef MIN
+#undef MAX
+#include <sys/param.h>
+
+#include <sys/time.h>
+
+#if !defined(VPP)
+
+FORTRAN_CALL
+double util_walltime_()
+{
+  static double time_init = -1;
+  double time_in_secs;
+#if !defined(CRAYXT)
+  struct timeval tbuf;
+  if (gettimeofday(&tbuf,NULL) == -1) perror("UTIL_WALLTIME");
+
+  if (time_init == -1) time_init = 
+    (double) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0);
+
+  time_in_secs = 
+  (double) tbuf.tv_sec + (tbuf.tv_usec / 1000000.0) - time_init;
+#else
+  if (time_init == -1) time_init = dclock();
+  time_in_secs = dclock() - time_init;
+#endif
+
+  return time_in_secs;
+}
+
+#if defined(CRAYXT)
+/* Cray XT3/XT4 with catamount microkernel */
+
+FORTRAN_CALL
+double util_cputime_()
+{
+  return util_walltime_(); /* In absence of anything better */
+}
+
+#else
+
+extern clock_t times (struct tms *buffer);
+
+FORTRAN_CALL
+double util_cputime_()
+{
+  struct tms tbuf;
+  static int first_time = 1;
+  static double clock_ticks = 0;
+
+  (void) times(&tbuf);
+
+  if (first_time) {
+    clock_ticks = (double) sysconf(_SC_CLK_TCK);
+    first_time = 0;
+  }
+
+  return (tbuf.tms_utime + tbuf.tms_stime +
+          tbuf.tms_cutime + tbuf.tms_cstime) / clock_ticks; 
+}
+#endif
+
+#else 
+/* VPP */
+FORTRAN_CALL
+double util_walltime_() 
+{
+  double w, time_in_secs;
+  static double wallref = 0;
+  extern FORTRAN_CALL gettod_(double *);
+  if (wallref == 0) gettod_(&wallref);
+  gettod_(&w);
+  time_in_secs = (w - wallref) * 0.000001;
+  return time_in_secs;
+}
+#endif
+
+#ifdef VPP
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <sys/proc.h>
+#include <fcntl.h>
+
+static int fujitsu_getrusage(int who, struct rusage *rusage)
+{
+  int rc = -1;
+
+  if (rusage) rusage->ru_maxrss = 0;
+
+  if (who == RUSAGE_SELF && rusage) {
+    static int maxrss =  0;
+    static int oldpid = -1;
+    static char procfile[20] = "";
+    static char *pf = NULL;
+    /* static prpsinfo_t ps; */
+    static proc_t proc;
+    int pid = getpid();
+    static int fildes = -1;
+    unsigned int size;
+
+    if (oldpid != pid) {
+      oldpid = pid;
+      maxrss = 0;
+      pf = NULL;
+    }
+
+    if (!pf) {
+      sprintf(procfile,"/proc/%d",pid);
+      pf = procfile;
+      fildes = open(procfile, O_RDONLY);
+    }
+
+    if (fildes == -1) return rc;
+
+    /*
+    if (ioctl(fildes, PIOCPSINFO, &ps) == -1) {
+      perror("ioctl at fujitsu_getrusage(PIOCPSINFO)");
+      return rc;
+    }
+    */
+
+    if (ioctl(fildes, PIOCGETPR, &proc) == -1) {
+      perror("ioctl at fujitsu_getrusage(PIOCGETPR)");
+      return rc;
+    }
+
+    size  = /* ps.pr_usevpmem + */ proc.p_brksize + proc.p_stksize;
+    if (size > maxrss) maxrss = size;
+    rusage->ru_maxrss = maxrss;
+
+    /* close(fildes); */
+    rc = 0;
+  }
+  return rc;
+}
+#endif /* VPP */
+
+FORTRAN_CALL
+int util_ihpstat_(int *option)
+{
+  int ret_value = 0;
+
+#if defined(SGI) || defined(VPP)
+  if (*option == 1) {
+    struct rusage rusage;
+#ifdef SGI
+    int pagesize = 1024;
+    getrusage(0, &rusage);
+#endif
+#ifdef VPP
+    int pagesize = 1; /* getpagesize() */
+    fujitsu_getrusage(0, &rusage);
+#endif
+#if defined(SV2)
+    int pagesize = getpagesize();
+    getrusage(0, &rusage);
+#endif
+#if defined(XT3)
+    int pagesize = getpagesize();
+    getrusage(0, &rusage);
+#endif
+#if defined(XD1)
+    int pagesize = getpagesize();
+    getrusage(0, &rusage);
+#endif
+    ret_value = (rusage.ru_maxrss * pagesize + 7) / 8; /* In 8 byte words */
+  }
+#endif /* SGI or VPP */
+
+  return ret_value;
+}
diff --git a/odb/src/extras/ifsaux/support/endian.c b/odb/src/extras/ifsaux/support/endian.c
new file mode 100644
index 0000000..f4859f0
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/endian.c
@@ -0,0 +1,116 @@
+/* endian.c */
+
+/* 
+   Please note: the following 2 routines
+   cannot be named as "is_little_endian()"
+   and "is_big_endian()", since there is a clash
+   with the new Magics++ library  (by SS, 21-Mar-2006)
+
+   --> consequently "ec_" prefix was added
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int ec_is_little_endian()
+{
+  /* Little/big-endian runtime auto-detection */
+  const unsigned int ulbtest = 0x12345678;
+  const unsigned char *clbtest = (const unsigned char *)&ulbtest;
+  
+  if (*clbtest == 0x78) { 
+    /* We are on a little-endian machine */
+    return 1;
+  }
+  else { 
+    /* We are on a big-endian machine */
+    return 0;
+  }
+}
+
+int ec_is_big_endian()
+{
+  return !ec_is_little_endian();
+}
+
+/* Fortran interface */
+
+int ec_is_big_endian_()    { return ec_is_big_endian();    }
+int ec_is_little_endian_() { return ec_is_little_endian(); }
+
+/* A routine to be called at the very end in case MPI wasn't finalized */
+/* Registered *only* by MPL_INIT */
+/* Disable this feature via : export EC_MPI_ATEXIT=0 */
+
+void ec_mpi_atexit_(void)
+{
+  char *env = getenv("EC_MPI_ATEXIT");
+  int do_it = env ? atoi(env) : 1;
+  static int callnum = 0;
+  ++callnum;
+  if (do_it) {
+    if (callnum == 1) {
+      /* register */
+      atexit(ec_mpi_atexit_);
+    }
+    else if (callnum == 2) {
+      /* action : finish MPI via F90 cmpl_end (in cmpl_binding.F90) */
+      extern void cmpl_end_(int *);
+      int ierr = 0;
+      cmpl_end_(&ierr);
+    }
+  }
+}
+
+void ec_mpi_atexit(void)
+{
+  ec_mpi_atexit_();
+}
+
+void ec_set_umask_(void)
+{
+  char *env = getenv("EC_SET_UMASK");
+  if (env) {
+    int newmask;
+    int n = sscanf(env,"%o",&newmask);
+    if (n == 1) {
+      int oldmask = umask(newmask);
+      fprintf(stderr,
+	      "*** EC_SET_UMASK : new/old = %o/%o (oct), %d/%d (dec), %x/%x (hex)\n",
+	      newmask,oldmask,
+	      newmask,oldmask,
+	      newmask,oldmask);
+    } /* if (n == 1) */
+  } /* if (env) */
+}
+
+
+/* CALL ec_raise(6) == CALL abort() */
+
+void ec_raise_(const int *sig) { raise(*sig); }
+void ec_raise(const int *sig) { ec_raise_(sig); }
+
+/* CALL ec_exit(iexit_code) */
+
+void ec_exit_(const int *exit_code) { exit(exit_code ? *exit_code : 0); }
+void ec_exit(const int *exit_code) { ec_exit_(exit_code); }
+
+/* snprintf replacement for VPP/VPP5000's */
+
+#if defined(VPP5000) || defined(VPP)
+
+int snprintf(char *str, size_t size, const char *format, ...)
+{
+  int rc;
+  va_list ap;
+  va_start(ap, format);
+  rc = vsprintf(str, format, ap);
+  va_end(ap);
+  return rc;
+}
+
+#endif
diff --git a/odb/src/extras/ifsaux/support/env.c b/odb/src/extras/ifsaux/support/env.c
new file mode 100644
index 0000000..711fbce
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/env.c
@@ -0,0 +1,249 @@
+
+/* env.c */
+
+/* Implement Fortran-callable ec_getenv and ec_putenv,
+   since not all environments have getenv & putenv,
+   but Unix/C library always have them */
+
+/* Author: Sami Saarinen, ECMWF, 15-Mar-2006 */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "raise.h"
+
+extern char **environ; /* Global Unix var */
+static int numenv = 0;
+
+void
+ec_numenv_(int *n)
+{ /* Returns the number of environment variables currently active */
+  int j=0;
+  if (environ) {
+    for (; environ[j]; j++) { }
+  }
+  if (n) *n = j;
+  numenv = j; /* Not thread-safe */
+}
+
+
+void
+ec_numenv(int *n)
+{
+  ec_numenv_(n);
+}
+
+
+void
+ec_overwrite_env_(int *do_overwrite)
+{
+  if (do_overwrite) {
+    char *env = getenv("EC_OVERWRITE_ENV");
+    if (env) {
+      *do_overwrite = atoi(env);
+    }
+    else {
+      *do_overwrite = 0;
+    }
+  }
+}
+
+
+void
+ec_overwrite_env(int *do_overwrite)
+{
+  ec_overwrite_env_(do_overwrite);
+}
+
+
+void
+ec_strenv_(const int *i,
+	   char *value,
+	   /* Hidden arguments */
+	   const int valuelen)
+{ /* Returns (*i)'th environment number; 
+     Note: "Fortran", not "C" range between [1..numenv] */
+  int j = (i && environ) ? (*i) : 0;
+  memset(value, ' ', valuelen);
+  if (j >= 1 && j <= numenv) {
+    char *p = environ[--j];
+    if (p) {
+      int len = strlen(p);
+      if (valuelen < len) len = valuelen;
+      memcpy(value,p,len);
+    }
+  }
+}
+
+
+void
+ec_strenv(const int *i,
+	  char *value,
+	  /* Hidden arguments */
+	  const int valuelen)
+{
+  ec_strenv_(i, value, valuelen);
+}
+
+
+void
+ec_getenv_(const char *s,
+	   char *value,
+	   /* Hidden arguments */
+	   int slen,
+	   const int valuelen)
+{
+  char *env = NULL;
+  char *p = malloc(slen+1);
+  if (!p) {
+    fprintf(stderr,"ec_getenv_(): Unable to allocate %d bytes of memory\n", slen+1);
+    ABOR1("ec_getenv_(): Unable to allocate memory");
+  }
+  memcpy(p,s,slen);
+  p[slen]='\0';
+  memset(value, ' ', valuelen);
+  env = getenv(p);
+  if (env) {
+    int len = strlen(env);
+    if (valuelen < len) len = valuelen;
+    memcpy(value,env,len);
+  }
+  free(p);
+}
+
+
+void
+ec_getenv(const char *s,
+	   char *value,
+	   /* Hidden arguments */
+	   int slen,
+	   const int valuelen)
+{
+  ec_getenv_(s, value, slen, valuelen);
+}
+
+
+void
+ec_putenv_(const char *s,
+	   /* Hidden argument */
+	   int slen)
+{
+  const char *x = &s[slen-1];
+  /* strip trailing blanks first */
+  while (slen > 0 && *x == ' ') { --slen; --x; }
+  /* now go ahead */
+  if (slen > 0) {
+    char *p = malloc(slen+1);
+    if (!p) {
+      fprintf(stderr,"ec_putenv_(): Unable to allocate %d bytes of memory\n", slen+1);
+      ABOR1("ec_putenv_(): Unable to allocate memory");
+    }
+    memcpy(p,s,slen);
+    p[slen]='\0';
+    putenv(p);
+    /* Cannot free(p); , since putenv() uses this memory area for good ;-( */
+  }
+}
+
+
+void
+ec_putenv(const char *s,
+	  /* Hidden argument */
+	  int slen)
+{
+  ec_putenv_(s,slen);
+}
+
+
+void
+ec_putenv_nooverwrite_(const char *s,
+		       /* Hidden argument */
+		       int slen)
+{
+  const char *x = &s[slen-1];
+  /* strip trailing blanks first */
+  while (slen > 0 && *x == ' ') { --slen; --x; }
+  /* now go ahead */
+  if (slen > 0) {
+    char *eq = NULL;
+    char *p = malloc(slen+1);
+    if (!p) {
+      fprintf(stderr,"ec_putenv_nooverwrite_(): Unable to allocate %d bytes of memory\n", slen+1);
+      ABOR1("ec_putenv_nooverwrite_(): Unable to allocate memory");
+    }
+    memcpy(p,s,slen);
+    p[slen]='\0';
+    eq = strchr(p,'=');
+    if (eq) {
+      char *env = NULL;
+      *eq = '\0';
+      env = getenv(p);
+      if (env) {
+	/* Already found ==> do not overwrite */
+	free(p);
+	return;
+      }
+      else {
+	/* Reset '=' back and continue with putenv() */
+	*eq = '=';
+      }
+    }
+    putenv(p);
+    /* Cannot free(p); , since putenv() uses this memory area for good ;-( */
+  }
+}
+
+
+void
+ec_putenv_nooverwrite(const char *s,
+		      /* Hidden argument */
+		      int slen)
+{
+  ec_putenv_nooverwrite_(s,slen);
+}
+
+
+unsigned int
+ec_sleep_(const int *nsec)
+{
+  return sleep((nsec && *nsec > 0) ? *nsec : 0);
+}
+
+
+unsigned int
+ec_sleep(const int *nsec)
+{
+  return ec_sleep_(nsec);
+}
+
+
+/* Microsecond-sleep, by S.Saarinen, 25-jan-2008 */
+
+void  /* Global, C-callable, too */
+ec_microsleep(int usecs) {
+  if (usecs > 0) {
+    struct timeval t;
+    t.tv_sec =  usecs/1000000;
+    t.tv_usec = usecs%1000000;
+    (void) select(0, NULL, NULL, NULL, &t);
+  }
+}
+
+
+void
+ec_usleep_(const int *usecs)
+{
+  if (usecs && *usecs > 0) ec_microsleep(*usecs);
+}
+
+
+void
+ec_usleep(const int *usecs)
+{
+  ec_usleep_(usecs);
+}
diff --git a/odb/src/extras/ifsaux/support/gstats.F90 b/odb/src/extras/ifsaux/support/gstats.F90
new file mode 100644
index 0000000..a4dc375
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/gstats.F90
@@ -0,0 +1,397 @@
+SUBROUTINE GSTATS(KNUM,KSWITCH)
+
+!**** *GSTATS*  - Gather timing statistics
+
+!     PURPOSE.
+!     --------
+!       To gather timings for subsequent output by routine STATS_OUTPUT 
+
+
+!**   INTERFACE.
+!     ----------
+!       *CALL* *GSTATS(KNUM,KSWITCH)
+
+!        EXPLICIT ARGUMENTS
+!        --------------------
+!        KNUM - timing event number (for list of already defined events
+!               see routine STATS_OUTPUT)
+!        KSWITCH  - KSWITCH=0 - switch on timer
+!                   KSWITCH=1 - switch off timer
+!                   KSWITCH=2 - suspend timer
+!                   KSWITCH=3 - resume  timer
+
+!        IMPLICIT ARGUMENTS
+!        --------------------
+!        Module YOMSTATS
+
+!     METHOD.
+!     -------
+
+
+!     EXTERNALS.   USER_CLOCK - timing routine
+!     ----------   MPL_BARRIER - syncronization of processors
+
+!     REFERENCE.
+!     ----------
+!        ECMWF Research Department documentation of the IFS
+
+!     AUTHOR.
+!     -------
+!        Mats Hamrud ECMWF
+
+!     MODIFICATIONS.
+!     --------------
+!        ORIGINAL : 98-11-15
+!        D.Salmond: 02-02-25  Return if not master thread when called from a 
+!                             parallel region. 
+!        J.Hague:   03-06-11  Memory tracing (for NSTATS_MEM MPI tasks)
+!        G.Mozdzynski: 18 Apr 2008 Many corrections to gstats,
+!                             see LLFINDSUMB - when set is used detect gstat counter problems.
+!        G.Mozdzynski: 20 Jan 2010 Further corrections to gstats to get timed sections and
+!                             SUMB to 100 percent of the total time.
+!     ------------------------------------------------------------------
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPIB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+
+USE YOMGSTATS  
+USE MPL_MODULE
+USE OML_MOD
+
+IMPLICIT NONE
+
+INTEGER(KIND=JPIM),INTENT(IN) :: KNUM
+INTEGER(KIND=JPIM),INTENT(IN) :: KSWITCH
+
+INTEGER(KIND=JPIM) :: IMOD,ICALL
+INTEGER(KIND=JPIM) :: IIMEM, IIPAG, IIMEMC
+INTEGER(KIND=JPIB) :: IMEM, IMEMH, IMEMS, IMEMC, IPAG, INUM
+INTEGER(KIND=JPIB) :: GETRSS, GETHWM, GETSTK, GETCURHEAP, GETPAG
+EXTERNAL GETRSS, GETHWM, GETSTK, GETCURHEAP, GETPAG
+REAL(KIND=JPRB) :: ZTIMED,ZCLOCK,ZCLOCK1,ZTIME,ZTCPU,ZVCPU
+LOGICAL :: LLFIRST=.TRUE.
+LOGICAL :: LLMFIRST=.TRUE.
+  CHARACTER(LEN=32), SAVE :: CCDESC_DRHOOK(JPMAXSTAT)
+  CHARACTER(LEN=32), SAVE :: CCDESC_BARR(JPMAXSTAT)
+SAVE IIMEM, IIPAG, IIMEMC
+
+INTEGER(KIND=JPIM),SAVE :: NUM_THREADS
+REAL(KIND=JPRB),ALLOCATABLE,SAVE :: ZHOOK_HANDLE(:)
+REAL(KIND=JPRB),SAVE :: ZHOOK_HANDLE_COMMS, ZHOOK_HANDLE_COMMS1
+REAL(KIND=JPRB),SAVE :: ZHOOK_HANDLE_TRANS
+REAL(KIND=JPRB),SAVE :: ZHOOK_HANDLE_BARR
+CHARACTER*4 CC
+
+CHARACTER (LEN = 10) ::  CLDATEOD,CLZONEOD
+INTEGER(KIND=JPIM) :: IVALUES(8)
+
+INTEGER(KIND=JPIM) :: NMAX_STATS, KULNAM
+
+! Change LLFINDSUMB to TRUE to add diagnostics to help find SUMB times
+! Note that a similar setting exists in dr_hook_util for the same objective
+LOGICAL :: LLFINDSUMB=.FALSE.
+INTEGER(KIND=JPIM),SAVE :: ISUMBSTACK(10)
+INTEGER(KIND=JPIM) :: J
+REAL(KIND=JPRB) :: ZSUM,ZSUMB,ZTOT
+
+INTERFACE
+#include "user_clock.h"
+END INTERFACE
+
+! write(0,*) "GSTATS:LSTATS,JPMAXSTAT,LGSTATS_LABEL,KNUM=",LSTATS,JPMAXSTAT,LGSTATS_LABEL,KNUM
+
+IF(LSTATS) THEN
+
+! only process gstats calls for master thread
+
+  IF(OML_MY_THREAD() > 1)GOTO 99999
+
+  IF(.NOT.ALLOCATED(ZHOOK_HANDLE))THEN
+    NUM_THREADS=OML_MAX_THREADS()
+    ALLOCATE(ZHOOK_HANDLE(NUM_THREADS))
+  ENDIF
+
+  IF(LGSTATS_LABEL)THEN
+    DO INUM=1,JPMAXSTAT
+      WRITE(CC,'(I4)')INUM
+      CCDESC_BARR(INUM)='>BAR-'//CCDESC(INUM)(1:21)//'('//CC//')'
+    ENDDO
+    DO INUM=1,JPMAXSTAT
+      WRITE(CC,'(I4)')INUM
+!     write(6,*) inum,cctype(inum)
+      IF(CCTYPE(INUM).EQ."TRS".OR.CCTYPE(INUM).EQ.'MP-'.OR.CCTYPE(INUM).EQ.'MPL'&
+                            & .OR.CCTYPE(INUM).EQ.'BAR'.OR.CCTYPE(INUM).EQ.'OMP') THEN
+        CCDESC_DRHOOK(INUM)='>'//CCTYPE(INUM)//'-'//CCDESC(INUM)(1:21)//'('//CC//')'
+      ENDIF
+    ENDDO
+    LGSTATS_LABEL=.FALSE.
+  ENDIF
+!     ------------------------------------------------------------------
+
+!J  IF(KNUM/=0) THEN
+!J    IF(LSYNCSTATS .AND.(KSWITCH==0.OR. KSWITCH==2)) THEN
+!J      IF(.NOT.OML_IN_PARALLEL().AND. KNUM < 500 )THEN
+!J        IF(LHOOK)CALL DR_HOOK(CCDESC_BARR(KNUM),0,ZHOOK_HANDLE_BARR)
+!J        CALL MPL_BARRIER(CDSTRING='GSTATS:')
+!J        IF(LHOOK)CALL DR_HOOK(CCDESC_BARR(KNUM),1,ZHOOK_HANDLE_BARR)
+!J      ENDIF
+!J    ENDIF
+!J  ENDIF
+
+  CALL USER_CLOCK(PELAPSED_TIME=ZCLOCK)
+  IF (LSTATSCPU.OR.KNUM==0) THEN
+    CALL USER_CLOCK(PTOTAL_CP=ZTCPU,PVECTOR_CP=ZVCPU)
+  ELSE
+    ZTCPU = 0.0_JPRB
+    ZVCPU = 0.0_JPRB
+  ENDIF
+
+  IF (LHOOK .AND. (KSWITCH == 0 .OR. KSWITCH == 1)) THEN
+!   write(0,*) "KNUM,SWITCH=",KNUM,KSWITCH
+!   write(0,*) "CCTYPE=",CCTYPE(KNUM)
+!   write(0,*) "CCDESC_DRHOOK=",CCDESC_DRHOOK(KNUM)
+    IF(CCTYPE(KNUM).EQ."TRS")THEN
+      CALL DR_HOOK(CCDESC_DRHOOK(KNUM),KSWITCH,ZHOOK_HANDLE_TRANS)
+    ELSEIF(CCTYPE(KNUM).EQ.'MP-')THEN
+      CALL DR_HOOK(CCDESC_DRHOOK(KNUM),KSWITCH,ZHOOK_HANDLE_COMMS)
+    ELSEIF(CCTYPE(KNUM).EQ.'MPL'.AND.KNUM.NE.682)THEN
+      CALL DR_HOOK(CCDESC_DRHOOK(KNUM),KSWITCH,ZHOOK_HANDLE_COMMS1)
+    ELSEIF(CCTYPE(KNUM).EQ.'OMP')THEN
+      CALL DR_HOOK(CCDESC_DRHOOK(KNUM),KSWITCH,ZHOOK_HANDLE)
+    ELSEIF(CCTYPE(KNUM).EQ.'BAR')THEN
+      CALL DR_HOOK(CCDESC_DRHOOK(KNUM),KSWITCH,ZHOOK_HANDLE_BARR)
+    ENDIF
+! measure GSTATS HOOK overhead
+    CALL USER_CLOCK(PELAPSED_TIME=ZCLOCK1)
+    TIMESUM(401) = TIMESUM(401)+ZCLOCK1-ZCLOCK
+    NCALLS(401) = NCALLS(401)+1
+    ZCLOCK=ZCLOCK1
+  ENDIF
+
+  IF (LLFIRST) THEN
+
+!   write(0,*) "JPMAXSTAT:2=",JPMAXSTAT
+
+    NCALLS(:) = 0
+    NSWITCHVAL(:) = -1
+    TIMESUM(:) = 0.0_JPRB
+    TIMESQSUM(:) = 0.0_JPRB
+    TIMEMAX(:) = 0.0_JPRB
+    TIMESUMB(:) = 0.0_JPRB
+    IF( LLFINDSUMB )THEN
+      ISUMBSTACK(:)=0
+    ENDIF
+    TTCPUSUM(:) = 0.0_JPRB
+    TVCPUSUM(:) = 0.0_JPRB
+    TIMELCALL(:) = ZCLOCK
+    CCDESC=""
+    CCTYPE=""
+    NTMEM      = 0
+    NTMEM(:,5) = 99999999
+    IIMEM=0
+    IIPAG=0
+    IIMEMC=0
+    TIME_LAST_CALL = ZCLOCK
+    LLFIRST = .FALSE.
+  ENDIF
+
+  IF(KNUM < 0.OR. KNUM > JPMAXSTAT) CALL ABOR1('GSTATS')
+  IF(KSWITCH == 0.OR. KSWITCH == 1) THEN
+    NCALLS(KNUM) = NCALLS(KNUM)+1
+  ENDIF
+  IMOD = MOD(NCALLS(KNUM),2)
+  IF(.NOT.((KSWITCH == 0.AND. IMOD == 1) .OR.&
+   &(KSWITCH == 2.AND. IMOD == 1) .OR.&
+   &(KSWITCH == 3.AND. IMOD == 1) .OR.&
+   &(KSWITCH == 1.AND. IMOD == 0))) THEN
+    WRITE(JPERR,*) 'KNUM,KSWITCH,IMOD,NCALLS(KNUM)',&
+     &KNUM,KSWITCH,IMOD,NCALLS(KNUM)
+    CALL ABOR1('GSTATS')
+  ENDIF
+
+! WRITE(0,'("GSTATS(SUMB): ",I4,2X,I1,2X,A40)') KNUM,KSWITCH,CCDESC(KNUM)
+
+  NSWITCHVAL(KNUM)=KSWITCH
+
+  IF( KSWITCH == 0 ) THEN
+! Start timing event
+    IF(KNUM>=500)THEN
+      ZTIMED = ZCLOCK-TIME_LAST_CALL
+      TIMESUMB(KNUM) = TIMESUMB(KNUM)+ZTIMED
+    ELSE
+      ZTIMED = 0.0_JPRB
+    ENDIF
+
+    IF( LLFINDSUMB .AND. MYPROC_STATS <= 2 )THEN
+!     diagnostic code to find source of sumb (this should only be activated temporarily)
+      DO J=9,1,-1
+        ISUMBSTACK(J+1)=ISUMBSTACK(J)
+      ENDDO
+      ISUMBSTACK(1)=KNUM
+      IF( ZTIMED > 0.1 .AND. (TIMESUMB(KNUM) > 1.0) )THEN
+        WRITE(0,'("GSTATS(SUMB): KNUM=",I4," ZTIMED=",F10.6," TIMESUMB=",F10.6)')&
+        & KNUM,ZTIMED,TIMESUMB(KNUM)
+        DO J=1,10
+          IF( ISUMBSTACK(J) > 0 )THEN
+            WRITE(0,'("GSTATS(SUMB): ",I4,2X,I8,2X,A40)')ISUMBSTACK(J),&
+             & NCALLS(ISUMBSTACK(J)),CCDESC(ISUMBSTACK(J))
+          ENDIF
+        ENDDO
+      ENDIF
+!     check if grouped counters are overlapping
+      DO J=0,JPMAXSTAT
+        IF( J /= KNUM )THEN
+          IF( CCTYPE(J   )/='   '.AND.CCTYPE(J   )/='TRS'.AND.CCTYPE(J   )/='MP-' .AND.&
+           &  CCTYPE(KNUM)/='   '.AND.CCTYPE(KNUM)/='TRS'.AND.CCTYPE(KNUM)/='MP-' )THEN
+            IF( NSWITCHVAL(J)==0.OR.NSWITCHVAL(J)==3 )THEN
+              WRITE(0,'("GSTATS(SUMB): OVERLAPPING COUNTERS ",I4,2X,I4)')KNUM,J
+            ENDIF
+          ENDIF
+        ENDIF
+      ENDDO
+    ENDIF
+
+    THISTIME(KNUM) = 0.0_JPRB
+    TIMELCALL(KNUM) = ZCLOCK
+    TTCPULCALL(KNUM) = ZTCPU
+    TVCPULCALL(KNUM) = ZVCPU
+    THISTCPU(KNUM) = 0.0_JPRB
+    THISVCPU(KNUM) = 0.0_JPRB
+    IF(MYPROC_STATS.LE.NSTATS_MEM.AND.MYPROC_STATS.NE.0) THEN
+!     CALL getrss(IMEM)
+      IMEM = getrss()/1024
+      IPAG = getpag()
+      IMEMH = gethwm()/1024
+      IMEMS = getstk()/1024
+      IMEMC = 0
+      IF(LSTATS_ALLOC) IMEMC = GETCURHEAP()/1024
+      IF(IMEM > IIMEM.OR.IPAG > IIPAG.OR.(LSTATS_ALLOC.AND.(IMEMC.NE.IIMEMC))) THEN
+        IF(LLMFIRST) THEN
+          WRITE(0,*) ".---------------------------------------------------------"
+          WRITE(0,*) "| Memory trace details"
+          WRITE(0,*) "| --------------------"
+          WRITE(0,*) "| Memory examined at each GSTATS call if NSTATS_MEM>0."
+          WRITE(0,*) "| Header for each trace line is:"    
+          WRITE(0,*) "|"
+          WRITE(0,*) "|   RSS_INC: Increase in RSS_MAX (KB)"
+          WRITE(0,*) "|   RSS_MAX: Maximum real working set so far (KB)"
+          WRITE(0,*) "|   HEAP_MX: High Water Mark for heap so far (KB)"
+          WRITE(0,*) "|   STK:     Current Stack usage (KB)"
+          WRITE(0,*) "|   PGS:     Page faults w I/O since last trace line"
+          WRITE(0,*) "|   CALL:    Number of gstats call"
+          WRITE(0,*) "|   HEAP:    Current malloc'd total (KB)"
+          WRITE(0,*) "|" 
+          WRITE(0,*) "| Trace line written for NSTATS_MEM MPI tasks if RSS_MAX"
+          WRITE(0,*) "| RSS_MAX increases, PGS>0, or HEAP changed"
+          WRITE(0,*) "| (if LTATS_ALLOC=.TRUE.)"
+          WRITE(0,*) "`---------------------------------------------------------"
+          WRITE(0,*) ""
+          WRITE(0,'(A10,A5,21X,A7,2A8,A7,A5,A5,A8)') &
+           & "MEMORY    "," KNUM","RSS_INC"," RSS_MAX"," HEAP_MX","    STK", &
+           & "  PGS"," CALL","    HEAP"
+          LLMFIRST=.FALSE.
+        ENDIF
+        WRITE(0,'(A10,I5,1X,A20,1X,I6,2(1X,I7),1X,I6,1X,I4,1X,I4,1X,I7)') &
+             & "MEMORY bfr",KNUM,CCDESC(KNUM),IMEM-IIMEM,IMEM,IMEMH,IMEMS, &
+             & IPAG-IIPAG,(NCALLS(KNUM)+1)/2,IMEMC
+      ENDIF
+      NTMEM(KNUM,2)=IMEM
+      IIMEM=IMEM
+      IIPAG=IPAG
+      IIMEMC=IMEMC
+    ENDIF
+  ELSEIF( KSWITCH == 1 ) THEN
+! Finish timing event
+    ZTIME = THISTIME(KNUM)+(ZCLOCK-TIMELCALL(KNUM))
+    TIMESUM(KNUM) = TIMESUM(KNUM)+ZTIME
+    TIMESQSUM(KNUM) = TIMESQSUM(KNUM)+ZTIME**2
+    TIMEMAX(KNUM) = MAX(TIMEMAX(KNUM),ZTIME)
+    TTCPUSUM(KNUM) = TTCPUSUM(KNUM)+THISTCPU(KNUM)+ZTCPU-TTCPULCALL(KNUM)
+    TVCPUSUM(KNUM) = TVCPUSUM(KNUM)+THISVCPU(KNUM)+ZVCPU-TVCPULCALL(KNUM)
+    IF(MYPROC_STATS.LE.NSTATS_MEM.AND.MYPROC_STATS.NE.0) THEN
+!     CALL getrss(IMEM)
+      IMEM = GETRSS()/1024
+      IPAG = GETPAG()
+      IMEMH = GETHWM()/1024
+      IMEMS = GETSTK()/1024
+      IMEMC = 0
+      IF(LSTATS_ALLOC) IMEMC = GETCURHEAP()/1024
+      IF(IMEM > IIMEM.OR.IPAG > IIPAG.OR.(LSTATS_ALLOC.AND.(IMEMC.NE.IIMEMC))) THEN
+        WRITE(0,'(A10,I5,1X,A20,1X,I6,2(1X,I7),1X,I6,1X,I4,1X,I4,1X,I7)') &
+             & "MEMORY aft ",KNUM,CCDESC(KNUM),IMEM-IIMEM,IMEM,IMEMH,IMEMS, &
+             & IPAG-IIPAG,NCALLS(KNUM)/2,IMEMC
+      ENDIF
+      IIMEM=IMEM
+      IIPAG=IPAG
+      IIMEMC=IMEMC 
+      IMEM=IMEM-NTMEM(KNUM,2)
+      NTMEM(KNUM,4)=NTMEM(KNUM,4)+IMEM
+      IF(IMEM > NTMEM(KNUM,1)) THEN
+        NTMEM(KNUM,1)=IMEM
+        NTMEM(KNUM,3)=NCALLS(KNUM)
+      ENDIF
+      IF(IMEM < NTMEM(KNUM,5)) NTMEM(KNUM,5)=IMEM
+    ENDIF
+! Save counters that result in large delays
+    IF( KNUM >= 500 .AND. NCALLS(KNUM)/2 > 10 )THEN
+      IF( ZTIME > TIMESUM(KNUM)/FLOAT(NCALLS(KNUM)/2) + 0.2_JPRB )THEN
+        ! ignore counters 1007 and 1013 due to NFRLW frequency LW radiation calls 
+        ! in ec_phys_tl and ec_phys_ad call trees
+        ! also ignore 635 and 636 due to increasing sujbwavallo matrix sizes
+        IF( KNUM /= 1007 .AND. KNUM /= 1013 .AND. KNUM /= 635 .AND. KNUM /= 636 )THEN
+          IF( NDELAY_INDEX < JPMAXDELAYS )THEN
+            NDELAY_INDEX=NDELAY_INDEX+1
+            NDELAY_COUNTER(NDELAY_INDEX)=KNUM
+            TDELAY_VALUE(NDELAY_INDEX)=ZTIME-TIMESUM(KNUM)/FLOAT(NCALLS(KNUM)/2)
+            CALL DATE_AND_TIME(CLDATEOD,CDELAY_TIME(NDELAY_INDEX),CLZONEOD,IVALUES)
+          ENDIF
+        ENDIF
+      ENDIF
+    ENDIF
+  ELSEIF( KSWITCH == 2 ) THEN
+! Suspend timing event
+    ZTIMED = ZCLOCK-TIMELCALL(KNUM)
+    THISTIME(KNUM) = THISTIME(KNUM)+ZTIMED
+    THISTCPU(KNUM) = THISTCPU(KNUM)+ZTCPU-TTCPULCALL(KNUM)
+    THISVCPU(KNUM) = THISVCPU(KNUM)+ZVCPU-TVCPULCALL(KNUM)
+  ELSEIF( KSWITCH == 3 ) THEN
+! Resume timing event
+    TIMELCALL(KNUM) = ZCLOCK
+    TTCPULCALL(KNUM) = ZTCPU
+    TVCPULCALL(KNUM) = ZVCPU
+    IF(KNUM>=500)THEN
+      ZTIMED = ZCLOCK-TIME_LAST_CALL
+      TIMESUMB(KNUM) = TIMESUMB(KNUM)+ZTIMED
+    ENDIF
+  ENDIF
+  IF(KNUM >= 500)THEN
+    TIME_LAST_CALL = ZCLOCK
+  ENDIF
+
+!   Trace stats
+  NCALLS_TOTAL = NCALLS_TOTAL+1
+  IF (LTRACE_STATS .AND. NCALLS_TOTAL <= NTRACE_STATS) THEN
+    ICALL = NCALLS_TOTAL
+    TIME_TRACE(ICALL) = ZCLOCK
+    NCALL_TRACE(ICALL) = (JPMAXSTAT+1)*KSWITCH+KNUM
+  ENDIF
+
+! measure gstats overhead
+  CALL USER_CLOCK(PELAPSED_TIME=ZCLOCK1)
+  TIMESUM(400) = TIMESUM(400)+ZCLOCK1-ZCLOCK
+  NCALLS(400) = NCALLS(400)+1
+  LAST_KSWITCH=KSWITCH
+  LAST_KNUM=KNUM
+
+! ZSUM=SUM(TIMESUM(500:JPMAXSTAT))
+! ZSUMB=SUM(TIMESUMB(500:JPMAXSTAT))
+! ZTOT=ZCLOCK1-TIMELCALL(0)
+! IF( (ZSUM+ZSUMB)/ZTOT >1.0_JPRB )THEN
+!   write(0,'("GSTATS_DEBUG: KNUM=",I6," KSWITCH=",I1," (zsum+zsumb)/ztot=",F10.6)')&
+!    &KNUM,KSWITCH,(zsum+zsumb)/ztot
+! ENDIF
+  
+ENDIF
+
+99999 CONTINUE
+END SUBROUTINE GSTATS
diff --git a/odb/src/extras/ifsaux/support/mpe_locking.c b/odb/src/extras/ifsaux/support/mpe_locking.c
new file mode 100644
index 0000000..9bd4c46
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/mpe_locking.c
@@ -0,0 +1,27 @@
+#ifdef VPP
+
+void mpe_lock_(int *lockid, int *status)
+{
+  int LockID = (*lockid) + 1;
+  *status = VPP_SemWait(0,LockID);
+}
+
+void mpe_unlock_(int *lockid,int *status)
+{
+  int LockID = (*lockid) + 1;
+  *status = VPP_SemPost(0,LockID);
+}
+
+#else
+
+void mpe_lock_(int *lockid, int *status)
+{
+  *status = 0;
+}
+
+void mpe_unlock_(int *lockid,int *status)
+{
+  *status = 0;
+}
+#endif
+
diff --git a/odb/src/extras/ifsaux/support/my_sync.c b/odb/src/extras/ifsaux/support/my_sync.c
new file mode 100644
index 0000000..adb8d3b
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/my_sync.c
@@ -0,0 +1,8 @@
+      void my_sync_()
+      {
+#ifdef RS6K
+#ifdef PMAPI_P6
+        asm("sync 1 " : );
+#endif
+#endif
+      }
diff --git a/odb/src/extras/ifsaux/support/timef.F b/odb/src/extras/ifsaux/support/timef.F
new file mode 100644
index 0000000..43f1a77
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/timef.F
@@ -0,0 +1,61 @@
+#if defined ( VPP )
+      function timef()
+      data ifirst/0/
+      save ifirst,zfirst
+c
+c   fujitsu special
+c
+      call gettod(ztimef)
+      ztimef=ztimef/1000.0
+c
+      if(ifirst.eq.0) then
+         ifirst=1
+         zfirst=ztimef
+         timef=0.0
+      else
+         timef=(ztimef-zfirst)
+      endif
+c
+      return
+      end
+#elif defined ( RS6K )
+      function timef()
+      integer*8 irtc
+      external irtc
+      data ifirst/0/
+      save ifirst,zfirst
+c
+      ztimef=irtc()*1.0e-6
+c
+      if(ifirst.eq.0) then
+         ifirst=1
+         zfirst=ztimef
+         timef=0.0
+      else
+         timef=(ztimef-zfirst)
+      endif
+c
+      return
+      end
+#else
+      function timef()
+      data ifirst/0/
+      save ifirst,zfirst
+
+c     This is a real time clock in milliseconds.
+c     Usage of Fortran90 intrinsic function.
+      CALL SYSTEM_CLOCK (COUNT=i_time1,COUNT_RATE=i_rate)
+      ztimef=float(i_time1)/float(i_rate)
+
+      if(ifirst.eq.0) then
+         ifirst=1
+         zfirst=ztimef
+         timef=0.0
+      else
+         timef=1000.0*(ztimef-zfirst)
+      endif
+
+      return
+      end
+
+#endif
diff --git a/odb/src/extras/ifsaux/support/user_clock.F90 b/odb/src/extras/ifsaux/support/user_clock.F90
new file mode 100644
index 0000000..d157f8d
--- /dev/null
+++ b/odb/src/extras/ifsaux/support/user_clock.F90
@@ -0,0 +1,76 @@
+SUBROUTINE USER_CLOCK(PELAPSED_TIME,PELAPSED_TIME_SINCE,PVECTOR_CP,PTOTAL_CP)
+
+!**** *USER_CLOCK* - interface to system dependent timer routines
+
+!     Purpose.
+!     --------
+!        Returns elapsed and CP from the start of execution.
+!        Elapsed time is made relative to the first call to USER_CLOCK.
+
+!**   Interface.
+!     ----------
+!        ZTIME=USER_CLOCK(PELAPSED_TIME,PELAPSED_TIME_SINCE,
+!                         PVECTOR_CP,PTOTAL_CP)
+
+!        Explicit arguments: (All are optional arguments)
+!                           PELAPSED_TIME=wall clock time (seconds)
+!                           PELAPSED_TIME_SINCE=wall clock time (seconds)
+!                             change from input value of this parameter
+!                           PVECTOR_CP=CP vector time  (seconds)
+!                           PTOTAL_CP=total CP time   (seconds)
+
+!     Author.
+!     -------
+!        D.Dent      *ECMWF*
+
+!     External References:
+!     -------------------
+
+!        TIMEF,CPTIME
+
+!     Modifications.
+!     --------------
+!        Original  : 97-09-25
+!     ----------------------------------------------------------
+
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+REAL(KIND=JPRB),INTENT(OUT) :: PELAPSED_TIME,PVECTOR_CP,PTOTAL_CP
+REAL(KIND=JPRB),INTENT(INOUT) :: PELAPSED_TIME_SINCE
+OPTIONAL            PELAPSED_TIME,PELAPSED_TIME_SINCE
+OPTIONAL            PVECTOR_CP,PTOTAL_CP
+REAL(KIND=JPRB)      :: ZVECTOR_CP,ZTOTAL_CP,ZWALL
+REAL(KIND=JPRB),EXTERNAL :: TIMEF
+
+
+! === END OF INTERFACE BLOCK ===
+IF(PRESENT(PELAPSED_TIME).OR. PRESENT(PELAPSED_TIME_SINCE)) THEN
+
+  ZWALL=TIMEF()
+!             TIMEF returns milliseconds since first call to TIMEF
+  IF(PRESENT(PELAPSED_TIME)) THEN
+    PELAPSED_TIME=ZWALL*1.0E-3_JPRB
+  ENDIF
+  IF(PRESENT(PELAPSED_TIME_SINCE)) THEN
+    PELAPSED_TIME_SINCE=ZWALL*1.0E-3_JPRB - PELAPSED_TIME_SINCE
+  ENDIF
+ENDIF
+
+IF( PRESENT(PVECTOR_CP) .OR. PRESENT(PTOTAL_CP) ) THEN
+  CALL CPTIME(ZVECTOR_CP,ZTOTAL_CP)
+ENDIF
+IF( PRESENT(PVECTOR_CP) ) THEN
+  PVECTOR_CP=ZVECTOR_CP
+ENDIF
+IF( PRESENT(PTOTAL_CP) ) THEN
+  PTOTAL_CP=ZTOTAL_CP
+ENDIF
+
+RETURN
+END SUBROUTINE USER_CLOCK
+
+
+
diff --git a/odb/src/extras/ifsaux/utilities/addrdiff.c b/odb/src/extras/ifsaux/utilities/addrdiff.c
new file mode 100644
index 0000000..5cefae7
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/addrdiff.c
@@ -0,0 +1,15 @@
+/* Address difference in bytes */
+
+void 
+addrdiff_(const char *p1, const char *p2, int *diff)
+{
+  *diff = (p2 - p1);
+}
+
+/* loc()-function */
+
+unsigned long long int
+loc_addr_(const char *p)
+{
+  return (unsigned long long int)(p - (const char *)0);
+}
diff --git a/odb/src/extras/ifsaux/utilities/countingsort.c b/odb/src/extras/ifsaux/utilities/countingsort.c
new file mode 100644
index 0000000..bbe0dae
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/countingsort.c
@@ -0,0 +1,366 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <signal.h>
+#include "intercept_alloc.h"
+#include "raise.h"
+
+/* ec_countingsort_() : Fortran-callable counting-sort */
+
+/*
+   by Sami Saarinen, ECMWF, 01/11/2007 : 1st working version
+
+   Algorithm derived from C++ implementation in Wikipedia
+   However, the index[]'ed version added by ourselves.
+*/
+
+/*
+   Methods:
+
+   0 : Unsigned 32-bit ints
+   1 :   Signed 32-bit ints
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   3 :          32-bit floats  (IEEE) : signbit +  8-bit exp + 23-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+#define SORT_UINT 0
+
+#define SORT_INT  1
+
+#define SORT_R64  2
+
+#define SORT_R32  3
+
+#define SORT_I64  4
+
+#define SORT_U64  5
+
+typedef unsigned long long int  Uint64;
+typedef          long long int  Sint64;
+typedef unsigned int            Uint32;
+typedef          int            Sint32;
+
+typedef          long long int   ll_t;
+typedef unsigned long long int u_ll_t;
+
+#define  ALLOC(x,size)    \
+ { ll_t bytes = (ll_t)sizeof(*x) * (size); \
+   bytes = (bytes < 1) ? 1 : bytes; \
+   x = THEmalloc(bytes); \
+   if (!x) { fprintf(stderr, \
+                     "malloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
+                     #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
+
+#define  CALLOC(x,size)    \
+ { ll_t sz = (ll_t)(size); \
+   sz = (sz < 1) ? 1 : sz; \
+   x = THEcalloc(sz, sizeof(*x)); \
+   if (!x) { ll_t bytes = (ll_t)sizeof(*x) * (sz); \
+             fprintf(stderr, \
+                     "calloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
+                     #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
+
+#define FREE(x)           if (x) { THEfree(x); x = NULL; }
+
+#ifdef DEBUG
+#define AZZERT(cond) if (cond) ABOR1("Azzertion failed: "#cond)
+#else
+#define AZZERT(cond) 
+#endif
+
+/* Applicable for 32-bits only */
+
+#define SIGNBIT32   0x80000000u
+#define MASKALL32   0xFFFFFFFFu
+
+#define CVMGM32(a,b,c) ( ((c) & SIGNBIT32) ? (a) : (b) )
+
+static const int Npasses32 = 2; /* i.e. 2 x 16-bit passes == 32-bits */
+
+/* Applicable for 64-bits only */
+
+#define SIGNBIT64   0x8000000000000000ull
+#define MASKALL64   0xFFFFFFFFFFFFFFFFull
+
+#define CVMGM64(a,b,c) ( ((c) & SIGNBIT64) ? (a) : (b) )
+
+static const int Npasses64 = 4; /* i.e. 4 x 16-bit passes == 64-bits */
+
+/* CountingSort */
+
+#define MASKALL16 0xFFFF
+
+#define NCOUNT (MASKALL16+1)
+
+typedef struct {
+  int *sorted;
+  int counts[NCOUNT];
+} cs_shared_t;
+
+#define FOR(i,s,e) for (i = s; i < e; ++i)
+
+#define SHIFTMASK(a,shift) ((int)(((a) >> shift) & mask))
+
+#define CntSort(T,NB,shift,idummy) \
+static void \
+CSortSM##shift##NB(const T A[], const int n, int local_index[], \
+                   const T idummy, cs_shared_t *cs, const int irev) \
+{ /* Note: A[] is a contiguous, stride=1, local data -- a shade copy of the original "void *Data"-array */ \
+  const T mask = MASKALL16; \
+  int i, tmp, nr, min = MASKALL16, max = min; \
+  FOR(i,0,n) { \
+    tmp = SHIFTMASK(A[i],shift); if (tmp < min) min = tmp; else if (tmp > max) max = tmp; \
+  } \
+  nr = max - min + 1; \
+  AZZERT(nr <= 0 || nr > NCOUNT); \
+  if (nr > 1) { /* i.e. max > min */ \
+    /* nr == 1 would have meant that all values were equal --> skip */ \
+    int j, icnt; \
+    int *counts = cs->counts; \
+    memset(counts, 0, nr * sizeof(*counts)); \
+    if (irev) { /* Reverse, descending order */ \
+      FOR(i,0,n) { tmp = max - SHIFTMASK(A[i],shift); AZZERT(tmp < 0 || tmp >= NCOUNT); ++counts[ tmp ]; } \
+    } \
+    else { /* Ascending order */ \
+      FOR(i,0,n) { tmp = SHIFTMASK(A[i],shift) - min; AZZERT(tmp < 0 || tmp >= NCOUNT); ++counts[ tmp ]; } \
+    } \
+    /* Cascade counts to get cumulative counts */ \
+    FOR(j,1,nr) counts[j] += counts[j-1]; \
+    { \
+      int *sorted = cs->sorted; \
+      if (!sorted) { ALLOC(sorted, n); cs->sorted = sorted; } \
+      if (irev) { /* Reverse, descending order */ \
+	for (i = n-1; i >= 0; --i) { \
+          j = local_index[i]; \
+	  tmp = max - SHIFTMASK(A[j],shift); AZZERT(tmp < 0 || tmp >= NCOUNT); \
+          icnt = --counts[ tmp ]; AZZERT(icnt < 0 || icnt >= n); \
+	  sorted[icnt] = j; \
+	} \
+      } \
+      else { /* Ascending order */ \
+	for (i = n-1; i >= 0; --i) { \
+          j = local_index[i]; \
+	  tmp = SHIFTMASK(A[j],shift) - min; AZZERT(tmp < 0 || tmp >= NCOUNT); \
+          icnt = --counts[ tmp ]; AZZERT(icnt < 0 || icnt >= n); \
+	  sorted[icnt] = j; \
+	} \
+      } \
+      memcpy(local_index, sorted, n * sizeof(int)); \
+    } \
+  } /* if (nr > 1) */ \
+}
+
+#define Helpers(T,NB) \
+static T *  \
+signmask##NB(const T Data[], int n, int inc, const int *index, int index_adj) \
+{ \
+  T *A = NULL; \
+  int i; \
+  ALLOC(A, n); \
+  if (index && index_adj == 0) { \
+    if (inc == 1) { \
+      FOR(i,0,n) { \
+        int j = index[i]; \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[j]); \
+        A[i] = Data[j] ^ mask; \
+      } \
+    } else { \
+      FOR(i,0,n) { \
+        int j = index[i]*inc; \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[j]); \
+        A[i] = Data[j] ^ mask; \
+      } \
+    } \
+  } \
+  else if (index) { \
+    if (inc == 1) { \
+      FOR(i,0,n) { \
+        int j = (index[i] - index_adj); \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[j]); \
+        A[i] = Data[j] ^ mask; \
+      } \
+    } else { \
+      FOR(i,0,n) { \
+        int j = (index[i] - index_adj)*inc; \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[j]); \
+        A[i] = Data[j] ^ mask; \
+      } \
+    } \
+  } else { \
+    if (inc == 1) { \
+      FOR(i,0,n) { \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[i]); \
+        A[i] = Data[i] ^ mask; \
+      } \
+    } else { \
+      FOR(i,0,n) { \
+        int j = i*inc; \
+        T mask = CVMGM##NB(MASKALL##NB, SIGNBIT##NB, Data[j]); \
+        A[i] = Data[j] ^ mask; \
+      } \
+    } \
+  } \
+  return A; \
+} \
+static T * \
+justcopy##NB(const T Data[], int n, int inc, const int *index, int index_adj) \
+{ \
+  T *A = NULL; \
+  int i; \
+  ALLOC(A, n); \
+  if (index && index_adj == 0) { \
+    if (inc == 1) { \
+      FOR(i,0,n) A[i] = Data[index[i]]; \
+    } else { \
+      FOR(i,0,n) A[i] = Data[index[i]*inc]; \
+    } \
+  } \
+  else if (index) { \
+    if (inc == 1) { \
+      FOR(i,0,n) A[i] = Data[(index[i]-index_adj)]; \
+    } else { \
+      FOR(i,0,n) A[i] = Data[(index[i]-index_adj)*inc]; \
+    } \
+  } \
+  else { \
+    if (inc == 1) { \
+      memcpy(A, Data, n * sizeof(T)); \
+    } else { \
+      FOR(i,0,n) A[i] = Data[i*inc]; \
+    } \
+  } \
+  return A; \
+} \
+static void \
+sorted##NB(T Data[], int n, int inc, const int local_index[], T work[]) \
+{ \
+  int i; \
+  if (inc == 1) { \
+    FOR(i,0,n) work[i] = Data[local_index[i]]; \
+    memcpy(Data, work, n * sizeof(T)); \
+  } \
+  else { \
+    FOR(i,0,n) work[i] = Data[local_index[i]*inc]; \
+    FOR(i,0,n) Data[i * inc] = work[i]; \
+  } \
+}
+
+
+static int *
+CreateIndex(int n)
+{
+  int *local_index = NULL;
+  int i;
+  ALLOC(local_index, n);
+  FOR(i,0,n) local_index[i] = i;
+  return local_index;
+}
+
+static void
+Local2GlobalIndex(int n, const int local_index[], int index[], void *work)
+{
+  int i;
+  int *tmpidx = work;
+  FOR(i,0,n) {
+    int lc = local_index[i];
+    AZZERT(lc < 0 || lc >= n);
+    tmpidx[i] = index[lc];
+  }
+  memcpy(index, tmpidx, n * sizeof(*index));
+}
+
+
+CntSort(Uint32,32,0,idummy)
+CntSort(Uint32,32,shift,shift)
+Helpers(Uint32,32)
+
+
+CntSort(Uint64,64,0,idummy)
+CntSort(Uint64,64,shift,shift)
+Helpers(Uint64,64)
+
+
+#define DoSort(T,copyfun,NB) { \
+  int j; \
+  int Npasses = Npasses##NB; \
+  int *local_index = NULL; \
+  T *data = Data; \
+  T *dada = copyfun(&data[addr], n, inc, index, index ? index_adj : 0); \
+  T shift = 0; \
+  cs_shared_t cs; \
+  cs.sorted = NULL; \
+  local_index = CreateIndex(n); \
+  CSortSM0##NB(dada, n, local_index, shift, &cs, irev); \
+  for (j=1; j<Npasses; j++) { \
+    shift += 16; \
+    CSortSMshift##NB(dada, n, local_index, shift, &cs, irev); \
+  } \
+  if (index) { \
+    Local2GlobalIndex(n, local_index, index, dada); \
+  } \
+  else { /* No index[] supplied */ \
+    sorted##NB(&data[addr], n, inc, local_index, dada); \
+  } \
+  FREE(local_index); \
+  FREE(cs.sorted); \
+  FREE(dada); \
+  rc = n; \
+}
+
+void
+ec_countingsort_(const    int *Mode,
+		 const    int *N,
+		 const    int *Inc,
+		 const    int *Start_addr,
+            	         void *Data,
+		          int *index,
+		 const    int *Nindex,
+		 const    int *Index_adj,
+		 const    int *Reverse,
+	                  int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+  int nidx = *Nindex; /* Must be >= n or otherwise the index[] is disregarded */
+  int index_adj = *Index_adj;
+  int irev = *Reverse;
+
+  if (n <= 0) goto finish;
+
+  if (nidx < n) index = NULL;
+  
+  switch (method) {
+  case SORT_UINT:
+    DoSort(Uint32,justcopy32,32);
+    break;
+  case SORT_INT:
+    DoSort(Uint32,signmask32,32);
+    break;
+  case SORT_R64:
+    DoSort(Uint64,signmask64,64);
+    break;
+  case SORT_R32:
+    DoSort(Uint32,signmask32,32);
+    break;
+  case SORT_I64:
+    DoSort(Uint64,signmask64,64);
+    break;
+  case SORT_U64:
+    DoSort(Uint64,justcopy64,64);
+    break;
+  default:
+    rc = -1;
+    break;
+  }
+
+ finish:
+  *retc = rc;
+}
+
diff --git a/odb/src/extras/ifsaux/utilities/ecqsort.c b/odb/src/extras/ifsaux/utilities/ecqsort.c
new file mode 100644
index 0000000..5c03ce4
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/ecqsort.c
@@ -0,0 +1,509 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <signal.h>
+#include "intercept_alloc.h"
+#include "raise.h"
+
+/* ecqsort_() : Fortran-callable quick-sort */
+
+/* 
+   by Sami Saarinen, ECMWF, 7/07/2005 : Interface derived from rsort32.c & rsort64.c
+           - " -            4/09/2006 : Dr.Hook call for kwiksort_u64_index
+           - " -            7/02/2007 : Intercepting alloc (IBM & NEC SX) + NEC SX vectorization
+           - " -            3/07/2007 : Rewritten to use qsort() standard library routine
+           - " -           15/10/2007 : Fast qsort() added for simple 1-dim cases (see ../include/ecsort_shared.h)
+           - " -           16/10/2007 : Reverse-flag added to avoid explicit negation of the array (cheaper)
+           - " -           03/12/2007 : Dr.Hook calls removed; disturbs when in OMP-region on IBM ; a compiler bug ?
+*/
+
+/* 
+   Methods:
+
+   0 : Unsigned 32-bit ints
+   1 :   Signed 32-bit ints
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   3 :          32-bit floats  (IEEE) : signbit +  8-bit exp + 23-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+typedef unsigned long long int  Uint64;
+typedef          long long int  Sint64;
+typedef unsigned int            Uint32;
+typedef          int            Sint32;
+
+typedef    short int            Sint16;
+typedef   signed char           Sint8;
+
+#ifdef __uxppx__
+#ifndef VPP
+#define VPP
+#endif
+#endif
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+typedef long long int ll_t;
+
+#define  ALLOC(x,size)    \
+ { ll_t bytes = (ll_t)sizeof(*x) * (size); \
+   bytes = (bytes < 1) ? 1 : bytes; \
+   x = THEmalloc(bytes); \
+   if (!x) { fprintf(stderr, \
+		     "malloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
+		     #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
+
+#define FREE(x)           if (x) { THEfree(x); x = NULL; }
+
+#if defined(NO_TRUNC) || defined(VPP) || defined(NECSX)
+/* For systems without trunc() -function [an extension of ANSI-C, but usually available] */
+#define trunc(x) ((x) - fmod((x),1))
+#else
+extern double trunc(double d);
+#endif
+
+#define MakeKwikSort(T) \
+typedef struct { \
+  const T *valueptr; \
+  int j; \
+  int idx; \
+} T##Str_t; \
+\
+static int \
+T##cmp(const T##Str_t *a, const T##Str_t *b) { \
+  if      ( *a->valueptr > *b->valueptr ) return  1; \
+  else if ( *a->valueptr < *b->valueptr ) return -1; \
+  else { /* *a->valueptr == *b->valueptr */ \
+    /* the next line is essential for the stable qsort() */ \
+    return (a->j > b->j) ? 1 : -1; \
+  } \
+} \
+static int \
+T##cmp_rev(const T##Str_t *a, const T##Str_t *b) { \
+  if      ( *a->valueptr < *b->valueptr ) return  1; \
+  else if ( *a->valueptr > *b->valueptr ) return -1; \
+  else { /* a->valueptr == b->valueptr */ \
+    /* the next line is essential for the stable qsort() */ \
+    return (a->j > b->j) ? 1 : -1; \
+  } \
+} \
+\
+static void \
+kwiksort_##T(const T v[], int n, int index[], int inc, \
+             int index_adj, int mode, int irev) \
+{ \
+  int j; \
+  T##Str_t *x = NULL; \
+  ALLOC(x, n); \
+  if (mode < 10) { \
+    /* index[] needs to be initialized */ \
+    if (inc == 1) { \
+      for (j=0; j<n; j++) { x[j].valueptr = &v[j]; \
+                            x[j].j = j; \
+                            x[j].idx = j + index_adj; /* C -> Fortran */ \
+                          } \
+    } \
+    else { \
+      for (j=0; j<n; j++) { x[j].valueptr = &v[j * inc]; \
+                            x[j].j = j; \
+                            x[j].idx = j + index_adj; /* C -> Fortran */ \
+                          } \
+    } \
+  } \
+  else { \
+    if (inc == 1) { \
+      for (j=0; j<n; j++) { \
+        int tmpidx = index[j] - index_adj; /* Fortran -> C */ \
+        x[j].valueptr = &v[tmpidx]; \
+        x[j].j = j; \
+        x[j].idx = index[j]; \
+      } \
+    } \
+    else { \
+      for (j=0; j<n; j++) { \
+        int tmpidx = index[j] - index_adj; /* Fortran -> C */ \
+        x[j].valueptr = &v[tmpidx * inc]; \
+        x[j].j = j; \
+        x[j].idx = index[j]; \
+      } \
+    } \
+  } \
+  qsort(x, n, sizeof(*x), \
+	irev ? \
+	(int (*)(const void *, const void *))T##cmp_rev : \
+	(int (*)(const void *, const void *))T##cmp); \
+  for (j=0; j<n; j++) index[j] = x[j].idx; /* Re-arranged indices */ \
+  FREE(x); \
+}
+
+#define MakeFastSort(T) \
+static int \
+T##fcmp(const T *a, const T *b) { \
+  if      ( *a > *b ) return  1; \
+  else if ( *a < *b ) return -1; \
+  else return 0; \
+} \
+static int \
+T##fcmp_rev(const T *a, const T *b) { \
+  if      ( *a < *b ) return  1; \
+  else if ( *a > *b ) return -1; \
+  else return 0; \
+} \
+\
+static void \
+FastSort_##T(T v[], int n, int irev) \
+{ \
+  qsort(v, n, sizeof(*v), \
+	irev ? \
+	(int (*)(const void *, const void *))T##fcmp_rev : \
+	(int (*)(const void *, const void *))T##fcmp); \
+}
+
+#define kwiksort(T) \
+MakeKwikSort(T) \
+MakeFastSort(T)
+
+#define SORT_UINT 0
+kwiksort(Uint32)
+
+#define SORT_INT  1
+kwiksort(Sint32)
+
+#define SORT_R64  2
+kwiksort(double)
+
+#define SORT_R32  3
+kwiksort(float)
+
+#define SORT_I64  4
+kwiksort(Sint64)
+
+#define SORT_U64  5
+kwiksort(Uint64)
+
+#define DoSort(T) { \
+  T *data = Data; \
+  { \
+    kwiksort_##T(&data[addr], n, index, inc, index_adj, mode, irev); \
+  } \
+}
+
+#define DoFastSort(T) { \
+  T *data = Data; \
+  { \
+    FastSort_##T(data, n, irev); \
+  } \
+}
+
+void 
+ecqsort_(const    int *Mode,
+	 const    int *N,
+	 const    int *Inc,
+	 const    int *Start_addr,
+	         void *Data,
+	          int  index[],
+	 const    int *Index_adj,
+	 const    int *Reverse,
+	          int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int index_adj = *Index_adj;
+  int irev = *Reverse;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  if (inc < 1) {
+    rc = -3;
+    goto finish;
+  }
+
+  switch (method) {
+  case SORT_UINT:
+    DoSort(Uint32);
+    break;
+  case SORT_INT:
+    DoSort(Sint32);
+    break;
+  case SORT_R64:
+    DoSort(double);
+    break;
+  case SORT_R32:
+    DoSort(float);
+    break;
+  case SORT_I64:
+    DoSort(Sint64);
+    break;
+  case SORT_U64:
+    DoSort(Uint64);
+    break;
+  }
+
+ finish:
+
+  *retc = rc;
+}
+
+void 
+ecqsortfast_(const    int *Mode,
+	     const    int *N,
+	             void *Data,
+	     const    int *Reverse,
+	              int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int irev = *Reverse;
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  switch (method) {
+  case SORT_UINT:
+    DoFastSort(Uint32);
+    break;
+  case SORT_INT:
+    DoFastSort(Sint32);
+    break;
+  case SORT_R64:
+    DoFastSort(double);
+    break;
+  case SORT_R32:
+    DoFastSort(float);
+    break;
+  case SORT_I64:
+    DoFastSort(Sint64);
+    break;
+  case SORT_U64:
+    DoFastSort(Uint64);
+    break;
+  }
+
+ finish:
+
+  *retc = rc;
+}
+
+#define MakeMergeFuncs(T)  \
+static int \
+T##_Merge(T data[], int amax, int bmax) \
+{ \
+  int i, j, N = amax + bmax; \
+  T *a = data; \
+  T *b = &data[amax]; \
+  i=amax-1; j=N-1; \
+  if (a[i] > b[0]) { \
+    int k; \
+    T *c = NULL; \
+    ALLOC(c, bmax); \
+    memcpy(c, b, bmax * sizeof(T)); \
+    k=bmax-1; \
+    while ((i >= 0) && (k >= 0)) { \
+      if (a[i] >= c[k]) data[j--] = a[i--]; else data[j--] = c[k--]; \
+    } \
+    while (k >= 0) data[j--] = c[k--]; \
+    FREE(c); \
+  } \
+  return N; \
+} \
+static int \
+T##_MergeIdx(const T data[], int amax, int bmax, int index[], const int rank[]) \
+{ \
+  int i, j, N = amax + bmax; \
+  int *a = index; \
+  int *b = &index[amax]; \
+  i=amax-1; j=N-1; \
+  if (data[a[i]] > data[b[0]]) { \
+    int k; \
+    int *c = NULL; \
+    ALLOC(c, bmax); \
+    memcpy(c, b, bmax * sizeof(int)); \
+    k=bmax-1; \
+    while ((i >= 0) && (k >= 0)) { \
+      T dai = data[a[i]]; \
+      T dck = data[c[k]]; \
+      if (dai > dck) index[j--] = a[i--]; \
+      else if (dai < dck) index[j--] = c[k--]; \
+      else { /* dai == dck : the rank[] decides */ \
+        if (rank[a[i]] > rank[c[k]]) index[j--] = a[i--]; else index[j--] = c[k--]; \
+      } \
+    } \
+    while (k >= 0) index[j--] = c[k--]; \
+    FREE(c); \
+  } \
+  return N; \
+} \
+static int \
+T##_Merge_rev(T data[], int amax, int bmax) \
+{ \
+  int i, j, N = amax + bmax; \
+  T *a = data; \
+  T *b = &data[amax]; \
+  i=amax-1; j=N-1; \
+  if (a[i] < b[0]) { \
+    int k; \
+    T *c = NULL; \
+    ALLOC(c, bmax); \
+    memcpy(c, b, bmax * sizeof(T)); \
+    k=bmax-1; \
+    while ((i >= 0) && (k >= 0)) { \
+      if (a[i] <= c[k]) data[j--] = a[i--]; else data[j--] = c[k--]; \
+    } \
+    while (k >= 0) data[j--] = c[k--]; \
+    FREE(c); \
+  } \
+  return N; \
+} \
+static int \
+T##_MergeIdx_rev(const T data[], int amax, int bmax, int index[], const int rank[]) \
+{ \
+  int i, j, N = amax + bmax; \
+  int *a = index; \
+  int *b = &index[amax]; \
+  i=amax-1; j=N-1; \
+  if (data[a[i]] < data[b[0]]) { \
+    int k; \
+    int *c = NULL; \
+    ALLOC(c, bmax); \
+    memcpy(c, b, bmax * sizeof(int)); \
+    k=bmax-1; \
+    while ((i >= 0) && (k >= 0)) { \
+      T dai = data[a[i]]; \
+      T dck = data[c[k]]; \
+      if (dai < dck) index[j--] = a[i--]; \
+      else if (dai > dck) index[j--] = c[k--]; \
+      else { /* dai == dck : the rank[] decides */ \
+        if (rank[a[i]] > rank[c[k]]) index[j--] = a[i--]; else index[j--] = c[k--]; \
+      } \
+    } \
+    while (k >= 0) index[j--] = c[k--]; \
+    FREE(c); \
+  } \
+  return N; \
+}
+
+MakeMergeFuncs(Uint32)
+MakeMergeFuncs(Sint32)
+MakeMergeFuncs(double)
+MakeMergeFuncs(float)
+MakeMergeFuncs(Sint64)
+MakeMergeFuncs(Uint64)
+
+#define DoMerge(T) { \
+  T *X = Data; \
+  X += addr; \
+  if (index && nidx >= n) { \
+    int j; \
+    if (index_adj) for (j=0; j<n; j++) index[j] -= index_adj; /* Fortran -> C */ \
+    rc = irev ? \
+      T##_MergeIdx_rev(X, amax, bmax, index, rank) : \
+      T##_MergeIdx(X, amax, bmax, index, rank); \
+    if (index_adj) for (j=0; j<n; j++) index[j] += index_adj; /* C -> Fortran */ \
+  } \
+  else { \
+    rc = irev ? T##_Merge_rev(X, amax, bmax) : T##_Merge(X, amax, bmax); \
+  } \
+}
+
+void ecmerge2_(const int *Mode, 
+	       const int *Start_addr,
+	       const int *Amax,
+	       const int *Bmax,
+	            void *Data,
+	             int *index,
+	       const int *Nidx,
+	       const int *Index_adj,
+	       const int *Reverse,
+	       const int  rank[],
+	             int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+  int amax = *Amax;
+  int bmax = *Bmax;
+  int n = amax + bmax;
+  int nidx = *Nidx;
+  int index_adj = *Index_adj;
+  int irev = *Reverse;
+  int rc = 0;
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  switch (method) {
+  case SORT_UINT:
+    DoMerge(Uint32);
+    break;
+  case SORT_INT:
+    DoMerge(Sint32);
+    break;
+  case SORT_R64:
+    DoMerge(double);
+    break;
+  case SORT_R32:
+    DoMerge(float);
+    break;
+  case SORT_I64:
+    DoMerge(Sint64);
+    break;
+  case SORT_U64:
+    DoMerge(Uint64);
+    break;
+  }
+
+ finish:
+  *retc = rc;
+}
diff --git a/odb/src/extras/ifsaux/utilities/fnecsx.c b/odb/src/extras/ifsaux/utilities/fnecsx.c
new file mode 100644
index 0000000..7c4c3ce
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/fnecsx.c
@@ -0,0 +1,388 @@
+/* fnecsx.c */
+
+/* 
+
+   This source file contains reverse-engineered functions that are called
+   when ALLOCATE & DEALLOCATE are issued in Fortran90 codes on NEC SX.
+
+   This facilitates memory monitoring and allocations in a similar way
+   as we can do on IBM (see also getcurheap.c) and 
+   provides unified interface to Dr.Hook with memory tracing/profiling.
+
+   To have any effect, compile with sxcc :
+
+   -DINTERCEPT_ALLOC
+   -DNECSX
+
+
+   Author: Sami Saarinen, ECMWF, 02-Feb-2007
+
+*/
+
+#include "intercept_alloc.h"
+
+#if defined(INTERCEPT_ALLOC)
+#if defined(NECSX)
+
+#include "raise.h"
+#include <stdlib.h>
+
+typedef long long int ll_t;
+typedef unsigned long long int u_ll_t;
+
+/* Maximum no of dimensions allowed in any given Fortran90 array */
+
+#define FNECSX_MAXDIM 7
+
+/*
+typedef struct {
+  ll_t lo;
+  ll_t hi;
+  ll_t stride;
+} dim_t ;
+*/
+
+#define FNECSX_NKEYS  3
+#define FNECSX_KEY_LO 0
+#define FNECSX_KEY_HI 1
+#define FNECSX_KEY_ST 2
+
+typedef struct {
+  u_ll_t *p;
+  int status;
+  int ndims;
+  ll_t s[FNECSX_MAXDIM][FNECSX_NKEYS];
+} desc_t;
+
+#if 0
+/* Logical, f.ex.: if (ALLOCATED(allocatable_array)) ... */
+extern ll_t fy_sallocd(desc_t *d);
+#endif
+
+/* For sxf90 -dw i.e. 4-byte int for istat in [DE]ALLOCATE(..., stat=istat) is required */
+extern void f_alloc(ll_t arg1, desc_t *d, int *stat, ll_t elsize);
+extern void f_deallc(ll_t arg1, desc_t *d, int *stat);
+
+/* For sxf90 -ew i.e. 8-byte int for istat in [DE]ALLOCATE(..., stat=istat) is required */
+extern void f_allocl(ll_t arg1, desc_t *d, ll_t *stat, ll_t elsize);
+extern void f_deallcl(ll_t arg1, desc_t *d, ll_t *stat);
+
+int EC_malloc_will_abort = 0; /* affects getcurheap.c when memory allocation fails in EC_malloc() */
+
+extern void necsx_trbk_fl_(const char *msg, const char *filename, int *lineno,
+			   int msglen, int filenamelen); /* from ../utilities/gentrbk.F90 */
+#define ERROR_MSG(msg) { \
+  int lineno = __LINE__; necsx_trbk_fl_(msg, __FILE__, &lineno, strlen(msg), sizeof(__FILE__)-1); }
+
+#else
+#undef INTERCEPT_ALLOC
+#endif
+#endif /* defined(INTERCEPT_ALLOC) */
+
+#if !defined(INTERCEPT_ALLOC)
+
+/* Other than NEC SX machines or when -DINTERCEPT_ALLOC was NOT supplied */
+
+void ec_envredo_() { }
+
+#else /* is indeed defined(INTERCEPT_ALLOC) */
+
+/* NEC SX with -DINTERCEPT_ALLOC */
+
+static int ec_prtdesc = -1;
+static int ec_initheap = 0;
+static unsigned int  ec_initval4 = 0;
+static u_ll_t        ec_initval8 = 0;
+static int ec_malloc = 1;
+
+static
+void init4(unsigned int p4[], ll_t n)
+{
+  u_ll_t tmp = ec_initval4;
+  ll_t j;
+  for (j=0; j<n; j++) p4[j] = tmp;
+}
+
+static
+void init8(u_ll_t p8[], ll_t n)
+{
+  u_ll_t tmp = ec_initval8;
+  ll_t j;
+  for (j=0; j<n; j++) p8[j] = tmp;
+}
+
+static
+void envinit()
+{
+  char *env;
+
+  /* Print array descriptor info */
+  env = getenv("EC_PRTDESC");
+  if (env) {
+    ec_prtdesc = atoi(env);
+    if (ec_prtdesc != 0) ec_prtdesc = 1;
+  }
+  else {
+    ec_prtdesc = 0;
+  }
+
+  /* Simulating the effect of "-init heap={zero|nan|0xXXXX}" */
+  env = getenv("EC_INITHEAP");
+  if (env) {
+    int len = strlen(env);
+    if (strcasecmp(env,"zero") == 0 || strcasecmp(env,"0") == 0) {
+      ec_initheap = 1; /* 1-byte long */
+      if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d\n",env,ec_initheap);
+    }
+    else if (strcasecmp(env,"nan") == 0) {
+      ec_initheap = 4; /* 4-bytes long */
+      ec_initval4 = 0x7fffffff;
+      if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%x (%u,%d)\n",
+			      env,ec_initheap,ec_initval4,ec_initval4,ec_initval4);
+    }
+    else if (len >= 2 && env[0] == '0' && (env[1] == 'x' || env[1] == 'X')) {
+      if (len <= 10) { /* 0x12345678 */
+	ec_initheap = 4;
+	sscanf(env,"0x%x",&ec_initval4);
+	if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%x (%u,%d)\n",
+				env,ec_initheap,ec_initval4,ec_initval4,ec_initval4);
+      }
+      else if (len > 10 && len <= 18) { /* 0x1234567890abcdef */
+	ec_initheap = 8;
+	sscanf(env,"0x%llx",&ec_initval8);
+	if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%llx (%llu,%lld)\n",
+				env,ec_initheap,ec_initval8,ec_initval8,ec_initval8);
+      }
+      else {
+	ec_initheap = 0;
+      }
+    }
+    else {
+      ec_initheap = 0;
+    }
+  }
+  else {
+    ec_initheap = 0;
+  }
+
+  /* Use EC_malloc/EC_calloc/EC_free (default) or malloc/calloc/free */
+  env = getenv("EC_MALLOC");
+  if (env) {
+    ec_malloc = atoi(env);
+    if (ec_malloc != 0) ec_malloc = 1;
+  }
+  else {
+    ec_malloc = 1;
+  }
+}
+
+void ec_envredo_() { envinit(); };
+
+static 
+void prtdesc(ll_t arg1, FILE *fp, const char *s, const desc_t *d, 
+	     const int *stat, ll_t elsize_in)
+{
+  if (ec_prtdesc == -1) {
+    envinit();
+    if (ec_prtdesc == 0) return;
+  }
+  if (fp && s && d) {
+    int j;
+    int ndims = d->ndims;
+    ll_t elsize = d->s[0][FNECSX_KEY_ST];
+    ll_t ntot = 1;
+    ll_t total_bytes;
+    ll_t nsave[FNECSX_MAXDIM];
+#pragma cdir altcode,loopcnt=FNECSX_MAXDIM
+    for (j=0; j<ndims; j++) {
+      ll_t n = d->s[j][FNECSX_KEY_HI] - d->s[j][FNECSX_KEY_LO] + 1;
+      ntot *= n;
+      nsave[j] = n;
+    }
+    if (((ntot/2)*2) != ntot) ntot++; /* mod(ntot,2) not 0 i.e. ntot is odd --> add 1 */
+    total_bytes = ntot * elsize + 1;
+    fprintf(fp, "=== %s : desc = 0x%llx [%lld] : arg1 = %lld, stat (addr) = 0x%llx\n",s,d,d,arg1,stat);
+    fprintf(fp,"p = 0x%llx [%lld] : status = %d, ndims = %d, elsize's = (%lld, %lld), total = %lld\n",
+	    d->p, d->p, d->status, ndims, elsize, elsize_in, total_bytes);
+    for (j=0; j<ndims; j++) {
+      ll_t n = nsave[j];
+      fprintf(fp,"[dim#%d] : lo = %lld, hi = %lld (n=%lld), stride = %lld\n",
+	      j+1, d->s[j][FNECSX_KEY_LO], d->s[j][FNECSX_KEY_HI], n, 
+	      d->s[j][FNECSX_KEY_ST]);
+    }
+    if (d->p) {
+      u_ll_t dummy = d->p[-1];
+      u_ll_t adjsize = d->p[-2];
+      u_ll_t keyptr = d->p[-3];
+      fprintf(fp,"\tdummy = %llu\n",dummy);
+      fprintf(fp,"\tadjsize (bytes) = %llu\n",adjsize);
+      fprintf(fp,"\tDr.Hook keyptr = 0x%llx [%llu]\n",keyptr,keyptr);
+    }
+  }
+}
+
+#if 0
+ll_t fy_sallocd(desc_t *d)
+{
+  if (ec_prtdesc) prtdesc(-1, stderr, "fy_sallocd", d, NULL, -1);
+  return (d && d->p && (d->status == 3 || d->status == 1)) ? 1 : 0;
+}
+#endif
+
+void f_alloc(ll_t arg1, desc_t *d, int *stat, ll_t elsize)
+{
+  const int istat_offset = 193;
+  int istat = 0;
+  const char *errmsg[2] = {
+    "Value of allocate-object must not be currently allocated array in ALLOCATE.", /* 193 */
+    "Could not allocate in ALLOCATE." /* 194 */
+  };
+  if (stat && stat == (int *)0x1) stat = NULL;
+  if (ec_prtdesc) prtdesc(arg1, stderr, "f_alloc>", d, stat, elsize);
+  if (d && (arg1 == 3 || arg1 == 2)) { 
+    /* arg1 == 3 : ALLOCATABLE array --> d->status becomes = 3
+       arg1 == 2 : POINTER array     --> d->status becomes = 1 */
+    int j;
+    int ndims = d->ndims;
+    u_ll_t *p = NULL;
+    void *vptr = NULL;
+    ll_t ntot = 1;
+    ll_t total_bytes;
+    ll_t nsave[FNECSX_MAXDIM];
+#pragma cdir altcode,loopcnt=FNECSX_MAXDIM
+    for (j=0; j<ndims; j++) {
+      ll_t n = d->s[j][FNECSX_KEY_HI] - d->s[j][FNECSX_KEY_LO] + 1;
+      ntot *= n;
+      nsave[j] = n;
+    }
+    if (((ntot/2)*2) != ntot) ntot++; /* mod(ntot,2) not 0 i.e. ntot is odd --> add 1 */
+    total_bytes = ntot * elsize + 1;
+    if (ec_initheap == 1) {
+      /* EC_INITHEAP=zero */
+      if (ec_malloc) {
+	vptr = EC_calloc(total_bytes,1);
+      }
+      else {
+	vptr = calloc(total_bytes,1);
+      }
+    }
+    else {
+      if (ec_malloc) {
+	vptr = EC_malloc(total_bytes);
+      }
+      else {
+	vptr = malloc(total_bytes);
+      }
+      if (ec_initheap != 0) {
+	if (ec_initheap == 4) {
+	  /* EC_INITHEAP=nan or max an 8 digit hexadecimal number */
+	  ll_t n = total_bytes/4;
+	  init4(vptr, n);
+	}
+	else if (ec_initheap == 8) {
+	  /* EC_INITHEAP=nan or a 9-16 digit hexadecimal number */
+	  ll_t n = total_bytes/8;
+	  init8(vptr, n);
+	}
+      } /* if (ec_initheap) */
+    }
+    p = vptr;
+    if (p) {
+      d->p = p;
+      d->status = (arg1 == 3) ? 3 : 1;
+      d->s[0][FNECSX_KEY_ST] = elsize;
+      if (ndims > 1) {
+#pragma cdir altcode,loopcnt=FNECSX_MAXDIM
+	for (j=1; j<ndims; j++) {
+	  d->s[j][FNECSX_KEY_ST] = nsave[j] * d->s[j-1][FNECSX_KEY_ST];
+	}
+      } /* if (ndims > 1) */
+    }
+    else {
+      istat = 194;
+    }
+  }
+  else {
+    istat = 193;
+  }
+  if (ec_prtdesc) prtdesc(arg1, stderr, "f_alloc<", d, stat, elsize);
+  if (istat != 0 && !stat) {
+    const char *msg = errmsg[istat-istat_offset];
+    fprintf(stderr,"***Error#%d: %s\n",istat,msg);
+    prtdesc(arg1, stderr, "f_alloc", d, stat, elsize);
+    ERROR_MSG(msg);
+    RAISE(SIGABRT);
+    _exit(1); /* Just in case, but shouldn't end up here at all */
+  }
+  if (stat) *stat = istat;
+}
+
+
+void f_allocl(ll_t arg1, desc_t *d, ll_t *stat, ll_t elsize)
+{
+  int istat = 0;
+  if (stat && stat == (ll_t *)0x1) stat = NULL;
+  f_alloc(arg1, d, stat ? &istat : NULL, elsize);
+  if (stat) *stat = istat;
+}
+
+
+void f_deallc(ll_t arg1, desc_t *d, int *stat)
+{
+  const int istat_offset = 195;
+  int istat = 0;
+  const char *errmsg[2] = {
+    "Value of allocate-object must not be disassociated pointer/not allocated array in DEALLOCATE.", /* 195 */
+    "Illegal value of allocate-object in DEALLOCATE." /* 196 */
+  };
+  if (stat && stat == (int *)0x1) stat = NULL;
+  if (ec_prtdesc) prtdesc(arg1, stderr, "f_deallc>", d, stat, -1);
+  if (d && ((arg1 | d->status) == 3)) {
+    int j;
+    int ndims = d->ndims;
+    u_ll_t *p = d->p;
+    if (p) {
+      if (ec_malloc) {
+	EC_free(p);
+      }
+      else {
+	free(p);
+      }
+      d->p = NULL;
+      d->status = 0;
+#pragma cdir altcode,loopcnt=FNECSX_MAXDIM
+      for (j=0; j<ndims; j++) {
+	d->s[j][FNECSX_KEY_ST] = 0;
+      }
+    }
+    else {
+      istat = 196;
+    }
+  }
+  else {
+    istat = 195;
+  }
+  if (ec_prtdesc) prtdesc(arg1, stderr, "f_deallc<", d, stat, -1);
+  if (istat != 0 && !stat) {
+    const char *msg = errmsg[istat-istat_offset];
+    fprintf(stderr,"***Error#%d: %s\n",istat,msg);
+    prtdesc(arg1, stderr, "f_deallc", d, stat, -1);
+    ERROR_MSG(msg);
+    RAISE(SIGABRT);
+    _exit(1); /* Just in case, but shouldn't end up here at all */
+  }
+  if (stat) *stat = istat;
+}
+
+
+void f_deallcl(ll_t arg1, desc_t *d, ll_t *stat)
+{
+  int istat = 0;
+  if (stat && stat == (ll_t *)0x1) stat = NULL;
+  f_deallc(arg1, d, stat ? &istat : NULL);
+  if (stat) *stat = istat;
+}
+
+#endif /* #if !defined(INTERCEPT_ALLOC) ... #else ... */
+
+void ec_envredo() { ec_envredo_(); }
diff --git a/odb/src/extras/ifsaux/utilities/gentrbk.F90 b/odb/src/extras/ifsaux/utilities/gentrbk.F90
new file mode 100644
index 0000000..5ad8461
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/gentrbk.F90
@@ -0,0 +1,41 @@
+!-- Generic traceback calls here
+
+SUBROUTINE gentrbk_dummy
+END SUBROUTINE gentrbk_dummy
+
+#ifdef __INTEL_COMPILER
+SUBROUTINE intel_trbk()
+USE IFCORE
+#ifndef BOM
+CALL TRACEBACKQQ('Calling traceback from intel_trbk()', USER_EXIT_CODE=-1)
+#endif
+#ifdef LINUX
+CALL LINUX_TRBK() ! See ifsaux/utilities/linuxtrbk.c
+#endif
+END SUBROUTINE intel_trbk
+#endif
+
+#ifndef VPP
+SUBROUTINE ERRTRA
+END SUBROUTINE ERRTRA
+#endif
+
+#ifdef NECSX
+subroutine necsx_trbk(cdmess)
+implicit none
+character(len=*), intent(in) :: cdmess
+call mesput(cdmess, len(cdmess), 1)
+call dbx_trbk()
+end subroutine necsx_trbk
+
+subroutine necsx_trbk_fl(cdmess, cdfilename, klineno)
+USE PARKIND1  ,ONLY : JPIM
+implicit none
+character(len=*), intent(in) :: cdmess
+character(len=*), intent(in) :: cdfilename
+INTEGER(KIND=JPIM), intent(in) :: klineno
+character(len=len(cdmess)+len(cdfilename)+30) clocal
+write(clocal,'(a," at ",a,":",i6.6)') trim(cdmess),trim(cdfilename),klineno
+call necsx_trbk(trim(clocal))
+end subroutine necsx_trbk_fl
+#endif
diff --git a/odb/src/extras/ifsaux/utilities/get_max_threads.F90 b/odb/src/extras/ifsaux/utilities/get_max_threads.F90
new file mode 100644
index 0000000..22cccd0
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/get_max_threads.F90
@@ -0,0 +1,8 @@
+FUNCTION get_max_threads() RESULT(imaxt)
+USE PARKIND1  ,ONLY : JPIM
+USE oml_mod, only : OML_MAX_THREADS
+implicit none
+INTEGER(KIND=JPIM) :: imaxt
+imaxt = 1
+!$ imaxt = OML_MAX_THREADS()
+END FUNCTION get_max_threads
diff --git a/odb/src/extras/ifsaux/utilities/get_num_threads.F90 b/odb/src/extras/ifsaux/utilities/get_num_threads.F90
new file mode 100644
index 0000000..d11d6d9
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/get_num_threads.F90
@@ -0,0 +1,8 @@
+FUNCTION get_num_threads() RESULT(inumt)
+USE PARKIND1  ,ONLY : JPIM
+USE oml_mod, only : OML_NUM_THREADS
+implicit none
+INTEGER(KIND=JPIM) :: inumt
+inumt = 1
+!$ inumt = OML_NUM_THREADS()
+END FUNCTION get_num_threads
diff --git a/odb/src/extras/ifsaux/utilities/get_thread_id.F90 b/odb/src/extras/ifsaux/utilities/get_thread_id.F90
new file mode 100644
index 0000000..c835d4f
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/get_thread_id.F90
@@ -0,0 +1,8 @@
+FUNCTION get_thread_id() RESULT(tid)
+USE PARKIND1  ,ONLY : JPIM
+USE oml_mod, only : OML_MY_THREAD
+implicit none
+INTEGER(KIND=JPIM) :: tid
+tid = 1
+!$ tid = OML_MY_THREAD()
+END FUNCTION get_thread_id
diff --git a/odb/src/extras/ifsaux/utilities/getcurheap.c b/odb/src/extras/ifsaux/utilities/getcurheap.c
new file mode 100644
index 0000000..911bb5c
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getcurheap.c
@@ -0,0 +1,617 @@
+#if defined(RS6K) && defined(__64BIT__)
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include "intercept_alloc.h"
+#include "drhook.h"
+extern int drhook_memtrace;
+#include "raise.h"
+
+typedef  long long int  ll_t;
+
+#define WORDLEN   ((ll_t)sizeof(ll_t))
+#define RNDUP(i,n) (( ( (i) + (n) - 1 ) / (n) ) * (n))
+#define TRUE_BYTES(x) ((x) + 4*WORDLEN) /* size, keyptr at start & padding at end */
+
+#if defined(CRAY) && !defined(SV2)
+#define getcurheap           GETCURHEAP
+#define getmaxcurheap        GETMAXCURHEAP
+#define getcurheap_thread    GETCURHEAP_THREAD
+#define getmaxcurheap_thread GETMAXCURHEAP_THREAD
+#define getmaxloc            GETMAXLOC
+#define resetmaxloc          RESETMAXLOC
+#define profile_heap_get     PROFILE_HEAP_GET
+#else
+#define getcurheap           getcurheap_
+#define getmaxcurheap        getmaxcurheap_
+#define getcurheap_thread    getcurheap_thread_
+#define getmaxcurheap_thread getmaxcurheap_thread_
+#define getmaxloc            getmaxloc_
+#define resetmaxloc          resetmaxloc_
+#define profile_heap_get     profile_heap_get_
+#endif
+
+#if !defined(NTHRDS)
+#define NTHRDS 64   /* ***Note: A hardcoded max number of threads !!! */
+#endif
+
+#if !defined(CACHELINESIZE)
+#define CACHELINESIZE 128 /* ***Note: A hardcoded cache line size in bytes !!! */
+#endif
+
+#define TIMES  0    /* 0=Normal, 1=timing locks v threads */
+
+static ll_t maxloc = 0;    /* For stackcheck */
+static ll_t begloc = 0;    /* For stackcheck */
+static int heapcheck = 0;  /* Fro heapcheck */
+
+extern int get_thread_id_(void);   /* ***Note: Returns YOMOML-value [1..max_threads] */
+extern int get_proc_id_(void);  
+extern int get_max_threads_(void);
+extern ll_t getstk_();
+extern ll_t gethwm_();
+#ifdef RS6K
+extern void xl__trbk_();
+#elif defined(NECSX)
+extern void necsx_trbk_(const char *msg, int msglen); /* from ../utilities/gentrbk.F90 */
+extern void necsx_trbk_fl_(const char *msg, const char *filename, int *lineno,
+			   int msglen, int filenamelen); /* from ../utilities/gentrbk.F90 */
+#define xl__trbk_() { int lineno = __LINE__; necsx_trbk_fl_("Error", __FILE__, &lineno, 5, sizeof(__FILE__)-1); }
+#else
+#define xl__trbk_() /* do nothing */
+#endif
+
+#if defined(CLSZ_OPT)
+#undef CLSZ_OPT
+#endif
+
+#if defined(INTERCEPT_ALLOC)
+
+/* Intercepts F90 ALLOCATE/DEALLOCATE */
+
+#if defined(RS6K) && defined(__64BIT__)
+/* Assume AIX >= 5.1 with 64-bit addressing */
+
+pthread_mutex_t getcurheap_lock = PTHREAD_MUTEX_INITIALIZER;
+#define CLSZ_OPT 1
+
+#define EC_free     __free
+#define EC_malloc   __malloc
+#define EC_calloc   __calloc
+#define EC_realloc  __realloc
+#define EC_strdup   __strdup
+
+int EC_malloc_will_abort = 1;
+
+#elif defined(NECSX)
+
+#include <pthread.h>
+pthread_mutex_t getcurheap_lock = PTHREAD_MUTEX_INITIALIZER;
+#define CLSZ_OPT 1
+
+extern int EC_malloc_will_abort; /* see fnecsx.c */
+
+#else
+
+#undef INTERCEPT_ALLOC
+
+#endif
+
+#endif /* defined(INTERCEPT_ALLOC) */
+
+
+static ll_t maxcurheap = 0;
+
+#if defined(CLSZ_OPT)
+
+static int profile_heap = -1; /* Profiling:  -1 = UNDEF (initvalue), 0 = OFF (default), 1 = ON */
+#define NPROFILE 9 /* byte ranges: 10**1 .. 10^9 */
+static ll_t malloc_hits[NPROFILE+1]; /* +1 for ranges >= 10^9 */
+static ll_t free_hits[NPROFILE+1];
+static ll_t alloc_amount[NPROFILE+1];
+static ll_t malloc_hits_thrd[NTHRDS][NPROFILE+1]; 
+static ll_t free_hits_thrd[NTHRDS][NPROFILE+1];
+static ll_t alloc_amount_thrd[NTHRDS][NPROFILE+1];
+
+static ll_t curalloc = 0;
+
+static struct {
+  ll_t curalloca;
+  ll_t maxcurheapa;
+  char pad[CACHELINESIZE - 2*WORDLEN]; /* padding : e.g. 128 bytes - 2*8 bytes */
+} clsz_opt[NTHRDS]; /* cachelinesize optimized --> less false sharing when running with OpenMP */
+
+#define NANS_FILL ((ll_t)0x7FF7FFFF7FF7FFFF)
+static int nans_fill = -1; /* NaNS fill:  -1 = First, 1 = ON */
+static int free_error     = 0;
+static int max_free_error = 10;
+
+#ifdef RS6K
+
+#if 1
+/* Turn NODISCLAIM on i.e. do NOT call disclaim() [before free()], since things get very, very expensive */
+#if !defined(NODISCLAIM)
+#define NODISCLAIM 1
+#endif
+#endif
+
+#else
+
+#if defined(NODISCLAIM)
+#undef NODISCLAIM
+#endif
+#define NODISCLAIM 1
+
+#endif 
+
+#ifdef RS6K
+
+#if !defined(NODISCLAIM)
+#include <sys/shm.h> /* for use by disclaim() function */
+/*
+   http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm
+   extern int disclaim (char *Address,  unsigned int Length,  unsigned int Flag);
+
+   Note: We could also use 'export MALLOCOPTIONS=disclaim', but a short test showed
+   that wall clock time went up by factor of 4, and cpu-time by factor 10 on a multithreaded MPI-code !!
+
+   Now use 'export EC_DISCLAIM_THRESHOLD=50' to disclaim space for (say) allocations >= 50 MBytes
+*/
+/* Try to disclaim only if size < 2^31 && size >= disclaim_threshold (see below) */
+static double disclaim_threshold = 2048; /* In MBytes -- for convenience : max however < 2^31/1024/1024 */
+static ll_t disclaim_threshold_test = 0;
+static ll_t disclaim_threshold_limit = 2147483647;
+#endif /* !defined(NODISCLAIM) */
+
+#endif /* RS6K */
+
+static void
+Check_curalloc() /* Normally not called */
+{
+  const ll_t big = (ll_t) 1000000000000L; /* 1,000,000 million bytes */
+  if (curalloc < 0 || curalloc > big) {
+    fprintf(stderr,
+	    "Check_curalloc(): curalloc has probably gone crazy : Attempt to allocate ==> %lld bytes\n",curalloc);
+    xl__trbk_();
+    RAISE(SIGABRT);
+    _exit(1);  /* Just in case, but shouldn't end up here at all */
+  }
+}
+
+static void
+Profile_heap_init()
+{
+  if (profile_heap == -1) { /* First time */
+    char *env = getenv("EC_PROFILE_HEAP");
+    if (env) {
+      profile_heap = atoi(env);
+      if (profile_heap != 0) profile_heap = 1; /* OFF by export EC_PROFILE_HEAP=0 */
+    }
+    if (profile_heap != 1) profile_heap = 0;
+#if !defined(NODISCLAIM)
+    if (disclaim_threshold_test == 0) {
+      env = getenv("EC_DISCLAIM_THRESHOLD"); /* In MBytes (can have decimals) */
+      if (env) {
+	double tmp = atof(env);
+	if (tmp > 0 || tmp < 2048) disclaim_threshold = tmp;
+      }
+      {
+	double tmp = disclaim_threshold * 1024 * 1024;
+	disclaim_threshold_test = (ll_t) tmp;
+      }
+    }
+#endif
+  }
+}
+
+static void
+Profile_heap_put(ll_t size, int is_malloc)
+{
+  if (profile_heap == -1) Profile_heap_init();
+  if (profile_heap == 1) {
+    int j;
+    ll_t n = 1; /* initial byte range */
+    ll_t *p = is_malloc ? malloc_hits : free_hits;
+    for (j=0; j<NPROFILE; j++) { 
+      n *= 10; /* increment byte range by 10X */
+      /* BTW: Don't want log10() overhead here !! */
+      if (size < n) { /* i.e. size < pow(10,j+1) */
+	alloc_amount[j] += is_malloc ? size : -size;
+	p[j]++;
+	return;
+      }
+    }
+    j = NPROFILE;
+    alloc_amount[j] += is_malloc ? size : -size;
+    p[j]++;
+  } /* if (profile_heap == 1) */
+}
+
+static void
+Profile_heap_put_thrd(ll_t size, int is_malloc, int it)
+{
+  if (it == 0 && profile_heap == -1) Profile_heap_init(); /* 1st thread only checks this */
+  if (profile_heap == 1) {
+    int j;
+    ll_t n = 1; /* initial byte range */
+    ll_t *p = is_malloc ? malloc_hits_thrd[it] : free_hits_thrd[it];
+    for (j=0; j<NPROFILE; j++) { 
+      n *= 10; /* increment byte range by 10X */
+      /* BTW: Don't want log10() overhead here !! */
+      if (size < n) { /* i.e. size < pow(10,j+1) */
+	alloc_amount_thrd[it][j] += is_malloc ? size : -size;
+	p[j]++;
+	return;
+      }
+    }
+    j = NPROFILE;
+    alloc_amount_thrd[it][j] += is_malloc ? size : -size;
+    p[j]++;
+  } /* if (profile_heap == 1) */
+}
+
+#endif /* defined(CLSZ_OPT) */
+
+void
+profile_heap_get(ll_t val[], 
+		 const int *Nval, 
+		 const int *Icase,
+		 int *nret)
+     /* Fortran callable */
+{
+#if defined(INTERCEPT_ALLOC)
+  int nval = *Nval;
+  int icase = *Icase;
+  int j, it, nt;
+  if (nval < 0) nval = 0;
+  if (nval > NPROFILE+1) nval = NPROFILE+1;
+  nt = get_max_threads_();
+  for (j=0; j<nval; j++) {
+    free_hits[j] = 0;
+    malloc_hits[j] = 0;
+    alloc_amount[j] = 0;
+  }
+  for (it=0; it<nt; it++) {
+    for (j=0; j<nval; j++) {
+      free_hits[j] += free_hits_thrd[it][j];
+      malloc_hits[j] += malloc_hits_thrd[it][j];
+      alloc_amount[j] += alloc_amount_thrd[it][j];
+    }
+  }
+  if (icase == 0) { /* free() hits */
+    for (j=0; j<nval; j++) val[j] = free_hits[j];
+  }
+  else if (icase == 1) { /* malloc() hits */
+    for (j=0; j<nval; j++) val[j] = malloc_hits[j];
+  }
+  else if (icase == 2) { /* outstanding allocs (malloc minus free) */
+    for (j=0; j<nval; j++) val[j] = malloc_hits[j] - free_hits[j];
+  }
+  else if (icase == 3) { /* allocation amount left per range; in bytes */
+    for (j=0; j<nval; j++) val[j] = alloc_amount[j];
+  }
+  else if (icase == 4) { /* average allocation chunk left per range; in bytes */
+    for (j=0; j<nval; j++) {
+      ll_t tmp = malloc_hits[j] - free_hits[j];
+      val[j] = (tmp > 0) ? RNDUP(alloc_amount[j],tmp)/tmp : 0;
+    }
+  }
+  else {
+    nval = 0;
+  }
+  *nret = nval;
+#else
+  *nret = 0;
+#endif /* defined(CLSZ_OPT) */
+}
+
+
+#if defined(CLSZ_OPT)
+
+void EC_free(void *vptr)
+{
+  if (vptr) {
+    ll_t *p = vptr;
+    ll_t dummy = *--p; 
+    ll_t adjsize = *--p;
+    ll_t keyptr = *--p;
+    ll_t true_bytes;
+    int it;
+    if (nans_fill == 1) {
+      ll_t *q = vptr;
+      ll_t nans  = NANS_FILL;
+      ll_t j = adjsize/WORDLEN;
+      if (q[j] != nans) {
+        fprintf(stderr,"WARNING: NaNS at end of array overwritten with %e\n",q[j]);
+        xl__trbk_();
+        free_error++;
+        if (free_error > max_free_error) {
+	  fprintf(stderr,"ERROR: Too many NaNS overwrites at end of arrays\n");
+	  xl__trbk_(); /* Oops !! */
+	  RAISE(SIGABRT);
+	  _exit(1); /* Just in case, but shouldn't end up here at all */
+	}
+      }
+    }
+    it=get_thread_id_()-1;
+    true_bytes = -TRUE_BYTES(adjsize);
+#if !defined(NODISCLAIM)
+    if (it == 0) { /* Do on OpenMP thread#1 only */
+      ll_t *addr = (ll_t *)p;
+      /* ll_t tb = -true_bytes; */
+      ll_t tb = addr[-1]; /* Since addr[-1] contains the true length in bytes */ 
+      if (tb >= disclaim_threshold_test &&
+	  tb <= disclaim_threshold_limit) {
+	unsigned int len = (unsigned int)tb;
+	/* Important : Call disclaim(p, ...) BEFORE free(p) */
+	int rc = disclaim(p, len, ZERO_MEM);
+	/* printf("disclaim: rc=%d, len=%u, addr=%x\n",rc,len,addr); */
+      }
+    }
+#endif
+    p[1] = 0; /* Bytes reserved reset */ 
+    free(p);
+    if (drhook_memtrace) pthread_mutex_lock(&getcurheap_lock);
+    clsz_opt[it].curalloca += true_bytes; /* += since true_bytes is negative */
+    if (drhook_memtrace) pthread_mutex_unlock(&getcurheap_lock);
+    if (drhook_memtrace) { ++it; c_drhook_memcounter_(&it, &true_bytes, &keyptr); --it; }
+    if (profile_heap != 0) Profile_heap_put_thrd(true_bytes, 0, it);
+  }
+}
+
+void *EC_malloc(ll_t size)
+{
+  double *d = NULL;
+  void *vptr = NULL;
+  ll_t keyptr = 0;
+  ll_t adjsize = size;
+  ll_t thesize = size;
+  ll_t true_bytes;
+  int it;
+  if (nans_fill == -1) { /* First time */
+    char *env = getenv("EC_FILL_NANS");
+    nans_fill=0;
+    if (env) {
+      if (strcmp(env,"true") == 0 || 
+	  strcmp(env,"TRUE") == 0 ||
+	  strcmp(env,"1"   ) == 0) nans_fill = 1;
+      /* fprintf(stderr,"EC_FILL_NANS ==> env,env,nans_fill= 0x%x %s %d\n",env,env,nans_fill); */
+    }
+  }
+  if (adjsize < 0) adjsize = 0;
+  adjsize = RNDUP(adjsize,WORDLEN);
+#if !defined(NECSX)
+  thesize = adjsize;
+#endif
+  true_bytes = TRUE_BYTES(adjsize);
+  it=get_thread_id_()-1;
+  if (TIMES == 1) {
+    DRHOOK_START(dummy);
+    DRHOOK_END(0);
+  }
+  if (TIMES == 1) {
+    DRHOOK_START(malloc);
+    d = (double *)malloc(true_bytes); 
+    DRHOOK_END(0);
+  }
+  else {
+    d = (double *)malloc(true_bytes);
+  }
+  vptr = d;
+  if (vptr) {
+    if (TIMES == 1) {
+      {
+        ll_t *p = vptr;
+        DRHOOK_START(lock);
+        (void) getstk_(); /* to gather near up to date stack statistics */
+	*p++ = keyptr;
+        *p++ = thesize;
+        *p++ = 0;
+        pthread_mutex_lock(&getcurheap_lock);
+        curalloc += true_bytes;
+        if (curalloc > maxcurheap) maxcurheap = curalloc;
+        /* Check_curalloc(); */
+        Profile_heap_put(true_bytes, 1);
+        pthread_mutex_unlock(&getcurheap_lock);
+        vptr = p;
+        DRHOOK_END(0);
+      }
+      {
+        ll_t *p = vptr;
+        DRHOOK_START(thread);
+        (void) getstk_(); /* to gather near up to date stack statistics */
+        if (drhook_memtrace) pthread_mutex_lock(&getcurheap_lock);
+        clsz_opt[it].curalloca += true_bytes;
+        if (clsz_opt[it].maxcurheapa < clsz_opt[it].curalloca) 
+	    clsz_opt[it].maxcurheapa = clsz_opt[it].curalloca;
+	if (drhook_memtrace) { ++it; c_drhook_memcounter_(&it, &true_bytes, &keyptr); --it; }
+        if (drhook_memtrace) pthread_mutex_unlock(&getcurheap_lock);
+        if (profile_heap != 0) Profile_heap_put_thrd(true_bytes, 1, it);
+        DRHOOK_END(0);
+      }
+    }
+    else {
+      int ip;
+      ll_t *p = vptr;
+      ll_t q;
+      (void) getstk_(); /* to gather near up to date stack statistics */
+      *p++ = keyptr;
+      *p++ = thesize;
+      *p++ = 0;
+      if (drhook_memtrace) pthread_mutex_lock(&getcurheap_lock);
+      clsz_opt[it].curalloca += true_bytes;
+      if (clsz_opt[it].maxcurheapa < clsz_opt[it].curalloca) 
+	  clsz_opt[it].maxcurheapa = clsz_opt[it].curalloca;
+      if (drhook_memtrace) { ++it; c_drhook_memcounter_(&it, &true_bytes, &keyptr); --it; }
+      if (drhook_memtrace) pthread_mutex_unlock(&getcurheap_lock);
+      if (profile_heap != 0) Profile_heap_put_thrd(true_bytes, 1, it);
+      if (nans_fill == 1) {
+        int j;
+        ll_t nans  = NANS_FILL;
+        for (j=0; j<(WORDLEN+adjsize)/WORDLEN; j++) {
+          p[j]=nans;
+        }
+      }
+      if(heapcheck == 1) {
+        it=get_thread_id_();
+        ip=get_proc_id_();
+        if (it == 1 && ip == 1 ) {
+          if (begloc == 0) begloc=(ll_t)p;
+          q=(ll_t)p+true_bytes;
+          if (q > maxloc) {
+            maxloc=q;
+/*
+            fprintf(stderr,"JJJ pntr= %d %ld %ld %ld %ld %ld\n",it,maxloc-begloc,maxloc,begloc,p,true_bytes);
+            xl__trbk_();
+*/
+          }
+        }
+      }
+      vptr=p;
+    }
+  }
+  else {
+    pthread_mutex_lock(&getcurheap_lock);
+    fprintf(stderr,
+	    "EC_malloc(size=%lld => thesize=%lld => adjsize=%lld, true_bytes=%lld bytes) failed in file=%s, line=%d\n",
+	    size, thesize, adjsize, true_bytes, __FILE__, __LINE__);
+    xl__trbk_(); /* Oops !! */
+    if (EC_malloc_will_abort) RAISE(SIGABRT);
+    pthread_mutex_unlock(&getcurheap_lock);
+    if (EC_malloc_will_abort) _exit(1); /* Just in case, but shouldn't end up here at all */
+  }
+  return vptr;
+}
+
+void *EC_calloc(ll_t nelem, ll_t elsize)
+{
+  ll_t totbytes = nelem * elsize;
+  void *p = EC_malloc(totbytes);
+  if (p) memset(p, 0, totbytes);
+  return p;
+}
+
+void *EC_realloc(void *vptr, ll_t size)
+{
+  ll_t *pnew = NULL;
+  if (vptr) {
+    ll_t *p = vptr;
+    ll_t oldsize = p[-1];
+    if (oldsize < size) {
+      pnew = EC_malloc(size);
+      if (pnew) {
+	memcpy(pnew, p, oldsize);
+	EC_free(p);
+      }
+    }
+    else { /* the old allocation size was already sufficient */
+      pnew = p;
+    }
+  }
+  else { /* Revert to malloc() */
+    pnew = EC_malloc(size);
+  }
+  return pnew;
+}
+
+char *EC_strdup(const char *s)
+{
+  ll_t totbytes = sizeof(*s) * strlen(s);
+  return EC_malloc(totbytes);
+}
+
+#endif /* defined(CLSZ_OPT) */
+
+ll_t
+getcurheap()
+{
+#if defined(CLSZ_OPT)
+  int it = get_thread_id_();
+  ll_t curvalue = clsz_opt[it-1].curalloca;
+  if (it == 1) { /* Only thread#1 sums up */
+    int i, nt = get_max_threads_();
+    if (drhook_memtrace) pthread_mutex_lock(&getcurheap_lock);
+    for (i=1; i<nt; i++) {
+      curvalue += clsz_opt[i].curalloca;
+    }
+    if (drhook_memtrace) pthread_mutex_unlock(&getcurheap_lock);
+  }
+  return curvalue;
+#else
+  ll_t rc = gethwm_();
+  if (rc > maxcurheap) maxcurheap = rc;
+  return rc;
+#endif
+}
+
+ll_t
+getcurheap_thread(const int *thread_id)
+{
+#if defined(CLSZ_OPT)
+  int it = (thread_id && (*thread_id > 0)) ? *thread_id : get_thread_id_();
+  return clsz_opt[--it].curalloca;
+#else
+  return getcurheap();
+#endif
+}
+
+/* Maximum (total) current (virtual mem) allocation encountered */
+
+ll_t
+getmaxcurheap()
+{
+#if defined(CLSZ_OPT)
+  ll_t maxcurheap_local=0;
+  int it, nt = get_max_threads_();
+  if (drhook_memtrace) pthread_mutex_lock(&getcurheap_lock);
+  for (it=0; it<nt; it++) {
+    maxcurheap_local += clsz_opt[it].maxcurheapa;
+  }
+  if (maxcurheap < maxcurheap_local) maxcurheap = maxcurheap_local;
+  if (drhook_memtrace) pthread_mutex_unlock(&getcurheap_lock);
+  return maxcurheap_local;
+#else
+  return 0;
+#endif
+}
+
+/* Maximum (total) current (virtual mem) allocation encountered per thread */
+
+ll_t
+getmaxcurheap_thread(const int *thread_id) /* ***Note: YOMOML thread id */
+{
+#if defined(CLSZ_OPT)
+  int it = (thread_id && (*thread_id > 0)) ? *thread_id : get_thread_id_();
+  return  clsz_opt[--it].maxcurheapa;
+#else
+  return 0;
+#endif
+}
+
+#if 1
+ll_t
+getmaxloc()
+{
+  ll_t z=maxloc-begloc;
+  return z;
+}
+
+void
+resetmaxloc()
+{
+  maxloc=0;
+}
+
+void
+
+setheapcheck_()
+{
+  heapcheck=1;
+}
+
+#endif
+
diff --git a/odb/src/extras/ifsaux/utilities/getheapstat.F90 b/odb/src/extras/ifsaux/utilities/getheapstat.F90
new file mode 100644
index 0000000..aa43e92
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getheapstat.F90
@@ -0,0 +1,85 @@
+SUBROUTINE getheapstat(kout, cdlabel)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPIB
+
+use mpl_module
+
+#ifdef NAG
+use f90_unix_env, only: getenv
+#endif
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in) :: kout
+character(len=*), intent(in) :: cdlabel
+INTEGER(KIND=JPIM) :: i, imyproc, inproc, iret, ioffset, ii
+INTEGER(KIND=JPIM), parameter :: JP_NPROFILE = 9 ! pls. consult ifsaux/utilities/getcurheap.c
+INTEGER(KIND=JPIM), parameter :: isize = JP_NPROFILE+1
+INTEGER(KIND=JPIB) ilimit(isize)
+INTEGER(KIND=JPIB) icnt(isize)
+REAL(KIND=JPRB), allocatable :: zsend(:), zrecv(:)
+INTEGER(KIND=JPIM), allocatable :: icounts(:)
+character(len=1) CLenv
+character(len=80) CLtext(0:4)
+
+call getenv("EC_PROFILE_HEAP", CLenv) ! turn OFF by export EC_PROFILE_HEAP=0
+
+if (kout >= 0 .and. CLenv /= '0') then
+  imyproc = mpl_myrank()
+  inproc  = mpl_nproc()
+
+  do i=1,isize
+    ilimit(i) = i ! power of 10's ; pls. consult ifsaux/utilities/getcurheap.c
+  enddo
+
+  allocate(zsend(isize))
+  allocate(zrecv(isize * inproc))
+  allocate(icounts(inproc))
+
+  CLtext(0) = "free()/DEALLOCATE -hits per byte range"
+  CLtext(1) = "malloc()/ALLOCATE -hits per byte range"
+  CLtext(2) = "Outstanding malloc()/ALLOCATE -hits per byte range"
+  CLtext(3) = "Outstanding amount of malloc()/ALLOCATE -bytes per byte range"
+  CLtext(4) = "Average amount of outstanding malloc()/ALLOCATE -bytes per byte range"
+
+  do ii=0,4
+    icnt(:) = 0
+    CALL profile_heap_get(icnt, isize, ii, iret)
+
+    zsend(:) = 0
+    do i=1,iret
+      zsend(i) = icnt(i)
+    enddo
+    zrecv(:) = -1
+
+    icounts(:) = isize
+    call mpl_gatherv(zsend(:), kroot=1, krecvcounts=icounts(:), &
+                    &precvbuf=zrecv, cdstring='GETHEAPSTAT:')
+
+    if (imyproc == 1) then
+!     Not more than 132 columns, please :-)
+      write(kout,9000) trim(CLtext(ii)),trim(cdlabel), "Node", &
+                     & (ilimit(i),i=1,min(JP_NPROFILE,9)), "Larger"
+9000  format(/,"Heap Utilization Profile (",a,"): ",a,&
+            &/,126("="),&
+            &//,(a4,2x,9(:,2x,4x,"< 10^",i1),:,2x,a10))
+      write(kout,9001)
+9001  format(4("="),2x,10(2x,10("="))/)
+      ioffset = 0
+      do i=1,inproc
+        icnt(:) = zrecv(ioffset+1:ioffset+isize)
+        write(kout,'(i4,2x,(10(:,2x,i10)))') i,icnt(:)
+        ioffset = ioffset + isize
+      enddo
+    endif
+  enddo
+
+  if (imyproc == 1) then
+    write(kout,'(/,a,/)') 'End of Heap Utilization Profile'
+  endif
+
+  deallocate(zsend)
+  deallocate(zrecv)
+  deallocate(icounts)
+endif
+END SUBROUTINE getheapstat
diff --git a/odb/src/extras/ifsaux/utilities/gethwm.c b/odb/src/extras/ifsaux/utilities/gethwm.c
new file mode 100644
index 0000000..d62568e
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/gethwm.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "getstatm.h"
+
+typedef  long long int  ll_t;
+
+#if defined(CRAY) && !defined(SV2)
+#define gethwm GETHWM
+#else
+#define gethwm gethwm_
+#endif
+
+#ifdef RS6K
+
+#if defined(__64BIT__)
+/* Assume AIX >= 5.1 with 64-bit addressing */
+#include <fcntl.h>
+#include <sys/procfs.h>
+ll_t
+gethwm()
+{
+  static int fd = -9999;
+  static char *heapbase = NULL;
+  ll_t heapsize = 0;
+
+  if (fd == -9999) {
+    pstatus_t pstatus;
+    char procfile[80];
+    int pid = getpid();
+    sprintf(procfile,"/proc/%d/status",pid);
+    fd = open(procfile, O_RDONLY);
+    if (read(fd, &pstatus, sizeof(pstatus)) == sizeof(pstatus)) {
+      heapbase = (char *)pstatus.pr_brkbase;
+      close(fd);
+      fd = 0;
+    }
+  }
+
+  if (fd == 0 && heapbase != NULL) {
+    heapsize = (ll_t)((char *)sbrk(0) - heapbase);
+  }
+
+  return heapsize;
+}
+
+#else
+
+ll_t
+gethwm() 
+{ 
+  extern ll_t getrss_();
+  return getrss_();
+}
+
+#endif /* defined(__64BIT__) */
+
+#else  /* non-RS6K */
+
+#if defined(LINUX)
+static ll_t basesize = -1;
+static size_t pagesize = 4096;
+ll_t gethwm()
+{
+  struct statm sm;
+  ll_t rc = 0;
+  if (getstatm(&sm) == 0) {
+    if (basesize < 0) { /* the very first time */
+      basesize = sm.size;
+      pagesize = getpagesize();
+      if (pagesize <= 0) pagesize = 4096;
+    }
+    rc = (sm.size - basesize) * pagesize;
+  }
+  return rc;
+}
+
+#elif defined(NECSX)
+
+ll_t
+gethwm() 
+{ 
+  extern ll_t getrss_();
+  return getrss_();
+}
+
+#else
+ll_t gethwm()
+{
+  ll_t rc = (ll_t)((char *)sbrk(0) - (char *)0);
+  return rc;
+}
+#endif
+
+#endif
+
+#if defined(SV2)
+int getpid_()
+{
+  return getpid();
+}
+
+unsigned int sleep_(unsigned int seconds)
+{
+  return sleep(seconds);
+}
+
+#endif
diff --git a/odb/src/extras/ifsaux/utilities/getmemstat.F90 b/odb/src/extras/ifsaux/utilities/getmemstat.F90
new file mode 100644
index 0000000..b806f0b
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getmemstat.F90
@@ -0,0 +1,60 @@
+SUBROUTINE getmemstat(kout, cdlabel)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPIB
+
+use mpl_module
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in) :: kout
+character(len=*), intent(in) :: cdlabel
+INTEGER(KIND=JPIM) :: i, imyproc, inproc, ioffset
+INTEGER(KIND=JPIM), PARAMETER :: JP_MEMKEYS = 5  ! pls. consult ifsaux/utilities/getmemvals.F90
+INTEGER(KIND=JPIM) imemkeys(JP_MEMKEYS)
+INTEGER(KIND=JPIB) imemvals(JP_MEMKEYS)
+REAL(KIND=JPRB), allocatable :: zsend(:), zrecv(:)
+INTEGER(KIND=JPIM), allocatable :: icounts(:)
+
+if (kout >= 0) then
+  imyproc = mpl_myrank()
+  inproc  = mpl_nproc()
+
+  allocate(zsend(JP_MEMKEYS))
+  allocate(zrecv(JP_MEMKEYS * inproc))
+  allocate(icounts(inproc))
+
+!                 1=MAXHEAP, 2=MAXRSS, 3=CURRENTHEAP, 5=MAXSTACK, 6=PAGING
+  IMEMKEYS(:) = (/1,         2,        3,             5,          6/) 
+  CALL GETMEMVALS(JP_MEMKEYS, IMEMKEYS, IMEMVALS)
+
+  zsend(:) = 0
+  do i=1,JP_MEMKEYS
+    zsend(i) = imemvals(i)
+  enddo
+  zrecv(:) = -1
+
+  icounts(:) = JP_MEMKEYS
+  call mpl_gatherv(zsend(:), kroot=1, krecvcounts=icounts(:), &
+                  &precvbuf=zrecv, cdstring='GETMEMSTAT:')
+
+  if (imyproc == 1) then
+     WRITE(KOUT,9000) trim(cdlabel)
+9000 FORMAT(/,"Memory Utilization Information (in bytes) : ",a,/,79("="),//,&
+         &  "Node   Max heapsize   Max resident   Current heap      Max stack   I/O-paging #",/,&
+         &  "====   ============   ============   ============   ============   ============",//)
+     IOFFSET = 0
+     DO I=1,INPROC
+       IMEMVALS(:) = ZRECV(IOFFSET+1:IOFFSET+JP_MEMKEYS)
+       WRITE(KOUT,'(I4,5(3X,I12))') I,IMEMVALS(:)
+       IOFFSET = IOFFSET + JP_MEMKEYS
+     ENDDO
+     write(kout,'(/,a,/)') 'End of Memory Utilization Information'
+  ENDIF
+
+  deallocate(zsend)
+  deallocate(zrecv)
+  deallocate(icounts)
+
+  CALL getheapstat(kout, cdlabel)
+endif
+END SUBROUTINE getmemstat
diff --git a/odb/src/extras/ifsaux/utilities/getmemvals.F90 b/odb/src/extras/ifsaux/utilities/getmemvals.F90
new file mode 100644
index 0000000..42e8b4f
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getmemvals.F90
@@ -0,0 +1,35 @@
+SUBROUTINE getmemvals(n, key, kval)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPIB
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: n, key(n)
+INTEGER(KIND=JPIB), intent(out):: kval(n)
+!--------------------------------- key ----------------------------------------------
+INTEGER(KIND=JPIB), external :: gethwm    !  1  High Water Mark for HEAP-alloc
+INTEGER(KIND=JPIB), external :: getrss    !  2  Maximum resident memory so far
+INTEGER(KIND=JPIB), external :: getcurheap!  3  Instantaneous allocation from ALLOCATE/malloc
+INTEGER(KIND=JPIB), external :: getstk    !  4  Instantaneous stack usage
+INTEGER(KIND=JPIB), external :: getmaxstk !  5  Maximum stack usage so far
+INTEGER(KIND=JPIB), external :: getpag    !  6  I/O caused by paging
+! -- add more as required (all 64-bit integers upon return, though) --
+
+INTEGER(KIND=JPIM) j
+
+do j=1,n
+  if (key(j) == 1) then
+    kval(j) = gethwm()
+  else if (key(j) == 2) then
+    kval(j) = getrss()
+  else if (key(j) == 3) then
+    kval(j) = getcurheap()
+  else if (key(j) == 4) then
+    kval(j) = getstk()
+  else if (key(j) == 5) then
+    kval(j) = getmaxstk()
+  else if (key(j) == 6) then
+    kval(j) = getpag()
+!  else if (key(j) == ) then
+!    kval(j) = get()
+  endif
+enddo
+
+END SUBROUTINE getmemvals
diff --git a/odb/src/extras/ifsaux/utilities/getpag.c b/odb/src/extras/ifsaux/utilities/getpag.c
new file mode 100644
index 0000000..5d59ac5
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getpag.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#if defined(CRAY) && !defined(SV2)
+#define getpag GETPAG
+#else
+#define getpag getpag_
+#endif
+
+#if defined(RS6K) || defined(SV2)
+#include <sys/resource.h>
+long long int
+getpag()
+{
+#if defined(__64BIT__)
+  struct rusage64 r;
+  long long int rc = getrusage64(RUSAGE_SELF, &r);
+#else
+  struct rusage r;
+  long long int rc = getrusage(RUSAGE_SELF, &r);
+#endif
+  rc = (rc == 0) ? (long long int) r.ru_majflt : 0;
+  return rc;
+}
+
+#else
+
+
+long long int getpag()
+{
+  return 0L;
+}
+
+#endif
+
diff --git a/odb/src/extras/ifsaux/utilities/getrss.c b/odb/src/extras/ifsaux/utilities/getrss.c
new file mode 100644
index 0000000..47aabc5
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getrss.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "getstatm.h"
+
+typedef  long long int  ll_t;
+
+#if defined(CRAY) && !defined(SV2)
+#define getrss GETRSS
+#else
+#define getrss getrss_
+#endif
+
+#if defined(RS6K) || defined(SGI) || defined(NECSX)
+#include <sys/resource.h>
+
+#if defined(RS6K) && defined(__64BIT__)
+#if defined(USE_GETPROCS) 
+/* From http://www-941.ibm.com/collaboration/wiki/display/WikiPtype/ryo
+   Also : Thanks to Oliver Treiber, ECMWF, 16-Jan-2007 for useful discussions !! */
+#include <procinfo.h>
+#include <sys/time.h>
+extern int getprocs64 (struct procentry64 *ProcessBuffer, 
+		       int ProcessSize, struct fdsinfo64 *FileBuffer, int FileSize, 
+		       pid_t *IndexPointer, int Count);
+/* By the way : getprocs() for 32-bit addressing may also be worth trying */
+#endif
+#endif
+
+ll_t
+getrss()
+{
+  const ll_t scaler = 1024; /* in kilobytes */
+  ll_t rc = 0;
+#if defined(__64BIT__)
+#if defined(USE_GETPROCS)
+  /* IBM RS6K with -DUSE_GETPROCS */
+  struct procentry64 procs;
+  pid_t mypid = getpid();
+  rc = getprocs64(&procs, sizeof(procs), NULL, 0, &mypid, 1); 
+  rc = (rc == 1) ? (ll_t) procs.pi_drss*4*scaler : 0;
+#else
+  struct rusage64 r;
+  rc = getrusage64(RUSAGE_SELF, &r);
+  rc = (rc == 0) ? (ll_t) r.ru_maxrss * scaler : 0;
+#endif
+#else
+  struct rusage r;
+  rc = getrusage(RUSAGE_SELF, &r);
+  rc = (rc == 0) ? (ll_t) r.ru_maxrss * scaler : 0;
+#endif
+  return rc;
+}
+
+#else
+
+#if defined(LINUX)
+static ll_t basesize = -1;
+static size_t pagesize = 4096;
+ll_t getrss()
+{
+  struct statm sm;
+  ll_t rc = 0;
+  if (getstatm(&sm) == 0) {
+    if (basesize < 0) { /* the very first time */
+      basesize = sm.resident;
+      pagesize = getpagesize();
+      if (pagesize <= 0) pagesize = 4096;
+    }
+    rc = (sm.resident - basesize) * pagesize;
+  }
+  return rc;
+}
+#else
+ll_t getrss()
+{
+  ll_t rc = (ll_t)((char *)sbrk(0) - (char *)0);
+  return rc;
+}
+#endif
+
+#endif
+
diff --git a/odb/src/extras/ifsaux/utilities/getstackusage.c b/odb/src/extras/ifsaux/utilities/getstackusage.c
new file mode 100644
index 0000000..c3fe2d1
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getstackusage.c
@@ -0,0 +1,5 @@
+#ifdef VPP
+long long int getstackusage_dummy_() { return 0L; }
+#else
+long long int getstackusage_() { return 0L; }
+#endif
diff --git a/odb/src/extras/ifsaux/utilities/getstatm.c b/odb/src/extras/ifsaux/utilities/getstatm.c
new file mode 100644
index 0000000..3bbd887
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getstatm.c
@@ -0,0 +1,35 @@
+#include "getstatm.h"
+
+#if defined(LINUX)
+#include <stdio.h>
+#include <stdlib.h>
+
+int getstatm(struct statm *sm)
+{
+  static int dont_bother = 0;
+  if (!sm || dont_bother) {
+    return -2;
+  }
+  else {
+    FILE *statfile = fopen ("/proc/self/statm", "r");
+    if (!statfile) {
+      dont_bother = 1;
+      return -1;
+    }
+    fscanf(statfile, "%d %d %d %d %d %d %d", 
+	   &(sm->size), &(sm->resident),
+	   &(sm->shared), &(sm->trs), &(sm->drs), 
+	   &(sm->lrs), &(sm->dt));
+    fclose(statfile);
+  }
+  return 0;
+}
+
+#else
+
+int getstatm(struct statm *sm)
+{
+  return -1; /* Not implemented */
+}
+
+#endif
diff --git a/odb/src/extras/ifsaux/utilities/getstk.c b/odb/src/extras/ifsaux/utilities/getstk.c
new file mode 100644
index 0000000..e82b589
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/getstk.c
@@ -0,0 +1,102 @@
+#if defined(__64BIT__) && defined(RS6K)
+#include <pthread.h> /* requires xlc_r or cc_r */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+typedef  long long int  ll_t;
+
+static ll_t maxstack = 0;
+
+#ifdef RS6K
+
+#if defined(__64BIT__)
+/* Assume AIX >= 5.1 with 64-bit addressing */
+
+#include <fcntl.h>
+#include <sys/procfs.h>
+
+static pthread_t master_tid;
+
+ll_t
+getstk_()
+{
+  static int fd = -9999;
+  static ll_t stackbase = 0;
+  ll_t stackused = 0;
+
+  if (fd == -9999) {
+    pstatus_t pstatus;
+    char procfile[80];
+    int pid = getpid();
+    master_tid = pthread_self();
+    snprintf(procfile,sizeof(procfile),"/proc/%d/status",pid);
+    fd = open(procfile, O_RDONLY);
+    if (read(fd, &pstatus, sizeof(pstatus)) == sizeof(pstatus)) {
+      stackbase = (ll_t)pstatus.pr_stkbase;
+      close(fd);
+      fd = 0;
+    }
+  }
+
+  if (fd == 0 && stackbase > 0) {
+    int tid = pthread_self();
+    if (pthread_equal(tid, master_tid)) { /* the master thread */
+      char addr[1];
+      stackused = stackbase - (ll_t)addr;
+      if (stackused > maxstack) maxstack = stackused;
+    }
+    else {
+      stackused = 0; /* at the moment we cannot figure out 
+			stack base address for slave thread(s) */
+    }
+  }
+
+  return stackused;
+}
+
+#else
+
+ll_t
+getstk_() 
+{ 
+  extern ll_t getstackusage_();
+  static ll_t init_stack = -1;
+  ll_t stackused = 0;
+  if (init_stack == -1) init_stack = getstackusage_();
+  stackused = getstackusage_() - init_stack;
+  if (stackused > maxstack) maxstack = stackused;
+  return stackused;
+}
+
+#endif /* defined(__64BIT__) */
+
+#else  /* non-RS6K */
+
+ll_t
+getstk_() 
+{ 
+#if defined(CRAY)
+  return 0;
+#else
+  extern ll_t getstackusage_();
+  static ll_t init_stack = -1;
+  ll_t stackused = 0;
+  if (init_stack == -1) init_stack = getstackusage_();
+  stackused = getstackusage_() - init_stack;
+  if (stackused > maxstack) maxstack = stackused;
+  return stackused;
+#endif
+}
+
+#endif
+
+/* Maximum stacksize encountered */
+
+ll_t
+getmaxstk_()
+{
+  return maxstack;
+}
diff --git a/odb/src/extras/ifsaux/utilities/gnomesort.c b/odb/src/extras/ifsaux/utilities/gnomesort.c
new file mode 100644
index 0000000..3e84808
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/gnomesort.c
@@ -0,0 +1,175 @@
+#include <stdio.h>
+
+/* 
+   gnomesort.c : The easiest sort on Earth ? Yes, it is. 
+
+   This is how a Dutch Garden Gnome sorts a line of flower pots. Basically,
+   he looks at the flower pot next to him and the previous one; 
+   if they are in the right order he steps one pot forward, otherwise 
+   he swaps them and steps one pot backwards. 
+   Boundary conditions: if there is no previous pot, he steps forwards; 
+   if there is no pot next to him, he is done.
+
+   See more Wikipedia & http://www.cs.vu.nl/~dick/gnomesort.html
+
+   Author: Sami Saarinen, ECMWF, 12-Nov-2007
+*/
+
+/* Fortran callable: ecgnomesort_() */
+
+/*
+   Methods:
+
+   0 : Unsigned 32-bit ints
+   1 :   Signed 32-bit ints
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   3 :          32-bit floats  (IEEE) : signbit +  8-bit exp + 23-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+
+typedef unsigned long long int  Uint64;
+typedef          long long int  Sint64;
+typedef unsigned int            Uint32;
+typedef          int            Sint32;
+
+#define GnomeSort(T) \
+static void GnomeSort_##T(T a[], const int n, const int inc) \
+{ \
+  int i = 0; \
+  if (inc == 1) { \
+    while (i < n) { \
+      if (i == 0 || a[i-1] <= a[i]) ++i; \
+      else {T tmp = a[i]; a[i] = a[i-1]; a[--i] = tmp;} \
+    } \
+  } else { \
+    while (i < n) { \
+      if (i == 0 || a[(i-1)*inc] <= a[i*inc]) ++i; \
+      else {T tmp = a[i*inc]; a[i*inc] = a[(i-1)*inc]; a[(--i)*inc] = tmp;} \
+    } \
+  } \
+} \
+static void GnomeSortIdx_##T(const T a[], const int n, const int inc, int index[], const int index_adj) \
+{ \
+  int i = 0; \
+  if (inc == 1) { \
+    if (index_adj) { \
+      while (i < n) { \
+        if (i == 0 || a[index[i-1]-index_adj] <= a[index[i]-index_adj]) ++i; \
+        else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
+      } \
+    } else { /* index_adj == 0 */ \
+       while (i < n) { \
+        if (i == 0 || a[index[i-1]] <= a[index[i]]) i++; \
+        else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
+      } \
+    } \
+  } else { /* inc != 1 */ \
+    if (index_adj) { \
+      while (i < n) { \
+        if (i == 0 || a[(index[i-1]-index_adj)*inc] <= a[(index[i]-index_adj)*inc]) ++i; \
+        else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
+      } \
+    } else { /* index_adj == 0 */ \
+       while (i < n) { \
+        if (i == 0 || a[index[i-1]*inc] <= a[index[i]*inc]) ++i; \
+        else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
+      } \
+    } \
+  } \
+}
+
+#define DoSort(T) { \
+  T *data = Data; \
+  if (index && nidx >= n) { \
+    GnomeSortIdx_##T(&data[addr], n, inc, index, index_adj); \
+  } else { \
+    GnomeSort_##T(&data[addr], n, inc); \
+  } \
+}
+
+#define SORT_UINT 0
+GnomeSort(Uint32)
+
+#define SORT_INT  1
+GnomeSort(Sint32)
+
+#define SORT_R64  2
+GnomeSort(double)
+
+#define SORT_R32  3
+GnomeSort(float)
+
+#define SORT_I64  4
+GnomeSort(Sint64)
+
+#define SORT_U64  5
+GnomeSort(Uint64)
+
+void
+ecgnomesort_(const    int *Mode,
+	     const    int *N,
+	     const    int *Inc,
+	     const    int *Start_addr,
+	             void *Data,
+                      int *index,
+	     const    int *Nindex,
+	     const    int *Index_adj,
+	              int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int nidx = *Nindex; /* Must be >= n or otherwise the index[] is disregarded */
+  int index_adj = *Index_adj;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  if (inc < 1) {
+    rc = -3;
+    goto finish;
+  }
+
+  switch (method) {
+  case SORT_UINT:
+    DoSort(Uint32);
+    break;
+  case SORT_INT:
+    DoSort(Sint32);
+    break;
+  case SORT_R64:
+    DoSort(double);
+    break;
+  case SORT_R32:
+    DoSort(float);
+    break;
+  case SORT_I64:
+    DoSort(Sint64);
+    break;
+  case SORT_U64:
+    DoSort(Uint64);
+    break;
+  }
+
+ finish:
+
+  *retc = rc;
+}
diff --git a/odb/src/extras/ifsaux/utilities/iusrcl.F b/odb/src/extras/ifsaux/utilities/iusrcl.F
new file mode 100644
index 0000000..d08aecc
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/iusrcl.F
@@ -0,0 +1,83 @@
+      INTEGER FUNCTION IUSRCL()
+      INTEGER TIMENOWHIGH
+      DOUBLE PRECISION AMICCLK
+C
+C   MACHINE-DEPENDENT TIMING ROUTINE
+C
+C----------------------------------------------------------------------
+C Author.
+C -------
+C    Ute Gaertel, Wolfgang Joppich, Anton Schueller   *GMD*
+C
+C Modifications.
+C -------------
+C    Original : 93-01-15
+C    Modified : 93-03-15
+C    Modified : 93-08-25
+C----------------------------------------------------------------------
+C
+C------CM 5
+C
+CCM5  integer cmmd_node_timer_clear,cmmd_node_timer_start,
+CCM5 *        cmmd_node_timer_stop,i,istat
+CCM5  double precision time,cmmd_node_timer_elapsed
+CCM5  data istat /0/
+CCM5  save istat
+CCM5
+CCM5  if (istat.eq.0) then
+CCM5    istat = 1
+CCM5    i = cmmd_node_timer_clear(0)
+CCM5    i = cmmd_node_timer_start(0)
+CCM5  endif
+CCM5    i = cmmd_node_timer_stop(0)
+CCM5    time = cmmd_node_timer_elapsed(0)
+CCM5    iusrcl = nint(time*1.0d3)
+CCM5    i = cmmd_node_timer_start(0)
+      double precision util_walltime
+      double precision util_cputime
+      IUSRCL = 0
+C
+C------iPSC/2,  iPSC/860
+C
+C     IUSRCL = MCLOCK()
+C
+C------Parsytec GCel
+C
+C     IUSRCL = TIMENOWHIGH()
+C
+C------IBM RS 6000, Meiko, SGI
+C
+CCSB  IUSRCL = 1000 * SECOND()
+ccli  IUSRCL = 10 * MCLOCK()
+c     IUSRCL =      MCLOCK()
+#if defined(SGI) || defined(VPP)
+      IUSRCL = 1000 * util_walltime()
+c      IUSRCL = 1000 * util_cputime()
+#endif
+C
+C
+C------SUN 
+C
+C3LI  IUSRCL = 1000 
+C
+C
+C------nCUBE/2
+C
+C     IUSRCL = INT (AMICCLK()/1000)
+#ifdef CRAY
+#ifndef T3D
+C
+C------Cray C90
+C
+      IUSRCL = INT( RTC()*4.186D-6 )
+#else
+C------Cray T3D
+C
+      IUSRCL = INT( RTC()*6.667D-6 )
+c--      IUSRCL = 1000 * util_walltime()
+#endif
+#endif
+C
+
+
+      END
diff --git a/odb/src/extras/ifsaux/utilities/jsort.F b/odb/src/extras/ifsaux/utilities/jsort.F
new file mode 100644
index 0000000..5895b33
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/jsort.F
@@ -0,0 +1,84 @@
+#ifdef RS6K
+
+!-- Thanks to John Hague (IBM) and Deborah Salmond (ECMWF) -- 2002
+!   real --> real*8 by Sami Saarinen, ECMWF, 16-Jan-2004
+
+      subroutine jdsort(N, istride, iptr, c, index)
+!
+!**C* *JDSORT* - interface to IBM essl dsorts
+!
+!**C  INTERFACE.
+!     ----------
+!
+!          *CALL* *JDSORT(N,ISTRIDE, IPTR, C, INDEX)
+!           N = number of elements to be sorted
+!           ISTRIDE = stride
+!           IPTR = start address
+!           C = array to be sorted
+!           INDEX = index into array
+!
+      implicit none
+      integer N,istride, iptr
+      real*8 c(*)
+      integer index(N)
+
+! local variables
+
+      integer i,j,ixx(N),ix(N)
+      real*8 cc(N)
+      real*8 w(N/2+1)
+
+      do i=1,N
+        j=(i-1)*istride+1
+        cc(i)=c(iptr+(index(i)-1)*istride)
+        ixx(i)=index(i)
+      enddo
+      call dsorts(cc,1,N,ix,w,size(w))
+      do i=1,N
+        index(i)=ixx(ix(i))
+      enddo
+      return
+      end
+
+
+      subroutine jisort(N, istride, iptr, c, index)
+!
+!**** *JISORT* - interface to IBM essl isorts
+!
+!**   INTERFACE.
+!     ----------
+!
+!          *CALL* *JISORT(N,ISTRIDE, IPTR, C, INDEX)
+!           N = number of elements to be sorted
+!           ISTRIDE = stride
+!           IPTR = start address
+!           C = array to be sorted
+!           INDEX = index into array
+!
+      implicit none
+      integer N,istride, iptr
+      integer c(*),index(N)
+
+! local variables
+
+      integer cc(N)
+      integer i,j,ixx(N),ix(N)
+      integer w(N/2+1)
+
+      do i=1,N
+        j=(i-1)*istride+1
+        cc(i)=c(iptr+(index(i)-1)*istride)
+        ixx(i)=index(i)
+      enddo
+      call isorts(cc,1,N,ix,w,size(w))
+      do i=1,N
+        index(i)=ixx(ix(i))
+      enddo
+      return
+      end
+#else
+!-- other machines --
+      subroutine jsort_dummy()
+      end 
+#endif
+
diff --git a/odb/src/extras/ifsaux/utilities/linuxtrbk.c b/odb/src/extras/ifsaux/utilities/linuxtrbk.c
new file mode 100644
index 0000000..54a7a16
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/linuxtrbk.c
@@ -0,0 +1,295 @@
+
+/* linuxtrbk.c : Print traceback on linux */
+
+/* 
+   Author: Sami Saarinen, ECMWF, 28-Apr-2006
+   The code "nicked" from ifsaux/support/drhook.c
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include "cargs.h"
+
+#ifdef CRAYXT
+/* Cray XT3/XT4 with catamount microkernel */
+#define system(cmd) (-1)
+#endif
+
+#define PRETOSTR(x) #x
+#define TOSTR(x) PRETOSTR(x)
+
+#if defined(SUN4) && !defined(PSTACKTRACE)
+#define PSTACKTRACE /bin/pstack
+#endif
+
+#define strequ(s1,s2)     ((void *)s1 && (void *)s2 && strcmp(s1,s2) == 0)
+#define strnequ(s1,s2,n)  ((void *)s1 && (void *)s2 && memcmp(s1,s2,n) == 0)
+
+
+#if (defined(LINUX) || defined(SUN4)) && !defined(XT3) && !defined(XD1) 
+
+#ifndef LINELEN
+#define LINELEN 1024
+#endif
+
+#if defined(__GNUC__)
+
+#if defined(LINUX) && !defined(CYGWIN) && !defined(DARWIN) && !defined(CRAYXT)
+#include <execinfo.h>
+#elif defined(DARWIN)
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/times.h>
+#include <limits.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#undef HANDLE
+#define HANDLE pthread_t*
+#endif
+
+#define GNUC_BTRACE 1024
+#define __USE_GNU
+#if !defined(CYGWIN)
+#include <ucontext.h>
+#endif
+
+#endif /* defined(__GNUC__) */
+
+#if !defined(ADDR2LINE)
+#define ADDR2LINE /usr/bin/addr2line
+#endif
+
+
+void
+LinuxTraceBack(void *sigcontextptr)
+{
+  extern void gdb_trbk_();
+  extern void dbx_trbk_();
+#if defined(__GNUC__) && defined(LINUX) && !defined(CYGWIN)
+  ucontext_t ctx;
+#endif
+  static int recur = 0;
+  pid_t pid = getpid();
+  const char *a_out = ec_GetArgs(0);
+  fprintf(stderr,"[LinuxTraceBack]: Backtrace(s) for program '%s' (pid=%d) :\n", a_out ? a_out : ec_GetArgs(0), pid);
+  if (++recur > 1) {
+    fprintf(stderr,
+	    "[LinuxTraceBack]: I don't handle recursive calls very well (recursion level = %d)\n",
+	    recur);
+    if (recur > 10) {
+      fprintf(stderr,"[LinuxTraceBack]: Recursion too deep. Exiting immediately with _exit(%d)\n",
+	      recur);
+      _exit(recur); /* Exit immediately */
+    }
+  }
+
+#if defined(__GNUC__) && defined(LINUX) && !defined(CYGWIN) && !defined(DARWIN)
+  fflush(NULL);
+
+  if (!sigcontextptr) {
+    sigcontextptr = getcontext(&ctx) ? NULL : &ctx;
+  }
+  
+  if (sigcontextptr) {
+    /* To have a desired effect, 
+       compile with -g (and maybe -O1 or greater to get some optimization)
+       and link with -g -Wl,-export-dynamic */
+    void *trace[GNUC_BTRACE];
+    int trace_size = 0;
+    ucontext_t *uc = (ucontext_t *)sigcontextptr;
+    int fd = fileno(stderr);
+    trace_size = backtrace(trace, GNUC_BTRACE);
+#if defined(REG_EIP)
+    /* overwrite sigaction with caller's address */
+    trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP]; /* Help!! REG_EIP only available in 32-bit mode ? */
+#endif
+    if (trace_size > 0 && (access(TOSTR(ADDR2LINE),X_OK) == 0)) {
+      /* Use ADDR2LINE to obtain source file & line numbers for each trace-address */
+      int i;
+      FILE *fp = NULL;
+      /* char addr2linecmd[strlen(TOSTR(ADDR2LINE)) + 10 + strlen(a_out) + trace_size * 30]; */
+      int len_addr2linecmd = sizeof(TOSTR(ADDR2LINE)) + 10 + strlen(a_out) + trace_size * 30;
+      char *addr2linecmd = malloc(len_addr2linecmd);
+      snprintf(addr2linecmd, len_addr2linecmd, "%s -e '%s'", TOSTR(ADDR2LINE), a_out);
+      for (i = 0; i < trace_size; i++) {
+	char s[30];
+	snprintf(s,sizeof(s),(sizeof(void *) == 8) ? " %llx" : " %x",trace[i]);
+	strcat(addr2linecmd,s);
+      }
+      fp = popen(addr2linecmd,"r");
+      free(addr2linecmd);
+      if (fp) {
+	char **strings = backtrace_symbols(trace, trace_size);
+	if (strings) {
+	  int len = 20;
+	  for (i = 0; i < trace_size; i++) {
+	    char line[LINELEN];
+	    if (!feof(fp) && fgets(line, LINELEN, fp)) {
+	      const char *last_slash = strrchr(strings[i],'/');
+	      if (last_slash) last_slash++; else last_slash = strings[i];
+	      if (*line != '?') {
+		int newlen;
+		char *nl = strchr(line,'\n');
+		if (nl) *nl = '\0';
+		newlen = strlen(line);
+		if (newlen > len) len = newlen;
+		fprintf(stderr, "(pid=%d): %*.*s  :  %s\n", pid, len, len, line, last_slash);
+	      }
+	      else {
+		fprintf(stderr, "(pid=%d): %*.*s  :  %s\n", pid, len, len, "<Unknown>", last_slash);
+	      }
+	    }
+	    else {
+	      fprintf(stderr, "(pid=%d): %s\n", pid, strings[i]);
+	    }
+	  } /* for (i = 0; i < trace_size; i++) */
+	} /* if (strings) */
+	/* free(strings) */
+	fflush(stderr);
+	pclose(fp);
+      } /* if (fp) */
+    }
+    else {
+      /* Print traceback directly to fd=2 (stderr) */
+      backtrace_symbols_fd(trace, trace_size, fd);
+    } /* if (addr2linecmd) else ... */
+  }
+#endif /* __GNUC__ */
+
+#if defined(PSTACKTRACE)
+  /* This is normally available on Sun/Solaris ("SUN4") platforms */
+  if (access(TOSTR(PSTACKTRACE),X_OK) == 0) {
+    char cmd[sizeof(TOSTR(PSTACKTRACE)) + 20];
+    snprintf(cmd,sizeof(cmd),"%s %d", TOSTR(PSTACKTRACE), pid);
+    fflush(NULL);
+    system(cmd);
+    fflush(NULL);
+  }
+#endif /* defined(PSTACKTRACE) */
+
+  gdb_trbk_();
+  dbx_trbk_();
+
+ finish:
+  fprintf(stderr,"[LinuxTraceBack] : End of backtrace(s)\n");
+  recur--;
+}
+ 
+void linux_trbk_(void)
+{
+  LinuxTraceBack(NULL);
+}
+
+#else
+
+/* Non-Linux: A dummy call which does nothing */
+
+void LinuxTraceBack(void *sigcontextptr) { }
+
+void linux_trbk_(void) { }
+
+#endif
+
+void linux_trbk(void)
+{
+  linux_trbk_();
+}
+
+/* GNU-debugger traceback */
+
+#if !defined(GNUDEBUGGER)
+#define GNUDEBUGGER /usr/bin/gdb
+#endif
+
+void gdb_trbk_()
+{
+  char *gdb = getenv("GNUDEBUGGER");
+  if (gdb && 
+      (access(TOSTR(GNUDEBUGGER),X_OK) == 0) && /* GNUDEBUGGER was set */
+      (strequ(gdb,"1")    || 
+       strequ(gdb,"true") || 
+       strequ(gdb,"TRUE"))) {
+    char gdbcmd[65536];
+    pid_t pid = getpid();
+    const char *a_out = ec_GetArgs(0);
+    fprintf(stderr,
+	    "[gdb_trbk] : Invoking %s ...\n",
+	    TOSTR(GNUDEBUGGER));
+    snprintf(gdbcmd,sizeof(gdbcmd),
+	     "set +e; /bin/echo '"
+	     "set watchdog 1\n"
+	     "set confirm off\n"
+	     "set pagination off\n"
+	     "set print elements 16\n"
+	     "set print repeats 3\n"
+	     "set print sevenbit-strings on\n"
+	     "where\n"
+	     "quit\n' > ./gdb_drhook.%d ; "
+	     "%s -x ./gdb_drhook.%d -q -n -f -batch %s %d < /dev/null ; "
+	     "/bin/rm -f ./gdb_drhook.%d"
+	     , pid
+	     , TOSTR(GNUDEBUGGER), pid, a_out, pid
+	     , pid);
+    
+    /* fprintf(stderr,"%s\n",gdbcmd); */
+    fflush(NULL);
+    system(gdbcmd);
+    fflush(NULL);
+  }
+}
+
+void gdb_trbk() { gdb_trbk_(); }
+
+
+/* DBX-debugger traceback */
+
+#if !defined(DBXDEBUGGER)
+#define DBXDEBUGGER /usr/bin/dbx
+#endif
+
+void dbx_trbk_()
+{
+  char *dbx = getenv("DBXDEBUGGER");
+  if (dbx && 
+      (access(TOSTR(DBXDEBUGGER),X_OK) == 0) && /* DBXDEBUGGER was set */
+      (strequ(dbx,"1")    || 
+       strequ(dbx,"true") || 
+       strequ(dbx,"TRUE"))) {
+    pid_t pid = getpid();
+    const char *a_out = ec_GetArgs(0);
+    char dbxcmd[65536];
+#if defined(SUN4)
+    const char *qopt = " -q";
+#else
+    const char *qopt = "";
+#endif
+    fprintf(stderr,
+	    "[dbx_trbk] : Invoking %s ...\n",
+	    TOSTR(DBXDEBUGGER));
+    if (a_out && (access(a_out,X_OK|R_OK) == 0)) {
+      snprintf(dbxcmd,sizeof(dbxcmd),
+	       "set +e; /bin/echo 'where; quit; '"
+	       " | %s%s %s %d ",
+	       TOSTR(DBXDEBUGGER), qopt, a_out, pid);
+    }
+    else {
+      snprintf(dbxcmd,sizeof(dbxcmd),
+	       "set +e; /bin/echo 'where; quit; '"
+	       " | %s%s - %d ",
+	       TOSTR(DBXDEBUGGER), qopt, pid);
+    }
+    
+    /* fprintf(stderr,"%s\n",dbxcmd); */
+    fflush(NULL);
+    system(dbxcmd);
+    fflush(NULL);
+  }
+}
+
+void dbx_trbk() { dbx_trbk_(); }
diff --git a/odb/src/extras/ifsaux/utilities/rsort32.c b/odb/src/extras/ifsaux/utilities/rsort32.c
new file mode 100644
index 0000000..ebf702f
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/rsort32.c
@@ -0,0 +1,459 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <signal.h>
+#include "intercept_alloc.h"
+#include "raise.h"
+
+/* rsort32_() : 32-bit Fortran-callable RADIX-sort */
+
+/* 
+   by Sami Saarinen, ECMWF, 3/2/1998 
+         - " -              1/2/2000 : BIG_ENDIAN & LITTLE_ENDIAN labels renamed to *_INDIAN
+                                       since they may conflict with the ones in <sys/endian.h>
+         - " -              3/1/2001 : reference to valloc() removed; ALLOC() modified
+	 - " -	           25/1/2001 : BIG_INDIAN removed (as label)
+			               LITTLE_INDIAN called as LITTLE
+         - " -            ??/9?/2001 : Speedup in rsort32
+         - " -             14/3/2002 : rsort32_func implemeted to enable to run alternative sorting
+                                       routine than rsort32
+         - " -            18/02/2005 : Handle 64-bit (signed) ints
+                                       IBM malloc() may call __malloc()/__free() [see getcurheap.c]
+         - " -            21/02/2005 : Some optimization & endian detection on-the-fly
+         - " -            07/07/2005 : Mods in index_adj & bitsum
+	                               Added support for 64-bit unsigned ints
+           - " -          07/02/2007 : Intercepting alloc (IBM & NEC SX) + NEC SX vectorization
+
+   Thanks to Mike Fisher, ECMWF
+   and Cray SCILIB ORDERS()-function developers
+*/
+
+/* 
+   Methods:
+
+   0 : Unsigned 32-bit ints
+   1 :   Signed 32-bit ints
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   3 :          32-bit floats  (IEEE) : signbit +  8-bit exp + 23-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+typedef unsigned int  Uint32;
+typedef unsigned char Uchar;
+
+#ifdef __uxppx__
+#ifndef VPP
+#define VPP
+#endif
+#endif
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#if defined(VPP) || defined(NECSX)
+/* .. or any vector machine */
+static int SpeedUp = 0;
+#else
+/* scalar prozezzorz */
+static int SpeedUp = 1;
+#endif
+
+#define SORT_UINT 0
+#define SORT_INT  1
+#define SORT_R64  2
+#define SORT_R32  3
+#define SORT_I64  4
+#define SORT_U64  5
+
+typedef long long int ll_t;
+
+#define  ALLOC(x,size)    \
+ { ll_t bytes = (ll_t)sizeof(*x) * (size); \
+   bytes = (bytes < 1) ? 1 : bytes; \
+   x = THEmalloc(bytes); \
+   if (!x) { fprintf(stderr, \
+		     "malloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
+		     #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
+
+#define FREE(x)           if (x) { THEfree(x); x = NULL; }
+
+#define BITSUM(x) bitsum[x] += ((item >> x) & 1U)
+
+#define SIGNBIT32   0x80000000
+#define MASKALL32   0xFFFFFFFF
+#define ZEROALL32   0x00000000
+
+#define CVMGM(a,b,c) ( ((c) & SIGNBIT32) ? (a) : (b) )
+
+#define N32BITS 32
+
+void 
+rsort32_(const    int *Mode,
+	 const    int *N,
+	 const    int *Inc,
+	 const    int *Start_addr,
+	       Uint32  Data[],
+	          int  index[],
+	 const    int *Index_adj,
+	          int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int index_adj = *Index_adj;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+  int i, j, jj;
+  Uchar xorit = 0;
+  Uchar copytmp = 0;
+  Uchar alloc_data = 0;
+  Uint32 *data = NULL;
+  int *tmp = NULL;
+  Uint32 bitsum[N32BITS];
+  int lsw, msw;
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  if (inc < 1) {
+    rc = -3;
+    goto finish;
+  }
+
+  { /* Little/big-endian selection */
+    extern int ec_is_little_endian();
+    int i_am_little = ec_is_little_endian();
+
+    if (i_am_little) { 
+      /* We are on little-endian machine */
+      lsw   =  0;
+      msw   =  1;
+    }
+    else { 
+      /* We are on big-endian machine */
+      lsw   =  1;
+      msw   =  0;
+    }
+  }
+
+  if (method == SORT_R64    || 
+      method == SORT_I64    ||
+      method == SORT_U64) {
+    inc  *= 2;
+    addr *= 2;
+  }
+
+  if (mode < 10) {
+    /* index[] needs to be initialized */
+    for (i=0; i<n; i++) index[i] = i + index_adj;
+  }
+
+  alloc_data = ((inc > 1) 
+		|| (method == SORT_R32) 
+		|| (method == SORT_R64)
+		|| (method == SORT_I64)
+		|| (method == SORT_U64)
+		);
+  if (alloc_data) ALLOC(data, n);
+
+  if (method == SORT_R32) {
+    j = addr;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, SIGNBIT32, Data[j]);
+      data[i] = Data[j] ^ mask;
+      j += inc;
+    }
+
+    method = SORT_UINT;
+  }
+  else if (method == SORT_R64) {
+    int Method = 10 + SORT_UINT;
+    const int aStart_addr = 1;
+    int aN = n;
+    const int aInc = 1;
+    int aIndex_adj = index_adj;
+
+    /* Least significant word */
+    j  = addr + lsw;
+    jj = addr + msw;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, ZEROALL32, Data[jj]);
+      data[i] = Data[j] ^ mask;
+      j += inc;
+      jj += inc;
+    }
+
+    rsort32_(&Method, &aN, &aInc, &aStart_addr, data, index, &aIndex_adj, &rc);
+
+    if (rc != n) goto finish;
+
+    /* Most significant word */
+    jj = addr + msw;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, SIGNBIT32, Data[jj]);
+      data[i] = Data[jj] ^ mask;
+      jj += inc;
+    }
+
+    method = SORT_UINT;
+  }
+  else if (method == SORT_I64 || method == SORT_U64) {
+    int Method = 10 + SORT_UINT;
+    const int aStart_addr = 1;
+    int aN = n;
+    const int aInc = 1;
+    int aIndex_adj = index_adj;
+
+    /* Least significant word */
+    jj = addr + lsw;
+    for (i=0; i<n; i++) {
+      data[i] = Data[jj];
+      jj += inc;
+    }
+
+    rsort32_(&Method, &aN, &aInc, &aStart_addr, data, index, &aIndex_adj, &rc);
+
+    if (rc != n) goto finish;
+
+    /* Most significant word */
+    if (method == SORT_I64) {
+      jj = addr + msw;
+      for (i=0; i<n; i++) {
+	data[i] = Data[jj] ^ SIGNBIT32;
+	jj += inc;
+      }
+    }
+    else { /* unsigned 64-bit ints i.e. method == SORT_U64 */
+      jj = addr + msw;
+      for (i=0; i<n; i++) {
+	data[i] = Data[jj];
+	jj += inc;
+      }
+    }
+
+    method = SORT_UINT;
+  }
+  else if (inc > 1) {
+    j = addr;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+    for (i=0; i<n; i++) {
+      data[i] = Data[j];
+      j += inc;
+    }
+  }
+  else {
+    data = &Data[addr];
+  }
+
+  xorit = (method == SORT_INT);
+
+  /* Check whether particular "bit-columns" are all zero or one */
+
+  for (j=0; j<N32BITS; j++) bitsum[j] = 0;
+
+  for (i=0; i<n; i++) {
+    Uint32 item;
+    if (xorit) data[i] ^= SIGNBIT32;
+    item = data[i];
+    /* Unrolled, full vector */
+    BITSUM(0) ; BITSUM(1) ; BITSUM(2) ; BITSUM(3) ;
+    BITSUM(4) ; BITSUM(5) ; BITSUM(6) ; BITSUM(7) ;
+    BITSUM(8) ; BITSUM(9) ; BITSUM(10); BITSUM(11);
+    BITSUM(12); BITSUM(13); BITSUM(14); BITSUM(15);
+    BITSUM(16); BITSUM(17); BITSUM(18); BITSUM(19);
+    BITSUM(20); BITSUM(21); BITSUM(22); BITSUM(23);
+    BITSUM(24); BITSUM(25); BITSUM(26); BITSUM(27);
+    BITSUM(28); BITSUM(29); BITSUM(30); BITSUM(31);
+  }
+
+  ALLOC(tmp, n);
+
+  jj = 0;
+  for (j=0; j<N32BITS; j++) {
+    int sum = bitsum[j];
+    if (sum > 0 && sum < n) { /* if 0 or n, then the whole column of bits#j 0's or 1's */
+      Uint32 mask = (1U << j);
+      int *i1, *i2;
+      
+      if (jj%2 == 0) {
+	i1 = index;
+	i2 = tmp;
+	copytmp = 1;
+      }
+      else {
+	i1 = tmp;
+	i2 = index;
+	copytmp = 0;
+      }
+      
+      if (SpeedUp == 0) {
+	int k = 0;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+	for (i=0; i<n; i++) /* Gather zero bits */
+	  if ( (data[i1[i]-index_adj] & mask) ==    0 ) i2[k++] = i1[i];
+	
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+	for (i=0; i<n; i++) /* Gather one bits */
+	  if ( (data[i1[i]-index_adj] & mask) == mask ) i2[k++] = i1[i];
+      }
+      else
+      {
+	int k1 = 0, k2 = n-sum;
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+	for (i=0; i<n; i++) { /* Gather zero & one bits in a single sweep */
+	  Uint32 value = data[i1[i]-index_adj] & mask;
+	  i2[value == 0 ? k1++ : k2++] = i1[i];
+	} /* for (i=0; i<n; i++) */
+	if (k1 + sum != n || k2 != n) {
+	  fprintf(stderr,
+		  "***Programming error in rsort32_(): k1 + sum != n || k2 != n; k1=%d,k2=%d,sum=%d,n=%d\n",
+		  k1,k2,sum,n);
+	  RAISE(SIGABRT);
+	}
+      }
+      
+      jj++;
+    }
+  }
+
+  if (copytmp) {
+#ifdef NECSX
+#pragma cdir nodep
+#endif
+	for (i=0; i<n; i++) index[i] = tmp[i];
+  }
+
+  FREE(tmp);
+
+  if (!alloc_data && xorit && inc == 1) {
+    /* 32-bit signed ints : backward */
+    for (i=0; i<n; i++) data[i] ^= SIGNBIT32;
+  }
+
+  if (alloc_data) FREE(data);
+
+ finish:
+
+  *retc = rc;
+}
+
+
+void 
+rsort32_ibm_(const    int *Mode,
+	     const    int *N,
+	     const    int *Inc,
+	     const    int *Start_addr,
+	           Uint32  Data[],
+	              int  index[],
+	     const    int *Index_adj,
+	              int *retc)
+{
+#ifdef RS6K
+  int mode = *Mode;
+  int method = mode%10;
+  int index_adj = *Index_adj;
+
+  if (method == SORT_INT && index_adj == 1) { /* 32-bit ints ; Fortran-arrays */
+    jisort_( N, Inc, Start_addr, Data, index ); /* from jsort.F in ifsaux */
+    *retc = *N;
+  }
+  else if (method == SORT_R64 && index_adj == 1) { /* 64-bit reals ; Fortran-arrays */
+    jdsort_( N, Inc, Start_addr, Data, index ); /* from jsort.F in ifsaux */
+    *retc = *N;
+  }
+  else { /* Any other type => revert to the generic rsort32 */
+    rsort32_(Mode, N, Inc, Start_addr, Data, index, Index_adj, retc);
+  }
+#else
+  /* Any other machine than IBM/RS6000 => revert to the generic rsort32 */
+  rsort32_(Mode, N, Inc, Start_addr, Data, index, Index_adj, retc);
+#endif
+}
+
+
+static 
+void (*default_rsort32_func)(const    int *Mode,
+			     const    int *N,
+			     const    int *Inc,
+			     const    int *Start_addr,
+			           Uint32  Data[],
+			              int  index[],
+			     const    int *Index_adj,
+			              int *retc) =
+#ifdef RS6K
+     rsort32_ibm_
+#else
+     rsort32_
+#endif
+;
+
+void 
+rsort32_func_(const    int *Mode,
+	      const    int *N,
+	      const    int *Inc,
+	      const    int *Start_addr,
+	      Uint32        Data[],
+	      int           index[],
+	      const    int *Index_adj,
+	      int          *retc)
+{
+  default_rsort32_func(Mode,
+		       N,
+		       Inc,
+		       Start_addr,
+		       Data,
+		       index,
+		       Index_adj,
+		       retc);
+}
+
+void 
+rsort32_setup_(void (*func)(const    int *Mode,
+			    const    int *N,
+			    const    int *Inc,
+			    const    int *Start_addr,
+			    Uint32        Data[],
+			    int           index[],
+			    const    int *Index_adj,
+			    int          *retc),
+	       int *speedup)
+{
+  if (func) default_rsort32_func = func;
+  if (speedup) SpeedUp = *speedup;
+}
diff --git a/odb/src/extras/ifsaux/utilities/rsort64.c b/odb/src/extras/ifsaux/utilities/rsort64.c
new file mode 100644
index 0000000..36f4e5c
--- /dev/null
+++ b/odb/src/extras/ifsaux/utilities/rsort64.c
@@ -0,0 +1,248 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <signal.h>
+#include "intercept_alloc.h"
+#include "raise.h"
+
+/* rsort64_() : 64-bit Fortran-callable RADIX-sort */
+
+/* 
+   by Sami Saarinen, ECMWF, 22/02/2005 : Initial version derived from rsort32.c
+           - " -            23/02/2005 : Fixes and some optimizations
+           - " -            07/07/2005 : Mods in index_adj & bitsum
+           - " -            07/02/2007 : Intercepting alloc (IBM & NEC SX) + NEC SX vectorization
+      
+
+   Thanks to Mike Fisher, ECMWF
+   and Cray SCILIB ORDERS()-function developers
+*/
+
+/* 
+   Methods:
+
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+typedef unsigned int            Uint32;
+typedef unsigned long long int  Uint64;
+typedef unsigned char           Uchar;
+
+#ifdef __uxppx__
+#ifndef VPP
+#define VPP
+#endif
+#endif
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#if defined(VPP) || defined(NECSX)
+/* .. or any vector machine */
+static int SpeedUp = 0;
+#else
+/* scalar prozezzorz */
+static int SpeedUp = 1;
+#endif
+
+#define SORT_R64  2
+#define SORT_I64  4
+#define SORT_U64  5
+
+typedef long long int ll_t;
+
+#define  ALLOC(x,size)    \
+ { ll_t bytes = (ll_t)sizeof(*x) * (size); \
+   bytes = (bytes < 1) ? 1 : bytes; \
+   x = THEmalloc(bytes); \
+   if (!x) { fprintf(stderr, \
+		     "malloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
+		     #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
+
+#define FREE(x)           if (x) { THEfree(x); x = NULL; }
+
+#define BITSUM(x) bitsum[x] += ((item >> x) & 1ull)
+
+#define SIGNBIT64   0x8000000000000000ull
+#define MASKALL64   0xFFFFFFFFFFFFFFFFull
+#define ZEROALL64   0x0000000000000000ull
+
+#define CVMGM(a,b,c) ( ((c) & SIGNBIT64) ? (a) : (b) )
+
+#define N64BITS 64
+
+void 
+rsort64_(const    int *Mode,       /* if < 10, then index[] needs to be initialized ; method = modulo 10 */
+	 const    int *N,          /* no. of 64-bit elements */
+	 const    int *Inc,        /* stride in terms of 64-bit elements */
+	 const    int *Start_addr, /* Fortran start address i.e. normally == 1 */
+	       Uint64  Data[],     /* 64-bit elements to be sorted */
+	          int  index[],    /* sorting index */
+	 const    int *Index_adj,  /* 0=index[] is a C-index, 1=index[] is a Fortran-index (the usual case) */
+	          int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int index_adj = *Index_adj;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+  int i, j, jj;
+  Uchar xorit = 0;
+  Uchar copytmp = 0;
+  Uchar alloc_data = 0;
+  Uint64 *data = NULL;
+  int *tmp = NULL;
+  Uint32 bitsum[N64BITS];
+
+  if (method != SORT_R64    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  if (inc < 1) {
+    rc = -3;
+    goto finish;
+  }
+
+  if (mode < 10) {
+    /* index[] needs to be initialized */
+    for (i=0; i<n; i++) index[i] = i + index_adj; /* Fortran-index */
+  }
+
+  j = addr;
+  data = &Data[j];
+
+  alloc_data = ((inc > 1) || (method == SORT_R64));
+  if (alloc_data) ALLOC(data, n);
+
+  if (method == SORT_R64) {
+    for (i=0; i<n; i++) {
+      Uint64 mask = CVMGM(MASKALL64, SIGNBIT64, Data[j]);
+      data[i] = Data[j] ^ mask;
+      j += inc;
+    }
+  }
+  else if (method == SORT_I64) {
+    if (inc == 1) { /* optimization */
+      for (i=0; i<n; i++) {
+	data[i] ^= SIGNBIT64;
+      }
+    }
+    else {
+      for (i=0; i<n; i++) {
+	data[i] = Data[j] ^ SIGNBIT64;
+	j += inc;
+      }
+    }
+    xorit = 1;
+  }
+  else if (inc > 1) {
+    for (i=0; i<n; i++) {
+      data[i] = Data[j];
+      j += inc;
+    }
+  }
+
+  /* Check whether particular "bit-columns" are all zero or one */
+
+  for (j=0; j<N64BITS; j++) bitsum[j] = 0;
+
+  for (i=0; i<n; i++) {
+    Uint64 item = data[i];
+    /* Unrolled, full vector */
+    BITSUM(0) ; BITSUM(1) ; BITSUM(2) ; BITSUM(3) ;
+    BITSUM(4) ; BITSUM(5) ; BITSUM(6) ; BITSUM(7) ;
+    BITSUM(8) ; BITSUM(9) ; BITSUM(10); BITSUM(11);
+    BITSUM(12); BITSUM(13); BITSUM(14); BITSUM(15);
+    BITSUM(16); BITSUM(17); BITSUM(18); BITSUM(19);
+    BITSUM(20); BITSUM(21); BITSUM(22); BITSUM(23);
+    BITSUM(24); BITSUM(25); BITSUM(26); BITSUM(27);
+    BITSUM(28); BITSUM(29); BITSUM(30); BITSUM(31);
+    BITSUM(32); BITSUM(33); BITSUM(34); BITSUM(35); 
+    BITSUM(36); BITSUM(37); BITSUM(38); BITSUM(39); 
+    BITSUM(40); BITSUM(41); BITSUM(42); BITSUM(43);
+    BITSUM(44); BITSUM(45); BITSUM(46); BITSUM(47);
+    BITSUM(48); BITSUM(49); BITSUM(50); BITSUM(51);
+    BITSUM(52); BITSUM(53); BITSUM(54); BITSUM(55);
+    BITSUM(56); BITSUM(57); BITSUM(58); BITSUM(59);
+    BITSUM(60); BITSUM(61); BITSUM(62); BITSUM(63);
+  }
+
+  ALLOC(tmp, n);
+
+  jj = 0;
+  for (j=0; j<N64BITS; j++) {
+    int sum = bitsum[j];
+    if (sum > 0 && sum < n) { /* if 0 or n, then the whole column of bits#j 0's or 1's */
+      Uint64 mask = (1ull << j);
+      int *i1, *i2;
+      
+      if (jj%2 == 0) {
+	i1 = index;
+	i2 = tmp;
+	copytmp = 1;
+      }
+      else {
+	i1 = tmp;
+	i2 = index;
+	copytmp = 0;
+      }
+      
+      if (SpeedUp == 0) {
+	int k = 0;
+	for (i=0; i<n; i++) /* Gather zero bits */
+	  if ( (data[i1[i]-index_adj] & mask) ==    0 ) i2[k++] = i1[i];
+	
+	for (i=0; i<n; i++) /* Gather one bits */
+	  if ( (data[i1[i]-index_adj] & mask) == mask ) i2[k++] = i1[i];
+      }
+      else
+      {
+	int k1 = 0, k2 = n-sum;
+	for (i=0; i<n; i++) { /* Gather zero & one bits in a single sweep */
+	  Uint64 value = data[i1[i]-index_adj] & mask;
+	  i2[value == 0 ? k1++ : k2++] = i1[i];
+	} /* for (i=0; i<n; i++) */
+	if (k1 + sum != n || k2 != n) {
+	  fprintf(stderr,
+		  "***Programming error in rsort64_(): k1 + sum != n || k2 != n; k1=%d,k2=%d,sum=%d,n=%d\n",
+		  k1,k2,sum,n);
+	  RAISE(SIGABRT);
+	}
+      }
+      
+      jj++;
+    } /* if (sum > 0 && sum < n) */
+  }
+
+  if (copytmp) for (i=0; i<n; i++) index[i] = tmp[i];
+
+  FREE(tmp);
+
+  if (!alloc_data && xorit && inc == 1) {
+    /* 64-bit signed ints : backward */
+    for (i=0; i<n; i++) data[i] ^= SIGNBIT64;
+  }
+
+  if (alloc_data) FREE(data);
+
+ finish:
+
+  *retc = rc;
+}
diff --git a/odb/src/extras/mpi_serial/CMakeLists.txt b/odb/src/extras/mpi_serial/CMakeLists.txt
new file mode 100644
index 0000000..712d9d6
--- /dev/null
+++ b/odb/src/extras/mpi_serial/CMakeLists.txt
@@ -0,0 +1,64 @@
+list(APPEND _odb_mpi_serial_sources
+
+    mpif.h
+    mpif.h.necsx.BoM
+    mpif.h.necsx5.CSCS
+
+    mpi_abort.F
+    mpi_allgatherv.F
+    mpi_allreduce.F
+    mpi_alltoallv.F
+    mpi_barrier.F
+    mpi_bcast.F
+    mpi_bsend.F
+    mpi_buffer_attach.F
+    mpi_buffer_detach.F
+    mpi_cart_coords.F
+    mpi_cart_create.F
+    mpi_cart_rank.F
+    mpi_cart_sub.F
+    mpi_comm_create.F
+    mpi_comm_group.F
+    mpi_comm_rank.F
+    mpi_comm_size.F
+    mpi_comm_split.F
+    mpi_end.F
+    mpi_error_string.F
+    mpi_finalize.F
+    mpi_finalized.F
+    mpi_gather.F
+    mpi_gatherv.F
+    mpi_get_count.F
+    mpi_group_incl.F
+    mpi_ibsend.F
+    mpi_init.F
+    mpi_initialized.F
+    mpi_iprobe.F
+    mpi_irecv.F
+    mpi_isend.F
+    mpi_probe.F
+    mpi_recv.F
+    mpi_scatterv.F
+    mpi_send.F
+    mpi_ssend.F
+    mpi_wait.F
+    mpi_waitall.F
+    tracecalls.c
+    vpp_abort.F
+    vpp_barrier.F
+    vpp_sempost.c
+    vpp_semwait.c
+)
+
+ecbuild_add_library(TARGET odbmpiserial
+  TYPE ${ODB_LIBS_TYPE}
+  SOURCES ${_odb_mpi_serial_sources}
+  CONDITION NOT HAVE_ODB_MPI)
+
+if(NOT HAVE_ODB_MPI)
+  set(_ODB_MPI_LIBS odbmpiserial PARENT_SCOPE)
+  set(_ODB_MPI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
+else()
+  set(_ODB_MPI_LIBS ${MPI_Fortran_LIBRARIES} PARENT_SCOPE)
+  set(_ODB_MPI_INCLUDE_DIRS ${MPI_Fortran_INCLUDE_PATH} PARENT_SCOPE)
+endif()
diff --git a/odb/src/extras/mpi_serial/mpi_abort.F b/odb/src/extras/mpi_serial/mpi_abort.F
new file mode 100644
index 0000000..e6b2ff5
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_abort.F
@@ -0,0 +1,6 @@
+      subroutine mpi_abort(icomm,iret,ierr)
+      INTEGER, parameter :: SIGABRT = 6 ! Hardcoded
+      CALL ec_raise(SIGABRT)
+      ierr=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_allgatherv.F b/odb/src/extras/mpi_serial/mpi_allgatherv.F
new file mode 100644
index 0000000..bcb5289
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_allgatherv.F
@@ -0,0 +1,3 @@
+      subroutine mpi_allgatherv
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_allreduce.F b/odb/src/extras/mpi_serial/mpi_allreduce.F
new file mode 100644
index 0000000..16d5fa8
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_allreduce.F
@@ -0,0 +1,3 @@
+      subroutine mpi_allreduce
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_alltoallv.F b/odb/src/extras/mpi_serial/mpi_alltoallv.F
new file mode 100644
index 0000000..d81330c
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_alltoallv.F
@@ -0,0 +1,4 @@
+      subroutine mpi_alltoallv
+      call abor1('mpi_alltoallv should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_barrier.F b/odb/src/extras/mpi_serial/mpi_barrier.F
new file mode 100644
index 0000000..c4edb1c
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_barrier.F
@@ -0,0 +1,3 @@
+      subroutine mpi_barrier
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_bcast.F b/odb/src/extras/mpi_serial/mpi_bcast.F
new file mode 100644
index 0000000..f43ce14
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_bcast.F
@@ -0,0 +1,3 @@
+      subroutine mpi_bcast
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_bsend.F b/odb/src/extras/mpi_serial/mpi_bsend.F
new file mode 100644
index 0000000..556a966
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_bsend.F
@@ -0,0 +1,4 @@
+      subroutine mpi_bsend
+      call abor1('attempt to call dummy mpi_bsend')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_buffer_attach.F b/odb/src/extras/mpi_serial/mpi_buffer_attach.F
new file mode 100644
index 0000000..6f7fd54
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_buffer_attach.F
@@ -0,0 +1,4 @@
+      subroutine mpi_buffer_attach(i1,i2,ierror)
+      ierror=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_buffer_detach.F b/odb/src/extras/mpi_serial/mpi_buffer_detach.F
new file mode 100644
index 0000000..f45ecab
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_buffer_detach.F
@@ -0,0 +1,3 @@
+      subroutine mpi_buffer_detach
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_cart_coords.F b/odb/src/extras/mpi_serial/mpi_cart_coords.F
new file mode 100644
index 0000000..3977515
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_cart_coords.F
@@ -0,0 +1,4 @@
+      subroutine mpi_cart_coords
+!     call abor1('mpi_cart_coords should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_cart_create.F b/odb/src/extras/mpi_serial/mpi_cart_create.F
new file mode 100644
index 0000000..b0a01c0
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_cart_create.F
@@ -0,0 +1,4 @@
+      subroutine mpi_cart_create
+!     call abor1('mpi_cart_create should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_cart_rank.F b/odb/src/extras/mpi_serial/mpi_cart_rank.F
new file mode 100644
index 0000000..3e2caaf
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_cart_rank.F
@@ -0,0 +1,4 @@
+      subroutine mpi_cart_rank
+!     call abor1('mpi_cart_rank should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_cart_sub.F b/odb/src/extras/mpi_serial/mpi_cart_sub.F
new file mode 100644
index 0000000..ae0c2b0
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_cart_sub.F
@@ -0,0 +1,4 @@
+      subroutine mpi_cart_sub
+!     call abor1('mpi_cart_sub should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_comm_create.F b/odb/src/extras/mpi_serial/mpi_comm_create.F
new file mode 100644
index 0000000..48e49ae
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_comm_create.F
@@ -0,0 +1,6 @@
+      subroutine mpi_comm_create(MPI_COMM_WORLD,IGROUP,KCOMM,IER)
+!      call abor1('mpi_comm_create should never be called')
+      KCOMM = MPI_COMM_WORLD
+      IER=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_comm_group.F b/odb/src/extras/mpi_serial/mpi_comm_group.F
new file mode 100644
index 0000000..c8cffb9
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_comm_group.F
@@ -0,0 +1,5 @@
+      subroutine mpi_comm_group(MPI_COMM_WORLD,MPI_GROUP_WORLD,IER)
+!     call abor1('mpi_comm_group should never be called')
+      IER=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_comm_rank.F b/odb/src/extras/mpi_serial/mpi_comm_rank.F
new file mode 100644
index 0000000..6e0a411
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_comm_rank.F
@@ -0,0 +1,5 @@
+      subroutine mpi_comm_rank(ic,ir,ie)
+      ir=0
+      ie=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_comm_size.F b/odb/src/extras/mpi_serial/mpi_comm_size.F
new file mode 100644
index 0000000..7a525a4
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_comm_size.F
@@ -0,0 +1,5 @@
+      subroutine mpi_comm_size(ic,is,ie)
+      is=1
+      ie=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_comm_split.F b/odb/src/extras/mpi_serial/mpi_comm_split.F
new file mode 100644
index 0000000..bc9dba7
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_comm_split.F
@@ -0,0 +1,4 @@
+      subroutine mpi_comm_split(ierr)
+      ierr=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_end.F b/odb/src/extras/mpi_serial/mpi_end.F
new file mode 100644
index 0000000..88e41cb
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_end.F
@@ -0,0 +1,4 @@
+      subroutine mpi_end(ierr)
+      ierr=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_error_string.F b/odb/src/extras/mpi_serial/mpi_error_string.F
new file mode 100644
index 0000000..ffcedae
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_error_string.F
@@ -0,0 +1,4 @@
+      subroutine mpi_error_string
+      call abor1('attempt to call dummy mpi_error_string')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_finalize.F b/odb/src/extras/mpi_serial/mpi_finalize.F
new file mode 100644
index 0000000..6b059e6
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_finalize.F
@@ -0,0 +1,4 @@
+      subroutine mpi_finalize(ie)
+      ie=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_finalized.F b/odb/src/extras/mpi_serial/mpi_finalized.F
new file mode 100644
index 0000000..07451a7
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_finalized.F
@@ -0,0 +1,6 @@
+      subroutine mpi_finalized(lf,ie)
+      implicit logical (l)
+      lf=.FALSE.
+      ie=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_gather.F b/odb/src/extras/mpi_serial/mpi_gather.F
new file mode 100644
index 0000000..3f98dce
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_gather.F
@@ -0,0 +1,3 @@
+      subroutine mpi_gather
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_gatherv.F b/odb/src/extras/mpi_serial/mpi_gatherv.F
new file mode 100644
index 0000000..efef327
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_gatherv.F
@@ -0,0 +1,3 @@
+      subroutine mpi_gatherv
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_get_count.F b/odb/src/extras/mpi_serial/mpi_get_count.F
new file mode 100644
index 0000000..8342671
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_get_count.F
@@ -0,0 +1,4 @@
+      subroutine mpi_get_count
+      call abor1('attempt to call dummy mpi_get_count')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_group_incl.F b/odb/src/extras/mpi_serial/mpi_group_incl.F
new file mode 100644
index 0000000..2b4bbfc
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_group_incl.F
@@ -0,0 +1,5 @@
+      subroutine mpi_group_incl(MPI_GROUP_WORLD,N,IRANK,IGROUP,IER)
+!      call abor1('mpi_group_incl should never be called')
+      IER=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_ibsend.F b/odb/src/extras/mpi_serial/mpi_ibsend.F
new file mode 100644
index 0000000..a112212
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_ibsend.F
@@ -0,0 +1,4 @@
+      subroutine mpi_ibsend
+      call abor1('attempt to call dummy mpi_ibsend')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_init.F b/odb/src/extras/mpi_serial/mpi_init.F
new file mode 100644
index 0000000..af13322
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_init.F
@@ -0,0 +1,4 @@
+      subroutine mpi_init(ierr)
+      ierr=0
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_initialized.F b/odb/src/extras/mpi_serial/mpi_initialized.F
new file mode 100644
index 0000000..8d8a6f5
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_initialized.F
@@ -0,0 +1,34 @@
+      subroutine mpi_initialized(ldflag,ierr)
+      logical ldflag
+      integer ierr
+      ldflag=.FALSE. ! doesn't matter, 1 proc anyway since mpi_serial
+      ierr=0
+      return
+      end
+
+!-- the following dummies that are never called, but cause linking to fail with GNU/g95
+!   and produce complaints with Intel ifort.
+!   origin of these "externals" is coming from generic & dummy odb/scripts/mpif.h
+
+      FUNCTION MPI_WTIME()
+      DOUBLE PRECISION MPI_WTIME
+      MPI_WTIME = 1d-10
+      END
+      FUNCTION MPI_WTICK()
+      DOUBLE PRECISION MPI_WTICK
+      MPI_WTICK = 1
+      END
+      FUNCTION PMPI_WTIME()
+      DOUBLE PRECISION PMPI_WTIME
+      PMPI_WTIME = 1d-10
+      END
+      FUNCTION PMPI_WTICK()
+      DOUBLE PRECISION PMPI_WTICK
+      PMPI_WTICK = 1
+      END
+      SUBROUTINE MPI_NULL_COPY_FN
+      END
+      SUBROUTINE MPI_NULL_DELETE_FN
+      END
+      SUBROUTINE MPI_DUP_FN
+      END
diff --git a/odb/src/extras/mpi_serial/mpi_iprobe.F b/odb/src/extras/mpi_serial/mpi_iprobe.F
new file mode 100644
index 0000000..72b517a
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_iprobe.F
@@ -0,0 +1,4 @@
+      subroutine mpi_iprobe
+      call abor1('attempt to call dummy mpi_iprobe')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_irecv.F b/odb/src/extras/mpi_serial/mpi_irecv.F
new file mode 100644
index 0000000..8fa8640
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_irecv.F
@@ -0,0 +1,4 @@
+      subroutine mpi_irecv
+      call abor1('attempt to call dummy mpi_irecv')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_isend.F b/odb/src/extras/mpi_serial/mpi_isend.F
new file mode 100644
index 0000000..a5dbd84
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_isend.F
@@ -0,0 +1,4 @@
+      subroutine mpi_isend
+      call abor1('attempt to call dummy mpi_isend')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_probe.F b/odb/src/extras/mpi_serial/mpi_probe.F
new file mode 100644
index 0000000..ed34da0
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_probe.F
@@ -0,0 +1,4 @@
+      subroutine mpi_probe
+      call abor1('attempt to call dummy mpi_probe')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_recv.F b/odb/src/extras/mpi_serial/mpi_recv.F
new file mode 100644
index 0000000..a55600c
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_recv.F
@@ -0,0 +1,4 @@
+      subroutine mpi_recv
+      call abor1('attempt to call dummy mpi_recv')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_scatterv.F b/odb/src/extras/mpi_serial/mpi_scatterv.F
new file mode 100644
index 0000000..2a65103
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_scatterv.F
@@ -0,0 +1,4 @@
+      subroutine mpi_scatterv
+      call abor1('mpi_scatterv should never be called')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_send.F b/odb/src/extras/mpi_serial/mpi_send.F
new file mode 100644
index 0000000..10193cd
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_send.F
@@ -0,0 +1,4 @@
+      subroutine mpi_send
+      call abor1('attempt to call dummy mpi_send')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_ssend.F b/odb/src/extras/mpi_serial/mpi_ssend.F
new file mode 100644
index 0000000..59e0e16
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_ssend.F
@@ -0,0 +1,4 @@
+      subroutine mpi_ssend
+      call abor1('attempt to call dummy mpi_ssend')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_wait.F b/odb/src/extras/mpi_serial/mpi_wait.F
new file mode 100644
index 0000000..ff44b6d
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_wait.F
@@ -0,0 +1,3 @@
+      subroutine mpi_wait
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpi_waitall.F b/odb/src/extras/mpi_serial/mpi_waitall.F
new file mode 100644
index 0000000..8e012a2
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpi_waitall.F
@@ -0,0 +1,4 @@
+      subroutine mpi_waitall
+      call abor1('attempt to call dummy mpi_waitall')
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/mpif.h b/odb/src/extras/mpi_serial/mpif.h
new file mode 100644
index 0000000..6a0497d
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpif.h
@@ -0,0 +1,221 @@
+!
+!  
+!  (C) 1993 by Argonne National Laboratory and Mississipi State University.
+!      All rights reserved.  See COPYRIGHT in top-level directory.
+!
+!
+! user include file for MPI programs, with no dependencies 
+!
+! It really is not possible to make a perfect include file that can
+! be used by both F77 and F90 compilers, but this is close.  We have removed
+! continuation lines (allows free form input in F90); systems whose
+! Fortran compilers support ! instead of just C or * for comments can
+! globally replace a C in the first column with !; the resulting file
+! should work for both Fortran 77 and Fortran 90.
+!
+! If your Fortran compiler supports ! for comments, you can run this 
+! through sed with
+!     sed -e 's/^C/\!/g'
+!
+! We have also removed the use of contractions (involving the single quote)
+! character because some users use .F instead of .f files (to invoke the
+! cpp preprocessor) and further, their preprocessor is determined to find
+! matching single quote pairs (and probably double quotes; given the
+! different rules in C and Fortran, this sounds like a disaster).  Rather than
+! take the position that the poor users should get a better system, we
+! have removed the text that caused problems.  Of course, the users SHOULD
+! get a better system...
+!
+! return codes 
+      INTEGER MPI_SUCCESS,MPI_ERR_BUFFER,MPI_ERR_COUNT,MPI_ERR_TYPE
+      INTEGER MPI_ERR_TAG,MPI_ERR_COMM,MPI_ERR_RANK,MPI_ERR_ROOT
+      INTEGER MPI_ERR_GROUP
+      INTEGER MPI_ERR_OP,MPI_ERR_TOPOLOGY,MPI_ERR_DIMS,MPI_ERR_ARG
+      INTEGER MPI_ERR_UNKNOWN,MPI_ERR_TRUNCATE,MPI_ERR_OTHER
+      INTEGER MPI_ERR_INTERN,MPI_ERR_IN_STATUS,MPI_ERR_PENDING
+      INTEGER MPI_ERR_REQUEST, MPI_ERR_LASTCODE
+      PARAMETER (MPI_SUCCESS=0,MPI_ERR_BUFFER=1,MPI_ERR_COUNT=2)
+      PARAMETER (MPI_ERR_TYPE=3,MPI_ERR_TAG=4,MPI_ERR_COMM=5)
+      PARAMETER (MPI_ERR_RANK=6,MPI_ERR_ROOT=7,MPI_ERR_GROUP=8)
+      PARAMETER (MPI_ERR_OP=9,MPI_ERR_TOPOLOGY=10,MPI_ERR_DIMS=11)
+      PARAMETER (MPI_ERR_ARG=12,MPI_ERR_UNKNOWN=13)
+      PARAMETER (MPI_ERR_TRUNCATE=14,MPI_ERR_OTHER=15)
+      PARAMETER (MPI_ERR_INTERN=16,MPI_ERR_IN_STATUS=17)
+      PARAMETER (MPI_ERR_PENDING=18,MPI_ERR_REQUEST=19)
+      PARAMETER (MPI_ERR_LASTCODE=1073741823)
+!
+      INTEGER MPI_UNDEFINED
+      parameter (MPI_UNDEFINED = (-32766))
+!
+      INTEGER MPI_GRAPH, MPI_CART
+      PARAMETER (MPI_GRAPH = 1, MPI_CART = 2)
+      INTEGER  MPI_PROC_NULL
+      PARAMETER ( MPI_PROC_NULL = (-1) )
+!
+      INTEGER MPI_BSEND_OVERHEAD
+      PARAMETER ( MPI_BSEND_OVERHEAD = 512 )
+
+      INTEGER MPI_SOURCE, MPI_TAG, MPI_ERROR
+      PARAMETER(MPI_SOURCE=2, MPI_TAG=3, MPI_ERROR=4)
+      INTEGER MPI_STATUS_SIZE
+      PARAMETER (MPI_STATUS_SIZE=4)
+      INTEGER MPI_MAX_PROCESSOR_NAME, MPI_MAX_ERROR_STRING
+      PARAMETER (MPI_MAX_PROCESSOR_NAME=256)
+      PARAMETER (MPI_MAX_ERROR_STRING=512)
+      INTEGER MPI_MAX_NAME_STRING
+      PARAMETER (MPI_MAX_NAME_STRING=63)
+!
+      INTEGER MPI_COMM_NULL
+      PARAMETER (MPI_COMM_NULL=0)
+!
+      INTEGER MPI_DATATYPE_NULL
+      PARAMETER (MPI_DATATYPE_NULL = 0)
+      
+      INTEGER MPI_ERRHANDLER_NULL
+      PARAMETER (MPI_ERRHANDLER_NULL = 0)
+      
+      INTEGER MPI_GROUP_NULL
+      PARAMETER (MPI_GROUP_NULL = 0)
+      
+      INTEGER MPI_KEYVAL_INVALID
+      PARAMETER (MPI_KEYVAL_INVALID = 0)
+      
+      INTEGER MPI_REQUEST_NULL
+      PARAMETER (MPI_REQUEST_NULL = 0)
+! 
+      INTEGER MPI_IDENT, MPI_CONGRUENT, MPI_SIMILAR, MPI_UNEQUAL
+      PARAMETER (MPI_IDENT=0, MPI_CONGRUENT=1, MPI_SIMILAR=2)
+      PARAMETER (MPI_UNEQUAL=3)
+!
+!     MPI_BOTTOM needs to be a known address; here we put it at the
+!     beginning of the common block.  The point-to-point and collective
+!     routines know about MPI_BOTTOM, but MPI_TYPE_STRUCT as yet does not.
+!
+!     MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects
+!     Until the underlying MPI library implements the C version of these
+!     (a null pointer), these are declared as arrays of MPI_STATUS_SIZE
+!
+!     The types MPI_INTEGER1,2,4 and MPI_REAL4,8 are OPTIONAL.
+!     Their values are zero if they are not available.  Note that
+!     using these reduces the portability of code (though may enhance
+!     portability between Crays and other systems)
+!
+      INTEGER MPI_TAG_UB, MPI_HOST, MPI_IO
+      INTEGER MPI_BOTTOM
+      INTEGER MPI_STATUS_IGNORE(MPI_STATUS_SIZE)
+      INTEGER MPI_STATUSES_IGNORE(MPI_STATUS_SIZE)
+      INTEGER MPI_INTEGER, MPI_REAL, MPI_DOUBLE_PRECISION 
+      INTEGER MPI_COMPLEX, MPI_DOUBLE_COMPLEX,MPI_LOGICAL
+      INTEGER MPI_CHARACTER, MPI_BYTE, MPI_2INTEGER, MPI_2REAL
+      INTEGER MPI_2DOUBLE_PRECISION, MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
+      INTEGER MPI_UB, MPI_LB
+      INTEGER MPI_PACKED, MPI_WTIME_IS_GLOBAL
+      INTEGER MPI_COMM_WORLD, MPI_COMM_SELF, MPI_GROUP_EMPTY
+      INTEGER MPI_SUM, MPI_MAX, MPI_MIN, MPI_PROD, MPI_LAND, MPI_BAND
+      INTEGER MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR, MPI_MINLOC
+      INTEGER MPI_MAXLOC
+      INTEGER MPI_OP_NULL
+      INTEGER MPI_ERRORS_ARE_FATAL, MPI_ERRORS_RETURN
+      INTEGER MPI_THREAD_SINGLE, MPI_THREAD_FUNNELED, MPI_THREAD_SERIALIZED
+      INTEGER MPI_THREAD_MULTIPLE
+      INTEGER MPI_MODE_RDONLY, MPI_MODE_WRONLY, MPI_MODE_CREATE
+
+!
+      PARAMETER (MPI_ERRORS_ARE_FATAL=119)
+      PARAMETER (MPI_ERRORS_RETURN=120)
+!
+      PARAMETER (MPI_COMPLEX=23,MPI_DOUBLE_COMPLEX=24,MPI_LOGICAL=25)
+      PARAMETER (MPI_REAL=26,MPI_DOUBLE_PRECISION=27,MPI_INTEGER=28)
+      PARAMETER (MPI_2INTEGER=29,MPI_2COMPLEX=30,MPI_2DOUBLE_COMPLEX=31)
+      PARAMETER (MPI_2REAL=32,MPI_2DOUBLE_PRECISION=33,MPI_CHARACTER=1)
+      PARAMETER (MPI_BYTE=3,MPI_UB=16,MPI_LB=15,MPI_PACKED=14)
+
+      INTEGER MPI_ORDER_C, MPI_ORDER_FORTRAN 
+      PARAMETER (MPI_ORDER_C=56, MPI_ORDER_FORTRAN=57)
+      INTEGER MPI_DISTRIBUTE_BLOCK, MPI_DISTRIBUTE_CYCLIC
+      INTEGER MPI_DISTRIBUTE_NONE, MPI_DISTRIBUTE_DFLT_DARG
+      PARAMETER (MPI_DISTRIBUTE_BLOCK=121, MPI_DISTRIBUTE_CYCLIC=122)
+      PARAMETER (MPI_DISTRIBUTE_NONE=123)
+      PARAMETER (MPI_DISTRIBUTE_DFLT_DARG=-49767)
+      INTEGER MPI_MAX_INFO_KEY, MPI_MAX_INFO_VAL
+      PARAMETER (MPI_MAX_INFO_KEY=255, MPI_MAX_INFO_VAL=1024)
+      INTEGER MPI_INFO_NULL
+      PARAMETER (MPI_INFO_NULL=0)
+
+!
+! Optional Fortran Types.  Configure attempts to determine these.  
+!
+      INTEGER MPI_INTEGER1, MPI_INTEGER2, MPI_INTEGER4, MPI_INTEGER8
+      INTEGER MPI_INTEGER16
+      INTEGER MPI_REAL4, MPI_REAL8, MPI_REAL16
+      INTEGER MPI_COMPLEX8, MPI_COMPLEX16, MPI_COMPLEX32
+      PARAMETER (MPI_INTEGER1=1,MPI_INTEGER2=4)
+      PARAMETER (MPI_INTEGER4=6)
+      PARAMETER (MPI_INTEGER8=13)
+      PARAMETER (MPI_INTEGER16=0)
+      PARAMETER (MPI_REAL4=10)
+      PARAMETER (MPI_REAL8=11)
+      PARAMETER (MPI_REAL16=0)
+      PARAMETER (MPI_COMPLEX8=23)
+      PARAMETER (MPI_COMPLEX16=24)
+      PARAMETER (MPI_COMPLEX32=0)
+!
+!    This is now handled with either the "pointer" extension or this same
+!    code, appended at the end.
+!      COMMON /MPIPRIV/ MPI_BOTTOM,MPI_STATUS_IGNORE,MPI_STATUSES_IGNORE
+!C
+!C     Without this save, some Fortran implementations may make the common
+!C     dynamic!
+!C    
+!C     For a Fortran90 module, we might replace /MPIPRIV/ with a simple
+!C     SAVE MPI_BOTTOM
+!C
+!      SAVE /MPIPRIV/
+!
+      PARAMETER (MPI_MAX=100,MPI_MIN=101,MPI_SUM=102,MPI_PROD=103)
+      PARAMETER (MPI_LAND=104,MPI_BAND=105,MPI_LOR=106,MPI_BOR=107)
+      PARAMETER (MPI_LXOR=108,MPI_BXOR=109,MPI_MINLOC=110)
+      PARAMETER (MPI_MAXLOC=111, MPI_OP_NULL=0)
+!
+      PARAMETER (MPI_GROUP_EMPTY=90,MPI_COMM_WORLD=91,MPI_COMM_SELF=92)
+      PARAMETER (MPI_TAG_UB=80,MPI_HOST=82,MPI_IO=84)
+      PARAMETER (MPI_WTIME_IS_GLOBAL=86)
+!
+      INTEGER MPI_ANY_SOURCE
+      PARAMETER (MPI_ANY_SOURCE = (-2))
+      INTEGER MPI_ANY_TAG
+      PARAMETER (MPI_ANY_TAG = (-1))
+!
+      INTEGER MPI_VERSION, MPI_SUBVERSION
+      PARAMETER (MPI_VERSION    = 1, MPI_SUBVERSION = 2)
+!
+!     There are additional MPI-2 constants 
+      INTEGER MPI_ADDRESS_KIND, MPI_OFFSET_KIND
+      PARAMETER (MPI_ADDRESS_KIND=4)
+      PARAMETER (MPI_OFFSET_KIND=8)
+!
+!     All other MPI routines are subroutines
+!     This may cause some Fortran compilers to complain about defined and
+!     not used.  Such compilers should be improved.
+!
+!     Some Fortran compilers will not link programs that contain
+!     external statements to routines that are not provided, even if
+!     the routine is never called.  Remove PMPI_WTIME and PMPI_WTICK
+!     if you have trouble with them.
+!
+      DOUBLE PRECISION MPI_WTIME, MPI_WTICK,PMPI_WTIME,PMPI_WTICK
+      EXTERNAL MPI_WTIME, MPI_WTICK,PMPI_WTIME,PMPI_WTICK
+!
+!     The attribute copy/delete subroutines are symbols that can be passed
+!     to MPI routines
+!
+      EXTERNAL MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, MPI_DUP_FN
+      COMMON /MPIPRIV/ MPI_BOTTOM,MPI_STATUS_IGNORE,MPI_STATUSES_IGNORE
+!
+!     Without this save, some Fortran implementations may make the common
+!     dynamic!
+!    
+!     For a Fortran90 module, we might replace /MPIPRIV/ with a simple
+!     SAVE MPI_BOTTOM
+!
+      SAVE /MPIPRIV/
diff --git a/odb/src/extras/mpi_serial/mpif.h.necsx.BoM b/odb/src/extras/mpi_serial/mpif.h.necsx.BoM
new file mode 100644
index 0000000..d734423
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpif.h.necsx.BoM
@@ -0,0 +1,511 @@
+!
+!         COPYRIGHT
+!  
+! The following is a notice of limited availability of the code, and
+! disclaimer which must be included in the prologue of the code and in
+! all source listings of the code.
+! 
+! Copyright Notice
+!  + 1997/2003 NEC Corporation
+!  + 1993/1997 University of Chicago
+!  + 1993 Mississippi State University
+! 
+! The underlying software called "MPICH" was originally authored by:
+! 
+! Argonne National Laboratory Group
+! W. Gropp:  (708) 252-4318; FAX: (708) 252-7852; e-mail: gropp at mcs.anl.gov
+! E. Lusk:   (708) 252-7852; FAX: (708) 252-7852; e-mail: lusk at mcs.anl.gov
+! R. Thakur: (630) 252-1682; FAX: (630) 252-5986; e-mail: thakur at mcs.anl.gov
+! Mathematics and Computer Science Division
+! Argonne National Laboratory, Argonne IL 60439
+! 
+! Mississippi State Group
+! N. Doss:  (601) 325-2565; FAX: (601) 325-7692;
+!           e-mail: doss at erc.msstate.edu
+! A. Skjellum:(601) 325-8435; FAX: (601) 325-8997;
+!           e-mail: tony at erc.msstate.edu
+! Mississippi State University, Computer Science Department &
+! NSF Engineering Research Center for Computational Field Simulation,
+! P.O. Box 6176, Mississippi State MS 39762
+! 
+! This software is MPICH, with modifications by NEC Corporation's CCRLE 
+! laboratory:
+! CCRLE, NEC Europe Ltd., Rathausallee 10, 53757 Sankt Augustin, Germany.
+! The use of the modifications included in this software is governed by
+! the license agreement between the customer and NEC Corporation. In
+! particular, the distribution to others or use for the preparation of
+! derivative works incorporating NEC's modifications to the software
+! is prohibited unless prior written approval from NEC Corporation is
+! obtained.
+! 
+! 
+!       DISCLAIMER
+! 
+! This computer code material was prepared, in part, as an account of work
+! sponsored by an agency of the United States Government. Neither the
+! United States, nor the University of Chicago, nor Mississippi State
+! University, nor any of their employees, makes any warranty express or
+! implied, or assumes any legal liability or responsibility for the
+! accuracy, completeness, or usefulness of any information, apparatus,
+! product, or process disclosed, or represents that its use would not
+! infringe privately owned rights.
+!      
+! 
+!      AVAILABILITY OF MPICH
+!      
+! MPICH is available from Argonne National Laboratory and Mississippi
+! State under a royalty-free license to use, reproduce, prepare
+! derivative works, and to redistribute to others. MPICH was prepared, in
+! part, as an account of work under a U.S. Government Contract and is
+! subject to the following license: the Government is granted for itself
+! and others acting on its behalf a paid-up, nonexclusive, irrevocable
+! worldwide license in this computer software to reproduce, prepare
+! derivative works, and perform publicly and display publicly. 
+!
+! user include file for MPI programs, with no dependencies.
+!
+!     Return codes 
+!
+      INTEGER(kind=8) MPI_SUCCESS,MPI_ERR_BUFFER,MPI_ERR_COUNT,MPI_ERR_TYPE
+      INTEGER(kind=8) MPI_ERR_TAG,MPI_ERR_COMM,MPI_ERR_RANK,MPI_ERR_ROOT
+      INTEGER(kind=8) MPI_ERR_GROUP
+      INTEGER(kind=8) MPI_ERR_OP,MPI_ERR_TOPOLOGY,MPI_ERR_DIMS,MPI_ERR_ARG
+      INTEGER(kind=8) MPI_ERR_UNKNOWN,MPI_ERR_TRUNCATE,MPI_ERR_OTHER
+      INTEGER(kind=8) MPI_ERR_INTERN,MPI_ERR_IN_STATUS,MPI_ERR_PENDING
+      INTEGER(kind=8) MPI_ERR_REQUEST, MPI_ERR_LASTCODE
+!
+      INTEGER(kind=8) MPI_ERR_IO, MPI_ERR_ACCESS, MPI_ERR_AMODE, MPI_ERR_ASSERT
+      INTEGER(kind=8) MPI_ERR_BAD_FILE, MPI_ERR_BASE, MPI_ERR_CONVERSION
+      INTEGER(kind=8) MPI_ERR_DISP, MPI_ERR_DUP_DATAREP, MPI_ERR_FILE_EXISTS
+      INTEGER(kind=8) MPI_ERR_FILE_IN_USE, MPI_ERR_FILE, MPI_ERR_INFO_KEY
+      INTEGER(kind=8) MPI_ERR_INFO_NOKEY, MPI_ERR_INFO_VALUE, MPI_ERR_INFO
+      INTEGER(kind=8) MPI_ERR_KEYVAL, MPI_ERR_LOCKTYPE, MPI_ERR_NAME
+      INTEGER(kind=8) MPI_ERR_NO_MEM, MPI_ERR_NOT_SAME, MPI_ERR_NO_SPACE
+      INTEGER(kind=8) MPI_ERR_NO_SUCH_FILE, MPI_ERR_PORT, MPI_ERR_QUOTA
+      INTEGER(kind=8) MPI_ERR_READ_ONLY, MPI_ERR_RMA_CONFLICT, MPI_ERR_RMA_SYNC
+      INTEGER(kind=8) MPI_ERR_SERVICE, MPI_ERR_SIZE, MPI_ERR_SPAWN
+      INTEGER(kind=8) MPI_ERR_UNSUPPORTED_DATAREP, MPI_ERR_UNSUPPORTED_OPERATION
+      INTEGER(kind=8) MPI_ERR_WIN
+!
+      PARAMETER (MPI_SUCCESS = 0)
+      PARAMETER (MPI_ERR_BUFFER = 1)
+      PARAMETER (MPI_ERR_COUNT = 2)
+      PARAMETER (MPI_ERR_TYPE = 3)
+      PARAMETER (MPI_ERR_TAG = 4)
+      PARAMETER (MPI_ERR_COMM = 5)
+      PARAMETER (MPI_ERR_RANK = 6)
+      PARAMETER (MPI_ERR_ROOT = 7)
+      PARAMETER (MPI_ERR_GROUP = 8)
+      PARAMETER (MPI_ERR_OP = 9)
+      PARAMETER (MPI_ERR_TOPOLOGY = 10)
+      PARAMETER (MPI_ERR_DIMS = 11)
+      PARAMETER (MPI_ERR_ARG = 12)
+      PARAMETER (MPI_ERR_UNKNOWN = 13)
+      PARAMETER (MPI_ERR_TRUNCATE = 14)
+      PARAMETER (MPI_ERR_OTHER = 15)
+      PARAMETER (MPI_ERR_INTERN = 16)
+      PARAMETER (MPI_ERR_IN_STATUS = 17)
+      PARAMETER (MPI_ERR_PENDING = 18)
+      PARAMETER (MPI_ERR_REQUEST = 19)
+!
+      PARAMETER (MPI_ERR_IO = 20)
+      PARAMETER (MPI_ERR_ACCESS = 21)
+      PARAMETER (MPI_ERR_AMODE = 22)
+      PARAMETER (MPI_ERR_ASSERT = 23)
+      PARAMETER (MPI_ERR_BAD_FILE = 24)
+      PARAMETER (MPI_ERR_BASE = 25)
+      PARAMETER (MPI_ERR_CONVERSION = 26)
+      PARAMETER (MPI_ERR_DISP = 27)
+      PARAMETER (MPI_ERR_DUP_DATAREP = 28)
+      PARAMETER (MPI_ERR_FILE_EXISTS = 29)
+      PARAMETER (MPI_ERR_FILE_IN_USE = 30)
+      PARAMETER (MPI_ERR_FILE = 31)
+      PARAMETER (MPI_ERR_INFO_KEY = 32)
+      PARAMETER (MPI_ERR_INFO_NOKEY = 33)
+      PARAMETER (MPI_ERR_INFO_VALUE = 34)
+      PARAMETER (MPI_ERR_INFO = 35)
+      PARAMETER (MPI_ERR_KEYVAL = 36)
+      PARAMETER (MPI_ERR_LOCKTYPE = 37)
+      PARAMETER (MPI_ERR_NAME = 38)
+      PARAMETER (MPI_ERR_NO_MEM = 39)
+      PARAMETER (MPI_ERR_NOT_SAME = 40)
+      PARAMETER (MPI_ERR_NO_SPACE = 41)
+      PARAMETER (MPI_ERR_NO_SUCH_FILE = 42)
+      PARAMETER (MPI_ERR_PORT = 43)
+      PARAMETER (MPI_ERR_QUOTA = 44)
+      PARAMETER (MPI_ERR_READ_ONLY = 45)
+      PARAMETER (MPI_ERR_RMA_CONFLICT = 46)
+      PARAMETER (MPI_ERR_RMA_SYNC = 47)
+      PARAMETER (MPI_ERR_SERVICE = 48)
+      PARAMETER (MPI_ERR_SIZE = 49)
+      PARAMETER (MPI_ERR_SPAWN = 50)
+      PARAMETER (MPI_ERR_UNSUPPORTED_DATAREP = 51)
+      PARAMETER (MPI_ERR_UNSUPPORTED_OPERATION = 52)
+      PARAMETER (MPI_ERR_WIN = 53)
+!
+      PARAMETER (MPI_ERR_LASTCODE = 4114)
+!
+      INTEGER(kind=8) MPI_ERRORS_ARE_FATAL, MPI_ERRORS_RETURN
+!
+      PARAMETER (MPI_ERRORS_ARE_FATAL = 119)
+      PARAMETER (MPI_ERRORS_RETURN    = 120)
+!
+!     Parameters
+!
+      INTEGER(kind=8) MPI_UNDEFINED, MPI_KEYVAL_INVALID, MPI_BSEND_OVERHEAD
+!
+      PARAMETER (MPI_UNDEFINED      = (-32766))
+      PARAMETER (MPI_KEYVAL_INVALID = 0)
+      PARAMETER (MPI_BSEND_OVERHEAD = 512)
+!
+      INTEGER(kind=8) MPI_GRAPH, MPI_CART
+      PARAMETER (MPI_GRAPH = 1)
+      PARAMETER (MPI_CART  = 2)
+!
+      INTEGER(kind=8) MPI_SOURCE, MPI_TAG, MPI_ERROR, MPI_STATUS_SIZE
+      PARAMETER (MPI_ERROR       = 1)
+      PARAMETER (MPI_SOURCE      = 2)
+      PARAMETER (MPI_TAG         = 3)
+      PARAMETER (MPI_STATUS_SIZE = 6)
+!
+      INTEGER(kind=8) MPI_MAX_PROCESSOR_NAME, MPI_MAX_ERROR_STRING
+      INTEGER(kind=8) MPI_MAX_NAME_STRING, MPI_MAX_INFO_KEY, MPI_MAX_INFO_VAL
+      INTEGER(kind=8) MPI_MAX_DATAREP_STRING, MPI_MAX_OBJECT_NAME
+      INTEGER(kind=8) MPI_MAX_PORT_NAME
+!
+      PARAMETER (MPI_MAX_DATAREP_STRING = 128)
+      PARAMETER (MPI_MAX_ERROR_STRING   = 512)
+      PARAMETER (MPI_MAX_INFO_KEY       = 255)
+      PARAMETER (MPI_MAX_INFO_VAL       = 1024)
+      PARAMETER (MPI_MAX_NAME_STRING    = 63)
+      PARAMETER (MPI_MAX_PROCESSOR_NAME = 256)
+      PARAMETER (MPI_MAX_OBJECT_NAME    = MPI_MAX_NAME_STRING)
+      PARAMETER (MPI_MAX_PORT_NAME      = MPI_MAX_NAME_STRING)
+!
+!     Null objects
+!
+      INTEGER(kind=8) MPI_COMM_NULL,  MPI_DATATYPE_NULL, MPI_ERRHANDLER_NULL
+      INTEGER(kind=8) MPI_GROUP_NULL, MPI_REQUEST_NULL,  MPI_PROC_NULL
+      INTEGER(kind=8) MPI_OP_NULL,    MPI_INFO_NULL,     MPI_FILE_NULL
+      INTEGER(kind=8) MPI_WIN_NULL
+!
+      PARAMETER (MPI_COMM_NULL       = 0)
+      PARAMETER (MPI_DATATYPE_NULL   = 0)
+      PARAMETER (MPI_ERRHANDLER_NULL = 0)
+      PARAMETER (MPI_FILE_NULL       = 0)
+      PARAMETER (MPI_GROUP_NULL      = 0)
+      PARAMETER (MPI_INFO_NULL       = 0)
+      PARAMETER (MPI_OP_NULL         = 0)
+      PARAMETER (MPI_REQUEST_NULL    = 0)
+      PARAMETER (MPI_WIN_NULL        = 0)
+      PARAMETER (MPI_PROC_NULL       = (-1))
+! 
+!     Results of the compare operations
+! 
+      INTEGER(kind=8) MPI_IDENT, MPI_CONGRUENT, MPI_SIMILAR, MPI_UNEQUAL
+      PARAMETER (MPI_IDENT     = 0)
+      PARAMETER (MPI_CONGRUENT = 1)
+      PARAMETER (MPI_SIMILAR   = 2)
+      PARAMETER (MPI_UNEQUAL   = 3)
+!
+!     The types MPI_INTEGER1,2,4 and MPI_REAL4,8 are OPTIONAL.
+!     Their values are zero if they are not available.  Note that
+!     using these reduces the portability of code.
+!
+      INTEGER(kind=8) MPI_INTEGER, MPI_REAL, MPI_DOUBLE_PRECISION 
+      INTEGER(kind=8) MPI_COMPLEX, MPI_DOUBLE_COMPLEX, MPI_LOGICAL
+      INTEGER(kind=8) MPI_CHARACTER, MPI_BYTE, MPI_2INTEGER, MPI_2REAL
+      INTEGER(kind=8) MPI_2DOUBLE_PRECISION, MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
+      INTEGER(kind=8) MPI_UB, MPI_LB, MPI_PACKED
+      INTEGER(kind=8) MPI_TYPECLASS_INTEGER, MPI_TYPECLASS_REAL
+      INTEGER(kind=8) MPI_TYPECLASS_COMPLEX, MPI_TYPECLASS_LOGICAL
+!
+      PARAMETER (MPI_CHARACTER = 1)
+      PARAMETER (MPI_BYTE      = 3)
+      PARAMETER (MPI_PACKED    = 14)
+      PARAMETER (MPI_LB        = 15)
+      PARAMETER (MPI_UB        = 16)
+      PARAMETER (MPI_COMPLEX   = 23)
+      PARAMETER (MPI_DOUBLE_COMPLEX = 24)
+      PARAMETER (MPI_LOGICAL   = 25)
+      PARAMETER (MPI_REAL      = 26)
+      PARAMETER (MPI_DOUBLE_PRECISION = 27)
+      PARAMETER (MPI_INTEGER   = 28)
+      PARAMETER (MPI_2INTEGER  = 29)
+      PARAMETER (MPI_2COMPLEX  = 30)
+      PARAMETER (MPI_2DOUBLE_COMPLEX = 31)
+      PARAMETER (MPI_2REAL     = 32)
+      PARAMETER (MPI_2DOUBLE_PRECISION = 33)
+!
+      PARAMETER (MPI_TYPECLASS_INTEGER = -1)
+      PARAMETER (MPI_TYPECLASS_REAL    = -2)
+      PARAMETER (MPI_TYPECLASS_COMPLEX = -3)
+      PARAMETER (MPI_TYPECLASS_LOGICAL = -4)
+!
+!     FORTRAN Extensions for NEC SX
+!
+!  MPI_AINT   corresponds to the datatype of
+!                         an INTEGER (KIND=MPI_ADDRESS_KIND) variable
+!  MPI_OFFSET corresponds to the datatype of
+!                         an INTEGER (KIND=MPI_OFFSET_KIND) variable
+!
+      INTEGER(kind=8) MPI_INTEGER1, MPI_INTEGER2, MPI_INTEGER4, MPI_INTEGER8
+      INTEGER(kind=8) MPI_INTEGER16
+      INTEGER(kind=8) MPI_LOGICAL1, MPI_LOGICAL4, MPI_LOGICAL8
+      INTEGER(kind=8) MPI_REAL4, MPI_REAL8, MPI_REAL16
+      INTEGER(kind=8) MPI_COMPLEX8, MPI_COMPLEX16, MPI_COMPLEX32
+      INTEGER(kind=8) MPI_2REAL4, MPI_2REAL8, MPI_2COMPLEX8, MPI_2COMPLEX16
+      INTEGER(kind=8) MPI_QUADRUPLE_PRECISION, MPI_QUADRUPLE_COMPLEX
+      INTEGER(kind=8) MPI_OFFSET, MPI_AINT
+!
+      PARAMETER (MPI_INTEGER1 = MPI_DATATYPE_NULL)
+      PARAMETER (MPI_INTEGER2 = 50)
+      PARAMETER (MPI_INTEGER8 = 51)
+      PARAMETER (MPI_INTEGER16 = MPI_DATATYPE_NULL)
+      PARAMETER (MPI_LOGICAL1 = 52)
+      PARAMETER (MPI_LOGICAL8 = 53)
+      PARAMETER (MPI_QUADRUPLE_PRECISION = 54)
+      PARAMETER (MPI_QUADRUPLE_COMPLEX = 55)
+!
+      PARAMETER (MPI_INTEGER4 = MPI_INTEGER)
+      PARAMETER (MPI_LOGICAL4 = MPI_LOGICAL)
+      PARAMETER (MPI_REAL4  = MPI_REAL)
+      PARAMETER (MPI_REAL8  = MPI_DOUBLE_PRECISION)
+      PARAMETER (MPI_REAL16 = MPI_QUADRUPLE_PRECISION)
+      PARAMETER (MPI_COMPLEX8  = MPI_COMPLEX)
+      PARAMETER (MPI_COMPLEX16 = MPI_DOUBLE_COMPLEX)
+      PARAMETER (MPI_COMPLEX32 = MPI_QUADRUPLE_COMPLEX)
+!
+      PARAMETER (MPI_2REAL4 = MPI_2REAL)
+      PARAMETER (MPI_2REAL8 = MPI_2DOUBLE_PRECISION)
+      PARAMETER (MPI_2COMPLEX8  = MPI_2COMPLEX)
+      PARAMETER (MPI_2COMPLEX16 = MPI_2DOUBLE_COMPLEX)
+!
+      PARAMETER (MPI_AINT    = MPI_INTEGER8)
+      PARAMETER (MPI_OFFSET  = MPI_INTEGER8)
+!
+!     Combiner
+!
+      INTEGER(kind=8) MPI_COMBINER_NAMED,   MPI_COMBINER_CONTIGUOUS
+      INTEGER(kind=8) MPI_COMBINER_VECTOR,  MPI_COMBINER_HVECTOR
+      INTEGER(kind=8) MPI_COMBINER_INDEXED, MPI_COMBINER_HINDEXED
+      INTEGER(kind=8) MPI_COMBINER_STRUCT,  MPI_COMBINER_DUP
+      INTEGER(kind=8) MPI_COMBINER_INDEXED_BLOCK, MPI_COMBINER_HVECTOR_INTEGER
+      INTEGER(kind=8) MPI_COMBINER_HINDEXED_INTEGER, MPI_COMBINER_STRUCT_INTEGER
+      INTEGER(kind=8) MPI_COMBINER_DARRAY,  MPI_COMBINER_SUBARRAY
+      INTEGER(kind=8) MPI_COMBINER_RESIZED, MPI_COMBINER_F90_REAL
+      INTEGER(kind=8) MPI_COMBINER_F90_COMPLEX, MPI_COMBINER_F90_INTEGER
+!
+      PARAMETER (MPI_COMBINER_NAMED            = 2312)
+      PARAMETER (MPI_COMBINER_CONTIGUOUS       = 2313)
+      PARAMETER (MPI_COMBINER_VECTOR           = 2314)
+      PARAMETER (MPI_COMBINER_HVECTOR          = 2315)
+      PARAMETER (MPI_COMBINER_INDEXED          = 2316)
+      PARAMETER (MPI_COMBINER_HINDEXED         = 2317)
+      PARAMETER (MPI_COMBINER_STRUCT           = 2318)
+      PARAMETER (MPI_COMBINER_DUP              = 2319)
+      PARAMETER (MPI_COMBINER_INDEXED_BLOCK    = 2320)
+      PARAMETER (MPI_COMBINER_HVECTOR_INTEGER  = 2321)
+      PARAMETER (MPI_COMBINER_HINDEXED_INTEGER = 2322)
+      PARAMETER (MPI_COMBINER_STRUCT_INTEGER   = 2323)
+      PARAMETER (MPI_COMBINER_DARRAY           = 2324)
+      PARAMETER (MPI_COMBINER_SUBARRAY         = 2325)
+      PARAMETER (MPI_COMBINER_RESIZED          = 2326)
+      PARAMETER (MPI_COMBINER_F90_REAL         = 2327)
+      PARAMETER (MPI_COMBINER_F90_COMPLEX      = 2328)
+      PARAMETER (MPI_COMBINER_F90_INTEGER      = 2329)
+!
+!     For subarray and darray constructors
+!
+      INTEGER(kind=8) MPI_ORDER_C, MPI_ORDER_FORTRAN 
+      PARAMETER (MPI_ORDER_C       = 56)
+      PARAMETER (MPI_ORDER_FORTRAN = 57)
+!
+      INTEGER(kind=8) MPI_DISTRIBUTE_BLOCK, MPI_DISTRIBUTE_CYCLIC
+      INTEGER(kind=8) MPI_DISTRIBUTE_NONE, MPI_DISTRIBUTE_DFLT_DARG
+      PARAMETER (MPI_DISTRIBUTE_BLOCK  = 121)
+      PARAMETER (MPI_DISTRIBUTE_CYCLIC = 122)
+      PARAMETER (MPI_DISTRIBUTE_NONE   = 123)
+      PARAMETER (MPI_DISTRIBUTE_DFLT_DARG = -49767)
+!
+!     Collective operations
+!
+      INTEGER(kind=8) MPI_SUM, MPI_MAX, MPI_MIN,  MPI_PROD, MPI_LAND, MPI_BAND
+      INTEGER(kind=8) MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR, MPI_MINLOC
+      INTEGER(kind=8) MPI_MAXLOC, MPI_REPLACE
+!
+      PARAMETER (MPI_MAX    = 100)
+      PARAMETER (MPI_MIN    = 101)
+      PARAMETER (MPI_SUM    = 102)
+      PARAMETER (MPI_PROD   = 103)
+      PARAMETER (MPI_LAND   = 104)
+      PARAMETER (MPI_BAND   = 105)
+      PARAMETER (MPI_LOR    = 106)
+      PARAMETER (MPI_BOR    = 107)
+      PARAMETER (MPI_LXOR   = 108)
+      PARAMETER (MPI_BXOR   = 109)
+      PARAMETER (MPI_MINLOC = 110)
+      PARAMETER (MPI_MAXLOC = 111)
+      PARAMETER (MPI_REPLACE= 112)
+!
+!     Communicator
+!
+      INTEGER(kind=8) MPI_COMM_WORLD, MPI_COMM_SELF, MPI_GROUP_EMPTY
+      INTEGER(kind=8) MPI_TAG_UB, MPI_HOST, MPI_IO, MPI_WTIME_IS_GLOBAL
+      INTEGER(kind=8) MPI_UNIVERSE_SIZE, MPI_APPNUM
+      INTEGER(kind=8) MPI_LASTUSEDCODE
+      INTEGER(kind=8) MPI_APPL_GROUP, MPI_MAX_APPL_GROUP
+      INTEGER(kind=8) MPI_COMM_SPECIAL_BARRIER, MPI_WIN_SPECIAL_BARRIER
+!
+      PARAMETER (MPI_GROUP_EMPTY = 90)
+      PARAMETER (MPI_COMM_WORLD  = 91)
+      PARAMETER (MPI_COMM_SELF   = 92)
+!
+!     Attributes
+!
+      PARAMETER (MPI_TAG_UB = 80)
+      PARAMETER (MPI_HOST   = 82)
+      PARAMETER (MPI_IO     = 84)
+      PARAMETER (MPI_WTIME_IS_GLOBAL = 86)
+      PARAMETER (MPI_UNIVERSE_SIZE   = 88)
+      PARAMETER (MPI_APPNUM          = 78)
+      PARAMETER (MPI_LASTUSEDCODE = 150)
+!
+      PARAMETER (MPI_APPL_GROUP     = 146)
+      PARAMETER (MPI_MAX_APPL_GROUP = 148)
+!
+      PARAMETER (MPI_COMM_SPECIAL_BARRIER = 142)
+      PARAMETER (MPI_WIN_SPECIAL_BARRIER  = 144)
+!
+      INTEGER(kind=8) MPI_ANY_TAG, MPI_ANY_SOURCE, MPI_ROOT
+      PARAMETER (MPI_ANY_TAG    = (-1))
+      PARAMETER (MPI_ANY_SOURCE = (-2))
+      PARAMETER (MPI_ROOT       = (-3))
+!
+      INTEGER(kind=8) MPI_VERSION, MPI_SUBVERSION
+      PARAMETER (MPI_VERSION    = 2)
+      PARAMETER (MPI_SUBVERSION = 0)
+!
+!     Fortran MPI-IO
+!
+      INTEGER(kind=8) MPI_MODE_RDONLY, MPI_MODE_RDWR, MPI_MODE_WRONLY
+      INTEGER(kind=8) MPI_MODE_DELETE_ON_CLOSE, MPI_MODE_UNIQUE_OPEN
+      INTEGER(kind=8) MPI_MODE_CREATE, MPI_MODE_EXCL
+      INTEGER(kind=8) MPI_MODE_APPEND, MPI_MODE_SEQUENTIAL
+      PARAMETER (MPI_MODE_RDONLY = 2)
+      PARAMETER (MPI_MODE_RDWR   = 8)
+      PARAMETER (MPI_MODE_WRONLY = 4)
+      PARAMETER (MPI_MODE_CREATE = 1)
+      PARAMETER (MPI_MODE_DELETE_ON_CLOSE = 16)
+      PARAMETER (MPI_MODE_UNIQUE_OPEN = 32)
+      PARAMETER (MPI_MODE_EXCL = 64)
+      PARAMETER (MPI_MODE_APPEND = 128)
+      PARAMETER (MPI_MODE_SEQUENTIAL = 256)
+!
+      INTEGER(kind=8) MPI_SEEK_SET, MPI_SEEK_CUR, MPI_SEEK_END
+      PARAMETER (MPI_SEEK_SET = 600)
+      PARAMETER (MPI_SEEK_CUR = 602)
+      PARAMETER (MPI_SEEK_END = 604)
+!
+      INTEGER(kind=8) MPI_DISPLACEMENT_CURRENT
+      PARAMETER (MPI_DISPLACEMENT_CURRENT = -1)
+!
+!     Offset kind and address kind
+!
+      INTEGER(kind=8) MPI_INTEGER_KIND, MPI_OFFSET_KIND, MPI_ADDRESS_KIND
+!
+      PARAMETER (MPI_INTEGER_KIND = 4)
+      PARAMETER (MPI_OFFSET_KIND  = 8)
+      PARAMETER (MPI_ADDRESS_KIND = 8)
+!
+!     Thread support
+!
+      INTEGER(kind=8) MPI_THREAD_SINGLE,     MPI_THREAD_FUNNELED
+      INTEGER(kind=8) MPI_THREAD_SERIALIZED, MPI_THREAD_MULTIPLE
+!
+      PARAMETER (MPI_THREAD_SINGLE     = 1)
+      PARAMETER (MPI_THREAD_FUNNELED   = 2)
+      PARAMETER (MPI_THREAD_SERIALIZED = 3)
+      PARAMETER (MPI_THREAD_MULTIPLE   = 4)
+!
+!     Windows
+!
+      INTEGER(kind=8) MPI_LOCK_EXCLUSIVE, MPI_LOCK_SHARED
+      INTEGER(kind=8) MPI_MODE_NOCHECK,   MPI_MODE_NOSTORE
+      INTEGER(kind=8) MPI_MODE_NOPUT,     MPI_MODE_NOPRECEDE
+      INTEGER(kind=8) MPI_MODE_NOSUCCEED
+!
+      PARAMETER (MPI_LOCK_EXCLUSIVE    = 0)
+      PARAMETER (MPI_LOCK_SHARED       = 1)
+!
+      PARAMETER (MPI_MODE_NOCHECK      = 256)
+      PARAMETER (MPI_MODE_NOSTORE      = 512)
+      PARAMETER (MPI_MODE_NOPUT        = 1024)
+      PARAMETER (MPI_MODE_NOPRECEDE    = 2048)
+      PARAMETER (MPI_MODE_NOSUCCEED    = 4096)
+!
+!  NEC extension
+!
+      INTEGER(kind=8) MPI_NEC_MODE_GETPUTALIGNED
+      PARAMETER (MPI_NEC_MODE_GETPUTALIGNED = 16384)
+!
+      INTEGER(kind=8) MPI_WIN_BASE, MPI_WIN_SIZE, MPI_WIN_DISP_UNIT
+!
+      PARAMETER (MPI_WIN_BASE          = 94)
+      PARAMETER (MPI_WIN_SIZE          = 96)
+      PARAMETER (MPI_WIN_DISP_UNIT     = 98)
+!
+!     Common blocks :
+!
+!     Dummy variables in order to guarantuee compatibility
+!     to previous versions of MPI/SX
+!
+      INTEGER(kind=8) MPIR_ARGV_NULL_I,     MPIR_ARGVS_NULL_I
+      INTEGER(kind=8) MPIR_STATUS_IGNORE_I, MPIR_STATUSES_IGNORE_I
+      INTEGER(kind=8) MPIR_DUMMY (4)
+!
+!     MPI_BOTTOM needs to be a known address; here we put it at the
+!     beginning of the common block.
+!     MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE, MPI_ERRCODES_IGNORE, ...
+!     are similar objects
+!
+      INTEGER(kind=8) MPI_BOTTOM, MPI_IN_PLACE
+      INTEGER(kind=8) MPI_STATUS_IGNORE   (MPI_STATUS_SIZE)
+      INTEGER(kind=8) MPI_STATUSES_IGNORE (MPI_STATUS_SIZE, 1)
+      INTEGER(kind=8) MPI_ERRCODES_IGNORE(1)
+      CHARACTER (LEN=8) MPI_ARGV_NULL(1), MPI_ARGVS_NULL(1,1)
+!
+      GLOBAL COMMON /MPIPRIV/  MPI_BOTTOM, MPIR_DUMMY
+      GLOBAL COMMON /MPIPRIV2/ MPIR_STATUS_IGNORE_I
+      GLOBAL COMMON /MPIPRIV2/ MPIR_STATUSES_IGNORE_I
+      GLOBAL COMMON /MPIPRIV2/ MPI_ERRCODES_IGNORE, MPI_IN_PLACE
+      GLOBAL COMMON /MPIPRIV2/ MPIR_ARGV_NULL_I,  MPIR_ARGVS_NULL_I
+      GLOBAL COMMON /MPIPRIV3/ MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE
+      GLOBAL COMMON /MPIPRIV4/ MPI_ARGV_NULL,     MPI_ARGVS_NULL
+!
+      SAVE /MPIPRIV/, /MPIPRIV2/, /MPIPRIV3/, /MPIPRIV4/
+!
+!     All other MPI routines are subroutines
+!
+      DOUBLE PRECISION MPI_WTIME, MPI_WTICK
+      EXTERNAL         MPI_WTIME, MPI_WTICK
+!
+      DOUBLE PRECISION MPI_NEC_BLOCK_TIME
+      EXTERNAL         MPI_NEC_BLOCK_TIME
+!
+!     DOUBLE PRECISION PMPI_WTIME, PMPI_WTICK
+!     EXTERNAL         PMPI_WTIME, PMPI_WTICK
+!
+!     The attribute copy/delete subroutines are symbols that can be passed
+!     to MPI routines
+!
+      EXTERNAL MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, MPI_DUP_FN
+!
+      EXTERNAL MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN
+      EXTERNAL MPI_COMM_DUP_FN
+!
+      EXTERNAL MPI_TYPE_NULL_COPY_FN, MPI_TYPE_NULL_DELETE_FN
+      EXTERNAL MPI_TYPE_DUP_FN
+!
+      EXTERNAL MPI_WIN_NULL_COPY_FN, MPI_WIN_NULL_DELETE_FN
+      EXTERNAL MPI_WIN_DUP_FN
diff --git a/odb/src/extras/mpi_serial/mpif.h.necsx5.CSCS b/odb/src/extras/mpi_serial/mpif.h.necsx5.CSCS
new file mode 100644
index 0000000..c5fb5c5
--- /dev/null
+++ b/odb/src/extras/mpi_serial/mpif.h.necsx5.CSCS
@@ -0,0 +1,512 @@
+!
+!         COPYRIGHT
+!  
+! The following is a notice of limited availability of the code, and
+! disclaimer which must be included in the prologue of the code and in
+! all source listings of the code.
+! 
+! Copyright Notice
+!  + 1997/2003 NEC Corporation
+!  + 1993/1997 University of Chicago
+!  + 1993 Mississippi State University
+! 
+! The underlying software called "MPICH" was originally authored by:
+! 
+! Argonne National Laboratory Group
+! W. Gropp:  (708) 252-4318; FAX: (708) 252-7852; e-mail: gropp at mcs.anl.gov
+! E. Lusk:   (708) 252-7852; FAX: (708) 252-7852; e-mail: lusk at mcs.anl.gov
+! R. Thakur: (630) 252-1682; FAX: (630) 252-5986; e-mail: thakur at mcs.anl.gov
+! Mathematics and Computer Science Division
+! Argonne National Laboratory, Argonne IL 60439
+! 
+! Mississippi State Group
+! N. Doss:  (601) 325-2565; FAX: (601) 325-7692;
+!           e-mail: doss at erc.msstate.edu
+! A. Skjellum:(601) 325-8435; FAX: (601) 325-8997;
+!           e-mail: tony at erc.msstate.edu
+! Mississippi State University, Computer Science Department &
+! NSF Engineering Research Center for Computational Field Simulation,
+! P.O. Box 6176, Mississippi State MS 39762
+! 
+! This software is MPICH, with modifications by NEC Corporation's CCRLE 
+! laboratory:
+! CCRLE, NEC Europe Ltd., Rathausallee 10, 53757 Sankt Augustin, Germany.
+! The use of the modifications included in this software is governed by
+! the license agreement between the customer and NEC Corporation. In
+! particular, the distribution to others or use for the preparation of
+! derivative works incorporating NEC's modifications to the software
+! is prohibited unless prior written approval from NEC Corporation is
+! obtained.
+! 
+! 
+!       DISCLAIMER
+! 
+! This computer code material was prepared, in part, as an account of work
+! sponsored by an agency of the United States Government. Neither the
+! United States, nor the University of Chicago, nor Mississippi State
+! University, nor any of their employees, makes any warranty express or
+! implied, or assumes any legal liability or responsibility for the
+! accuracy, completeness, or usefulness of any information, apparatus,
+! product, or process disclosed, or represents that its use would not
+! infringe privately owned rights.
+!      
+! 
+!      AVAILABILITY OF MPICH
+!      
+! MPICH is available from Argonne National Laboratory and Mississippi
+! State under a royalty-free license to use, reproduce, prepare
+! derivative works, and to redistribute to others. MPICH was prepared, in
+! part, as an account of work under a U.S. Government Contract and is
+! subject to the following license: the Government is granted for itself
+! and others acting on its behalf a paid-up, nonexclusive, irrevocable
+! worldwide license in this computer software to reproduce, prepare
+! derivative works, and perform publicly and display publicly. 
+!
+! user include file for MPI programs, with no dependencies.
+!
+!     Return codes 
+!
+      INTEGER MPI_SUCCESS,MPI_ERR_BUFFER,MPI_ERR_COUNT,MPI_ERR_TYPE
+      INTEGER MPI_ERR_TAG,MPI_ERR_COMM,MPI_ERR_RANK,MPI_ERR_ROOT
+      INTEGER MPI_ERR_GROUP
+      INTEGER MPI_ERR_OP,MPI_ERR_TOPOLOGY,MPI_ERR_DIMS,MPI_ERR_ARG
+      INTEGER MPI_ERR_UNKNOWN,MPI_ERR_TRUNCATE,MPI_ERR_OTHER
+      INTEGER MPI_ERR_INTERN,MPI_ERR_IN_STATUS,MPI_ERR_PENDING
+      INTEGER MPI_ERR_REQUEST, MPI_ERR_LASTCODE
+!
+      INTEGER MPI_ERR_IO, MPI_ERR_ACCESS, MPI_ERR_AMODE, MPI_ERR_ASSERT
+      INTEGER MPI_ERR_BAD_FILE, MPI_ERR_BASE, MPI_ERR_CONVERSION
+      INTEGER MPI_ERR_DISP, MPI_ERR_DUP_DATAREP, MPI_ERR_FILE_EXISTS
+      INTEGER MPI_ERR_FILE_IN_USE, MPI_ERR_FILE, MPI_ERR_INFO_KEY
+      INTEGER MPI_ERR_INFO_NOKEY, MPI_ERR_INFO_VALUE, MPI_ERR_INFO
+      INTEGER MPI_ERR_KEYVAL, MPI_ERR_LOCKTYPE, MPI_ERR_NAME
+      INTEGER MPI_ERR_NO_MEM, MPI_ERR_NOT_SAME, MPI_ERR_NO_SPACE
+      INTEGER MPI_ERR_NO_SUCH_FILE, MPI_ERR_PORT, MPI_ERR_QUOTA
+      INTEGER MPI_ERR_READ_ONLY, MPI_ERR_RMA_CONFLICT, MPI_ERR_RMA_SYNC
+      INTEGER MPI_ERR_SERVICE, MPI_ERR_SIZE, MPI_ERR_SPAWN
+      INTEGER MPI_ERR_UNSUPPORTED_DATAREP, MPI_ERR_UNSUPPORTED_OPERATION
+      INTEGER MPI_ERR_WIN
+!
+      PARAMETER (MPI_SUCCESS = 0)
+      PARAMETER (MPI_ERR_BUFFER = 1)
+      PARAMETER (MPI_ERR_COUNT = 2)
+      PARAMETER (MPI_ERR_TYPE = 3)
+      PARAMETER (MPI_ERR_TAG = 4)
+      PARAMETER (MPI_ERR_COMM = 5)
+      PARAMETER (MPI_ERR_RANK = 6)
+      PARAMETER (MPI_ERR_ROOT = 7)
+      PARAMETER (MPI_ERR_GROUP = 8)
+      PARAMETER (MPI_ERR_OP = 9)
+      PARAMETER (MPI_ERR_TOPOLOGY = 10)
+      PARAMETER (MPI_ERR_DIMS = 11)
+      PARAMETER (MPI_ERR_ARG = 12)
+      PARAMETER (MPI_ERR_UNKNOWN = 13)
+      PARAMETER (MPI_ERR_TRUNCATE = 14)
+      PARAMETER (MPI_ERR_OTHER = 15)
+      PARAMETER (MPI_ERR_INTERN = 16)
+      PARAMETER (MPI_ERR_IN_STATUS = 17)
+      PARAMETER (MPI_ERR_PENDING = 18)
+      PARAMETER (MPI_ERR_REQUEST = 19)
+!
+      PARAMETER (MPI_ERR_IO = 20)
+      PARAMETER (MPI_ERR_ACCESS = 21)
+      PARAMETER (MPI_ERR_AMODE = 22)
+      PARAMETER (MPI_ERR_ASSERT = 23)
+      PARAMETER (MPI_ERR_BAD_FILE = 24)
+      PARAMETER (MPI_ERR_BASE = 25)
+      PARAMETER (MPI_ERR_CONVERSION = 26)
+      PARAMETER (MPI_ERR_DISP = 27)
+      PARAMETER (MPI_ERR_DUP_DATAREP = 28)
+      PARAMETER (MPI_ERR_FILE_EXISTS = 29)
+      PARAMETER (MPI_ERR_FILE_IN_USE = 30)
+      PARAMETER (MPI_ERR_FILE = 31)
+      PARAMETER (MPI_ERR_INFO_KEY = 32)
+      PARAMETER (MPI_ERR_INFO_NOKEY = 33)
+      PARAMETER (MPI_ERR_INFO_VALUE = 34)
+      PARAMETER (MPI_ERR_INFO = 35)
+      PARAMETER (MPI_ERR_KEYVAL = 36)
+      PARAMETER (MPI_ERR_LOCKTYPE = 37)
+      PARAMETER (MPI_ERR_NAME = 38)
+      PARAMETER (MPI_ERR_NO_MEM = 39)
+      PARAMETER (MPI_ERR_NOT_SAME = 40)
+      PARAMETER (MPI_ERR_NO_SPACE = 41)
+      PARAMETER (MPI_ERR_NO_SUCH_FILE = 42)
+      PARAMETER (MPI_ERR_PORT = 43)
+      PARAMETER (MPI_ERR_QUOTA = 44)
+      PARAMETER (MPI_ERR_READ_ONLY = 45)
+      PARAMETER (MPI_ERR_RMA_CONFLICT = 46)
+      PARAMETER (MPI_ERR_RMA_SYNC = 47)
+      PARAMETER (MPI_ERR_SERVICE = 48)
+      PARAMETER (MPI_ERR_SIZE = 49)
+      PARAMETER (MPI_ERR_SPAWN = 50)
+      PARAMETER (MPI_ERR_UNSUPPORTED_DATAREP = 51)
+      PARAMETER (MPI_ERR_UNSUPPORTED_OPERATION = 52)
+      PARAMETER (MPI_ERR_WIN = 53)
+!
+      PARAMETER (MPI_ERR_LASTCODE = 4114)
+!
+      INTEGER MPI_ERRORS_ARE_FATAL, MPI_ERRORS_RETURN
+!
+      PARAMETER (MPI_ERRORS_ARE_FATAL = 119)
+      PARAMETER (MPI_ERRORS_RETURN    = 120)
+!
+!     Parameters
+!
+      INTEGER MPI_UNDEFINED, MPI_KEYVAL_INVALID, MPI_BSEND_OVERHEAD
+!
+      PARAMETER (MPI_UNDEFINED      = (-32766))
+      PARAMETER (MPI_KEYVAL_INVALID = 0)
+      PARAMETER (MPI_BSEND_OVERHEAD = 512)
+!
+      INTEGER MPI_GRAPH, MPI_CART
+      PARAMETER (MPI_GRAPH = 1)
+      PARAMETER (MPI_CART  = 2)
+!
+      INTEGER MPI_SOURCE, MPI_TAG, MPI_ERROR, MPI_STATUS_SIZE
+      PARAMETER (MPI_ERROR       = 1)
+      PARAMETER (MPI_SOURCE      = 2)
+      PARAMETER (MPI_TAG         = 3)
+      PARAMETER (MPI_STATUS_SIZE = 6)
+!
+      INTEGER MPI_MAX_PROCESSOR_NAME, MPI_MAX_ERROR_STRING
+      INTEGER MPI_MAX_NAME_STRING, MPI_MAX_INFO_KEY, MPI_MAX_INFO_VAL
+      INTEGER MPI_MAX_DATAREP_STRING, MPI_MAX_OBJECT_NAME
+      INTEGER MPI_MAX_PORT_NAME
+!
+      PARAMETER (MPI_MAX_DATAREP_STRING = 128)
+      PARAMETER (MPI_MAX_ERROR_STRING   = 512)
+      PARAMETER (MPI_MAX_INFO_KEY       = 255)
+      PARAMETER (MPI_MAX_INFO_VAL       = 1024)
+      PARAMETER (MPI_MAX_NAME_STRING    = 65)
+      PARAMETER (MPI_MAX_PROCESSOR_NAME = 256)
+      PARAMETER (MPI_MAX_OBJECT_NAME    = MPI_MAX_NAME_STRING)
+      PARAMETER (MPI_MAX_PORT_NAME      = MPI_MAX_NAME_STRING)
+!
+!     Null objects
+!
+      INTEGER MPI_COMM_NULL,  MPI_DATATYPE_NULL, MPI_ERRHANDLER_NULL
+      INTEGER MPI_GROUP_NULL, MPI_REQUEST_NULL,  MPI_PROC_NULL
+      INTEGER MPI_OP_NULL,    MPI_INFO_NULL,     MPI_FILE_NULL
+      INTEGER MPI_WIN_NULL
+!
+      PARAMETER (MPI_COMM_NULL       = 0)
+      PARAMETER (MPI_DATATYPE_NULL   = 0)
+      PARAMETER (MPI_ERRHANDLER_NULL = 0)
+      PARAMETER (MPI_FILE_NULL       = 0)
+      PARAMETER (MPI_GROUP_NULL      = 0)
+      PARAMETER (MPI_INFO_NULL       = 0)
+      PARAMETER (MPI_OP_NULL         = 0)
+      PARAMETER (MPI_REQUEST_NULL    = 0)
+      PARAMETER (MPI_WIN_NULL        = 0)
+      PARAMETER (MPI_PROC_NULL       = (-1))
+! 
+!     Results of the compare operations
+! 
+      INTEGER MPI_IDENT, MPI_CONGRUENT, MPI_SIMILAR, MPI_UNEQUAL
+      PARAMETER (MPI_IDENT     = 0)
+      PARAMETER (MPI_CONGRUENT = 1)
+      PARAMETER (MPI_SIMILAR   = 2)
+      PARAMETER (MPI_UNEQUAL   = 3)
+!
+!     The types MPI_INTEGER1,2,4 and MPI_REAL4,8 are OPTIONAL.
+!     Their values are zero if they are not available.  Note that
+!     using these reduces the portability of code.
+!
+      INTEGER MPI_INTEGER, MPI_REAL, MPI_DOUBLE_PRECISION 
+      INTEGER MPI_COMPLEX, MPI_DOUBLE_COMPLEX, MPI_LOGICAL
+      INTEGER MPI_CHARACTER, MPI_BYTE, MPI_2INTEGER, MPI_2REAL
+      INTEGER MPI_2DOUBLE_PRECISION, MPI_2COMPLEX, MPI_2DOUBLE_COMPLEX
+      INTEGER MPI_UB, MPI_LB, MPI_PACKED
+      INTEGER MPI_TYPECLASS_INTEGER, MPI_TYPECLASS_REAL
+      INTEGER MPI_TYPECLASS_COMPLEX, MPI_TYPECLASS_LOGICAL
+!
+      PARAMETER (MPI_CHARACTER = 1)
+      PARAMETER (MPI_BYTE      = 3)
+      PARAMETER (MPI_PACKED    = 14)
+      PARAMETER (MPI_LB        = 15)
+      PARAMETER (MPI_UB        = 16)
+      PARAMETER (MPI_COMPLEX   = 23)
+      PARAMETER (MPI_DOUBLE_COMPLEX = 24)
+      PARAMETER (MPI_LOGICAL   = 25)
+      PARAMETER (MPI_REAL      = 26)
+      PARAMETER (MPI_DOUBLE_PRECISION = 27)
+      PARAMETER (MPI_INTEGER   = 28)
+      PARAMETER (MPI_2INTEGER  = 29)
+      PARAMETER (MPI_2COMPLEX  = 30)
+      PARAMETER (MPI_2DOUBLE_COMPLEX = 31)
+      PARAMETER (MPI_2REAL     = 32)
+      PARAMETER (MPI_2DOUBLE_PRECISION = 33)
+!
+      PARAMETER (MPI_TYPECLASS_INTEGER = -1)
+      PARAMETER (MPI_TYPECLASS_REAL    = -2)
+      PARAMETER (MPI_TYPECLASS_COMPLEX = -3)
+      PARAMETER (MPI_TYPECLASS_LOGICAL = -4)
+!
+!     FORTRAN Extensions for NEC SX
+!
+!  MPI_AINT   corresponds to the datatype of
+!                         an INTEGER (KIND=MPI_ADDRESS_KIND) variable
+!  MPI_OFFSET corresponds to the datatype of
+!                         an INTEGER (KIND=MPI_OFFSET_KIND) variable
+!
+      INTEGER MPI_INTEGER1, MPI_INTEGER2, MPI_INTEGER4, MPI_INTEGER8
+      INTEGER MPI_INTEGER16
+      INTEGER MPI_LOGICAL1, MPI_LOGICAL4, MPI_LOGICAL8
+      INTEGER MPI_REAL4, MPI_REAL8, MPI_REAL16
+      INTEGER MPI_COMPLEX8, MPI_COMPLEX16, MPI_COMPLEX32
+      INTEGER MPI_2REAL4, MPI_2REAL8, MPI_2COMPLEX8, MPI_2COMPLEX16
+      INTEGER MPI_QUADRUPLE_PRECISION, MPI_QUADRUPLE_COMPLEX
+      INTEGER MPI_OFFSET, MPI_AINT
+!
+      PARAMETER (MPI_INTEGER1 = MPI_DATATYPE_NULL)
+      PARAMETER (MPI_INTEGER2 = 50)
+      PARAMETER (MPI_INTEGER8 = 51)
+      PARAMETER (MPI_INTEGER16 = MPI_DATATYPE_NULL)
+      PARAMETER (MPI_LOGICAL1 = 52)
+      PARAMETER (MPI_LOGICAL8 = 53)
+      PARAMETER (MPI_QUADRUPLE_PRECISION = 54)
+      PARAMETER (MPI_QUADRUPLE_COMPLEX = 55)
+!
+      PARAMETER (MPI_INTEGER4 = MPI_INTEGER)
+      PARAMETER (MPI_LOGICAL4 = MPI_LOGICAL)
+      PARAMETER (MPI_REAL4  = MPI_REAL)
+      PARAMETER (MPI_REAL8  = MPI_DOUBLE_PRECISION)
+      PARAMETER (MPI_REAL16 = MPI_QUADRUPLE_PRECISION)
+      PARAMETER (MPI_COMPLEX8  = MPI_COMPLEX)
+      PARAMETER (MPI_COMPLEX16 = MPI_DOUBLE_COMPLEX)
+      PARAMETER (MPI_COMPLEX32 = MPI_QUADRUPLE_COMPLEX)
+!
+      PARAMETER (MPI_2REAL4 = MPI_2REAL)
+      PARAMETER (MPI_2REAL8 = MPI_2DOUBLE_PRECISION)
+      PARAMETER (MPI_2COMPLEX8  = MPI_2COMPLEX)
+      PARAMETER (MPI_2COMPLEX16 = MPI_2DOUBLE_COMPLEX)
+!
+      PARAMETER (MPI_AINT    = MPI_INTEGER8)
+      PARAMETER (MPI_OFFSET  = MPI_INTEGER8)
+!
+!     Combiner
+!
+      INTEGER MPI_COMBINER_NAMED,   MPI_COMBINER_CONTIGUOUS
+      INTEGER MPI_COMBINER_VECTOR,  MPI_COMBINER_HVECTOR
+      INTEGER MPI_COMBINER_INDEXED, MPI_COMBINER_HINDEXED
+      INTEGER MPI_COMBINER_STRUCT,  MPI_COMBINER_DUP
+      INTEGER MPI_COMBINER_INDEXED_BLOCK, MPI_COMBINER_HVECTOR_INTEGER
+      INTEGER MPI_COMBINER_HINDEXED_INTEGER, MPI_COMBINER_STRUCT_INTEGER
+      INTEGER MPI_COMBINER_DARRAY,  MPI_COMBINER_SUBARRAY
+      INTEGER MPI_COMBINER_RESIZED, MPI_COMBINER_F90_REAL
+      INTEGER MPI_COMBINER_F90_COMPLEX, MPI_COMBINER_F90_INTEGER
+!
+      PARAMETER (MPI_COMBINER_NAMED            = 2312)
+      PARAMETER (MPI_COMBINER_CONTIGUOUS       = 2313)
+      PARAMETER (MPI_COMBINER_VECTOR           = 2314)
+      PARAMETER (MPI_COMBINER_HVECTOR          = 2315)
+      PARAMETER (MPI_COMBINER_INDEXED          = 2316)
+      PARAMETER (MPI_COMBINER_HINDEXED         = 2317)
+      PARAMETER (MPI_COMBINER_STRUCT           = 2318)
+      PARAMETER (MPI_COMBINER_DUP              = 2319)
+      PARAMETER (MPI_COMBINER_INDEXED_BLOCK    = 2320)
+      PARAMETER (MPI_COMBINER_HVECTOR_INTEGER  = 2321)
+      PARAMETER (MPI_COMBINER_HINDEXED_INTEGER = 2322)
+      PARAMETER (MPI_COMBINER_STRUCT_INTEGER   = 2323)
+      PARAMETER (MPI_COMBINER_DARRAY           = 2324)
+      PARAMETER (MPI_COMBINER_SUBARRAY         = 2325)
+      PARAMETER (MPI_COMBINER_RESIZED          = 2326)
+      PARAMETER (MPI_COMBINER_F90_REAL         = 2327)
+      PARAMETER (MPI_COMBINER_F90_COMPLEX      = 2328)
+      PARAMETER (MPI_COMBINER_F90_INTEGER      = 2329)
+!
+!     For subarray and darray constructors
+!
+      INTEGER MPI_ORDER_C, MPI_ORDER_FORTRAN 
+      PARAMETER (MPI_ORDER_C       = 56)
+      PARAMETER (MPI_ORDER_FORTRAN = 57)
+!
+      INTEGER MPI_DISTRIBUTE_BLOCK, MPI_DISTRIBUTE_CYCLIC
+      INTEGER MPI_DISTRIBUTE_NONE, MPI_DISTRIBUTE_DFLT_DARG
+      PARAMETER (MPI_DISTRIBUTE_BLOCK  = 121)
+      PARAMETER (MPI_DISTRIBUTE_CYCLIC = 122)
+      PARAMETER (MPI_DISTRIBUTE_NONE   = 123)
+      PARAMETER (MPI_DISTRIBUTE_DFLT_DARG = -49767)
+!
+!     Collective operations
+!
+      INTEGER MPI_SUM, MPI_MAX, MPI_MIN,  MPI_PROD, MPI_LAND, MPI_BAND
+      INTEGER MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR, MPI_MINLOC
+      INTEGER MPI_MAXLOC, MPI_REPLACE
+!
+      PARAMETER (MPI_MAX    = 100)
+      PARAMETER (MPI_MIN    = 101)
+      PARAMETER (MPI_SUM    = 102)
+      PARAMETER (MPI_PROD   = 103)
+      PARAMETER (MPI_LAND   = 104)
+      PARAMETER (MPI_BAND   = 105)
+      PARAMETER (MPI_LOR    = 106)
+      PARAMETER (MPI_BOR    = 107)
+      PARAMETER (MPI_LXOR   = 108)
+      PARAMETER (MPI_BXOR   = 109)
+      PARAMETER (MPI_MINLOC = 110)
+      PARAMETER (MPI_MAXLOC = 111)
+      PARAMETER (MPI_REPLACE= 112)
+!
+!     Communicator
+!
+      INTEGER MPI_COMM_WORLD, MPI_COMM_SELF, MPI_GROUP_EMPTY
+!
+      PARAMETER (MPI_GROUP_EMPTY = 90)
+      PARAMETER (MPI_COMM_WORLD  = 91)
+      PARAMETER (MPI_COMM_SELF   = 92)
+!
+!     Attributes
+!
+      INTEGER MPI_TAG_UB, MPI_HOST, MPI_IO, MPI_WTIME_IS_GLOBAL
+      INTEGER MPI_UNIVERSE_SIZE, MPI_APPNUM
+      INTEGER MPI_LASTUSEDCODE
+      INTEGER MPI_APPL_GROUP, MPI_MAX_APPL_GROUP
+      INTEGER MPI_COMM_SPECIAL_BARRIER, MPI_WIN_SPECIAL_BARRIER
+!
+      PARAMETER (MPI_TAG_UB = 80)
+      PARAMETER (MPI_HOST   = 82)
+      PARAMETER (MPI_IO     = 84)
+      PARAMETER (MPI_WTIME_IS_GLOBAL = 86)
+      PARAMETER (MPI_UNIVERSE_SIZE   = 88)
+      PARAMETER (MPI_APPNUM          = 78)
+      PARAMETER (MPI_LASTUSEDCODE = 150)
+!
+      PARAMETER (MPI_APPL_GROUP     = 146)
+      PARAMETER (MPI_MAX_APPL_GROUP = 148)
+!
+      PARAMETER (MPI_COMM_SPECIAL_BARRIER = 142)
+      PARAMETER (MPI_WIN_SPECIAL_BARRIER  = 144)
+!
+      INTEGER MPI_ANY_TAG, MPI_ANY_SOURCE, MPI_ROOT
+      PARAMETER (MPI_ANY_TAG    = (-1))
+      PARAMETER (MPI_ANY_SOURCE = (-2))
+      PARAMETER (MPI_ROOT       = (-3))
+!
+      INTEGER MPI_VERSION, MPI_SUBVERSION
+      PARAMETER (MPI_VERSION    = 2)
+      PARAMETER (MPI_SUBVERSION = 0)
+!
+!     Fortran MPI-IO
+!
+      INTEGER MPI_MODE_RDONLY, MPI_MODE_RDWR, MPI_MODE_WRONLY
+      INTEGER MPI_MODE_DELETE_ON_CLOSE, MPI_MODE_UNIQUE_OPEN
+      INTEGER MPI_MODE_CREATE, MPI_MODE_EXCL
+      INTEGER MPI_MODE_APPEND, MPI_MODE_SEQUENTIAL
+      PARAMETER (MPI_MODE_RDONLY = 2)
+      PARAMETER (MPI_MODE_RDWR   = 8)
+      PARAMETER (MPI_MODE_WRONLY = 4)
+      PARAMETER (MPI_MODE_CREATE = 1)
+      PARAMETER (MPI_MODE_DELETE_ON_CLOSE = 16)
+      PARAMETER (MPI_MODE_UNIQUE_OPEN = 32)
+      PARAMETER (MPI_MODE_EXCL = 64)
+      PARAMETER (MPI_MODE_APPEND = 128)
+      PARAMETER (MPI_MODE_SEQUENTIAL = 256)
+!
+      INTEGER MPI_SEEK_SET, MPI_SEEK_CUR, MPI_SEEK_END
+      PARAMETER (MPI_SEEK_SET = 600)
+      PARAMETER (MPI_SEEK_CUR = 602)
+      PARAMETER (MPI_SEEK_END = 604)
+!
+      INTEGER MPI_DISPLACEMENT_CURRENT
+      PARAMETER (MPI_DISPLACEMENT_CURRENT = -1)
+!
+!     Offset kind and address kind
+!
+      INTEGER MPI_INTEGER_KIND, MPI_OFFSET_KIND, MPI_ADDRESS_KIND
+!
+      PARAMETER (MPI_INTEGER_KIND = 4)
+      PARAMETER (MPI_OFFSET_KIND  = 8)
+      PARAMETER (MPI_ADDRESS_KIND = 8)
+!
+!     Thread support
+!
+      INTEGER MPI_THREAD_SINGLE,     MPI_THREAD_FUNNELED
+      INTEGER MPI_THREAD_SERIALIZED, MPI_THREAD_MULTIPLE
+!
+      PARAMETER (MPI_THREAD_SINGLE     = 1)
+      PARAMETER (MPI_THREAD_FUNNELED   = 2)
+      PARAMETER (MPI_THREAD_SERIALIZED = 3)
+      PARAMETER (MPI_THREAD_MULTIPLE   = 4)
+!
+!     Windows
+!
+      INTEGER MPI_LOCK_EXCLUSIVE, MPI_LOCK_SHARED
+      INTEGER MPI_MODE_NOCHECK,   MPI_MODE_NOSTORE
+      INTEGER MPI_MODE_NOPUT,     MPI_MODE_NOPRECEDE
+      INTEGER MPI_MODE_NOSUCCEED
+!
+      PARAMETER (MPI_LOCK_EXCLUSIVE    = 0)
+      PARAMETER (MPI_LOCK_SHARED       = 1)
+!
+      PARAMETER (MPI_MODE_NOCHECK      = 256)
+      PARAMETER (MPI_MODE_NOSTORE      = 512)
+      PARAMETER (MPI_MODE_NOPUT        = 1024)
+      PARAMETER (MPI_MODE_NOPRECEDE    = 2048)
+      PARAMETER (MPI_MODE_NOSUCCEED    = 4096)
+!
+!  NEC extension
+!
+      INTEGER MPI_NEC_MODE_GETPUTALIGNED
+      PARAMETER (MPI_NEC_MODE_GETPUTALIGNED = 16384)
+!
+      INTEGER MPI_WIN_BASE, MPI_WIN_SIZE, MPI_WIN_DISP_UNIT
+!
+      PARAMETER (MPI_WIN_BASE          = 94)
+      PARAMETER (MPI_WIN_SIZE          = 96)
+      PARAMETER (MPI_WIN_DISP_UNIT     = 98)
+!
+!     Common blocks :
+!
+!     Dummy variables in order to guarantuee compatibility
+!     to previous versions of MPI/SX
+!
+      INTEGER MPIR_ARGV_NULL_I,     MPIR_ARGVS_NULL_I
+      INTEGER MPIR_STATUS_IGNORE_I, MPIR_STATUSES_IGNORE_I
+      INTEGER MPIR_DUMMY (4)
+!
+!     MPI_BOTTOM needs to be a known address; here we put it at the
+!     beginning of the common block.
+!     MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE, MPI_ERRCODES_IGNORE, ...
+!     are similar objects
+!
+      INTEGER MPI_BOTTOM, MPI_IN_PLACE
+      INTEGER MPI_STATUS_IGNORE   (MPI_STATUS_SIZE)
+      INTEGER MPI_STATUSES_IGNORE (MPI_STATUS_SIZE, 1)
+      INTEGER MPI_ERRCODES_IGNORE(1)
+      CHARACTER (LEN=8) MPI_ARGV_NULL(1), MPI_ARGVS_NULL(1,1)
+!
+      GLOBAL COMMON /MPIPRIV/  MPI_BOTTOM, MPIR_DUMMY
+      GLOBAL COMMON /MPIPRIV2/ MPIR_STATUS_IGNORE_I
+      GLOBAL COMMON /MPIPRIV2/ MPIR_STATUSES_IGNORE_I
+      GLOBAL COMMON /MPIPRIV2/ MPI_ERRCODES_IGNORE, MPI_IN_PLACE
+      GLOBAL COMMON /MPIPRIV2/ MPIR_ARGV_NULL_I,  MPIR_ARGVS_NULL_I
+      GLOBAL COMMON /MPIPRIV3/ MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE
+      GLOBAL COMMON /MPIPRIV4/ MPI_ARGV_NULL,     MPI_ARGVS_NULL
+!
+      SAVE /MPIPRIV/, /MPIPRIV2/, /MPIPRIV3/, /MPIPRIV4/
+!
+!     All other MPI routines are subroutines
+!
+      DOUBLE PRECISION MPI_WTIME, MPI_WTICK
+      EXTERNAL         MPI_WTIME, MPI_WTICK
+!
+      DOUBLE PRECISION MPI_NEC_BLOCK_TIME
+      EXTERNAL         MPI_NEC_BLOCK_TIME
+!
+!     DOUBLE PRECISION PMPI_WTIME, PMPI_WTICK
+!     EXTERNAL         PMPI_WTIME, PMPI_WTICK
+!
+!     The attribute copy/delete subroutines are symbols that can be passed
+!     to MPI routines
+!
+      EXTERNAL MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, MPI_DUP_FN
+!
+      EXTERNAL MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN
+      EXTERNAL MPI_COMM_DUP_FN
+!
+      EXTERNAL MPI_TYPE_NULL_COPY_FN, MPI_TYPE_NULL_DELETE_FN
+      EXTERNAL MPI_TYPE_DUP_FN
+!
+      EXTERNAL MPI_WIN_NULL_COPY_FN, MPI_WIN_NULL_DELETE_FN
+      EXTERNAL MPI_WIN_DUP_FN
diff --git a/odb/src/extras/mpi_serial/tracecalls.c b/odb/src/extras/mpi_serial/tracecalls.c
new file mode 100644
index 0000000..7a616ff
--- /dev/null
+++ b/odb/src/extras/mpi_serial/tracecalls.c
@@ -0,0 +1,20 @@
+/* dummy _TraceCalls */
+void _TraceCalls(char *nothing) { }
+
+#if defined(NECSX)
+
+/* some dummies for NEC + libmpi_serial */
+
+double mpi_nec_block_time_() { return 0; }
+void mpi_type_dup_fn_() { }
+void mpi_type_null_copy_fn_() { }
+void mpi_type_null_delete_fn_() { }
+void mpi_comm_dup_fn_() { }
+void mpi_comm_null_copy_fn_() { }
+void mpi_comm_null_delete_fn_() { }
+void mpi_win_dup_fn_() { }
+void mpi_win_null_copy_fn_() { }
+void mpi_win_null_delete_fn_() { }
+
+#endif
+
diff --git a/odb/src/extras/mpi_serial/vpp_abort.F b/odb/src/extras/mpi_serial/vpp_abort.F
new file mode 100644
index 0000000..87569df
--- /dev/null
+++ b/odb/src/extras/mpi_serial/vpp_abort.F
@@ -0,0 +1,3 @@
+      subroutine vpp_abort
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/vpp_barrier.F b/odb/src/extras/mpi_serial/vpp_barrier.F
new file mode 100644
index 0000000..62553c3
--- /dev/null
+++ b/odb/src/extras/mpi_serial/vpp_barrier.F
@@ -0,0 +1,3 @@
+      subroutine vpp_barrier
+      return
+      end
diff --git a/odb/src/extras/mpi_serial/vpp_sempost.c b/odb/src/extras/mpi_serial/vpp_sempost.c
new file mode 100644
index 0000000..ee2b14a
--- /dev/null
+++ b/odb/src/extras/mpi_serial/vpp_sempost.c
@@ -0,0 +1,3 @@
+/* dummy VPP_SemPost */
+void VPP_SemPost(int a1, int a2) { }
+
diff --git a/odb/src/extras/mpi_serial/vpp_semwait.c b/odb/src/extras/mpi_serial/vpp_semwait.c
new file mode 100644
index 0000000..3a2e7f2
--- /dev/null
+++ b/odb/src/extras/mpi_serial/vpp_semwait.c
@@ -0,0 +1,4 @@
+/* dummy VPP_SemWait */
+void VPP_SemWait(int a1, int a2) { }
+
+
diff --git a/odb/src/include/CMakeLists.txt b/odb/src/include/CMakeLists.txt
new file mode 100644
index 0000000..041ffb5
--- /dev/null
+++ b/odb/src/include/CMakeLists.txt
@@ -0,0 +1,65 @@
+list(APPEND include_files
+
+    alloc.h
+    bits.h
+    cdrhook.h
+    cma_read.h
+    cma_seek.h
+    cma_write.h
+    cmaio.h
+    codb.h
+    codb_netcdf.h
+    dca.h
+    defs.h
+    ecstdlib.h
+    evaluate.h
+    fodb.h
+    fodbmp.h
+    fodbmp1.h
+    fodbmp2.h
+    fodbutil.h
+    fortint.h
+    funcs.h
+    history.h
+    idx.h
+    info.h
+    ioassign.h
+    iostuff.h
+    lzw.h
+    magicwords.h
+    memmap.h
+    mr2d_hdr.h
+    mysql.h
+    newio.h
+    node.h
+    odb.h
+    odb_ioprof.h
+    odb_macros.h
+    odbcrc.h
+    odbcs.h
+    odbcsdefs.h
+    odbcstags.h
+    odbdump.h
+    odbi.h
+    odbi_cs.h
+    odbi_direct.h
+    odbi_struct.h
+    odbmd5.h
+    pcma.h
+    pcma_extern.h
+    privpub.h
+    qtar.h
+    regcache.h
+    result.h
+    setodbcs.h
+    static.h
+    swapbytes.h
+    symtab.h
+    vparam.h
+)
+
+foreach(file ${include_files})
+    configure_file(${file} ${CMAKE_BINARY_DIR}/include/${file} COPYONLY)
+endforeach()
+
+install(FILES ${include_files} DESTINATION include)
diff --git a/odb/src/include/alloc.h b/odb/src/include/alloc.h
new file mode 100644
index 0000000..c5e2d73
--- /dev/null
+++ b/odb/src/include/alloc.h
@@ -0,0 +1,273 @@
+#ifndef _ALLOC_H_
+#define _ALLOC_H_
+
+#if (defined(LINUX) && !defined(CYGWIN)) || defined(SUN4) || defined(RS6K) || defined(NECSX)
+/* Above systems: Enforce to use <alloca.h> i.e. ALLOCX becomes ALLOCA, unless explicitly set -DUSE_ALLOCA_H=0 */
+#if !defined(USE_ALLOCA_H) || (defined(USE_ALLOCA_H) && USE_ALLOCA_H != 0)
+#define USE_ALLOCA_H 1
+#endif
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#if defined(USE_ALLOCA_H) && USE_ALLOCA_H != 0
+#include <alloca.h>
+#endif
+#include "ecstdlib.h"
+#include <signal.h>
+
+#include "privpub.h"
+
+#if defined(STD_MEM_ALLOC) && STD_MEM_ALLOC == 1 && defined(INTERCEPT_ALLOC)
+#undef INTERCEPT_ALLOC
+#endif
+
+#if defined(INTERCEPT_ALLOC)
+#if defined(RS6K) && defined(__64BIT__)
+
+#define EC_free     __free
+#define EC_malloc   __malloc
+#define EC_calloc   __calloc
+#define EC_realloc  __realloc
+#define EC_strdup   __strdup
+
+#elif defined(NECSX)
+/* Do nothing */
+#else
+/* Illegal to have -DINTERCEPT_ALLOC */
+#undef INTERCEPT_ALLOC
+#endif
+
+#endif
+
+#if defined(INTERCEPT_ALLOC)
+
+/* For reference, see also ifsaux/utilities/getcurheap.c */
+
+#define THEmalloc  EC_malloc
+extern void *EC_malloc(ll_t size);
+#define THEcalloc  EC_calloc
+extern void *EC_calloc(ll_t nelem, ll_t elsize);
+#define THErealloc EC_realloc
+extern void *EC_realloc(void *p, ll_t size);
+#define THEstrdup  EC_strdup
+extern char *EC_strdup(const char *s);
+#define THEfree    EC_free
+extern void EC_free(void *p);
+
+#else /* i.e. !defined(INTERCEPT_ALLOC) */
+
+#define THEmalloc  malloc
+#define THEcalloc  calloc
+#define THErealloc realloc
+#define THEstrdup  strdup
+#define THEfree    free
+
+#endif
+
+extern int ODB_std_mem_alloc(int onoff);
+extern void *ODB_reserve_zeromem(int size_elem, int num_elem, const char *var, const char *file, int linenum);
+extern void *ODB_reserve_mem(int size_elem, int num_elem, const char *var, const char *file, int linenum);
+extern void *ODB_re_alloc(void *p, int size_elem, int num_elem, const char *var, const char *file, int linenum);
+extern void  ODB_release_mem(void *x, const char *var, const char *file, int linenum);
+extern char *ODB_strdup_mem(const char *s, const char *var, const char *file, int linenum);
+extern int ODB_freeptr_trace(FILE *fp, const char *routine, const char *file, int line, int onoff);
+
+extern void
+codb_strblank_(char *c,
+	       /* Hidden arguments */
+	       int len_c);
+extern void
+codb_zerofill_(void *c, const size_t *nbytes);
+
+/* Some common file I/O utilities */
+
+int file_exist_(const char *s);
+int is_regular_file_(const char *s);
+int is_directory_(const char *s);
+int rename_file_(const char *in, const char *out);
+int remove_file_(const char *filename);
+
+#define ALLOC_ABORT(x, bytes, via) { \
+  fprintf(stderr,"***Error: Unable to allocate %lld bytes via '%s' for %s at %s:%d\n", \
+                  (ll_t)(bytes), via, #x, __FILE__, __LINE__); \
+  RAISE(SIGABRT); \
+}
+
+/* Since ALLOCA uses alloca(), don't encapsulate the ALLOCA around {}'s */
+#define ALLOCA(x,size) \
+  x = alloca((ll_t)MAX(1,(size)) * sizeof(*(x))); \
+  if (!x) ALLOC_ABORT(x, MAX(1,(size)) * sizeof(*(x)), "alloca()"); \
+  { extern ll_t getstk_(); /* From IFSAUX */ \
+         (void) getstk_(); /* Keep track of stacksizes */ }
+
+#if defined(USE_ALLOCA_H) && USE_ALLOCA_H != 0
+#define ALLOCX ALLOCA
+#define FREEX(x) (x) = NULL
+#else
+#define ALLOCX ALLOC
+#define FREEX  FREE
+#endif
+
+#if defined(STD_MEM_ALLOC) && STD_MEM_ALLOC == 1
+
+/* Memory allocation via standard route 
+   (not necessarely the default; pls. check config/Makefiles) */
+
+#define CALLOC(x,size) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THEcalloc(_nelem_x, sizeof(*(x))); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * sizeof(*(x)), "calloc()"); }
+
+#define CALLOC3(x,size,elemsize) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THEcalloc(_nelem_x, elemsize); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * elemsize), "calloc()@3"); }
+
+#define ALLOC(x,size) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THEmalloc(_nelem_x * sizeof(*(x))); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * sizeof(*(x)), "malloc()"); }
+
+#define ALLOC3(x,size,elemsize) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THEmalloc(_nelem_x * elemsize); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * elemsize, "malloc()@3"); }
+
+#define REALLOC(x,size) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THErealloc(x, _nelem_x * sizeof(*(x))); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * sizeof(*(x)), "realloc()"); }
+
+#define REALLOC3(x,size,elemsize) { \
+  ll_t _nelem_x = MAX(1,(size)); \
+  x = THErealloc(x, _nelem_x * elemsize); \
+  if (!x) ALLOC_ABORT(x, _nelem_x * elemsize), "realloc()@3"); }
+
+#define FREE(x) ((x) ? (THEfree(x), (x) = NULL) : NULL)
+
+#define FREEPTR_TRACE(fp, routine, onoff) 0
+
+#define STRDUP(s) THEstrdup(s ? s : "")
+
+#else
+
+/* Use memory allocation via wrapper library for better control of memory leaks when needed */
+
+#define CALLOC(x,size) \
+  x = ODB_reserve_zeromem(sizeof(*(x)), (size), #x, __FILE__, __LINE__)
+
+#define CALLOC3(x,size,elemsize) \
+  x = ODB_reserve_zeromem(elemsize, (size), #x, __FILE__, __LINE__)
+
+#define  ALLOC(x,size) \
+  x = ODB_reserve_mem(sizeof(*(x)), (size), #x, __FILE__, __LINE__)
+
+#define  ALLOC3(x,size,elemsize) \
+  x = ODB_reserve_mem(elemsize, (size), #x, __FILE__, __LINE__)
+
+#define REALLOC(x,size) \
+  x = ODB_re_alloc(x, sizeof(*(x)), (size), #x, __FILE__, __LINE__)
+
+#define REALLOC3(x,size,elemsize) \
+  x = ODB_re_alloc(x, elemsize, (size), #x, __FILE__, __LINE__)
+
+#define FREE(x) \
+  if (x) { ODB_release_mem(x, #x, __FILE__, __LINE__); (x) = NULL; }
+
+#define FREEPTR_TRACE(fp, routine, onoff) \
+  ODB_freeptr_trace(fp, #routine, __FILE__, __LINE__, onoff)
+
+#define STRDUP(s) ODB_strdup_mem(s,  #s, __FILE__, __LINE__)
+
+#endif
+
+/* string equalities (moved here from odb.h) */
+
+#define strequ(s1,s2)     ((const void *)(s1) && (const void *)(s2) && *(s1) == *(s2) && strcmp(s1,s2) == 0)
+#define strnequ(s1,s2,n)  ((const void *)(s1) && (const void *)(s2) && *(s1) == *(s2) && strncmp(s1,s2,n) == 0)
+
+#ifndef odbA2aDIFF
+#define odbA2aDIFF 32
+#endif
+
+#define strcaseequ(s1,s2)     ((const void *)(s1) && (const void *)(s2) && \
+(*(s1) == *(s2) || *(s1) == (*(s2)) + odbA2aDIFF || *(s2) == (*(s1)) + odbA2aDIFF) && \
+ strcasecmp(s1,s2) == 0)
+#define strncaseequ(s1,s2,n)  ((const void *)(s1) && (const void *)(s2) && \
+(*(s1) == *(s2) || *(s1) == (*(s2)) + odbA2aDIFF || *(s2) == (*(s1)) + odbA2aDIFF) && \
+ strncasecmp(s1,s2,n) == 0)
+
+/* For convenience & consistency */
+
+#define CALLOC2  CALLOC
+#define ALLOC2   ALLOC
+#define REALLOC2 REALLOC
+
+/* Fortran to C character string passing */
+
+#define DECL_FTN_CHAR(x)  char *p_##x = NULL
+
+/* Keep ALLOCX's outside {}'s since may be an alloca() */
+
+#define ALLOC_FTN_CHAR(x) \
+  ALLOCX(p_##x, x##_len + 1); \
+  { register int _plen = x##_len; /* try not to alter the value of x##_len */ \
+  /* skip leading blanks, if any */ \
+  while ((_plen > 0) && (*x == ' ')) { ++x; --_plen; } \
+  /* copy string */ \
+  memcpy(p_##x, x, _plen); \
+  p_##x[_plen] = '\0'; \
+  /* strip trailing blanks, if any */ \
+  while (_plen-- > 0) { if (p_##x[_plen] != ' ' && p_##x[_plen] != '\0') break; } \
+  p_##x[++_plen] = '\0'; }
+
+#define ALLOC_OUTPUT_FTN_CHAR(x) ALLOCX(p_##x, x##_len + 1)
+
+#define COPY_2_FTN_CHAR(x) if ((p_##x) && (x)) { \
+  int _plen = strlen(p_##x); \
+  _plen = MIN(x##_len, _plen); \
+  memcpy(x, p_##x, _plen); \
+  if (x##_len > _plen) memset(&x[_plen], ' ', x##_len - _plen); }
+
+#define COPY_2_FTN_CHARv2(x,len) if ((p_##x) && (x)) { \
+  int _plen = MIN(x##_len, len); \
+  memcpy(x, p_##x, _plen); \
+  if (x##_len > _plen) memset(&x[_plen], ' ', x##_len - _plen); }
+
+#define FREE_FTN_CHAR(x)  FREEX(p_##x)
+
+#ifdef USE_CTRIM
+/* Faster macros ; assume FTN input strings are char(0) terminated 
+   Assume that -DUSE_CTRIM is used both in C and Fortran90 compilations */
+
+#ifdef SV2 
+  /* CGG 03/09 */ 
+#define ALLOC_FASTFTN_CHAR(x) { \
+  int _plen = x##_len;  /* try not to alter the value of x##_len */ \
+  p_##x = (char *)x; \
+  if (_plen > 0 && p_##x[_plen-1] == '\0') --_plen; \
+}
+#define FREE_FASTFTN_CHAR(x) FREE_FTN_CHAR(x)
+#else
+  /* The following is used */
+#define ALLOC_FASTFTN_CHAR(x) /* do nothing */
+#define FREE_FASTFTN_CHAR(x)  /* do nothing */
+#endif
+
+
+#else
+
+#define ALLOC_FASTFTN_CHAR(x) ALLOC_FTN_CHAR(x)
+#define FREE_FASTFTN_CHAR(x)  FREE_FTN_CHAR(x)
+
+#endif
+
+#endif
+
+
+
diff --git a/odb/src/include/bits.h b/odb/src/include/bits.h
new file mode 100644
index 0000000..fb6dd6e
--- /dev/null
+++ b/odb/src/include/bits.h
@@ -0,0 +1,95 @@
+#ifndef _BITS_H_
+#define _BITS_H_
+
+/* bits.h */
+
+/* Fortran callables */
+
+extern void
+codbit_get_count_(const void *data,
+		  const int *nbits,
+		  const int *nbw,
+		  int *rc);
+
+extern void 
+codbit_getidx_(const void *data, 
+	       const int *nbits,
+	       const int *nbw,
+	       unsigned int idx[], /* bit numbers [0 .. *nbits - 1] that are set to 1 */
+	       const int *nidx, /* length of idx[], potentially >= *nbits */
+	       int *rc); /* no. of bits set to 1 */
+
+extern void
+codbit_get_(const void *data, 
+	    const int *nbits,
+	    const int *nbw,
+	    const int *bitno, /* C-indexing : between [0 .. *nbits - 1] */
+	    int *rc);
+
+extern void
+codbit_set_(void *data, 
+	    const int *nbits,
+	    const int *nbw,
+	    const int *bitno1,
+	    const int *bitno2); /* C-indexing : between [0 .. *nbits - 1] */
+
+extern void 
+codbit_setidx_(void *data, 
+	       const int *nbits,
+	       const int *nbw,
+	       const unsigned int idx[], /* bit numbers [0 .. *nbits - 1] that will be set to 1 */
+	       const int *nidx); /* length of idx[], potentially >= *nbits */
+
+extern void
+codbit_unset_(void *data, 
+	      const int *nbits,
+	      const int *nbw,
+	      const int *bitno1,
+	      const int *bitno2); /* C-indexing : between [0 .. *nbits - 1] */
+
+extern void 
+codbit_unsetidx_(void *data, 
+		 const int *nbits,
+		 const int *nbw,
+		 const unsigned int idx[], /* bit numbers [0 .. *nbits - 1] that will be set to 0 */
+		 const int *nidx); /* length of idx[], potentially >= *nbits */
+
+extern void 
+codbit_and_(void *out_data, 
+	    const void *in_data,
+	    const int *nbits,
+	    const int *nbw);
+
+extern void 
+codbit_or_(void *out_data, 
+	   const void *in_data,
+	   const int *nbits,
+	   const int *nbw);
+
+/* Non-Fortran callables */
+
+extern int
+ODBIT_get_count(const void *data, int nbits, int nbw);
+
+extern unsigned int *
+ODBIT_getidx(const void *data, int nbits, int nbw, int *idxlen);
+
+extern void
+ODBIT_free(void *v);
+
+extern char *
+ODBIT_getmap(const void *data, int nbits, int nbw, char *s);
+
+extern int
+ODBIT_get(const void *data, int nbits, int nbw, int bitno);
+
+extern int
+ODBIT_test(const void *data, int nbits, int nbw, int bitno1, int bitno2);
+
+extern void
+ODBIT_set(void *data, int nbits, int nbw, int bitno1, int bitno2);
+
+extern void
+ODBIT_unset(void *data, int nbits, int nbw, int bitno1, int bitno2);
+
+#endif
diff --git a/odb/src/include/cdrhook.h b/odb/src/include/cdrhook.h
new file mode 100644
index 0000000..e1e7ea8
--- /dev/null
+++ b/odb/src/include/cdrhook.h
@@ -0,0 +1,51 @@
+#ifndef _CDRHOOK_H_
+#define _CDRHOOK_H_
+
+/* This is near-replica of ifsaux/include/drhook.h for use (mainly) by generated C-codes.
+   Keep macros consistent with the original !! */
+
+extern int drhook_lhook;
+
+/**** C-interface to Dr.Hook ****/
+
+extern void
+Dr_Hook(const char *name, int option, double *handle, 
+        const char *filename, int sizeinfo,
+        int name_len, int filename_len);
+
+#define DRHOOK_START_RECUR(name,recur) \
+  static const char *drhook_name = #name; \
+  static const int drhook_name_len = sizeof(#name) - 1; /* Compile time eval */ \
+  static const char *drhook_filename = __FILE__; \
+  static const int drhook_filename_len = sizeof(__FILE__) - 1; /* Compile time eval */ \
+  double zhook_handle; \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 0, &zhook_handle, \
+                                      drhook_filename, 0, \
+                                      drhook_name_len, drhook_filename_len); {
+
+#define DRHOOK_START(name) DRHOOK_START_RECUR(name,0)
+
+#define DRHOOK_START_BY_STRING_RECUR(name, recur) \
+  static const char *drhook_name = name; \
+  static const int drhook_name_len = sizeof(name) - 1; /* Compile time eval */ \
+  static const char *drhook_filename = __FILE__; \
+  static const int drhook_filename_len = sizeof(__FILE__) - 1; /* Compile time eval */ \
+  double zhook_handle; \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 0, &zhook_handle, \
+                                      drhook_filename, 0, \
+                                      drhook_name_len, drhook_filename_len); {
+
+#define DRHOOK_START_BY_STRING(name) DRHOOK_START_BY_STRING_RECUR(name,0)
+
+#define DRHOOK_RETURN_RECUR(sizeinfo,recur) \
+  if (!recur && drhook_lhook) Dr_Hook(drhook_name, 1, &zhook_handle, \
+                                      drhook_filename, sizeinfo, \
+                                      drhook_name_len, drhook_filename_len)
+
+#define DRHOOK_RETURN(sizeinfo) DRHOOK_RETURN_RECUR(sizeinfo,0)
+
+#define DRHOOK_END_RECUR(sizeinfo,recur) ; } DRHOOK_RETURN_RECUR(sizeinfo,recur)
+
+#define DRHOOK_END(sizeinfo) DRHOOK_END_RECUR(sizeinfo,0) 
+
+#endif  /* _CDRHOOK_H_ */
diff --git a/odb/src/include/cma_read.h b/odb/src/include/cma_read.h
new file mode 100644
index 0000000..9958677
--- /dev/null
+++ b/odb/src/include/cma_read.h
@@ -0,0 +1,177 @@
+#if TYPE_ID == real_8
+#include "pcma_extern.h"
+#endif
+
+#include "swapbytes.h"
+#include "cdrhook.h"
+
+FORTRAN_CALL void 
+FUNC_NAME(const integer4 *unit,
+	  DATA_TYPE       pbuf[],
+	  const integer4 *kbufsize,
+	  integer4       *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  int bin = IOBIN(*unit);
+  int sz = 0;
+  DRHOOK_START_BY_STRING(FUNC_STR);
+
+  if (iostuff_debug) 
+    fprintf(stderr,"%s(%d,w=%d) ", FUNC_STR, *unit, *kbufsize);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      if (!pcmaio->io.read_only) {
+	/* Error : File was open for write only */
+	rc = -3;
+	goto finish;
+      }
+
+      if (bin >= 0 && bin < pcmaio->io.numbins) {
+	IObin *pbin = &pcmaio->io.bin[bin];
+	FILE *fp = pbin->fp;
+	int bufsize = *kbufsize;
+
+	/* fread() */
+	if (iostuff_stat) IOtimes(NULL);
+#if TYPE_ID == real_8
+	if ((pcmaio->io.scheme & internal) == internal) {
+	  int can_swp_data = pcmaio->io.req_byteswap; /* in absence any better information ;-( */
+
+	  if (bufsize == 1 && pcmaio->chunk == 0) {
+	    /* A frequently used special case where only 
+	       the report length is requested */
+	    int method, chunk, msgbytes;
+	    double nmdi, rmdi;
+	    int new_version = 0;
+	    int swp = 0;
+
+	    rc = upcma_hdr(fp, &swp,
+			   pcmaio->hdr, 1,
+			   &method, &chunk, &msgbytes,
+			   &nmdi, &rmdi,
+			   &new_version);
+
+	    if ((!new_version && rc == HDRLEN) ||
+		( new_version && rc == PCMA_HDRLEN)) {
+	      pcmaio->io.packmethod = method;
+	      pcmaio->chunk = chunk;
+	      pbuf[0] = chunk;
+	      rc = 1;
+	    }
+	  }
+	  else if (pcmaio->chunk > 0) {
+	    int bytes_in, bytes_out;
+	    int chunk = pcmaio->chunk;
+	    real8 *tmpbuf = NULL;
+
+	    ALLOC(tmpbuf, chunk);
+	    cma_set_lock(1);
+	    rc = upcma(can_swp_data, fp, NULL,
+		       NULL, 0, 1,
+		       tmpbuf, chunk,
+		       pcmaio->hdr,
+		       NULL,
+		       &bytes_in, &bytes_out);
+	    cma_unset_lock(1);
+	    sz += bytes_in;
+	    if (rc >= 0) {
+	      rc = MIN(chunk - 1, bufsize);
+	      IOrcopy(pbuf, &tmpbuf[1], rc);
+	    }
+    	    FREE(tmpbuf);
+
+	    pcmaio->chunk = 0;
+	  }
+	  else {
+	    int bytes_in, bytes_out;
+	    cma_set_lock(1);
+	    rc = upcma(can_swp_data, fp, NULL,
+		       NULL, 0, 1,
+		       pbuf, bufsize,
+		       NULL,
+		       NULL,
+		       &bytes_in, &bytes_out);
+	    cma_unset_lock(1);
+	    sz += bytes_in;
+	    if (rc >= 0) {
+	      rc = bytes_out/sizeof(DATA_TYPE);
+	    }
+	  }
+	}
+	else {
+	  rc = fread(pbuf, sizeof(DATA_TYPE), bufsize, fp);
+	  if (rc > 0 && pcmaio->io.req_byteswap) swap8bytes_(pbuf, &rc); /* double */
+	  if (rc > 0) sz += rc * sizeof(DATA_TYPE);
+	}
+#else
+	rc = fread(pbuf, sizeof(DATA_TYPE), bufsize, fp);
+	if (rc > 0) sz += rc * sizeof(DATA_TYPE);
+#endif
+#if (TYPE_ID == integer_4) || (TYPE_ID == real_4)
+	if (rc > 0 && pcmaio->io.req_byteswap) swap4bytes_(pbuf, &rc); /* int */
+#endif
+	if (iostuff_stat) IOtimes(&pbin->stat.t);
+	
+	if (iostuff_debug) fprintf(stderr," : fread(%d:%s)",rc,DATA_STR);
+	
+	if (rc == 0 && feof(fp)) {
+	  /* EOF */
+	  rc = -1;
+	  goto finish;
+	}
+
+	if (rc < 0 || ferror(fp)) {
+	  /* Error while reading data */
+	  rc = -6;
+	  goto finish;
+	}
+
+	pbin->filepos += rc * sizeof(DATA_TYPE);      
+	
+	if (iostuff_stat) {
+	  pbin->stat.bytes += rc * sizeof(DATA_TYPE);
+	  pbin->stat.num_trans++;
+	}
+#if TYPE_ID == real_8
+	{
+	  static volatile Boolean check_it = true;
+	  cma_set_lock(1);
+	  if (check_it) {
+	    Boolean tsek = true;
+	    char *filename = pbin->true_name;
+	    CMA_flpchecker(FUNC_STR, 1, filename,
+			   pbuf, pbin->filepos, &rc,
+			   &tsek);
+	    check_it = tsek;
+	  }
+	  cma_unset_lock(1);
+	}
+#endif
+      }
+      else {
+	/* Error : Attempt to use an invalid bin */
+	rc = -5;
+      }
+    }
+    else {
+      /* Error : File was not in use */
+      rc = -4;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  DRHOOK_END(sz);
+}
diff --git a/odb/src/include/cma_seek.h b/odb/src/include/cma_seek.h
new file mode 100644
index 0000000..329f67d
--- /dev/null
+++ b/odb/src/include/cma_seek.h
@@ -0,0 +1,103 @@
+#include "privpub.h"
+#include "cdrhook.h"
+
+FORTRAN_CALL void 
+FUNC_NAME(const integer4 *unit,
+	  const integer4 *koffset, /* 1 unit == sizeof(DATA_TYPE) */
+	  const integer4 *kwhence, /* 0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END */
+	  integer4       *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  int bin = IOBIN(*unit);
+  int sz = 0;
+  DRHOOK_START_BY_STRING(FUNC_STR);
+
+  if (iostuff_debug) 
+    fprintf(stderr,"%s(%d,off=%d,wh=%d) ", FUNC_STR, *unit, *koffset, *kwhence);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      if ((pcmaio->io.scheme & external) == external) {
+	/* Handle special case by reading data in */
+	if (*koffset >= 0 && *kwhence == 1 &&
+	    bin >= 0 && bin < pcmaio->io.numbins) {
+	  IObin *pbin = &pcmaio->io.bin[bin];
+	  int buflen = pbin->readbuf.len;
+	  int len = (*koffset) * sizeof(DATA_TYPE); 
+	  int nread;
+	  byte1 *buf = NULL;
+	  buflen = MAX(buflen, IO_BUFSIZE_DEFAULT); /* IO_BUFSIZE_DEFAULT from privpub.h */
+	  ALLOC(buf, buflen);
+	  nread = 0;
+	  while (nread < len) {
+	    int n = MIN(buflen, len - nread);
+	    cma_readb_(unit, buf, &n, &rc);
+	    if (rc != n) break; /* Error */
+	    nread += n;
+	  }
+	  sz = nread;
+	  if (nread == len) rc = 0; /* All was okay from "simulated" fseek() point of view */
+	  else rc = -7;
+	  FREE(buf);
+	}
+	else {
+	  /* Error : File was opened via pipe and seek was not from current position & forward */
+	  rc = -1;
+	}
+	goto finish;
+      }
+
+      if (bin >= 0 && bin < pcmaio->io.numbins) {
+	IObin *pbin = &pcmaio->io.bin[bin];
+	FILE *fp = pbin->fp;
+	int offset = (*koffset) * sizeof(DATA_TYPE);
+	int whence = *kwhence;
+	int oldpos = pbin->filepos;
+	int newpos;
+
+	/* fseek() */
+	if (iostuff_stat) IOtimes(NULL);
+	rc = fseek(fp, offset, whence);
+	if (iostuff_stat) IOtimes(&pbin->stat.t);
+	
+	if (iostuff_debug) fprintf(stderr," : fseek(%d:%s)",rc,DATA_STR);
+
+	if (rc < 0 || ferror(fp)) {
+	  /* Error while seeking */
+	  rc = -6;
+	  goto finish;
+	}
+
+	newpos = pbin->filepos = ftell(fp);
+	sz = ABS(newpos - oldpos);
+	
+	if (iostuff_stat) {
+	  pbin->stat.num_trans++;
+	}
+      }
+      else {
+	/* Error : Attempt to use an invalid bin */
+	rc = -5;
+      }
+    }
+    else {
+      /* Error : File was not in use */
+      rc = -4;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit  */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  DRHOOK_END(sz);
+}
diff --git a/odb/src/include/cma_write.h b/odb/src/include/cma_write.h
new file mode 100644
index 0000000..979589f
--- /dev/null
+++ b/odb/src/include/cma_write.h
@@ -0,0 +1,120 @@
+#if TYPE_ID == real_8
+#include "pcma_extern.h"
+#endif
+
+#include "cdrhook.h"
+
+FORTRAN_CALL void 
+FUNC_NAME(const integer4 *unit,
+	  const DATA_TYPE pbuf[],
+	  const integer4 *kbufsize,
+	  integer4       *retcode)
+{
+  int rc = 0;
+  int index = IOINDEX(*unit);
+  int bin = IOBIN(*unit);
+  int sz = 0;
+  DRHOOK_START_BY_STRING(FUNC_STR);
+
+  if (iostuff_debug) fprintf(stderr,"%s(%d,w=%d) ", FUNC_STR, *unit, *kbufsize);
+
+  if (index >= 0 && index < CMA_get_MAXCMAIO()) {
+    int tid = get_thread_id_();
+    IOcma *pcmaio = &cmaio[tid][index];
+
+    if (pcmaio->io.is_inuse) {
+      if (pcmaio->io.read_only) {
+	/* Error : File was open for read only */
+	rc = -3;
+	goto finish;
+      }
+
+      if (bin >= 0 && bin < pcmaio->io.numbins) {
+	IObin *pbin = &pcmaio->io.bin[bin];
+	FILE *fp = pbin->fp;
+	int bufsize = *kbufsize;
+	
+	/* fwrite() */
+	if (iostuff_stat) IOtimes(NULL);
+#if TYPE_ID == real_8
+	{
+	  static volatile Boolean check_it = true;
+	  cma_set_lock(2);
+	  if (check_it) {
+	    Boolean tsek = true;
+	    char *filename = pbin->true_name;
+	    rc = bufsize;
+	    CMA_flpchecker(FUNC_STR, 2, filename,
+			   pbuf, pbin->filepos, &rc,
+			   &tsek);
+	    check_it = tsek;
+	    if (rc == -7) {
+	      /* Error : Invalid flp values were detected */
+	      goto finish;
+	    }
+	  }
+	  cma_unset_lock(2);
+	}
+
+	if ((pcmaio->io.scheme & internal) == internal) {
+	  int bytes_in, bytes_out;
+
+	  cma_set_lock(2);
+	  rc = pcma(NULL, fp,
+		    pcmaio->io.packmethod,
+		    pbuf, bufsize,
+		    NULL,
+		    &bytes_in, &bytes_out);	
+	  cma_unset_lock(2);
+
+	  sz += bytes_out;
+	  if (rc >= 0) {
+	    rc = bytes_in/sizeof(DATA_TYPE);
+	  }
+	}
+	else {
+	  rc = fwrite(pbuf, sizeof(DATA_TYPE), bufsize, fp);
+	  if (rc > 0) sz += rc * sizeof(DATA_TYPE);
+	}
+#else
+	rc = fwrite(pbuf, sizeof(DATA_TYPE), bufsize, fp);
+	if (rc > 0) sz += rc * sizeof(DATA_TYPE);
+#endif
+	if (iostuff_stat) IOtimes(&pbin->stat.t);
+	
+	if (iostuff_debug) fprintf(stderr," : fwrite(%d:%s)",rc,DATA_STR);
+	
+	pbin->filepos += rc * sizeof(DATA_TYPE);
+	
+	if (iostuff_stat) {
+	  pbin->stat.bytes += rc * sizeof(DATA_TYPE);
+	  pbin->stat.num_trans++;
+	}
+	
+	if (rc != bufsize) {
+	  /* Error while writing data */
+	  rc = -1;
+	}
+      }  
+      else {
+	/* Error : Attempt to use an invalid bin */
+	rc = -5;
+      }
+     }
+    else {
+      /* Error : File was not in use */
+      rc = -4;
+    }
+  }
+  else {
+    /* Error : Invalid internal file unit */
+    rc = -2;
+  }
+
+ finish:
+
+  if (iostuff_debug) fprintf(stderr," : rc=%d\n",rc);
+
+  *retcode = rc;
+  DRHOOK_END(sz);
+}
diff --git a/odb/src/include/cmaio.h b/odb/src/include/cmaio.h
new file mode 100644
index 0000000..20d5975
--- /dev/null
+++ b/odb/src/include/cmaio.h
@@ -0,0 +1,295 @@
+#ifndef _CMAIO_H_
+#define _CMAIO_H_
+
+#include "privpub.h"
+
+#include "iostuff.h"
+#include "pcma_extern.h"
+
+#ifndef FORTRAN_CALL
+#define FORTRAN_CALL extern
+#endif
+
+/* ------------------ */
+
+typedef struct iocma_t {
+  IOstuff  io;
+  int      zinfolen;
+  real8   *zinfo;
+  int      ddr_read_counter;
+  integer4 numddrs;
+  integer4 lenddrs;
+  integer4 numobs;
+  integer4 maxreplen;
+  integer4 cmalen;
+  real8   *ddrs;
+  /* For delayed unpacking */
+  unsigned int  hdr[PCMA_HDRLEN];
+  int           chunk;
+} IOcma;
+
+extern IOcma **cmaio;
+extern int *cmaio_1stfree;
+extern int *cma_perror_flag; /* flags for thread-safe perror()'ing ; used to be handled via cma_perror() */
+
+FORTRAN_CALL void 
+cma_open_(integer4       *unit, 
+	  const char     *filename,
+	  const char     *mode,
+	  integer4       *retcode,	 
+	  /* Hidden arguments to Fortran-program */
+	  int             len_filename,
+	  int             len_mode);
+
+FORTRAN_CALL void 
+cma_attach_(integer4       *unit, 
+	    const char     *filename,
+	    const char     *mode,
+	    integer4       *retcode,
+	    /* Hidden arguments to Fortran-program */
+	    int             len_filename,
+	    int             len_mode);
+
+FORTRAN_CALL void 
+cma_detach_(const integer4 *unit, integer4 *retcode);
+
+FORTRAN_CALL void
+cma_read_(const integer4 *unit,
+	  real8           pbuf[],
+	  const integer4 *kbufsize,
+	  integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_write_(const integer4 *unit,
+	   const real8     pbuf[],
+	   const integer4 *kbufsize,
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_info_(const integer4 *unit, 
+	  integer4        info[],
+	  const integer4 *infolen,
+	  integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_close_(const integer4 *unit, integer4 *retcode);
+
+FORTRAN_CALL void 
+cma_debug_(const integer4 *toggle,
+	         integer4 *old_value);
+
+FORTRAN_CALL void 
+cma_stat_(const integer4 *ftn_unit,
+	  const integer4 *toggle, 
+   	        integer4 *old_value);
+
+FORTRAN_CALL void
+cma_get_report_(const integer4 *unit,
+		real8           pbuf[],
+		const integer4 *kbufsize,
+		integer4       *retcode);
+
+FORTRAN_CALL void
+cma_get_ddrs_(const integer4 *unit,
+	      real8           ddrs[],
+	      const integer4 *lenddrs,
+	      integer4       *retcode);
+
+FORTRAN_CALL void
+cma_wrapup_(integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_prt_stat_(const integer4 *ftn_unit, const integer4 *cma_unit, 
+	      const integer4 *binno,   const integer4 *numbins,
+	      const integer4 *fileno,
+	      const char     *str_open_time, const char *str_close_time,
+	      const char     *logical_name,  const char *true_name,
+	      const char     *pipecmd,       const char *cmd,
+              const integer4 *read_only, const integer4 *packmethod, const integer4 *blocksize,
+              const integer4 *numddrs,  const integer4 *lenddrs,
+              const integer4 *numobs,   const integer4 *maxreplen, const integer4 *cmalen,
+              const integer4 *filesize, const integer4 *filepos, const integer4 *blksize,
+              const integer4 *bytes,    const integer4 *num_trans,
+              const integer4 *readbuf_len,  const integer4 *readbuf_is_alloc,
+	      const integer4 *writebuf_len, const integer4 *writebuf_is_alloc,
+	      const integer4 *prealloc, const integer4 *extent,
+	      const integer4 *mrfs_flag,
+              const real8    *walltime, const real8 *xfer_speed,
+              const real8    *usercpu,  const real8 *syscpu,
+	      /* Hidden arguments to Fortran-program */
+	      int len_str_open_time, int len_str_close_time,
+	      int len_logical_name,  int len_true_name,
+	      int len_pipecmd,       int len_cmd
+	      );
+
+FORTRAN_CALL void 
+cma_rewind_(integer4 *unit,
+	    integer4 *retcode);
+
+FORTRAN_CALL void 
+cma_seek_(const integer4 *unit,
+	  const integer4 *koffset, /* 1 unit == sizeof(real8) */
+	  const integer4 *kwhence, /* 0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END */
+	  integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_seekb_(const integer4 *unit,
+	   const integer4 *koffset, /* 1 unit == sizeof(byte1) */
+	   const integer4 *kwhence, /* 0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END */
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_seeki_(const integer4 *unit,
+	   const integer4 *koffset, /* 1 unit == sizeof(integer4) */
+	   const integer4 *kwhence, /* 0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END */
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_seekf_(const integer4 *unit,
+	   const integer4 *koffset, /* 1 unit == sizeof(integer4) */
+	   const integer4 *kwhence, /* 0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END */
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_readi_(const integer4 *unit,
+	   integer4        pbuf[],
+	   const integer4 *kbufsize,
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_readf_(const integer4 *unit,
+	   real4           pbuf[],
+	   const integer4 *kbufsize,
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_readb_(const integer4 *unit,
+	   byte1           pbuf[],
+	   const integer4 *kbufsize,
+	   integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_readc_(const integer4 *unit,
+	   byte1           s[],
+	   integer4       *retcode
+	    /* Hidden arguments */
+	   , int slen);
+
+FORTRAN_CALL void 
+cma_writei_(const integer4 *unit,
+	    const integer4  pbuf[],
+	    const integer4 *kbufsize,
+	    integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_writef_(const integer4 *unit,
+	    const real4     pbuf[],
+	    const integer4 *kbufsize,
+	    integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_writeb_(const integer4 *unit,
+	    const byte1     pbuf[],
+	    const integer4 *kbufsize,
+	    integer4       *retcode);
+
+FORTRAN_CALL void 
+cma_writec_(const integer4 *unit,
+	    const byte1     s[],
+	    integer4       *retcode
+	    /* Hidden arguments */
+	    , int slen);
+
+FORTRAN_CALL void
+cma_bin_info_(const integer4 *unit,
+	      integer4       *numbins,
+	      integer4       *binfactor);
+
+FORTRAN_CALL void 
+cma_bin_file_(const integer4 *unit,
+              char *filename,
+              integer4 *retcode,
+	      /* Hidden argument to Fortran-program */
+              int len_filename);
+
+FORTRAN_CALL void 
+cma_is_packed_(const integer4 *unit,
+	       integer4 *retcode);
+
+FORTRAN_CALL void 
+cma_on_mrfs_(const integer4 *unit,
+	     integer4 *retcode);
+
+FORTRAN_CALL void 
+cma_get_concat_(const integer4 *unit,
+		integer4 *retcode);
+
+FORTRAN_CALL void 
+cma_get_concat_byname_(const char *filename,
+		       integer4 *retcode,
+		       /* Hidden arguments to Fortran-program */
+		       int len_filename);
+
+FORTRAN_CALL void
+cma_flpcheck_(const double d[],
+	      const   int *nd,
+	              int  flag[],
+	      const   int *nf,
+	              int *rinf,
+	              int *rtiny,
+	              int *rnan);
+
+FORTRAN_CALL void
+cma_get_byteswap_(const integer4 *unit, integer4 *retcode);
+
+FORTRAN_CALL void
+cma_set_byteswap_(const integer4 *unit, 
+		  const integer4 *toggle,
+		  integer4 *retcode);
+
+FORTRAN_CALL void
+cma_set_perror_(const integer4 *onoff, integer4 *retcode);
+
+FORTRAN_CALL void
+cma_get_perror_(integer4 *retcode);
+
+FORTRAN_CALL void
+cma_is_externally_compressed_(const char *filename,
+			      const char *mode,
+			      integer4 *retcode,
+			      /* Hidden argument to Fortran-program */
+			      int len_filename,
+			      int len_mode);
+
+void
+cma_filesize_(const char *filename,
+	      integer4 *retcode,
+	      int len_filename);
+
+/* Not Fortran accessible */
+
+#define MAX_CMAIO_LOCKS 3
+
+void cma_set_lock(int lockno);   /* lockno must be [0 .. MAX_CMAIO_LOCKS-1] */
+void cma_unset_lock(int lockno); /* lockno must be [0 .. MAX_CMAIO_LOCKS-1] */
+
+int
+CMA_fetch_ddrs(const integer4 *unit,
+	       IOcma *pcmaio);
+
+FILE *
+CMA_get_fp(const integer4 *unit);
+
+int
+CMA_get_MAXCMAIO(void);
+
+void
+CMA_flpchecker(const char *name,
+	       int mode, /* 1=read, 2=write */
+	       const char *filename,
+	       const double d[], 
+	       int filepos, 
+	       int *retcode,
+	       Boolean *check_it);
+
+#endif
diff --git a/odb/src/include/codb.h b/odb/src/include/codb.h
new file mode 100644
index 0000000..0980562
--- /dev/null
+++ b/odb/src/include/codb.h
@@ -0,0 +1,549 @@
+#if REAL_VERSION == 8
+
+#define GEN_TYPE       double
+#define GEN_TYPE_CAST  GEN_TYPE
+#define GEN_GET        codb_dget_
+#define GEN_PUT        codb_dput_
+#define GEN_GETFUNC    dget
+#define GEN_PUTFUNC    dput
+#define GEN_GETNAME    "codb_dget_"
+#define GEN_PUTNAME    "codb_dput_"
+#define GEN_BYTES      8
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(REAL_VERSION)
+
+PUBLIC void
+GEN_GET(const int *handle,
+	const int *poolno,
+	const char *dataname,
+	GEN_TYPE d[],
+	const int *doffset,
+	const int *ldimd,
+	const int *nrows,
+	const int *ncols,
+	const int  flag[],
+	const int *procid,
+	const int *istart,
+	const int *ilimit,
+	const int *inform_progress,
+	const int *using_it,
+	int *retcode,
+	/* Hidden arguments */
+	int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int Pbar = *inform_progress; /* whether to invoke codb_progress_bar_() or not */
+  int ProcID = *procid;
+  boolean AnyPool = (Poolno == -1);
+  int LdimD = *ldimd;
+  int Doffset = *doffset;
+  int Nrows = *nrows;
+  int Ncols = *ncols;
+  int Neff_rows = 0;
+  int Neff_cols = 0;
+  int Nrows_total = 0;
+  int Nrows_polled = 0;
+  int k1 = Doffset;
+  int Start = *istart;
+  int HighWaterMark = *ilimit;
+  int Limit = *ilimit;
+#if 0
+  int globprt = 0;
+#endif
+  POOLREG_DEF;
+  int it = USING_IT;
+  static int myproc = 0;
+  DECL_FTN_CHAR(dataname);
+  static char *env = NULL;
+  static int first_time = 1;
+  static int do_debug = 0;
+  int windowing = (ProcID <= 0);
+  DRHOOK_START_BY_STRING(GEN_GETNAME);
+
+  if (first_time) {
+    env = getenv("ODB_DEBUG_CODB_H");
+    if (env) {
+      int value = atoi(env);
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      if (value == -1 || value == myproc) do_debug = 1;
+    }
+    first_time = 0;
+  }
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (do_debug) {
+    printf("\n>>>%s(view=%s, myproc=%d, Poolno=%d,"
+	   " ProcID=%d, LdimD=%d, Doffset=%d, Nrows=%d, Ncols=%d, Start=%d, Limit=%d)\n",
+	   GEN_GETNAME, p_dataname, myproc, Poolno,
+	   ProcID, LdimD, Doffset, Nrows, Ncols,
+	   Start, Limit);
+    fflush(stdout);
+  }
+
+  if (LdimD - Doffset < Nrows) { rc = -3; goto finish; }
+
+  POOLREG_FOR {
+    boolean pf_found = 0;
+
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	int GetInterMed = pf->tmp ? 1 : 0;
+	void *data = pf->data;
+	int nr, nc, noffset;
+	int pool = p->poolno;
+	int row_offset = 0;
+	int nr_orig;
+	extern double util_walltime_();
+	double zwall[2];
+	
+	if (Pbar) zwall[0] = util_walltime_();
+
+	pf_found = 1;
+
+	if (!GetInterMed) {
+	  PFCOM->dim(data, &nr, &nc, &noffset, ProcID);
+	}
+	else {
+	  nr = pf->tmp->nr;
+	  nc = pf->tmp->nc;
+	  noffset = 0;
+	}
+	nr_orig = nr;
+
+	if (do_debug) {
+	  printf("<0>%s(myproc=%d): pf=%p, data=%p, d=%p, pool=%d :"
+		 " k1=%d, noffset=%d, Nrows=%d, nc=%d,"
+		 " nr_orig=%d, Start=%d, Limit=%d, Nrows_polled=%d, GetInterMed=%d\n",
+		 p_dataname, myproc, pf, data, d, pool, 
+		 k1, noffset, Nrows, nc,
+		 nr_orig, Start, Limit, Nrows_polled, GetInterMed);
+	  fflush(stdout);
+	}
+
+	if (windowing && !GetInterMed) {
+	  /* (start,limit)-windowing allowed only for non-parallel (i.e. non-shuffle/non-replicated) views */
+	  if (Start >= Nrows_polled && Start < Nrows_polled + nr_orig) {
+	    row_offset = Start - Nrows_polled;
+	    nr = MIN(nr - row_offset, Limit);
+	    Start += nr;
+	    Limit -= nr;
+	    Nrows_polled += nr_orig;
+	  }
+	  else {
+	    Nrows_polled += nr_orig;
+	    goto next_pool;
+	  }
+	}
+
+	if (Ncols < nc) nc = Ncols;
+
+	Nrows -= nr;
+
+	if (do_debug) {
+	  printf("<1>%s(myproc=%d): pf=%p, data=%p, d=%p, pool=%d :"
+		 " k1=%d, noffset=%d, Nrows=%d, nc=%d,"
+		 " nr=%d, Start=%d, Limit=%d, Nrows_polled=%d, row_offset=%d\n",
+		 p_dataname, myproc, pf, data, d, pool,
+		 k1, noffset, Nrows, nc,
+		 nr, Start, Limit, Nrows_polled, row_offset);
+	  fflush(stdout);
+	}
+
+	if (Nrows < 0) { rc = -2; goto finish; }
+
+	if (nr > LdimD) { rc = -5; goto finish; }
+	
+	if (nr > 0) {
+	  int k2 = k1 + nr;
+
+	  if (do_debug) {
+	    printf("<2>%s(myproc=%d): k1=%d, k2=%d, nr=%d, nc=%d ; LdimD=%d, LdimD + k1=%d ; getfunc()=%p\n",
+		   p_dataname, myproc, k1, k2, nr, nc, LdimD, LdimD + k1, PFCOM->GEN_GETFUNC);
+	    fflush(stdout);
+	  }
+
+	  if (GetInterMed) { 
+	    int jc;
+	    for (jc=0; jc<nc; jc++) {
+	      int jr;
+	      const double *din = pf->tmp->d[jc];
+	      GEN_TYPE *dout = (GEN_TYPE_CAST *)&d[LdimD + jc*LdimD + k1];
+	      for (jr=0; jr<nr; jr++) dout[jr] = din[jr];
+	    }
+	    rc = nr;
+	  }
+	  else {
+	    rc = PFCOM->GEN_GETFUNC(data, (GEN_TYPE_CAST *)&d[LdimD + k1], 
+				    LdimD, nr, nc, 
+				    ProcID, flag, row_offset);
+
+	    if (rc == nr && PFCOM->has_usddothash && PFCOM->tags) {
+	      /* Resolve "$<parent_table>.<child_table>" -variables */
+	      int jc;
+	      for (jc=0; jc<nc; jc++) {
+		if (FLAG_FETCH(flag[jc])) {
+		  const ODB_Tags *tag = &PFCOM->tags[jc];
+		  if (tag && tag->is_usddothash && 
+		      tag->name && *tag->name == 'F') {
+		    char *s = STRDUP(tag->name);
+		    char *name = s;
+		    char *p = strchr(s,'$');
+		    if (p) name = p;
+		    p = strchr(name,'#');
+		    if (p) p[1] = '\0';
+		    (void) ODB_dynfill(name,
+				       data,
+				       PFCOM->getindex,
+				       &d[LdimD + jc*LdimD], LdimD,
+				       k1, k1+nr, 0);
+		    FREE(s);
+		  } /* if (tag && tag->is_usddothash) */
+		} /* if (FLAG_FETCH(flag[jc])) */
+	      } /* for (jc=0; jc<nc; jc++) */
+	    }
+	  }
+
+	  if (rc != nr) {
+	    rc = -1;
+	    goto finish;
+	  }
+	  else {
+	    const int offset = 0;
+	    int kk1=0, kk2=nr;
+
+	    noffset += row_offset; /* For (start,limit) "ODB_gets" gives the correct dbidx */
+
+	    codb_put_control_word_(&d[k1], 
+				   &kk1, 
+				   &kk2, 
+				   &offset, 
+				   &pool, 
+				   &noffset);
+
+#if 0
+	    if (do_debug && ProcID > 0) {
+	      int j, jc;
+	      globprt = 1;
+	      printf("<sub>: j = [k1=%d .. k2=%d) : (pool#%d)\n",k1,k2,pool);
+	      for (j=k1; j<k2; j++) {
+		const int x[4] = { 0, 1, 0, 0 };
+		int poolno = 0, rownum = 0;
+		double dd = d[LdimD * 0 + j];
+		codb_get_poolnos_(&dd, &x[0], &x[1], &x[2], &poolno);
+		codb_get_rownum_(&dd, &x[0], &x[1], &x[2],&x[3], &rownum);
+		printf("<sub>: %d) [%5d:%12d]",j, poolno, rownum);
+		for (jc=1; jc<=nc; jc++) {
+		  printf(" %25.14g", d[LdimD * jc + j]);
+		}
+		printf("\n");
+	      }
+	      fflush(stdout);
+	    }
+#endif
+
+	  }
+	  
+	  Nrows_total += rc;
+	  k1 += rc;
+
+	  if (do_debug) {
+	    printf("<3>%s(myproc=%d): Nrows_total=%d, Limit=%d, k1=%d, rc=%d, nr=%d\n",
+		   p_dataname, myproc, Nrows_total, Limit, k1, rc, nr);
+	    fflush(stdout);
+	  }
+
+	  if (Pbar) {
+	    double wtime;
+	    zwall[1] = util_walltime_();
+	    wtime = zwall[1] - zwall[0];
+	    codb_progress_bar_(NULL,
+			       p_dataname,
+			       &p->poolno,
+			       NULL,
+			       &rc,
+			       NULL,
+			       &wtime,
+			       NULL,
+			       strlen(p_dataname));
+	  }
+	  
+	} /* if (nr > 0) */
+      } /* if (pf) */
+    } /* if (MATCHING) */
+
+  next_pool:
+    if (pf_found && do_debug) {
+      int pool = p->poolno;
+      printf("<4>%s(myproc=%d): pool=%d : Nrows_total=%d, Limit=%d, HighWaterMark=%d\n",
+	     p_dataname, myproc, pool, Nrows_total, Limit, HighWaterMark);
+      fflush(stdout);
+    }
+    if (Nrows_total >= HighWaterMark) break;
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  rc = Nrows_total;
+
+ finish:
+  if (do_debug) {
+    printf("<<<%s(view=%s, myproc=%d, Poolno=%d, ProcID=%d, LdimD=%d, Doffset=%d, Nrows=%d, Ncols=%d, rc=%d)\n",
+	   GEN_GETNAME, p_dataname, myproc, Poolno, ProcID, LdimD, Doffset, Nrows, Ncols, rc);
+    fflush(stdout);
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = rc;
+
+#if 0
+  if (globprt && rc > 0) {
+    int j, jc;
+    int nc = Ncols;
+    int k2 = Nrows_total;
+    k1 = Doffset;
+    printf("<all>: j = [k1=Doffset=%d .. k2=Nrows_total=%d) :\n",k1,k2);
+    for (j=k1; j<k2; j++) {
+      const int x[4] = { 0, 1, 0, 0 };
+      int poolno = 0, rownum = 0;
+      double dd = d[LdimD * 0 + j];
+      codb_get_poolnos_(&dd, &x[0], &x[1], &x[2], &poolno);
+      codb_get_rownum_(&dd, &x[0], &x[1], &x[2],&x[3], &rownum);
+      printf("<all>: %d) [%5d:%12d]",j, poolno, rownum);
+      for (jc=1; jc<=nc; jc++) {
+	printf(" %25.14g", d[LdimD * jc + j]);
+      }
+      printf("\n");
+    }
+    fflush(stdout);
+  }
+#endif
+
+  if (drhook_lhook && rc >= 0) {
+    int jf;
+    Neff_rows = rc;
+    for (jf=0; jf<Ncols; jf++) {
+      if (flag[jf] & 0x1) Neff_cols++;
+    }
+  }
+  DRHOOK_END(Neff_rows * Neff_cols * GEN_BYTES);
+}
+
+
+PUBLIC void
+GEN_PUT(const int *handle,
+	const int  *poolno,
+	const char *dataname,
+	const GEN_TYPE d[],
+	const int *doffset,
+	const int *ldimd,
+	const int *nrows,
+	const int *ncols,
+	const int  flag[],
+	const int *procid,
+	const int *fill_intermed,
+	const int *using_it,
+	int *retcode,
+	/* Hidden arguments */
+	int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int ProcID = *procid;
+  boolean AnyPool = (Poolno == -1);
+  int LdimD = *ldimd;
+  int Doffset = *doffset;
+  int Nrows_in = *nrows;
+  int Nrows = *nrows;
+  int Ncols_in = *ncols;
+  int Ncols = *ncols;
+  int Neff_rows = 0;
+  int Neff_cols = 0;
+  int Nrows_total = 0;
+  int k1 = Doffset;
+  POOLREG_DEF;
+  int it = USING_IT;
+  static int myproc = 0;
+  int PutInterMed = *fill_intermed;
+  DECL_FTN_CHAR(dataname);
+  static char *env = NULL;
+  static int first_time = 1;
+  static int do_debug = 0;
+  DRHOOK_START_BY_STRING(GEN_PUTNAME);
+
+  if (first_time) {
+    env = getenv("ODB_DEBUG_CODB_H");
+    if (env) {
+      int value = atoi(env);
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      if (value == -1 || value == myproc) do_debug = 1;
+    }
+    first_time = 0;
+  }
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (do_debug) {
+    printf("\n>>>%s(view=%s, myproc=%d, Poolno=%d, ProcID=%d, LdimD=%d, Doffset=%d, Nrows=%d, Ncols=%d)\n",
+	   GEN_PUTNAME, p_dataname, myproc, Poolno, ProcID, LdimD, Doffset, Nrows, Ncols);
+    fflush(stdout);
+  }
+  
+  if (LdimD - Doffset < Nrows) { rc = -3; goto finish; }
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	boolean is_table = PFCOM->is_table;
+	int nr, nc;
+	int pool = p->poolno;
+	int Npools = 1;
+	int offset = 0;
+
+	if (do_debug) {
+	  printf("<1>%s(myproc=%d): pf=%p, data=%p, d=%p, pool=%d, is_table=%d : k1=%d, PutInterMed=%d\n",
+		 p_dataname, myproc, pf, data, d, pool, (int)is_table, k1, PutInterMed);
+	  fflush(stdout);
+	}
+
+	if (!PutInterMed) {
+	  PFCOM->dim(data, &nr, &nc, NULL, ProcID);
+	}
+	else {
+	  nr = Nrows_in;
+	  nc = Ncols_in;
+	}
+
+	if (is_table) {
+	  nr = Nrows_in; /* by definition we do this pool only for TABLEs; Poolno cannot be -1 for TABLEs */
+	}
+
+	if (PutInterMed) {
+	  int jc;
+	  DELETE_INTERMED(pf->tmp);
+	  ALLOC(pf->tmp,1);
+	  ALLOC(pf->tmp->d, nc);
+	  pf->tmp->nc = nc;
+	  for (jc=0; jc<nc; jc++) ALLOC(pf->tmp->d[jc], nr);
+	  pf->tmp->nr = 0; /* To be changed after data has been filled */
+	}
+
+	if (do_debug) {
+	  printf("<2>%s(myproc=%d): nr=%d, nc=%d\n", p_dataname, myproc, nr, nc);
+	  fflush(stdout);
+	}
+
+	if (nr > LdimD) { rc = -5; goto finish; }
+
+	if (nr > 0) {
+	  if (Ncols < nc) nc = Ncols;
+	  
+	  if (!is_table) {
+	    int k2 = k1 + nr;
+	    int kk1=0, kk2=nr;
+	    int count = 0;
+
+	    codb_get_pool_count_(&d[k1], 
+				 &kk1, 
+				 &kk2,
+				 &offset,
+				 &Npools, 
+				 &pool, 
+				 &count);
+
+	    if (do_debug) {
+	      printf("<3>%s(myproc=%d): k1=%d, k2=%d, nr=%d, nc=%d, count=%d ; LdimD=%d, LdimD + k1=%d ; putfunc()=%p\n",
+		     p_dataname, myproc, k1, k2, nr, nc, count, LdimD, LdimD + k1, PFCOM->GEN_PUTFUNC);
+	      fflush(stdout);
+	    }
+
+	    if (count != nr) { rc = -2; goto finish; }
+	  }
+
+	  Nrows -= nr;
+
+	  if (PutInterMed) {
+	    int jc;
+	    for (jc=0; jc<nc; jc++) {
+	      int jr;
+	      double *dout = pf->tmp->d[jc];
+	      const GEN_TYPE *din = (GEN_TYPE_CAST *)&d[LdimD + jc*LdimD + k1];
+	      for (jr=0; jr<nr; jr++) dout[jr] = din[jr];
+	    }
+	    rc = pf->tmp->nr = nr;
+	  }
+	  else {
+	    if (PFCOM->GEN_PUTFUNC) {
+	      rc = PFCOM->GEN_PUTFUNC(data, (const GEN_TYPE_CAST *)&d[LdimD + k1],
+				      LdimD, nr, nc, 
+				      ProcID, flag);
+	    }
+	    else
+	      rc = nr;
+	  }
+
+	  if (is_table) {
+	    /* ... since "rc" denotes total no. of rows in TABLE so far */
+	    if (rc < 0) { rc = -4; goto finish; }
+	  }
+	  else {
+	    if (rc != nr) { rc = -1; goto finish; }
+	  }
+	  if (PFCOM->GEN_PUTFUNC) Neff_rows += nr;
+	    
+	  Nrows_total += rc;
+	  k1 += rc; /* Meaningful for VIEWs only */
+	} /* if (nr > 0) */
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  rc = Nrows_total;
+
+ finish:
+  if (do_debug) {
+    printf("<<<%s(view=%s, myproc=%d, Poolno=%d, ProcID=%d, LdimD=%d, Doffset=%d, Nrows=%d, Ncols=%d, rc=%d)\n",
+	   GEN_PUTNAME, p_dataname, myproc, Poolno, ProcID, LdimD, Doffset, Nrows, Ncols, rc);
+    fflush(stdout);
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = rc;
+
+  if (drhook_lhook && rc >= 0) {
+    int jf;
+    for (jf=0; jf<Ncols; jf++) {
+      if (flag[jf] & 0x1) Neff_cols++;
+    }
+  }
+  DRHOOK_END(Neff_rows * Neff_cols * GEN_BYTES);
+}
+
+#undef GEN_TYPE
+#undef GEN_TYPE_CAST
+#undef GEN_GET
+#undef GEN_PUT
+#undef GEN_GETFUNC
+#undef GEN_PUTFUNC
+#undef GEN_GETNAME
+#undef GEN_PUTNAME
+#undef GEN_BYTES
+
+#endif
+
diff --git a/odb/src/include/codb_netcdf.h b/odb/src/include/codb_netcdf.h
new file mode 100644
index 0000000..7809e13
--- /dev/null
+++ b/odb/src/include/codb_netcdf.h
@@ -0,0 +1,126 @@
+#ifndef _CODB_NETCDF_H_
+#define _CODB_NETCDF_H_
+
+/* codb_netcdf.h */
+
+#include "privpub.h"
+
+PUBLIC void codb_has_netcdf_(int *retcode);
+
+PUBLIC void codb_gettype_netcdf_(const char *typename,
+				 int *retcode
+				 /* Hidden arguments */
+				 ,int typename_len);
+
+PUBLIC void dtnum_to_netcdf_type_(const uint *Dtnum, int *retcode);
+
+PUBLIC void codb2netcdf_(const char title[], const char ncfile[], const char namecfg[], const char sql_query[],
+			 const double *d, const int *nra, const int *nrows, const int *ncols,
+			 const uint idtnum[], const int *ipoolno,
+			 const char *odb_type_tag, const char *odb_name_tag, const char *odb_nickname_tag
+			 /* Hidden arguments */
+			 , int title_len
+			 , int ncfile_len
+			 , int namecfg_len
+			 , int sql_query_len
+			 , int odb_type_tag_len
+			 , int odb_name_tag_len
+			 , int odb_nickname_tag_len
+			 );
+
+PUBLIC void codb_open_netcdf_(int *ncid,
+			      const char *filename,
+			      const char *mode,
+			      int *retcode
+			      /* Hidden arguments */
+			      ,int filename_len
+			      ,int mode_len);
+
+PUBLIC void codb_begindef_netcdf_(const int *ncid,
+				  const char *title,
+				  const char *sql_query,
+				  const int *nrows, 
+				  const int *ncols,
+				  const double *mdi,
+				  const int *poolno,
+				  int *retcode
+				  /* Hidden arguments */
+				  , int title_len
+				  , int sql_query_len);
+
+PUBLIC void codb_enddef_netcdf_(const int *ncid, 
+				int *retcode);
+
+PUBLIC void codb_putheader_netcdf_(const int *ncid,
+				   const int *colnum,
+
+				   const char *odb_type,
+				   const char *odb_name,
+				   const char *odb_nickname,
+				   const char *mapname,
+				   const char *long_name,
+				   const char *units,
+
+				   const double *mdi,
+				   const int *coltype,
+				   const int *colpack,
+				   const double *scale_factor,
+				   const double *add_offset,
+
+				   int *retcode
+				   /* Hidden arguments */
+				   ,int odb_type_len
+				   ,int odb_name_len
+				   ,int odb_nickname_len
+				   ,int mapname_len
+				   ,int units_len
+				   ,int long_name_len);
+
+PUBLIC void codb_putdata_netcdf_(const int *ncid,
+				 const int *colid,
+				 const int *colpack,
+				 const double d[],
+				 const int *f90_addr,
+				 const int *nd,
+				 int *retcode);
+
+PUBLIC void codb_close_netcdf_(int *ncid, 
+			       int *retcode);
+
+/* To set up the HAS_NETCDF-option properly */
+
+/* If you definitely don't want/have NetCDF then specify
+
+      -DHAS_NETCDF=0
+
+   while you compile, since -UHAS_NETCDF may still pick NetCDF depending on the ARCH (see the test-logic below) */
+
+#undef TEST_HAS_NETCDF
+
+#ifdef HAS_NETCDF
+
+#define TEST_HAS_NETCDF HAS_NETCDF
+
+#else 
+
+/* Add new ARCH here (defined(ARCH)) after checking their implementation on NetCDF exists.
+   The new ARCH will then be automatically supported */
+
+#if (defined(LINUX) && !defined(CRAYXT)) || defined(RS6K) || defined(SUN4) || defined(HPPA) || defined(SGI)
+#define TEST_HAS_NETCDF 1
+#else
+#define TEST_HAS_NETCDF 0
+#endif
+
+#endif /* HAS_NETCDF */
+
+#if TEST_HAS_NETCDF == 0
+#undef HAS_NETCDF
+#else
+#undef HAS_NETCDF
+#define HAS_NETCDF 1
+#endif
+
+#undef TEST_HAS_NETCDF
+
+#endif /* _CODB_NETCDF_H_ */
diff --git a/odb/src/include/dca.h b/odb/src/include/dca.h
new file mode 100644
index 0000000..7d89785
--- /dev/null
+++ b/odb/src/include/dca.h
@@ -0,0 +1,140 @@
+#ifndef _DCA_H_
+#define _DCA_H_
+
+/* dca.h */
+
+#include "privpub.h"
+
+/*
+  #DCA: 
+col# colname dtname dtnum file pool# offset length 
+     pmethod pmethod_actual nrows nmdis avg 
+     min max res1 res2 is_little
+   0 seqno at hdr pk1int 279 1/hdr 1 84 6220
+     1 1 2145 0 1816064.6037296 
+     1 3679992 0 0 0
+*/
+
+typedef struct _dca_t {
+  int colnum;           /* column number (starting from 0, C-indexing) */
+  char *colname;        /* column name (in format "column at table")*/
+  char *dtname;         /* data type name */
+  uint  dtnum;          /* ODB data type information number (actually of odb_types_t) */
+  char *filename;       /* The file name where this column resides ;
+			   if begins "/", then the full path, otherwise
+			   relative to the $ODB_SRCPATH_<dbname> in concern,
+			   or $ODB_SRCPATH or current path, 
+			   in this order */
+  uint hash;            /* A hash that stems from the colname */
+  int poolno;           /* Pool number in concern */
+  u_ll_t offset;        /* 64-bit unsigned int offset to column data */
+  int length;           /* 32-bit int length of column data */
+  int pmethod;          /* Nominal packing method */
+  int pmethod_actual;   /* Actual packing method in force */
+  int nrows;            /* Number of rows */
+  int nmdis;            /* Number of missing data values */
+  double avg;           /* Column data average excluding missing data */
+  double min;           /* Column data minimum excluding missing data */
+  double max;           /* Column data maximum excluding missing data */
+  double cr;            /* Compression ratio */
+  int ncard;            /* Cardinality */
+  int is_little;        /* Column is in little-endian format */
+} dca_t;
+
+typedef struct _iodca_t {
+  char *file;
+  int unit;
+  int offset;
+  int can_rewind;
+} iodca_t;
+
+typedef struct _dca_chain_t {
+  /* The current active DCA I/O */
+  iodca_t *iodca;
+  /* To enchance lookup */
+  int   handle;
+  int   it;
+  char  *dbname;
+  char  *tblname;
+  /* The DCA-file */
+  char  *dcafile;
+  /* DCA-datas for this file */
+  dca_t *dca;
+  int    dcalen;
+  /* Cache maximum column number in this DCA-data chunk */
+  int    ncols;
+  /* Cache min & max pool numbers in this DCA-data chunk */
+  int    min_poolno, max_poolno;
+  /* Cache min & max hash numbers in this DCA-data chunk */
+  uint   min_hash, max_hash;
+  /* A pointer to next chunk of DCA-data */
+  struct _dca_chain_t *next;
+} dca_chain_t;
+
+extern dca_chain_t *
+DCA_alloc(int handle,
+	  const char *dbname,
+	  const char *tblname,
+	  int *retcode);
+
+extern int
+DCA_free(int handle);
+
+extern void
+DCA_debugprt(FILE *fp,
+	     int handle,
+	     const char *dbname,
+	     const char *tblname,
+	     const char *colname,
+	     int poolno);
+
+extern int
+DCA_getsize(int handle,
+	    const char *dbname,
+	    const char *tblname,
+	    int poolno,
+	    int *nrows,
+	    int *ncols);
+
+extern void *
+DCA_fetch(int handle,
+	  const char *dbname,
+	  const char *tblname,
+	  const char *colname,
+	  int poolno,
+	  int unpack,
+	  const int idx[],
+	  int idxlen,
+	  int *nrows,
+	  int *nbytes,
+	  uint *datatype,
+	  int *offset);
+
+extern double *
+DCA_fetch_double(int handle,
+		 const char *dbname,
+		 const char *tblname,
+		 const char *colname,
+		 int poolno,
+		 const int idx[],
+		 int idxlen,
+		 int *nrows);
+
+extern int *
+DCA_fetch_int(int handle,
+	      const char *dbname,
+	      const char *tblname,
+	      const char *colname,
+	      int poolno,
+	      const int idx[],
+	      int idxlen,
+	      int *nrows);
+
+extern
+void codb_detect_dcadir_(const char *dbname, 
+			 int *io_method_env
+			 /* Hidden arguments */
+			 , int dbname_len);
+			
+
+#endif
diff --git a/odb/src/include/defs.h b/odb/src/include/defs.h
new file mode 100644
index 0000000..724b938
--- /dev/null
+++ b/odb/src/include/defs.h
@@ -0,0 +1,654 @@
+
+/* defs.h */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include "ecstdlib.h"
+#include <stdarg.h>
+#include <unistd.h>
+#include <math.h>
+#include <limits.h>
+#include <signal.h>
+#ifdef HPPA
+#include <sys/time.h>
+#else
+#include <sys/select.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "alloc.h"
+
+#include "odbcrc.h"
+#include "odbmd5.h"
+
+#if 0
+
+/* These are here to *FOOL* the make-depend system
+   and to enforce rebuild of ODB/SQL-compiler,
+   when one of these files below has changed */
+
+#include "odb.h"
+#include "odb_macros.h"
+#include "dca.h"
+#include "idx.h"
+#include "info.h"
+#include "odb98.h"
+
+#endif
+
+
+#define ODB_H "$ODB_SYSPATH/odb.h"
+
+#define exit ODB_exit
+
+#define FOPEN(name, mode)    ODB_fopen(name, mode, __FILE__, __LINE__)
+#define FCLOSE(fp)           if (fp) { ODB_fclose(fp, __FILE__, __LINE__); fp = NULL; }
+#define FREWIND(fp)          if (fp) { rewind(fp); }
+
+#define UINT "uint"
+#define BITFIELD "Bitfield"
+#define STRING "string"
+#define UNUSED "Unused"
+
+#ifndef MAXLINE
+#define MAXLINE    1024
+#endif
+
+#define ODB_FROM_ATTR_USER   0x1
+#define ODB_FROM_ATTR_AUTO   0x2
+#define ODB_FROM_ATTR_INSERT 0x4
+
+#define ODB_BAILOUT_ALL      (-1)
+
+#define ODB_BAILOUT_SELECT     0x01 /*  1 */
+#define ODB_BAILOUT_SELECTEXPR 0x02 /*  2 */
+#define ODB_BAILOUT_UNIQUEBY   0x04 /*  4 */
+#define ODB_BAILOUT_FROM       0x08 /*  8 */
+#define ODB_BAILOUT_WHERE      0x10 /* 16 */
+#define ODB_BAILOUT_ORDERBY    0x20 /* 32 */
+
+#define ODB_SCALE 10000
+
+#define ODB_GTGT  ODB_GT * ODB_SCALE + ODB_GT
+#define ODB_GTGE  ODB_GT * ODB_SCALE + ODB_GE
+#define ODB_GEGE  ODB_GE * ODB_SCALE + ODB_GE
+#define ODB_GEGT  ODB_GE * ODB_SCALE + ODB_GT
+
+#define ODB_LTLT  ODB_LT * ODB_SCALE + ODB_LT
+#define ODB_LTLE  ODB_LT * ODB_SCALE + ODB_LE
+#define ODB_LELE  ODB_LE * ODB_SCALE + ODB_LE
+#define ODB_LELT  ODB_LE * ODB_SCALE + ODB_LT
+
+#define IS_SET(mode,val) ( ((mode)&(val)) == (val) )
+
+#define IS_LINK(s)    strequ(s,"Link")
+#define IS_VARCHAR(s) (isalnum(*s) || (*s == '_'))
+#define IS_WILDCARD(s) (strstr(s,"*@") != NULL)
+#define IS_REGEX(s, slen)  ( \
+			    ((slen > 2) && (s[0] == '/' && s[slen-1] == '/')) || \
+			    ((slen > 3) && (strnequ(s,"!/",2) && s[slen-1] == '/')) || \
+			    ((slen > 3) && (strnequ(s,"~/",2) && s[slen-1] == '/')) || \
+			    ((slen > 3) && (s[0] == '/' && strncaseequ(&s[slen-2],"/i",2))) || \
+			    ((slen > 4) && (strnequ(s,"!/",2) && strncaseequ(&s[slen-2],"/i",2))) || \
+			    ((slen > 4) && (strnequ(s,"~/",2) && strncaseequ(&s[slen-2],"/i",2))) \
+			   )
+
+#define ARTIFICIAL_NICKCHAR '\a'
+#define HAS_NICKNAME(sym) (sym && sym->name && (*sym->name != ARTIFICIAL_NICKCHAR) \
+                               && (sym->kind == ODB_NICKNAME))
+
+static const char FORMULA_CHAR[] = "\b";
+#define IS_FORMULA(s) (s && *s == *FORMULA_CHAR)
+
+#define LINKOFFSETTYPE "linkoffset_t"
+#define LINKLENTYPE    "linklen_t"
+
+#define BETWEEN(x,a,b) ( ((x) >= (a)) && ((x) <= (b)) )
+
+#define ZEROIT(x,n1,n2) { int l; for(l=(n1); l<(n2); l++) (x)[l] = 0; }
+
+#define EMPTY_MEMBER "/* an empty member */"
+
+PUBLIC void odb_warn(char *errormsg, int rc);
+PUBLIC void yyerror(char *errormsg);
+
+PRIVATE char msg[MAXLINE];
+
+#define PRTMSG(s) \
+{ \
+  extern char *odb_source;\
+  extern int ODB_lineno; \
+  if (odb_source && ODB_lineno > 0) { \
+    fprintf(stderr,"\"%s\":%d [%s:%d] : ",odb_source, ODB_lineno, __FILE__, __LINE__); \
+  } else { \
+    fprintf(stderr,"[%s:%d] : ", __FILE__, __LINE__); \
+  } \
+  fprintf(stderr,"%s",s);			\
+}
+
+#define PRTMSG3(s,filename,lineno) \
+{ \
+  extern char *odb_source;\
+  extern int ODB_lineno; \
+  if (odb_source && ODB_lineno > 0) { \
+    fprintf(stderr,"\"%s\":%d [%s:%d called from %s:%d] : ",odb_source, ODB_lineno, \
+            __FILE__, __LINE__, \
+            filename, lineno); \
+  } else { \
+    fprintf(stderr,"[%s:%d called from %s:%d] : ", \
+            __FILE__, __LINE__, \
+            filename, lineno); \
+  } \
+  fprintf(stderr,"%s",s);			\
+}
+
+#define YYwarn(rc,s) { \
+  if (s != NULL) { \
+    int len=strlen(s); \
+    PRTMSG(s); \
+    if (s[len-1] != '\n') fprintf(stderr,"\n"); \
+  } \
+  odb_warn(NULL,rc); \
+}
+
+#define YYwarn3(rc,s,filename,lineno) { \
+  if (s != NULL) { \
+    int len=strlen(s); \
+    PRTMSG3(s,filename,lineno); \
+    if (s[len-1] != '\n') fprintf(stderr,"\n"); \
+  } \
+  odb_warn(NULL,rc); \
+}
+
+#define YYerror(s) { \
+  if (s != NULL) { \
+    int len=strlen(s); \
+    PRTMSG(s); \
+    if (s[len-1] != '\n') fprintf(stderr,"\n"); \
+  } \
+  yyerror(NULL); \
+}
+
+#define YYerror3(s,filename,lineno) { \
+  if (s != NULL) { \
+    int len=strlen(s); \
+    PRTMSG3(s,filename,lineno); \
+    if (s[len-1] != '\n') fprintf(stderr,"\n"); \
+  } \
+  yyerror(NULL); \
+}
+
+#define SETMSG0(s) sprintf(msg,(s))
+#define SETMSG1(s,var1) sprintf(msg,(s),(var1))
+#define SETMSG2(s,var1,var2) sprintf(msg,(s),(var1),(var2))
+#define SETMSG3(s,var1,var2,var3) sprintf(msg,(s),(var1),(var2),(var3))
+#define SETMSG4(s,var1,var2,var3,var4) sprintf(msg,(s),(var1),(var2),(var3),(var4))
+#define SETMSG5(s,var1,var2,var3,var4,var5) sprintf(msg,(s),(var1),(var2),(var3),(var4),(var5))
+
+#define ODBOPER0(what)                 ODB_oper(what, NULL, NULL, NULL, NULL, __FILE__, __LINE__)
+#define ODBOPER1(what, p1)             ODB_oper(what, p1, NULL, NULL, NULL, __FILE__, __LINE__)
+#define ODBOPER2(what, p1, p2)         ODB_oper(what, p1, p2, NULL, NULL, __FILE__, __LINE__)
+#define ODBOPER3(what, p1, p2, p3)     ODB_oper(what, p1, p2, p3, NULL, __FILE__, __LINE__)
+#define ODBOPER4(what, p1, p2, p3, p4) ODB_oper(what, p1, p2, p3, p4, __FILE__, __LINE__)
+
+#define FUNC_LINKLIST_ADD         1
+#define FUNC_LINKLIST_START       2
+#define FUNC_LINKLIST_QUERY       3
+
+typedef struct _ODB_linklist {
+  char *lhs;
+  struct _rhs_t {
+    char *name;
+    struct _rhs_t *next;
+  } *rhs;
+  struct _rhs_t *last_rhs;
+  int n_rhs;
+  int type; /* 1 : -1 (onelooper), 2 : -A (align), 4 : a regular link, 8 : shared link (N/A) */
+  struct _ODB_linklist *next;
+} ODB_linklist;
+
+typedef struct _ODB_Arridx {
+  int low;
+  int high;
+  int inc;
+  Boolean only_low;
+  Boolean only_high;
+} ODB_Arridx;
+
+typedef struct _ODB_Filelist {
+  char *filename;
+  Boolean create_so;
+  struct _ODB_Filelist *next;
+} ODB_Filelist;
+
+typedef struct _ODB_Tree {
+  int    what;      /* What sort of command */
+  double dval;      /* Direct numeric value (if applicable) */
+  int    argc;      /* No of args */
+  void **argv;      /* Argument list */
+  int   level;      /* FROM-level nesting (0,1,2,...) or uninitialized = -1 */
+  int joffset;      /* Arg-offset (usually 0) as in funcs_t in funcs.h */
+  struct _ODB_Tree *next; /* Next in chain */
+} ODB_Tree;
+
+typedef struct _ODB_Cmd {
+  int lineno;                 /* ODB-source line number */
+  ODB_Tree *node;             /* Pointer to the next expression */
+  struct _ODB_Cmd *next;
+} ODB_Cmd;
+
+typedef struct _ODB_Match_t {
+  ODB_Tree *expr;
+  char *formula; /* expression as a character string */
+  ODB_Tree *symexpr; /* formula as a symexpr */
+} ODB_Match_t;
+
+typedef struct selattr_t {
+  Boolean distinct;
+} ODB_SelAttr_t;
+
+typedef struct _ODB_dbcred {
+  char *dbname;   /* current database name <dbname> */
+  char *srcpath;  /* ODB_SRCPATH_<dbname>           */
+  char *datapath; /* ODB_DATAPATH_<dbname>          */
+  char *idxpath;  /* ODB_IDXPATH_<dbname>           */
+  char *poolmask; /* ODB_PERMANENT_POOLMASK         */
+} ODB_dbcred;
+
+typedef struct _ODB_Symbol {
+  uint hash;        /* A hash of {kind,name} */
+  int kind;         /* The kind of an entry : ODB_{TYPE|NAME|USDNAME|STRING|TABLE|VIEW} */
+  double dval;      /* Direct numeric value (if applicable) */
+  char *name;       /* Name of the symbol in concern */
+  char *dname;      /* "True" value of the name (kind == ODB_STRING or ODB_WC_STRING) */
+  char *sorig;      /* Original value (as input) of the string, if kind == ODB_STRING or ODB_WC_STRING */
+  uint  flag;       /* Various flags needed during the processing */
+  Boolean only_view; /* A dollar symbol that exist for VIEW only */
+  struct _ODB_Symbol *next;
+} ODB_Symbol;
+
+#define RESET_SYM(x,num) ((x) &= ~(1U << ((num)-1)))
+#define   SET_SYM(x,num) ((x) |=  (1U << ((num)-1)))
+#define  DONE_SYM(x,num) ((x) &   (1U << ((num)-1)))
+
+typedef struct _ODB_Type {
+  ODB_Symbol *type;    /* Ptr to a symbol to describe the type itself */
+  int nsym;            /* No. of members */
+  ODB_Symbol **sym;    /* Pointers to type symbols */
+  ODB_Symbol **member; /* Pointers to member symbols */
+  Boolean no_members;  /* If a raw typedef : TYPE mytype = uint; */
+  Boolean processed;   /* If ODB_TYPE has been processed to the C-language already */
+  Boolean bitstream;   /* Solely a bit stream (up to MAXBITS allowed) */
+  int *pos;            /* Start of a bit position */
+  int *len;            /* No. of bits in that position */
+  struct _ODB_Type *next;
+} ODB_Type;
+
+typedef struct _ODB_Table {
+  ODB_Symbol *table; /* Ptr to a symbol to describe the table itself */
+  int nsym;          /* No. of types/symbols in this table */
+  int tableno;       /* Sequence number of this table : [0..ODB_ntables-1] */
+  int rank;          /* Table's rank (order# in hierarchy) after final weight (wt) has been applied */
+  double wt;         /* Precedence weight for use by ordering the FROM-stmt */
+  ODB_Type   **type; /* Pointers to types */
+  ODB_Symbol **sym;  /* Pointers to variable symbols */
+  char    **expname; /* Fully expanded names ("datatype:varname at table") */
+  int     *linkmode; /* 0 = not a  link; 1 = link-offset; 2 = link-length */
+  int         nlink; /* No. of links to the other tables, if any */
+  char   **linkname; /* Link names (before are the link-tables are available */
+  struct _ODB_Table **link; /* Links to the other tables */
+  uchar *linkslavemask; /* A mask against every table to denote if the current table is slave for
+			   given tableno, so that linkslavemask[tableno] > 0
+			   Array dimension [0..ODB_ntables-1] */
+  struct _ODB_Table **sharedlink; /* Detects shareable links (saves dbase-space) */
+  char   **sharedlinkname;        /* Name of the possible master shareable table */
+  Boolean any_sharedlinks; /* 1 if any sharedlinkname[] points to non-NULL */
+  ODB_dbcred *db;      /* Associated database credentials */
+  struct _ODB_Table *next;
+} ODB_Table;
+
+typedef struct tabledef_t {
+  int num_tables;
+  ODB_Table **tables;
+} Tabledef_t;
+
+typedef struct _ODB_AndList {
+  ODB_Tree *expr;
+  int maxfrom;
+} ODB_AndList;
+
+typedef struct _ODB_SelectExpr {
+  ODB_Tree *expr;       /* Expression tree in concern */
+  uint aggr_flag;       /* Non-zero if any of aggregate funcs {SUM|MIN|MAX|AVG|STDEV|COUNT} used */
+  int ncols_aux;        /* Number of auxiliary columns needed (if aggregate {CORR|COVAR|...}) */
+  char *formula;        /* Expression as a formula/character string (upon input) */
+  char *formula_out;    /* Expression as a formula/character string (upon output) */
+  ODB_Symbol *nicksym;  /* Expression's nickname symbols */
+  int nsym;             /* No. of symbols in this expressions */
+  ODB_Symbol **sym;     /* Ptrs to expression symbols */
+} ODB_SelectExpr;
+
+typedef struct _ODB_View {
+  ODB_Symbol *view;    /* Ptr to a symbol to describe the view itself */
+
+  ODB_dbcred *db;      /* Associated database credentials */
+
+  int create_index;     /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+  Boolean binary_index; /* True if binary index (file) is meant to be created */
+
+  int nselect;         /* No. of symbols in SELECT-clause (after dupl. removal) */
+  int nselect_all;     /* Original no. of symbols in SELECT (before dupl. removal) */
+  Boolean *readonly;   /* Read/Only symbols in SELECT-clause */
+  Boolean all_readonly;/* when true, then do not generate code for put()-routines at all */
+  ODB_Symbol **select; /* Ptrs to SELECT-symbols */
+
+  ODB_SelectExpr **sel; /* SELECT-expressions i.e. "formulas" (when present) & their symbols */
+  Boolean *is_formula;  /* Flag for each SELECT-column to denote if it is a formula (=1) or not (=0) */
+  Boolean has_formulas; /* true if any SELECT colums involves formulas */
+  int nselsym;          /* Total number of symbols in SELECT-expressions **sel */
+  ODB_Symbol **selsym;  /* SELECT-expression symbols as a one list (length = nselsym) */
+
+  int ncols_aux;        /* Total number of auxiliary columns needed; derived from SELECT-expressions' ncols_aux */
+
+  Boolean select_distinct; /* SELECT DISTINCT (or SELECT UNIQUE) was used */
+
+  Boolean usddothash; /* Has "$<parent_table>.<child_table>" -variables in SELECT */
+
+  Boolean use_indices; /* If true (default) then prefer to use CREATE INDEX-indices */
+  char *use_index_name;
+
+  Boolean reorder_tables; /* View-specific reordering of FROM-tables */
+
+  Boolean insert_tables;  /* When true (default), ODB/SQL will insert missing FROM-tables 
+			     by looking into database layout table-hierarchy */
+
+  Boolean has_count_star; /* True if any of the SELECT-expressions have count(*) */
+
+  Boolean safeGuard;      /* True if -G option or SAFEGUARD keyword active */
+
+  Boolean no_from_stmt; /* True if FROM-statement wasn't explicitly present */
+
+  uint select_aggr_flag; /* Non-zero if any of aggregate funcs {SUM|MIN|MAX|AVG|STDEV|COUNT} used */
+
+  int nfrom_start;     /* Starting table (deferred implementation) */
+  int nfrom;           /* No. of tables in FROM-clause */
+  ODB_Table **from;    /* Ptrs to FROM-tables */
+  int *from_attr;      /* ODB_FROM_ATTR_xxx to FROM-tables indicate how table was supplied in FROM-stmt */
+
+  int maxfrom;         /* The most inner loop of [0..nfrom-1], where to put the WHERE-test */
+  int *active;         /* Table is active (|= 0x1), if in SELECT i.e. Index_Table[] is needed 
+			  active[i] is [also] |= 0x2, if "i" is is one of values of table_index[j]
+			*/
+  char **merged_with;  /* Table maybe aliased with some other table, i.e. Index_Table[] merge can occur */
+
+  int nwhere;          /* No. of symbols in WHERE-clause */
+  ODB_Symbol **where;  /* Ptrs to WHERE-symbols */
+
+  int nuniqueby;       /* No. of UNIQUE BY symbols; naturally > 0 if UNIQUE BY present */
+  ODB_Symbol **uniqueby; /* UNIQUEBY symbols */
+
+  Boolean has_thin;    /* thin-function is present in WHERE */
+
+  int norderby;        /* No. of symbols in ORDER BY-clause */
+  ODB_Symbol **orderby;/* Ptrs to ORDER BY-symbols */
+  int *mkeys;          /* Resolved (SELECT-matched) sorting columns 
+			  from ORDER BY-clause for use by (multi-)KEYSORT() */
+
+  int  *table_index;   /* Index to from[] -table for each SELECT/WHERE-symbol */
+  char **tag;          /* An array of symbol tags of the  SELECT/WHERE-variables */
+
+  char **call_arg;     /* A symbol of the SELECT/WHERE-variables when passed to the help routines */
+
+  char **def_put;      /* LHS name to be used when addressing SELECT/WHERE-variables in C-code */
+  char **alias_put;    /* Alias or the actual name as in #define for LHS */
+
+  char **def_get;      /* RHS name to be used when addressing SELECT/WHERE-variables in C-code */
+  char **alias_get;    /* Alias or the actual name as in #define for RHS */
+
+  char **poslen;       /* Bitfield pos & len, if applicable */
+
+  char **offset;       /* The constant expression part from offset(var,const_expr)-"function" */
+
+  ODB_Tree *cond;      /* Pointer to WHERE-condition code */
+  ODB_AndList *andlist;  /* A list of AND-expressions */
+  int andlen;            /* No. of AND-expressions */
+
+  struct _ODB_View *next;
+} ODB_View;
+
+typedef struct symbolparam_t {
+  int nsym;
+  ODB_Symbol **sym;
+  Boolean *readonly;
+  ODB_SelectExpr **sel;
+} SymbolParam_t;
+
+typedef struct viewdef_t {
+  int num_views;
+  ODB_View **views;
+} Viewdef_t;
+
+typedef struct selectdef_t {
+  int nselect;
+  char **select_items; /* array */
+  Boolean *readonly; /* array */
+  ODB_SelectExpr *sel; /* array */
+  struct selectdef_t *next;
+} Selectdef_t;
+
+typedef struct _ODB_Tracesym {
+  int  flag;
+  int  next;
+  int  maxfrom;
+  int  *table_index;
+  char **where;
+  char **tag;
+  Boolean has_maxcount; /* The maxcount() function has been referred (=1), not referred (=0) */
+  Boolean has_Unique;   /* The Unique() function has been referred (=1), not referred (=0) */
+  Boolean has_thin;     /* The thin() function has been referred (=1), not referred (=0) */
+} ODB_Tracesym;
+
+typedef struct _ODB_Stack {
+  unsigned int flag;
+  union {
+    char *s;
+    int i;
+    ODB_Tree *expr;
+    FILE *fp;
+    ODB_Symbol *psym;
+    ODB_SelectExpr *sel;
+  } u;
+  struct _ODB_Stack *prev;
+  struct _ODB_Stack *next;
+} ODB_Stack;
+
+extern ODB_Symbol   *ODB_new_symbol(int kind, const char *s);
+extern ODB_Symbol   *ODB_symbol_copy(ODB_Symbol *psym);
+extern Boolean       ODB_is_symbol(void *p);
+extern ODB_Type     *ODB_new_type(const char *p, Boolean reuse_okay);
+extern ODB_Table    *ODB_new_table(const char *p, Boolean reuse_okay);
+extern ODB_Table    *ODB_copy_table(const ODB_Table *from, const char *table_name);
+extern ODB_View     *ODB_new_view(const char *p, Boolean reuse_okay);
+extern ODB_Cmd      *ODB_new_cmd(ODB_Tree *pnode);
+extern ODB_Tree     *ODB_oper(int what, void *p1, void *p2, void *p3, void *p4,
+			      const char *filename, int lineno);
+extern ODB_Tree     *ODB_oper_copy(ODB_Tree *expr, Boolean recursive);
+extern Boolean       ODB_is_oper(void *p);
+extern void          ODB_pushSELECTEXPR(ODB_SelectExpr *sel);
+extern void          ODB_pushSYMBOL(ODB_Symbol *psym);
+extern void          ODB_pushFILE(FILE *fp);
+extern void          ODB_pushexpr(ODB_Tree *expr);
+extern void          ODB_pushstr(char *s);
+extern void          ODB_pushi(int i);
+
+extern ODB_SelectExpr *ODB_popSELECTEXPR();
+extern ODB_Symbol     *ODB_popSYMBOL();
+extern FILE           *ODB_popFILE();
+extern ODB_Tree       *ODB_popexpr();
+extern char           *ODB_popstr();
+extern int             ODB_popi();
+
+extern char *ODB_keymap(int what);
+
+extern char *ODB_lowercase(const char *s);
+extern char *ODB_uppercase(const char *s);
+extern char *ODB_capitalize(const char *s);
+
+extern ODB_Symbol  *ODB_lookup(int kind, const char *s, ODB_Symbol *start_symbol);
+extern ODB_Type    *ODB_lookup_type(const char *name, ODB_Type *start_type);
+extern ODB_Table   *ODB_lookup_table(const char *name, ODB_Table *start_table);
+extern ODB_View    *ODB_lookup_view(const char *name, ODB_View *start_view);
+
+extern Boolean      ODB_in_table(int kind, const char *name, const ODB_Table *ptable, int *index);
+extern Boolean      ODB_in_type(const char *name, const ODB_Type *ptype, int *index);
+
+extern ODB_Symbol **ODB_resolve_relations(const char *label,
+					  int bailout_key,
+					  SymbolParam_t *sp,
+					  const char *vname,
+					  ODB_Table **table, 
+					  const int *from_attr,
+					  int ntable,
+					  ODB_Symbol **sym, 
+					  int *sign_in,
+					  int nsym,
+					  Boolean allow_dollar,
+					  Boolean allow_hash,
+					  int *nsym_out,
+					  int **sign_out);
+
+extern void ODB_setup_where(ODB_View *pview);
+extern int ODB_setup_selectexpr(ODB_View *pview, int k, int j);
+extern Boolean ODB_IsSimpleExpr(const ODB_Tree *pnode, Boolean funcs_are_simple);
+
+extern Boolean ODB_matchup_sym(Boolean report_error,
+			       const char *target_label,
+			       ODB_Symbol **target,
+			       int ntarget,
+			       const char *with_label,
+			       ODB_Symbol **with,
+			       int nwith,
+			       int *key);
+
+extern FILE *ODB_fopen(const char *file, const char *mode, const char *srcfile, int srcline);
+extern int   ODB_fclose(FILE *fp, const char *srcfile, int srcline);
+
+extern ODB_Tree    *ODB_start_oper();
+extern ODB_Symbol  *ODB_start_symbol();
+extern ODB_Type    *ODB_start_type();
+extern ODB_Table   *ODB_start_table();
+extern ODB_View    *ODB_start_view();
+extern ODB_Cmd     *ODB_start_cmd();
+
+extern void ODB_print_symbols(FILE *fp);
+extern int ODB_pick_tables(int nfrom);
+extern int ODB_pick_symbols(ODB_Table **from, const int *from_attr, int nfrom);
+extern int ODB_trace_symbols(ODB_Tree *pnode, ODB_Tracesym *t, Boolean is_selectexpr);
+extern int ODB_wildcard(const char *s, ODB_Table **from, const int *from_attr, int nfrom);
+extern int ODB_regex(const char *s, ODB_Table **from, const int *from_attr, int nfrom);
+extern Boolean ODB_is_integer(const char *s);
+extern Boolean ODB_is_dollar(const char *s);
+extern void ODB_where_massage(ODB_View *pview);
+extern int ODB_reorder_tables(ODB_View *pview);
+extern int ODB_insert_tables(ODB_View *pview);
+extern char *ODB_get_sharedlinkname(const char *table_name, const char *target);
+extern int ODB_remove_duplicates(SymbolParam_t *in, 
+				 int  *table_index,
+				 char **tag,
+				 char **call_arg,
+				 char **def_put,
+				 char **alias_put,
+				 char **def_get,
+				 char **alias_get,
+				 char **poslen,
+				 char **offset);
+extern Boolean ODB_dupl_symbols(ODB_Symbol **psym, int nsym, Boolean extract);
+extern Boolean ODB_split(const char *s, 
+			 char **type, char **var, char **member, char **table, char **offset);
+extern char *ODB_expand_sym(const ODB_Symbol *psym, const char *suffix, const char *table, const char *offset);
+extern uint ODB_which_aggr(const ODB_Tree *pnode, int *ncols_aux);
+
+extern   char *ODB_extract(const char *in, int left_delim, int right_delim);
+extern void ODB_link_massage();
+extern int ODB_addrel(const char *p, char separ);
+
+extern ODB_Filelist *genc(Boolean views_only);
+
+extern void ODB_exit(int status);
+extern void ODB_sigexit(int status);
+extern int ODB_evaluate(ODB_Tree *pnode, double *dval);
+
+extern void     destroy_list();
+extern char    *init_list(const char *p);
+extern Boolean  in_list(const char *p);
+extern Boolean in_mylist(const char *p, const char *mylist, char delim);
+extern Boolean  in_extlist(const char *p, const char *extlist);
+extern char    *in_extlist1(const char *p, const char *extlist);
+extern char    *add_list(const char *p);
+extern char    *get_list();
+extern char     get_list_delim();
+extern int      get_list_elemcount();
+
+extern void  dump_c(FILE *cfp, int lineno, ODB_Tree *pnode);
+extern char *dump_s(char *in, ODB_Tree *pnode, int flag, Boolean *subexpr_is_aggrfunc);
+extern const char *ODB_NickName(int colnum);
+
+extern void   ODB_put_define(const char *s, double default_value);
+extern double ODB_get_define(const char *s);
+extern Boolean ODB_has_define(const char *s);
+
+extern int ODB_copyfile(FILE *fpout, const char *file,
+			const char *start_mark, const char *end_mark,
+			Boolean backslash_dblquote,
+			Boolean keep_backslash);
+
+extern int ODB_grepfile(FILE *fpout, const char *pattern, const char *file,
+			const char *start_mark, const char *end_mark,
+			Boolean backslash_dblquote,
+			Boolean keep_backslash);
+
+extern Boolean ODB_fixconv(ODB_Tree *pnode);
+
+extern uint ODB_hash(int kind, const char *s);
+extern ODB_linklist *manage_linklist(int function,
+				     const char *lhs, const char *rhs,
+				     int type);
+extern void process_one_tables(FILE *cfp,
+			       const char *start, const char *end);
+
+extern Boolean is_dummy_table(const char *name);
+
+extern int ODB_RemoveDuplicateTables(ODB_View *v);
+
+#ifndef THIS_IS_YACC_FILE
+#include "y.tab.h"
+#endif
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+#ifdef YYLEX_PARAM
+extern int yylex (YYLEX_PARAM);
+#else /* ! YYLEX_PARAM */
+extern int yylex ();
+#endif /* ! YYLEX_PARAM */
+
+
diff --git a/odb/src/include/ecstdlib.h b/odb/src/include/ecstdlib.h
new file mode 100644
index 0000000..7aa8021
--- /dev/null
+++ b/odb/src/include/ecstdlib.h
@@ -0,0 +1,11 @@
+#ifndef _ECSTDLIB_H_
+#define _ECSTDLIB_H_
+
+#include <stdlib.h>
+
+#ifdef CRAYXT
+/* Cray XT3/XT4 with catamount microkernel */
+#define system(cmd) (-1)
+#endif
+
+#endif /* _ECSTDLIB_H_ */
diff --git a/odb/src/include/evaluate.h b/odb/src/include/evaluate.h
new file mode 100644
index 0000000..785e0fd
--- /dev/null
+++ b/odb/src/include/evaluate.h
@@ -0,0 +1,161 @@
+#ifndef _EVALUATE_H_
+#define _EVALUATE_H_
+
+/* evaluate.h */
+
+#include "alloc.h"
+#include "symtab.h"
+
+typedef enum {
+  EMPTY = -255, INCR = -1, DECR = -2  /* not supported */
+  , UNKNOWN = 0
+  , NAME, NUMBER, FUNC
+  , UNARY_PLUS, UNARY_MINUS
+  , LE, GE, EQ, NE, AND, OR
+  , LSHIFT, RSHIFT
+  , INCR_ASSIGN, DECR_ASSIGN
+  , MUL_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, POWER_ASSIGN
+  , CMP
+  , LT = '<', GT = '>', NOT = '!'
+  , PLUS = '+', MINUS = '-', MUL = '*', DIV = '/', MOD = '%', POWER = '^'
+  , SEMI = ';', ASSIGN = '=', LP = '(', RP = ')'
+  , COMMA = ',', COLON = ':', QMARK='?'
+  , DOT = '.'
+} Kind_t;
+
+typedef struct _thsafe_parse_t {
+  double lastres;
+  int recursion;
+  int nparens;
+  int in_func;
+  int numelems;
+  int aggr_argno;
+  Bool unary;
+  int (*prtfunc)(void *, const char *, ...); /* like fprintf */
+  void *chan_out; /* like stdout */
+  void *chan_err; /* like stderr */
+} thsafe_parse_t;
+
+#define Aggr_argnO thsp[IT].aggr_argno
+
+#define FprintF  thsp[IT].prtfunc
+#define StdouT   thsp[IT].chan_out
+#define StderR   thsp[IT].chan_err
+
+/* for now : ERROR("string") */
+#define ERROR(s,fatal) { \
+  FprintF(StderR,"***Error#%d: %s (%s:%d)\n",fatal,s,__FILE__,__LINE__); \
+  if (fatal > 0) { RAISE(SIGABRT); } else { rc = fatal; goto finish; } }
+
+#define ERROR1(s,fatal,arg1) { \
+  FprintF(StderR,"***Error#%d: ",fatal); FprintF(StderR,s,arg1); \
+  FprintF(StderR," (%s:%d)\n",__FILE__,__LINE__); \
+  if (fatal > 0) { RAISE(SIGABRT); } else { rc = fatal; goto finish; } }
+
+#define ERROR2(s,fatal,arg1,arg2) { \
+  FprintF(StderR,"***Error#%d: ",fatal); FprintF(StderR,s,arg1,arg2); \
+  FprintF(StderR," (%s:%d)\n",__FILE__,__LINE__); \
+  if (fatal > 0) { RAISE(SIGABRT); } else { rc = fatal; goto finish; } }
+
+#define ERROR3(s,fatal,arg1,arg2,arg3) { \
+  FprintF(StderR,"***Error#%d: ",fatal); FprintF(StderR,s,arg1,arg2,arg3); \
+  FprintF(StderR," (%s:%d)\n",__FILE__,__LINE__); \
+  if (fatal > 0) { RAISE(SIGABRT); } else { rc = fatal; goto finish; } }
+
+/* from funcs.c */
+
+extern void initfunc();
+extern const void *getfunc(const char *s, int numargs);
+extern Bool checkfunc(const char *s, int numargs);
+extern double callfunc(void *pnode, int *retcode);
+extern void printfunc(void *fp);
+
+/* from evaluate.c */
+
+extern const char *KindStr(Kind_t kind);
+extern void *ParseTree(const char *cmds, int *retcode);
+extern int DelParseTree(void *ptree);
+extern void InitTHSP();
+extern const void *GetTHSP();
+extern void SetTHSPio(int it
+		      , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+		      , void *chan_out                            /* like stdout */
+		      , void *chan_err                            /* like stderr */
+		      );
+extern void PrintNode(void *fp, void *pnode);
+extern void PrintTree(void *fp, void *ptree);
+
+extern double RunTree(void *ptree, void *fp, int *retcode);
+extern double RunNode(void *pnode, int *retcode);
+
+extern double Run(const char *cmds
+		  , int *retcode
+		  , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+		  , void *chan_out /* like stdout */
+		  , void *chan_err /* like stderr */
+		  , Bool output2devnull
+		  );
+
+extern char *ReplaceSubStrings(const char *haystack, 
+			       const char *needle, 
+			       const char *repl_with, 
+			       Bool all_occurences,
+			       Bool remove_white_space,
+			       Bool ignore_case);
+
+extern char *ReplaceSubStringsBetween(const char *str, 
+				      const char *mark_begin, const char *mark_end,
+				      const char *repl_with, 
+				      Bool all_occurences,
+				      Bool remove_white_space,
+				      Bool ignore_case);
+
+extern const char *
+StrCaseStr(const char *haystack, const char *needle, Bool ignore_case);
+
+extern char ToLower(char ch);
+extern char ToUpper(char ch);
+
+extern char *GetLHSwhenSimpleExpr(const char *exprstr, int *oper, double *rhsvalue,
+				  const void *Set, int nset);
+
+/* from generic.c */
+
+extern char *S2D_fix(const void *Info, const char *s);
+
+/* from stack.c */
+
+extern void initOpStack();
+extern int OpStackLen();
+extern int OpStackMaxLen();
+extern void PushOpStack(Kind_t kind);
+extern Kind_t PopOpStack();
+extern void PrintOpStack(void *fp, const char *msg);
+
+/* from curses.c */
+
+extern int
+curse_this(const char *progname, 
+	   const char *prompt, 
+	   const char *initfile, 
+	   int lenHistory,
+	   double (*ExecCmds)(const char *cmds
+			      , int *retcode
+			      , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+			      , void *chan_out /* like stdout */
+			      , void *chan_err /* like stderr */
+			      , Bool output2devnull
+			      ),
+	   Bool intermed
+	   );
+
+extern double
+RunShell(const char *cmds
+	 , int *retcode
+	 , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+	 , void *chan_out /* like stdout */
+	 , void *chan_err /* like stderr */
+	 , Bool output2devnull
+	 );
+
+#endif /* _EVALUATE_H_ */
diff --git a/odb/src/include/fodb.h b/odb/src/include/fodb.h
new file mode 100644
index 0000000..4be4db2
--- /dev/null
+++ b/odb/src/include/fodb.h
@@ -0,0 +1,1388 @@
+#if REAL_VERSION == 8
+
+#define GEN_TYPE       REAL(KIND=JPRB)
+#define GEN_GET        ODB_dget
+#define GEN_PUT        ODB_dput
+#define GEN_GETNAME   'ODB:ODB_DGET'
+#define GEN_PUTNAME   'ODB:ODB_DPUT'
+#define GEN_CODB_GET  cODB_dget
+#define GEN_CODB_PUT  cODB_dput
+#define GEN_INC        2
+#define GEN_CTRLW_SORT ODB_dctrlw_sort
+#define GEN_CTRLW_SORTNAME     'ODB:ODB_DCTRLW_SORT'
+#define GEN_CTRLW_SORTNAME_OMP 'ODB:ODB_DCTRLW_SORT>OMPCOPY'
+#define GEN_AE_DUMP_DATATYPE (REAL_VERSION * 100)
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(REAL_VERSION)
+
+FUNCTION GEN_GET(handle, dtname, d, nrows, ncols,&
+    &poolno, colget, colpack, colfree, index, sorted, offset,&
+    &start, limit, process_select_distinct, inform_progress, using)&
+    &RESULT(rc)
+
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: dtname
+GEN_TYPE, intent(inout)       :: d(:,0:)
+INTEGER(KIND=JPIM), intent(inout)        :: nrows
+INTEGER(KIND=JPIM), intent(inout), optional :: ncols
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, offset, start, limit, using
+logical, intent(in), optional :: colget(:), colpack(:), colfree(:)
+INTEGER(KIND=JPIM), intent(out),optional :: index(:)
+     logical, intent(in), optional :: sorted, process_select_distinct, inform_progress
+INTEGER(KIND=JPIM) :: rc, ipoolno
+INTEGER(KIND=JPIM) :: i, j, nra, jcol
+INTEGER(KIND=JPIM) :: nrows_in, ncols_out, doffset, info(4)
+INTEGER(KIND=JPIM) :: nrows_out, ireplicate_PE
+INTEGER(KIND=JPIM) :: ldimd, nlastrow, targetPE
+INTEGER(KIND=JPIM) :: ndupl
+INTEGER(KIND=JPIM) :: jj, ngrp, maxlen, iphase_id, using_it, ii
+INTEGER(KIND=JPIM), allocatable :: iflag(:)
+logical  , allocatable :: takethis(:)
+INTEGER(KIND=JPIM) :: npes, nrows_in_arr(1), i_inform_progress
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(0), inumabs, icnt
+logical is_table, has_index, has_index_abs, want_sorted, has_anyflp, is_replicated
+logical has_select_distinct, LLsync, LLmpex1debug
+logical has_aggrfuncs, LLall_aggr, LLchanged, LLinform_progress
+character(len=1) env
+INTEGER(KIND=JPIM) :: nkey, maxbits, vhandle, imaxcol, maxcols
+INTEGER(KIND=JPIM), allocatable :: mkeys(:)
+INTEGER(KIND=JPIM), allocatable :: index_abs(:), absmode(:)
+INTEGER(KIND=JPIM), allocatable :: nrowvec(:)
+INTEGER(KIND=JPIM), allocatable :: index_aggr(:), grpsta(:)
+GEN_TYPE, allocatable :: dtmp(:,:), dtmpabs(:,:), zbuf(:)
+GEN_TYPE, allocatable :: tol(:)
+GEN_TYPE, allocatable :: dres(:,:)
+GEN_TYPE tmpval(2)
+INTEGER(KIND=JPIM), allocatable :: colidx(:), dupl_with(:), dupl_index(:), k(:)
+INTEGER(KIND=JPIM), allocatable :: iaggrfuncflag(:)
+INTEGER(KIND=JPIM) :: opponent(ODBMP_NPROC+1)
+INTEGER(KIND=JPIM) :: joppo, noppo, loopcnt, jloop, ndata
+INTEGER(KIND=JPIM) :: ikey, ndtypes, istart, ilimit, iaggrcols, icols_aux, i2nd, icols
+logical, allocatable :: LLswap(:), LLmask(:)
+character(len=maxvarlen), allocatable :: CLdtypes(:)
+INTEGER(KIND=JPIM) :: fast_physproc, xfast
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK(GEN_GETNAME,0,ZHOOK_HANDLE)
+
+has_aggrfuncs = .FALSE.
+iaggrcols = 0
+has_select_distinct = .FALSE.
+has_index_abs = .FALSE.
+has_index = present(index)
+
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+
+rc = 0
+ldimd = size(d, dim=1)
+ncols_out = size(d, dim=2) - 1
+if (present(ncols)) then
+  ncols_out = min(ncols,ncols_out)
+endif
+icols_aux = 0
+icols = 0
+nrows_in = nrows
+nrows_out = 0
+ireplicate_PE = 0
+if (present(offset)) then
+  doffset = offset ! No checking by the way
+else
+  doffset = 0
+endif
+
+!-- starting row (from database query/table point of view)
+if (present(start)) then
+  istart = max(1,start)
+else
+  istart = 1
+endif
+istart = istart - 1 ! In terms of C-indexing
+
+!-- how many rows to return (to the array d(:,0:) itself)
+if (present(limit)) then
+  ilimit = max(0,min(limit, nrows_in))
+else
+  ilimit = nrows_in
+endif
+
+if (ldimd < nrows_in) then
+  rc = ldimd - nrows_in
+  CALL ODB_abort(&
+       &GEN_GETNAME,&
+       &'The actual no. of rows is less than specified in TABLE/VIEW="'//&
+       &trim(dtname)//'"',&
+       &rc)
+  goto 99999
+endif
+
+want_sorted = .TRUE.
+if (present(sorted)) want_sorted = sorted
+
+LLinform_progress=.FALSE.
+i_inform_progress=0
+if (present(inform_progress)) then
+  LLinform_progress=inform_progress
+  if (LLinform_progress) i_inform_progress=1
+endif
+if (ODBMP_nproc > 1) then
+  LLinform_progress=.FALSE. ! Otherwise messy output
+  i_inform_progress=0
+endif
+
+using_it = 0
+if (present(using)) using_it = using
+
+if (db_trace) then
+  info(1) = ldimd
+  info(2) = nrows_in
+  info(3) = ncols_out
+  info(4) = using_it
+  CALL cODB_trace(handle, 1,&
+       & GEN_GETNAME//':'//dtname, info, size(info))
+endif
+
+if (odbHcheck(handle, GEN_GETNAME)) then
+  allocate(iflag(ncols_out))
+
+  if (present(colget) .or. present(colpack) .or. present(colfree)) then
+    iflag(:) = 0
+  else
+    iflag(:) = def_flag
+  endif
+
+  if (present(colget)) then
+    do i=1,min(ncols_out,size(colget))
+      if (colget(i)) iflag(i) = iflag(i) + flag_get
+    enddo
+  endif
+
+  if (present(colpack)) then
+    do i=1,min(ncols_out,size(colpack))
+      if (colpack(i)) iflag(i) = iflag(i) + flag_pack
+    enddo
+  endif
+
+  if (ODB_io_method(handle) == 5) then
+    !-- With I/O-method#5 meant for read/only we prefer deallocating column space
+    !   *IMMEDIATELY* a column in concern has been fetch'ed
+    !   The drawback is that subsequent references imply re-read of data i.e. seek&read I/O
+    if (present(colfree)) then
+      do i=1,min(ncols_out,size(colfree))
+        if (colfree(i)) iflag(i) = iflag(i) + flag_free
+      enddo
+    else
+      do i=1,ncols_out
+        iflag(i) = iflag(i) + flag_free
+      enddo
+    endif
+  endif
+
+  allocate(takethis(0:ncols_out))
+  takethis(0) = .TRUE.
+  do i=1,ncols_out
+    takethis(i) = (IAND(iflag(i),flag_get) == flag_get)
+  enddo
+
+  ipoolno = get_poolno(handle, poolno)
+
+  if (is_table) then
+    has_aggrfuncs = .FALSE.
+    has_select_distinct = .FALSE.
+    npes = 0
+  else
+    has_aggrfuncs = ODB_has_aggrfuncs(handle, dtname, ncols=iaggrcols, using=using)
+    has_select_distinct = ODB_has_select_distinct(handle, dtname)
+    vhandle = ODB_gethandle(handle, dtname, using=using)
+    CALL cODB_restore_peinfo(vhandle, ireplicate_PE, npes, using_it)
+  endif
+
+  if (has_select_distinct .OR. has_aggrfuncs) then 
+    ! do NOT allow the use of (start,limit) -feature with 'SELECT DISTINCT'
+    ! do NOT allow the use of (start,limit) -feature when aggregate functions are involved
+    istart = 0
+    ilimit = nrows_in
+  endif
+
+  is_replicated = (ireplicate_PE /= 0)
+
+  if (npes == 0) then
+    if (nrows_in > 0 .and. ilimit > 0) then
+      if (doffset == 0) CALL init_region(d, size(d) * ODB_SIZEOF_INT * GEN_INC, UNDEFDB_actual)
+      CALL & 
+        GEN_CODB_GET &
+            &(handle, ipoolno,&
+            &ctrim(dtname), d(1+doffset,0), 0, ldimd,&
+            &ilimit, ncols_out, &
+            &iflag, -1,&
+            &istart, ilimit,&
+            &i_inform_progress, using_it, rc)
+#if 0
+      CALL cODB_ae_dump(handle, 1, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                        ldimd, nrows_in, ncols_out, d(1,0))
+#endif
+    endif
+
+    if (rc < 0) then
+      CALL ODB_abort(&
+             &GEN_GETNAME,&
+             &'Cannot get data for VIEW/TABLE="'//&
+             &trim(dtname)//'"',&
+             &rc)
+      goto 99999
+    endif
+
+    nrows_out = rc
+    nrows = rc
+  else
+
+    if (is_replicated) then
+      nrows_in_arr(1) = 0
+      CALL cODB_get_rowvec(handle, ipoolno,&
+            &ctrim(dtname),&
+            &nrows_in_arr, 1,&
+            &rc, using_it)
+      nrows_in = nrows_in_arr(1)
+      npes = ODBMP_nproc
+      allocate(nrowvec(npes))
+      nrowvec(:) = 0
+      nrowvec(ODBMP_myproc) = nrows_in
+      CALL ODBMP_global('SUM', nrowvec)
+    else
+      allocate(nrowvec(npes))
+      CALL cODB_get_rowvec(handle, ipoolno,&
+            &ctrim(dtname),&
+            &nrowvec, npes,&
+            &rc, using_it)
+    endif
+
+    nrows_in = maxval(nrowvec(:))
+    nra = ODB_lda(nrows_in)
+    allocate(dtmp(nra,0:ncols_out))
+
+    !-- do only the necessary initializations
+    dtmp(:,0) = 0 ! control-word
+
+    nlastrow = 0
+
+    if (is_replicated) then
+      istart = 0
+      ilimit = nrowvec(ODBMP_myproc)
+      if (ilimit > 0) then
+        CALL &
+         GEN_CODB_GET &
+             &(handle, ipoolno,&
+             &ctrim(dtname), dtmp, 0, nra,&
+             &nrowvec(ODBMP_myproc), ncols_out, &
+             &iflag, 1,&
+             &istart, ilimit,&
+             &i_inform_progress, using_it, rc)
+
+#if 0
+        CALL cODB_ae_dump(handle, 2, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                          nra, nrowvec(ODBMP_myproc), ncols_out, dtmp)
+#endif
+      else
+        rc = ilimit
+      endif
+
+      if (rc /= ilimit) then
+        CALL ODB_abort(&
+                &GEN_GETNAME,&
+                &'Cannot get local replicated data for VIEW="'//&
+                &trim(dtname)//'"',&
+                &ipoolno)
+        rc = -2
+        goto 99999
+      endif
+
+      if (nrows_in > 0) CALL ODBMP_exchange2(d,nlastrow,dtmp,nrowvec,ncols_out,takethis)
+    else
+      !*** Note: npes is a kind of no. of pools over all procs
+
+      CALL cODB_getenv('ODB_MPEXCHANGE1_DEBUG', env)
+      LLmpex1debug = (env == '1')
+
+      loopcnt = (npes + ODBMP_nproc - 1)/ODBMP_nproc
+      noppo = ODBMP_setup_exchange(opponent)
+
+      LLsync = (npes < ODBMP_nproc   .OR. &
+                noppo /= ODBMP_nproc .OR. &
+                mod(npes,ODBMP_nproc) /= 0)
+
+      if (LLmpex1debug) then
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': ODBMP_nproc, ODBMP_myproc, npes, loopcnt, noppo, LLsync=', &
+                                                     ODBMP_nproc, ODBMP_myproc, npes, loopcnt, noppo, LLsync
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': view='//ctrim(dtname)
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': opponent(:)=',opponent(:)
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': size(nrowvec), nrowvec(:)=',size(nrowvec), nrowvec(:)
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': size & shape of d   =',size(d)   , shape(d)
+        write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': size & shape of dtmp=',size(dtmp), shape(dtmp)
+        call flush(6)
+      endif
+
+      CALL ODBMP_sync(where=0)
+      do jloop=1,loopcnt
+        if (LLmpex1debug) then
+          write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': >jloop=',jloop
+          call flush(6)
+        endif
+        do joppo=1,noppo
+          targetPE = opponent(joppo)
+          if (LLmpex1debug) then
+            write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': >>>joppo, targetPE=',joppo,targetPE
+            call flush(6)
+          endif
+          if (targetPE >= 1 .and. targetPE <= ODBMP_nproc) then
+            j = targetPE + (jloop-1)*ODBMP_nproc !*** Pools j assigned in a round-robin fashion
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': j, npes=',j,npes
+              call flush(6)
+            endif
+            if (j <= npes) then
+              if (LLmpex1debug) then
+                write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': j, nrowvec(j)=',j, nrowvec(j)
+                call flush(6)
+              endif
+              istart = 0
+              ilimit = nrowvec(j)
+              if (ilimit > 0) then
+                CALL &
+                 GEN_CODB_GET &
+                 &(handle, ipoolno,&
+                 &ctrim(dtname), dtmp, 0, nra,&
+                 &nrowvec(j), ncols_out, &
+                 &iflag, j,&
+                 &istart, ilimit,&
+                 &i_inform_progress, using_it, rc)
+
+#if 0
+                CALL cODB_ae_dump(handle, 3, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                                  nra, nrowvec(j), ncols_out, dtmp)
+#endif
+              else
+                rc = ilimit
+              endif
+
+              if (rc /= ilimit) then
+                CALL ODB_abort(&
+                     &GEN_GETNAME,&
+                     &'Cannot get parallel data for VIEW="'//&
+                     &trim(dtname)//'"',&
+                     &j)
+                rc = -2
+                goto 99999
+              endif
+              ndata = nrowvec(j)
+            else
+              ndata = 0
+            endif ! if (j <= npes) then ... else ..
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': ==> j, nlastrow, ndata=',j, nlastrow, ndata
+              call flush(6)
+            endif
+            CALL ODBMP_exchange1(targetPE,&
+                                 d,nlastrow,&
+                                 dtmp,ndata,ncols_out,takethis,LLmpex1debug)
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_GETNAME//': <== j, nlastrow, ndata=',j, nlastrow, ndata
+              call flush(6)
+            endif
+          endif ! if (targetPE >= 1 .and. targetPE <= ODBMP_nproc) then ...
+          if (LLsync) CALL ODBMP_sync(where=joppo)
+        enddo ! do joppo=1,noppo
+        if (.not.LLsync) CALL ODBMP_sync(where=jloop)
+      enddo ! do jloop=1,loopcnt
+    endif
+
+    deallocate(dtmp)
+    deallocate(nrowvec)
+
+    nrows_out = nlastrow
+
+    rc = nlastrow
+
+    if (nlastrow /= nrows) then
+      rc = nrows - nlastrow
+      CALL ODB_abort(&
+             &GEN_GETNAME, &
+             &'Unable to get ALL parallel data in VIEW="'//&
+             &trim(dtname)//'"',&
+             &rc)
+      rc = -3
+      goto 99999
+    endif ! if (is_replicated) then ... else ...
+
+#if 0
+    CALL cODB_ae_dump(handle, 4, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                      ldimd, nrows_out, ncols_out, d)
+#endif
+
+    call ODB_ctrlw_sort(d, nrows_out, takethis)
+
+#if 0
+    CALL cODB_ae_dump(handle, 5, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                      ldimd, nrows_out, ncols_out, d)
+#endif
+
+  endif ! if (npes == 0) then ... else ...
+
+  if (has_aggrfuncs .AND. nrows_out > 0 .AND. ncols_out > 0) then
+    LLall_aggr = (iaggrcols == ncols_out) ! True if all (columns) are aggregate funcs
+    allocate(iaggrfuncflag(ncols_out))
+    iaggrfuncflag(:) = 0
+    rc = ODB_get_aggr_info(handle, dtname, iaggrfuncflag, iphase_id, poolno=ipoolno, using=using)
+
+    allocate(colidx(ncols_out))
+    idummy = ODB_getsize(handle, dtname, idummy, icols, poolno=ipoolno, using=using, &
+         & colaux=colidx, ncols_aux=icols_aux)
+
+#if 0
+    write(0,'(1x,a,7i12)') &
+         & 'fodb.h: ipoolno, nrows_out, ncols_out, iaggrcols, icols, icols_aux, iphase_id = ',&
+         &          ipoolno, nrows_out, ncols_out, iaggrcols, icols, icols_aux, iphase_id
+#endif
+
+    if (ncols_out < icols) then
+      CALL ODB_abort(&
+           &GEN_GETNAME,&
+           &'Too few columns supplied to perform aggregate function calculations in VIEW="'//&
+           &trim(dtname)//'"',&
+           &ncols_out - icols)
+      rc = -6
+      goto 99999
+    endif
+
+    if (LLall_aggr) then ! Every column is an aggregate function
+      do j=1,icols-icols_aux
+        if (iphase_id == 1 .or. colidx(j) == j) then
+          jj = j
+          i2nd = 1
+        else
+          jj = colidx(j)
+          i2nd = 2
+        endif
+#if 0
+        write(0,*) 'fodb.h: j, jj, i2nd, iphase_id =',j, jj, i2nd, iphase_id
+#endif
+        CALL cODB_calc_aggr(iphase_id, iaggrfuncflag(j), i2nd, tmpval(1), nrows_out, d(1,j), d(1,jj))
+        jj = j
+        do ii=1,i2nd
+          d(1,jj) = tmpval(ii)
+          jj = colidx(jj)
+        enddo
+      enddo
+      ngrp = 1
+    else ! *not* all columns aggregate funcs --> f.ex. due to binning : SELECT obstype,codetype,avg(obsvalue)
+      nkey = icols - icols_aux - iaggrcols
+#if 0
+      write(0,'(1x,a,5i12)') 'fodb.h: nkey, ncols_out, iaggrcols, icols, icols_aux =',&
+           &                          nkey, ncols_out, iaggrcols, icols, icols_aux
+#endif
+      allocate(mkeys(nkey))
+      mkeys(:) = 0
+      jj = 0
+      do j=1,icols - icols_aux
+        if (iaggrfuncflag(j) == 0) then ! i.e. ODB_AGGR_NONE
+          jj = jj + 1
+          mkeys(jj) = j + 1 ! +1 since array d(:,0:), not d(:,1:) passed to the keysort
+        endif
+      enddo
+#if 0
+      write(0,*) 'fodb.h: jj, mkeys(:)=',jj, mkeys(:)
+#endif
+      allocate(index_aggr(nrows_out))
+      CALL keysort(rc, d, nrows_out, &
+           &multikey=mkeys(1:nkey), &
+           &index=index_aggr(1:nrows_out), init=.TRUE.)
+      mkeys(:) = mkeys(:) - 1 ! Now outside the keysort : normal column numbering
+!      do i=1,min(100,nrows_out)
+!         write(0,*) i,index_aggr(i),d(index_aggr(i),mkeys(1:nkey))
+!      enddo
+      allocate(grpsta(nrows_out+1))
+      ngrp = 1
+      jj = 1
+      grpsta(ngrp) = jj
+      do i=2,nrows_out
+        LLchanged = .FALSE.
+        do j=1,nkey
+          if (d(index_aggr(i),mkeys(j)) /= d(index_aggr(jj),mkeys(j))) then
+            LLchanged = .TRUE.
+            exit
+          endif
+        enddo
+        if (LLchanged) then
+          jj = i
+          ngrp = ngrp + 1
+          grpsta(ngrp) = jj
+        endif
+      enddo
+      grpsta(ngrp+1) = nrows_out + 1
+      deallocate(mkeys)
+      maxlen = maxval(grpsta(2:ngrp+1) - grpsta(1:ngrp))
+#if 0
+      write(0,*) 'fodb.h: ngrp, maxlen, nrows_out=',ngrp, maxlen,nrows_out
+      write(0,*) 'fodb.h: grpsta(1:ngrp+1)=',grpsta(1:ngrp+1)
+#endif
+      maxlen = ODB_lda(maxlen)
+      if (iphase_id == 1 .or. icols_aux == 0) then
+        i2nd = 1
+      else
+        i2nd = 2
+      endif
+#if 0
+      write(0,'(1x,a,5i12)') 'fodb.h> icols, icols_aux, i2nd, maxlen, iphase_id=',&
+           &                          icols, icols_aux, i2nd, maxlen, iphase_id
+#endif
+      allocate(dtmp(maxlen,i2nd))
+      allocate(dres(ODB_lda(ngrp),icols))
+      do i=1,ngrp
+        do j=1,icols-icols_aux
+          if (iaggrfuncflag(j) > 0) then ! i.e. has aggregate functions
+            jj = grpsta(i+1)-grpsta(i)
+! bug fixed 21/10/08 AF            dtmp(1:jj,1) = d(index_aggr(grpsta(i):grpsta(i+1)),j)
+            dtmp(1:jj,1) = d(index_aggr(grpsta(i):grpsta(i+1) -1),j)
+            if (iphase_id == 1 .or. colidx(j) == j) then
+              i2nd = 1
+            else
+              i2nd = 2
+              dtmp(1:jj,i2nd) = d(index_aggr(grpsta(i):grpsta(i+1)),colidx(j))
+            endif
+#if 0
+            write(0,'(1x,a,4i12)') 'fodb.h: j, jj, i2nd, iphase_id =',j, jj, i2nd, iphase_id
+#endif
+            CALL cODB_calc_aggr(iphase_id, iaggrfuncflag(j), i2nd, tmpval(1), jj, dtmp(1,1), dtmp(1,i2nd))
+            jj = j
+            do ii=1,i2nd
+              dres(i,jj) = tmpval(ii)
+              jj = colidx(jj)
+            enddo
+          else
+            dres(i,j) = d(index_aggr(grpsta(i)),j)
+          endif
+        enddo
+      enddo
+      if (iphase_id == 0) then
+        d(1:ngrp,1:icols) = dres(1:ngrp,1:icols)
+      else
+        d(1:ngrp,1:icols-icols_aux) = dres(1:ngrp,1:icols-icols_aux)
+      endif
+      deallocate(dtmp)
+      deallocate(dres)
+      deallocate(index_aggr)
+      deallocate(grpsta)
+    endif
+    deallocate(colidx)
+    if (iphase_id == 0) icols_aux = 0 ! To return correct "ncols", if (present(ncols)) [since still in preproc phase]
+    rc = ngrp
+    nrows_out = ngrp
+    nrows = ngrp
+    deallocate(iaggrfuncflag)
+  endif
+
+  if (present(process_select_distinct)) then
+    if (has_select_distinct .and. .NOT.process_select_distinct) has_select_distinct = .FALSE.
+  endif
+
+  if (has_select_distinct .AND. &
+!-wrong      (ireplicate_PE == ODBMP_myproc .OR. ireplicate_PE == -1) .AND. &
+      nrows_out > 0 .AND. ncols_out > 0) then
+
+     if (has_index) then
+        if (size(index) < nrows_out) then
+           CALL ODB_abort(&
+                &GEN_GETNAME,&
+                &'Index vector supplied is too short in VIEW="'//&
+                &trim(dtname)//'"',&
+                &size(index) - nrows_out)
+           rc = -4
+           goto 99999
+        endif
+     endif
+
+     allocate(colidx(ncols_out))
+     allocate(tol(ncols_out))
+     allocate(dupl_with(nrows_out))
+     allocate(dupl_index(nrows_out))
+
+     do j=1,ncols_out
+       colidx(j) = j
+       tol(j) = 0
+     enddo
+
+     if (has_index) then
+       do i=1,nrows_out
+         dupl_index(i) = index(i)
+       enddo
+     else
+       do i=1,nrows_out
+         dupl_index(i) = i
+       enddo
+     endif
+
+     ndupl = ODB_duplchk(d(:,1:), nrows_out, ncols_out, ncols_out, &
+                         colidx, tol, dupl_with, idx=dupl_index)
+
+!     write(0,*)'---> ndupl=',ndupl
+
+     if (ndupl > 0) then
+       nra = ODB_lda(nrows_out - ndupl)
+       allocate(dtmp(nrows_out - ndupl, 0:ncols_out))
+       allocate(k(ncols_out))
+
+       do j=1,ncols_out
+         k(j) = 0
+         do i=1,nrows_out
+           if (dupl_with(i) == 0) then
+             k(j) = k(j) + 1
+             dtmp(k(j),j) = d(i,j) 
+           endif
+         enddo
+       enddo
+
+       ! if (ANY(k(:) != nrows_out - ndupl)) then abort
+
+       deallocate(k)
+       nrows_out = nrows_out - ndupl
+
+       do j=1,ncols_out
+         do i=1,nrows_out
+           d(i,j) = dtmp(i,j)
+         enddo
+       enddo
+
+       !-- This not supposed to be updatable, so put control word to zero
+       !! d(1:nrows_out,0) = 0 ! -- we may want to display the origin (= poolno & rownum) of dada!
+
+       !-- And this is how much valid data we have left in the d-matrix
+       nrows = nrows_out
+
+#if 0
+       CALL cODB_ae_dump(handle, 6, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                         ldimd, nrows_out, ncols_out, d)
+#endif
+
+       deallocate(dtmp)
+     endif
+
+     deallocate(colidx)
+     deallocate(tol)
+     deallocate(dupl_with)
+     deallocate(dupl_index)
+  endif
+
+  if (want_sorted) then
+    nkey = ODB_sortkeys(handle, ctrim(dtname))
+  else
+    nkey = -1
+  endif
+
+  if (nkey > 0 .and. nrows_out > 0 .and. .not. is_table) then
+    allocate(mkeys(nkey))
+
+    mkeys(:) = 0
+    rc = ODB_sortkeys(handle, ctrim(dtname), mkeys)
+
+    allocate(absmode(nkey))
+    absmode(:) = 0
+    inumabs = 0
+    CALL cODB_maxcols(maxcols)
+
+!    write(0,*)'--> maxcols, nkey   , mkeys(1:nkey)=',maxcols, nkey, mkeys(1:nkey)
+
+!--   Plus one to account the col#0
+!     Accumulate only active columns in the range of [1..ncols_out] or [-ncols_out..-1]
+    nkey = 0
+    do j=1,size(mkeys)
+      ikey = abs(mkeys(j))
+      if (ikey == 0) cycle
+      if (ikey > ncols_out .and. ikey <= maxcols) cycle
+      if (ikey > maxcols + ncols_out) cycle
+
+      if (ikey > maxcols) then
+        if (mkeys(j) > 0) then
+          ikey = mkeys(j) - maxcols + 1 ! ABS-sorting, ascending
+          absmode(nkey+1) = 1
+        else
+          ikey = -(abs(mkeys(j)) - maxcols + 1) ! ABS-sorting, descending
+          absmode(nkey+1) = -1
+        endif
+      else if (mkeys(j) > 0) then
+        ikey = mkeys(j) + 1 ! Ascending sort
+      else if (mkeys(j) < 0) then
+        ikey = mkeys(j) - 1 ! Descending sort
+      else
+        cycle
+      endif
+
+      if (takethis(abs(ikey)-1)) then
+        mkeys(nkey+1) = ikey
+        if (absmode(nkey+1) /= 0) inumabs = inumabs + 1
+        nkey = nkey + 1
+      else
+        absmode(nkey+1) = 0
+      endif
+    enddo
+
+!    write(0,*)'->> nkey   , mkeys(1:nkey)=',nkey, mkeys(1:nkey)
+!    write(0,*)'->> inumabs, absmode(1:nkey)=',inumabs, absmode(1:nkey)
+    
+    if (nkey > 0) then
+
+#if defined(LITTLE)
+!-- Little endian machines need to byteswap strings i.e. 8-byte holleriths to obtain
+!   correct sorting; After sorting bytes must be swapped back
+      ndtypes = ODB_getnames(handle, ctrim(dtname), 'datatype') 
+      allocate(CLdtypes(ndtypes))
+      ndtypes = ODB_getnames(handle, ctrim(dtname), 'datatype', CLdtypes) 
+      allocate(LLswap(nkey))
+      LLswap(:) = .FALSE.
+      do j=1,nkey
+        ikey = abs(mkeys(j)) - 1
+        if (CLdtypes(ikey) == 'string') then
+          LLswap(j) = .TRUE.
+          CALL swap8bytes(d(1,ikey), nrows_out)
+        endif
+      enddo
+      deallocate(CLdtypes)
+#endif
+
+      if (inumabs > 0) then ! ABS-sorting
+        allocate(dtmpabs(nrows_out,inumabs))
+        if (has_index) then
+           has_index_abs = .FALSE.
+        else
+           has_index_abs = .TRUE.
+           allocate(index_abs(1:nrows_out))
+        endif
+        jcol = 0
+        do j=1,nkey
+          if (absmode(j) /= 0) then
+            ikey = absmode(j) * mkeys(j) - 1
+            jcol = jcol + 1
+            do i=1,nrows_out
+              dtmpabs(i,jcol) = d(i,ikey)
+              if (d(i,ikey) < 0) d(i,ikey) = -d(i,ikey)
+            enddo
+          endif
+        enddo
+      endif
+
+      if (has_index) then
+        CALL keysort(rc, d, nrows_out, &
+               &multikey=mkeys(1:nkey), &
+               &index=index(1:nrows_out), init=.TRUE.)
+      else if (has_index_abs) then
+        CALL keysort(rc, d, nrows_out, &
+               &multikey=mkeys(1:nkey), &
+               &index=index_abs(1:nrows_out), init=.TRUE.)
+      else
+        CALL keysort(rc, d, nrows_out, &
+               &multikey=mkeys(1:nkey))
+      endif
+
+      if (inumabs > 0) then ! ABS-sorting (guaranteed via index-sorting)
+        jcol = 0
+        do j=1,nkey
+          if (absmode(j) /= 0) then
+            ikey = absmode(j) * mkeys(j) - 1
+            jcol = jcol + 1
+            d(1:nrows_out,ikey) = dtmpabs(1:nrows_out,jcol) ! index-sort => order preserved
+          endif
+        enddo
+        deallocate(dtmpabs)
+      endif
+
+      if (allocated(index_abs)) then ! need physical reordering
+        allocate(zbuf(nrows_out))
+        imaxcol = min(size(d,dim=2),size(takethis)) - 1
+        do j=0,imaxcol
+           if (j > 0 .and. .not. takethis(j)) cycle
+           zbuf(1:nrows_out) = d(index_abs(1:nrows_out),j)
+           d(1:nrows_out,j) = zbuf(1:nrows_out)
+        enddo
+        deallocate(index_abs)
+        deallocate(zbuf)
+      endif
+
+#if defined(LITTLE)
+!-- Little endian machines need to byteswap strings i.e. 8-byte holleriths to obtain
+!   correct sorting; After sorting bytes must be swapped back
+      do j=1,nkey
+        ikey = abs(mkeys(j)) - 1
+        if (LLswap(j)) CALL swap8bytes(d(1,ikey), nrows_out)
+      enddo
+      deallocate(LLswap)
+#endif
+
+      if (has_index) then
+        CALL cODB_ae_dump(handle, 7, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                          ldimd, nrows_out, ncols_out, d)
+      else
+        CALL cODB_ae_dump(handle, 8, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                          ldimd, nrows_out, ncols_out, d)
+      endif
+
+    endif ! if (nkey > 0) then
+
+    deallocate(mkeys)
+    deallocate(absmode)
+  endif ! if (nkey > 0 .and. nrows_out > 0 .and. .not. is_table) ...
+
+  if (allocated(iflag))    deallocate(iflag)
+  if (allocated(takethis)) deallocate(takethis)
+endif ! if (odbHcheck(handle, GEN_GETNAME))
+
+if (present(ncols)) then
+  if (icols > 0) then
+    ncols = icols - icols_aux
+  else
+    ncols = ncols_out
+  endif
+endif
+
+if (rc >= 0) then
+  rc = nrows_out
+endif
+
+CALL cODB_trace(handle, 0,&
+    &GEN_GETNAME//':'//dtname, idummy_arr, 0)
+99999 continue
+IF (LHOOK) CALL DR_HOOK(GEN_GETNAME,1,ZHOOK_HANDLE)
+END FUNCTION
+
+
+FUNCTION GEN_PUT(handle, dtname, d, nrows, ncols,&
+    &poolno, colput, colpack, sorted, offset, store_intermed, using) &
+    &RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: dtname
+GEN_TYPE, intent(inout)       :: d(:,0:)
+INTEGER(KIND=JPIM), intent(in)              :: nrows
+INTEGER(KIND=JPIM), intent(inout), optional :: ncols
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, offset, using
+logical, intent(in), optional :: colput(:), colpack(:)
+logical, intent(in), optional :: sorted, store_intermed
+INTEGER(KIND=JPIM) :: rc, ipoolno
+INTEGER(KIND=JPIM) :: i, j, jcol
+INTEGER(KIND=JPIM) :: nrows_out, nra
+INTEGER(KIND=JPIM) :: nrows_in, ncols_out, doffset
+INTEGER(KIND=JPIM) :: ldimd, ireplicate_PE, info(5)
+INTEGER(KIND=JPIM) :: icount, npes, nlastrow, ifill_intermed, using_it
+logical is_table, is_replicated, do_sort, LLsync, LLmpex1debug
+character(len=1) env
+INTEGER(KIND=JPIM) :: glbNpools, targetPE
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(0), nkey
+GEN_TYPE, allocatable :: dtmp(:,:)
+INTEGER(KIND=JPIM), allocatable :: ipool(:), npoollen(:), npoolptr(:)
+INTEGER(KIND=JPIM), allocatable :: nrowvec(:)
+INTEGER(KIND=JPIM), allocatable :: iflag(:)
+logical  , allocatable :: takethis(:)
+INTEGER(KIND=JPIM) opponent(ODBMP_nproc+1)
+INTEGER(KIND=JPIM) :: joppo, noppo, loopcnt, jloop, ipoolptr1, ipoolptr2, ndata
+INTEGER(KIND=JPIM) :: fast_physproc, xfast
+INTEGER(KIND=JPIM) :: ipoolno_save
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(GEN_PUTNAME,0,ZHOOK_HANDLE)
+
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+
+rc = 0
+ireplicate_PE = 0
+if (present(offset)) then
+  doffset = offset ! No checking by the way
+else
+  doffset = 0
+endif
+
+ipoolno = get_poolno(handle, poolno)
+
+if ( is_table .and. (&
+    &.not. ODB_valid_poolno(ipoolno) .or. ipoolno == -1) ) then
+  CALL ODB_abort(&
+       &GEN_PUTNAME,&
+       &'A valid local pool is required for TABLE put : "'//&
+       &trim(dtname)//'"',&
+       &ipoolno,&
+       &.FALSE.)
+  rc = -1
+  goto 99999
+endif
+
+ipoolno_save = ipoolno
+
+ldimd = size(d, dim=1)
+nrows_in = nrows
+ncols_out = size(d, dim=2) - 1
+if (present(ncols)) then
+  ncols_out = min(ncols,ncols_out)
+endif
+
+if (ldimd < nrows_in) then
+  rc = ldimd - nrows_in
+  CALL ODB_abort(&
+       &GEN_PUTNAME,&
+       &'The actual no. of rows is less than specified in TABLE/VIEW="'//&
+       &trim(dtname)//'"',&
+       &rc)
+  goto 99999
+endif
+
+do_sort = .FALSE.
+if (present(sorted)) do_sort = sorted
+
+ifill_intermed = 0
+if (present(store_intermed)) then
+  if (store_intermed) ifill_intermed = 1
+endif
+
+using_it = 0
+if (present(using)) using_it = using
+
+if (db_trace) then
+  info(1) = ldimd
+  info(2) = nrows_in
+  info(3) = ncols_out
+  info(4) = ifill_intermed
+  info(5) = using_it
+  CALL cODB_trace(handle, 1,&
+       &GEN_PUTNAME//':'//dtname, info, size(info))
+endif
+
+if (odbHcheck(handle, GEN_PUTNAME)) then
+  if (ODB_io_method(handle) == 5 .and. ifill_intermed /= 1) then
+    CALL ODB_abort(&
+      & GEN_PUTNAME, &
+      & 'ODB_IO_METHOD=5 does not allow ODB_put()-operations. Found with "'//&
+      & trim(dtname)//'"',&
+      & 5)
+    goto 99999
+  endif
+
+  allocate(iflag(ncols_out))
+
+  if (present(colput) .or. present(colpack)) then
+    iflag(:) = 0
+  else
+    iflag(:) = def_flag
+  endif
+
+  if (present(colput)) then
+    do i=1,min(ncols_out,size(colput))
+      if (colput(i)) iflag(i) = iflag(i) + flag_put
+    enddo
+!== Not putting back anything ==> skip extra processing
+    if (ALL(iflag(:) == 0)) goto 9999
+  endif
+
+  if (present(colpack)) then
+    do i=1,min(ncols_out,size(colpack))
+      if (colpack(i)) iflag(i) = iflag(i) + flag_pack
+    enddo
+  endif
+
+  allocate(takethis(0:ncols_out))
+  takethis(0) = .TRUE.
+  do i=1,ncols_out
+    takethis(i) = (IAND(iflag(i),flag_put) == flag_put)
+  enddo
+
+  if (is_table) then
+!--   A table
+
+!..   Note: Control word (column#0) is overwritten in the case of a table
+
+    if (nrows_in > 0) then
+      CALL cODB_put_control_word(d(1,0), &
+                                 0, nrows_in, 0, &
+                                 ipoolno, 0)
+    endif
+
+    npes = 0
+  else
+    CALL cODB_get_npes(handle, ipoolno,&
+         & ctrim(dtname), ireplicate_PE, rc, using_it)
+    is_replicated = (ireplicate_PE /= 0)
+
+    if (rc < 0) then
+      CALL ODB_abort(&
+             & GEN_PUTNAME, &
+             &'Cannot get NPES for VIEW="'//&
+             &trim(dtname)//'"',&
+             &rc)
+      goto 99999
+    endif
+
+    npes = rc
+
+    if (is_replicated .or. npes == 0) then
+!--   A replicated view; forget the "ipoolno"; it'll be determined 
+!     from the control word, column#0
+!     Note: Only local pools with local data mods will be affected
+!           thus no message passing is involved
+
+      icount = 0      
+      if (nrows_in > 0) then
+        allocate(ipool(nrows_in))
+        CALL cODB_get_poolnos(d(1,0), &
+                              0, nrows_in, 0, &
+                              ipool)
+
+        do j=1,nrows_in
+          ipoolno = ipool(j)
+          if (fast_physproc(ipoolno) /= ODBMP_myproc) then
+            icount = icount + 1
+            ipool(j) = -1
+          endif
+        enddo
+
+        if (icount > 0) then
+          CALL cODB_mask_control_word(d(1,0), &
+                                      0, nrows_in, 0, &
+                                      ipool)
+        endif
+
+        deallocate(ipool)
+      endif
+
+!-- Was sorted i.e. ORDERBY/SORTBY was present ? If yes ==> *must* sort
+      nkey = ODB_sortkeys(handle, ctrim(dtname))
+
+!-- Try to avoid unnecessary sorting and you will possibly save 
+!   a considerable amount of memory !!
+
+      if (do_sort .or. icount > 0 .or. is_replicated .or. nkey > 0) then
+        CALL cODB_ae_dump(handle, -1, ipoolno_save, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                          ldimd, nrows_in, ncols_out, d)
+
+        call ODB_ctrlw_sort(d, nrows_in, takethis)
+        nrows_in = nrows_in - icount
+      endif
+    else
+      CALL cODB_ae_dump(handle, -2, ipoolno_save, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                        ldimd, nrows_in, ncols_out, d)
+
+      call ODB_ctrlw_sort(d, nrows_in, takethis)
+
+      allocate(npoollen(npes))
+      allocate(npoolptr(npes))
+
+      if (nrows_in > 0) then
+        allocate(ipool(nrows_in))
+        CALL cODB_get_poolnos(d(1,0), &
+            & 0, nrows_in, 0, &
+            & ipool)
+        do ipoolno=1,npes
+          npoollen(ipoolno) = count(ipool(:) == ipoolno)
+        enddo
+        deallocate(ipool)
+      else
+        npoollen(:) = 0
+      endif
+
+      npoolptr(1) = 0
+      do ipoolno=2,npes
+        npoolptr(ipoolno) = npoolptr(ipoolno-1) + npoollen(ipoolno-1)
+      enddo
+
+      CALL cODB_getenv('ODB_MPEXCHANGE1_DEBUG', env)
+      LLmpex1debug = (env == '1')
+
+      allocate(nrowvec(npes))
+
+      CALL cODB_get_rowvec(handle, -1,&
+             &ctrim(dtname),&
+             &nrowvec, npes,&
+             &rc, using_it)
+
+      nrows_in = sum(nrowvec(:))
+
+      if (LLmpex1debug) then
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//':   nrows_in, npes, nrowvec(1:npes) [local]=',&
+                   nrows_in, npes, nrowvec(:)
+        call flush(6)
+      endif
+
+      CALL ODBMP_global('SUM', nrowvec)
+
+      nrows_out = 0
+      do j=1,npes
+        if (fast_physproc(j) == ODBMP_myproc) then
+          nrows_out = nrows_out + nrowvec(j)
+        endif
+      enddo
+
+      if (LLmpex1debug) then
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': nrows_out, npes, nrowvec(1:npes) [global]=',&
+                   nrows_out, npes, nrowvec(:)
+        call flush(6)
+      endif
+
+      nra = ODB_lda(nrows_out)
+      allocate(dtmp(nra,0:ncols_out))
+      !-- do only the necessary initializations
+      dtmp(:,0) = 0 ! control-word
+
+      !*** Note: npes is a kind of no. of pools over all procs
+
+      loopcnt = (npes + ODBMP_nproc - 1)/ODBMP_nproc
+      noppo = ODBMP_setup_exchange(opponent)
+
+      LLsync = (npes < ODBMP_nproc   .OR. &
+                noppo /= ODBMP_nproc .OR. &
+                mod(npes,ODBMP_nproc) /= 0)
+
+      if (LLmpex1debug) then
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': ODBMP_nproc, ODBMP_myproc, npes, loopcnt, noppo, LLsync=', &
+                                                     ODBMP_nproc, ODBMP_myproc, npes, loopcnt, noppo, LLsync
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': view='//ctrim(dtname)
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': opponent(:)=',opponent(:)
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': size(npoolptr), npoolptr(:)=',size(npoolptr), npoolptr(:)
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': size(npoollen), npoollen(:)=',size(npoollen), npoollen(:)
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': size & shape of d   =',size(d)   , shape(d)
+        write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': size & shape of dtmp=',size(dtmp), shape(dtmp)
+        call flush(6)
+      endif
+
+      CALL ODBMP_sync(where=0)
+      nlastrow = 0
+      do jloop=1,loopcnt
+        if (LLmpex1debug) then
+          write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': >jloop=',jloop
+          call flush(6)
+        endif
+        do joppo=1,noppo
+          targetPE = opponent(joppo)
+          if (LLmpex1debug) then
+            write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': >>> joppo, targetPE=',joppo,targetPE
+            call flush(6)
+          endif
+          if (targetPE >= 1 .and. targetPE <= ODBMP_nproc) then
+            j = targetPE + (jloop-1)*ODBMP_nproc !*** Pools j assigned in a round-robin fashion
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': j, npes=',j,npes
+              call flush(6)
+            endif
+            if (j <= npes) then
+              if (LLmpex1debug) then
+                write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': j,nlastrow,npoolptr(j),npoollen(j)=',&
+                                                             j,nlastrow,npoolptr(j),npoollen(j)
+                call flush(6)
+              endif
+              if (npoollen(j) > 0) then
+                ipoolptr1 = npoolptr(j)+1
+                ipoolptr2 = npoolptr(j)+npoollen(j)
+                ndata = npoollen(j)
+              else
+                ipoolptr1 = 0
+                ipoolptr2 = 0
+                ndata = 0
+              endif
+            else
+              ipoolptr1 = 0
+              ipoolptr2 = 0
+              ndata = 0
+            endif ! if (j <= npes) then ...
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': ==> j,nlastrow,ndata,ipoolptr1,ipoolptr2=',&
+                                                               j,nlastrow,ndata,ipoolptr1,ipoolptr2
+              call flush(6)
+            endif
+            CALL ODBMP_exchange1(targetPE,&
+                              &dtmp,nlastrow,&
+                              &d(ipoolptr1:ipoolptr2,:),&
+                              &ndata,ncols_out,takethis,LLmpex1debug)
+            if (LLmpex1debug) then
+              write(6,*) ODBMP_myproc,';'//GEN_PUTNAME//': <== j,nlastrow,ndata,ipoolptr1,ipoolptr2=',&
+                                                               j,nlastrow,ndata,ipoolptr1,ipoolptr2
+              call flush(6)
+            endif
+          endif ! if (targetPE >= 1 .and. targetPE <= ODBMP_nproc) then ...
+          if (LLsync) CALL ODBMP_sync(where=-joppo)
+        enddo ! do joppo=1,noppo
+        if (.not.LLsync) CALL ODBMP_sync(where=-jloop)
+      enddo ! do jloop=1,loopcnt
+
+      deallocate(npoollen)
+      deallocate(npoolptr)
+
+      if (nlastrow == nrows_out) then
+        if (nlastrow > 0) then
+          CALL cODB_ae_dump(handle, -3, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                            nra, nlastrow, ncols_out, dtmp)
+
+          CALL ODB_ctrlw_sort(dtmp, nlastrow, takethis)
+
+          CALL cODB_ae_dump(handle, -4, ipoolno, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                            nra, nlastrow, ncols_out, dtmp)
+
+          ipoolno = -1
+          CALL &
+            GEN_CODB_PUT &
+                &(handle, ipoolno,&
+                &ctrim(dtname), dtmp, 0, nra,&
+                &nlastrow, ncols_out, &
+                &iflag, -1, ifill_intermed, &
+                &using_it, rc)
+
+          if (rc /= nlastrow) then
+            CALL ODB_abort(&
+                  &GEN_PUTNAME, &
+                  &'Cannot put parallel data for VIEW="'//&
+                  &trim(dtname)//'"',&
+                  &rc)
+            rc = -2
+            goto 99999
+          endif
+        endif
+      else
+!        write(0,*)'nrows_out, nlastrow=',nrows_out, nlastrow
+        CALL ODB_abort(&
+                &GEN_PUTNAME, &
+                &'Unable to put ALL parallel data in VIEW="'//&
+                &trim(dtname)//'"',&
+                &nrows_out-nlastrow)
+        rc = -3
+        goto 99999
+      endif
+
+      deallocate(dtmp)
+      deallocate(nrowvec)
+
+      rc = nrows_out
+
+      nrows_in = 0 ! Put already performed
+    endif ! if (is_replicated .or. npes == 0) then ... else
+  endif ! if (is_table) then ... else
+
+  if (nrows_in > 0) then
+
+!--   This is for TABLEs or replicated VIEWs or non-shuffled VIEWs only
+
+    if (nrows_in >= ODB_MAXROWS) then
+!--   With 32-bit signed arithmetic should never enter here !!
+      rc = ODB_MAXROWS - nrows_in
+      CALL ODB_abort(&
+             &GEN_PUTNAME, &
+             &'Too many rows in VIEW/TABLE="'//&
+             &trim(dtname)//'"',&
+             &rc)
+      goto 99999
+    endif
+
+    if (nrows_in > 0) then
+      CALL cODB_ae_dump(handle, -5, ipoolno_save, ctrim(dtname), GEN_AE_DUMP_DATATYPE, &
+                        ldimd, nrows_in, ncols_out, d(1,0))
+
+      CALL &
+        GEN_CODB_PUT &
+          &(handle, ipoolno_save,&
+          &ctrim(dtname), d(1+doffset,0), 0, ldimd,&
+          &nrows_in, ncols_out, &
+          &iflag, -1, ifill_intermed, &
+          &using_it, rc)
+    endif
+
+    if (rc < 0) then
+      CALL ODB_abort(&
+             &GEN_PUTNAME, &
+             &'Cannot put data for VIEW/TABLE="'//&
+             &trim(dtname)//'"',&
+             &rc)
+      goto 99999
+    endif
+  endif
+
+9999 continue
+  if (allocated(iflag))    deallocate(iflag)
+  if (allocated(takethis)) deallocate(takethis)
+endif ! if (odbHcheck(handle, GEN_PUTNAME))
+
+if (present(ncols)) ncols = ncols_out
+
+CALL cODB_trace(handle, 0,&
+    &GEN_PUTNAME//':'//dtname, idummy_arr, 0)
+99999 continue
+IF (LHOOK) CALL DR_HOOK(GEN_PUTNAME,1,ZHOOK_HANDLE)
+END FUNCTION
+
+SUBROUTINE GEN_CTRLW_SORT(d, nrows_in, takethis)
+implicit none
+GEN_TYPE, intent(inout) :: d(:,0:)
+INTEGER(KIND=JPIM), intent(in)   :: nrows_in
+logical, intent(in)     :: takethis(0:)
+INTEGER(KIND=JPIM), allocatable :: ctrlw_index(:) ! can be large >> 100,000 elements
+INTEGER(KIND=JPIB), allocatable :: ctrlw(:)       ! can be large >> 100,000 elements (note: 64-bit int)
+INTEGER(KIND=JPIM), allocatable :: icols(:)
+GEN_TYPE , allocatable :: zbuf(:)
+INTEGER(KIND=JPIM) :: rc, j, imaxcol, inumcols, jj, inumt
+INTEGER(KIND=JPIM), external :: get_max_threads
+logical :: LLomp_okay
+REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_HANDLE_OMP
+IF (LHOOK) CALL DR_HOOK(GEN_CTRLW_SORTNAME,0,ZHOOK_HANDLE)
+if (nrows_in > 0) then
+  allocate(ctrlw(nrows_in), ctrlw_index(nrows_in))
+  CALL cODB_get_control_word(d(1,0), 0, nrows_in, 0, ctrlw(1))
+  CALL keysort(rc, ctrlw, nrows_in, index=ctrlw_index, init=.TRUE.)
+  deallocate(ctrlw)
+  imaxcol = min(size(d,dim=2),size(takethis)) - 1
+  allocate(icols(imaxcol+1))
+  jj = 0
+  do j=0,imaxcol
+    if (j > 0 .and. .not. takethis(j)) cycle
+    jj = jj + 1
+    icols(jj) = j
+  enddo
+  inumcols = jj
+  inumt = get_max_threads()
+!  LLomp_okay = ( &
+!       & nrows_in > 10000 .and. &
+!       & inumcols >= inumt .and. &
+!       & .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP & too short loops/too few columns
+!!$OMP PARALLEL PRIVATE(j,jj,zbuf,ZHOOK_HANDLE_OMP) IF (LLomp_okay)
+!  IF (LHOOK) CALL DR_HOOK(GEN_CTRLW_SORTNAME_OMP,0,ZHOOK_HANDLE_OMP)
+  allocate(zbuf(nrows_in))
+!!$OMP DO SCHEDULE(DYNAMIC,1)
+  do jj=1,inumcols
+    j = icols(jj)
+    zbuf(1:nrows_in) = d(ctrlw_index(1:nrows_in),j)
+    d(1:nrows_in,j) = zbuf(1:nrows_in)
+  enddo
+!!$OMP END DO
+  deallocate(zbuf)
+!  IF (LHOOK) CALL DR_HOOK(GEN_CTRLW_SORTNAME_OMP,1,ZHOOK_HANDLE_OMP)
+!!$OMP END PARALLEL
+  deallocate(ctrlw_index, icols)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK(GEN_CTRLW_SORTNAME,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+#ifndef NO_UNDEF
+#undef GEN_TYPE
+#undef GEN_GET
+#undef GEN_PUT
+#undef GEN_GETNAME
+#undef GEN_PUTNAME
+#undef GEN_CODB_GET
+#undef GEN_CODB_PUT
+#undef GEN_INC
+#undef GEN_CTRLW_SORT
+#undef GEN_CTRLW_SORTNAME
+#undef GEN_CTRLW_SORTNAME_OMP
+#undef GEN_AE_DUMP_DATATYPE
+#endif
+
+#endif
diff --git a/odb/src/include/fodbmp.h b/odb/src/include/fodbmp.h
new file mode 100644
index 0000000..591f417
--- /dev/null
+++ b/odb/src/include/fodbmp.h
@@ -0,0 +1,272 @@
+#if INT_VERSION == 4
+
+#define GEN_TYPE          INTEGER(KIND=JPIM)
+#define GEN_MSGTYPE       1
+#define GEN_GLOPER_SC     ODBMP_iglobal_scalar
+#define GEN_GLOPER        ODBMP_iglobal
+#define GEN_GLOPER_2D     ODBMP_iglobal_2d
+#define GEN_GLOPER_3D     ODBMP_iglobal_3d
+#define GEN_GLOPER_NAME  'ODBMP:ODBMP_IGLOBAL'
+#define GEN_DISTRIBUTE_1D       ODBMP_idistribute
+#define GEN_DISTRIBUTE_1D_NAME 'ODBMP:ODBMP_IDISTRIBUTE'
+
+#elif REAL_VERSION == 8
+
+#define GEN_TYPE          REAL(KIND=JPRB)
+#define GEN_MSGTYPE       8
+#define GEN_GLOPER_SC     ODBMP_dglobal_scalar
+#define GEN_GLOPER        ODBMP_dglobal
+#define GEN_GLOPER_2D     ODBMP_dglobal_2d
+#define GEN_GLOPER_3D     ODBMP_dglobal_3d
+#define GEN_GLOPER_NAME  'ODBMP:ODBMP_DGLOBAL'
+#define GEN_DISTRIBUTE_1D       ODBMP_ddistribute
+#define GEN_DISTRIBUTE_1D_NAME 'ODBMP:ODBMP_DDISTRIBUTE'
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(INT_VERSION) || defined(REAL_VERSION)
+
+SUBROUTINE GEN_GLOPER_SC &
+    &(operation,&
+    &v, root, ldreprod)
+implicit none
+character(len=*), intent(in)  :: operation
+GEN_TYPE,       intent(inout) :: v
+INTEGER(KIND=JPIM), intent(in), optional :: root
+logical, intent(in), optional :: ldreprod
+GEN_TYPE v1d(1)
+logical LLcopy
+if (ODBMP_nproc <= 1) return
+v1d(1) = v
+CALL &
+    GEN_GLOPER (operation, v1d, root, ldreprod)
+if (present(root)) then
+  LLcopy = .FALSE.
+  if (root == ODBMP_myproc .or. root == -1) LLcopy = .TRUE.
+else
+  LLcopy = .TRUE.
+endif
+if (LLcopy) v = v1d(1)
+END SUBROUTINE
+
+SUBROUTINE GEN_GLOPER_2D &
+    &(operation,&
+    &v, root, ldreprod)
+implicit none
+character(len=*), intent(in)  :: operation
+GEN_TYPE,       intent(inout) :: v(:,:)
+INTEGER(KIND=JPIM), intent(in), optional :: root
+logical, intent(in), optional :: ldreprod
+GEN_TYPE v1d(size(v))
+INTEGER(KIND=JPIM) :: nr, nc
+INTEGER(KIND=JPIM) :: i, j, k
+logical LLcopy
+if (ODBMP_nproc <= 1) return
+nr = size(v,dim=1)
+nc = size(v,dim=2)
+k = 0
+do j=1,nc
+  do i=1,nr
+    k = k + 1
+    v1d(k) = v(i,j)
+  enddo
+enddo
+CALL &
+     GEN_GLOPER (operation, v1d, root, ldreprod)
+if (present(root)) then
+  LLcopy = .FALSE.
+  if (root == ODBMP_myproc .or. root == -1) LLcopy = .TRUE.
+else
+  LLcopy = .TRUE.
+endif
+if (LLcopy) then
+  k = 0
+  do j=1,nc
+    do i=1,nr
+      k = k + 1
+      v(i,j) = v1d(k)
+    enddo
+  enddo
+endif
+END SUBROUTINE
+
+SUBROUTINE GEN_GLOPER_3D &
+    &(operation,&
+    &v, root, ldreprod)
+implicit none
+character(len=*), intent(in)  :: operation
+GEN_TYPE,       intent(inout) :: v(:,:,:)
+INTEGER(KIND=JPIM), intent(in), optional :: root
+logical, intent(in), optional :: ldreprod
+GEN_TYPE v1d(size(v))
+INTEGER(KIND=JPIM) :: nr, nc, nt
+INTEGER(KIND=JPIM) :: i, j, t, k
+logical LLcopy
+if (ODBMP_nproc <= 1) return
+nr = size(v,dim=1)
+nc = size(v,dim=2)
+nt = size(v,dim=3)
+k = 0
+do t=1,nt
+  do j=1,nc
+    do i=1,nr
+      k = k + 1
+      v1d(k) = v(i,j,t)
+    enddo
+  enddo
+enddo
+CALL &
+     GEN_GLOPER (operation, v1d, root, ldreprod)
+if (present(root)) then
+  LLcopy = .FALSE.
+  if (root == ODBMP_myproc .or. root == -1) LLcopy = .TRUE.
+else
+  LLcopy = .TRUE.
+endif
+if (LLcopy) then
+  k = 0
+  do t=1,nt
+    do j=1,nc
+      do i=1,nr
+        k = k + 1
+        v(i,j,t) = v1d(k)
+      enddo
+    enddo
+  enddo
+endif
+END SUBROUTINE
+
+
+SUBROUTINE GEN_GLOPER &
+    &(operation,&
+    &v, root, ldreprod)
+USE MPL_MODULE
+implicit none
+character(len=*), intent(in)  :: operation
+GEN_TYPE,       intent(inout) :: v(:)
+INTEGER(KIND=JPIM), intent(in), optional :: root
+logical, intent(in), optional :: ldreprod
+GEN_TYPE tmp(size(v))
+logical LLcopy
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(GEN_GLOPER_NAME,0,ZHOOK_HANDLE)
+if (ODBMP_nproc <= 1) goto 99999
+if (present(root)) then
+  LLcopy = .FALSE.
+  if (root == ODBMP_myproc .or. root == -1) LLcopy = .TRUE.
+else
+  LLcopy = .TRUE.
+endif
+if (LLcopy) then ! "v" gets updated directly
+  CALL MPL_ALLREDUCE(v,operation,LDREPROD=ldreprod)
+else ! Do *not* update values of "v"
+  tmp = v
+  CALL MPL_ALLREDUCE(tmp,operation,LDREPROD=ldreprod)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK(GEN_GLOPER_NAME,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+
+SUBROUTINE GEN_DISTRIBUTE_1D &
+  (s, slen, with, rc)
+USE MPL_MODULE
+implicit none
+INTEGER(KIND=JPIM), intent(in)    :: slen, with
+GEN_TYPE , intent(inout) :: s(slen)
+INTEGER(KIND=JPIM), intent(out)   :: rc
+INTEGER(KIND=JPIM), parameter :: msgtype = GEN_MSGTYPE
+INTEGER(KIND=JPIM), parameter :: msgtag = 1997
+INTEGER(KIND=JPIM) :: target, info(4)
+INTEGER(KIND=JPIM) :: recv_count, recv_from, recv_tag
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(GEN_DISTRIBUTE_1D_NAME,0,ZHOOK_HANDLE)
+if (ODBMP_nproc > 1) then
+  if (with == 0) then
+!--   PE#1 (=rootPE) distributes, all other PEs receive;
+!     All in one routine
+    if (mp_trace) then
+      info(1) = rootPE
+      info(2) = slen
+      info(3) = msgtag
+      info(4) = msgtype
+      CALL cODB_trace(-1, 1, &
+          & GEN_DISTRIBUTE_1D_NAME &
+          & //':broadcast',info,4)
+    endif
+    CALL MPL_BROADCAST(s(:),kroot=rootPE,ktag=msgtag,kerror=rc)
+    if (mp_trace) then
+      info(1) = rootPE
+      info(2) = slen
+      info(3) = msgtag
+      info(4) = rc
+      CALL cODB_trace(-1, 0, &
+          & GEN_DISTRIBUTE_1D_NAME &
+          & //':broadcast',info,4)
+    endif
+    if (rc == Success) rc = slen
+  else
+    target = max(1,min(abs(with),ODBMP_nproc))
+    if (with > 0) then
+!--   I'll send()
+      if (mp_trace) then
+        info(1) = target
+        info(2) = slen
+        info(3) = msgtag
+        info(4) = msgtype
+        CALL cODB_trace(-1, 2, &
+          & GEN_DISTRIBUTE_1D_NAME &
+          & //':send',info,4)
+      endif
+      CALL MPL_SEND(s(:),kdest=target,ktag=msgtag,kerror=rc)
+      if (rc == Success) rc = slen
+    else
+!--   I'll recv()
+      if (mp_trace) then
+        info(1) = target
+        info(2) = slen
+        info(3) = msgtag
+        info(4) = msgtype
+        CALL cODB_trace(-1, 1, &
+          & GEN_DISTRIBUTE_1D_NAME &
+          & //':recv',info,4)
+      endif
+      CALL MPL_RECV(s(:),ksource=target,ktag=msgtag,&
+       &kount=recv_count,kfrom=recv_from,krecvtag=recv_tag,kerror=rc)
+      if (mp_trace) then
+        info(1) = recv_from
+        info(2) = recv_count
+        info(3) = recv_tag
+        info(4) = rc
+        CALL cODB_trace(-1, 0, &
+          & GEN_DISTRIBUTE_1D_NAME &
+          & //':recv',info,4)
+      endif
+      if (rc == Success) rc = recv_count
+    endif
+  endif
+else
+!--   Only one PE; do nothing
+  rc = slen
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK(GEN_DISTRIBUTE_1D_NAME,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+#ifndef NO_UNDEF
+#undef GEN_TYPE
+#undef GEN_MSGTYPE
+#undef GEN_GLOPER_SC
+#undef GEN_GLOPER
+#undef GEN_GLOPER_2D
+#undef GEN_GLOPER_3D
+#undef GEN_GLOPER_NAME
+#undef GEN_DISTRIBUTE_1D
+#undef GEN_DISTRIBUTE_1D_NAME
+#endif
+
+#endif
diff --git a/odb/src/include/fodbmp1.h b/odb/src/include/fodbmp1.h
new file mode 100644
index 0000000..5b0c721
--- /dev/null
+++ b/odb/src/include/fodbmp1.h
@@ -0,0 +1,241 @@
+#if INT_VERSION == 4
+
+#define GEN_TYPE          INTEGER(KIND=JPIM)
+#define GEN_MSGTYPE       1
+#define GEN_XCHANGE1       ODBMP_iexchange1
+#define GEN_XCHANGE1_NAME 'ODBMP:ODBMP_IEXCHANGE1'
+
+#elif REAL_VERSION == 8
+
+#define GEN_TYPE          REAL(KIND=JPRB)
+#define GEN_MSGTYPE       8
+#define GEN_XCHANGE1       ODBMP_dexchange1
+#define GEN_XCHANGE1_NAME 'ODBMP:ODBMP_DEXCHANGE1'
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(INT_VERSION) || defined(REAL_VERSION)
+
+SUBROUTINE GEN_XCHANGE1 &
+    &(targetPE, &
+    &to, nlastrow, &
+    &from, nrows, ncols, &
+    &takethis, LDdebug)
+USE MPL_MODULE
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)    :: targetPE, nrows, ncols
+INTEGER(KIND=JPIM), intent(inout) :: nlastrow
+GEN_TYPE, intent(out)  :: to(:,0:)
+GEN_TYPE, intent(in)   :: from(:,0:)
+logical , intent(in)   :: takethis(0:), LDdebug
+
+INTEGER(KIND=JPIM), parameter :: datatype = GEN_MSGTYPE
+INTEGER(KIND=JPIM) :: msgtag_send, msgtag_recv, j, rc, info(8)
+INTEGER(KIND=JPIM) :: recv_count, recv_from, recv_tag
+INTEGER(KIND=JPIM) :: nlastrow_local, freerows
+INTEGER(KIND=JPIM) :: ireq(1+ncols), nreq
+INTEGER(KIND=JPIM) :: ireq_zerodata(1+ncols), nreq_zerodata
+GEN_TYPE :: zerodata(0)
+logical LLsuppress_send, LLsuppress_recv
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(GEN_XCHANGE1_NAME,0,ZHOOK_HANDLE)
+
+nreq=0
+nreq_zerodata=0
+freerows = size(to,dim=1) - nlastrow
+
+if (LDdebug) then
+  write(6,'(a1,i2,a,10i8)') &
+           '#',ODBMP_myproc, ': '// GEN_XCHANGE1_NAME &
+           //' targetPE, nlastrow, nrows, ncols, freerows, size(to,dim=1), size(from,dim=1)=', &
+               targetPE, nlastrow, nrows, ncols, freerows, size(to,dim=1), size(from,dim=1)
+  call flush(6)
+endif
+
+if (&
+    ((targetPE == ODBMP_myproc) .and. (nrows > 0 .and. freerows < nrows)) .OR. &
+    ((targetPE /= ODBMP_myproc) .and. (freerows < 0))) then
+    write(0,*) ODBMP_myproc, ': '// GEN_XCHANGE1_NAME &
+           //' targetPE, nlastrow, nrows, ncols, freerows, size(to,dim=1), size(from,dim=1)=', &
+               targetPE, nlastrow, nrows, ncols, freerows, size(to,dim=1), size(from,dim=1)
+    CALL ODBMP_abort(&
+                     & GEN_XCHANGE1_NAME, &
+                     & 'Insufficient amount of free rows in destination matrix', &
+                     & freerows-nrows)
+endif
+
+if (targetPE == ODBMP_myproc) then
+!== Perform local copying only
+  recv_count = 0
+  if (nrows > 0) then
+    COPY_MYSELF_LOOP: do j=0,ncols
+      if (j > 0 .and. .not. takethis(j)) cycle COPY_MYSELF_LOOP ! Always take col#0, however!
+      to(nlastrow+1:nlastrow+nrows,j) = from(1:nrows,j)
+    enddo COPY_MYSELF_LOOP
+    nlastrow = nlastrow + nrows
+  endif
+  goto 999
+endif
+
+LLsuppress_send=.FALSE.
+LLsuppress_recv=.FALSE.
+nlastrow_local = nlastrow
+COMM_LOOP: do j=0,ncols
+  if (LLsuppress_send .and. LLsuppress_recv) exit COMM_LOOP
+  if (j > 0 .and. .not. takethis(j)) cycle COMM_LOOP ! Always take col#0, however!
+  rc = 0
+  if (LLsuppress_send) goto 2001
+
+  msgtag_send = targetPE * 100 + j
+
+  if (mp_trace) then
+    info(1) = j
+    info(2) = targetPE
+    info(3) = nrows
+    info(4) = msgtag_send
+    info(5) = datatype
+    CALL cODB_trace(-1, 2, &
+        & GEN_XCHANGE1_NAME &
+        & //':send column',info,5)
+  endif
+
+  if (LDdebug) then
+    write(6,*) '#',ODBMP_myproc, ': send() to PE#',targetPE,&
+               ' j, nrows, msgtag_send=',&
+                 j, nrows, msgtag_send
+    call flush(6)
+  endif
+
+  if (nrows > 0) then
+    nreq=nreq+1
+    CALL MPL_SEND(from(1:nrows,j),kdest=targetPE,ktag=msgtag_send,kmp_type=JP_NON_BLOCKING_STANDARD, &
+                  krequest=ireq(nreq), kerror=rc)
+  else
+    nreq_zerodata=nreq_zerodata+1
+    CALL MPL_SEND(zerodata,kdest=targetPE,ktag=msgtag_send,kmp_type=JP_NON_BLOCKING_STANDARD, &
+                  krequest=ireq_zerodata(nreq_zerodata), kerror=rc)
+    LLsuppress_send = .TRUE. ! Send zero length data once only
+    if (LDdebug .and. LLsuppress_send) then
+      write(6,*) '#',ODBMP_myproc, ": Further send()'s suppressed"
+      call flush(6)
+    endif
+  endif
+
+  if (rc /= 0) then
+    write(0,*) ODBMP_myproc,': Failed to send() data to PE#',targetPE,&
+                            ' : j, nrows, msgtag_send, rc=',&
+                                j, nrows, msgtag_send, rc
+    CALL ODBMP_abort(&
+                     & GEN_XCHANGE1_NAME, &
+                     & 'Failed to send() data', &
+                     & rc)
+  endif
+
+2001 continue
+  if (LLsuppress_recv) cycle COMM_LOOP
+
+  msgtag_recv = ODBMP_myproc * 100 + j
+
+  if (mp_trace) then
+    info(1) = j
+    info(2) = targetPE
+    info(3) = nrows
+    info(4) = msgtag_recv
+    info(5) = datatype
+    info(6) = rc
+    info(7) = nlastrow
+    info(8) = freerows
+    CALL cODB_trace(-1, 1, &
+        & GEN_XCHANGE1_NAME &
+        & //':send rc/last; begin recv column',info,8)
+  endif
+
+  if (LDdebug) then
+    write(6,*) '#',ODBMP_myproc, ': >>recv() from PE#',targetPE,&
+               ' j, msgtag_recv, freerows, nlastrow=',&
+                 j, msgtag_recv, freerows, nlastrow
+    call flush(6)
+  endif
+
+  if (freerows > 0) then
+    CALL MPL_RECV(to(nlastrow+1:nlastrow+freerows,j),ksource=targetPE,ktag=msgtag_recv,&
+                 &kount=recv_count,kfrom=recv_from,krecvtag=recv_tag,kerror=rc)
+  else
+    CALL MPL_RECV(zerodata,ksource=targetPE,ktag=msgtag_recv,&
+                 &kount=recv_count,kfrom=recv_from,krecvtag=recv_tag,kerror=rc)
+  endif
+
+  if (LDdebug) then
+    write(6,*) '#',ODBMP_myproc, ': <<recv() from PE#',targetPE,&
+               ' j, msgtag_recv, freerows, nlastrow, recv_count, recv_from, recv_tag, rc=',&
+                 j, msgtag_recv, freerows, nlastrow, recv_count, recv_from, recv_tag, rc
+    call flush(6)
+  endif
+
+  if (rc /= 0) then
+    write(0,*) ODBMP_myproc,': Failed to recv() data from PE#',targetPE,&
+               ' : j, msgtag_recv, freerows, nlastrow, recv_count, recv_from, recv_tag, rc=',&
+                   j, msgtag_recv, freerows, nlastrow, recv_count, recv_from, recv_tag, rc
+    CALL ODBMP_abort(&
+                     & GEN_XCHANGE1_NAME, &
+                     & 'Failed to recv() data', &
+                     & rc)
+  endif
+
+  if (mp_trace) then
+    info(1) = j
+    info(2) = recv_from
+    info(3) = recv_count
+    info(4) = recv_tag
+    info(5) = datatype
+    info(6) = rc
+    info(7) = nlastrow
+    info(8) = freerows
+    CALL cODB_trace(-1, 0, &
+        & GEN_XCHANGE1_NAME &
+        & //':              end recv column',info,8)
+  endif
+
+  if (j == 0) then
+    nlastrow_local = nlastrow_local + recv_count
+    LLsuppress_recv = (recv_count == 0)
+    if (LDdebug .and. LLsuppress_recv) then
+      write(6,*) '#',ODBMP_myproc, ": Further recv()'s suppressed"
+      call flush(6)
+    endif
+  endif
+enddo COMM_LOOP
+nlastrow = nlastrow_local
+
+
+999 continue
+if (LDdebug) then
+  write(6,'(a1,i2,a,10i8)') &
+           '#',ODBMP_myproc, ': '// GEN_XCHANGE1_NAME &
+           //' targetPE, nlastrow, recv_count=', &
+               targetPE, nlastrow, recv_count
+  call flush(6)
+endif
+if (nreq > 0) then
+     call MPL_WAIT(from(1:nrows, 1), krequest=ireq(1:nreq), cdstring=GEN_XCHANGE1_NAME//' : wait for send data')
+end if
+if (nreq_zerodata > 0) then
+    call MPL_WAIT(zerodata, krequest=ireq_zerodata(1:nreq_zerodata), cdstring=GEN_XCHANGE1_NAME//' : wait for send zerodata')
+end if
+
+IF (LHOOK) CALL DR_HOOK(GEN_XCHANGE1_NAME,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+#ifndef NO_UNDEF
+#undef GEN_TYPE
+#undef GEN_MSGTYPE
+#undef GEN_XCHANGE1
+#undef GEN_XCHANGE1_NAME
+#endif
+
+#endif
diff --git a/odb/src/include/fodbmp2.h b/odb/src/include/fodbmp2.h
new file mode 100644
index 0000000..364f8d1
--- /dev/null
+++ b/odb/src/include/fodbmp2.h
@@ -0,0 +1,172 @@
+#if INT_VERSION == 4
+
+#define GEN_TYPE          INTEGER(KIND=JPIM)
+#define GEN_MSGTYPE       1
+#define GEN_SIZEOF_DATA   4
+#define GEN_XCHANGE2       ODBMP_iexchange2
+#define GEN_XCHANGE2_NAME 'ODBMP:ODBMP_IEXCHANGE2'
+
+#elif REAL_VERSION == 8
+
+#define GEN_TYPE          REAL(KIND=JPRB)
+#define GEN_MSGTYPE       8
+#define GEN_SIZEOF_DATA   8
+#define GEN_XCHANGE2       ODBMP_dexchange2
+#define GEN_XCHANGE2_NAME 'ODBMP:ODBMP_DEXCHANGE2'
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(INT_VERSION) || defined(REAL_VERSION)
+
+SUBROUTINE GEN_XCHANGE2 &
+    &(to, nlastrow, &
+    &from, nrows, ncols, &
+    &takethis)
+USE MPL_MODULE
+USE OML_MOD, ONLY : OML_SET_LOCK, OML_UNSET_LOCK
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: nrows(:), ncols
+INTEGER(KIND=JPIM), intent(out) :: nlastrow
+GEN_TYPE, intent(out)  :: to(:,0:)
+GEN_TYPE, intent(in)   :: from(:,0:)
+logical , intent(in)   :: takethis(0:)
+
+INTEGER(KIND=JPIM) :: ldimto, ldimfrom
+INTEGER(KIND=JPIM) :: i, ii, j, jcol, jroc
+INTEGER(KIND=JPIM) :: icols, icolumn(ncols+1)
+INTEGER(KIND=JPIM) :: istat_from, ilen_from
+INTEGER(KIND=JPIM) :: istat_to  , ilen_to
+INTEGER(KIND=JPIM) :: nrows_tmp(size(nrows))
+GEN_TYPE, allocatable :: tmp_from(:), tmp_to(:)
+character(len=256) CLtmp
+character(len=20) CLenv
+logical, save :: first_time = .TRUE.
+INTEGER(KIND=JPIM), save :: imax = 0
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK(GEN_XCHANGE2_NAME,0,ZHOOK_HANDLE)
+
+ldimto   = size(to, dim=1)
+ldimfrom = size(from, dim=1)
+
+nlastrow = sum(nrows(:))
+
+!-- nobody sends/receives anything ==> suppress message passing
+if (nlastrow <= 0) then
+  IF (LHOOK) CALL DR_HOOK(GEN_XCHANGE2_NAME,1,ZHOOK_HANDLE)
+  return 
+endif
+
+if (nlastrow > ldimto) then
+  write(0,*)'***Error: Recv-array is too small in '// &
+             GEN_XCHANGE2_NAME
+  CALL ODBMP_abort(GEN_XCHANGE2_NAME,'Recv-array is too small',ldimto-nlastrow)
+endif
+
+if (first_time) then
+!$ CALL OML_SET_LOCK()
+ if (first_time) then
+  CALL cODB_getenv('ODB_MPEXCHANGE2_PACKMAX', CLenv) ! in bytes
+  if (CLenv == ' ') then
+!-- the default: a rudimentary control to prevent excessive memory usage on recv-side
+!!    imax = MPL_MBX_SIZE/GEN_SIZEOF_DATA ! now in respective words
+    imax = 0
+  else
+    read(CLenv,*) imax
+    imax = imax/GEN_SIZEOF_DATA ! now in respective words
+  endif
+  first_time =.FALSE.
+ endif
+!$ CALL OML_UNSET_LOCK()
+endif
+
+ilen_from = 0
+ilen_to = 0
+icols = 0
+icolumn(:) = -1
+do j=0,ncols
+  if (j > 0 .and. .not. takethis(j)) cycle ! Always take col#0, however!
+  icols = icols + 1
+  icolumn(icols) = j
+enddo
+
+ilen_from = icols * nrows(ODBMP_myproc)
+ilen_to   = icols * nlastrow
+
+!-- to be done : blocking i.e. 'nproma'-like approach in splitting
+
+if (icols > 1 .and. ilen_to < imax) then
+#ifndef VPP
+  write(CLtmp,'(a,i12,a,i12)') GEN_XCHANGE2_NAME &
+     //' via single allgatherv : recv-size ',ilen_to,' < limit ',imax
+#endif
+allocate(tmp_from(ilen_from), stat=istat_from)
+  if (istat_from /= 0) then
+    write(0,*)'***Error: Unable to allocate memory (',ilen_from,' words) for "tmp_from" in '// &
+               GEN_XCHANGE2_NAME
+    CALL ODBMP_abort(GEN_XCHANGE2_NAME,'Unable to allocate memory for "tmp_from"',istat_from)
+  endif
+
+  allocate(tmp_to(ilen_to), stat=istat_to)
+  if (istat_to /= 0) then
+    write(0,*)'***Error: Unable to allocate memory (',ilen_to,' words) for "tmp_to" in '// &
+               GEN_XCHANGE2_NAME
+    CALL ODBMP_abort(GEN_XCHANGE2_NAME,'Unable to allocate memory for "tmp_to"',istat_to)
+  endif
+
+  i = 0
+  do jcol=1,icols
+    j = icolumn(jcol)
+    tmp_from(i+1:i+nrows(ODBMP_myproc)) = from(1:nrows(ODBMP_myproc),j)
+    i = i + nrows(ODBMP_myproc)
+  enddo
+  nrows_tmp(:) = icols * nrows(:)
+
+  CALL MPL_ALLGATHERV(tmp_from, tmp_to, nrows_tmp, &
+                     & cdstring= GEN_XCHANGE2_NAME )
+
+  deallocate(tmp_from)
+
+  i = 0
+  ii = 0
+  do jroc=1,ODBMP_nproc
+    do jcol=1,icols
+      j = icolumn(jcol)
+      to(i+1:i+nrows(jroc),j) = tmp_to(ii+1:ii+nrows(jroc))
+      ii = ii + nrows(jroc)
+    enddo
+    i = i + nrows(jroc)
+  enddo
+
+  deallocate(tmp_to)
+else
+#ifndef VPP
+  if (icols > 1) then
+    write(CLtmp,'(a,i5,a,i12,a,i12)') GEN_XCHANGE2_NAME &
+       //' via multiple (',icols,') allgathervs : recv-size ',ilen_to,' >= limit ',imax
+  endif
+#endif
+  do j=0,ncols
+    if (j > 0 .and. .not. takethis(j)) cycle ! Always take col#0, however!
+CALL MPL_ALLGATHERV(from(1:nrows(ODBMP_myproc),j), &
+                       & to(1:nlastrow,j), nrows, &
+                       & cdstring= GEN_XCHANGE2_NAME )
+  enddo
+endif
+
+IF (LHOOK) CALL DR_HOOK(GEN_XCHANGE2_NAME,1,ZHOOK_HANDLE)
+END SUBROUTINE
+
+#ifndef NO_UNDEF
+#undef GEN_TYPE
+#undef GEN_MSGTYPE
+#undef GEN_SIZEOF_DATA
+#undef GEN_XCHANGE2
+#undef GEN_XCHANGE2_NAME
+#endif
+
+#endif
diff --git a/odb/src/include/fodbutil.h b/odb/src/include/fodbutil.h
new file mode 100644
index 0000000..54ced46
--- /dev/null
+++ b/odb/src/include/fodbutil.h
@@ -0,0 +1,809 @@
+#if INT_VERSION == 4
+
+#define GEN_TYPE             INTEGER(KIND=JPIM)
+#define GEN_TOLSEARCH        ODB_itolsearch
+#define GEN_TOLSEARCH_NAME  'ODB_itolsearch'
+#define GEN_BINSEARCH        ODB_ibinsearch
+#define GEN_BINSEARCH_NAME  'ODB_ibinsearch'
+#define GEN_DUPL0            iduplchk0
+#define GEN_DUPL0_NAME      'iduplchk0'
+#define GEN_UI_RATIO         1
+#define GEN_DUPL             ODB_iduplchk
+#define GEN_DUPL_NAME       'ODB_iduplchk'
+#define GEN_GROUP            ODB_igroupify
+#define GEN_GROUP_NAME      'ODB_igroupify'
+#define GEN_UNIQUE_FUNC      cODB_ui_unique
+#define GEN_AGGR             ODB_iaggregate
+#define GEN_AGGR_NAME       'ODB_iaggregate'
+
+#elif REAL_VERSION == 8
+
+#define GEN_TYPE             REAL(KIND=JPRB)
+#define GEN_TOLSEARCH        ODB_dtolsearch
+#define GEN_TOLSEARCH_NAME  'ODB_dtolsearch'
+#define GEN_BINSEARCH        ODB_dbinsearch
+#define GEN_BINSEARCH_NAME  'ODB_dbinsearch'
+#define GEN_DUPL0            dduplchk0
+#define GEN_DUPL0_NAME      'dduplchk0'
+#define GEN_UI_RATIO         2
+#define GEN_DUPL             ODB_dduplchk
+#define GEN_DUPL_NAME       'ODB_dduplchk'
+#define GEN_GROUP            ODB_dgroupify
+#define GEN_GROUP_NAME      'ODB_dgroupify'
+#define GEN_UNIQUE_FUNC      cODB_d_unique
+#define GEN_AGGR             ODB_daggregate
+#define GEN_AGGR_NAME       'ODB_daggregate'
+
+#else
+
+  ERROR in programming : No datatype given (should never have ended up here)
+
+#endif
+
+#if defined(INT_VERSION) || defined(REAL_VERSION)
+
+FUNCTION GEN_DUPL0(&
+    &a, nrows, ncols, npkcols,&
+    &colidx, dupl_with,idx)&
+    &RESULT(ndupl)
+
+implicit none
+INTEGER(KIND=JPIM), intent(in)     :: nrows, ncols, npkcols
+INTEGER(KIND=JPIM), intent(out)    :: dupl_with(:)
+GEN_TYPE, intent(in)      :: a(:,:)
+INTEGER(KIND=JPIM),  intent(in)    :: colidx(npkcols)
+INTEGER(KIND=JPIM),intent(in),optional :: idx(:)
+
+INTEGER(KIND=JPIM) :: cnt(nrows), info(5 + npkcols)
+INTEGER(KIND=JPIM) :: ndupl, kpkcols
+INTEGER(KIND=JPIM) :: i, j, jj, kk, nldx, itag, ihash
+INTEGER(KIND=JPIM) :: is_unique, n
+GEN_TYPE, allocatable :: x(:,:)
+INTEGER(KIND=JPIM) , allocatable :: hash(:)
+
+ndupl = 0
+dupl_with(:) = 0
+
+kpkcols = npkcols
+do jj=1,npkcols
+  j = colidx(jj)
+  if (j < 1 .or. j > ncols) kpkcols = kpkcols - 1
+enddo
+
+n = min(size(a,dim=1),nrows)
+n = min(n,size(dupl_with))
+if (present(idx)) n = min(n,size(idx))
+
+if (db_trace) then
+  info(1) = n
+  info(2) = nrows
+  info(3) = ncols
+  info(4) = npkcols
+  info(5) = kpkcols
+  info(5 + 1:5 + npkcols) = colidx(npkcols)
+  CALL cODB_trace(-1, 1,&
+         GEN_DUPL0_NAME,&
+         info, size(info))
+endif
+
+if (kpkcols == 0) goto 9999
+if (n < nrows) goto 9999
+
+nldx = ODB_lda(kpkcols)
+allocate(x(nldx,n))
+
+kk = 0
+do jj=1,npkcols
+  j = colidx(jj)
+  if (j < 1 .or. j > ncols) cycle
+  kk = kk + 1
+  if (present(idx)) then
+    do i=1,n
+      x(kk,i) = a(idx(i),j)
+    enddo
+  else
+    do i=1,n
+      x(kk,i) = a(i,j)
+    enddo
+  endif
+enddo
+
+CALL cODB_hash_set_lock()
+CALL cODB_hash_init()
+
+allocate(hash(n))
+CALL cODB_vechash(&
+     kpkcols * GEN_UI_RATIO, &
+     nldx * GEN_UI_RATIO,&
+     n, &
+     x(1,1), hash(1))
+
+do i=1,n
+  itag = i
+  CALL &
+       GEN_UNIQUE_FUNC(&
+       kpkcols, x(1,i), hash(i), &
+       is_unique, itag, ihash)
+  if (is_unique == 0) then ! i.e. is duplicate
+    if (present(idx)) then
+      dupl_with(i) = idx(itag)
+    else
+      dupl_with(i) = itag
+    endif
+  endif
+enddo
+
+CALL cODB_hash_init()
+
+deallocate(hash)
+deallocate(x)
+
+CALL cODB_hash_unset_lock()
+
+ndupl = count(dupl_with(:) > 0)
+
+9999 continue
+!write(0,*) trim(GEN_DUPL0_NAME)//&
+!    &': No. of duplicates found =',ndupl
+
+if (db_trace) then
+  info(1) = n
+  info(2) = n - ndupl
+  info(3) = ndupl
+  CALL cODB_trace(-1, 0, &
+         GEN_DUPL0_NAME,&
+         info, 3)
+endif
+
+END FUNCTION
+
+
+FUNCTION GEN_TOLSEARCH(&
+    &tol, v, &
+    &ksta, kend, index)&
+    &RESULT(loc)
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: ksta, kend
+GEN_TYPE, intent(in) :: tol, v(:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: index(:)
+INTEGER(KIND=JPIM) :: n, k, low, high, loc
+GEN_TYPE refval, value, delta, ztol
+
+n = size(v)
+if (present(index)) n = min(n,size(index))
+
+loc = ksta
+
+if (n <= 0) return
+if (ksta > kend) return
+if (ksta < 1 .or. ksta > n) return
+if (kend < 1 .or. kend > n) return
+if (tol < 0) return
+
+low  = ksta
+high = kend
+ztol = tol
+
+if (present(index)) then
+  refval = v(index(low))
+  do k=low+1,high
+    delta = abs(refval-v(index(k)))
+    if (delta > ztol) then
+      loc = k-1
+      return
+    endif
+  enddo
+else
+  refval = v(low)
+  do k=low+1,high
+    delta = abs(refval-v(k))
+    if (delta > ztol) then
+      loc = k-1
+      return
+    endif
+  enddo
+endif
+
+loc = high
+
+END FUNCTION
+
+FUNCTION GEN_BINSEARCH(&
+    &refval, v, &
+    &ksta, kend, &
+    &index, &
+    &cluster_start, cluster_end) &
+    &RESULT(loc)
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: ksta, kend
+GEN_TYPE, intent(in) :: v(:), refval
+INTEGER(KIND=JPIM), intent(in) , OPTIONAL :: index(:)
+INTEGER(KIND=JPIM), intent(out), OPTIONAL :: cluster_start, cluster_end
+INTEGER(KIND=JPIM) :: n, k, low, high, loc, mid
+
+n = size(v)
+if (present(index)) n = min(n,size(index))
+
+loc = 0
+
+if (present(cluster_start)) cluster_start = 0
+if (present(cluster_end)) cluster_end = 0
+
+if (n <= 0) goto 9999
+if (ksta > kend) goto 9999
+if (ksta < 1 .or. ksta > n) goto 9999
+if (kend < 1 .or. kend > n) goto 9999
+
+low  = ksta
+high = kend
+
+if (present(index)) then
+  do while (low <= high)
+    mid = (low+high)/2
+    k = mid
+    if (refval < v(index(k))) then
+      high = mid - 1
+    else if (refval > v(index(k))) then
+      low = mid + 1
+    else ! Match found
+      loc = k
+      if (present(cluster_start)) then
+        if (refval > v(index(ksta))) then
+          cluster_start = loc
+          do k=loc-1,ksta,-1
+            if (refval > v(index(k))) exit
+            cluster_start = k
+          enddo
+        else
+          cluster_start = ksta
+        endif
+      endif
+      if (present(cluster_end)) then
+        if (refval < v(index(kend))) then
+          cluster_end = loc
+          do k=loc+1,kend
+            if (refval < v(index(k))) exit
+            cluster_end = k
+          enddo
+        else
+          cluster_end = kend
+        endif
+      endif
+      goto 9999
+    endif
+  enddo ! do while (low <= high)
+else
+  do while (low <= high)
+    mid = (low+high)/2
+    k = mid
+    if (refval < v(k)) then
+      high = mid - 1
+    else if (refval > v(k)) then
+      low = mid + 1
+    else ! Match found
+      loc = k
+      if (present(cluster_start)) then
+        if (refval > v(ksta)) then
+          cluster_start = loc
+          do k=loc-1,ksta,-1
+            if (refval > v(k)) exit
+            cluster_start = k
+          enddo
+        else
+          cluster_start = ksta
+        endif
+      endif
+      if (present(cluster_end)) then
+        if (refval < v(kend)) then
+          cluster_end = loc
+          do k=loc+1,kend
+            if (refval < v(k)) exit
+            cluster_end = k
+          enddo
+        else
+          cluster_end = kend
+        endif
+      endif
+      goto 9999
+    endif
+  enddo ! do while (low <= high)
+endif
+
+loc = 0
+
+9999 continue
+
+END FUNCTION
+
+!---  Public routines
+FUNCTION GEN_DUPL(&
+    &a, nrows, ncols, npkcols,&
+    &colidx, tol, dupl_with, idx)&
+    &RESULT(ndupl)
+USE odbshared, only : db_trace
+implicit none
+INTEGER(KIND=JPIM), intent(in)     :: nrows, ncols, npkcols
+INTEGER(KIND=JPIM), intent(out)    :: dupl_with(:)
+GEN_TYPE, intent(inout) :: a(:,:)  ! Not actually updated (indexed sort)
+INTEGER(KIND=JPIM),  intent(in)    :: colidx(npkcols)
+GEN_TYPE, intent(in)    :: tol(npkcols)
+INTEGER(KIND=JPIM),intent(in),optional :: idx(:)
+
+INTEGER(KIND=JPIM) :: cnt(nrows), info(5 + npkcols), index(nrows)
+INTEGER(KIND=JPIM) :: icnt, iloc, inc, maxsweep, n, nra
+INTEGER(KIND=JPIM) :: ndupl, kpkcols, isweep, rc, nhigh
+INTEGER(KIND=JPIM) :: i,j,k,ii,jj,kk,iend,iii,jjarr(1)
+GEN_TYPE, allocatable :: atemp(:,:)
+INTEGER(KIND=JPIM), allocatable :: mkeys(:)
+GEN_TYPE toler
+logical zerotol
+
+zerotol = ALL(tol(:)<=0)
+if (zerotol) then
+  ndupl = GEN_DUPL0(&
+         a, nrows, ncols, npkcols,&
+         colidx, dupl_with, idx=idx)
+  return
+endif
+
+ndupl = 0
+dupl_with(:) = 0
+
+kpkcols = npkcols
+do jj=1,npkcols
+  j = colidx(jj)
+  if (j < 1 .or. j > ncols) kpkcols = kpkcols - 1
+enddo
+
+n = min(size(a,dim=1),nrows)
+n = min(n,size(dupl_with))
+if (present(idx)) n = min(n,size(idx))
+
+if (db_trace) then
+  info(1) = n
+  info(2) = nrows
+  info(3) = ncols
+  info(4) = npkcols
+  info(5) = kpkcols
+  info(5 + 1:5 + npkcols) = colidx(npkcols)
+  CALL cODB_trace(-1, 1,&
+       GEN_DUPL_NAME,&
+       info, size(info))
+endif
+
+if (kpkcols == 0) goto 9999
+if (n < nrows) goto 9999
+
+allocate(mkeys(kpkcols))
+kk = 0
+do jj=1,npkcols
+  j = colidx(jj)
+  if (j < 1 .or. j > ncols) cycle
+  kk = kk + 1
+  mkeys(kk) = j
+enddo
+
+if (kk > 0) then
+  if (present(idx)) then
+    do j=1,n
+      index(j) = idx(j)
+    enddo
+  else
+    do j=1,n
+      index(j) = j
+    enddo
+  endif
+  CALL keysort(rc, a, nrows, &
+       key=mkeys(1),&
+!       multikey=mkeys(1:kk),&
+       index=index, init=.FALSE.)
+endif
+
+deallocate(mkeys)
+
+if (kk == 0) goto 9999
+maxsweep = kk
+
+!write(0,*) trim(GEN_DUPL_NAME)//': maxsweep=',maxsweep
+
+cnt(:) = 0
+isweep = 1
+do jj=1,npkcols
+  j = colidx(jj)
+  if (j < 1 .or. j > ncols) cycle
+!!  write(0,*)'atemp: start of sweep ',isweep,'; jj,j=',jj,j
+
+  jjarr(1) = jj
+  CALL cODB_trace(-1, 2,&
+       trim(GEN_DUPL_NAME)//': jj=', &
+       jjarr, 1)
+
+  toler = tol(jj)
+
+!  write(0,*) trim(GEN_DUPL_NAME)//' : jj, j, tol(jj)=',jj, j, tol(jj)
+
+  ii = 1
+  do while ( ii < nrows )
+    iloc = -1
+    if (isweep > 1) then
+      icnt = cnt(ii)
+      nhigh = min(ii+icnt-1,nrows)
+      if (nhigh - ii + 1 > 2) then
+        if (.not.allocated(atemp)) then
+          nra = ODB_lda(nrows)
+          allocate(atemp(nra,2))
+!!          write(0,*)'atemp: allocated; ',nrows,nra,2,shape(atemp)
+        endif
+!!        write(0,*)'atemp: ii,nhigh=',ii,nhigh
+        do iii=ii,nhigh
+          atemp(iii,1) = a(index(iii),j)
+          atemp(iii,2) = index(iii)
+        enddo
+!!        write(0,*)'atemp:  iii,atemp(ii:nhigh,1:2) in>'
+!!        do iii=ii,nhigh
+!!           write(0,*) iii,atemp(iii,1:2),index(iii),a(index(iii),j)
+!!        enddo
+        CALL keysort(rc, atemp(ii:nhigh,1:2), nhigh - ii + 1, key=1)
+        do iii=ii,nhigh
+          index(iii) = atemp(iii,2)
+        enddo
+!!        write(0,*)'atemp:  iii,atemp(ii:nhigh,1:2) out<'
+!!        do iii=ii,nhigh
+!!           write(0,*) iii,atemp(iii,1:2),index(iii),a(index(iii),j)
+!!        enddo
+      endif
+    else
+      icnt = 0
+      nhigh = nrows
+    endif
+
+    if (ii < nhigh) then
+      iloc = GEN_TOLSEARCH(&
+             toler, a(1:nrows,j),&
+             ii, nhigh, index=index)
+    else
+      iloc = ii
+    endif
+
+    icnt = iloc - ii + 1
+
+!!    write(0,*) 'atemp: ii,nhigh,iloc,icnt=',ii,nhigh,iloc,icnt
+
+!    if (isweep > 1 .and. icnt > 0) &
+!      write(0,'(6i8)') isweep,ii,nhigh,iloc,cnt(ii),icnt
+
+    cnt(ii) = icnt
+
+    if (icnt > 1) then
+      inc = 0
+      iend = min(ii+icnt-1,nrows)
+      do kk=ii+1,iend
+         cnt(kk) = cnt(kk-1) - 1
+         inc = inc + 1
+      enddo
+    else
+      inc = 1
+    endif
+    inc = max(inc,1)
+
+    ii = ii + inc
+  enddo
+
+!  write(0,*)'After sweep#',isweep,' : column#',j,toler
+!  do kk=1,nrows
+!    if (cnt(kk) > 0) then
+!      write(0,'(2i10,2x,g13.7,2x,i10)') &
+!       &       kk, index(kk), a(index(kk),j), cnt(kk)
+!      if (cnt(kk) == 1 .and. kk < nrows) then
+!        write(0,'(2i10,2x,g13.7,2x,i10," ***")') &
+!         &       kk+1, index(kk+1), a(index(kk+1),j), cnt(kk+1)
+!      endif
+!    endif
+!  enddo
+
+  isweep = isweep + 1
+enddo
+
+do ii=1,nrows
+  i = index(ii)
+  icnt = cnt(ii)
+  if (dupl_with(i) == 0 .and. icnt > 1) then
+    nhigh = min(ii+icnt-1,nrows)
+    do kk=ii+1,nhigh
+      k = index(kk)
+      dupl_with(k) = i
+    enddo
+  endif
+enddo
+
+ndupl = count(dupl_with(:) > 0)
+
+!      write(0,*) trim(GEN_DUPL_NAME)//': No. of duplicates found =',ndupl
+!      write(0,'((4i10))') &
+!     &     (kk, index(kk), cnt(kk), dupl_with(index(kk)), &
+!     &     kk=1,min(nrows,50))
+
+
+9999 continue
+!write(0,*) trim(GEN_DUPL_NAME)//': No. of duplicates found =',ndupl
+
+if (allocated(atemp)) then
+  deallocate(atemp)
+!!  write(0,*)'atemp: deallocated'
+endif
+
+if (db_trace) then
+  info(1) = nrows
+  info(2) = nrows - ndupl
+  info(3) = ndupl
+  CALL cODB_trace(-1, 0, &
+       GEN_DUPL_NAME,&
+       info, 3)
+endif
+
+END FUNCTION
+
+
+
+FUNCTION GEN_GROUP(&
+    &a,&
+    &idx, off, cnt, grplist) RESULT(ngrp)
+implicit none
+GEN_TYPE, intent(in) :: a(:)
+INTEGER(KIND=JPIM), intent(in) , optional :: idx(:)
+INTEGER(KIND=JPIM), intent(out), optional :: off(:), cnt(:)
+GEN_TYPE,intent(out), optional :: grplist(:)
+INTEGER(KIND=JPIM) :: j, jj, n, k, nminsz, iret
+INTEGER(KIND=JPIM), allocatable :: nidx(:)
+GEN_TYPE refval
+INTEGER(KIND=JPIM) ngrp
+
+ngrp = 0
+n = size(a)
+if (present(idx)) n = min(n,size(idx))
+k = min(1,n)
+
+if (k <= 0) return
+
+allocate(nidx(n))
+if (present(idx)) then
+  nidx(1:n) = idx(1:n)
+else
+  do j=1,n
+    nidx(j) = j
+  enddo
+endif
+
+k = 1
+jj = 1
+j = nidx(jj)
+refval = a(j)
+do jj=2,n
+  j = nidx(jj)
+  if (a(j) /= refval) then
+    refval = a(j)
+    k = k + 1
+  endif
+enddo
+
+ngrp = k
+
+if (present(off) .and. present(cnt)) then
+  if (present(grplist)) then
+    nminsz = min(size(off), size(cnt), size(grplist))
+  else
+    nminsz = min(size(off), size(cnt))
+  endif
+  if (nminsz < ngrp) then
+!--   An error
+    ngrp = -ngrp 
+    goto 99
+  endif
+
+  k = 1
+  jj = 1
+  j = nidx(jj)
+  refval = a(j)
+  off(k) = 0
+  do jj=2,n
+    j = nidx(jj)
+    if (a(j) /= refval) then
+      refval = a(j)
+      k = k + 1
+      off(k) = jj-1
+    endif
+  enddo
+
+  do k=1,ngrp-1
+    cnt(k) = off(k+1) - off(k)
+  enddo
+  cnt(ngrp) = n - off(ngrp)
+
+  if (present(grplist)) then
+    do k=1,ngrp
+      grplist(k) = a(nidx(off(k)+1))
+    enddo
+  endif
+endif
+
+99   continue
+if (allocated(nidx)) deallocate(nidx)
+END FUNCTION
+
+
+FUNCTION GEN_AGGR(&
+                  oper, a, nrows, target, &
+                  idx, &
+                  group_by, &
+                  grplist, result) RESULT(ngrp)
+
+implicit none
+CHARACTER(len=*), intent(in) :: oper
+INTEGER(KIND=JPIM), intent(in) :: nrows, target
+GEN_TYPE, intent(inout) :: a(:,:)  ! Not actually updated
+INTEGER(KIND=JPIM), intent(in) , optional :: group_by(:), idx(:)
+GEN_TYPE,intent(out), optional :: grplist(:,:)
+REAL(KIND=JPRB),  intent(out), optional :: result(:)
+INTEGER(KIND=JPIM), allocatable :: nidx(:)
+INTEGER(KIND=JPIM) n, ngrp, ncols, rc, j, nkeys, i, i1, ndupl
+logical LL_count, LL_sum, LL_avg, LL_max, LL_min
+logical LL_absmax, LL_absmin
+INTEGER(KIND=JPIM), allocatable :: off(:), cnt(:), mkeys(:), dupl_with(:)
+
+
+ngrp = 0
+n = min(nrows,size(a,dim=1))
+if (n <= 0) goto 99
+
+LL_count  = (oper == 'COUNT'  .or. oper == 'count'  )
+LL_sum    = (oper == 'SUM'    .or. oper == 'sum'    )
+LL_avg    = (oper == 'AVG'    .or. oper == 'avg'    )
+LL_max    = (oper == 'MAX'    .or. oper == 'max'    )
+LL_min    = (oper == 'MIN'    .or. oper == 'min'    )
+LL_absmax = (oper == 'ABSMAX' .or. oper == 'absmax' )
+LL_absmin = (oper == 'ABSMIN' .or. oper == 'absmin' )
+
+if (.not. LL_count   .and. &
+    .not. LL_sum     .and. .not. LL_avg    .and. &
+    .not. LL_max     .and. .not. LL_min    .and. &
+    .not. LL_absmax  .and. .not. LL_absmin &
+   ) goto 99
+
+ncols = size(a,dim=2)
+if (target <= 0 .or. target > ncols) goto 99
+
+if (present(group_by)) then
+  if (any(abs(group_by(:)) > ncols)) goto 99
+  if (any(abs(group_by(:)) ==    0)) goto 99
+  nkeys = size(group_by)
+  if (present(grplist)) then
+    if (size(grplist,dim=2) > nkeys) goto 99
+  endif
+  allocate(mkeys(group_by(nkeys)))
+  mkeys(:) = group_by(:)
+else
+  nkeys=0
+endif
+
+if (nkeys > 0) then
+  allocate(nidx(n))
+  if (present(idx)) then
+    nidx(1:n) = idx(1:n)
+  else
+    do j=1,n
+      nidx(j) = j
+    enddo
+  endif
+  CALL keysort(rc, a, n, &
+       multikey=mkeys, &
+       index=nidx, init=.FALSE.)
+!  ngrp = ODB_groupify(a(1:n,group_by), nidx)
+  mkeys(:) = abs(group_by(:))
+  allocate(dupl_with(n))
+  ndupl = GEN_DUPL0(&
+    &a, n, ncols, nkeys,&
+    &mkeys, dupl_with, idx=nidx)
+  ngrp = n - ndupl
+else
+  ngrp = 1
+endif
+
+if (ngrp <= 0) goto 99
+
+if (present(result)) then
+  if (size(result) < ngrp) then
+!-- An error
+    ngrp = -ngrp
+    goto 99
+  endif
+endif
+
+if (nkeys > 0) then
+  allocate(off(ngrp))
+  allocate(cnt(ngrp))
+!  ngrp = ODB_groupify(a(1:n,group_by), nidx, off, cnt, grplist)
+!  if (ngrp <= 0) goto 99
+  i1 = 1 ! The first one is by definition not a duplicate
+  do j=1,ngrp
+    if (present(grplist)) then
+      grplist(j,1:nkeys) = a(nidx(i1),mkeys(1:nkeys))
+    endif
+    off(j) = i1-1
+    cnt(j) = 1
+    do i=i1+1,n
+      if (dupl_with(i) == 0) then
+        i1 = i
+        exit
+      endif
+      cnt(j) = cnt(j) + 1
+    enddo
+  enddo
+  if (present(result)) then
+    do j=1,ngrp
+      if (LL_count) then
+        result(j) = cnt(j)
+      else if (LL_sum .or. LL_avg) then
+        result(j) = sum(a(nidx(off(j)+1:off(j)+cnt(j)),target))
+        if (LL_avg) result(j) = result(j)/cnt(j)
+      else if (LL_max) then
+        result(j) = maxval(a(nidx(off(j)+1:off(j)+cnt(j)),target))
+      else if (LL_min) then
+        result(j) = minval(a(nidx(off(j)+1:off(j)+cnt(j)),target))
+      else if (LL_absmax) then
+        result(j) = maxval(abs(a(nidx(off(j)+1:off(j)+cnt(j)),target)))
+      else if (LL_absmin) then
+        result(j) = minval(abs(a(nidx(off(j)+1:off(j)+cnt(j)),target)))
+      endif
+    enddo
+  endif
+else
+  if (present(result)) then
+    ngrp = 1
+    j = 1
+    if (LL_count) then
+      result(j) = n
+    else if (LL_sum .or. LL_avg) then
+      result(j) = sum(a(1:n,target))
+      if (LL_avg) result(j) = result(j)/n
+    else if (LL_max) then
+      result(j) = maxval(a(1:n,target))
+    else if (LL_min) then
+      result(j) = minval(a(1:n,target))
+    else if (LL_absmax) then
+      result(j) = maxval(abs(a(1:n,target)))
+    else if (LL_absmin) then
+      result(j) = minval(abs(a(1:n,target)))
+    endif
+  endif
+endif
+
+99   continue
+if (allocated(nidx))  deallocate(nidx)
+if (allocated(off))   deallocate(off)
+if (allocated(cnt))   deallocate(cnt)
+if (allocated(mkeys)) deallocate(mkeys)
+if (allocated(dupl_with)) deallocate(dupl_with)
+
+END FUNCTION
+
+#ifndef NO_UNDEF
+#undef GEN_TYPE
+#undef GEN_TOLSEARCH
+#undef GEN_TOLSEARCH_NAME
+#undef GEN_BINSEARCH
+#undef GEN_BINSEARCH_NAME
+#undef GEN_DUPL0
+#undef GEN_DUPL0_NAME
+#undef GEN_UI_RATIO
+#undef GEN_DUPL
+#undef GEN_DUPL_NAME
+#undef GEN_GROUP
+#undef GEN_GROUP_NAME
+#undef GEN_UNIQUE_FUNC
+#undef GEN_AGGR
+#undef GEN_AGGR_NAME
+#endif
+
+#endif
diff --git a/odb/src/include/fortint.h b/odb/src/include/fortint.h
new file mode 100644
index 0000000..c79ce46
--- /dev/null
+++ b/odb/src/include/fortint.h
@@ -0,0 +1,25 @@
+#ifndef FORTINT_H
+#define FORTINT_H
+
+#ifdef INTEGER_IS_INT
+#define fortint int
+#define JPointer int *
+#else
+#if defined hpR64 || defined hpiaR64
+#define fortint long long
+#define JPointer long long *
+#else
+#define fortint long
+#define JPointer long *
+#endif
+#endif
+
+#ifdef REAL_8
+#define fortreal double
+#else
+#define fortreal float
+#endif
+
+#define fortdouble double
+
+#endif /* End of FORTINT_H */
diff --git a/odb/src/include/funcs.h b/odb/src/include/funcs.h
new file mode 100644
index 0000000..99386da
--- /dev/null
+++ b/odb/src/include/funcs.h
@@ -0,0 +1,715 @@
+#ifndef _FUNCS_H_
+#define _FUNCS_H_
+
+/* funcs.h */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <math.h>
+#include "privpub.h"
+#include "odbcrc.h"
+
+/* Natural logarithm */
+#define Ln log
+
+/* Base-10 logarithm */
+#define Lg log10
+
+static double ftrunc(double x) { return trunc(x); }
+static double Cot(double x) { return 1/tan(x); }
+static double ACot(double x) { return atan(1/x); }
+static double ACot2(double y, double x) { return atan2(x,y); }
+static double Coth(double x) { return 1/tanh(x); }
+static double Asinh(double x) { return Ln(x+sqrt(x*x+1)); }
+static double Acosh(double x) { return Ln(x+sqrt(x*x-1)); }
+/* static double Acosh(double x) { return Ln(x-sqrt(x*x-1)); } */
+static double Atanh(double x) { return Ln((1+x)/(1-x))/2; }
+static double ACoth(double x) { return Ln((x+1)/(x-1))/2; }
+static double sign(double x) { return x < 0 ? 1 : -1; }
+static double touch(double x) { return 1; }
+static double binlo(double x, double deltax)
+{
+  double rc = RMDI;
+  if (deltax != 0) {
+    if (deltax < 0) deltax = -deltax;
+    if (x >= 0) {
+      rc = ((int)(x/deltax)) * deltax;
+    }
+    else {
+      rc = ((int)(x/deltax)) * deltax - deltax;
+    }
+  }
+  return rc;
+}
+static double binhi(double x, double deltax)
+{
+  double rc = RMDI;
+  if (deltax != 0) {
+    if (deltax < 0) deltax = -deltax;
+    if (x >= 0) {
+      rc = ((int)(x/deltax)) * deltax + deltax;
+    }
+    else {
+      rc = ((int)(x/deltax)) * deltax;
+    }
+  }
+  return rc;
+}
+static double dnint(double d) { return F90nint(d); }
+static double dint(double d) { return ftrunc(d); }
+static double cmp(double x, double y) { return ((x < y) ? -1 : ((x > y) ? +1 : 0)); }
+
+static double fmaxval(const int n, const double d[])
+{
+  const double mdi = ABS(RMDI);
+  double dmax = mdi;
+  int jj=0;
+  while (jj<n && ABS(d[jj]) == mdi) jj++;
+  if (jj<n) {
+    int j;
+    dmax = d[jj];
+    for (j=jj+1; j<n; j++) {
+      if (ABS(d[j]) != mdi && dmax < d[j]) dmax = d[j];
+    }
+  }
+  return dmax;
+}
+
+static double fminval(const int n, const double d[])
+{
+  const double mdi = ABS(RMDI);
+  double dmin = mdi;
+  int jj=0;
+  while (jj<n && ABS(d[jj]) == mdi) jj++;
+  if (jj<n) {
+    int j;
+    dmin = d[jj];
+    for (j=jj+1; j<n; j++) {
+      if (ABS(d[j]) != mdi && dmin > d[j]) dmin = d[j];
+    }
+  }
+  return dmin;
+}
+
+static double Cksum32(const int n, const double d[])
+{
+  unsigned int crc32 = 0;
+  int keylen = n * sizeof(double);
+  fodb_crc32_(d, &keylen, &crc32);
+  return (double) crc32;
+}
+
+static double duint(double d)
+{
+  d = ftrunc(d);
+  if (d >= -INT_MAX && d <= INT_MAX) {
+    /* see also : ../lib/codb.c, function codb_d2u_(d,u) */
+    int tmp = d;
+    unsigned int u = tmp;
+    d = u;
+  }
+  else if (d < 0) {
+    /* Not correct ? */
+    d = -d;
+  }
+  return d;
+}
+
+static double dfloat(double d) { float f = d; d = f; return d; }
+
+static double dble(double d) { return d; }
+
+static double k2c(double kelvin) {
+  double celsius = kelvin - ZERO_POINT;
+  return celsius;
+}
+
+static double c2k(double celsius)
+{
+  double kelvin = celsius + ZERO_POINT;
+  return kelvin;
+}
+
+static double c2f(double celsius)
+{
+  double fahrenheit = ((9*celsius)/5) + 32;
+  return fahrenheit;
+}
+
+static double f2c(double fahrenheit)
+{
+  double celsius = ((fahrenheit - 32)*5)/9;
+  return celsius;
+}
+
+static double k2f(double kelvin)
+{
+  double fahrenheit = c2f(k2c(kelvin));
+  return fahrenheit;
+}
+
+static double f2k(double fahrenheit)
+{
+  double kelvin = c2k(f2c(fahrenheit));
+  return kelvin;
+}
+
+static double
+rad(double reflat, double reflon, double refdeg, double obslat, double obslon) 
+{
+  return (double)(acos(cos(reflat) * cos(obslat) * cos(obslon-reflon) +
+		       sin(reflat) * sin(obslat) ) <= refdeg);
+}
+
+static double
+distance(double obslat, double obslon, double reflat, double reflon)
+{
+  return (double)( R_Earth * 
+		   acos(cos(reflat) * cos(obslat) * cos(obslon-reflon) +
+			sin(reflat) * sin(obslat)) );
+}
+
+static double
+dist(double reflat, double reflon, double refdist_km, double obslat, double obslon)
+{
+  return (double)( R_Earth_km * 
+		   acos(cos(reflat) * cos(obslat) * cos(obslon-reflon) +
+			sin(reflat) * sin(obslat)) <= (refdist_km) );
+}
+
+static double
+km(double reflat, double reflon, double obslat, double obslon)
+{
+  return (double)( R_Earth_km * 
+		   acos(cos(reflat) * cos(obslat) * cos(obslon-reflon) +
+			sin(reflat) * sin(obslat)) );
+}
+
+#define POW(x,y) ((y) == 2 ? (x)*(x) : pow(x,y))
+
+static double circle(double x, double x0, double y, double y0, double r)
+{
+  return (double)( POW(x-x0,2) + POW(y-y0,2) <= POW(r,2) );
+}
+
+static double lon0to360(double lon_minus180_to_plus180)
+{
+  const double three_sixty = 360;
+  return fmod(lon_minus180_to_plus180 + three_sixty, three_sixty);
+}
+
+#define CASE_GET_BITS(x, pos, len) \
+  case len: rc = GET_BITS(x, pos, len); break
+
+static double ibits(double X, double Pos, double Len)
+{
+  int rc = 0; /* the default */
+  X = ftrunc(X);
+  Pos = ftrunc(Pos);
+  Len = ftrunc(Len);
+  if (X   >= INT_MIN && X   <= INT_MAX &&
+      Pos >= 0       && Pos <  MAXBITS &&
+      Len >= 1       && Len <= MAXBITS) {
+    int x = X;
+    int pos = Pos;
+    int len = Len;
+    switch (len) {
+      CASE_GET_BITS(x, pos, 1);
+      CASE_GET_BITS(x, pos, 2);
+      CASE_GET_BITS(x, pos, 3);
+      CASE_GET_BITS(x, pos, 4);
+      CASE_GET_BITS(x, pos, 5);
+      CASE_GET_BITS(x, pos, 6);
+      CASE_GET_BITS(x, pos, 7);
+      CASE_GET_BITS(x, pos, 8);
+      CASE_GET_BITS(x, pos, 9);
+      CASE_GET_BITS(x, pos,10);
+      CASE_GET_BITS(x, pos,11);
+      CASE_GET_BITS(x, pos,12);
+      CASE_GET_BITS(x, pos,13);
+      CASE_GET_BITS(x, pos,14);
+      CASE_GET_BITS(x, pos,15);
+      CASE_GET_BITS(x, pos,16);
+      CASE_GET_BITS(x, pos,17);
+      CASE_GET_BITS(x, pos,18);
+      CASE_GET_BITS(x, pos,19);
+      CASE_GET_BITS(x, pos,20);
+      CASE_GET_BITS(x, pos,21);
+      CASE_GET_BITS(x, pos,22);
+      CASE_GET_BITS(x, pos,23);
+      CASE_GET_BITS(x, pos,24);
+      CASE_GET_BITS(x, pos,25);
+      CASE_GET_BITS(x, pos,26);
+      CASE_GET_BITS(x, pos,27);
+      CASE_GET_BITS(x, pos,28);
+      CASE_GET_BITS(x, pos,29);
+      CASE_GET_BITS(x, pos,30);
+      CASE_GET_BITS(x, pos,31);
+      CASE_GET_BITS(x, pos,32);
+    }
+  }
+  return (double) rc;
+}
+
+static double aYear(double date)
+{
+  const double mdi = ABS(RMDI);
+  int year = NMDI;
+  if (ABS(date) != mdi) {
+    year = (int)(date/10000);
+  }
+  return (double)year;
+}
+
+static double aMonth(double date)
+{
+  const double mdi = ABS(RMDI);
+  int month = NMDI;
+  if (ABS(date) != mdi) {
+    month = (int)(date/100);
+    month %= 100;
+  }
+  return (double)month;
+}
+ 
+static double aDay(double date)
+{
+  const double mdi = ABS(RMDI);
+  int day = NMDI;
+  if (ABS(date) != mdi) {
+    day = (int)date;
+    day %= 100;
+  }
+  return (double)day;
+}
+
+static double anHour(double time)
+{
+  const double mdi = ABS(RMDI);
+  int hour = NMDI;
+  if (ABS(time) != mdi) {
+    hour = (int)(time/10000);
+  }
+  return (double)hour;
+}
+
+static double aMinute(double time)
+{
+  const double mdi = ABS(RMDI);
+  int minute = NMDI;
+  if (ABS(time) != mdi) {
+    minute = (int)(time/100);
+    minute %= 100;
+  }
+  return (double)minute;
+}
+
+static double aSecond(double time)
+{
+  const double mdi = ABS(RMDI);
+  int second = NMDI;
+  if (ABS(time) != mdi) {
+    second = (int)time;
+    second %= 100;
+  }
+  return (double)second;
+}
+
+/* Wind speed (ff), direction (dd), u- and v-components */
+
+#define parc  ((double)360)
+#define degcon  pi_over_180
+
+static double Pi()
+{
+  return pi; /* A macro #define from privpub.h */
+}
+
+static double Speed(double u, double v)
+{ /* Aliases : uv2ff, ff */
+  const double mdi = ABS(RMDI);
+  double ff = (ABS(u) == mdi || ABS(v) == mdi) ? mdi : sqrt(u*u + v*v);
+  return ff;
+}
+
+static double Dir(double u, double v)
+{ /* Aliases : ff2uv, dd */
+  const double mdi = ABS(RMDI);
+  double dd;
+  if (ABS(u) == mdi || ABS(v) == mdi) {
+    dd = mdi;
+  }
+  else {
+    if (u == 0 && v == 0) {
+      dd = 0.5e0 * parc;
+    }
+    else {
+      dd = fmod(parc+atan2(-u,-v)/degcon,parc);
+    }
+  }
+  return dd;
+}
+
+static double Ucom(double dd, double ff)
+{ /* Aliases : ucomp, u */
+  const double mdi = ABS(RMDI);
+  double u = (ABS(dd) == mdi || ABS(ff) == mdi) ? mdi : -ff * sin(dd*degcon);
+  return u;
+}
+
+static double Vcom(double dd, double ff)
+{ /* Aliases : vcomp, v */
+  const double mdi = ABS(RMDI);
+  double v = (ABS(dd) == mdi || ABS(ff) == mdi) ? mdi : -ff * cos(dd*degcon);
+  return v;
+}
+
+static double Within(double target, double lo, double hi)
+{
+  return (target >= lo && target <= hi) ? 1 : 0;
+}
+
+static double Within360(double target, double lo, double hi)
+{
+  target = lon0to360(target);
+  lo = lon0to360(lo);
+  hi = lon0to360(hi);
+  return Within(target, lo, hi);
+}
+
+static double llu2double(double i0, double i1)
+{
+  union {
+    double d;
+    int i[2];
+  } u;
+  u.i[0] = i0;
+  u.i[1] = i1;
+  return u.d;
+}
+
+#if defined(FUNCS_C)
+
+static double Min(double x) { return x; }
+static double Max(double x) { return x; }
+
+static double Density(double resol) { return resol; }
+static double Count(double x)       { return (double)1; }
+static double Bcount(double x)      { return (double) (((x) != 0) ? 1 : 0); }
+static double Sum(double x)         { return x; }
+static double Avg(double x)         { return x; }
+static double Median(double x)      { return x; }
+static double Stdev(double x)       { return x; }
+static double Var(double x)         { return x; }
+static double Rms(double x)         { return x; }
+static double Dotp(double x, double y) { return (x * y); }
+static double Norm(double x, double y) { return Dotp(x,y); }
+
+static double Count_distinct(double x)   { return x; }
+static double Bcount_distinct(double x)  { return x; }
+static double Sum_distinct(double x)     { return Sum(x); }
+static double Avg_distinct(double x)     { return Avg(x); }
+static double Median_distinct(double x)  { return Median(x); }
+static double Stdev_distinct(double x)   { return Stdev(x); }
+static double Var_distinct(double x)     { return Var(x); }
+static double Rms_distinct(double x)     { return Rms(x); }
+static double Dotp_distinct(double x, double y) { return Dotp(x,y); }
+static double Norm_distinct(double x, double y) { return Dotp(x,y); }
+
+/* from evaluate.h */
+
+#define Aggr_argnO thsp[IT].aggr_argno
+
+static double Shared2ArgFunc(double x, double y)
+{
+  DEF_IT;
+  const thsafe_parse_t *thsp = GetTHSP();
+  double value = 0;
+  if (thsp) {
+    if (Aggr_argnO == 1) value = x;
+    else if (Aggr_argnO == 2) value = y;
+  }
+  return value;
+}
+
+static double Covar(double x, double y)      { return Shared2ArgFunc(x,y); }
+static double Corr(double x, double y)       { return Shared2ArgFunc(x,y); }
+static double Linregr_a(double x, double y)  { return Shared2ArgFunc(x,y); }
+static double Linregr_b(double x, double y)  { return Shared2ArgFunc(x,y); }
+static double Maxloc(double x, double y)     { return Shared2ArgFunc(x,y); }
+static double Minloc(double x, double y)     { return Shared2ArgFunc(x,y); }
+
+#endif
+
+/* 
+   Included from two places : 
+   lib/funcs.c --> #define FUNCS_C set to 1
+   compiler/tree.c --> FUNCS_C not set at all
+*/
+
+typedef struct _funcs_t {
+  char *name;
+  int numargs;
+  union {
+    void *compile_time;
+    double dbladdr;
+    double (*zeroarg) (void);
+    double (*onearg)  (double arg1);
+    double (*twoarg)  (double arg1, double arg2);
+    double (*threearg)(double arg1, double arg2, double arg3);
+    double (*fourarg) (double arg1, double arg2, double arg3, double arg4);
+    double (*fivearg) (double arg1, double arg2, double arg3, double arg4, double arg5);
+    double (*sixarg)  (double arg1, double arg2, double arg3, double arg4, double arg5, double arg6);
+    double (*vararg)  (const int n, const double args[]);
+  } u;
+  union {
+    void *run_time;
+    double dbladdr;
+    double (*zeroarg) (void);
+    double (*onearg)  (double arg1);
+    double (*twoarg)  (double arg1, double arg2);
+    double (*threearg)(double arg1, double arg2, double arg3);
+    double (*fourarg) (double arg1, double arg2, double arg3, double arg4);
+    double (*fivearg) (double arg1, double arg2, double arg3, double arg4, double arg5);
+    double (*sixarg)  (double arg1, double arg2, double arg3, double arg4, double arg5, double arg6);
+    double (*vararg)  (const int n, const double args[]);
+  } f;
+  int deg2rad; /*
+		 0=No conversions
+		 1=degrees argument(s) need to be converted into radians
+		 2=the result needs to be converted back to degrees
+		 < 0 : Convert all arguments to radians except the ABS(deg2rad)'th [hack]
+	       */
+  int joffset; /* The count of extra args added in front of the user supplied args */
+} funcs_t;
+
+#if defined(FUNCS_C)
+#define AGGRO(x) "_" #x
+#define RUNTIME(x) (void *)x
+#define timestamp ODB_timestamp
+#define basetime ODB_basetime
+#else
+#define AGGRO(x) #x
+#define RUNTIME(x) NULL
+#endif
+
+static int NfuncS = 0;
+
+static funcs_t Func[] = {
+  /* Compile-time evaluable functions */
+  "sin", 1, (void *)sin, NULL, 1, 0,
+  "cos", 1, (void *)cos, NULL, 1, 0,
+  "tan", 1, (void *)tan, NULL, 1, 0,
+  "cot", 1, (void *)Cot, NULL, 1, 0,
+  "asin", 1, (void *)asin, NULL, 2, 0,
+  "acos", 1, (void *)acos, NULL, 2, 0,
+  "atan", 1, (void *)atan, NULL, 2, 0,
+  "atan2", 2, (void *)atan2, NULL, 2, 0,
+  "acot", 1, (void *)ACot, NULL, 2, 0,
+  "acot2", 2, (void *)ACot2, NULL, 2, 0,
+  "sinh", 1, (void *)sinh, NULL, 0, 0,
+  "cosh", 1, (void *)cosh, NULL, 0, 0,
+  "tanh", 1, (void *)tanh, NULL, 0, 0,
+  "coth", 1, (void *)Coth, NULL, 0, 0,
+  "asinh", 1, (void *)Asinh, NULL, 0, 0,
+  "acosh", 1, (void *)Acosh, NULL, 0, 0,
+  "atanh", 1, (void *)Atanh, NULL, 0, 0,
+  "acoth", 1, (void *)ACoth, NULL, 0, 0,
+  "sqrt", 1, (void *)sqrt, NULL, 0, 0,
+  "mod", 2, (void *)fmod, NULL, 0, 0,
+  "pow", 2, (void *)pow, NULL, 0, 0,
+  "exp", 1, (void *)exp, NULL, 0, 0,
+  "log", 1, (void *)log, NULL, 0, 0,
+  "ln", 1, (void *)Ln, NULL, 0, 0,
+  "lg", 1, (void *)Lg, NULL, 0, 0,
+  "log10", 1, (void *)log10, NULL, 0, 0,
+  "floor", 1, (void *)floor, NULL, 0, 0,
+  "ceil", 1, (void *)ceil, NULL, 0, 0,
+  "ldexp", 2, (void *)ldexp, NULL, 0, 0,
+  "abs", 1, (void *)fabs, NULL, 0, 0,
+  "trunc", 1, (void *)ftrunc, NULL, 0, 0,
+  "touch", 1, (void *)touch, NULL, 0, 0,
+  "sign", 1, (void *)sign, NULL, 0, 0,
+  "binlo", 2, (void *)binlo, NULL, 0, 0,
+  "binhi", 2, (void *)binhi, NULL, 0, 0,
+  "int", 1, (void *)dint, NULL, 0, 0,
+  "nint", 1, (void *)dnint, NULL, 0, 0,
+  "cmp", 2, (void *)cmp, NULL, 0, 0,
+  "max", -1, (void *)fmaxval, NULL, 0, 1,
+  "maxval", -1, (void *)fmaxval, NULL, 0, 1,
+  "min", -1, (void *)fminval, NULL, 0, 1,
+  "minval", -1, (void *)fminval, NULL, 0, 1,
+  "cksum", -1, (void *)Cksum32, NULL, 0, 1,
+  "uint", 1, (void *)duint, NULL, 0, 0,
+  "float", 1, (void *)dfloat, NULL, 0, 0,
+  "dble", 1, (void *)dble, NULL, 0, 0,
+  "celsius", 1, (void *)k2c, NULL, 0, 0, /* Kelvin to Celsius */
+  "k2c", 1, (void *)k2c, NULL, 0, 0, /* Kelvin to Celsius */
+  "c2k", 1, (void *)c2k, NULL, 0, 0, /* and Celsius to Kelvin */
+  "fahrenheit", 1, (void *)k2f, NULL, 0, 0, /*  Kelvin to Fahrenheit */
+  "k2f", 1, (void *)k2f, NULL, 0, 0, /* Kelvin to Fahrenheit */
+  "f2k", 1, (void *)f2k, NULL, 0, 0, /* and vice versa */
+  "c2f", 1, (void *)c2f, NULL, 0, 0, /* Celsius to Fahrenheit */
+  "f2c", 1, (void *)f2c, NULL, 0, 0, /* Fahrenheit to Celsius */
+  "rad", 5, (void *)rad, NULL, 1, 0,
+  "distance", 4, (void *)distance, NULL, 1, 0,
+  "dist", 5, (void *)dist, NULL, -3, 0, /* Uses [hack] for deg2rad : No deg2rad for 3rd arg */
+  "km", 4, (void *)km, NULL, 1, 0,
+  "lon0to360", 1, (void *)lon0to360, NULL, 1, 0,
+  "ibits", 3, (void *)ibits, NULL, 0, 0,
+  "circle", 5, (void *)circle, NULL, 0, 0,
+  "year", 1, (void *)aYear, NULL, 0, 0,
+  "month", 1, (void *)aMonth, NULL, 0, 0,
+  "day", 1, (void *)aDay, NULL, 0, 0,
+  "hour", 1, (void *)anHour, NULL, 0, 0,
+  "hours", 1, (void *)anHour, NULL, 0, 0,
+  "minutes", 1, (void *)aMinute, NULL, 0, 0,
+  "minute", 1, (void *)aMinute, NULL, 0, 0,
+  "seconds", 1, (void *)aSecond, NULL, 0, 0,
+  "second", 1, (void *)aSecond, NULL, 0, 0,
+  "pi", 0, (void *)Pi, NULL, 0, 0,
+  "speed", 2, (void *)Speed, NULL, 0, 0,
+  "uv2ff", 2, (void *)Speed, NULL, 0, 0,
+  "ff", 2, (void *)Speed, NULL, 0, 0,
+  "dir", 2, (void *)Dir, NULL, 0, 0,
+  "uv2dd", 2, (void *)Dir, NULL, 0, 0,
+  "dd", 2, (void *)Dir, NULL, 0, 0,
+  "u", 2, (void *)Ucom, NULL, 0, 0,
+  "ucomp", 2, (void *)Ucom, NULL, 0, 0,
+  "ucom", 2, (void *)Ucom, NULL, 0, 0,
+  "v", 2, (void *)Vcom, NULL, 0, 0,
+  "vcomp", 2, (void *)Vcom, NULL, 0, 0,
+  "vcom", 2, (void *)Vcom, NULL, 0, 0,
+  "within", 3, (void *)Within, NULL, 0, 0,
+  "within", 3, (void *)Within, NULL, 0, 0,
+
+  "tstamp", 2, (void *)timestamp, RUNTIME(ODB_timestamp), 0, 0, /* alias to timestamp */
+  "basetime", 2, (void *)basetime, RUNTIME(ODB_basetime), 0, 0,
+
+  /* Run-time only -evaluable functions */
+  "eq_min_resol", 0, NULL, RUNTIME(ODB_eq_min_resol), 0, 0,
+  "eq_max_n", 0, NULL, RUNTIME(ODB_eq_max_n), 0, 0,
+  "eq_resol", 1, NULL, RUNTIME(ODB_eq_resol), 0, 0,
+  "eq_area", 1, NULL, RUNTIME(ODB_eq_area_with_resol), 0, 0,
+  "eq_truearea", 3, NULL, RUNTIME(ODB_eq_truearea_with_resol), 0, 0,
+  "eq_latband", 2, NULL, RUNTIME(ODB_eq_latband_with_resol), 0, 0,
+  "eq_n", 1, NULL, RUNTIME(ODB_eq_n), 0, 0,
+  "eq_boxid", 3, NULL, RUNTIME(ODB_eq_boxid_with_resol), 0, 0,
+  "eq_boxlat", 3, NULL, RUNTIME(ODB_eq_boxlat_with_resol), 0, 0,
+  "eq_boxlon", 3, NULL, RUNTIME(ODB_eq_boxlon_with_resol), 0, 0,
+  "rgg_boxid", 3, NULL, RUNTIME(ODB_rgg_boxid), 0, 0,
+  "rgg_boxlat", 3, NULL, RUNTIME(ODB_rgg_boxlat), 0, 0,
+  "rgg_boxlon", 3, NULL, RUNTIME(ODB_rgg_boxlon), 0, 0,
+  "rgg_resol", 1, NULL, RUNTIME(ODB_rgg_resol), 0, 0,
+  "rotlat", 4, NULL, RUNTIME(ODB_rotlat), 0, 0,
+  "rotlon", 4, NULL, RUNTIME(ODB_rotlon), 0, 0,
+  "boxlat", 2, NULL, RUNTIME(ODB_boxlat), 0, 0,
+  "boxlon", 2, NULL, RUNTIME(ODB_boxlon), 0, 0,
+  "boxid_lat", 2, NULL, RUNTIME(ODB_boxid_lat), 0, 0,
+  "boxid_lon", 2, NULL, RUNTIME(ODB_boxid_lon), 0, 0,
+  "boxid", 4, NULL, RUNTIME(ODB_boxid), 0, 0,
+  "random", 0, NULL, RUNTIME(ODB_random), 0, 0,
+  "seed", 1, NULL, RUNTIME(ODB_seed), 0, 0,
+  "now", 0, NULL, RUNTIME(ODB_now), 0, 0,
+  "date_now", 0, NULL, RUNTIME(ODB_date_now), 0, 0,
+  "time_now", 0, NULL, RUNTIME(ODB_time_now), 0, 0,
+  "InFile", 2, NULL, RUNTIME(ODBinfile), 0, 0,
+  "NotInFile", 2, NULL, RUNTIME(ODBnotinfile), 0, 0,
+  "InGenList", 4, NULL, RUNTIME(ODB_InGenList), 0, 0,
+  "lldegrees", 1, NULL, RUNTIME(ODB_lldegrees), 0, 0,
+  "llradians", 1, NULL, RUNTIME(ODB_llradians), 0, 0,
+  "degrees", 1, NULL, RUNTIME(ODB_degrees), 0, 0,
+  "radians", 1, NULL, RUNTIME(ODB_radians), 0, 0,
+  "thin", -1, NULL, RUNTIME(ODB_vthin), 0, 2,
+  "offset", 2, NULL, RUNTIME(ODBoffset), 0, 0,
+  "twindow", 6, NULL, RUNTIME(ODB_twindow), 0, 0,
+  "tdiff", 4, NULL, RUNTIME(ODB_tdiff), 0, 0,
+  "maxcount", 1, NULL, RUNTIME(ODB_maxcount), 0, 0,
+  "maxrows", 0, NULL, RUNTIME(ODB_maxrows), 0, 0,
+  "Unique", -1, NULL, RUNTIME(ODBunique), 0, 0, /* Now in sync with ODB_Unique(const int n, ...) */
+  "SubQuery", -1, NULL, RUNTIME(ODBsubquery), 0, 1,
+  "RunOnceQuery", -1, NULL, RUNTIME(ODBsubquery), 0, 1,
+  "InQuery", -1, NULL, RUNTIME(ODBinquery), 0, 0,
+  "WildCard", -1, NULL, RUNTIME(ODBwildcard), 0, 1,
+  "StrEqual", -1, NULL, RUNTIME(ODBstrequal), 0, 1,
+  "Inside", 3, NULL, RUNTIME(ODBinside), 0, 0,
+  "InPolygon", 3, NULL, RUNTIME(ODBinpolygon), 0, 0,
+  "Near", 3, NULL, RUNTIME(ODBnear), 0, 0,
+  "lat", 1, NULL, RUNTIME(ODBlat), 0, 0,
+  "latitude", 1, NULL, RUNTIME(ODBlat), 0, 0,
+  "lon", 1, NULL, RUNTIME(ODBlon), 0, 0,
+  "longitude", 1, NULL, RUNTIME(ODBlon), 0, 0,
+  "alt", 1, NULL, RUNTIME(ODBalt), 0, 0,
+  "altitude", 1, NULL, RUNTIME(ODBalt), 0, 0,
+  "elev", 1, NULL, RUNTIME(ODBalt), 0, 0,
+  "elevation", 1, NULL, RUNTIME(ODBalt), 0, 0,
+  "pop", 1, NULL, RUNTIME(ODBpop), 0, 0,
+  "popul", 1, NULL, RUNTIME(ODBpop), 0, 0,
+  "population", 1, NULL, RUNTIME(ODBpop), 0, 0,
+  "walltime", 0, NULL, RUNTIME(util_walltime_), 0, 0,
+  "cputime", 0, NULL, RUNTIME(util_cputime_), 0, 0,
+  "datenum", 1, NULL, RUNTIME(ODB_datenum), 0, 0,
+  "hours_utc", 1, NULL, RUNTIME(ODB_hours_utc), 0, 0,
+  "julian_date", 2, RUNTIME(ODB_jd), NULL, 0, 0,
+  "jd", 2, RUNTIME(ODB_jd), NULL, 0, 0,
+  "ta", 2, NULL, RUNTIME(ODB_time_angle), 0, 0,
+  "ha", 1, NULL, RUNTIME(ODB_hour_angle), 0, 0,
+  "sda", 2, NULL, RUNTIME(ODB_solar_declination), 0, 0,
+  "sela", 4, NULL, RUNTIME(ODB_solar_elevation), 0, 0,
+  "sza", 4, NULL, RUNTIME(ODB_solar_zenith), 0, 0,
+  "saza", 4, NULL, RUNTIME(ODB_solar_azimuth), 0, 0,
+  "daynight", 4, NULL, RUNTIME(ODB_daynight), 0, 0,
+
+  "myproc", 0, NULL, RUNTIME(ODB_myproc), 0, 0,
+  "nproc", 0, NULL, RUNTIME(ODB_nproc), 0, 0,
+  "pid", 0, NULL, RUNTIME(ODB_pid), 0, 0,
+  "tid", 0, NULL, RUNTIME(ODB_tid), 0, 0,
+  "nthreads", 0, NULL, RUNTIME(ODB_nthreads), 0, 0,
+
+  /* Aggregate functions (prepended with underscore when with FUNCS_C) */
+  AGGRO(density), 1, NULL, RUNTIME(Density), 0, 0,
+  AGGRO(count), 1, NULL, RUNTIME(Count), 0, 0,
+  AGGRO(bcount), 1, NULL, RUNTIME(Bcount), 0, 0,
+  AGGRO(sum), 1, NULL, RUNTIME(Sum), 0, 0,
+  AGGRO(avg), 1, NULL, RUNTIME(Avg), 0, 0,
+  AGGRO(median), 1, NULL, RUNTIME(Median), 0, 0,
+  AGGRO(stdev), 1, NULL, RUNTIME(Stdev), 0, 0,
+  AGGRO(var), 1, NULL, RUNTIME(Var), 0, 0,
+  AGGRO(rms), 1, NULL, RUNTIME(Rms), 0, 0,
+  AGGRO(dotp), 2, NULL, RUNTIME(Dotp), 0, 0,
+  AGGRO(norm), 2, NULL, RUNTIME(Norm), 0, 0,
+  AGGRO(count_distinct), 1, NULL, RUNTIME(Count_distinct), 0, 0,
+  AGGRO(bcount_distinct), 1, NULL, RUNTIME(Bcount_distinct), 0, 0,
+  AGGRO(sum_distinct), 1, NULL, RUNTIME(Sum_distinct), 0, 0,
+  AGGRO(avg_distinct), 1, NULL, RUNTIME(Avg_distinct), 0, 0,
+  AGGRO(median_distinct), 1, NULL, RUNTIME(Median_distinct), 0, 0,
+  AGGRO(stdev_distinct), 1, NULL, RUNTIME(Stdev_distinct), 0, 0,
+  AGGRO(var_distinct), 1, NULL, RUNTIME(Var_distinct), 0, 0,
+  AGGRO(rms_distinct), 1, NULL, RUNTIME(Rms_distinct), 0, 0,
+  AGGRO(dotp_distinct), 2, NULL, RUNTIME(Dotp_distinct), 0, 0,
+  AGGRO(norm_distinct), 2, NULL, RUNTIME(Norm_distinct), 0, 0,
+  AGGRO(covar), 2, NULL, RUNTIME(Covar), 0, 0,
+  AGGRO(corr), 2, NULL, RUNTIME(Corr), 0, 0,
+  AGGRO(linregr_a), 2, NULL, RUNTIME(Linregr_a), 0, 0,
+  AGGRO(linregr_b), 2, NULL, RUNTIME(Linregr_b), 0, 0,
+  AGGRO(minloc), 2, NULL, RUNTIME(Minloc), 0, 0,
+  AGGRO(maxloc), 2, NULL, RUNTIME(Maxloc), 0, 0,
+
+  /* Special cases */
+
+  "Conv_llu2double", 2, (void *)llu2double, NULL, 0, 0,
+#if defined(FUNCS_C)
+  "_min", 1, NULL, RUNTIME(Min), 0, 0, /* alias _minval */
+  "_max", 1, NULL, RUNTIME(Max), 0, 0, /* alias _maxval */
+#else
+  "in_vector", 2, NULL, RUNTIME(ODB_in_vector), 0, 0, /* ctxgetdb.F90 only */
+  "paral", 2, NULL, NULL, 0, 0, /* only relevant in generated C-code */
+  "debug_print", 1, NULL, NULL, 0, 0, /* only relevant in generated C-code, if at all */
+#endif
+
+  NULL,
+};
+
+#endif /* _FUNCS_H_ */
diff --git a/odb/src/include/history.h b/odb/src/include/history.h
new file mode 100644
index 0000000..cba1513
--- /dev/null
+++ b/odb/src/include/history.h
@@ -0,0 +1,18 @@
+#ifndef _HISTORY_H_
+#define _HISTORY_H_
+
+/* history.h */
+
+#include "alloc.h"
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+
+extern const char *AddHistory(const char *cmd, const int *Date, const int *Time);
+extern const char *GetHistory(int next);
+extern void PrintHistory(FILE *fp);
+extern char *LoadHistory(const char *name);
+extern char *SaveHistory(const char *name, int nlastlines);
+extern void DelHistory();
+
+#endif /* _HISTORY_H_ */
diff --git a/odb/src/include/idx.h b/odb/src/include/idx.h
new file mode 100644
index 0000000..90bdc41
--- /dev/null
+++ b/odb/src/include/idx.h
@@ -0,0 +1,234 @@
+#ifndef _IDX_H_
+#define _IDX_H_
+
+/* idx.h */
+
+#include "privpub.h"
+
+/* Structures for ODB (row-)indices */
+
+typedef struct {
+  double *value; /* ncols (see below) data value(s) for this index */
+  int nclusters; /* 
+		    idxdata[] could be expressed in this many "clusters" when IDXT (text)-mode :
+		    A cluster is either : 
+		    (a) A number >= 0
+		    (b) start:end (range with increment of 1; start & end inclusive)
+		    (c) start:end:inc (same as (b) but increment > 1
+		 */
+  int idxlen;   /* Count of words occupied in idxdata[], when it's unpacked; usually == ndata */
+  int ndata;
+  /*
+    when idxtype (see below) = 1,
+    idxdata[] contains ndata rowid's with all values >= 0 i.e. between [0..nrows-1]
+
+    when idxtype = 2,
+    idxdata[] contains a bitmap of ndata unsigned int's, where
+    ndata is now determined from (nrows + 32 - 1)/32 [32 = no. of bits in uint]
+
+    if ndata is < 0, then idxdata[] denotes PCMA-packed stream of ndata-words
+  */
+  unsigned int *idxdata; 
+} odbidx_set_t;
+
+typedef struct { /* per pool (=pp) entries */
+  ll_t backwd;   /* No. bytes to jump backwards to get to the previous pool */
+  ll_t fwd;      /* No. bytes to jump forward to get to the next pool */
+  int poolno;    /* pool number in concern */
+  int idxtype;   /* type of index : 1=unique, 2=bitmap, -1/-2=unique/bitmap, but not active */
+  int nrows;     /* no. of rows in this table (i.e. SELECT count(*) FROM table) */
+  int nsets;     /* cardinality i.e. no. of distinct value-sets in this pool */
+  odbidx_set_t *idxset;
+} odbidx_pp_t;
+
+typedef struct _odbidx_t {
+  char *filename;    /* Index file name when file was written (stored in the file itself) */
+  char *tblname;     /* table name the index belongs to */
+  char *idxname;     /* name of the index */
+  char *colnames;    /* comma separated column names */
+  char *wherecond;   /* WHERE-condition : NULL if the default i.e. "1" */
+
+  /* Timestamp info */
+  yyyymmdd creation_date;
+  hhmmss creation_time;
+
+  yyyymmdd modification_date;
+  hhmmss modification_time;
+
+  int ncols;         /* How many columns in this index >= 0 && <= MAXBITS (32) */
+  int npools;        /* Number of pp-entries */
+  unsigned int typeflag; /* 
+			    Type flag FOR EACH COLUMN (--> up to MAXBITS-columns) :
+			     0 = if not a string
+			     1 = if a string (--> no byteswapping)
+			  */
+
+  /* The following two, when ncols > 0 */
+  int ncard;     /* Global cardinality over *ALL POOLS* (= SELECT DISTINCT cols ... WHERE cond) */
+  double *dcard; /* Distinct column values, in row-major order (total ncard rows) ;
+		    in total ncols * ncard -values */
+
+  odbidx_pp_t *pp;
+
+  struct _odbidx_t *next; /* for chaining (filekind = 2) */
+} odbidx_t;
+
+typedef struct {
+  int handle;
+  char *dbname;
+  int nidx;
+  odbidx_t *idx;
+} odbidx_main_t;
+
+/* 
+   ODB rows index binary (IDXB) / text (IDXT) file format :
+
+   One index file per table covering *ALL* the pools
+   (may need some message passing to read/write this file ; not a big problem ?)
+
+   Start of IDXF-block:
+
+     Format is text until the first '\f' (form-feed) is reached
+
+     "IDXB"       - 4-bytes magic word : used also to detect the need for byte-swapping of the block
+      or
+     "IDXT"       - 4-bytes magic word, if text format is to follow
+
+     Index-file format version number - int (4-bytes)
+     Index-file kind - int (4 bytes)
+        1 = normal index-file with pool entries etc.
+	2 = chained index-file with other index-files as entries (like in iomap-file)
+
+     if (index_file_kind == 2) then
+
+       other_index_file_name_1
+       other_index_file_name_2
+         ...
+       other_index_file_name_N
+       End-Of-File
+
+      (each of these text fields precede their length in format "%d")
+
+     else if (index_file_kind == 1) then
+
+     "filename"   - Full name of the index-file, when it was written
+     "tblname"    - table name (length up to the next \n)
+     "idxname"    - index name (length up to the next \n)
+     "colnames"   - comma separated column names (length up to the next \n)
+
+     "WHERE-condition" - "1" if no particular WHERE-condition applied (up to the next form feed \f)
+
+     (each of these text fields precede their length in format "%d")
+
+     index creation date & time     - 2 x 4-byte words
+     index modification date & time - 2 x 4-byte words
+
+     ncols        - number of columns in this index >= 0 && <= MAXBITS (32)
+     npools       - number of pools covered by this index
+     typeflag     - type flag for each column to denote whether it's a string (=1) or not (=0)
+
+     if (ncols > 0) then
+       ncard - global cardinality of the columns (i.e. SELECT DISTINCT cols) over all pools
+       dcard[] - 8-byte vector of cardinal values : ncols * ncard ; row-major; ncard-rows
+     endif
+
+     For the binary file only: ncard is always written, even if it is 0 (i.e. ncols = 0)
+
+     POOL_LOOP: Repeat until poolno below is -1
+
+       The following 4 entries are 4-byte ints all:
+
+       poolno       - pool number in concern
+       idxtype      - index type : 1=unique, 2=bitmap, -1 or -2 the same, but not active
+       nrows        - number of data rows in the table (in this poolno), SELECT count(*) FROM table
+       nsets        - cardinality (no. of distinct value-sets)
+
+       2 x 8-byte integers : for binary these are meaningful, for text -- just for information
+
+         backwd - no. of bytes to jump backward to reach the previous pool in pp-structure
+	 fwd    - no. of bytes to jump forward to reach the next pool in pp-structure
+
+       SET_LOOP: Repeat for each set :
+
+         if (ncols > 0) then
+           value[]      - ncols values : 
+                          all 8-byte long (64-bit flps [b/swap] or 8-byte '<string>' [no b/swap])
+	 endif
+
+         ndata        - length of index data vector (4-byte int)
+         idxlen       - Original length of idxdata[] before is was (possibly) packed
+                        When idxdata[] not packed, idxlen == ndata
+	 nclusters    - identifies how many chuncks of idxdata[] grouped together (text-mode only)
+         if < 0, indicates that idxdata[] below is PCMA-packed of up to 
+	         ABS(ndata) packed words !!
+         idxdata[]    - index data vector, unsigned int (when unpacked, its length is idxlen-elements)
+   
+       End SET_LOOP
+
+     End POOL_LOOP
+
+     -1           - To indicate end of pools has been reached
+
+     endif
+
+   End of IDXF-block
+
+*/
+
+extern int codb_IDXF_drop(void *Info);
+
+extern char *codb_IDXF_filename(Bool create_name,
+				const char *idxpath,
+				const char *tblname,
+				const char *idxname,
+				int ncols,
+				const char *colnames,
+				const char *wherecond,
+				const char *filesuffix);
+
+extern char *codb_IDXF_open(int *io_odx, const char *filename, const char *mode);
+extern int   codb_IDXF_close(int io_idx, odbidx_t *idx);
+
+extern int codb_IDXF_read(int io_idx, odbidx_t *idx, 
+			  int handle, int *poolno_offset, int recur,
+			  int oper,
+			  const double *rhs);
+
+extern int codb_IDXF_write(int io_idx, odbidx_t *idx, int binary, int pmethod, int use_idxtype);
+
+extern odbidx_pp_t *codb_IDXF_pack(odbidx_t *idx, int poolno, int pmethod, int idxtype, int recur);
+extern odbidx_pp_t *codb_IDXF_unpack(odbidx_t *idx, int poolno, int recur);
+extern odbidx_pp_t *codb_IDXF_locate_pp(odbidx_t *idx, int poolno, int recur);
+
+extern odbidx_t *
+codb_IDXF_create_index(int handle,
+		       void *Idx, int poolno, 
+		       int idxtype, 
+		       void *Info, int *Nrows);
+
+extern void *
+codb_IDXF_freeidx(odbidx_t *idx, int recur);
+
+extern odbidx_t *
+codb_IDXF_fetch(int handle,
+		const char *idxpath,
+		const char *tblname,
+		const char *idxname,
+		int ncols,
+		const char *colnames,
+		const char *wherecond,
+		int oper,
+		const double *rhs);
+
+extern void
+codb_cardinality_(const int *ncols, const int *nrows, const int *lda,
+		  const double a[], /* A Fortran matrix A(LDA,1:NCOLS), LDA >= NROWS */
+		  int *rc,          /* cardinality i.e. number of distinct values <= NROWS */
+		  int unique_idx[], /* if not NULL, 
+				       then Fortran-indices to unique rows of A upon output */
+		  const int *nunique_idx, /* Number of elements allocated for unique_idx[] */
+		  const int *bailout /* Bailout from cardinality 
+					study after this many distinct entries found */
+		  );
+   
+#endif
diff --git a/odb/src/include/info.h b/odb/src/include/info.h
new file mode 100644
index 0000000..c1ac89a
--- /dev/null
+++ b/odb/src/include/info.h
@@ -0,0 +1,292 @@
+#ifndef _INFO_H_
+#define _INFO_H_
+
+/* info.h */
+
+#include "alloc.h"
+#include "pcma_extern.h"
+#include "idx.h"
+
+/* Since IBM Power5+ was complaining about "col_t" being already defined,
+   then lets not fall into the same trap on any other platforms */
+
+#define DB_t            ODB_DB_t
+#define set_t           ODB_set_t
+#define str_t           ODB_str_t
+#define col_t           ODB_col_t
+#define table_t         ODB_table_t
+#define simple_where_t  ODB_simple_where_t
+#define dyn_t           ODB_dyn_t
+#define info_t          ODB_info_t
+#define dbcred_t        ODB_dbcred_t
+
+static const double mdi = ABS(RMDI);
+
+#define NLINKCASES 6
+static const char *linkcase_name[1+NLINKCASES] = {
+  "<undef>"
+  ,"(1) ONELOOPER - link"            /* 1 */
+  ,"(2) ALIGNed table"               /* 2 */
+  ,"(3) ALIGNed, but orphaned table" /* 3 */
+  ,"(4) A regular link"              /* 4 */
+  ,"(5) First table in FROM-stmt"    /* 5 */
+  ,"(6) Lonely, disconnected table"  /* 6 */
+};
+
+#define BEGIN_ROW "$begin_row#"
+#define END_ROW "$end_row#"
+
+typedef struct _DB_t {
+  int h;
+  char *dbname;
+  char *srcpath;
+  char *datapath;
+  char *idxpath;
+  char *poolmask;
+  int npools;
+  int ntables;
+  char **tblname;
+} DB_t;
+
+
+typedef struct _table_t {
+  struct _info_t *info;
+  int table_id;
+  char *name;
+  char *b;
+  char *e;
+  int linkparent_id;
+  int offset_parent_id;
+  struct _table_t *prev;
+  struct _table_t *next;
+  struct _table_t *linkparent;
+  struct _table_t *offset_parent;
+  char *linkoffset;
+  char *linklen;
+  int jr;
+  int lo;
+  int ob;
+  int linkcase;
+  linkoffset_t *offset;
+  linklen_t *len;
+  int nrows, ncols;
+  int *idx;
+  char *wherecond_and;
+  void *wherecond_and_ptree;
+  Bool simple_wherecond;
+  byte *skiprow;
+  int nwl;
+  struct _simple_where_t *wl;
+  int stored_idx_count;
+  Bool in_select_clause;
+} table_t;
+
+typedef struct _dyn_t {
+  char *name;
+  double *data;
+  int ndata;
+  int colid;
+  table_t *parent;
+  table_t *child;
+} dyn_t;
+
+typedef struct _col_t {
+  char *name;
+  char *fetch_name;
+  char *nickname;
+  char *dtype;
+  uint dtnum;
+  int kind;
+  int bitpos;
+  int bitlen;
+  int ioffset;
+  int table_id;
+  table_t *t;
+  double *dsym;
+  double *dinp;
+  int dinp_len;
+  Bool dinp_alloc;
+  void *formula_ptree;
+  Bool formula_ptree_owner;
+} col_t;
+
+typedef struct _simple_where_t {
+  char *condstr;
+  col_t *wcol;
+  char *lhs;
+  int oper;
+  double rhs;
+  odbidx_t *stored_idx; /* via CREATE INDEX ... ON table ... , if found */
+} simple_where_t;
+
+typedef struct _set_t {
+  char *name;
+  double value;
+} set_t;
+
+typedef struct _str_t {
+  char *name;
+  char *value;
+  S2D_Union u;
+} str_t;
+
+typedef struct _dbcred_t {
+  char *dbname;   /* current database name <dbname> */
+  char *srcpath;  /* ODB_SRCPATH_<dbname>           */
+  char *datapath; /* ODB_DATAPATH_<dbname>          */
+  char *idxpath;  /* ODB_IDXPATH_<dbname>           */
+  char *poolmask; /* ODB_PERMANENT_POOLMASK         */
+} dbcred_t;
+
+typedef struct _info_t {
+  char *dir;
+  char *host;
+  char *tstamp;
+
+  dbcred_t dbcred;
+
+  char *view;
+  char *sql_query;
+
+  int create_index; /* 
+		       -1 = DROP INDEX
+		        0 = Normal SELECT stmt, 
+		        1 = CREATE UNIQUE INDEX, 
+		        2 = CREATE BITMAP INDEX 
+		    */
+  Bool binary_index; /* If binary index (file) is meant to be created */
+  Bool use_indices;
+  char *use_index_name; /* Usually "*" i.e. any */
+
+  Bool has_select_distinct;
+  Bool has_count_star;
+  Bool has_aggrfuncs;
+  Bool has_thin;
+  Bool has_ll; /* True if has refs to lldegrees()/llradians() */
+
+  Bool need_global_view; /* Usually an orderby/select distinct/aggregate-func view */
+  Bool need_hash_lock; /* Has select distinct or unique by keywords */
+  Bool is_bc; /* Basic calculator : no table refs and just one line of output expected */
+
+  uint optflags; /* 
+		    0x1 : SELECT count(*) FROM table
+		 */
+
+  int latlon_rad; /* 
+		     Affects values returned by lldegrees()/llradians()
+		     Legal values of $ODB_LATLON_RAD :
+		     -1 : undefined
+		          -> lldegrees() behaves like degrees() i.e. does conversion to degrees
+		          -> llradians() behaves like radians() i.e. does conversion to radians
+		      0 : $ODB_LAT/$ODB_LON assumed to be in degrees
+		          -> lldegrees() does no conversion
+		          -> llradians() does conversion to radians
+		      1 : $ODB_LAT/$ODB_LON assumed to be in radians
+		          -> lldegrees() does conversion to degrees
+		          -> llradians() does no conversion
+		  */
+
+  col_t *odb_lat;   /* getenv("ODB_LAT"); */
+  col_t *odb_lon;   /* getenv("ODB_LON"); */
+  col_t *odb_date;  /* getenv("ODB_DATE"); */
+  col_t *odb_time;  /* getenv("ODB_TIME"); */
+  col_t *odb_color; /* getenv("ODB_COLOR"); */
+  col_t *odb_u;     /* getenv("ODB_U"); */
+  col_t *odb_v;     /* getenv("ODB_V"); */
+
+  int error_code;
+  int maxcols;
+  int npools;
+
+  Bool dca_alloc;
+
+  int idxalloc;
+  int idxlen;
+  double *idxlen_dsym; /* aka ROWNUM */
+
+  double *__maxcount__; /* Traces ODBTk's $__maxcount__ efficiently */
+
+  int nset;
+  set_t *s;
+
+  int ns2d;
+  str_t *s2d;
+
+  col_t *c;
+  int ncols; /* total number of columns to be dealt with when executing SELECT */
+  int ncols_true; /* True number of columns i.e. ncols_pure + ncols_formula + ncols_aggr_formula */
+  int ncols_pure; /* no formula, pure column (kind=1) */
+  int ncols_formula; /* simple formula (kind=2) */
+  int ncols_aggr_formula; /* aggregate formula (kind=4) */
+  int ncols_aux; /* auxiliary cols needed due to aggregate functions (kind=8) */
+  int ncols_nonassoc; /* column variables needed to be prefetched due to formula(s) (kind=0) */ 
+
+  int ncolaux; /* Should be == ncols_true + ncols_aux */
+  int *colaux;
+
+  col_t *u;
+  int nuniqueby;
+
+  table_t *t; /* full FROM-hierarchy; chain length = nfrom */
+  int nfrom;
+
+  char *wherecond;
+  void *wherecond_ptree; /* Used for table-less WHERE only */
+
+  col_t *w;
+  int nwhere; /* no. of columns that need to be fetched due to WHERE-condition */
+
+  col_t *o;
+  int norderby;
+
+  col_t *p;
+  int nprefetch; /* additional columns to be prefetched due to LINKs */
+
+  /* dynamic @LINK-lengths for use by "$<parent_tblname>.<child_tblname>#" -variables */
+  int ndyn;
+  dyn_t *dyn;
+
+  DB_t *ph; /* A back-reference to DB_t structure this info_t belongs to */
+
+  struct _info_t *next; /* Another SQL info */
+} info_t;
+
+
+extern int ODBc_open(const char *dbname, 
+		     const char *mode, int *npools, int *ntables,
+		     const char *poolmask); /* Returns handle >= 1 if all ok */
+extern int ODBc_close(int handle); /*  Returns 0 if all ok */
+extern const char **ODBc_get_tablenames(int handle, int *ntables);
+
+extern FILE *ODBc_debug_fp(FILE *fp_debug); /* Returns old debug file pointer */
+extern FILE *ODBc_get_debug_fp(); /* Returns current debug file pointer */
+
+extern void *ODBc_sql_prepare(int handle, const char *sql_query, const set_t *setvar, int nsetvar); /* Returns ptr to info_t upon success */
+extern void *ODBc_sql_prepare_via_sqlfile(int handle, const char *sql_query_file, const set_t *setvar, int nsetvar); /* Returns ptr to info_t upon success */
+
+extern void *ODBc_create_index_prepare(int handle, /* A tool to handle CREATE INDEX */
+				       const void *Info, const void *Infoaux);  
+extern int ODBc_fetch_indices(table_t *t, info_t *info);
+
+extern int  /* Returns no. of rows >= 0 matched if all ok */
+ODBc_sql_exec(int handle, void *Info, int poolno, int *Begin_row, int *End_row);
+
+extern void *ODBc_get_info(const char *info_file_or_pipe, const set_t *setvar, int nsetvar); /* Returns ptr to info_t upon success */
+extern void ODBc_print_info(FILE *fp, void *Info);
+extern void *ODBc_reset_info(void *Info); /* Returns Info */
+extern void *ODBc_sql_cancel(void *Info); /* Returns NULL */
+
+extern const char *ODBc_get_sql_query(const void *Info); /* Returns SQL-query in concern */
+
+extern void *ODBc_make_setvars(const char *varvalue, int *nsetvar);
+
+extern void *ODBc_next(void *Info); /* Returns the next SQL info in chain (or NULL) */
+
+extern void ODBc_vget_bits(double x[], int nx, int pos, int len); /* Gets bits pos:pos+len-1 */
+
+extern void *ODBc_get_free_handles(int *Maxhandle); /* returns ptr to free_handles */
+
+extern int ODBc_get_handle(const char *db);
+
+#endif /* _INFO_H_ */
+
diff --git a/odb/src/include/ioassign.h b/odb/src/include/ioassign.h
new file mode 100644
index 0000000..171d890
--- /dev/null
+++ b/odb/src/include/ioassign.h
@@ -0,0 +1,62 @@
+#ifndef _IOASSIGN_H_
+#define _IOASSIGN_H_
+
+/* ioassign.h */
+
+typedef struct ioassign_t {
+  unsigned int hash;   /* Internal hash */
+
+  char *filename; 
+  char *aliasname;
+
+  int numbins;
+
+  int readbufsize;
+  int writebufsize;
+
+  int prealloc;
+  int extent;
+
+  int compression;     /* 0=none or via pipe; 1,2,..,5,..=internal packing method */
+  int blocksize;       /* Max. no. of words to pack in one go (specific to internal packing) */
+
+  int concat;          /* Request for file concatenation option across PE (for example)
+			  0=no concat; >0 no. of individual files forming a concatenated file.
+			  For write-only files : concatenate "concat" no. of files into one;
+			  For read-only files  : can be used to cross check the concatenation */
+
+  int maxproc;         /* If > 0, then filename or aliasname may still contain %d's */
+  int fromproc;        /* For use with %d in alias/filenames to specify applicable range of pools */
+  int toproc;          /*         " "                                                             */
+
+  char *pipecmd;
+
+  struct ioassign_t *next;
+} Ioassign;
+
+
+extern int 
+IOassign_read(const char  *IOASSIGN, 
+	             int  *pbcount_out, 
+	        Ioassign **ioassign_start_out, 
+	        Ioassign **ioassign_out);
+
+extern int 
+IOassign_read_incore(const char  *IOASSIGN, 
+	             int  *pbcount_out, 
+		     Ioassign **ioassign_start_out, 
+		     Ioassign **ioassign_out);
+
+extern int 
+IOassign_write(const char *IOASSIGN, 
+                      int  pbcount,
+	         Ioassign *ioassign_start); 
+
+extern unsigned int
+IOassign_hash(const char *s);
+
+extern Ioassign *
+IOassign_lookup(const char *s, Ioassign *pstart);
+
+
+#endif
diff --git a/odb/src/include/iostuff.h b/odb/src/include/iostuff.h
new file mode 100644
index 0000000..f4137ca
--- /dev/null
+++ b/odb/src/include/iostuff.h
@@ -0,0 +1,177 @@
+#ifndef _IO_STUFF_H_
+#define _IO_STUFF_H_
+
+/**************************************************************
+
+  iostuff.h: A header file for more organized I/O scheme.
+             Fortran-interface.
+             Needed only for pure C-applications.
+
+  Author:  Sami Saarinen, ECMWF
+           27-Jun-1997
+
+ **************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "alloc.h"
+#include "magicwords.h"
+
+#define MAXLINE    4096
+#define MAXFILELEN 1024
+
+#define has_percent_sign(s)    (strchr(s,'%') != NULL)
+#define has_no_percent_sign(s) (strchr(s,'%') == NULL)
+
+#define FREEIOBUF(x) if (x.p) { FREE(x.p); x.p = NULL; } x.len = 0
+
+#define SETBUF(iobuf) { \
+        ALLOC(iobuf->p, iobuf->len+8); \
+        if (iobuf->p) setvbuf(fp, (char *)iobuf->p, _IOFBF, iobuf->len); \
+        else iobuf->len = 0; }
+
+#define TRIM(s) s ? s : "<not available>"
+
+#define MEGABYTE 1048576
+
+#define IOBINFACTOR 1000
+#define IOINDEX(u)  ((u)%IOBINFACTOR)
+#define IOBIN(u)    ((u)/IOBINFACTOR)
+
+/* The following MUST BE numeric; sizeof(type) does not do, since used in preprocessing macros */
+#define byte_1      1
+#define integer_4   4
+#define real_8      8
+
+typedef enum { 
+  none=0x1, internal=0x2, external=0x4, 
+  Zlib=0x8, Mmap=0xF /* these 2 are not implemented yet */
+} Compression;
+
+typedef struct iobuf_t {
+  int   len;
+  byte1 *p;
+} IObuf;
+
+typedef struct iotiming_t {
+  real8 walltime;
+  real8 usercpu;
+  real8 syscpu;
+} IOtime;
+
+typedef struct iostat_t {
+  time_t open_time;
+  time_t close_time;
+  integer4 bytes;
+  integer4 num_trans;
+  IOtime t;
+} IOstat;
+
+#define NRES 1
+
+typedef struct iobin_t {
+  char *true_name;    /* True name after conversion */
+  
+  FILE *fp;           /* stdio File pointer (if used) */
+  integer4 fileno;    /* fileno(fp) or some other index to a file */
+  
+  integer4 begin_filepos; /* Offset to the actual data (skips the MR2D-section) */
+
+  integer4 filepos;   /* File read/write position (in bytes) */
+  integer4 filesize;  /* File size (read only and prior piping); in bytes */
+
+  integer4 blksize;   /* Disk blocksize for a file */
+  
+  IObuf readbuf;      /* Read I/O-buffer */
+  IObuf writebuf;     /* Write I/O-buffer */
+  
+  integer4 prealloc;  /* Preallocation (primarily used on VPP) */
+  integer4 extent;    /* Extent size (primarily used on VPP) */
+
+  IOstat stat;        /* Gather I/O-statistics (if enabled) */
+
+  /* Extra information due to the MR2D (concatenated) file format */
+  int  mr2d_infolen;
+  unsigned int *mr2d_info;
+
+  /* For external, popen()-based compression schemes only */
+  char *pipecmd;      /* Unix command to perform packing/unpacking via popen() */
+  char *cmd;          /* Fully blown packcmd with filename etc. substituted into it */
+
+} IObin;
+
+
+typedef struct iostuff_t {
+  char *logical_name; /* File name as given in the open statement */
+  char *leading_part; /* Leading part of the true_name (common with any IObin true_names) */
+
+  Boolean is_inuse;    /* true if structure is eventually opened */
+  Boolean read_only;   /* true if file is opened for read-only */
+  Boolean is_detached; /* true file is left open (detached) for subsequent attachments */
+  Boolean on_mrfs;     /* true if the actual file assigned to the memory resident file system */
+  Boolean is_mrfs2disk;/* true if file is MR2D-type i.e. created with 'mrfs2disk' or similar */
+  Boolean req_byteswap;/* true if data requires byteswap */
+
+  unsigned char scheme; /* An OR'red list of Compression enum's; see above */
+
+  /* For internal, non-popen(), compression schemes only */
+  int packmethod;     /* Packing method for internal compression scheme */
+  int blocksize;      /* Max. no. of words to pack in one go (specific to internal packing) */
+
+  int concat;          /* Request for concatenation */
+  /* int reserved[NRES]; */ /* Reserved for future use */
+
+  integer4 numbins;   /* No. of linked bins where data resides */
+  IObin *bin;         /* Chained files */
+} IOstuff;
+
+extern int IOgetattr(IOstuff *iostuff);
+extern char *IOtruename(const char *name, const int *len_str);
+extern int IOgetsize(const char *path, int *filesize, int *blksize);
+extern void IOstuff_init(IOstuff *p);
+extern void IOstuff_bin_init(IObin *pbin);
+extern void IOstuff_reset(IOstuff *p);
+extern Boolean IOstuff_byteswap(IOstuff *p, Boolean value);
+extern void IOstuff_bin_reset(IObin *pbin);
+extern void IOtimes(IOtime *p);
+extern char *IOstrdup(const char *str, const int *len_str);
+extern char *IOstrdup_int(const char *str, int binno);
+extern char *IOstrdup_fmt(const char *fmt, int nproc);
+extern char *IOstrdup_fmt2(const char *fmt, int nproc, char *table_name);
+extern char *IOstrdup_fmt3(const char *fmt, char *table_name);
+extern int  IOstrequ(const char *fmt, const char *str, int *nproc, char *table_name, int fromproc, int toproc);
+extern char *IOresolve_env(const char *str);
+extern void IOrcopy(real8 out[], const real8 in[], int len);
+extern void IOircopy(integer4 out[], const real8 in[], int len);
+extern void IOricopy(real8 out[], const integer4 in[], int len);
+extern void IOrucopy(real8 out[], const unsigned int in[], int len);
+extern void IOicopy(integer4 out[], const integer4 in[], int len);
+extern char *IOknowncmd(const char *label, Boolean read_only, Boolean *has_incore, char **suffix, const IObuf *iobuf);
+extern int  IOsetbuf(FILE *fp, 
+		     const char *filename, 
+		     Boolean read_only, 
+		     IObuf *iobuf,
+		     int *filesize,
+		     int *blksize);
+extern FILE *IOprealloc(const char *filename,
+			int         prealloc,
+			int         extent,
+			int        *blksize,
+			int        *retcode);
+extern int IOconcat_byname(const char *filename, int len_filename);
+extern int IOmkdir(const char *pathname);
+extern Boolean  iostuff_debug;
+extern Boolean  iostuff_stat;
+extern integer4 iostuff_stat_ftn_unit;
+
+#endif
diff --git a/odb/src/include/lzw.h b/odb/src/include/lzw.h
new file mode 100644
index 0000000..395d373
--- /dev/null
+++ b/odb/src/include/lzw.h
@@ -0,0 +1,383 @@
+#ifndef _LZW_H_
+#define _LZW_H_
+
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <signal.h>
+
+/*
+   ECMWF's LZW packing bugfixed by Sami Saarinen 1-Dec-2000
+ */
+
+#define MAXCODE(n)      ((1 << (n)) - 1)
+#define CHECK_GAP       10000           /* enc_ratio check interval */
+
+#define BITS_MIN        9               /* start with 9 bits */
+#define BITS_MAX        12              /* max of 12 bit strings */
+#define CODE_CLEAR      256             /* code to clear string table */
+#define CODE_EOI        257             /* end-of-information code */
+#define CODE_FIRST      258             /* first free code entry */
+#define CODE_MAX        MAXCODE(BITS_MAX)
+#if 1
+#define HSIZE           9001            /* 91% occupancy */
+#define HSHIFT          (8-(16-13))
+#else
+#define HSIZE           5003            /* 80% occupancy */
+#define HSHIFT          (8-(16-12))
+#endif
+
+typedef int           John;   /* could be long, too; 32-bit minimum */
+typedef unsigned int  uJohn;  /* could be unsigned long, too; 32-bit minimum */
+
+#define NUM8 8L
+
+static John   incount = 0;
+static John   outcount = 0;
+static John   bitio_used   = 0;
+static uJohn bitio_buffer = 0;
+
+static John     errflg = 0;
+static John     outlen = 0;
+static John     inlen = 0;
+static unsigned char *outbuffer = 0;
+
+static unsigned char masks[] =  {
+  0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,
+};
+
+/*====================================================================*/
+
+#define OUT(x,str,fail) \
+{unsigned char _c = x; \
+ if (++outcount>outlen) {errflg++; if (fail) Rabort(str,__FILE__,__LINE__);} \
+ else *outbuffer++ = _c; }
+
+#define NEXTBYTE(c,buf,str) \
+{ if (++incount>inlen) {errflg++; Rabort(str,__FILE__,__LINE__);} \
+  else c = *buf++; }
+
+
+#define CODE(str) (code < CODE_MAX) ? code : Rabort(str,__FILE__,__LINE__)
+
+/*====================================================================*/
+
+static int
+Rabort(const char *str, const char *file, int line)
+{
+  fprintf(stderr,"***Error: LZW packing/unpacking failed at %s:%s, line %d\n",file,str,line);
+  RAISE(SIGABRT);
+  exit(1);
+  return 0;
+}
+
+static void 
+write_code(uJohn code,
+	   John nbits,
+	   const char *str)
+{
+  if (nbits + bitio_used > sizeof(bitio_buffer)*NUM8) {
+    while (bitio_used >= NUM8) {
+      unsigned char c = (bitio_buffer >> (NUM8*sizeof(bitio_buffer) - NUM8));
+      OUT(c,str,0);
+      bitio_buffer <<= NUM8;
+      bitio_used    -= NUM8;
+    }
+  }
+  code <<= (sizeof(code)*NUM8 - nbits - bitio_used);
+  bitio_buffer += code;
+  bitio_used   += nbits;
+}
+
+static void 
+flush_code(void)
+{
+  while (bitio_used > 0) {
+    unsigned char c = (bitio_buffer >> (NUM8*sizeof(bitio_buffer) - NUM8));
+    OUT(c,"flush_code",0);
+    bitio_buffer <<= NUM8;
+    bitio_used    -= NUM8;
+  }
+}
+
+static void 
+init_table(register int *table,
+	   register int size)
+{
+  while (size--) *table++ = -1;
+}
+
+
+static uJohn 
+read_code(const unsigned char *p,
+	  John *bitp,
+	  John nbits)
+{
+  John    len  = nbits;
+  John    skip = *bitp;
+  int         s = skip%8;
+  int         n = 8-s;
+  uJohn  ret = 0;
+  const unsigned char *p_orig = p;
+
+  skip = (skip >> 3);
+  if (skip >= inlen) return CODE_EOI;
+
+  p += skip; /* skip the bytes */
+  
+  if (s) {
+    if (p - p_orig + 1 == inlen) return CODE_EOI;
+    ret = masks[n] & *p++;
+    len -= n;
+  }
+  
+  while (len >= 8) {
+    if (p - p_orig + 1 == inlen) return CODE_EOI;
+    ret = (ret<<8) + *p++;
+    len -= 8;
+  }
+
+  ret = (ret << len) + (*p >> (8-len));
+  
+  *bitp += nbits;
+
+  if (p - p_orig >= inlen) {
+    fprintf(stderr,"read_code: out of bounds by %d bytes\n",
+	    p - p_orig - inlen + 1);
+    Rabort("read_code",__FILE__,__LINE__);
+  }
+  
+  return ret;
+}
+
+
+void
+lzw_unpack_(const unsigned char ibuf[],
+	    const John *Ilen,
+	    unsigned char obuf[], 
+	    const John *Olen,
+	    John *retcode)
+{
+  John ilen = *Ilen;
+  John olen = *Olen;
+  short  prefix[HSIZE];
+  unsigned char suffix[CODE_MAX+1];
+  unsigned char stack [HSIZE];
+  
+  unsigned char *stackp = stack;
+  John code,firstchar, oldcode, incode;
+  int i;
+  John bitp = 0;
+  int maxcode;
+  John  first_free;
+  John  nbits;
+
+  for(i=0;i<256;i++) suffix[i] = (unsigned char)i;
+  
+  /* Initialize globals */
+
+  errflg       = 0;
+  outbuffer    = obuf;
+  outlen       = olen;
+  inlen        = ilen;
+  bitio_used   = 0;
+  bitio_buffer = 0;
+  outcount     = 0;
+  incount      = 0;
+
+  maxcode    = MAXCODE(BITS_MIN) - 1;
+  nbits      = BITS_MIN;
+  first_free = CODE_FIRST;
+
+  while ((code = read_code(ibuf,&bitp,nbits)) != CODE_EOI) {
+    if (code == CODE_CLEAR) {
+      bzero(prefix, sizeof(prefix));
+      
+      nbits      = BITS_MIN;
+      maxcode    = MAXCODE(BITS_MIN) - 1;
+      first_free = CODE_FIRST;
+      
+      if ((code = read_code(ibuf,&bitp,nbits)) == CODE_EOI) break;
+      
+      OUT(code,"lzw_decode[code]",1);
+      
+      oldcode = firstchar = code;
+      continue;
+    }
+
+    incode = code;
+
+    if (code >= first_free) {
+      /* code not in table */
+      *stackp++ = firstchar;
+      if(stackp - stack > sizeof(stack)) {
+	Rabort("Ooops.... error in lzw[*stackp++ = firstchar]",
+	       __FILE__,__LINE__);
+      }
+      code = oldcode;
+    }
+    
+    while (code >= 256) {
+      *stackp++ = suffix[CODE("while (code >= 256):suffix")];
+      if(stackp - stack > sizeof(stack)) {
+	Rabort("Ooops.... error in lzw[*stackp++ = suffix[code]]",
+	       __FILE__,__LINE__);
+      }
+      code      = prefix[CODE("while (code >= 256):prefix")];
+    }
+
+    *stackp++ = firstchar = suffix[CODE("*stackp++ = firstchar:suffix")];
+    
+    if(stackp - stack > sizeof(stack)) {
+      Rabort("Ooops.... error in lzw[*stackp++ = firstchar = suffix[code]]",
+	     __FILE__,__LINE__);
+    }
+
+    do {
+      if (outcount >= outlen) break;
+      OUT(*--stackp,"lzw_decode[stackp]",1);
+    } while (stackp > stack);
+
+    if ((code = first_free) < CODE_MAX) {
+      prefix[CODE("if ((code = first_free) < CODE_MAX):prefix")] = oldcode;
+      suffix[CODE("if ((code = first_free) < CODE_MAX):suffix")] = firstchar;
+      first_free++;
+      
+      if (first_free > maxcode) {
+	nbits++;
+	if (nbits > BITS_MAX) nbits = BITS_MAX;
+	maxcode = MAXCODE(nbits) - 1;
+      }
+    }
+
+    oldcode = incode;
+  } /* while ((code = read_code(ibuf,&bitp,nbits)) != CODE_EOI) */
+
+  *retcode = errflg ? -outcount : outcount;
+}
+
+
+void
+lzw_pack_(const unsigned char ibuf[], 
+	  const John *Ilen,
+	  unsigned char obuf[],
+	  const John *Olen,
+	  John *retcode)
+{
+  John ilen = *Ilen;
+  John olen = *Olen;
+  John string;
+  int h,disp,ent;
+  int maxcode;
+  John  first_free;
+  John  nbits;
+  
+  int   stringtab[HSIZE];
+  short codetab[HSIZE];
+
+  bzero(codetab, sizeof(codetab));
+
+  /* Initialize globals */
+  
+  errflg       = 0;
+  outbuffer    = obuf;
+  outlen       = olen;
+  inlen        = ilen;
+  bitio_used   = 0;
+  bitio_buffer = 0;
+  outcount     = 0;
+  incount      = 0;
+  
+  nbits      = BITS_MIN;
+  
+  init_table(stringtab,HSIZE);
+  first_free = CODE_FIRST;
+  
+  maxcode = MAXCODE(BITS_MIN);
+  
+  write_code(CODE_CLEAR,nbits,"lzw_encode[write_code(CODE_CLEAR)]");
+
+  NEXTBYTE(ent,ibuf,"lzw_encode[ent]");
+
+  while (--ilen > 0) {
+    int c;
+    
+    NEXTBYTE(c,ibuf,"lzw_encode[c]");
+
+    string = ((John)c << BITS_MAX) + ent;
+    h = (c << HSHIFT) ^ ent;        /* xor hashing */
+    
+    /* while(h<0) h+=HSIZE; h %= HSIZE; */
+    
+    if (stringtab[h] == string) {
+      ent = codetab[h];
+      continue;
+    }
+
+    if (stringtab[h] >= 0) {
+      /*
+       * Primary hash failed, check secondary hash.
+       */
+      disp = HSIZE - h;
+      if (h == 0)
+	disp = 1;
+      do {
+	if ((h -= disp) < 0)
+	  h += HSIZE;
+	if (stringtab[h] == string) {
+	  ent = codetab[h];
+	  goto hit;
+	}
+      } while (stringtab[h] >= 0);
+    }
+
+    /*
+     * New entry, emit code and add to table.
+     */
+
+    write_code(ent,nbits,"lzw_encode[write_code(ent)]");
+    
+    ent          = c;
+    codetab[h]   = first_free++;
+    stringtab[h] = string;
+    
+    if (first_free == CODE_MAX - 1) {
+      /* table is full, emit clear code and reset */
+      
+      /* ratio = 0; */
+      init_table(stringtab,HSIZE);
+      first_free = CODE_FIRST;
+      write_code(CODE_CLEAR,nbits,
+      "lzw_encode[write_code(CODE_CLEAR;'if (first_free == CODE_MAX - 1)')]");
+      nbits   = BITS_MIN;
+      maxcode =  MAXCODE(BITS_MIN);
+      
+    } else {
+      
+      /*
+       * If the next entry is going to be too big for
+       * the code size, then increase it, if possible.
+       */
+      
+      if (first_free > maxcode) {
+	nbits++;
+	if(nbits > BITS_MAX) Rabort("nbits > BITS_MAX",__FILE__,__LINE__);
+	maxcode =  MAXCODE(nbits);
+      }
+    }
+
+hit:
+    ;
+  }
+
+  write_code(ent,nbits,"lzw_encode[write_code(ent) at end]");
+  write_code(CODE_EOI,nbits,"lzw_encode[write_code(CODE_EOI)]");
+  flush_code();
+
+  *retcode = errflg ? -outcount : outcount;
+}
+
+#endif
diff --git a/odb/src/include/magicwords.h b/odb/src/include/magicwords.h
new file mode 100644
index 0000000..3a03146
--- /dev/null
+++ b/odb/src/include/magicwords.h
@@ -0,0 +1,88 @@
+
+/* magicwords.h */
+
+#ifndef _MAGICWORDS_H_
+#define _MAGICWORDS_H_
+
+#include <stdio.h>
+
+/* 
+   To obtain unsigned int values, use f.ex. commands like:
+
+   echo -n "PCMA" | od -t u4 | head -1 | awk '{print $2}'
+   and you should get 1095582544 on a LITTLE-endian machine
+   and                1346587969 on a BIG-endian machine 
+*/
+
+/* These values are for big-endian machines */
+
+#define  PCMA 1346587969U /* 'PCMA' */
+#define  ODB_ 1329873457U /* 'ODB1' */
+#define  ODBI 1329873481U /* 'ODBI' */
+#define  MR2D 1297232452U /* 'MR2D' */
+#define  HC32 1212363570U /* 'HC32' */
+#define  ALGN 1095518030U /* 'ALGN' */
+#define  MMRY 1296912985U /* 'MMRY' */
+#define  IDXB 1229215810U /* 'IDXB' */
+#define  IDXT 1229215828U /* 'IDXT' */
+#define  DCA2 1145258290U /* 'DCA2' */
+#define  OCAC 1329807683U /* 'OCAC' */
+#define  ODBX 1329873496U /* 'ODBX' */
+
+/* 
+   In reverse, to obtain unsigned int values, use f.ex. commands like:
+
+   echo -n "AMCP" | od -t u4 | head -1 | awk '{print $2}'
+   and you should get 1095582544 on a BIG-endian machine
+   and                1346587969 on a LITTLE-endian machine 
+*/
+
+/* These values are for little-endian machines */
+
+#define  AMCP 1095582544U /* 'PCMA' , in reverse */
+#define  _BDO  826426447U /* 'ODB1' , in reverse */
+#define  IBDO 1229079631U /* 'ODBI' , in reverse */
+#define  D2RM 1144148557U /* 'MR2D' , in reverse */
+#define _23CH  842220360U /* 'HC32' , in reverse */
+#define  NGLA 1313295425U /* 'ALGN' , in reverse */
+#define  YRMM 1498565965U /* 'MMRY' , in reverse */
+#define  BXDI 1113080905U /* 'IDXB' , in reverse */
+#define  TXDI 1415070793U /* 'IDXT' , in reverse */
+#define _2ACD  843137860U /* 'DCA2' , in reverse */
+#define  CACO 1128350543U /* 'OCAC' , in reverse */
+#define  XBDO 1480737871U /* 'ODBX' , in reverse */
+
+/* Access functions; also Fortran-callable */
+
+extern void get_magic_pcma_(const int *reversed, unsigned int *value);
+extern void get_magic_odb__(const int *reversed, unsigned int *value);
+extern void get_magic_odbi_(const int *reversed, unsigned int *value);
+extern void get_magic_mr2d_(const int *reversed, unsigned int *value);
+extern void get_magic_hc32_(const int *reversed, unsigned int *value);
+extern void get_magic_algn_(const int *reversed, unsigned int *value);
+extern void get_magic_mmry_(const int *reversed, unsigned int *value);
+extern void get_magic_idxb_(const int *reversed, unsigned int *value);
+extern void get_magic_idxt_(const int *reversed, unsigned int *value);
+extern void get_magic_dca2_(const int *reversed, unsigned int *value);
+extern void get_magic_ocac_(const int *reversed, unsigned int *value);
+extern void get_magic_obdx_(const int *reversed, unsigned int *value);
+
+/* Compressed file auto-detection (see aux/cma_open.c) */
+
+extern const char *
+Compression_Suffix_Check(const char *filename);
+
+extern const char *
+Compression_Magic_Check(FILE *fp, unsigned int *first_word, int close_fp);
+
+/* Maximum # of columns permitted */
+
+extern int ODB_maxcols();
+extern void codb_maxcols_(int *maxcols);
+
+/* ODB version ; shared with the odb98-compiler */
+
+extern const char *
+codb_versions_(double *major, double *minor, int *numeric, const int *check_IFS_CYCLE_env_first);
+
+#endif /* _MAGICWORDS_H_ */
diff --git a/odb/src/include/memmap.h b/odb/src/include/memmap.h
new file mode 100644
index 0000000..93f605e
--- /dev/null
+++ b/odb/src/include/memmap.h
@@ -0,0 +1,55 @@
+#ifndef _MEMMAP_H_
+#define _MEMMAP_H_
+
+/* memmap.h */
+
+/* Memory mapped I/O */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAS_MMAP
+
+#if (defined(LINUX) && !defined(CRAYXT)) || defined(RS6K) || defined(SUN4) || defined(ALPHA) || defined(HPPA) || defined(SGI)
+#define HAS_MMAP
+#endif
+
+#endif
+
+#ifdef HAS_MMAP
+
+#if defined(SUN4) && defined(PRIVATE)
+/* Sun/Solaris #define's PRIVATE, which we also do in privpub.h ;-( */
+#define PRIVATE_RYAN PRIVATE
+#undef PRIVATE
+#endif
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#endif
+
+typedef struct {
+  caddr_t buf;
+  size_t len;
+  off_t offset;
+} memmap_t;
+
+extern memmap_t *memmap_open_read(int fd, const off_t *Offset, const size_t *Len);
+extern int memmap_close(memmap_t *m);
+extern memmap_t *memmap_alloc(size_t Len, int Shared);
+
+#if defined(SUN4) && defined(PRIVATE)
+/* Get rid of PRIVATE #define'd in <sys/mman.h> */
+#undef PRIVATE
+#endif
+
+#if defined(SUN4) && defined(PRIVATE_RYAN)
+/* Restore our original PRIVATE (if it was already defined) */
+#define PRIVATE PRIVATE_RYAN
+#undef PRIVATE_RYAN
+#endif
+
+#endif
diff --git a/odb/src/include/mr2d_hdr.h b/odb/src/include/mr2d_hdr.h
new file mode 100644
index 0000000..641453f
--- /dev/null
+++ b/odb/src/include/mr2d_hdr.h
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+static char vers[]     = "1.2";
+static char date_str[] = __DATE__;
+static char time_str[] = __TIME__;
+
+#if defined(CRAY) && !defined(T3D) && !defined(T3E)
+#define SYSTEM_NAME "(CRAY PVP)"
+#endif
+
+#ifdef T3D
+#define SYSTEM_NAME "(CRAY T3D)"
+#endif
+
+#ifdef T3E
+#define SYSTEM_NAME "(CRAY T3E)"
+#endif
+
+#ifdef SGI
+#define SYSTEM_NAME "(Silicon Graphics)"
+#endif
+
+#ifdef RS6K
+#define SYSTEM_NAME "(IBM RS/6000)"
+#endif
+
+#ifdef VPP
+#define SYSTEM_NAME "(Fujitsu VPP)"
+#endif
+
+#ifdef NECSX
+#define SYSTEM_NAME "(NEC SX)"
+#endif
+
+#ifdef LINUX
+#define SYSTEM_NAME "(LINUX)"
+#endif
+
+#ifndef SYSTEM_NAME
+#define SYSTEM_NAME "(Unknown system)"
+#endif
+
+static char system_name[] = SYSTEM_NAME;
+
+#include "magicwords.h"
+#include "alloc.h"
+
+#define FREEIOBUF(x) if (x.p) { FREE(x.p); x.p = NULL; } x.len = 0
+
+#define SETBUF(fp, iobuf) { \
+        ALLOC(iobuf.p, iobuf.len + 8); \
+        if (iobuf.p) setvbuf(fp, (char *)iobuf.p, _IOFBF, iobuf.len); \
+        else iobuf.len = 0; }
+
+typedef struct iobuf_t {
+  int            len;
+  unsigned char *p;
+} IObuf;
+
+extern int filesize(const char *path);
+
+extern int filesize_by_fp(FILE *fp, const char *path);
+
+extern FILE *fopen_prealloc(const char *filename,
+                            const char *mode,
+                            int         prealloc,
+                            int         extent);
+
+
+#define has_no_percent_sign(s) (strchr(s,'%')==NULL)
+
+static char *
+KiloMegaGiga(char *s)
+{
+  const double maxint = 2147483647.0;
+  char *p = s;
+  int   len = strlen(s);
+  char *last = &s[len-1];
+  double num;
+
+  if (*last == 'k' || *last == 'K') {
+    *last = '\0';
+    num = atoi(s) * 1024.0; /* multiplier: 1kB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%0.f",num);
+  }
+  else if (*last == 'm' || *last == 'M') {
+    *last = '\0';
+    num = atoi(s) * 1048576.0; /* multiplier: 1MB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+  else if (*last == 'g' || *last == 'G') {
+    *last = '\0';
+    num = atoi(s) * 1073741824.0; /* multiplier: 1GB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+
+  return p;
+}
diff --git a/odb/src/include/mysql.h b/odb/src/include/mysql.h
new file mode 100644
index 0000000..91ded2c
--- /dev/null
+++ b/odb/src/include/mysql.h
@@ -0,0 +1,6 @@
+/* A dummy "mysql.h" header file */
+
+/* You need to access a proper one if you want to get
+   ODB to MySQL -link working */
+
+/* Needed by ../aux/odb2mysql.c */
diff --git a/odb/src/include/newio.h b/odb/src/include/newio.h
new file mode 100644
index 0000000..6b891fd
--- /dev/null
+++ b/odb/src/include/newio.h
@@ -0,0 +1,66 @@
+#ifndef _NEWIO_H_
+#define _NEWIO_H_
+
+/* newio.h */
+
+#include "odb.h"
+#include "odb_ioprof.h"
+#include "cmaio.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Table data */
+
+typedef struct io_tbl_t {
+  struct io_pool_t *mypool;
+  char *tblname;
+  int known_size; /* from TOC or reads/write */
+  int updated; /* i.e. any writes issued */
+  ll_t offset;
+  int nrows;
+  int ncols;
+  /* Incore table file */
+  int open_mode;
+  char *file;
+  char *incore;
+  int n_incore;
+  int n_alloc;
+  int incore_ptr;
+  int in_use;
+  /* QTAR-purposes only */
+  char *read_cmd;
+  char *delete_cmd;
+} IO_tbl_t;
+
+/* Pool data */
+
+typedef struct io_pool_t {
+  struct io_db_t *mydb;
+  int poolno;
+  int maxtables;
+  int ntables;
+  IO_tbl_t *tbl;
+  /* Pool file (QTAR purposes) */
+  char *file;
+  int file_exist;
+  char *last_write_cmd;
+} IO_pool_t;
+
+/* Database */
+
+typedef struct io_db_t {
+  char *dbname;
+  int in_use;
+  int handle;
+  int is_new;
+  int is_readonly;
+  int req_byteswap;
+  int io_method;
+  int npools;
+  IO_pool_t *pool;
+  int maxpools;
+  int *poolaccess;
+} IO_db_t;
+
+#endif
diff --git a/odb/src/include/node.h b/odb/src/include/node.h
new file mode 100644
index 0000000..6ccf80e
--- /dev/null
+++ b/odb/src/include/node.h
@@ -0,0 +1,19 @@
+#ifndef _NODE_H_
+#define _NODE_H_
+
+/* node.h */
+
+#include "evaluate.h"
+
+typedef struct _Node_t {
+  Kind_t kind;
+  char *name;
+  double value;
+  int numargs;
+  const void *funcptr; /* = const funcs_t * from funcs.c */
+  double *symval;      /* = symtab_t's ->value from symtab.c */
+  struct _Node_t **args;
+  struct _Node_t *next;
+} Node_t;
+
+#endif
diff --git a/odb/src/include/odb.h b/odb/src/include/odb.h
new file mode 100644
index 0000000..bd5b381
--- /dev/null
+++ b/odb/src/include/odb.h
@@ -0,0 +1,2169 @@
+#ifndef _ODB_H_
+#define _ODB_H_
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include "ecstdlib.h"
+#include <unistd.h>
+#include <math.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <stdarg.h>
+
+#include "alloc.h"
+#include "swapbytes.h"
+#include "magicwords.h"
+#include "dca.h"
+#include "bits.h"
+#include "pcma_extern.h"
+#include "privpub.h"
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#define ODB_COMPILER_DEFAULT "'ODB_COMPILER undefined : '"
+
+#define MAXVARLEN 128
+
+#define MAXTRACEARGS 16
+
+#define PKRATIO(in,out) (((in) != 0) ? ((1 - ((double)(out)/(double)(in))) * 100.0) : 0)
+
+#define UNUSED "Unused"
+
+#define INFOLEN 7
+
+#define SPACE(fp,n) { int l; for (l=0; l<(n); l++) fprintf(fp," "); }
+#define TAB(fp) fprintf(fp,"  ")
+#define NL(fp)  fprintf(fp,"\n")
+
+#define FORPOOL for (p = first_pool; p; p = p->next)
+
+#define POOLREG_DEF  ODB_Pool *p, *sp, *ep
+#define POOLREG_FOR \
+  sp = AnyPool ? NULL : get_poolreg(Handle,Poolno); \
+  ep = sp ? sp : NULL; \
+  sp = sp ? sp : first_pool; \
+  for (p = sp ; p ; p = p->next)
+#define POOLREG_BREAK if (ep) break
+
+#define FORFUNC for (pf = p->funcs; pf != NULL; pf = pf->next)
+
+#define PFCOM pf->common
+
+#define HASHFUNC(h,u,hashsize) ((u)%(hashsize) + 31U * (h))
+
+#define Func_uintequal(x,y) \
+  (ODB_uint_equal((const uint *)&(x),(const uint *)&(y),sizeof(x)/sizeof(uint)))
+
+#define Func_twindow(tgdate, tgtime, andate, antime, lmargin, rmargin) \
+  ODB_twindow(tgdate, tgtime, andate, antime, lmargin, rmargin)
+#define Func_tdiff(tgdate, tgtime, andate, antime) \
+  ODB_tdiff(tgdate, tgtime, andate, antime)
+
+extern double ODB_datenum(double Date);
+extern void  codb_datenum_(const double *Date, double *Result);
+#define Func_datenum(tgdate) ODB_datenum(tgdate)
+
+extern double ODB_hours_utc(double Time);
+extern void  codb_hours_utc_(const double *Time, double *Result);
+#define Func_hours_utc(tgtime) ODB_hours_utc(tgtime)
+
+extern double ODB_hour_angle(double Time);
+extern void codb_hour_angle_(double *Time, double *Result);
+#define Func_ha(tgtime) ODB_time_angle(tgtime)
+
+extern double ODB_time_angle(double Time, double lon);
+extern void codb_time_angle_(double *Time, double *lon, double *Result);
+#define Func_ta(tgtime, lon) ODB_time_angle(tgtime, lon)
+
+extern double ODB_solar_declination(double Date, double Time);
+extern void codb_solar_declination_(double *Date, double *Time, double *Result);
+#define Func_sda(tgdate, tgtime) ODB_solar_declination(tgdate, tgtime)
+
+extern double ODB_solar_elevation(double Date, double Time, double lat, double lon);
+extern void codb_solar_elevation_(double *Date, double *Time, double *lat, double *lon, double *Result);
+#define Func_sela(tgdate, tgtime, lat, lon) ODB_solar_elevation(tgdate, tgtime, lat, lon)
+
+extern double ODB_solar_zenith(double Date, double Time, double lat, double lon);
+extern void codb_solar_zenith_(double *Date, double *Time, double *lat, double *lon, double *Result);
+#define Func_sza(tgdate, tgtime, lat, lon) ODB_solar_zenith(tgdate, tgtime, lat, lon)
+
+extern double ODB_daynight(double Date, double Time, double lat, double lon);
+extern void codb_daynight_(double *Date, double *Time, double *lat, double *lon, double *Result);
+#define Func_daynight(tgdate, tgtime, lat, lon) ODB_daynight(tgdate, tgtime, lat, lon)
+
+extern double ODB_solar_azimuth(double Date, double Time, double lat, double lon);
+extern void codb_solar_azimuth_(double *Date, double *Time, double *lat, double *lon, double *Result);
+#define Func_saza(tgdate, tgtime, lat, lon) ODB_solar_azimuth(tgdate, tgtime, lat, lon)
+
+
+extern double ODB_duint(double d);
+extern double ODB_dfloat(double d);
+
+#define Func_int(x) trunc(x)
+#define Func_nint(x) F90nint(x)
+#define Func_uint(x) ODB_duint(x)
+#define Func_float(x) ODB_dfloat(x)
+#define Func_dble(x) ((double)(x))
+#define Func_floor(x) floor(x)
+#define Func_trunc(x) trunc(x)
+#define Func_ceil(x) ceil(x)
+#define Func_ldexp(x,n) ldexp(x,n)
+#define Func_touch(x) (1)
+#define Func_maxcount(x) ((Count + tmpcount)<(x))
+#define Func_maxrows() (Count + tmpcount)
+#define Func_abs(x)   ABS(x)
+
+/* Used in generic.c */
+extern double ODB_maxcount(double x);
+extern double ODB_maxrows();
+
+/*
+  These two (min/max) are obsolete as of 27-Mar-2006 by SS.
+  Now available are variable length min/max or minval/maxval
+#define Func_max(x,y) MAX(x,y)
+#define Func_min(x,y) MIN(x,y)
+*/
+#define Func_mod(x,y) fmod(x,y)
+#define Func_pow(x,y) ((y) == 2 ? (x)*(x) : pow(x,y))
+
+/* Note: ODB's trigonometric funcs require args in degrees 
+   and return degrees (where applicable) */
+
+#define Func_cos(x) cos(D2R(x))
+#define Func_sin(x) sin(D2R(x))
+#define Func_tan(x) tan(D2R(x))
+#define Func_acos(x) R2D(acos(x))
+#define Func_asin(x) R2D(asin(x))
+#define Func_atan(x) R2D(atan(x))
+#define Func_atan2(x,y) R2D(atan2(x,y))
+
+#define Func_exp(x) exp(x)
+#define Func_cosh(x) cosh(x)
+#define Func_sinh(x) sinh(x)
+#define Func_tanh(x) tanh(x)
+#define Func_sqrt(x) sqrt(x)
+#define Func_log(x) log(x)
+#define Func_ln(x)  log(x)
+#define Func_log10(x) log10(x)
+#define Func_lg(x)    log10(x)
+#define Func_ibits(x,pos,len) GET_BITS(x, pos, len) 
+
+#define Func_year(x)   ((ABS(x) != ABS(RMDI)) ? (double)((int)((x)/10000)) : (double)NMDI)
+#define Func_month(x)  ((ABS(x) != ABS(RMDI)) ? (double)(((int)((x)/100))%100) : (double)NMDI)
+#define Func_day(x)    ((ABS(x) != ABS(RMDI)) ? (double)(((int)(x))%100) : (double)NMDI)
+#define Func_hour(x)   ((ABS(x) != ABS(RMDI)) ? (double)((int)((x)/10000)) : (double)NMDI)
+#define Func_minute(x) ((ABS(x) != ABS(RMDI)) ? (double)(((int)((x)/100))%100) : (double)NMDI)
+#define Func_minutes(x) Func_minute(x)
+#define Func_second(x) ((ABS(x) != ABS(RMDI)) ? (double)(((int)(x))%100) : (double)NMDI)
+#define Func_seconds(x) Func_second(x)
+
+extern double ODB_jd(double Date, double Time);
+extern void  codb_jd_(const double *Date, const double *Time, double *Result);
+#define Func_julian_date ODB_jd
+#define Func_jd          ODB_jd
+
+
+#define Func_circle(x,x0,y,y0,r) (Func_pow(x-x0,2) + Func_pow(y-y0,2) <= Func_pow(r,2))
+/* (((x)-(x0))*((x)-(x0)) + ((y)-(y0))*((y)-(y0)) <= (r)*(r)) */
+/* NPEs-variable below defined inside the generated C-code and denotes no. of pools */
+/*AF 07/05/09 remove test <= NPEs
+#define Func_paral(PEvar, targetPE) \
+( ( (PEvar) <= 0 ) || \
+  ( (targetPE) >= 1 && (targetPE) <= NPEs && (((int)(targetPE)-1)%NPEs + 1) == (PEvar) ) \
+)
+*/
+#define Func_paral(PEvar, targetPE) \
+( ( (PEvar) <= 0 ) || \
+  ( (targetPE) >= 1 && (((int)(targetPE)-1)%NPEs + 1) == (PEvar) ) \
+)
+
+
+/* Special for the observation handling */
+
+#define Func_rad(reflat, reflon, refdeg, obslat, obslon) \
+(acos( \
+      Func_cos(reflat) * Func_cos(obslat) * Func_cos(obslon-reflon) + \
+      Func_sin(reflat) * Func_sin(obslat) ) <= D2R(refdeg))
+
+#define Func_distance(reflat, reflon, obslat, obslon) \
+(R_Earth * acos( \
+      Func_cos(reflat) * Func_cos(obslat) * Func_cos(obslon-reflon) + \
+      Func_sin(reflat) * Func_sin(obslat) ))
+
+#define Func_dist(reflat, reflon, refdist_km, obslat, obslon) \
+(R_Earth_km * acos( \
+      Func_cos(reflat) * Func_cos(obslat) * Func_cos(obslon-reflon) + \
+      Func_sin(reflat) * Func_sin(obslat) ) <= (refdist_km))
+
+#define Func_km(reflat, reflon, obslat, obslon) \
+(R_Earth_km * acos( \
+      Func_cos(reflat) * Func_cos(obslat) * Func_cos(obslon-reflon) + \
+      Func_sin(reflat) * Func_sin(obslat) ))
+
+extern double ODB_rotlat(double lat, double lon, double polelat, double polelon);
+extern double ODB_rotlon(double lat, double lon, double polelat, double polelon);
+
+#define Func_rotlat(lat,lon,polelat,polelon) ODB_rotlat(lat,lon,polelat,polelon)
+#define Func_rotlon(lat,lon,polelat,polelon) ODB_rotlon(lat,lon,polelat,polelon)
+
+extern double ODB_lldegrees(double d);
+extern double ODB_llradians(double d);
+extern double ODB_degrees(double d);
+extern double ODB_radians(double d);
+extern void codb_init_latlon_rad_();
+extern int codb_change_latlon_rad_(const int *newvalue);
+
+/* The following two rely on env-variable $ODB_LATLON_RAD */
+#define Func_lldegrees(x)    ODB_lldegrees(x)
+#define Func_llradians(x)    ODB_llradians(x)
+
+/* The following two rely convert unconditionally [use inline macros here for performance gain] */
+#define Func_degrees(x) R2D(x) /* ODB_degrees(x) */
+#define Func_radians(x) D2R(x) /* ODB_radians(x) */
+
+#define Func_lon0to360(x) Func_mod((x)+360e0,360e0)
+
+/* Aggregate functions */
+
+#define Func__min(x)   (x)
+#define Func__max(x)   (x)
+
+#define Func__density(resol) (resol)
+#define Func__count(x)     (1)
+#define Func__bcount(x)   ((x)?1:0)
+#define Func__sum(x)       (x)
+#define Func__avg(x)       (x)
+#define Func__median(x)    (x)
+#define Func__stdev(x)     (x)
+#define Func__var(x)       (x)
+#define Func__rms(x)       (x)
+#define Func__dotp(x,y)   ((x) * (y))
+#define Func__norm(x,y)   Func__dotp(x,y)
+
+#define Func__count_distinct(x)   (x)
+#define Func__bcount_distinct(x)  (x)
+#define Func__sum_distinct(x)     Func__sum(x)
+#define Func__avg_distinct(x)     Func__avg(x)
+#define Func__median_distinct(x)  Func__median(x)
+#define Func__stdev_distinct(x)   Func__stdev(x)
+#define Func__var_distinct(x)     Func__var(x)
+#define Func__rms_distinct(x)     Func__rms(x)
+#define Func__dotp_distinct(x,y)  Func__dotp(x,y)
+#define Func__norm_distinct(x,y)  Func__dotp(x,y)
+
+#define Take2Arg(x,y) ((ArgNo == 1) ? (x) : (y))
+
+#define Func__covar(x,y)           Take2Arg(x,y)
+#define Func__corr(x,y)            Take2Arg(x,y)
+#define Func__linregr_a(x,y)       Take2Arg(x,y)
+#define Func__linregr_b(x,y)       Take2Arg(x,y)
+
+#define Func__maxloc(x,y)          Take2Arg(x,y)
+#define Func__minloc(x,y)          Take2Arg(x,y)
+
+/* End of aggregate functions */
+
+extern double ODB_boxlat(double lat, double deltalat);
+extern double ODB_boxlon(double lon, double deltalon);
+extern double ODB_boxid_lat(double lat, double deltalat);
+extern double ODB_boxid_lon(double lon, double deltalon);
+extern double ODB_boxid(double lat, double lon, double deltalat, double deltalon);
+
+#define Func_boxlat(lat,deltalat) ODB_boxlat(lat, deltalat)
+#define Func_boxlon(lon,deltalon) ODB_boxlon(lon, deltalon)
+#define Func_boxid_lat(lat,deltalat) ODB_boxid_lat(lat, deltalat)
+#define Func_boxid_lon(lon,deltalon) ODB_boxid_lon(lon, deltalon)
+#define Func_boxid(lat,lon,deltalat,deltalon) ODB_boxid(lat,lon,deltalat,deltalon)
+
+extern double ODB_eq_resol(double rn);
+extern double ODB_eq_n(double resol);
+extern double ODB_eq_min_resol();
+extern double ODB_eq_max_n();
+
+#define Func_eq_resol(n) ODB_eq_resol(n)
+#define Func_eq_n(resol) ODB_eq_n(resol)
+#define Func_eq_min_resol ODB_eq_min_resol
+#define Func_eq_max_n ODB_eq_max_n
+
+extern double ODB_eq_boxid(double lat, double lon, double rn);
+extern double ODB_eq_boxlat(double lat, double lon, double rn);
+extern double ODB_eq_boxlon(double lat, double lon, double rn);
+extern double ODB_eq_boxid_with_resol(double lat, double lon, double resol);
+extern double ODB_eq_boxlat_with_resol(double lat, double lon, double resol);
+extern double ODB_eq_boxlon_with_resol(double lat, double lon, double resol);
+
+#define Func_eq_boxid(lat,lon,resol) ODB_eq_boxid(lat,lon,ODB_eq_n(resol))
+#define Func_eq_boxlat(lat,lon,resol) ODB_eq_boxlat(lat,lon,ODB_eq_n(resol))
+#define Func_eq_boxlon(lat,lon,resol) ODB_eq_boxlon(lat,lon,ODB_eq_n(resol))
+
+extern double ODB_eq_area(double rn);
+extern double ODB_eq_area_with_resol(double resol);
+#define Func_eq_area(resol) ODB_eq_area(ODB_eq_n(resol))
+
+extern double ODB_eq_truearea(double lat, double lon, double rn);
+extern double ODB_eq_truearea_with_resol(double lat, double lon, double resol);
+#define Func_eq_truearea(lat, lon, resol) ODB_eq_truearea(lat, lon, ODB_eq_n(resol))
+
+extern double ODB_eq_latband(double bandnum, double rn);
+extern double ODB_eq_latband_with_resol(double bandnum, double resol);
+#define Func_eq_latband(bandnum, resol) ODB_eq_latband(bandnum, ODB_eq_n(resol))
+
+extern double ODB_rgg_boxid(double lat, double lon, double Txxxx);
+extern double ODB_rgg_boxlat(double lat, double lon, double Txxxx);
+extern double ODB_rgg_boxlon(double lat, double lon, double Txxxx);
+extern double ODB_rgg_resol(double Txxxx);
+
+#define Func_rgg_boxid  ODB_rgg_boxid
+#define Func_rgg_boxlat ODB_rgg_boxlat
+#define Func_rgg_boxlon ODB_rgg_boxlon
+#define Func_rgg_resol ODB_rgg_resol
+
+#define Func_sign(x) ((x) < 0 ? -1 : 1)
+
+extern double ODB_binlo(double x, double deltax);
+extern double ODB_binhi(double x, double deltax);
+
+#define Func_binlo(x,dx) ODB_binlo(x,dx)
+#define Func_binhi(x,dx) ODB_binhi(x,dx)
+
+#define Func_cmp(x,y) ((double)((x < y) ? -1 : ((x > y) ? +1 : 0)))
+
+#define Func_k2c(kelvin)      ((kelvin) - ZERO_POINT)
+#define Func_c2k(celsius)     ((celsius) + ZERO_POINT)
+#define Func_c2f(celsius)     ((((double)9)*(celsius))/((double)5) + ((double)32))
+#define Func_f2c(fahrenheit)  (((fahrenheit) - (double)32)*((double)5))/((double)9)
+#define Func_k2f(kelvin)      (Func_c2f(Func_k2c(kelvin)))
+#define Func_f2k(fahrenheit)  (Func_c2k(Func_f2c(fahrenheit)))
+
+extern double ODB_timestamp(double indate, double intime);
+#define Func_tstamp(d,t) ODB_timestamp(d,t)
+
+extern double ODB_basetime(double indate, double intime);
+#define Func_basetime(d,t) ODB_basetime(d,t)
+
+extern double ODB_now();
+extern double ODB_date_now();
+extern double ODB_time_now();
+
+#define Func_now ODB_now
+#define Func_date_now ODB_date_now
+#define Func_time_now ODB_time_now
+
+extern void fodb_register_in_vector_(void *d, const int *nd, const int *is_int, double *addr);
+extern void fodb_unregister_in_vector_(double *addr);
+extern double ODB_in_vector(double var, double addr);
+#define Func_in_vector(var,addr) ODB_in_vector(var,addr)
+
+#define Func_debug_print odb_debug_print_
+
+extern double ODBoffset(double colvar, double offset);
+#define Func_offset ODBoffset
+
+extern double ODB_pi();
+extern double ODB_speed(double u, double v);
+extern double ODB_dir(double u, double v);
+extern double ODB_ucom(double dd, double ff);
+extern double ODB_vcom(double dd, double ff);
+
+#define Func_pi    ODB_pi
+#define Func_speed ODB_speed
+#define Func_ff    ODB_speed
+#define Func_uv2ff ODB_speed
+#define Func_dir   ODB_dir
+#define Func_dd    ODB_dir
+#define Func_uv2dd ODB_dir
+#define Func_ucom  ODB_ucom
+#define Func_ucomp ODB_ucom
+#define Func_u     ODB_ucom
+#define Func_vcom  ODB_vcom
+#define Func_vcomp ODB_vcom
+#define Func_v     ODB_vcom
+
+extern double ODB_myproc();
+extern double ODB_nproc();
+extern double ODB_pid();
+extern double ODB_tid();
+extern double ODB_nthreads();
+extern void init_proc_funcs();
+
+extern void init_RANDOM();
+extern double ODB_seed(double myseed);
+extern double ODB_random();
+#define Func_random ODB_random
+#define Func_seed(myseed) ODB_seed(myseed)
+
+extern double ODB_InGenList(double target, double begin, double end, double step);
+#define Func_InGenList    ODB_InGenList
+
+extern double ODB_Infile(const char *filename, double arg);
+extern double ODBinfile(double filename, double arg);
+#define Func_InFile    ODB_InFile
+
+extern double ODB_NotInFile(const char *filename, double arg);
+extern double ODBnotinfile(double filename, double arg);
+#define Func_NotInFile ODB_NotInFile
+
+extern boolean odb_debug_print_(const double arg);
+
+#define Func_thin      ODB_thin
+extern double ODB_thin(const int n, /* double key, double Every_nth, */ ...);
+extern double ODB_vthin(const int n, const double d[]);
+extern void codb_thin_init_();
+extern void codb_thin_reset_(const int *it);
+
+#define Func_max    ODB_maxval
+extern double ODB_maxval(const int n, ...);
+
+#define Func_min    ODB_minval
+extern double ODB_minval(const int n, ...);
+
+#define Func_cksum  ODB_Cksum32
+extern double ODB_Cksum32(const int n, ...);
+
+/* End */
+
+extern void
+exec_dummy(int dummy, ...);
+
+extern void 
+cdummy_load_();
+
+extern FILE *
+CMA_get_fp(const int *unit);
+
+extern void 
+cma_open_(int            *unit, 
+	  const char     *filename,
+	  const char     *mode,
+	  int            *retcode,	 
+	  /* Hidden arguments to Fortran-program */
+	  int             len_filename,
+	  int             len_mode);
+
+extern void 
+cma_close_(const int *unit, int *retcode);
+
+extern int
+ODB_error(const char *where,
+	  int how_much,
+	  const char *what,
+	  const char *srcfile,
+	  int srcline,
+	  int perform_abort);
+
+/* The next 3 are meant to be Fortran-callable */
+
+extern void
+newio_start32_(const char *dbname,
+	       const int *handle, const int *maxhandle, const int *io_method_input,
+               const int *ntables, const int *is_new, const int *is_readonly,
+	       const int *glbNpools, const int *locNpools, const int poolidx[],
+               int *rc
+	       /* Hidden argument */
+	       , int dbname_len);
+
+extern void
+newio_flush32_(const int *handle,
+	       const int *poolno,
+	       const int *enforce_to_disk,
+	       const int *ntables,
+	       /* Tables in format "/@table1/@tables2/.../"
+		  For all tables (currently in memory), use "*" or put *ntables to -1 */
+	       const char table[],
+	       int *rc
+	       /* Hidden argument */
+	       , int table_len);
+
+extern void
+newio_end32_(const int *handle, int *rc);
+
+extern void
+newio_get_incore32_(const int *handle,
+		    const int *poolno, /* must be a specific pool ; -1 doesn't do */
+		    char data[],       /* data area where incore data will be memcpy'ed to */
+		    const int *nbytes, /* size of supplied data bytes array */
+		    const int *reset_updated_flag, /* if == 1 --> reset updated-flag to 0 */
+		    const char *table, /* particular table name (both "@table" or "table" do) */
+		    int *rc
+		    /* Hidden argument */
+		    , int table_len);
+
+extern void
+newio_put_incore32_(const int *handle,
+		    const int *poolno, /* must be a specific pool ; -1 doesn't do */
+		    const char data[], /* data area from which data is copied into the incore */
+		    const int *nbytes, /* amount of data */
+		    const int *nrows,  /* no. of rows in data-matrix */
+		    const int *ncols,  /* no. of cols in data-matrix */
+		    const char *table, /* particular table name (both "@table" or "table" do) */
+		    int *rc
+		    /* Hidden argument */
+		    , int table_len);
+
+extern void /* Just in case we need to know this from Fortran */
+newio_dimlen32_(int *rc);
+
+extern void
+newio_status_incore32_(const int *handle,
+		       const int *poolno,  /* must be a specific pool ; -1 doesn't do */
+		             int status[], /* status[]-array */
+		       const int *nstatus, /* no. of words in status[]-array */
+		       const char *table, /* particular table name (both "@table" or "table" do) */
+		             int *rc       /* no. of words filled/returned */
+		       /* Hidden argument */
+		       , int table_len);
+
+
+extern void
+newio_release_pool32_(const int *handle,
+		      const int *poolno,  /* must be a specific pool ; -1 doesn't do */
+		      int *rc);
+
+extern int
+newio_Read32(int *fp_idx, 
+	     const char *filename, 
+	     const char *desc, 
+	     const char *entry,
+	     int handle,
+	     int poolno,
+	     void *data, 
+	     int sizeof_data, 
+	     int nelem);
+
+extern int
+newio_Write32(int *fp_idx, 
+	      const char *filename, 
+	      const char *desc, 
+	      const char *entry,
+	      int handle,
+	      int poolno,
+	      const void *data, 
+	      int sizeof_data, 
+	      int nelem);
+
+extern int
+newio_Open32(int *fp_idx, 
+	     const char *filename, 
+	     const char *dbname,
+	     const char *table,
+	     const char *desc,
+	     const char *entry,
+	     int handle,
+	     int poolno,
+	     const char *mode,
+	     int close_too,
+	     int lookup_only,
+	     unsigned int info[],
+	     int infolen);
+
+extern int
+newio_Close32(int *fp_idx, 
+	      const char *filename, 
+	      const char *dbname,
+	      const char *table,
+	      const char *desc,
+	      const char *entry,
+	      int handle,
+	      int poolno,
+	      unsigned int info[],
+	      int infolen
+	      );
+
+extern int
+newio_Size32(const char *filename,
+	     const char *dbname,
+	     const char *table,
+	     int handle,
+	     int poolno);
+
+extern int
+newio_GetByteswap(int *fp_idx, int handle, int poolno);
+
+extern int
+newio_SetByteswap(int *fp_idx, int toggle, int handle, int poolno);
+
+
+extern void 
+dd2ddl_(const char *dd_in,
+	const char *ddl_out
+	/* Hidden arguments */
+	,int dd_in_len
+	,int ddl_out_len
+	);
+
+#define ALLOCMORE(type,name,table,x,xlen,size) REALLOC(x,size)
+
+#ifndef MIN_ALLOC
+#define MIN_ALLOC 1
+#endif
+
+#ifndef INC_ALLOC
+#define INC_ALLOC 1
+#endif
+
+#define FREE_data(Var)     { FREE((Var).d); (Var).dlen = 0; (Var).nalloc = 0; }
+#define FREE_pkdata(Var)   { FREE((Var).pd); (Var).pdlen = 0; (Var).is_packed = 0; }
+#define FREE_savelist(Var) { FREE((Var).saved_data); (Var).saved_data_nbytes = 0; (Var).savelist = -1; }
+#define FREE_alldata(Var)  { FREE_data(Var); FREE_pkdata(Var); FREE_savelist(Var); }
+
+#define LINKOFFSET(s) Link2##s##_offset
+#define LINKLEN(s)    Link2##s##_length
+
+#define CHECK_PDS_ERROR(x) \
+  if (!PDS->on_error) Nbytes += BYTESIZE(PDS->pd); else { RAISE(SIGABRT); return -(x); }
+
+#define BW(bs, x) ((bs && Is_bitmap) ? MAXBITS : (x))
+
+#define FLAG_UPDATE(x) ((x) & 1U)
+#define FLAG_FETCH(x)  ((x) & 1U)
+#define FLAG_PACK(x)   ((x) & 2U)
+#define FLAG_FREE(x)   ((x) & 4U)
+
+#define PRINT_BITMAP(x)   ((x) & 1U)
+#define PRINT_BITFIELD(x) ((x) & 2U)
+#define PRINT_COLWISE(x)  ((x) & 4U)
+
+typedef struct _ODB_Setvar {
+  char *symbol;
+  double value;
+} ODB_Setvar;
+
+typedef struct _ODB_PE_Info {
+  double *addr;
+  char   *varname;
+  int     varname_len;
+  int     npes;
+  int    *nrowvec;
+  int     replicate_PE;
+} ODB_PE_Info;
+
+typedef struct _ODB_Tags {
+  char  *name;
+  int    is_usddothash;
+  int    nmem;
+  char **memb;
+} ODB_Tags;
+
+typedef enum { 
+  preptag_name    = 0x1,
+  preptag_type    = 0x2,
+  preptag_extname = 0x4,
+  preptag_exttype = 0x8,
+  preptag_tblname = 0x16
+} _ODB_PrepTag_Types;
+
+typedef struct _ODB_PrepTags { 
+  /* Prepared tags; for use by codb_getnames_() */
+  int    tagtype;      /* OR'red _ODB_PrepTag_Types */
+  int    longname_len; /* strlen() of longname */
+  char  *longname;     /* the "/xxx/yyy/zzz/" */
+} ODB_PrepTags;
+
+typedef struct _ODB_Trace {
+  int handle;
+  int mode;
+  char *msg;
+  int msglen;
+  int numargs;
+  int args[MAXTRACEARGS];
+} ODB_Trace;
+
+typedef struct _ODB_InterMed {
+  double **d;
+  int nr;
+  int nc;
+} ODB_InterMed;
+
+typedef struct _ODB_Pool {
+  int               handle;
+  int               inuse;
+  char             *dbname;
+  char             *srcpath;
+  int               poolno;
+  struct _ODB_PoolMask *pm;
+  void             (*add_var)(const char *dbname, 
+			      const char *symbol, 
+			      const char *viewname,
+			      int it,
+			      double addr);
+  int              (*load)(struct _ODB_Pool *pool, int io_method);
+  int              (*store)(const struct _ODB_Pool *pool, int io_method);
+  int               nfuncs;
+  struct _ODB_Funcs *funcs;
+  struct _ODB_Pool *next;
+} ODB_Pool;
+
+typedef struct _ODB_CommonFuncs {
+  char *name;
+  int is_table;
+  int is_considered; /* From ODB_CONSIDER_TABLES; by default considered i.e. == 1 */
+  int is_writable; /* From ODB_WRITE_TABLES; by default writable i.e. == 1 */
+  int ntables; /* Number of tables in view's ODB_CONSIDER_TABLES or 0 for tables */
+  int ncols;
+  int ncols_aux; /* Number of auxiliary columns not in SELECT; tot. columns = ncols */
+  int tableno;  /* Table's order number as it appears in the data layout file ("how many'th table") */
+  int rank;  /* Rank in TABLE hierarchy */
+  double wt; /* Hierarchy weight */
+  const ODB_Tags *tags;
+  const ODB_PrepTags *preptags;
+  int ntag;
+  int npreptag;
+  int nmem;
+  int has_select_distinct; /* > 0 for UNIQUEBY, < 0 for SELECT DISTINCT, 0 otherwise */
+  int has_usddothash; /* Has "$<parent_table>.<child_table>" -variables in SELECT */
+  int create_index; /* 0=Normal SELECT stmt, 1=CREATE UNIQUE INDEX, 2=CREATE BITMAP INDEX */
+  void *Info; /* Alias info_t: A future extension to allow "dynamic" queries via 'odbsql' */
+  void *(*init)(void *p, struct _ODB_Pool *pool, int is_new, int io_method, int it, int add_vars);
+  void  (*swapout)(void *p);
+  void  (*dim)(void *p, int *nrows, int *ncols, int *nrowoffset, int procid);
+  int  *(*sortkeys)(void *p, int *nsortkeys);
+  int   (*update_info)(void *p, const int ncols, int can_UPDATE[]);
+  int   (*aggr_info)(void *p, const int ncols, int aggr_func_flag[]);
+  int   (*select)(void *p, ODB_PE_Info *PEinfo, int phase, void *feedback);
+  void  (*peinfo)(void *p, ODB_PE_Info *PEinfo);
+  void  (*cancel)(void *p);
+  /* 64-bit floating point values */
+  int   (*dget)(void *p,       double d[], 
+	        int ldimd, int nrows, int ncols, int procid, const int flag[], int row_offset);
+  int   (*dput)(void *p, const double d[], 
+	        int ldimd, int nrows, int ncols, int procid, const int flag[]);
+  int   (*remove)(void *p);
+  int   (*load)(void *p);
+  int   (*store)(void *p);
+  int   (*pack)(void *p);
+  int   (*unpack)(void *p);
+  int   *(*getindex)(void *p, const char *table, int *lenidx);
+  int   (*putindex)(void *p, const char *table, int lenidx, int idx[], int by_address);
+  int   (*sql)(FILE *fp, int mode, const char *prefix, const char *postfix, char **sqlout);
+  int   (*colaux)(void *p, int colaux[], int colaux_len);
+} ODB_CommonFuncs;
+
+typedef struct _ODB_Funcs {
+  int   it; /* virtual thread id: 0 for TABLEs, 1..N for VIEWs */
+  void *data;
+  void *Res;  /* Alias result_t : A future extension to allow "dynamic" queries via 'odbsql' */
+  struct _ODB_InterMed *tmp; /* Intermediate data used by aggregate functions f.ex. */
+  struct _ODB_Pool *pool;
+  struct _ODB_CommonFuncs *common;
+  struct _ODB_Funcs *next;
+} ODB_Funcs;
+
+typedef struct _ODB_PoolMask {
+  int handle;
+  int npools;     /* No. of pools (fixed per handle) */
+  int inumt;      /* No. of threads (the N below) */
+  int **poolmask; /* For each thread it (1..N):
+                     Entry [it-1][0] ==> poolmask set (=1), not set (=0; the default)
+	 	     Entries [it-1][1..npools] : =1 if particular pool is to be INCLUDED
+		                                 =0 if particular pool is to be EXCLUDED
+		  */
+  char *dbname;
+} ODB_PoolMask;
+
+#define MAX_ODB_GLOBAL_LOCKS_OPENMP 4
+
+#if defined(ODB_POOLS)
+ODB_Pool *first_pool = NULL;
+ODB_Pool *last_pool = NULL;
+o_lock_t ODB_global_mylock[MAX_ODB_GLOBAL_LOCKS_OPENMP] = { 0 }; /* Specific OMP-locks; GLOBAL-variable; initialized only once in
+							     odb/lib/codb.c, routine codb_init_omp_locks_() */
+#else
+extern ODB_Pool *first_pool;
+extern ODB_Pool *last_pool;
+extern o_lock_t ODB_global_mylock[MAX_ODB_GLOBAL_LOCKS_OPENMP];  /* Specific OMP-locks; GLOBAL-variable; initialized only once in
+							     odb/lib/codb.c, routine codb_init_omp_locks_() */
+#endif
+
+extern int
+ODB_savelist(const char *dbname, /* NULL or f.ex. "ECMA" */
+	     const char *name);  /* Like "colname at tablename" */
+
+typedef struct _ODB_Anchor_Funcs {
+  int  (*create_funcs)(ODB_Pool *pool, int is_new, int io_method, int it);
+  int  (*load)(ODB_Pool *pool, int io_method);
+  int  (*store)(const ODB_Pool *pool, int io_method);
+} ODB_Anchor_Funcs;
+
+extern void
+codb_set_entrypoint_(const char *dbname,
+		     /* Hidden arguments */
+		     int dbname_len);
+
+extern void
+ODB_add2funclist(const char *dbname, 
+		 void (*func)(),
+		 int funcno);
+
+#define ODB_ANCHOR(db) \
+  { \
+    extern void db##_print_flags_file(); \
+    extern ODB_Funcs *Anchor2##db(void *, ODB_Pool *, int *, int it, int add_vars); \
+    ODB_addstatfunc(#db, NULL, Anchor2##db); \
+    ODB_add2funclist(#db, db##_print_flags_file, 1); \
+  }
+
+#define ODB_ANCHOR_VIEW(db, view) \
+  { \
+    extern ODB_Funcs *Anchor2##db##_##view(void *, ODB_Pool *, int *, int it, int add_vars); \
+    ODB_addstatfunc(#db, #view, Anchor2##db##_##view); \
+  }
+
+extern void 
+codb_save_peinfo_(const int *vhandle,
+		  const int *replicate_PE, 
+		  const int *npes);
+
+extern void 
+codb_restore_peinfo_(const int *vhandle,
+		     int *replicate_PE, 
+		     int *npes);
+
+extern ODB_Pool *
+get_poolreg(int handle, int poolno);
+
+extern void
+put_poolreg(int handle, int poolno, ODB_Pool *pool);
+
+extern ODB_Funcs *
+get_forfunc(int handle, 
+	    const char *dbname,
+	    int poolno, 
+	    int it, 
+	    const char *dataname,
+	    int do_abort);
+
+extern int 
+put_forfunc(ODB_Funcs *thisfunc, 
+	    int handle, 
+	    const char *dbname,
+	    int poolno, 
+	    int it, 
+	    const char *dataname);
+
+extern void
+nullify_forfunc(int handle, 
+		const char *dbname,
+		int poolno, 
+		int it, 
+		const char *dataname);
+
+extern void
+print_forfunc_(const int *enforce,
+	       const char *msg,
+	       /* Hidden arguments */
+	       int msg_len);
+
+extern void
+ctxreg_(const char *dbname,
+	const char *retr,
+	const int  *version,
+	const int  *ctxid,
+	int *retcode,
+	/* Hidden arguments */
+	int dbname_len,
+	int retr_len);
+
+extern void
+ctxid_(const char *dbname,
+       const char *retr,
+       const int  *version,
+       int *ctxid,
+       const int *ifailmsg,
+       int *retcode,
+       /* Hidden arguments */
+       int dbname_len,
+       int retr_len);
+
+extern void
+ctxdebug_(const int *enforce,
+	  const char *msg,
+	  /* Hidden arguments */
+	  int msg_len);
+
+extern void 
+cmdb_name_(const char *colname,
+	   char mdbname[],
+	   int *retcode,
+	   /* Hidden arguments */
+	         int colname_len,
+	   const int mdbname_len);
+
+extern void
+cmdb_reg_(const char *colname,
+	  const char *mdbname,
+	  int *mdbkey,
+	  const int *it,
+	  int *retcode,
+	  /* Hidden arguments */
+	  int colname_len,
+	  int mdbname_len);
+
+extern void
+cmdb_vecreg_(const char *colname,
+	     const char *mdbname,
+	     int vecmdbkey[],
+	     const int *low,
+	     const int *high,
+	     const int *it,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int colname_len,
+	     int mdbname_len);
+
+extern void
+cmdb_vecset_(const double zaddr[],
+	     const int *n_zaddr,
+	     int *retcode);
+
+extern void
+cmdb_set_(const char *colname,
+	  const int *actual_column_index,
+	  const int *it,
+	  int *retcode,
+	  /* Hidden arguments */
+	  int colname_len);
+
+extern void
+cmdb_reset_(const char *colname,
+	    int *reset_value,
+	    const int *it,
+	    int *retcode,
+	    /* Hidden arguments */
+	    int colname_len);
+
+extern void
+cmdb_get_(const char *colname,
+	  int *get_value,
+	  const int *it,
+	  int *retcode,
+	  /* Hidden arguments */
+	  int colname_len);
+
+extern void
+cmdb_addr_(const char *colname,
+	   double *zaddr,
+	   const int *it,
+	   int *retcode,
+	   /* Hidden arguments */
+	   int colname_len);
+
+extern void
+cmdb_debug_(const int *enforce,
+	    const char *msg,
+	    /* Hidden arguments */
+	    int msg_len);
+
+extern void
+cmdb_print_(const int *unit,
+	    const char *msg,
+	    const int *only_active,
+	    const int *it,
+	    int *retcode
+	    /* Hidden arguments */
+	    ,int msg_len);
+
+extern ODB_Pool *
+ODB_create_pool(int handle,
+		const char *dbname,
+		int poolno,
+		int is_new,
+		int io_method,
+		int add_vars);
+
+extern void
+ODB_del_vars(const char *dbname, 
+	     const char *viewname, 
+	     int it);
+
+extern int
+ODB_get_vars(const char *dbname,
+	     const char *viewname,
+	     int it,
+	     int nsetvar,
+	     ODB_Setvar setvar[]);
+
+extern void
+ODB_add_var(const char *dbname, 
+	    const char *symbol, 
+	    const char *viewname,
+	    int it,
+	    double addr);
+
+extern double *
+ODB_alter_var(const char   *dbname, 
+	      const char   *symbol,
+	      const char   *viewname,
+	      int it,
+	      const double *newvalue,
+	      double       *oldvalue,
+	      int           recur);
+
+extern double *
+ODB_getaddr_var(const char   *dbname, 
+		const char   *symbol,
+		const char   *viewname,
+		int it);
+
+extern double
+ODB_getval_var(const char   *dbname, 
+	       const char   *symbol,
+	       const char   *viewname,
+	       int it);
+
+extern int
+ODB_add_funcs(ODB_Pool *pool, ODB_Funcs *funcs, int it);
+
+extern int
+ODB_dynfill(const char *usddothash,
+	    void *V,
+	    int *(*getindex)(void *V, const char *table, int *lenidx),
+	    double data[], int ndata,
+	    int istart, int iend, int ioffset);
+
+extern ODB_PoolMask *
+ODB_get_poolmask_by_handle(int handle);
+
+extern void
+codb_reset_poolmask_(const int *handle,
+		     const int *ithread);
+
+extern void
+codb_print_poolmask_(const int *handle,
+		     const int *ithread);
+
+extern void 
+apply_poolmasking_(const int *khandle, const int *kversion, 
+		   const char *cdlabel, const int *kvlabel,
+		   const int *ktslot, const int *kobstype, const int *kcodetype, const int *ksensor,
+		   const int *ksubtype, const int *kbufrtype, const int *ksatinst
+		   /* Hidden arguments */
+		   , int cdlabel_len);
+
+extern void
+codb_poolmasking_status_(const int *handle,
+			 int *retcode);
+
+extern void
+codb_toggle_poolmask_(const int *handle, 
+		      const int *onoff, 
+		      int *oldvalue);
+
+extern void
+codb_alloc_poolmask_(const int *maxhandle);
+
+extern void
+codb_end_poolmask_(const int *handle);
+
+extern void
+codb_init_poolmask_(const int *handle,
+		    const char *dbname,
+		    const int *poolnos_in
+		    /* Hidden arguments */
+		    ,int dbname_len);
+
+extern void
+codb_get_permanent_poolmask_(const int *handle,
+			     const int *num_poolnos_in,
+			     int  poolnos[],
+			     int *num_poolnos_out);
+
+extern void
+codb_in_permanent_poolmask_(const int *handle,
+			    const int *poolno,
+			    int *retcode);
+
+extern int
+ODB_in_permanent_poolmask(int handle, int poolno);
+
+extern void
+codb_get_poolmask_(const int *handle,
+		   const int *poolnos_in,
+		         int  poolnos[],
+		         int *poolmask_set,
+		         int *poolnos_out);
+
+extern int *
+ODB_get_permanent_poolmask(int handle, int *npools);
+
+extern void
+codb_set_poolmask_(const int *handle,
+		   const int *poolnos_in,
+		   const int  poolnos[],
+		   const int *onoff);
+
+extern void
+odb_flpcheck_(const double d[],
+	      const   int *nd,
+	              int  flag[],
+	      const   int *nf,
+	              int *rinf,
+	              int *rtiny,
+	              int *rnan);
+
+extern void
+odb_intcheck_(const double d[],
+	      const   int *nd,
+	      const   int *test_unsigned_only,
+	              int  flag[],
+	      const   int *nf,
+	              int *nlo,
+	              int *nhi);
+
+extern FILE *
+ODB_getprt_FP();
+
+extern void
+ODB_check_considereness(int is_considered,
+			const char *tblname);
+extern void
+codb_consider_table_(const int *handle,
+		     const char *tblname, /* Must begin with '@' in front of */
+		     int *option_code, /* -1 = get info; 1/0 = set consider/not_consider'ness */
+		     int *retcode,     /* previous value of consider'ness */
+		     /* Hidden arguments */
+		     int tblname_len);
+
+extern int
+TableIsConsidered(const char *tblname);
+
+extern void
+codb_table_is_considered_(const char *tblname,
+			  int *retcode,
+			  /* Hidden arguments */
+			  int tblname_len);
+
+/* Anne Fouilloux - 23/02/10 - add ODB_WRITE_TABLES to give a list of table to write back on disk (if modified) */
+extern void
+codb_write_table_(const int *handle,
+             const char *tblname, /* Must begin with '@' in front of */
+             int *option_code, /* -1 = get info; 1/0 = set writable/not_writable'ness */
+             int *retcode,     /* previous value of consider'ness */
+             /* Hidden arguments */
+             int tblname_len);
+
+extern int
+TableIsWritable(const char *tblname);
+
+extern void
+codb_table_is_writable_(const char *tblname,
+              int *retcode,
+              /* Hidden arguments */
+              int tblname_len);
+
+/* End Anne Fouilloux - 23/02/10 */
+
+extern void
+codb_print_flags_file_(const char *dbname,
+		       const int *myproc,
+		       int *retcode,
+		       /* Hidden arguments */
+		       int dbname_len);
+
+extern void
+codb_static_init_(const char *a_out,
+		  const char *dbname,
+		  const int *myproc,
+		  int *retcode,
+		  /* Hidden arguments */
+		  int a_out_len,
+		  int dbname_len);
+
+extern void
+codb_sqlprint_(const int *handle,
+	       const char *dataname, 
+	       int *retcode,
+	       /* Hidden arguments */
+	       int dataname_len);
+
+extern void
+codb_getindex_(const int *handle,
+	       const int  *poolno,
+	       const char *viewname,
+	       const char *tablename,
+	       const int *idxlen,
+	       int idx[],
+	       int *retcode,
+	       const int *using_it,
+	       /* Hidden arguments */
+	       int viewname_len,
+	       int tablename_len);
+
+extern void
+codb_putindex_(const int *handle,
+	       const int  *poolno,
+	       const char *viewname,
+	       const char *tablename,
+	       const int *idxlen,
+	       const int idx[],
+	       int *retcode,
+	       const int *using_it,
+	       /* Hidden arguments */
+	       int viewname_len,
+	       int tablename_len);
+
+extern void 
+codb_gethandle_(const int *handle,
+		const char *dataname,
+		int *retcode,
+		const int *using_it,
+		/* Hidden arguments */
+		int dataname_len);
+
+extern void 
+codb_get_view_info_(const int *handle,
+		    const char *dataname,
+		    int  view_info[],
+		    const int *nview_info,
+		    int *retcode,
+		    /* Hidden arguments */
+		    int dataname_len);
+
+extern void 
+codb_sortkeys_(const int *handle,
+	       const char *dataname,
+	       int *nkeys,
+	       int  mkeys[],
+	       int *retcode,
+	       /* Hidden arguments */
+	       int dataname_len);
+
+extern void 
+codb_update_info_(const int *handle,
+		  const char *dataname,
+		  const int *ncols,
+		  int  can_UPDATE[],
+		  int *retcode,
+		  /* Hidden arguments */
+		  int dataname_len);
+
+extern void 
+codb_aggr_info_(const int *handle,
+		const int  *poolno,
+		const char *dataname,
+		const int *ncols,
+		int  aggr_func_flag[],
+		int *phase_id,
+		const int *using_it,
+		int *retcode,
+		/* Hidden arguments */
+		int dataname_len);
+
+extern void
+codb_calc_aggr_(const int    *phase_id,
+		const int    *aggr_func_flag,
+		int          *nrc,
+		double        rc[],
+		const int    *nd, 
+		const double  d[],
+		const double  daux[]);
+
+extern void
+codb_init_twindow_();
+
+extern void
+codb_twindow_(const int *target_date,
+	      const int *target_time,
+	      const int *anal_date,
+	      const int *anal_time,
+	      const int *left_margin,
+	      const int *right_margin,
+	      int *retcode);
+
+extern void
+codb_tdiff_(const int *target_date,
+	    const int *target_time,
+	    const int *anal_date,
+	    const int *anal_time,
+	    int *diff);
+
+extern void
+codb_envtransf_(const char *in,
+		      char *out,
+		       int *retcode,
+		/* Hidden arguments */
+		      int  in_len,
+		const int  out_len);
+
+extern void 
+codb_truename_(const char *in,
+	             char *out,
+	              int *retcode,
+	       /* Hidden arguments */
+	             int  in_len,
+	       const int  out_len);
+
+extern void
+codb_pc_filter_(const char *in,
+		char *out,
+		const int *procid,
+		int *retcode,
+		/* Hidden arguments */
+		int in_len,
+		const int out_len);
+
+extern void
+codb_init_omp_locks_();
+
+extern void
+codb_trace_init_(int *trace_on);
+
+extern void
+codb_trace_(const int  *handle,
+	    const int  *mode,
+	    const char *msg,
+	    const int   args[],
+	    const int  *numargs,
+	    /* Hidden arguments */
+	    int msg_len);
+
+extern FILE *
+ODB_trace_fp();
+
+extern void 
+codb_trace_begin_();
+
+extern void 
+codb_trace_end_();
+
+extern void
+ODB_debug_print_index(FILE *fp, const char *View, int poolno, int n, int ntbl, ...);
+
+extern void
+codb_set_progress_bar_(const char *param,
+		       const int *value
+		       /* Hidden arguments */
+		       , int param_len);
+
+extern void
+codb_get_progress_bar_(const char *param,
+		       int *value
+		       /* Hidden arguments */
+		       , int param_len);
+
+extern void
+codb_progress_nl_(const int *iounit);
+
+extern void
+codb_progress_bar_(const int *iounit,
+		   const char *dtname,
+		   const int *curpool,
+		   const int *maxpool,
+		   const int *currows,
+		   const int *totalrows,
+		   const double *wtime,
+		   const int *newline
+		   /* Hidden arguments */
+		   , int dtname_len);
+
+extern void
+ODB_packing_setup(int *prtmsg, int *threshold, double *factor);
+
+extern int
+ODB_packing(const int *pmethod);
+
+extern void
+ODB_packing_trace(int mode,
+		  const char *type, const char *name, const char *table,
+		  int pmethod, int pmethod_from_datatype,
+		  int dlen, int sizeof_dlen, int pdlen, uint datatype);
+
+extern double *
+ODB_unpack_DBL(const uint pd[],
+               const int  pdlen,
+                     int *dlen,
+                     int *method_used,
+	            uint  datatype);
+
+extern uint *
+ODB_pack_DBL(const double d[],
+               const int  dlen,
+                     int *method,
+                     int *pdlen,
+	             Bool avoid_copy);
+
+extern int *
+ODB_unpack_INT(const uint pd[],
+               const int  pdlen,
+                     int *dlen,
+                     int *method_used,
+	            uint  datatype);
+
+extern uint *
+ODB_pack_INT(const int  d[],
+             const int  dlen,
+                   int *method,
+                   int *pdlen,
+	           Bool avoid_copy);
+
+extern uint *
+ODB_unpack_UINT(const uint pd[],
+                const int  pdlen,
+                      int *dlen,
+                      int *method_used,
+	             uint  datatype);
+
+extern uint *
+ODB_pack_UINT(const uint d[],
+              const int  dlen,
+                    int *method,
+                    int *pdlen,
+	            Bool avoid_copy);
+
+extern void
+codb_print_vars_(const int *enforce,
+		 const char *msg,
+		 /* Hidden arguments */
+		 int msg_len);
+
+extern void
+codb_procdata_(int *myproc,
+	       int *nproc,
+	       int *pid,
+	       int *it,
+	       int *inumt);
+
+extern void
+codb_init_(const int *myproc, 
+	   const int *nproc);
+
+extern void
+setup_sort_(const int *func_no,
+	    int *prev_func_no);
+
+extern void /* a Fortran-routine */
+ckeysort_(double *a, 
+	  const int *nra, 
+	  const int *nrows, 
+	  const int *ncols, 
+	  const int keys[], 
+	  const int *nkeys,
+	  int idx[],
+	  const int *nidx,
+	  const int *init_idx,
+	  int *iret);
+
+extern void 
+init_region_(int array[], 
+	     const int *nbytes, 
+	     const int *the_magic_4bytes);
+
+extern void
+codb_abort_func_(const char *msg,
+		 /* Hidden arguments */
+		 int msg_len);
+
+extern void 
+codb_register_abort_func_(const char *name,
+                          /* Hidden arguments */
+                          int name_len);
+
+extern const char *
+odb_datetime_(int *date_out, int *time_out);
+
+extern const char *
+odb_resource_stamp_(const char *label);
+
+extern void
+codb_datetime_(int *date_out, int *time_out);
+
+extern void
+codb_analysis_datetime_(int *date_out, int *time_out);
+
+extern void 
+codb_create_pool_(const int  *handle,
+		  const char *dbname,
+		  const int  *poolno,
+		  const int  *is_new,
+		  const int  *io_method,
+		  const int  *add_vars,
+		  int *retcode,
+		  /* Hidden arguments */
+		  int dbname_len);
+
+extern void
+codb_close_(const int *handle,
+	    const int *save,
+	          int *retcode);
+
+extern void
+codb_load_(const int *handle,
+	   const int *poolno,
+	   const int *io_method,
+	   int *retcode);
+
+extern void
+codb_store_(const int *handle,
+	    const int *poolno,
+	    const int *io_method,
+	    int *retcode);
+
+extern void
+codb_select_(const int *handle,
+	     const int  *poolno,
+	     const char *dataname,
+	     int *nrows,
+	     int *ncols,
+	     int *retcode,
+	     const int *inform_progress,
+	     const int  *using_it,
+	     /* Hidden arguments */
+	     int dataname_len);
+
+extern void
+codb_mp_select_(const int *handle,
+		const int *poolno,
+		const char *dataname,
+		int nrows[],
+		int *ncols,
+		int *retcode,
+		const char *pevar,
+		const int *npes,
+		const int *replicate_PE,
+		const int  *using_it,
+		/* Hidden arguments */
+		int dataname_len,
+		int pevar_len);
+
+extern void
+codb_get_npes_(const int *handle,
+	       const int *poolno,
+	       const char *dataname,
+	       int *replicate_PE,
+	       int *retcode,
+	       const int  *using_it,
+	       /* Hidden arguments */
+	       int dataname_len);
+
+extern void
+codb_get_rowvec_(const int *handle,
+		 const int *poolno,
+		 const char *dataname,
+		 int  nrows[],
+		 const int *npes,
+		 int *retcode,
+		 const int  *using_it,
+		 /* Hidden arguments */
+		 int dataname_len);
+
+extern void
+codb_cancel_(const int  *handle,
+	     const int  *poolno,
+	     const char *dataname,
+	     int *retcode,
+	     const int  *delete_intermed,
+	     const int  *using_it,
+	     /* Hidden arguments */
+	     int dataname_len);
+
+extern void
+codb_swapout_(const int  *handle,
+	      const int  *poolno,
+	      const char *dataname,
+	      const int  *save,
+	      int  *retcode,
+	      const int  *delete_intermed,
+	      const int  *using_it,
+	      /* Hidden arguments */
+	      int dataname_len);
+
+extern void
+codb_packer_(const int  *handle,
+	     const int  *poolno,
+	     const char *dataname,
+	     const int  *pack_it,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int dataname_len);
+
+extern void
+codb_getval_(const char   *dbname,
+	     const char   *varname,
+	     const char   *viewname,
+	     double *value,
+	     const int  *using_it,
+	     /* Hidden arguments */
+	     int dbname_len,
+	     int varname_len,
+	     int viewname_len);
+
+extern void
+codb_setval_(const char   *dbname,
+	     const char   *varname,
+	     const char   *viewname,
+	     const double *newvalue,
+	           double *oldvalue,
+	     const int  *using_it,
+	     /* Hidden arguments */
+	     int dbname_len,
+	     int varname_len,
+	     int viewname_len);
+
+
+extern void
+codb_remove_(const int *handle,
+	     const int  *poolno,
+	     const char *dataname,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int dataname_len);
+
+
+extern void
+codb_dget_(const int *handle,
+	   const int  *poolno,
+	   const char *dataname,
+	   double d[],
+	   const int *doffset,
+	   const int *ldimd,
+	   const int *nrows,
+	   const int *ncols,
+	   const int  flag[],
+	   const int *procid,
+	   const int *istart,
+	   const int *ilimit,
+	   const int *inform_progress,
+	   const int  *using_it,
+	   int *retcode,
+	   /* Hidden arguments */
+	   int dataname_len);
+
+extern void
+codb_dput_(const int *handle,
+	   const int  *poolno,
+	   const char *dataname,
+	   const double d[],
+	   const int *doffset,
+	   const int *ldimd,
+	   const int *nrows,
+	   const int *ncols,
+	   const int  flag[],
+	   const int *procid,
+	   const int *fill_intermed,
+	   const int  *using_it,
+	   int *retcode,
+	   /* Hidden arguments */
+	   int dataname_len);
+
+extern void
+codb_getsize_(const int *handle,
+	      const int  *poolno,
+	      const char *dataname,
+	      int *nrows,
+	      int *ncols,
+	      const int *recur,
+	      int *retcode,
+	      const int  *using_it,
+	      /* Hidden arguments */
+	      int dataname_len);
+
+extern void
+codb_getsize_aux_(const int *handle,
+		  const int  *poolno,
+		  const char *dataname,
+		  const int *ncols,
+		  int *ncols_aux,
+		  int  colaux[],
+		  const int *colaux_len,
+		  int *retcode,
+		  const int  *using_it,
+		  /* Hidden arguments */
+		  int dataname_len);
+
+extern void
+write_ddl_(const int  *handle,
+	   const int  *iounit,
+	   int *retcode);
+
+extern void
+codb_write_metadata_(const int  *handle,
+		     const int  *iounit,
+		     const int  *npools,
+		     const int   CreationDT[],
+		     const int   AnalysisDT[],
+		     const double  *major,
+		     const double  *minor,
+		     const int  *io_method,
+		     int *retcode);
+
+extern void
+codb_write_metadata2_(const int  *handle,
+		      const int  *iounit,
+		      const int  *npools,
+		      const int  *ntables,
+		      /* const int   fsize[], *//* Npools x Ntables */
+		      int *retcode);
+
+extern void
+codb_write_metadata3_(const int  *handle,
+		      const int  *iounit,
+		      int *retcode);
+
+extern void
+codb_read_metadata_(const int  *handle,
+		    const int  *iounit,
+		    int  *npools,
+		    int   CreationDT[],
+		    int   AnalysisDT[],
+		    double  *major,
+		    double  *minor,
+		    int  *io_method,
+		    int *retcode);
+
+extern void
+codb_read_metadata2_(const int  *handle,
+		     const int  *iounit,
+		     const int  *npools,
+		     const int  *ntables,
+		     /*      int   fsize[], */ /* Npools x Ntables */
+		     int *retcode);
+
+extern void
+codb_tag_delim_(char *output
+		/* Hidden arguments */
+		, const int output_len);
+
+extern void 
+codb_getnames_(const int *handle,
+	       const char *dataname,
+	       const int *what, /* 1  = datatype, 
+				   2  = varname, 
+				   3  = tablename, 
+				   4  = viewname,
+				   11 = ftntype,
+				  101 = exttype,    (same as datatype, but adds bit<#> for bitfield members)
+				  102 = extname,    (same as varname, but gets bitfield members)
+				  111 = extftntype, (same as ftntype, but handles bitfield members)
+				*/
+	       char *output,    /* Output string: "/xxx/yyy/zzz/" */
+	       int *actual_output_len, /* # of bytes written into *output, excluding '\0' */
+	       int *retcode,    /* # of cols resolved */
+	       /* Hidden arguments */
+	       int dataname_len,
+	       const int output_len);
+
+extern void 
+codb_getprecision_(const int *handle,
+		   const char *dataname,
+		   int *maxbits,
+		   int *anyflp,
+		   int *retcode,
+		   /* Hidden arguments */
+		   int dataname_len);
+
+extern void
+codb_makeview_(const int  *handle,
+               const char *dataname,
+               const char *viewfile,
+               const char *select,
+               const char *uniqueby,
+               const char *from,
+               const char *where,
+               const char *orderby,
+	       const char *set,
+	       const char *query,
+               int *retcode,
+	       /* Hidden arguments */
+               int dataname_len,
+               int viewfile_len,
+	       int select_len,
+	       int uniqueby_len,
+	       int from_len,
+	       int where_len,
+	       int orderby_len,
+	       int set_len,
+	       int query_len);
+
+extern void
+codb_linkdb_(const char *dbname,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int dbname_len);
+
+extern void
+codb_linkview_(const int *handle, 
+	       const char *dataname,
+	       int *retcode,
+	       /* Hidden arguments */
+	       int dataname_len);
+
+extern void
+codb_filesize_(const char *filename,
+	       int *retcode,
+	       /* Hidden arguments */
+	       int filename_len);
+
+extern void
+codb_remove_file_(const char *filename,
+		  int *retcode,
+                  /* Hidden arguments */
+                  int filename_len);
+
+extern void
+codb_rename_file_(const char *oldfile,
+		  const char *newfile,
+		  int *retcode,
+                  /* Hidden arguments */
+		  int newfile_len,
+                  int oldfile_len);
+
+extern void
+codb_tablesize_(const char *dbname,
+		const char *table,
+		const int  *poolno,
+		int *retcode,
+		/* Hidden arguments */
+		int dbname_len,
+		int table_len);
+
+extern void
+ODB_addstatfunc(const char *dbname,
+		const char *viewname,
+		ODB_Funcs *(*anchor)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars));
+
+extern int
+ODB_undo_dynlink(const char *dbname, 
+		 boolean views_only);
+
+extern void
+codb_test_index_range_(const int vec[],
+		       const int *veclen,
+		       const int *low,
+		       const int *high,
+		       int *retcode);
+
+extern void 
+codb_mask_control_word_(double vec[],
+			const int *k1, /* Note : C-indexing */
+			const int *k2, /* Note : C-indexing */
+			const int *doffset,
+			const int poolno[]);
+
+extern void 
+codb_put_control_word_(double vec[],
+		       const int *k1,
+		       const int *k2,
+		       const int *doffset,
+		       const int *poolno,
+		       const int *noffset);
+
+extern double
+ODB_put_one_control_word(int k, int poolno);
+
+extern void 
+codb_get_control_word_(const double vec[],
+		       const int *k1,
+		       const int *k2,
+		       const int *doffset,
+		       ll_t ctrlw[]);
+
+extern void
+codb_get_pool_count_(const double vec[],
+		     const int *k1,
+		     const int *k2,
+		     const int *doffset,
+		     const int *npools,
+		     const int poolno[],
+		     int *retcode);
+
+extern void
+codb_get_poolnos_(const double vec[],
+		  const int *k1,
+		  const int *k2,
+		  const int *doffset,
+		  int poolno_out[]);
+
+extern void
+codb_get_rownum_(const double vec[],
+		 const int *k1,
+		 const int *k2,
+		 const int *doffset,
+		 const int *noffset,
+		 int rownum[]);
+
+extern void 
+cmask32bits_(uint u[], const int *n, const int *nbits);
+
+extern void 
+cmask64bits_(u_ll_t u[], const int *n, const int *nbits);
+
+extern void
+codb_init_ae_dump_(int *retcode);
+
+void
+codb_ae_dump_(const int *handle,
+	      const int *is_get,
+	      const int *poolno,
+	      const char *dtname,
+	      const int *datatype,
+	      const int *nra,
+	      const int *nrows,
+	      const int *ncols,
+	      const void *data
+	      /* Hidden arguments */
+	      , int dtname_len);
+
+extern void
+codb_vechash_(const int *nval,
+	      const int *nlda,      /* the leading dimension of u ; >= Nval */
+	      const int *nelem, 
+	      const uint u[], /* actual size : Nlda x  Nelem */
+	            uint h[]);
+
+extern uint 
+ODB_Hashsize();
+
+extern void 
+ODB_Hash_print(FILE *fp);
+
+#define Func_Unique    ODB_Unique
+extern int ODB_Unique(const int n, ...);
+extern double ODBunique(const int n, const double args[]);
+
+extern void
+ODB_Update_Hashmaxmin(int n, const uint h[]);
+
+extern void
+codb_hash_set_lock_();
+
+extern void
+codb_hash_unset_lock_();
+
+extern void
+codb_hash_init_();
+
+extern void
+codb_hash_reset_();
+
+extern void
+codb_d_unique_(const int *n, 
+	       const double d[],
+	       const uint *hash,
+	       int *is_unique,
+	       int *tag,
+	       uint *hash_out);
+
+extern void
+codb_r_unique_(const int *n,
+	       const float r[],
+	       const uint *hash,
+	       int *is_unique,
+	       int *tag,
+	       uint *hash_out);
+
+extern void
+codb_ui_unique_(const int *n,
+		const uint ui[],
+		const uint *hash,
+		int *is_unique,
+		int *tag,
+		uint *hash_out);
+
+extern void
+ODB_dbl2dbl(double to[], 
+	    const double from[],
+	    int n);
+
+extern void
+ODB_float2dbl(double to[], 
+	      const float from[],
+	      int n);
+
+extern void
+ODB_uint2dbl(double to[],
+	     const uint from[],
+	     int n);
+
+extern double
+ODB_twindow(double dtarget_date,  /* Date to be checked */   
+	    double dtarget_time,  /* Time to be checked */
+	    double danal_date,    /* Analysis date in format YYYYMMDD */
+	    double danal_time,    /* Analysis time in format   HHMMSS */
+	    double dleft_margin,  /* Left bdry; offset from analysis tstamp in +/-HHMMSS, HH can be > 23 */
+	    double dright_margin  /* Right bdry; offset from analysis tstamp in +/-HHMMSS, HH can be > 23 */
+	    );
+
+extern double
+ODB_tdiff(double dtarget_date,  /* Date to be checked */   
+	  double dtarget_time,  /* Time to be checked */
+	  double danal_date,    /* Analysis date in format YYYYMMDD */
+	  double danal_time     /* Analysis time in format   HHMMSS */
+	  );
+
+extern boolean
+ODB_uint_equal(const uint u1[], const uint u2[], int n);
+
+extern boolean
+ODB_uchar_equal(const unsigned char u1[], const unsigned char u2[], int n);
+
+extern void
+ODB_get_packing_consts(uint *magic, uint *hdrlen, uint *maxshift,
+		       double *nmdi, double *rmdi, int *new_version);
+
+extern void
+codb_d2u_(const double *d, uint *u);
+
+extern int
+ODB_min_alloc();
+
+extern int
+ODB_inc_alloc(int n, int min_alloc);
+
+extern void
+codb_set_signals_();
+
+extern void 
+codb_ignore_alarm_();
+
+extern void 
+codb_catch_alarm_(int *sig);
+
+extern void 
+codb_set_alarm_();
+
+extern void 
+codb_send_alarm_(int *pid);
+
+extern void
+codb_closeprt_(int *retcode);
+
+extern void
+codb_openprt_(const char *filename,
+	      const int *append_mode,
+	      int *retcode,
+	      /* Hidden arguments */
+	      int filename_len);
+
+extern void
+codb_lineprt_(const unsigned char *line,
+	      int *retcode,
+	      /* Hidden arguments */
+	      int line_len);
+
+extern void
+codb_flushprt_(int *retcode);
+
+extern void
+ODB_iolock(int onoff);
+
+#define Func_WildCard  ODB_WildCard
+extern int
+ODB_WildCard(int n, const char *str, ...);
+extern double
+ODBwildcard(const int Nd, const double d[]);
+
+#define Func_StrEqual  ODB_StrEqual
+extern int
+ODB_StrEqual(int n, const char *str, ...);
+extern double
+ODBstrequal(const int Nd, const double d[]);
+
+#define Func_Inside ODB_Inside
+extern int
+ODB_Inside(const char *region_name, double lat, double lon);
+extern double
+ODBinside(double region_name, double lat, double lon);
+
+#define Func_InPolygon ODB_InPolygon
+extern int
+ODB_InPolygon(const char *polygon_filename, double lat, double lon);
+extern double
+ODBinpolygon(double polygon_filename, double lat, double lon);
+
+#define Func_Near ODB_Near
+extern double
+ODB_Near(const char *place_name, double lat, double lon);
+extern double
+ODBnear(double place_name, double lat, double lon);
+
+#define Func_lat ODB_Lat
+extern double ODB_Lat(const char *place_name);
+extern double ODBlat(double place_name);
+
+#define Func_lon ODB_Lon
+extern double ODB_Lon(const char *place_name);
+extern double ODBlon(double place_name);
+
+#define Func_alt ODB_Alt
+extern double ODB_Alt(const char *place_name);
+extern double ODBalt(double place_name);
+
+#define Func_pop ODB_Pop
+extern double ODB_Pop(const char *place_name);
+extern double ODBpop(double place_name);
+
+#define Func_RunOnceQuery  ODB_SubQuery
+#define Func_SubQuery  ODB_SubQuery
+extern double ODB_SubQuery(const int n, 
+			   /* const char *poolmask, const char *db, const char *query, double make_sort_unique */ ...);
+extern double ODBsubquery(const int nargs, const double args[]);
+
+#define Func_InQuery  ODB_InQuery
+extern double ODB_InQuery(const int num_expr, const int nummatch, double subquery, double runonce 
+			  , /* double expr1, [double expr2, ... ] */ ...);
+extern double ODBinquery(const int nargs, const double args[]);
+
+extern int
+ODB_Common_StrEqual(const char *str,
+		    const char *cmpstr,
+		    int n, const double d[], 
+		    Boolean is_wildcard);
+
+extern void    destroy_alist();
+extern char   *init_alist(const char *p);
+extern boolean in_alist(const char *p);
+extern char   *add_alist(const char *p);
+
+/* Consistent logical filenames for TABLEs */
+
+/* Since ALLOCX may use alloca(), don't encapsulate the MakeFileName around {}'s 
+   Please note that you have to use FREEX, not FREE-macro to deallocate "filename" */
+#define MakeFileName(filename, dbname, table, poolno) \
+ ALLOCX(filename, strlen(dbname) + strlen(table) + 20); \
+ sprintf(filename, "%s.%s.%d", dbname, table, poolno); \
+
+/* Generic data structure (DS) manipulation macros */
+
+typedef struct {
+  uint *pd;
+  int   pdlen;
+  void *opaque;
+  int   nbytes;
+  int   on_error;
+} Packed_DS;
+
+#define DefineDS(Type) \
+  typedef struct { \
+    char *type; \
+    char *name; \
+    char *xname; \
+    char *table; \
+    Type *d; \
+    uint *pd; \
+    uint  datatype; \
+    int   elemsize; \
+    int   dlen; \
+    int   nalloc; \
+    int   pdlen; \
+    int   pmethod; \
+    int   pmethod_from_datatype; \
+    int   is_packed; \
+    int   savelist; \
+    void *saved_data; \
+    int   saved_data_nbytes; \
+    int   saved_data_N[2]; \
+  } DS_##Type
+
+#define DeclareDS(Type, Var) DS_##Type Var
+
+#endif /* _ODB_H_ */
diff --git a/odb/src/include/odb_ioprof.h b/odb/src/include/odb_ioprof.h
new file mode 100644
index 0000000..b9afc45
--- /dev/null
+++ b/odb/src/include/odb_ioprof.h
@@ -0,0 +1,16 @@
+
+/* odb_ioprof.h */
+
+enum { 
+  ioprof_read    = 1,
+  ioprof_write   = 2,
+  ioprof_open    = 4,
+  ioprof_close   = 8,
+  ioprof_iolock  = 16,
+  ioprof_rmfile  = 32
+};
+
+extern void Profile_newio32_init(int myproc);
+extern void Profile_newio32_start(int what, int n);
+extern void Profile_newio32_end(int what, int n);
+extern void Profile_newio32_flush();
diff --git a/odb/src/include/odb_macros.h b/odb/src/include/odb_macros.h
new file mode 100644
index 0000000..b7d20ed
--- /dev/null
+++ b/odb/src/include/odb_macros.h
@@ -0,0 +1,1145 @@
+#ifndef _ODB_MACROS_H_
+#define _ODB_MACROS_H_
+
+extern int
+Read_DS(void *Pvar,
+	int Handle, int PoolNo, int Nrows, int Byteswap, int IO_method,
+	const char *Dbase, int fp_idx, const char *filename,
+	uint datatype);
+
+extern int
+Write_DS(void *Pvar,
+	 int Handle, int PoolNo, int Nrows, int Byteswap, int IO_method,
+	 const char *Dbase, int fp_idx, const char *filename,
+	 uint datatype,
+	 Packed_DS *(*DoPackDS)(void *));
+
+extern int
+ODBSQL_PrintGet(const char *Sql[],
+		FILE *fp, int mode, const char *prefix, const char *postfix, char **sqlout);
+
+extern int
+ODBCopyGetTable(int Flag, int Count, double D[], const void *Var, uint datatype, int row_offset);
+
+extern int
+ODBCopyPutTable(int Flag, int Count, void *Var, const double D[], uint datatype);
+
+extern void
+ODBGatherGetBits(int k1, int k2, const int *Index, double d[], const void *Var, uint datatype,
+		 int pos, int len, int row_offset);
+
+extern void
+ODBScatterPutBits(int k1, int k2, const int *Index, void *Var, const double d[], uint datatype,
+		  int pos, int len);
+
+#ifdef ODB_GENCODE
+/* For generated codes only */
+
+/* Macros used by generated C-code to shorten the code itself */
+
+#define ALLOCINDEX(name, cnt) ALLOC(P->Index_##name, cnt); P->Allocated_##name = 1
+#define FREEINDEX(name)  if (P->Allocated_##name) FREE(P->Index_##name)
+
+/* Use of bitmap-index not implemented yet */
+#ifdef USE_BITMAP_INDEX
+#define ALLOCBITMAPINDEX(name) { int n_ = RNDUP_DIV(P->T_##name->Nrows, MAXBITS); ALLOC(P->BitmapIndex_##name, n_); }
+#else
+#define ALLOCBITMAPINDEX(name) P->BitmapIndex_##name = NULL
+#endif
+
+#define FREEBITMAPINDEX(name)  FREE(P->BitmapIndex_##name)
+
+#define NULLIFY_INDEX(name)  \
+  P->BitmapIndex_##name = NULL; P->Index_##name = NULL; P->Allocated_##name = 0
+
+#define OFFSET_Macro(macro,i,offset) \
+(((i+offset)>=i##_lo && (i+offset)<i##_hi) ? macro((int)(i+offset)) : 0)
+
+#define FreeDS(P, Var, Nbytes, Count) { \
+  if (P->Var.is_packed) { Nbytes += P->Var.pdlen * sizeof(*P->Var.pd); } \
+                   else { Nbytes += P->Var.dlen * P->Var.elemsize; } \
+  if (P->Var.savelist == 0) Nbytes += P->Var.saved_data_nbytes; \
+  Count++; FREE_alldata(P->Var); \
+}
+
+/* Copy for Get/Put Table */
+
+#define Call_CopyGet_TABLE(Dbase, Key, Num, Table, Type, D, Var, Count, DataType) \
+{ \
+  Type *Ptr = UseDS(P, Dbase, Type, Var); \
+  if (P->Var.d != Ptr || !Ptr || P->Var.dlen < Count) { \
+    fprintf(stderr,\
+    "***Error in CopyGet_TABLE(%s, col#%d, @%s, d=%p, LdimD=%d, var=%s, Ptr=%p," \
+    " Var.d=%p, dlen=%d, Count=%d, type=(%d,%s))\n", \
+    #Dbase, Num, #Table, D, LdimD, P->Var.name, Ptr, P->Var.d, P->Var.dlen, \
+    Count, DataType, #Type); RAISE(SIGABRT); \
+  } \
+  (void) ODBCopyGetTable(Flag[(Num-1)], Count, &D[(Num-1)*LdimD], Ptr, DataType, row_offset); \
+  if (FLAG_FREE(Flag[(Num-1)])) { int Dummy=0; FreeDS(P, Var, Dummy, Dummy); } \
+  else if (FLAG_PACK(Flag[(Num-1)])) { Packed_DS *Packed = PackDS(P, Dbase, Type, Var); FREE(Packed); } \
+}
+
+#define Call_CopyPut_TABLE(Dbase, Key, Num, Table, Type, Var, D, Count, DataType) \
+{ \
+  Type *Ptr = UseDSalloc(P, Dbase, Type, Var, Offset, \
+                         (DoAlloc || P->Var.nalloc < P->Nalloc) ? P->Nalloc : 0); \
+  int Dlen = P->Var.dlen; \
+  if (P->Var.d + Offset != Ptr || !Ptr || P->Var.nalloc < Count) { \
+    fprintf(stderr,\
+    "***Error in CopyPut_TABLE(%s, col#%d, @%s, d=%p, LdimD=%d, var=%s, Ptr=%p," \
+    " Var.d+%d=%p, nalloc=%d, Count=%d, type=(%d,%s))\n", \
+    #Dbase, Num, #Table, D, LdimD, P->Var.name, Ptr, Offset, P->Var.d + Offset, P->Var.nalloc, \
+    Count, DataType, #Type); RAISE(SIGABRT); \
+  } \
+  (void) ODBCopyPutTable(Flag[(Num-1)], Count, Ptr, &D[(Num-1)*LdimD], DataType); \
+  P->Var.dlen = Dlen + Count; \
+  if (FLAG_PACK(Flag[(Num-1)])) { Packed_DS *Packed = PackDS(P, Dbase, Type, Var); FREE(Packed); } \
+}
+
+/* Gather/Scatter for Get/Put View */
+
+#define ODBMAC_TRACE_GATHERGET(Dbase, View, Table, Var, K1, K2, Num) \
+    if (do_trace) { \
+      ODB_Trace TracE; \
+      TracE.handle = P->Handle; \
+      TracE.msg = "Fetching '" #Var "@" #Table "' in view '" #View "'"; \
+      TracE.msglen = strlen(TracE.msg); \
+      TracE.args[0] = P->Funcs->pool->poolno; \
+      TracE.args[1] = Num; \
+      TracE.args[2] = K1; \
+      TracE.args[3] = K2; \
+      TracE.args[4] = LdimD; \
+      TracE.args[5] = ncount; \
+      TracE.args[6] = out_of_range; \
+      TracE.args[7] = use_index; \
+      TracE.args[8] = row_offset; \
+      TracE.numargs = 9; \
+      TracE.mode = -1; \
+      codb_trace_(&TracE.handle, &TracE.mode, \
+                  TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+    } \
+    if (P->T_##Table->Var.d != Ptr || !Ptr || out_of_range > 0) { \
+      fprintf(stderr,\
+      "***Error in GatherGet_VIEW(%s, col#%d, %s, d=%p, LdimD=%d, var=%s@%s, Ptr=%p, " \
+      "Var.d=%p, Var.dlen=%d, ncount=%d, low=%d, high=%d, out_of_range=%d, use_index=%d, row_offset=%d)\n", \
+      #Dbase, Num, #View, D, LdimD, #Var, #Table, Ptr, \
+      P->T_##Table->Var.d, P->T_##Table->Var.dlen, ncount, \
+      low, high, out_of_range, use_index, row_offset); \
+      RAISE(SIGABRT); \
+    }
+
+#define USE_INDEX(P,Var) (row_offset == 0 && P && P->IO_method == 5 && !Var.d && !Var.pd) ? 1 : 0
+
+#define Call_GatherGet_VIEW(Dbase, Key, Num, View, Type, K1, K2, Table, D, Var, DataType, pos, len) { \
+ if (Num <= Ncols && FLAG_FETCH(Flag[(Num-1)])) { \
+    boolean use_index = USE_INDEX(P->T_##Table,P->T_##Table->Var); \
+    /* boolean use_index = 0; activate this line if the line above is shocking! */ \
+    int *idxaddr = &P->Index_##Table[K1]; \
+    int ncount = K2 - K1; \
+    Type *Ptr = UseDSindex(P->T_##Table, Dbase, Type, Var, \
+                           use_index ? idxaddr : NULL, ncount); \
+    int low = 0; \
+    int high = P->T_##Table->Var.dlen - 1; \
+    int out_of_range = 0; \
+    if (!use_index) codb_test_index_range_(idxaddr, &ncount, &low, &high, &out_of_range); \
+    ODBMAC_TRACE_GATHERGET(Dbase, View, Table, Var, K1, K2, Num); \
+    if (!use_index) { \
+      ODBGatherGetBits(K1, K2, P->Index_##Table, &D[(Num-1)*LdimD], Ptr, DataType, pos, len, row_offset); \
+    } \
+    else { /* Data already gathered (via previously used index --> use_index == 1) into consecutive locations */ \
+      ODBGatherGetBits(K1, K2, NULL, &D[(Num-1)*LdimD], Ptr, DataType, pos, len, row_offset); \
+      { int Dummy=0; FreeDS(P->T_##Table, Var, Dummy, Dummy); } \
+    } \
+ } \
+ if (FLAG_FREE(Flag[(Num-1)])) { int Dummy=0; FreeDS(P->T_##Table, Var, Dummy, Dummy); } \
+ else if (FLAG_PACK(Flag[(Num-1)])) { Packed_DS *Packed = PackDS(P->T_##Table, Dbase, Type, Var); FREE(Packed); } \
+}
+
+#define ODBMAC_TRACE_SCATTERPUT(Dbase, View, Table, Var, K1, K2, Num) \
+    if (do_trace) { \
+      ODB_Trace TracE; \
+      TracE.handle = P->Handle; \
+      TracE.msg = "Updating '" #Var "@" #Table "' in view '" #View "'"; \
+      TracE.msglen = strlen(TracE.msg); \
+      TracE.args[0] = P->Funcs->pool->poolno; \
+      TracE.args[1] = Num; \
+      TracE.args[2] = K1; \
+      TracE.args[3] = K2; \
+      TracE.args[4] = LdimD; \
+      TracE.args[5] = ncount; \
+      TracE.args[6] = out_of_range; \
+      TracE.numargs = 7; \
+      TracE.mode = -1; \
+      codb_trace_(&TracE.handle, &TracE.mode, \
+                  TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+    } \
+    if (P->T_##Table->Var.d != Ptr || !Ptr || out_of_range > 0) { \
+      fprintf(stderr,\
+      "***Error in ScatterPut_VIEW(%s, col#%d, %s, d=%p, LdimD=%d, var=%s@%s, Ptr=%p, " \
+      "Var.d=%p, Var.dlen=%d, ncount=%d, low=%d, high=%d, out_of_range=%d)\n", \
+      #Dbase, Num, #View, D, LdimD, #Var, #Table, Ptr, \
+      P->T_##Table->Var.d, P->T_##Table->Var.dlen, ncount, \
+      low, high, out_of_range); \
+      RAISE(SIGABRT); \
+    }
+
+#define Call_ScatterPut_VIEW(Dbase, Key, Num, View, Type, K1, K2, Table, Var, D, DataType, pos, len) { \
+ if (Num <= Ncols && FLAG_UPDATE(Flag[(Num-1)]) && (ODBIT_test(P->can_UPDATE, Ncols, MAXBITS, Num-1, Num-1) == 1)) { \
+    Type *Ptr = UseDSlong(P->T_##Table, Dbase, Type, P->T_##Table->Var); \
+    int *idxaddr = &P->Index_##Table[K1]; \
+    int ncount = K2 - K1; \
+    int low = 0; \
+    int high = P->T_##Table->Var.dlen - 1; \
+    int out_of_range = 0; \
+    codb_test_index_range_(idxaddr, &ncount, &low, &high, &out_of_range); \
+    ODBMAC_TRACE_SCATTERPUT(Dbase, View, Table, Var, K1, K2, Num); \
+    ODBScatterPutBits(K1, K2, P->Index_##Table, Ptr, &D[(Num-1)*LdimD], DataType, pos, len); \
+ } \
+ if (FLAG_PACK(Flag[(Num-1)])) { Packed_DS *Packed = PackDS(P->T_##Table, Dbase, Type, Var); FREE(Packed); } \
+}
+
+/* Macros for Load/Store tables */
+
+#define Call_TABLE_Load(xname, pf, inc_pf) \
+{ \
+   int bytes = pf->common->is_considered ? pf->common->load(pf->data) : 0; \
+   if (bytes < 0) { \
+     fprintf(stderr,"***Error: Unable to load table '%s' (expected table '%s'): bytes=%d\n", \
+             pf->common->name, #xname, bytes); \
+     RAISE(SIGABRT); return bytes; \
+   } \
+   Nbytes += bytes; \
+   if (inc_pf) pf = pf->next; \
+}
+
+#define Call_TABLE_Store(xname, pf, inc_pf) \
+{ \
+   int bytes = (pf->common->is_considered && pf->common->store) ? pf->common->store(pf->data) : 0; \
+   if (bytes < 0) { \
+     fprintf(stderr,"***Error: Unable to store table '%s' (expected table '%s') : bytes=%d\n", \
+             pf->common->name, #xname, bytes); \
+     RAISE(SIGABRT); return bytes; \
+   } \
+   Nbytes += bytes; \
+   if (inc_pf) pf = pf->next; \
+}
+
+/* DS I/O */
+
+#define Call_Read_DS(Dbase, fp_idx, filename, Nbytes, Type, DataType, Var)  \
+{ \
+  Nbytes += Read_DS(&P->Var, \
+		    P->Handle, P->PoolNo, P->Nrows, P->Byteswap, P->IO_method, \
+		    #Dbase, fp_idx, filename, \
+	            DataType); \
+}
+
+#define Call_Write_DS(Dbase, fp_idx, filename, Nbytes, Type, DataType, Var)  \
+{ \
+  Nbytes += Write_DS(&P->Var, \
+		     P->Handle, P->PoolNo, P->Nrows, P->Byteswap, P->IO_method, \
+		     #Dbase, fp_idx, filename, \
+	             DataType, \
+                     (Packed_DS *(*)(void *))Dbase##_DoPackDS_##Type); /* a nice type-castink! */ \
+}
+
+#ifndef ODB_MAINCODE
+#define DS_DummyPacks(Dbase, FType, Type) \
+extern Type *Dbase##_unpack_##FType(const uint pd[], \
+				    const int pdlen, int *dlen, int *method_used, uint datatype); \
+extern uint *Dbase##_pack_##FType(const Type d[], \
+				  const int dlen, int *method, int *pdlen, Bool avoid_copy);
+#else
+#define DS_DummyPacks(Dbase, FType, Type) \
+PUBLIC Type \
+*Dbase##_unpack_##FType(const uint pd[], \
+   		        const int pdlen, int *dlen, int *method_used, uint datatype) \
+{ \
+  *dlen = -1; \
+  fprintf(stderr,\
+          "***Error: Shouldn't be calling this unpacking-function %s_unpack_%s() : method=%d\n", \
+          #Dbase, #FType, *method_used); \
+  RAISE(SIGABRT); \
+  return NULL; \
+} \
+PUBLIC uint \
+*Dbase##_pack_##FType(const Type d[], \
+		      const int dlen, int *method, int *pdlen, Bool avoid_copy) \
+{ \
+  *pdlen = -1; \
+  fprintf(stderr,\
+          "***Error: Shouldn't be calling this packing-function for %s_pack_%s() : method=%d\n", \
+          #Dbase, #FType, *method); \
+  RAISE(SIGABRT); \
+  return NULL; \
+}
+#endif
+
+#ifndef ODB_MAINCODE
+#define DS_Unpacking(Dbase, FType, Type) \
+extern Type *Dbase##_DoUnpackDS_##Type(DeclareDS(Type, *Pvar), int Offset, int AllocMore);\
+extern Type Dbase##_DoUnpackValueDS_##Type(DeclareDS(Type, *Pvar), int Offset, int Nalloc);
+#else
+#define DS_Unpacking(Dbase, FType, Type) \
+PUBLIC Type *Dbase##_DoUnpackDS_##Type(DeclareDS(Type, *Pvar), int Offset, int AllocMore) \
+{ \
+ Type *Ptr = NULL; \
+ coml_set_lockid_(&ODB_global_mylock[0]); \
+ if (Pvar->is_packed || (AllocMore > Pvar->nalloc) || (!Pvar->d && Pvar->dlen == 0)) { \
+  if (Pvar->is_packed) { \
+    Pvar->d = Dbase##_unpack_##FType(Pvar->pd, Pvar->pdlen, \
+                                     &Pvar->dlen, &Pvar->pmethod, Pvar->datatype); \
+    ODB_packing_trace(0, \
+		      Pvar->type, Pvar->name, Pvar->table, \
+		      Pvar->pmethod, Pvar->pmethod_from_datatype, \
+		      Pvar->dlen, Pvar->elemsize, Pvar->pdlen, Pvar->datatype); \
+    if (!Pvar->d || Pvar->dlen < 0) { \
+      fprintf(stderr,\
+              "Unable to unpack '%s:%s@%s' : d=%p dlen=%d x %d, pdlen=%d, method=%d, orig_method=%d\n", \
+              Pvar->type, Pvar->name, Pvar->table, Pvar->d, \
+	      Pvar->dlen, Pvar->elemsize, Pvar->pdlen, \
+	      Pvar->pmethod, Pvar->pmethod_from_datatype); \
+      RAISE(SIGABRT); \
+      return NULL; /* Error */ \
+    } \
+    FREE_pkdata(*Pvar); \
+    Pvar->nalloc = Pvar->dlen; /* Guaranteed allocation */ \
+  } \
+  if (AllocMore > Pvar->nalloc) { \
+    ALLOCMORE(Pvar->type, Pvar->name, Pvar->table, Pvar->d, Pvar->nalloc, AllocMore); \
+    Pvar->nalloc = AllocMore; \
+  } \
+  /* Allocate at least one element (but keep dlen == 0) */ \
+  if (!Pvar->d && Pvar->dlen == 0) { \
+    Pvar->nalloc = 1; CALLOC(Pvar->d,Pvar->nalloc); \
+  } \
+ } \
+ if (Pvar->d && (Offset == 0 || (Offset > 0 && Offset < Pvar->nalloc))) { \
+   Type *base_addr = Pvar->d; \
+   Ptr = &base_addr[Offset]; \
+ } \
+ else { \
+   fprintf(stderr, \
+   "***Error: Cannot deliver pointer to '%s:%s@%s' at Offset=%d : Conflicting d=%p and/or dlen=%d, nalloc=%d, allocmore=%d\n", \
+           Pvar->type, Pvar->name, Pvar->table, Offset, Pvar->d, Pvar->dlen, Pvar->nalloc, AllocMore); \
+   RAISE(SIGABRT); \
+ } \
+ coml_unset_lockid_(&ODB_global_mylock[0]); \
+ return Ptr; \
+} \
+PUBLIC Type Dbase##_DoUnpackValueDS_##Type(DeclareDS(Type, *Pvar), int Offset, int Nalloc) \
+{ \
+  Type *P = Dbase##_DoUnpackDS_##Type(Pvar, Offset, Nalloc); \
+  if (!P) { \
+    fprintf(stderr, \
+    "***Error: Unable to get data pointer in %s_DoUnpackValueDS_%s ; Offset=%d, Nalloc=%d\n", \
+            #Dbase, #Type, Offset, Nalloc); \
+            RAISE(SIGABRT); \
+  } \
+  return *P; \
+}
+#endif
+
+#ifndef ODB_MAINCODE
+#define DS_Packing(Dbase, FType, Type) \
+extern Packed_DS *Dbase##_DoPackDS_##Type(DeclareDS(Type, *Pvar));
+#else
+#define DS_Packing(Dbase, FType, Type) \
+PUBLIC Packed_DS *Dbase##_DoPackDS_##Type(DeclareDS(Type, *Pvar)) \
+{ \
+ Packed_DS *PDS; \
+ ALLOC(PDS,1); \
+ coml_set_lockid_(&ODB_global_mylock[1]); { \
+  int pmethod_from_datatype_override = ODB_packing(&Pvar->pmethod_from_datatype); \
+  uint *pd = NULL; \
+  int pdlen = 0; \
+  double bytes_in = 0, bytes_out = 0; \
+  double CMAbytes_in = Pvar->dlen * sizeof(double); \
+  PDS->on_error = 0; \
+  if (Pvar->pmethod != pmethod_from_datatype_override) { \
+    int enforce_packing = (ODB_packing(NULL) == -1) ? 1 : 0; \
+    if (enforce_packing > 0) { \
+      /* Enforce packing with the original packing method */ \
+      /* May even require unpacking of a column to achieve desired effect */ \
+      /* Warning: The following may break the IO_method == 5 (DCA-fetched) */ \
+      Type *d = UseDS_no_hassle(Dbase, Type, *Pvar); /* Now unpacked */ \
+      int packing_method_was = Pvar->pmethod; /* Record the packing method used */ \
+      /* Set packing method back to the original, derived from datatype (unless overridden) */ \
+      Pvar->pmethod = pmethod_from_datatype_override; \
+      Pvar->pd = pd = Dbase##_pack_##FType(d, Pvar->dlen, &Pvar->pmethod, &pdlen, false); /* Re-pack */ \
+      ODB_packing_trace(2, \
+			Pvar->type, Pvar->name, Pvar->table, \
+			packing_method_was, pmethod_from_datatype_override, \
+			Pvar->dlen, Pvar->elemsize, pdlen, Pvar->datatype); \
+      if (!pd || pdlen < 0) { PDS->on_error = 1; \
+        fprintf(stderr,"***Error in enforcing packing\n"); RAISE(SIGABRT); return PDS; /* Error */ } \
+      Pvar->pdlen = pdlen; \
+      Pvar->is_packed = 1; \
+      FREE_data(*Pvar); \
+    } \
+  } \
+  Here_##Type: \
+  if (Pvar->pmethod > 0) { \
+    if (!Pvar->is_packed) { \
+      if (Pvar->dlen > 0) { \
+        int prtmsg, threshold; \
+        double factor; \
+        ODB_packing_setup(&prtmsg, &threshold, &factor); \
+        Pvar->pd = pd = Dbase##_pack_##FType(Pvar->d, Pvar->dlen, &Pvar->pmethod, &pdlen, false); \
+        ODB_packing_trace(1, \
+	  		  Pvar->type, Pvar->name, Pvar->table, \
+		  	  Pvar->pmethod, Pvar->pmethod_from_datatype, \
+			  Pvar->dlen, Pvar->elemsize, pdlen, Pvar->datatype); \
+        if (!pd || pdlen < 0) { PDS->on_error = 1; \
+          fprintf(stderr,"***Error in packing\n"); RAISE(SIGABRT); return PDS; /* Error */ } \
+        /* Turn packing off on the fly */ \
+        bytes_in = BYTESIZE(Pvar->d); \
+        bytes_out = BYTESIZE(pd); \
+        if ( \
+            ((bytes_in > threshold && bytes_out > bytes_in) || (bytes_out > factor*bytes_in))) { \
+          if (prtmsg) { \
+	    fprintf(stderr, \
+	    "***Warning: Packed object (%.0f bytes) LARGER than unpacked (%.0f) : var='%s@%s'\n", \
+	    bytes_out, bytes_in, Pvar->name, Pvar->table); \
+	    fprintf(stderr, \
+	    "            Due to exceeded thresholds (%d, %f) packing is now switched off\n", \
+	    threshold, factor); \
+	  } \
+	  FREE_pkdata(*Pvar); \
+	  Pvar->pmethod = 0; \
+	  goto Here_##Type; \
+        } \
+      } \
+      else { /* Pvar->dlen == 0 */ \
+        FREE_pkdata(*Pvar); \
+        Pvar->pmethod = 0; \
+	goto Here_##Type; \
+      } \
+      FREE_data(*Pvar); \
+      Pvar->is_packed = 1; \
+    } \
+    else { \
+      pd = Pvar->pd; \
+      pdlen = Pvar->pdlen; \
+    } \
+    PDS->pd = Pvar->pd = pd; \
+    PDS->pdlen = Pvar->pdlen = pdlen; \
+    PDS->opaque = NULL; \
+    PDS->nbytes = 0; \
+    bytes_in = BYTESIZE(Pvar->d); \
+    bytes_out = BYTESIZE(Pvar->pd); \
+  } \
+  else { /* (Pvar->pmethod == 0) */ \
+    PDS->pd = NULL; \
+    PDS->pdlen = 0; \
+    PDS->opaque = Pvar->d; \
+    PDS->nbytes = BYTESIZE(Pvar->d); \
+    bytes_out = PDS->nbytes; \
+  } \
+ } coml_unset_lockid_(&ODB_global_mylock[1]); \
+ return PDS; \
+}
+#endif
+
+#define PackDS(P, Dbase, Type, Var) \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+     P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       NULL, 0, &P->Var.dlen, NULL, NULL, NULL) : NULL, \
+  Dbase##_DoPackDS_##Type(&P->Var) )
+
+#define UseDS_no_hassle(Dbase, Type, Var)               Dbase##_DoUnpackDS_##Type(&Var, 0, 0) 
+#define UseDS(P, Dbase, Type, Var)                      \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+    (P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       NULL, 0, &P->Var.dlen, NULL, NULL, NULL), \
+     P->Var.nalloc = P->Var.dlen, P->Var.pd ? \
+     (free(P->Var.pd), P->Var.d = NULL) : NULL, P->Var.pdlen = 0, P->Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackDS_##Type(&P->Var, 0, 0) )
+#define UseDSlong(P, Dbase, Type, Var)                      \
+( (P && P->IO_method == 5 && !Var.d && !Var.pd) ? \
+    (Var.d = DCA_fetch(P->Handle, #Dbase, Var.table, Var.name, P->PoolNo, 1, \
+                       NULL, 0, &Var.dlen, NULL, NULL, NULL), \
+     Var.nalloc = Var.dlen, Var.pd ? \
+     (free(Var.pd), Var.d = NULL) : NULL, Var.pdlen = 0, Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackDS_##Type(&Var, 0, 0) )
+#define UseDSindex(P, Dbase, Type, Var, Index, lenIndex)          \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+    (P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       Index, lenIndex, &P->Var.dlen, NULL, NULL, NULL), \
+     P->Var.nalloc = P->Var.dlen, P->Var.pd ? \
+     (free(P->Var.pd), P->Var.d = NULL) : NULL, P->Var.pdlen = 0, P->Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackDS_##Type(&P->Var, 0, 0) )
+#define UseDSo(P, Dbase, Type, Var, Offset)             \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+    (P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       NULL, 0, &P->Var.dlen, NULL, NULL, NULL), \
+     P->Var.nalloc = P->Var.dlen, P->Var.pd ? \
+     (free(P->Var.pd), P->Var.d = NULL) : NULL, P->Var.pdlen = 0, P->Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackDS_##Type(&P->Var, Offset, 0) )
+#define UseDSoVal(P, Dbase, Type, Var, Offset)          \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+    (P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       NULL, 0, &P->Var.dlen, NULL, NULL, NULL), \
+     P->Var.nalloc = P->Var.dlen, P->Var.pd ? \
+     (free(P->Var.pd), P->Var.d = NULL) : NULL, P->Var.pdlen = 0, P->Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackValueDS_##Type(&P->Var, Offset, 0) )
+#define UseDSalloc(P, Dbase, Type, Var, Offset, Nalloc) \
+( (P && P->IO_method == 5 && !P->Var.d && !P->Var.pd) ? \
+    (P->Var.d = DCA_fetch(P->Handle, #Dbase, P->Var.table, P->Var.name, P->PoolNo, 1, \
+                       NULL, 0, &P->Var.dlen, NULL, NULL, NULL), \
+     P->Var.nalloc = P->Var.dlen, P->Var.pd ? \
+     (free(P->Var.pd), P->Var.d = NULL) : NULL, P->Var.pdlen = 0, P->Var.is_packed = 0) : 0, \
+  Dbase##_DoUnpackDS_##Type(&P->Var, Offset, Nalloc) )
+
+/* #define UseDSoDirect(Var, Offset)                    (Var[Offset]) */
+
+#if !defined(ODB_MAINCODE) && !defined(IS_a_VIEW)
+#define InitDS(Type, DataType, Var, Table, PMethod) { \
+  const int packing_method = PMethod; \
+  { static char s[] = #Type; P->Var.type = s; } \
+  { static char s[] = #Var; P->Var.name = s; } \
+  { static char s[] = "/" #Var "/"; P->Var.xname = s; } \
+  { static char s[] = #Table; P->Var.table = s; } \
+  P->Var.datatype = DataType; /* Overwritten when unpacking/reading in a column */ \
+  P->Var.elemsize = sizeof(Type); \
+  P->Var.d = NULL; \
+  P->Var.pd = NULL; \
+  P->Var.dlen = 0; \
+  P->Var.nalloc = 0; \
+  P->Var.pdlen = 0; \
+  P->Var.pmethod = (ODB_packing(NULL) == 0) ? 0 : ODB_packing(&packing_method); \
+  P->Var.pmethod_from_datatype = packing_method; \
+  P->Var.is_packed = 0; \
+  P->Var.savelist = ODB_savelist(ODB_LABEL,#Var "@" #Table); \
+  P->Var.saved_data = NULL; \
+  P->Var.saved_data_nbytes = 0; \
+  P->Var.saved_data_N[0] = 0; \
+  P->Var.saved_data_N[1] = 0; \
+}
+
+#define PreInitTable(P, nc) { \
+  P->Handle = -1; \
+  P->PoolNo = PoolNo; \
+  P->Funcs = NULL; \
+  P->Is_loaded = 0; \
+  P->Is_new = Is_new; \
+  P->Swapped_out = 0; \
+  P->Byteswap = 0; \
+  P->IO_method = IO_method; \
+  P->Created[0] = 0; \
+  P->Created[1] = 0; \
+  P->LastUpdated[0] = 0; \
+  P->LastUpdated[1] = 0; \
+  P->Ncols = nc; \
+  P->Nrows = 0; \
+  P->Nalloc = 0; \
+  P->Numreqs = 0; \
+}
+
+#define Call_LookupTable(Table, T, Nrows, Ncols) \
+  (void) Lookup_T_##Table(T, Nrows, Ncols)
+
+#define DefineLookupTable(Table) \
+PRIVATE int \
+Lookup_T_##Table(void *T, int *Nrows, int *Ncols) \
+{ \
+  TABLE_##Table *P = T; \
+  int PoolNo = P->PoolNo; \
+  int Handle = P->Handle; \
+  if (Nrows) *Nrows = 0; \
+  if (Ncols) *Ncols = 0; \
+  if (!P->Is_loaded && P->IO_method == 5) { \
+    if (!DCA_getsize(Handle, ODB_LABEL, #Table, PoolNo, &P->Nrows, &P->Ncols)) { \
+      int iret; \
+      (void) DCA_alloc(Handle, ODB_LABEL, #Table, &iret); \
+      (void) DCA_getsize(Handle, ODB_LABEL, #Table, PoolNo, &P->Nrows, &P->Ncols); \
+    } \
+    if (Nrows) *Nrows = P->Nrows; \
+    P->Is_loaded = 1; \
+  } \
+  else if (Nrows && !P->Is_new && !P->Is_loaded && P->IO_method != 5) { \
+    /* Can lookup only saved data */ \
+    int rc, Nbytes = 0; \
+    int close_too = 1; \
+    int lookup_only = 1; \
+    int fp_idx; \
+    int swp; \
+    uint Magic, Ninfo[2]; \
+    const int two = 2; \
+    char *filename = NULL; \
+    /* ODB_Pool *Pool = P->Funcs->pool; */ \
+    ODB_check_considereness(P->Funcs->common->is_considered, #Table); \
+    MakeFileName(filename, ODB_LABEL, #Table, PoolNo); \
+    /* fprintf(stderr,"Looking up TABLE %s from file %s ...\n",#Table, filename); */ \
+    Nbytes = newio_Open32(&fp_idx, filename, ODB_LABEL, #Table, "lookup:open/read", \
+                          "(lookup:open)", Handle, PoolNo, \
+			  "r", close_too, lookup_only, Ninfo, 2); \
+    swp = (Ninfo[0] == _BDO); \
+    if (swp) { \
+      swap4bytes_(Ninfo, &two); \
+      newio_SetByteswap(&fp_idx, 1, Handle, PoolNo); \
+    } \
+    P->Byteswap = swp; \
+    Magic = Ninfo[0]; \
+    if (Magic != ODB_) { \
+      fprintf(stderr,\
+              "***Error: Invalid MAGIC-word: Database file '%s' is not ODB's\n",filename); \
+      return -2; /* Error */ \
+    } \
+    if (Nrows) *Nrows = Ninfo[1]; \
+    FREEX(filename); \
+  } \
+  else { \
+    if (Nrows) *Nrows = P->Nrows; \
+  } \
+  if (Ncols) *Ncols = P->Ncols; \
+  return 0; \
+}
+
+#define PreLoadTable(Dbase, Table) \
+PUBLIC int \
+Dbase##_Load_T_##Table(void *T) \
+{ \
+ int Nbytes = 0; \
+ TABLE_##Table *P = T; \
+ int PoolNo = P->PoolNo; \
+ int Handle = P->Handle; \
+ coml_set_lockid_(&ODB_global_mylock[2]); \
+ if (!P->Is_loaded && P->IO_method == 5) { \
+   if (!DCA_getsize(Handle, ODB_LABEL, #Table, PoolNo, &P->Nrows, &P->Ncols)) { \
+     int iret; \
+     (void) DCA_alloc(Handle, ODB_LABEL, #Table, &iret); \
+     (void) DCA_getsize(Handle, ODB_LABEL, #Table, PoolNo, &P->Nrows, &P->Ncols); \
+   } \
+   P->Is_loaded = 1; \
+ } \
+ else if (!P->Is_loaded) { \
+  int rc; \
+  int fp_idx; \
+  char *filename = NULL; \
+  int Nrows=0, Ncols=0; \
+  uint Magic, Ninfo[INFOLEN]; \
+  int swp; \
+  const int infolen = INFOLEN; \
+  if (!P->Is_new && !P->Is_loaded) { /* Can only read saved data */ \
+    int close_too = 0; \
+    int lookup_only = 0; \
+    FILE *do_trace = ODB_trace_fp(); \
+    ODB_Pool *Pool = P->Funcs->pool; \
+    ODB_check_considereness(P->Funcs->common->is_considered, #Table); \
+    MakeFileName(filename, ODB_LABEL, #Table, PoolNo); \
+    if (do_trace) { \
+      ODB_Trace TracE; \
+      TracE.handle = Handle; \
+      TracE.msg = "Loading TABLE " #Table; \
+      TracE.msglen = strlen(TracE.msg); \
+      TracE.args[0] = PoolNo; \
+      TracE.numargs = 1; \
+      TracE.mode = 1; \
+      codb_trace_(&TracE.handle, &TracE.mode, \
+                  TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+    } \
+    if (P->Swapped_out) { \
+      (void) P->Funcs->common->init(P, Pool, P->Is_new, P->IO_method, 0, 1); \
+      P->Swapped_out = 0; \
+      P->Byteswap = 0; \
+    } \
+    Nbytes = newio_Open32(&fp_idx, filename, ODB_LABEL, #Table, "load:open/read", \
+                          "(load:open)", Handle, PoolNo, \
+			  "r", close_too, lookup_only, Ninfo, infolen); \
+    swp = (Ninfo[0] == _BDO); \
+    if (swp) { \
+      swap4bytes_(Ninfo, &infolen); \
+      newio_SetByteswap(&fp_idx, 1, Handle, PoolNo); \
+    } \
+    P->Byteswap = swp; \
+    Magic = Ninfo[0]; \
+    if (Magic != ODB_) \
+      { fprintf(stderr,\
+        "***Error: Magic != ODB_; Magic=%u, ODB_=%u\n",Magic,ODB_); \
+        RAISE(SIGABRT); return -2; /* Error */ } \
+    Nrows = Ninfo[1]; \
+    if (Ninfo[2] == 0) Ninfo[2] = P->Ncols; \
+    Ncols = Ninfo[2]; \
+    if (Ncols > 0 && Ncols != P->Ncols) \
+      { fprintf(stderr,\
+                "***Error: Ncols != P->Ncols; Ncols=%d, P->Ncols=%d\n",Ncols,P->Ncols); \
+        RAISE(SIGABRT); return -3; /* Error */ } \
+    P->Created[0] = Ninfo[3]; \
+    P->Created[1] = Ninfo[4]; \
+    P->LastUpdated[0] = Ninfo[5]; \
+    P->LastUpdated[1] = Ninfo[6]; \
+    if (P->Nalloc < Nrows || Nrows == 0) { \
+      int min_alloc = ODB_min_alloc(); \
+      int inc_alloc; \
+      P->Nalloc = RNDUP(Nrows, min_alloc); \
+      inc_alloc = ODB_inc_alloc(P->Nalloc, min_alloc); \
+      P->Nalloc = P->Nalloc + inc_alloc; \
+    } \
+    P->Nrows = Nrows
+
+#define PostLoadTable(Table) \
+    if (Nbytes > 0) { rc = newio_Close32(&fp_idx, filename, ODB_LABEL, #Table, "load:close", \
+					 "(load:close)", P->Handle, P->PoolNo, Ninfo, INFOLEN \
+					 ); \
+		    } \
+    FREEX(filename); \
+    P->Is_loaded = 1; \
+    if (do_trace) { \
+      ODB_Trace TracE; \
+      TracE.handle = P->Handle; \
+      TracE.msg = "TABLE " #Table " loaded"; \
+      TracE.msglen = strlen(TracE.msg); \
+      TracE.args[0] = PoolNo; \
+      TracE.args[1] = Nrows; \
+      TracE.args[2] = Ncols; \
+      TracE.args[3] = P->Nalloc; \
+      TracE.args[4] = Nbytes; \
+      TracE.numargs = 5; \
+      TracE.mode = 0; \
+      codb_trace_(&TracE.handle, &TracE.mode, \
+                  TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+    } \
+  } /* if (!P->Is_new && !P->Is_loaded) */ \
+ } /* if (!P->Is_loaded) */ \
+ coml_unset_lockid_(&ODB_global_mylock[2]); \
+ return Nbytes; \
+}
+
+#define PreStoreTable(Dbase, Table) \
+PUBLIC int \
+Dbase##_Store_T_##Table(void *T) \
+{ \
+ int Nbytes = 0; \
+ TABLE_##Table *P = T; \
+ coml_set_lockid_(&ODB_global_mylock[3]); \
+ if (P->Is_loaded && P->IO_method != 5) { \
+  int rc; \
+  int PoolNo = P->PoolNo; \
+  int Handle = P->Handle; \
+  int fp_idx; \
+  char *filename = NULL; \
+  char *table = #Table; \
+  int Nrows=0, Ncols=0; \
+  uint Ninfo[INFOLEN]; \
+  int close_too = 0; \
+  int lookup_only = 0; \
+  FILE *do_trace = ODB_trace_fp(); \
+  if (P->Swapped_out) goto return_Nbytes; \
+  MakeFileName(filename, ODB_LABEL, table, PoolNo); \
+  if (!P->Is_new && !P->Is_loaded) { \
+    int size = P->Funcs->common->is_considered ? \
+        newio_Size32(filename, ODB_LABEL, table, Handle, PoolNo) : 0; \
+    if (size >= 0) { FREEX(filename); goto return_Nbytes; /* Is indeed created => return */ } \
+  } \
+  if (do_trace) { \
+    ODB_Trace TracE; \
+    TracE.handle = Handle; \
+    TracE.msg = "Storing TABLE " #Table; \
+    TracE.msglen = strlen(TracE.msg); \
+    TracE.args[0] = PoolNo; \
+    TracE.numargs = 1; \
+    TracE.mode = 1; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+                TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  } \
+  if (P->Created[0] == 0 && P->Created[1] == 0) { \
+    codb_datetime_(&P->Created[0], &P->Created[1]); \
+    P->LastUpdated[0] = P->Created[0]; \
+    P->LastUpdated[1] = P->Created[1]; \
+  } \
+  else { \
+    codb_datetime_(&P->LastUpdated[0], &P->LastUpdated[1]); \
+  } \
+  Ninfo[0] = ODB_; \
+  Ninfo[1] = Nrows = P->Nrows; \
+  Ninfo[2] = Ncols = P->Ncols; \
+  Ninfo[3] = P->Created[0]; \
+  Ninfo[4] = P->Created[1]; \
+  Ninfo[5] = P->LastUpdated[0]; \
+  Ninfo[6] = P->LastUpdated[1]; \
+  Nbytes = newio_Open32(&fp_idx, filename, ODB_LABEL, table, "store:open/write", \
+		        "(store:open)", Handle, PoolNo, \
+			"w", close_too, lookup_only, Ninfo, INFOLEN);
+
+#define PostStoreTable(Table) \
+  if (Nbytes > 0) { rc = newio_Close32(&fp_idx, filename, ODB_LABEL, table, "store:close", \
+				       "(store:close)", Handle, PoolNo, Ninfo, INFOLEN \
+				       ); \
+		  } \
+  FREEX(filename); \
+  P->Is_new = 0; \
+  if (do_trace) { \
+    ODB_Trace TracE; \
+    TracE.handle = Handle; \
+    TracE.msg = "TABLE " #Table " stored"; \
+    TracE.msglen = strlen(TracE.msg); \
+    TracE.args[0] = PoolNo; \
+    TracE.args[1] = Nrows; \
+    TracE.args[2] = Ncols; \
+    TracE.args[3] = Nbytes; \
+    TracE.numargs = 4; \
+    TracE.mode = 0; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+                TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  } \
+ } /* if (P->Is_loaded && P->IO_method != 5) */ \
+return_Nbytes: \
+ coml_unset_lockid_(&ODB_global_mylock[3]); \
+ return Nbytes; \
+}
+
+#define DefineRemoveTable(Dbase, Table) \
+PUBLIC int \
+Dbase##_Remove_T_##Table(void *T) \
+{ \
+  TABLE_##Table *P = T; \
+  int rc = 0; \
+  int Nbytes = 0; \
+  int PoolNo = P->PoolNo; \
+  FILE *do_trace = ODB_trace_fp(); \
+  if (do_trace) { \
+    ODB_Trace TracE; \
+    TracE.handle = P->Handle; \
+    TracE.msg = "Removing TABLE " #Table; \
+    TracE.msglen = strlen(TracE.msg); \
+    TracE.args[0] = PoolNo; \
+    TracE.numargs = 1; \
+    TracE.mode = 0; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+                TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  } \
+  ODB_check_considereness(P->Funcs->common->is_considered, #Table); \
+  Dbase##_Swapout_T_##Table(P); \
+  P->Is_loaded = 1; \
+  P->Swapped_out = 0; \
+  P->Byteswap = 0; \
+  P->Nrows = 0; \
+  P->Nalloc = 0; \
+  Nbytes = Dbase##_Store_T_##Table(P); \
+  return Nbytes; \
+}
+
+
+#define PreGetTable(Dbase, Key, ExtType, Table) \
+PUBLIC int \
+Dbase##_##Key##Get_T_##Table(void *T, ExtType D[], \
+			 int LdimD, int Nrows, int Ncols, \
+                         int ProcID, const int Flag[], int row_offset) \
+{ \
+  TABLE_##Table *P = T; \
+  int Count; \
+  DRHOOK_START(Dbase##_##Key##Get_T_##Table); \
+  ODBMAC_TABLE_DELAYED_LOAD(Table); \
+  Count = MIN(Nrows, P->Nrows);
+
+#define PostGetTable(Key, ExtType, Table) \
+  DRHOOK_END(Count); \
+  return Count; \
+}
+
+#define PrePutTable(Dbase, Key, ExtType, Table) \
+PUBLIC int \
+Dbase##_##Key##Put_T_##Table(void *T, const ExtType D[], \
+			 int LdimD, int Nrows, int Ncols, \
+                         int ProcID, const int Flag[]) \
+{ \
+  TABLE_##Table *P = T; \
+  int Count = Nrows; \
+  int Offset = P->Nrows; \
+  boolean DoAlloc = 0; \
+  boolean JustLoaded = 0; \
+  DRHOOK_START(Dbase##_##Key##Put_T_##Table); \
+  if (P->Nrows == 0 && (P->Swapped_out || !P->Is_loaded)) { \
+    int Nbytes = 0; \
+    Call_TABLE_Load(Table, P->Funcs, 0); \
+    Offset = P->Nrows; \
+    JustLoaded = P->Funcs->common->is_considered; \
+  } \
+  if (JustLoaded || P->Nalloc < (Offset + Count) || (Offset + Count) == 0) { \
+    int min_alloc = ODB_min_alloc(); \
+    int inc_alloc; \
+    P->Nalloc = RNDUP(Offset + Count, min_alloc); \
+    inc_alloc = ODB_inc_alloc(P->Nalloc, min_alloc); \
+    P->Nalloc = P->Nalloc + inc_alloc; \
+    DoAlloc = 1; \
+  }
+
+#define PostPutTable(Key, ExtType, Table) \
+  P->Is_loaded = P->Funcs->common->is_considered; \
+  P->Swapped_out = 0; \
+  P->Byteswap = 0; \
+  P->Nrows += Count; \
+  DRHOOK_END(Count); \
+  return P->Nrows; \
+}
+
+#endif /*  !defined(ODB_MAINCODE) && !defined(IS_a_VIEW) */
+
+
+#ifdef ODB_MAINCODE
+#define PreGetTable(Dbase, Key, ExtType, Table) \
+extern int Dbase##_##Key##Get_T_##Table(void *T, ExtType D[], \
+			 int LdimD, int Nrows, int Ncols, \
+                         int ProcID, const int Flag[])
+
+#define PrePutTable(Dbase, Key, ExtType, Table) \
+extern int Dbase##_##Key##Put_T_##Table(void *T, const ExtType D[], \
+			 int LdimD, int Nrows, int Ncols, \
+                         int ProcID, const int Flag[])
+
+#define PreLoadTable(Dbase, Table) \
+extern int Dbase##_Load_T_##Table(void *T)
+
+#define PreStoreTable(Dbase, Table) \
+extern int Dbase##_Store_T_##Table(void *T)
+#endif /*  ODB_MAINCODE */
+
+#define ODBMAC_VIEW_TABLEDECL_NO_INDEX(name) \
+  TABLE_##name *T_##name; \
+  unsigned int *BitmapIndex_##name
+
+#define ODBMAC_VIEW_TABLEDECL_WITH_INDEX(name) \
+  ODBMAC_VIEW_TABLEDECL_NO_INDEX(name); \
+  int *Index_##name; \
+  int Allocated_##name
+
+
+#define ODBMAC_CCL_V_PRE(view) \
+  VIEW_##view *P = T; FREE(P->NrowVec); FREE(P->NrowOffset); P->Npes = 0; P->Nrows = 0
+
+#define ODBMAC_LC_GETVAL(dbname, usdname, viewstr) \
+  lc_USD_##usdname = ODB_getval_var(#dbname, "$" #usdname, viewstr, it)
+
+#define ODBMAC_ADDR_TRIGGER(dbname, name, usdname, viewstr) \
+  if (!Addr_trigger && strequ(name, "$" #usdname)) { \
+    ODBMAC_LC_GETVAL(dbname, usdname, viewstr); \
+    Addr_trigger = 1; \
+  }
+
+#define ODBMAC_PEINFO_BREAKLOOP() \
+    if (!Addr && PE > PEstart && P->NrowVec && P->NrowOffset) { \
+      break; /* Break from the PE-loop */ \
+    }
+
+#define ODBMAC_PEINFO_SETUP() \
+  if (PEinfo) { \
+    int Npes = P->Npes = PEinfo->npes; \
+    FREE(P->NrowVec); \
+    FREE(P->NrowOffset); \
+    ALLOC(P->NrowVec, Npes); \
+    ALLOC(P->NrowOffset, Npes); \
+    P->Replicate_PE = PEinfo ? PEinfo->replicate_PE : 0; \
+  }
+
+#define ODBMAC_PEINFO_COPY() \
+  if (PEinfo && P->NrowVec) { \
+    for (PE=PEstart; PE<=PEend; PE++) { \
+      PEinfo->nrowvec[PE-1] += P->NrowVec[PE-1]; \
+    } /* for (PE=PEstart; PE<=PEend; PE++) */ \
+  }
+
+#define ODBMAC_PEINFO_INIT(view) \
+  VIEW_##view *P = V; \
+  if (PEinfo) { \
+    PEinfo->addr = NULL; \
+    PEinfo->varname = NULL; \
+    PEinfo->varname_len = 0; \
+    PEinfo->npes = P->Npes; \
+    PEinfo->nrowvec = P->NrowVec; \
+    PEinfo->replicate_PE = P->Replicate_PE; \
+  }
+
+#define ODBMAC_PEINFO_SELVIEW_SETUP() \
+  FREE(P->NrowVec); FREE(P->NrowOffset); P->Npes = 0; \
+  P->Replicate_PE = PEinfo ? PEinfo->replicate_PE : 0;
+
+#define ODBMAC_PEINFO_OFFSET() \
+  if (ProcID > 0 && ProcID <= Npes && P->NrowVec && P->NrowOffset) \
+  { K1 = P->NrowOffset[ProcID-1]; K2 = K1 + P->NrowVec[ProcID-1]; }
+
+#define ODBMAC_PEINFO_SKIP() \
+  if (!Addr && PE > PEstart && P->NrowVec && P->NrowOffset) { \
+    P->NrowVec[PE-1] = P->NrowVec[PEstart-1]; \
+    P->NrowOffset[PE-1] = P->NrowOffset[PEstart-1]; \
+    continue; /* Skip to the end of the PE-loop */ \
+  }
+
+#define ODBMAC_PEINFO_UPDATE_COUNTS() \
+  if (P->NrowVec && P->NrowOffset) { \
+    P->NrowVec[PE-1] = tmpcount; \
+    P->NrowOffset[PE-1] = Count; \
+  }
+
+#define ODBMAC_TRACE_SWAPOUT(table,Ncols) \
+  if (do_trace) { \
+    ODB_Trace TracE; \
+    TracE.handle = P->Handle; \
+    TracE.msg = "TABLE " #table " swapped out"; \
+    TracE.msglen = strlen(TracE.msg); \
+    TracE.args[0] = PoolNo; \
+    TracE.args[1] = Ncols; /* no. of cols released */ \
+    TracE.args[2] = Count; /* no. of free()'s for data & packed data */ \
+    TracE.args[3] = Nbytes; /* no. of bytes freed */ \
+    TracE.numargs = 4; \
+    TracE.mode = -1; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+      TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_SETUP(view, tables) \
+  FILE *do_trace = ODB_trace_fp(); \
+  ODB_Trace TracE; \
+  static char *MsG[] = { \
+    "Some table(s) {" tables "} maybe loaded on demand for view='" #view "'", \
+    "PrS", \
+    "PoS", \
+    NULL \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_PRE() \
+  if (do_trace) { \
+    TracE.handle = P->Handle; \
+    TracE.numargs = 3; \
+    TracE.args[0] = phase; \
+    TracE.args[1] = P->PoolNo; \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_0() \
+  if (do_trace && Nbytes > 0) { \
+    TracE.msg = MsG[0]; \
+    TracE.msglen = strlen(MsG[0]); \
+    TracE.args[2] = Nbytes; \
+    TracE.mode = -1; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+        TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_1() \
+  if (do_trace) { \
+    TracE.msg = MsG[1]; \
+    TracE.msglen = strlen(MsG[1]); \
+    TracE.args[2] = 0; \
+    TracE.mode = 1; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+        TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_POST() \
+  if (do_trace) { \
+    TracE.args[2] = CountPrS; \
+    TracE.mode = 0; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+        TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_2() \
+  if (do_trace && CountPrS > 0) { \
+    TracE.msg = MsG[2]; \
+    TracE.msglen = strlen(MsG[2]); \
+    TracE.args[2] = 0; \
+    TracE.mode = 1; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+        TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_TRACE_SELVIEW_LAST() \
+  if (do_trace && CountPoS > 0) { \
+    TracE.args[2] = CountPoS; \
+    TracE.mode = 0; \
+    codb_trace_(&TracE.handle, &TracE.mode, \
+        TracE.msg, TracE.args, &TracE.numargs, TracE.msglen); \
+  }
+
+#define ODBMAC_ERRMSG_SELVIEW(view) \
+  if (CountPrS != CountPoS) { \
+    char msg[1024]; \
+    snprintf(msg,sizeof(msg),"CountPrS=%d differs from CountPoS=%d in Sel_V_%s()",CountPrS,CountPoS,#view); \
+    codb_abort_func_(msg,strlen(msg)); \
+  }
+
+#define ODBMAC_TABLESQL() if (sqlout) *sqlout = NULL; return 0
+
+#define ODBMAC_VIEWSQL() \
+  return ODBSQL_PrintGet(Sql, fp, mode, prefix, postfix, sqlout)
+
+#define ODBMAC_SORTKEYS(view) \
+  VIEW_##view *P = V; if (NSortKeys) *NSortKeys = P->NSortKeys; return P->SortKeys
+
+#define ODBMAC_UPDATEINFO(view) \
+  VIEW_##view *P = V; int j, Ncols; \
+  Ncols = MIN(ncols, P->Ncols); \
+  for (j=0; j<Ncols; j++) can_UPDATE[j] = \
+    (ODBIT_test(P->can_UPDATE, Ncols, MAXBITS, j, j) == 1) ? 1 : 0; \
+  return Ncols
+
+#define ODBMAC_AGGRINFO(view) \
+  VIEW_##view *P = V; int j, Ncols = P->Ncols, rc = P->numaggr; \
+  if (aggr_func_flag) { \
+    Ncols = MIN(ncols, P->Ncols); \
+    for (j=0; j<Ncols; j++) aggr_func_flag[j] = P->aggr_func_flag[j]; \
+  } \
+  return rc /* number of columns having aggregate functions */
+
+#define ODBMAC_GETINDEX(table) \
+  if (strequ(Table,#table)) { *Nlen = P->Nrows; return P->Index_##table; }
+
+#define ODBMAC_PUTINDEX(table) \
+  if (strequ(Table,#table)) { \
+    FREEINDEX(table); /* !!! Got possibly rid of an existing good index !!!*/ \
+    if (by_address) { \
+      P->Index_##table = idx; P->Allocated_##table = 0; \
+    } else { int j; \
+      ALLOCINDEX(table, Nidx); \
+      for (j=0; j<Nidx; j++) P->Index_##table[j] = idx[j]; \
+    } \
+    P->Nrows = Nidx; /* !!! Resets Nrows just like that !!! */ \
+    { /* Perform delayed load of this table -- if necessary */ \
+      int Nbytes = 0; \
+      ODBMAC_VIEW_DELAYED_LOAD(table); \
+    } \
+    return Nidx; \
+  }
+
+#define ODBMAC_DIM(view) \
+  VIEW_##view *P = V; \
+  if (Nrows)      { *Nrows = (ProcID > 0 && ProcID <= P->Npes && P->NrowVec) ? P->NrowVec[ProcID-1] : P->Nrows; } \
+  if (Ncols)        *Ncols = P->Ncols; \
+  if (Nrowoffset) { *Nrowoffset = (ProcID > 0 && ProcID <= P->Npes && P->NrowOffset) ? P->NrowOffset[ProcID-1] : 0; }
+
+#define ODBMAC_VIEW_DELAYED_LOAD(xname) \
+  if (!P->T_##xname->Is_loaded) { /* Delayed load */ \
+    ODB_Funcs *pf = P->T_##xname->Funcs; \
+    Call_TABLE_Load(xname, pf, 0); \
+  }
+
+#define ODBMAC_TABLE_DELAYED_LOAD(xname) \
+  if (!P->Is_loaded) { /* Delayed load of existing data */ \
+    int Nbytes = 0; \
+    ODB_Funcs *pf = P->Funcs; \
+    Call_TABLE_Load(xname, pf, 0); \
+  }
+
+#define ODBMAC_ASSIGN_TABLEDATA(tbl) \
+  P->T_##tbl = NULL; \
+  FORFUNC { if (pf->common->is_table && strequ(pf->common->name,"@" #tbl)) { P->T_##tbl = pf->data; break; } }
+
+#define ODBMAC_INIT_IsConsidered(table, id) IsConsidered[id] = TableIsConsidered(#table)
+
+#define ODBMAC_CREATE_TABLE(dbname, table, id, consider_me) \
+  if (io_method != 5 || IsConsidered[id]) { \
+    TABLE_##table *T_##table = dbname##_Init_T_##table(NULL, pool, is_new, io_method, it, 0); \
+    ODB_Funcs *pf = T_##table->Funcs; nfuncs = ODB_add_funcs(pool, pf, it); \
+    pf->common->is_considered = consider_me; \
+  }
+
+#define ODBMAC_COPY_COLAUX(name) \
+if (colaux) { \
+  int j, n = MIN(ColAux_len,colaux_len); \
+  for (j=0; j<n; j++) colaux[j] = ColAux[j]; \
+  filled = n; \
+}
+
+#endif /* ODB_GENCODE */
+
+#endif
diff --git a/odb/src/include/odbcrc.h b/odb/src/include/odbcrc.h
new file mode 100644
index 0000000..e259bec
--- /dev/null
+++ b/odb/src/include/odbcrc.h
@@ -0,0 +1,24 @@
+/* odbcrc.h */
+
+extern unsigned int
+ODB_pp_cksum32(int nbuf, unsigned int nCRC);
+
+extern unsigned int
+ODB_pp_cksum32but64len(long long int nbuf, unsigned int nCRC);
+
+extern unsigned long long int
+ODB_pp_cksum64(long long int nbuf, unsigned long long int nCRC);
+
+extern unsigned int
+ODB_cksum32(const char *buf, int nbuf, unsigned int nCRC);
+
+extern unsigned long long int
+ODB_cksum64(const char *buf, long long int nbuf, unsigned long long int nCRC);
+
+extern void
+fodb_crc32_(const void *vbuf, const int *pnbuf,
+	    unsigned int *pnCRC /* Note: An in & out -variable */);
+
+extern void
+fodb_crc64_(const void *vbuf, const long long int *pnbuf,
+	    unsigned long long int *pnCRC /* Note: An in & out -variable */);
diff --git a/odb/src/include/odbcs.h b/odb/src/include/odbcs.h
new file mode 100644
index 0000000..8587198
--- /dev/null
+++ b/odb/src/include/odbcs.h
@@ -0,0 +1,151 @@
+#ifndef _ODBCS_H_
+#define _ODBCS_H_
+
+/* odbcs.h */
+
+/* ODB client/server */
+
+/* Based on (late) W.Richard Stevens' & et.al. 
+   "Unix Network Programming", Volume 1, 3rd edition, 2004 */
+
+/* Thanks to Baudouin Raoult (ECMWF) for many constructive ideas */
+
+/* If you definitely don't want ODB client/server to be include, 
+   then specify 
+
+      -DODBCS=0 
+
+   while you compile, since -UODBCS may still pick ODBCS depending on ARCH */
+
+#include "setodbcs.h"
+
+#ifdef ODBCS
+
+#include "odb.h"
+#include "odbi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if !defined(CYGWIN)
+#include <sys/socketvar.h>
+#endif
+
+#include "vparam.h"
+
+#include "odbcstags.h"
+
+#define ODBCS_MAXLINE         4096    /* max text line length */
+#define ODBCS_INET_ADDRSTRLEN   46    /* accomodated IPv6 address (and IPv4 for sure) */
+#define ODBCS_INFO              16    /* max general info array length */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define SA      struct sockaddr
+
+typedef void    Sigfunc(int);   /* for signal handlers */
+
+int odbi_server(int sockfd, int timeout, int verbose);
+
+/* odbcs_signal.c */
+
+void     setup_sig(const char *, const int *, const int *, const int *);
+void     sig_chld(int);
+void     sig_term(int);
+void     sig_int(int);
+void     sig_alrm(int);
+void     sig_alrm_server(int);
+void     sig_ignore(int);
+
+/* odbcs_error.c */
+
+void     err_dump(const char *, ...);
+void     err_msg(const char *, ...);
+void     err_quit(const char *, ...);
+void     err_ret(const char *, ...);
+void     err_sys(const char *, ...);
+
+/* odbcs_wrappers.c */
+
+int      Accept(int, SA *, socklen_t *);
+
+void     Bind(int, const SA *, socklen_t);
+
+void     Close(int);
+void     Connect(int, SA *, socklen_t, const char *, int, int, const char *, int);
+
+void     Fclose(FILE *);
+FILE    *Fdopen(int, const char *);
+char    *Fgets(char *, int, FILE *);
+FILE    *Fopen(const char *, const char *);
+pid_t    Fork(void);
+void     Fputs(const char *, FILE *);
+
+const char *Inet_ntop(int, const void *, char *, size_t);
+void        Inet_pton(int, const char *, void *);
+
+void     Listen(int, int);
+
+ssize_t  Readline(int, void *, size_t);
+ssize_t  Readline_timeo(int, void *, size_t, int);
+ssize_t  Readn(int, void *, size_t);
+ssize_t  Readn_timeo(int, void *, size_t, int);
+
+int      Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+void     Shutdown(int, int);
+Sigfunc *Signal(int, Sigfunc *);
+int      Socket(int, int, int);
+
+pid_t    Waitpid(pid_t, int *, int);
+ssize_t  Writen(int, const void *, size_t);
+
+/* odbcs_conf.c */
+
+typedef struct _odbcs_t {
+  struct _odbcs_t *next;
+  struct _odbcs_t *prev;
+  char *line;
+  /* binpath */
+  char *odb_binpath; /* $ODB_ROOT/bin */
+  /* fields */
+  char *hostname;
+  char *username;
+  int port;
+  int timeout;
+  char *arch;
+  char *cpu_type;
+  int object_mode;
+  char *odb_arch;
+  char *odb_version;
+  char *odb_compdir;
+  char *odb_dir;
+  char *odb_root;
+} odbcs_t;
+
+const odbcs_t *odbcs_conf_match(const char *host, odbcs_t *conf, char **truehostname);
+odbcs_t *odbcs_conf_create();
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* ODBCS */
+
+#endif /* _ODBCS_H_ */
diff --git a/odb/src/include/odbcsdefs.h b/odb/src/include/odbcsdefs.h
new file mode 100644
index 0000000..2ca70c2
--- /dev/null
+++ b/odb/src/include/odbcsdefs.h
@@ -0,0 +1,20 @@
+#ifndef _ODBCSDEFS_H_
+#define _ODBCSDEFS_H_
+
+/* odbcsdefs.h */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#define MIN_PORT 10000
+#define MAX_PORT 20000
+
+#define DB_DEFAULT   "ECMA"
+#define HOST_DEFAULT "127.0.0.1"
+#define PORT_DEFAULT  ((getuid()%(MAX_PORT-MIN_PORT)) + MIN_PORT)
+#define TIMEOUT_DEFAULT 3600
+#define DATAPATH_DEFAULT "/tmp"
+#define SERVER_SELF_TIMEOUT(x) (2 * (x))
+#define LISTEN_QUEUE_LENGTH_DEFAULT 64
+
+#endif /* _ODBCSDEFS_H_ */
diff --git a/odb/src/include/odbcstags.h b/odb/src/include/odbcstags.h
new file mode 100644
index 0000000..ab4e7f2
--- /dev/null
+++ b/odb/src/include/odbcstags.h
@@ -0,0 +1,37 @@
+#ifndef _ODBCSTAGS_H_
+#define _ODBCSTAGS_H_
+
+/* odbcstags.h */
+
+#include "setodbcs.h"
+
+#ifdef ODBCS
+
+#define ODBCS_TAG_DB_METADATA            0
+#define ODBCS_TAG_PREPARE_QUERY          1
+#define ODBCS_TAG_EXECUTE_QUERY          2
+#define ODBCS_TAG_BIND_PARAM             3
+#define ODBCS_TAG_CONNECT                4
+#define ODBCS_TAG_BYEBYE                 5
+#define ODBCS_TAG_TIMEOUT                6
+#define ODBCS_TAG_VERBOSE                7
+#define ODBCS_TAG_FETCHFILE              8
+
+static const char *
+odbcs_tagname[] = {
+  "DB_METADATA",
+  "PREPARE_QUERY",
+  "EXECUTE_QUERY",
+  "BIND_PARAM",
+  "CONNECT",
+  "BYEBYE",
+  "TIMEOUT",
+  "VERBOSE",
+  "FETCHFILE"
+};
+
+#define ODBCS_MAXTAGS (sizeof(odbcs_tagname)/sizeof(*odbcs_tagname))
+
+#endif
+
+#endif /* _ODBCSTAGS_H_ */
diff --git a/odb/src/include/odbdump.h b/odb/src/include/odbdump.h
new file mode 100644
index 0000000..d1a218e
--- /dev/null
+++ b/odb/src/include/odbdump.h
@@ -0,0 +1,37 @@
+#ifndef _ODBDUMP_H_
+#define _ODBDUMP_H_
+
+/* odbdump.h */
+
+#include "result.h"
+
+/* from aux/odbdump.c */
+
+extern void
+odbdump_reset_stderr(FILE *fp, const char *filename, const char *mode);
+
+extern void *odbdump_open(const char *database,
+			  const char *sql_query, /* Precedence on this over the queryfile, if both present */
+			  const char *queryfile,
+			  const char *poolmask,
+			  const char *varvalue,
+			  int *ncols);
+
+extern int odbdump_nextrow(void *Handle, 
+			   void *v, /* at least nd elements of sizeof(double) */
+			   int nd,
+			   int *new_dataset);
+
+extern int odbdump_nextrow_packed(void *Handle,
+				  void *v, /* at least npk elements sizeof(char) */
+				  int npk,
+				  int *new_dataset);
+
+extern int odbdump_close(void *Handle);
+
+extern colinfo_t *odbdump_create_colinfo(void *Handle, int *ncols);
+
+extern colinfo_t *odbdump_destroy_colinfo(colinfo_t *ci, int ncols);
+
+#endif /* _ODBDUMP_H_ */
+
diff --git a/odb/src/include/odbi.h b/odb/src/include/odbi.h
new file mode 100644
index 0000000..6ad989c
--- /dev/null
+++ b/odb/src/include/odbi.h
@@ -0,0 +1,207 @@
+#ifndef _ODBI_H_
+#define _ODBI_H_
+
+
+/*!
+    \file odbi.h 
+    \brief ODB API include file
+
+     Define functions and subroutines common to client/server and direct access modes.
+*/
+
+/*! Both for client/server and direct access */
+
+#if ODBI_CLIENT == 1
+/* Client/Server mode (the default, unless ODBI_DIRECT is set to non-zero value) */
+
+#define ODBI_bind_param            CS_ODBI_bind_param
+#define ODBI_connect               CS_ODBI_connect
+#define ODBI_disconnect            CS_ODBI_disconnect
+#define ODBI_execute               CS_ODBI_execute
+#define ODBI_fetchrow_array        CS_ODBI_fetchrow_array
+#define ODBI_fetchonerow_array     CS_ODBI_fetchonerow_array
+#define ODBI_fetchfile             CS_ODBI_fetchfile
+#define ODBI_finish                CS_ODBI_finish
+#define ODBI_limits                CS_ODBI_limits
+#define ODBI_maxnamelen            CS_ODBI_maxnamelen
+#define ODBI_prepare               CS_ODBI_prepare
+#define ODBI_print_db_metadata     CS_ODBI_print_db_metadata
+#define ODBI_print_query_metadata  CS_ODBI_print_query_metadata
+
+  /* Shared routines i.e. source code is identical in direct *and* client/server -mode */
+
+#define ODBI_colname               CS_ODBI_colname
+#define ODBI_colnickname           CS_ODBI_colnickname
+#define ODBI_coltype               CS_ODBI_coltype
+#define ODBI_coltypenum            CS_ODBI_coltypenum
+#define ODBI_io_method             CS_ODBI_io_method
+#define ODBI_is_null               CS_ODBI_is_null
+#define ODBI_ncols                 CS_ODBI_ncols
+#define ODBI_npools                CS_ODBI_npools
+#define ODBI_printcol              CS_ODBI_printcol
+#define ODBI_swapbytes             CS_ODBI_swapbytes
+#define ODBI_timer                 CS_ODBI_timer
+
+#define ODBI_errno                 CS_ODBI_errno
+#define ODBI_perror                CS_ODBI_perror
+#define ODBI_strerror              CS_ODBI_strerror
+
+#endif
+
+#if ODBI_DIRECT == 1
+/* Direct mode */
+
+#define ODBI_bind_param            D_ODBI_bind_param
+#define ODBI_connect               D_ODBI_connect
+#define ODBI_disconnect            D_ODBI_disconnect
+#define ODBI_execute               D_ODBI_execute
+#define ODBI_fetchrow_array        D_ODBI_fetchrow_array
+#define ODBI_fetchonerow_array     D_ODBI_fetchonerow_array
+#define ODBI_fetchfile             D_ODBI_fetchfile
+#define ODBI_finish                D_ODBI_finish
+#define ODBI_limits                D_ODBI_limits
+#define ODBI_maxnamelen            D_ODBI_maxnamelen
+#define ODBI_prepare               D_ODBI_prepare
+#define ODBI_print_db_metadata     D_ODBI_print_db_metadata
+#define ODBI_print_query_metadata  D_ODBI_print_query_metadata
+
+/* Shared routines i.e. source code is identical in direct *and* client/server -mode */
+
+#define ODBI_colname               D_ODBI_colname
+#define ODBI_colnickname           D_ODBI_colnickname
+#define ODBI_coltype               D_ODBI_coltype
+#define ODBI_coltypenum            D_ODBI_coltypenum
+#define ODBI_io_method             D_ODBI_io_method
+#define ODBI_is_null               D_ODBI_is_null
+#define ODBI_ncols                 D_ODBI_ncols
+#define ODBI_npools                D_ODBI_npools
+#define ODBI_printcol              D_ODBI_printcol
+#define ODBI_swapbytes             D_ODBI_swapbytes
+#define ODBI_timer                 D_ODBI_timer
+
+#define ODBI_errno                 D_ODBI_errno
+#define ODBI_perror                D_ODBI_perror
+#define ODBI_strerror              D_ODBI_strerror
+
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+  extern int ODBI_errno;
+  extern void ODBI_perror(const char *s);
+  extern const char *ODBI_strerror(int errnum);
+
+  extern double ODBI_bind_param
+  (void *q, 
+   const char *param_name, 
+   double new_value);
+
+  extern const char *ODBI_colname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *ODBI_colnickname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *ODBI_coltype
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern unsigned int ODBI_coltypenum
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern void *ODBI_connect
+  (const char *dbname,
+   const char *params, /* More like for use by client */
+   ...);
+
+  extern int ODBI_disconnect
+  (void *db);
+
+  extern int ODBI_execute
+  (void *q);
+
+  extern int ODBI_fetchrow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int ODBI_fetchonerow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int ODBI_finish
+  (void *q);
+
+  extern int ODBI_is_null
+  (double d);
+
+  extern int ODBI_io_method
+  (void *db);
+
+  extern void ODBI_limits
+  (void *q,
+   int *start_row,
+   int *maxrows,
+   int *bufsize);
+
+  extern int ODBI_maxnamelen
+  (int new_len);
+
+  extern int ODBI_ncols
+  (const void *q);
+
+  extern int ODBI_npools
+  (void *db);
+
+  extern void *ODBI_prepare
+  (void *db,
+   const char *viewname,
+   const char *query_string /* For now: applicable only for client */
+   );
+
+  extern int ODBI_fetchfile
+  (void *q,
+   const char *filename,
+   const char *fileformat);
+
+  extern void ODBI_printcol
+  (FILE *fp,
+   void *q,
+   int jcol,
+   double d,
+   const char *delim,
+   int print_nulls);
+
+  extern void ODBI_print_db_metadata
+  (FILE *fp,
+   void *db,
+   int complete_info);
+
+  extern void ODBI_print_query_metadata
+  (FILE *fp,
+   void *q);
+			   
+  extern void ODBI_swapbytes
+  (void *v,      /* a vector of consecutive 2, 4 or 8-byte to be swapped */
+   int vlen,
+   int elemsize  /* set to 2,4 or 8 => v[] is treated as 2, 4 or 8-byte vector */
+   );
+  
+  extern double ODBI_timer
+  (const double *reftime);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/odb/src/include/odbi_cs.h b/odb/src/include/odbi_cs.h
new file mode 100644
index 0000000..577760a
--- /dev/null
+++ b/odb/src/include/odbi_cs.h
@@ -0,0 +1,132 @@
+#ifndef _ODBI_CS_H_
+#define _ODBI_CS_H_
+
+
+/*!
+    \file odbi_cs.h 
+    \brief ODB API include file
+
+     Define functions and subroutines for client/server mode.
+*/
+
+/*! Client/Server */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+  extern int CS_ODBI_errno;
+  extern void CS_ODBI_perror(const char *s);
+  extern const char *CS_ODBI_strerror(int errnum);
+
+  extern double CS_ODBI_bind_param
+  (void *q, 
+   const char *param_name, 
+   double new_value);
+
+  extern const char *CS_ODBI_colname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *CS_ODBI_colnickname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *CS_ODBI_coltype
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern unsigned int CS_ODBI_coltypenum
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern void *CS_ODBI_connect
+  (const char *dbname,
+   const char *params, /* More like for use by client */
+   ...);
+
+  extern int CS_ODBI_disconnect
+  (void *db);
+
+  extern int CS_ODBI_execute
+  (void *q);
+
+  extern int CS_ODBI_fetchrow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int CS_ODBI_fetchonerow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int CS_ODBI_finish
+  (void *q);
+
+  extern int CS_ODBI_is_null
+  (double d);
+
+  extern int CS_ODBI_io_method
+  (void *db);
+
+  extern void CS_ODBI_limits
+  (void *q,
+   int *start_row,
+   int *maxrows,
+   int *bufsize);
+
+  extern int CS_ODBI_maxnamelen
+  (int new_len);
+
+  extern int CS_ODBI_ncols
+  (const void *q);
+
+  extern int CS_ODBI_npools
+  (void *db);
+
+  extern void *CS_ODBI_prepare
+  (void *db,
+   const char *viewname,
+   const char *query_string /* For now: applicable only for client */
+   );
+
+  extern int CS_ODBI_fetchfile
+  (void *q,
+   const char *filename,
+   const char *fileformat);
+
+  extern void CS_ODBI_printcol
+  (FILE *fp,
+   void *q,
+   int jcol,
+   double d,
+   const char *delim,
+   int print_nulls);
+
+  extern void CS_ODBI_print_db_metadata
+  (FILE *fp,
+   void *db,
+   int complete_info);
+
+  extern void CS_ODBI_print_query_metadata
+  (FILE *fp,
+   void *q);
+			   
+  extern void CS_ODBI_swapbytes
+  (void *v,      /* a vector of consecutive 2, 4 or 8-byte to be swapped */
+   int vlen,
+   int elemsize  /* set to 2,4 or 8 => v[] is treated as 2, 4 or 8-byte vector */
+   );
+  
+  extern double CS_ODBI_timer
+  (const double *reftime);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/odb/src/include/odbi_direct.h b/odb/src/include/odbi_direct.h
new file mode 100644
index 0000000..6382d8b
--- /dev/null
+++ b/odb/src/include/odbi_direct.h
@@ -0,0 +1,132 @@
+#ifndef _ODBI_DIRECT_H_
+#define _ODBI_DIRECT_H_
+
+
+/*!
+    \file odbi_direct.h 
+    \brief ODB API include file
+
+     Define functions and subroutines for direct access modes.
+*/
+
+/*! Direct access */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+  extern int D_ODBI_errno;
+  extern void D_ODBI_perror(const char *s);
+  extern const char *D_ODBI_strerror(int errnum);
+
+  extern double D_ODBI_bind_param
+  (void *q, 
+   const char *param_name, 
+   double new_value);
+
+  extern const char *D_ODBI_colname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *D_ODBI_colnickname
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern const char *D_ODBI_coltype
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern unsigned int D_ODBI_coltypenum
+  (const void *q, 
+   int jcol); /* Note: The range is [1..ncols] */
+
+  extern void *D_ODBI_connect
+  (const char *dbname,
+   const char *params, /* More like for use by client */
+   ...);
+
+  extern int D_ODBI_disconnect
+  (void *db);
+
+  extern int D_ODBI_execute
+  (void *q);
+
+  extern int D_ODBI_fetchrow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int D_ODBI_fetchonerow_array
+  (void *q,
+   int *nrows, 
+   int *ncols,
+   double d[],
+   int nd);
+
+  extern int D_ODBI_finish
+  (void *q);
+
+  extern int D_ODBI_is_null
+  (double d);
+
+  extern int D_ODBI_io_method
+  (void *db);
+
+  extern void D_ODBI_limits
+  (void *q,
+   int *start_row,
+   int *maxrows,
+   int *bufsize);
+
+  extern int D_ODBI_maxnamelen
+  (int new_len);
+
+  extern int D_ODBI_ncols
+  (const void *q);
+
+  extern int D_ODBI_npools
+  (void *db);
+
+  extern void *D_ODBI_prepare
+  (void *db,
+   const char *viewname,
+   const char *query_string /* For now: applicable only for client */
+   );
+
+  extern int D_ODBI_fetchfile
+  (void *q,
+   const char *filename,
+   const char *fileformat);
+
+  extern void D_ODBI_printcol
+  (FILE *fp,
+   void *q,
+   int jcol,
+   double d,
+   const char *delim,
+   int print_nulls);
+
+  extern void D_ODBI_print_db_metadata
+  (FILE *fp,
+   void *db,
+   int complete_info);
+
+  extern void D_ODBI_print_query_metadata
+  (FILE *fp,
+   void *q);
+			   
+  extern void D_ODBI_swapbytes
+  (void *v,      /* a vector of consecutive 2, 4 or 8-byte to be swapped */
+   int vlen,
+   int elemsize  /* set to 2,4 or 8 => v[] is treated as 2, 4 or 8-byte vector */
+   );
+  
+  extern double D_ODBI_timer
+  (const double *reftime);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/odb/src/include/odbi_struct.h b/odb/src/include/odbi_struct.h
new file mode 100644
index 0000000..6d09476
--- /dev/null
+++ b/odb/src/include/odbi_struct.h
@@ -0,0 +1,85 @@
+
+/* odbi_struct.h */
+
+typedef struct _ODBI_col_t {
+  char *name;
+  char *nickname;
+  char *type;
+  unsigned int dtnum; /* see "privpub.h" */
+  /* the following 2: see "info.h" */
+  int bitpos;
+  int bitlen;
+} ODBI_col_t;
+
+typedef struct _ODBI_query_t {
+  char *name;
+  char *query_string;
+  FILE *fpcache;
+  int vhandle;
+  int poolno;
+  int ntot;
+  int nrows;
+  int ncols;
+  int nra;
+  int row_offset;
+  double *a; /* data matrix in native (F90) layout : a(nra,0:ncols) */
+  struct _ODBI_db_t *db;
+  int ncols_fixed;
+  int ncols_all; /* ordinary columns + bit members */
+  struct _ODBI_col_t *cols;
+  int start_row;
+  int maxrows;
+  int is_table;
+  int string_count;
+  /* For odbi_direct only */
+  /* Only applicable to fast_odbsql == 1 */
+  void *info; /* see info_t in "info.h" */
+  int need_global_picture;
+  int first_time;
+  int all_processed;
+  int re_eval_info;
+} ODBI_query_t;
+
+/* start client specific */
+typedef struct _ODBI_db_cli_t {
+  int   port;
+  char *host; /* hostname or ip-address */
+  char *hostname; /* normally meant to be the hostname, not ip-address */
+  char *datapath;
+  char *poolmask;
+  char *user;
+  char *password;
+  char *workdir;
+  char *exe;
+  char *clihost;
+  char *cliaddr;
+  int   sockfd;
+  int   metadata;
+  int   verbose;
+  int   silent;
+  int   timeout;
+  int   clean;
+  int   keep;
+  int   bufsize;
+  int   version;
+  int   odbsql;
+} ODBI_db_cli_t;
+/* end client specific */
+
+typedef struct _ODBI_db_t {
+  FILE *fp;
+  int fp_opened_here;
+  char *name;
+  char *mode;
+  int handle;
+  int npools;
+  int io_method;
+  int nquery;
+  int *poolstat;
+  struct _ODBI_query_t *query;
+  int swapbytes;
+  int ntables;
+  char **tables;
+  /* for client/server-model only */
+  ODBI_db_cli_t *cli;
+} ODBI_db_t;
diff --git a/odb/src/include/odbmd5.h b/odb/src/include/odbmd5.h
new file mode 100644
index 0000000..46c64c0
--- /dev/null
+++ b/odb/src/include/odbmd5.h
@@ -0,0 +1,26 @@
+
+/* odbmd5.h */
+
+#ifndef ODBMD5_H
+#define ODBMD5_H
+
+#include "alloc.h"
+#include "magicwords.h"
+
+typedef unsigned int uint32;
+
+struct MD5Context {
+        uint32 buf[4];
+        uint32 bits[2];
+        unsigned char in[64];
+};
+
+extern void MD5Init(struct MD5Context *ctx);
+extern void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned int len);
+extern void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+
+extern int MD5_signature(int argc, char *argv[], unsigned char sign[16]);
+extern char *MD5_sign2hex(const unsigned char sign[16], int lowercase);
+extern int MD5_str2sign(const char *s, unsigned char sign[16]);
+
+#endif
diff --git a/odb/src/include/pcma.h b/odb/src/include/pcma.h
new file mode 100644
index 0000000..e8358b7
--- /dev/null
+++ b/odb/src/include/pcma.h
@@ -0,0 +1,426 @@
+#ifndef _PCMA_H_
+#define _PCMA_H_
+
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+
+#include "alloc.h"
+#include "swapbytes.h"
+#include "pcma_extern.h"
+#include "cdrhook.h"
+
+#define PCMA_NEW_VERSION(h) ((*(h+1))%MAXSHIFT == 0) ? (PCMA_HDRLEN-HDRLEN) : 0
+
+/* Change the following every time you add a new method to the look_up[]
+   Also keep track which is/has the max at any given moment by moving around
+   the comment "The current MAXPACKFUNC minus 1" */
+
+#define MAXPACKFUNC 10
+
+#if defined(PCMA_C) || defined(UPCMA_C)
+#define BAD_IDX 0x8B8B8B8B
+static const int look_up[1+MAXPACKINGMETHOD /* packing_methods [1..255] ; including zero i.e. no packing */] = 
+{
+  BAD_IDX, /* method#0 : undefined (since means no packing) */
+
+  0, /* method#1 */
+  1, /* method#2 */
+  2, /* method#3 */
+
+  7, /* method#4 */
+
+  3, /* method#5 */
+
+  BAD_IDX, /* method#6 : undefined */
+  BAD_IDX, /* method#7 : undefined */
+  BAD_IDX, /* method#8 : undefined */
+
+  4, /* method#9 */
+
+  BAD_IDX, /* method#10 : undefined */
+
+  /* methods #11..19 map to the same method routine ; significant digits => 10 + sign_digits */
+
+  5, 5, 5, 5, 5, 5, 5, 5, 5,
+
+  /* methods #20..100 */
+
+  BAD_IDX, /* method#20, undefined */
+
+  /* methods #21..29 map to the same method routine ; significant digits => 20 + sign_digits ;
+     10^exponent is saved separately; a merger of method#1 & method#11..19 for unnormalized
+     reals */
+
+           6, 6, 6, 6, 6, 6, 6, 6, 6,
+
+  /* method #30 : undefined */
+
+  BAD_IDX,
+
+  /* methods #31..39 : Similar to #21..29, but retain full accuracy of 4-byte integers */
+
+           9, 9, 9, 9, 9, 9, 9, 9, 9,    /* The current MAXPACKFUNC minus 1 */
+
+  /* methods #40..93 */
+
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, 
+
+  /* method #94 (pseudo) */
+
+                             8,
+
+  /* methods #95..100 : undefined  */
+
+                                      BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+
+  /* methods #101..200  : undefined */
+
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+
+  /* methods #201..254 : undefined */
+
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX,
+  BAD_IDX, BAD_IDX, BAD_IDX, BAD_IDX, 
+
+  /* method#255  : undefined */
+
+  BAD_IDX
+};
+#undef BAD_IDX
+#endif
+
+#if defined(VPP) || defined(NECSX)
+
+static const unsigned int pwr2[32+1] = 
+{ 
+           1U,            2U,            4U,            8U,
+          16U,           32U,           64U,          128U,
+         256U,          512U,         1024U,         2048U,
+        4096U,         8192U,        16384U,        32768U,
+       65536U,       131072U,       262144U,       524288U,
+     1048576U,      2097152U,      4194304U,      8388608U,
+    16777216U,     33554432U,     67108864U,    134217728U,
+   268435456U,    536870912U,   1073741824U,   2147483648U,
+           0U,
+};
+
+#define PWR2(shift) (pwr2[shift])
+#else
+#define PWR2(shift) (1<<(shift))
+#endif
+
+#define N32BITS 32
+
+#define b1   1
+#define b2   2
+#define b4   4
+#define b8   8
+#define b10 10
+#define b16 16
+#define b32 32
+
+#define MINBLOCK     6144U
+#define MAXBLOCK (MAXSHIFT-1U)
+
+#define MINLEN ((int)((HDRLEN+1)*sizeof(unsigned int)))
+
+#define ZERO  0
+
+#define SWAP_DATA_BACK(swp,can_swap_data,cma,lencma) \
+if (swp && !can_swp_data && lencma > 1) { /* swap data back */ \
+  int len = lencma - 1; \
+  swap8bytes_(&cma[fill_zeroth_cma], &len); \
+}
+
+#define SWAP_DATA_BACKv2(swp,can_swap_data,cma,stacma,endcma) \
+if (swp && !can_swp_data && endcma-stacma > 0) { /* swap data back, vers#2 */ \
+  int len = endcma-stacma; \
+  swap8bytes_(&cma[fill_zeroth_cma+stacma], &len); \
+}
+
+#define STAEND_FIX() \
+    if (idx && idxlen > 0) { \
+      int j; \
+      int minidx = chunk+1; \
+      int maxidx = 0; \
+      for (j=0; j<idxlen; j++) { \
+	if (idx[j] < minidx) minidx = idx[j]; \
+	if (idx[j] > maxidx) maxidx = idx[j]; \
+      } \
+      stacma = minidx; \
+      stacma = MAX(0,stacma); \
+      endcma = maxidx+1; \
+      endcma = MIN(chunk,endcma); \
+    }
+
+#define END_FIX() \
+    if (idx && idxlen > 0) { \
+      int j; \
+      int maxidx = 0; \
+      for (j=0; j<idxlen; j++) { \
+	if (idx[j] > maxidx) maxidx = idx[j]; \
+      } \
+      endcma = maxidx+1; \
+      endcma = MIN(chunk,endcma); \
+    }
+
+#define FCLOSE(fp)        if (fp) { fclose(fp); fp = NULL; }
+
+extern int
+pcma_1_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_2_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_3_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_4_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_5_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_9_driver(          int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_11to19_driver(      int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_21to29_driver(     int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+pcma_31to39_driver(     int method,
+	              FILE *fp_out,
+	      const double  cma[],
+                       int  lencma,
+	            double  nmdi,
+	            double  rmdi,
+	           Packbuf *pbuf);
+
+extern int
+upcma_1_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+                	     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_2_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+                	     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_3_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+   	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+	                     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_4_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+   	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+	                     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_5_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+                	     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_9_driver(int method,
+	       int swp, int can_swp_data,
+	       int new_version,
+	       const unsigned int  packed_data[],
+	                      int  len_packed_data,	
+	                      int  msgbytes,
+	                   double  nmdi,
+	                   double  rmdi,
+                	     FILE *fp_out, 
+	                const int  idx[], int  idxlen,
+              	              int  fill_zeroth_cma,
+	                   double  cma[], int lencma);
+
+extern int
+upcma_11to19_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int  packed_data[],
+		                   int  len_packed_data,	
+		                   int  msgbytes,
+		                double  nmdi,
+                                double  rmdi,
+		                  FILE *fp_out, 
+		             const int  idx[], int  idxlen,
+		                   int  fill_zeroth_cma,
+		                double  cma[], int lencma);
+
+extern int
+upcma_21to29_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int  packed_data[],
+		                   int  len_packed_data,	
+		                   int  msgbytes,
+		                double  nmdi,
+		                double  rmdi,
+		                  FILE *fp_out, 
+		             const int  idx[], int  idxlen,
+		                   int  fill_zeroth_cma,
+		                double  cma[], int lencma);
+
+extern int
+upcma_31to39_driver(int method,
+		    int swp, int can_swp_data,
+		    int new_version,
+		    const unsigned int  packed_data[],
+		                   int  len_packed_data,	
+		                   int  msgbytes,
+		                double  nmdi,
+		                double  rmdi,
+		                  FILE *fp_out, 
+		             const int  idx[], int  idxlen,
+		                   int  fill_zeroth_cma,
+		                double  cma[], int lencma);
+
+/* Utilities */
+
+extern void 
+pcma_zero_uint(unsigned int u[], int n);
+
+extern void 
+pcma_copy_uint(unsigned int to[], const unsigned int from[], int n);
+
+extern void 
+pcma_copy_dbl(double to[], const double from[], int n);
+
+extern unsigned int *
+pcma_alloc(Packbuf *pbuf, int count);
+
+extern int 
+pcma_filesize(const char *path);
+
+extern FILE *
+pcma_prealloc(const char *filename,
+	      int         prealloc,
+	      int         extent,
+	      int        *blksize,
+	      int        *retcode);
+
+#endif
diff --git a/odb/src/include/pcma_extern.h b/odb/src/include/pcma_extern.h
new file mode 100644
index 0000000..b5f79d3
--- /dev/null
+++ b/odb/src/include/pcma_extern.h
@@ -0,0 +1,194 @@
+
+#ifndef _PCMA_EXTERN_H_
+#define _PCMA_EXTERN_H_
+
+/* pcma_extern.h */
+
+#define RMDI   -2147483647
+#define NMDI    2147483647
+
+#define MAXSHIFT 16777216U
+#define HDRLEN 3
+
+#define MAXPACKINGMETHOD 255
+
+/* hdrlen for the new version, since 14/12/2000 */
+#define PCMA_HDRLEN (HDRLEN + 1 + 2*(sizeof(double)/sizeof(int)))
+
+#include "magicwords.h"
+
+extern int pcma_blocksize;
+extern int pcma_verbose;
+extern int pcma_restore_packed;
+
+extern double pcma_nmdi; /* the default : an integer NMDI =  2147483647   */
+extern double pcma_rmdi; /* the default : a real     RMDI = -2147483647.0 */
+
+typedef struct {
+  int counter;
+  int maxalloc;
+  int len;
+  unsigned int *p;
+  unsigned char allocatable;
+} Packbuf;
+
+typedef struct {
+  int magic; /* PCMA */
+#ifdef LITTLE
+  int old_replen : 24;
+  int method : 8;
+#else
+  int method : 8; /* Packing method [0..255] */
+  int old_replen : 24; /* Old style report length; [1..16777215] words
+			  if zero, use new_replen + nmdi & rmdi present, too */
+#endif
+  int msgbytes; /* total length of packed message (excluding header), in bytes */
+  /* The following are only present if the old_replen is zero */
+  unsigned int new_replen; /* New style report length that can now span between [1..2147483647] */
+  double nmdi; /* NMDI used (the default = pcma_nmdi) */
+  double rmdi; /* RMDI used (the default = pcma_rmdi) */
+} Packhdr;
+
+/* Error exit */
+
+extern int
+pcma_error(const char *where,
+           int how_much,
+           const char *what,
+           const char *srcfile,
+           int srcline,
+           int perform_abort);
+
+/* CMA-packing */
+
+extern int
+pcma(        FILE *fp_in,
+             FILE *fp_out,
+              int  method,
+     const double  cma[],
+              int  lencma,
+          Packbuf *pbuf,
+              int *bytes_in,
+              int *bytes_out);
+
+
+extern void *
+PackDoubles(const double v[],
+	    const int nv,
+	    int *nbytes);
+
+/* CMA-unpacking */
+
+extern int
+upcma(         int  can_swp_data,
+              FILE *fp_in,
+              FILE *fp_out,
+	 const int  idx[], int  idxlen,
+	       int  fill_zeroth_cma,
+            double  cma[],
+               int  lencma,
+      unsigned int *hdr_in,
+           Packbuf *pbuf,
+               int *bytes_in,
+               int *bytes_out);
+
+extern int
+upcma_hdr(FILE *fp_in, int *swp,
+          unsigned int *hdr_in, int read_hdr,
+          int *method, int *replen, int *msgbytes,
+	  double *nmdi, double *rmdi,
+	  int *new_version);
+
+extern int 
+upcma_data(FILE *fp_in, const unsigned int *hdr,
+	   int new_version,
+           unsigned int *packed_data, int count);
+
+void
+upcmaTOcma(const          int *can_swp_data,
+	   const unsigned int  packed_hdr[],
+           const unsigned int  packed_stream[],
+	            const int  idx[], int  idxlen,
+	                  int  fill_zeroth_cma,
+                       double  cma[],
+                    const int *lencma,
+                          int *retcode);
+
+extern double *
+UnPackDoubles(const void *pk,
+	      const int nbytes,
+	      int *nv);
+
+
+/* Fortran callable routines */
+
+#ifndef FORTRAN_CALL
+#define FORTRAN_CALL extern
+#endif
+
+FORTRAN_CALL void
+pcma_set_mdis_(const double *nmdi,
+	       const double *rmdi);
+
+FORTRAN_CALL void
+pcma_get_mdis_(double *nmdi,
+	       double *rmdi);
+
+FORTRAN_CALL void 
+upcma_info_(const unsigned int  packed_hdr[],
+                           int  info[],
+                     const int *infolen,
+                           int *retcode);
+
+FORTRAN_CALL void
+pcma2cma_(const          int *can_swp_data,
+	  const unsigned int  packed_data[],
+                   const int *packed_len,
+	           const int  idx[], const int *idxlen,
+	           const int *fill_zeroth_cma,
+                      double  cma[],
+                   const int *lencma,
+                         int *packed_count,
+                         int *retcode);
+
+FORTRAN_CALL void
+cma2pcma_(const    int *method,
+          const double  cma[],
+	  const    int *lencma,
+	  unsigned int  packed_stream[],
+	  const    int *lenpacked_stream,
+                   int *bytes_in,
+                   int *bytes_out,
+	           int *retcode);
+
+FORTRAN_CALL void
+vpack_bits_(const int *N_bits,
+	    const unsigned int    unpacked[],
+	             const int *N_unpacked,
+	          unsigned int    packed[],
+	             const int *N_packed,
+	          int *retcode);
+
+FORTRAN_CALL void
+vunpack_bits_(const int *N_bits,
+	      const unsigned int    packed[],
+	               const int *N_packed,
+	            unsigned int    unpacked[],
+	               const int *N_unpacked,
+	            int *retcode);
+
+FORTRAN_CALL void
+lzw_unpack_(const unsigned char ibuf[],
+	    const int *Ilen,
+	    unsigned char obuf[], 
+	    const int *Olen,
+	    int *retcode);
+
+FORTRAN_CALL void
+lzw_pack_(const unsigned char ibuf[], 
+	  const int *Ilen,
+	  unsigned char obuf[],
+	  const int *Olen,
+	  int *retcode);
+
+#endif
diff --git a/odb/src/include/privpub.h b/odb/src/include/privpub.h
new file mode 100644
index 0000000..922e699
--- /dev/null
+++ b/odb/src/include/privpub.h
@@ -0,0 +1,636 @@
+
+/* privpub.h */
+
+#ifndef _PRIVPUB_H_
+#define _PRIVPUB_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#if !defined(IO_BUFSIZE_DEFAULT)
+/* The default I/O-buffer size = 4MBytes (unless overridden through ioassign) */
+#define IO_BUFSIZE_DEFAULT 4194304
+#endif
+
+#define NIL "(nil)"
+
+#define PERROR(msg) \
+fprintf(stderr,"%s: %s (in %s:%d) : errno#%d\n",msg?msg:NIL,strerror(errno),__FILE__, __LINE__,errno)
+
+#if defined(VPP5000) || defined(VPP)
+/* Fujitsu VPP doesn't have snprintf, so we created one in file ifsaux/support/endian.c */
+/* For ODB/SQL compiler the same code sits in odb/compiler/odb98.c */
+extern int snprintf(char *str, size_t size, const char *format, ...);
+#endif
+
+#if defined(NO_TRUNC) || defined(VPP) || defined(SV2)
+/* For systems without trunc() -function [an extension of ANSI-C, but usually available] */
+#define trunc(x) ((x) - fmod((x),1))
+#else
+#if !defined(__cplusplus)
+  extern double trunc(double d);
+#endif
+#endif
+
+#define PRIVATE static
+#define PUBLIC
+
+/* fprintf even if "fp" was NULL */
+extern int ODB_fprintf(FILE *fp, const char *format, ...);
+
+/* Fortran90 compatible NINT-function */
+
+#define F90nint(x) ( ((x) > 0) ? (int)((x) + 0.5) : (int)((x) - 0.5) )
+
+/* Pi related stuff */
+
+#define pi ((double)3.14159265358979323844e0)
+#define half_pi           (pi / 2)
+#define two_pi            (2 * pi)
+#define four_pi           (4 * pi)
+#define pi_over_180       (pi/180)
+#define recip_pi_over_180 (180/pi)
+
+/* Radians to degrees & degrees to radians (formerly in odb.h) */
+
+#define R2D(x) ( (180/pi) * ( ((x) >  pi) ? ((x) - 2*pi) : (x) ) )
+#define D2R(x) ( (pi/180) * ( ((x) > 180) ? ((x) -  360) : (x) ) )
+
+/* Radius of the Earth both in meters and kilometres (formerly in odb.h) */
+
+#define R_Earth    ((double)6371000e0)
+#define R_Earth_km ((double)6371e0)
+
+/* Some common things ... */
+
+#undef MIN
+#define MIN(a,b) ( ((a) < (b)) ? (a) :  (b) )
+
+#undef MAX
+#define MAX(a,b) ( ((a) > (b)) ? (a) :  (b) )
+
+#undef ABS
+#define ABS(x)   ( ((x) >= 0)  ? (x) : -(x) )
+
+#undef RNDUP_DIV
+#define RNDUP_DIV(i,n) (( (i) + (n) - 1 ) / (n))
+
+#undef RNDUP
+#define RNDUP(i,n) ( RNDUP_DIV(i,n) * (n))
+
+#define STRLEN(x)  (((const char *)(x)) ? (int)strlen(x) : (int)0)
+
+#define _POOLNO  "$pool#"
+#define _NPOOLS  "$npools#"
+#define _NTABLES "$ntables#"
+#define _UNIQNUM "$uniq#"
+#define _ROWNUM  "$row#"
+#define _COLNUM  "$col#"
+#define _NROWS   "$nrows#"
+#define _NCOLS   "$ncols#"
+
+#define IS_BSNUM(s)  ((s) && *(s) == '\\' && STRLEN(s) >= 2 && isdigit((s)[1]))
+#define IS_HASH(s)   ((s) && *(s) == '#')
+#define IS_DOLLAR(s) ((s) && *(s) == '$')
+#define IS_TABLE(s) ((s) && (s)[0] == '@')
+
+#define IS_POOLNO(s) ((s) && (((s)[0] == '$' && (s)[1] == '#')|| strequ(s,_POOLNO)))
+#define IS_(sym,s) strequ(s,_##sym)
+#define IS_USDHASH(s) ((s) && (s)[0] == '$' && (s)[STRLEN(s)-1] == '#')
+#define IS_USDDOTHASH(s) (IS_USDHASH(s) && strchr(s,'.') && (strchr(s,'.') == strrchr(s,'.')))
+
+static const char ODB_OFFSET_CHAR[] = "#";
+#define GET_OFFSET(s) ((!(s) || IS_DOLLAR(s) || IS_HASH(s) || IS_USDHASH(s)) ? NULL : strrchr(s,*ODB_OFFSET_CHAR))
+
+/* Timers */
+
+extern double util_cputime_();
+extern double util_walltime_();
+
+#ifdef RS6K
+extern void xl__trbk_();
+#else
+#define xl__trbk_()
+#endif
+
+extern void abor1fl_(const char *filename, const int *linenum, 
+		     const char *s, 
+		     int filenamelen, int slen);
+extern void abor1_(const char *s, int slen);
+
+#define ABOR1(txt) { \
+  const char *t = (txt); \
+  xl__trbk_(); t ? abor1_(t, strlen(t)) : abor1_("",0); }
+
+#define ABOR1FL(txt) { \
+  const char *t = (txt); \
+  int linenum=__LINE__; \
+  t ? abor1fl_(__FILE__, &linenum,  t, sizeof(__FILE__)-1, strlen(t)) \
+    : abor1fl_(__FILE__, &linenum, "", sizeof(__FILE__)-1, 0); \
+  _exit(1); /* Should never end up here */ }
+
+#define RAISE(x) { \
+  xl__trbk_(); \
+  if ((x) == SIGABRT) { \
+    const char *txt = "*** Fatal error; aborting (SIGABRT) ..."; \
+    ABOR1FL(txt); \
+    _exit(1); /* Should never end up here */ \
+  } \
+  else raise(x); \
+}
+
+/* No. of bits for "int" */
+#define MAXBITS 32
+
+/* No. of bits per 1-byte */
+#define BITS_PER_BYTE 8
+
+#ifndef O_LOCK_DONE
+#define O_LOCK_DONE
+
+/* OpenMP/ODB lock type */
+/* Keep consistent with "ifsaux/include/drhook.h" */
+/* Be ALSO consistent with OML_LOCK_KIND in ifsaux/module/oml_mod.F90 */
+
+typedef long long int o_lock_t; /* i.e. 64-bit integer */
+
+#define INIT_LOCKID_WITH_NAME(mylock, lockname) \
+  coml_init_lockid_with_name_(mylock, lockname, strlen(lockname))
+
+extern void coml_set_debug_(const int *konoff, int *kret);
+extern void coml_init_lock_();
+extern void coml_init_lockid_(o_lock_t *mylock);
+extern void coml_init_lockid_with_name_(o_lock_t *mylock, const char *name, int name_len);
+extern void coml_set_lock_();
+extern void coml_set_lockid_(o_lock_t *mylock);
+extern void coml_unset_lock_();
+extern void coml_unset_lockid_(o_lock_t *mylock);
+extern void coml_test_lock_(int *is_set);
+extern void coml_test_lockid_(int *is_set, o_lock_t *mylock);
+extern void coml_in_parallel_(int *is_parallel_region);
+
+#endif /* #ifndef O_LOCK_DONE */
+
+/* OpenMP-stuff */
+
+/* My thread-id [1 .. $OMP_NUM_THREADS] as in ifsaux/module/oml_mod.F90 */
+extern int
+get_thread_id_(); /* From "ifsaux/utilities/get_thread_id.F90" */
+
+/* Static number of threads allocated i.e. $OMP_NUM_THREADS */
+extern int
+get_max_threads_(); /* From "ifsaux/utilities/get_max_threads.F90" */
+
+/* The current number of threads allocated <= $OMP_NUM_THREADS */
+extern int
+get_num_threads_(); /* From "ifsaux/utilities/get_num_threads.F90" */
+
+#define DEF_IT    int it = get_thread_id_()
+#define IT        (it-1)
+#define DEF_INUMT int inumt = get_max_threads_()
+
+/* 0 (zero) Celsius in Kelvin */
+
+#define ZERO_POINT ((double)273.15e0)
+
+/* Aggregate function flags */
+
+#define ODB_AGGR_NONE            0x0000000
+
+#define ODB_AGGRMASK_DISTINCT    0x0100000
+#define ODB_AGGRMASK_BOOLEAN     0x1000000
+
+#define ODB_AGGR_COUNT           0x0000001
+#define ODB_AGGR_COUNT_DISTINCT  (ODB_AGGRMASK_DISTINCT | ODB_AGGR_COUNT)
+
+#define ODB_AGGR_BCOUNT          (ODB_AGGRMASK_BOOLEAN | ODB_AGGR_COUNT)
+#define ODB_AGGR_BCOUNT_DISTINCT (ODB_AGGRMASK_BOOLEAN | ODB_AGGR_COUNT_DISTINCT)
+
+#define ODB_AGGR_MIN             0x0000002
+#define ODB_AGGR_MAX             0x0000004
+
+#define ODB_AGGR_SUM             0x0000008
+#define ODB_AGGR_SUM_DISTINCT    (ODB_AGGRMASK_DISTINCT | ODB_AGGR_SUM)
+
+#define ODB_AGGR_AVG             0x0000010
+#define ODB_AGGR_AVG_DISTINCT    (ODB_AGGRMASK_DISTINCT | ODB_AGGR_AVG)
+
+#define ODB_AGGR_STDEV           0x0000020
+#define ODB_AGGR_STDEV_DISTINCT  (ODB_AGGRMASK_DISTINCT | ODB_AGGR_STDEV)
+
+#define ODB_AGGR_RMS             0x0000040
+#define ODB_AGGR_RMS_DISTINCT    (ODB_AGGRMASK_DISTINCT | ODB_AGGR_RMS)
+
+#define ODB_AGGR_DOTP            0x0000080
+#define ODB_AGGR_DOTP_DISTINCT   (ODB_AGGRMASK_DISTINCT | ODB_AGGR_DOTP)
+
+#define ODB_AGGR_NORM            0x0000100
+#define ODB_AGGR_NORM_DISTINCT   (ODB_AGGRMASK_DISTINCT | ODB_AGGR_NORM)
+
+#define ODB_AGGR_VAR             0x0000200
+#define ODB_AGGR_VAR_DISTINCT    (ODB_AGGRMASK_DISTINCT | ODB_AGGR_VAR)
+
+#define ODB_AGGR_COVAR           0x0000400
+#define ODB_AGGR_CORR            0x0000800
+
+#define ODB_AGGR_LINREGR_A       0x0001000
+#define ODB_AGGR_LINREGR_B       0x0002000
+
+#define ODB_AGGR_MEDIAN          0x0010000
+#define ODB_AGGR_MEDIAN_DISTINCT (ODB_AGGRMASK_DISTINCT | ODB_AGGR_MEDIAN)
+
+#define ODB_AGGR_MINLOC          0x0020000
+#define ODB_AGGR_MAXLOC          0x0040000
+
+#define ODB_AGGR_DENSITY         0x0080000
+
+#define ODB_tag_delim ";"
+
+
+#ifdef __cplusplus
+    typedef bool Bool;
+#else
+    typedef enum { false=0, true=1 } Bool;
+#endif
+
+/* char : Normally occupies 1 byte */
+
+typedef unsigned int  boolean;
+
+typedef boolean Boolean;
+
+typedef unsigned char  byte;
+typedef byte           byte1;
+#if !defined(RS6K)
+typedef unsigned char uchar;
+#endif
+typedef char            integer1;
+typedef unsigned char  uinteger1;
+
+/* short : Normally occupies 2 bytes */
+
+typedef short           integer2;
+#if !defined(RS6K) && !defined(LINUX) && !defined(HPPA) && !defined(VPP) && !defined(SUN4) && !defined(NECSX) && !defined(SV2)
+typedef unsigned short int ushort;
+#endif
+typedef unsigned short uinteger2;
+
+/* int : Normally occupies 4 bytes */
+
+/* typedef unsigned int uint; (defined via system include files) */
+typedef int             integer4;
+typedef unsigned int   uinteger4;
+
+/* typedef unsigned long ulong; (defined via system include files) */
+
+/* long long: A non-standard way to access 8 byte integer(s) */
+
+typedef          long long int  longlong;
+typedef          long long int  ll_t;
+typedef unsigned long long int ulonglong;
+typedef unsigned long long int u_ll_t;
+typedef          long long int  integer8;
+typedef unsigned long long int uinteger8;
+
+/* float : 32-bit flp (normally IEEE-754), 4 bytes */
+
+typedef float           real4;
+
+/* double : 64-bit flp (normally IEEE-754), 8 bytes */
+
+typedef double          real8;
+
+/* Formula alias double : For use by SELECT-expressions (29-Jun-2006/SS) */
+
+typedef double          Formula;
+
+/* Supported data types */
+/* Moved here from odb.h on 7-Jan-2004/SS */
+
+typedef int number;
+typedef int pk1int;
+typedef int pk2int;
+typedef int pk3int;
+typedef int pk4int;
+typedef int pk5int;
+typedef int pk9int;
+
+typedef pk1int linkoffset_t; /* also follows packing#1 */
+typedef pk1int linklen_t;    /* also follows packing#1 */
+
+/* 
+   typedef unsigned int Bitfield;
+   typedef unsigned int hex4;
+
+   We can't have (at least the above) unsigned ints since the following 
+   substitution for unsigned int u and double d gets incorrect on RS6K,
+   when d < 0 [... the IBM-s.o.b. RS6K sets the result to zero !!]
+
+   u = d ;
+
+   what appears to be working is, but very weird is:
+   u = (int)d;
+
+   but we don't want to use this cast-operator, since its introduction 
+   would add even more confusion
+
+   ==> lets make Bitfield and hex4 signed ints (29-May-2002/SS)
+
+*/
+
+typedef int Bitfield;
+typedef int hex4;
+
+typedef hex4 bufr;
+typedef hex4 grib;
+
+typedef integer4 integer;
+
+/* These inherit corresponding packing method */
+
+typedef pk1int yyyymmdd;
+typedef pk1int hhmmss;
+
+typedef double pk2real;
+typedef double pk3real;
+typedef double pk4real;
+typedef double pk5real;
+typedef double pk9real;
+typedef pk3real string;
+/* typedef double string; */
+
+typedef double pk11real;
+typedef double pk12real;
+typedef double pk13real;
+typedef double pk14real;
+typedef double pk15real;
+typedef double pk16real;
+typedef double pk17real;
+typedef double pk18real;
+typedef double pk19real;
+
+typedef double pk21real;
+typedef double pk22real;
+typedef double pk23real;
+typedef double pk24real;
+typedef double pk25real;
+typedef double pk26real;
+typedef double pk27real;
+typedef double pk28real;
+typedef double pk29real;
+
+typedef double pk31real;
+typedef double pk32real;
+typedef double pk33real;
+typedef double pk34real;
+typedef double pk35real;
+typedef double pk36real;
+typedef double pk37real;
+typedef double pk38real;
+typedef double pk39real;
+
+typedef real8 real;
+
+/* S2D-business */
+
+#define S2D     "S2D_"
+#define S2DLEN  (sizeof(S2D)-1) /* i.e. strlen(S2D) */
+
+#define S2Dlc     "s2d_"
+#define S2DlcLEN  (sizeof(S2Dlc)-1) /* i.e. strlen(S2Dlc) */
+
+#define S2D_all_blanks (0x2020202020202020ull)
+
+typedef union {
+  double dval;
+  u_ll_t llu;
+  uint ival[2];
+  char str[9];
+  char *saddr;
+} S2D_Union;
+
+typedef struct {
+  uint ival[2];
+} S2D_Type;
+
+#define MASK_0           0U  /*                                 0 */
+#define MASK_1           1U  /*                                 1 */
+#define MASK_2           3U  /*                                11 */
+#define MASK_3           7U  /*                               111 */
+#define MASK_4          15U  /*                              1111 */
+#define MASK_5          31U  /*                             11111 */
+#define MASK_6          63U  /*                            111111 */
+#define MASK_7         127U  /*                           1111111 */
+#define MASK_8         255U  /*                          11111111 */
+#define MASK_9         511U  /*                         111111111 */
+#define MASK_10       1023U  /*                        1111111111 */
+#define MASK_11       2047U  /*                       11111111111 */
+#define MASK_12       4095U  /*                      111111111111 */
+#define MASK_13       8191U  /*                     1111111111111 */
+#define MASK_14      16383U  /*                    11111111111111 */
+#define MASK_15      32767U  /*                   111111111111111 */
+#define MASK_16      65535U  /*                  1111111111111111 */
+#define MASK_17     131071U  /*                 11111111111111111 */
+#define MASK_18     262143U  /*                111111111111111111 */
+#define MASK_19     524287U  /*               1111111111111111111 */
+#define MASK_20    1048575U  /*              11111111111111111111 */
+#define MASK_21    2097151U  /*             111111111111111111111 */
+#define MASK_22    4194303U  /*            1111111111111111111111 */
+#define MASK_23    8388607U  /*           11111111111111111111111 */
+#define MASK_24   16777215U  /*          111111111111111111111111 */
+#define MASK_25   33554431U  /*         1111111111111111111111111 */
+#define MASK_26   67108863U  /*        11111111111111111111111111 */
+#define MASK_27  134217727U  /*       111111111111111111111111111 */
+#define MASK_28  268435455U  /*      1111111111111111111111111111 */
+#define MASK_29  536870911U  /*     11111111111111111111111111111 */
+#define MASK_30 1073741823U  /*    111111111111111111111111111111 */
+#define MASK_31 2147483647U  /*   1111111111111111111111111111111 */
+#define MASK_32 4294967295U  /*  11111111111111111111111111111111 */
+
+#define MASK(n) MASK_##n
+
+#define IOR(x,y)   ((x) | (y))
+#define IAND(x,y)  ((x) & (y))
+
+#define ISHFTL(x,n) ((x) << (n))
+#define ISHFTR(x,n) ((x) >> (n))
+
+#define GET_BITS(x, pos, len)      IAND(ISHFTR((int)(x), pos), MASK(len))
+
+#define PUT_BITS(to, x, pos, len) \
+  to = IOR(IAND(to, ~(ISHFTL(MASK(len), pos))), \
+           IAND((int)(x), ISHFTL(MASK(len), pos)))
+
+#define BYTESIZE(x) (x##len * sizeof(*x))
+#define BYTESIZE2(x,elemsize) (x##len * (elemsize))
+
+typedef struct {
+#ifdef LITTLE
+  unsigned int pmethod:8; /* Value 0 .. 255 ; 
+			     0 means not packed;
+			     1,2,3,5,9,11-19,21-29 methods implemented
+			     255 means not really packed, but PCMA-header exists for MDI's */
+
+  unsigned int signbit:1;  /* signed = 1, unsigned = 0 */
+
+  unsigned int byte_swappable:1; /* byte swapping applicable = 1, N/A i.e. raw data = 0 */
+
+  unsigned int precision_bits:6; /* power of 2 for length of data; range = [0..63] bits */
+
+  unsigned int base_type:2; /* other = 0, int = 1, flp = 2, complex flp = 3 
+			       notes: 
+			       - if other, look for other_type
+			       - precion_bits used for length as 2^precision_bits
+			       - if int, check also signed/unsigned part
+			    */
+  
+  unsigned int other_type:14; /* used when base_type == 0 ; currently defined
+				 undefined   = 00 000 000 000 000 =     0 = 0x0
+				 Bitfield    = 00 000 000 000 001 =     1 = 0x1
+				 (note: also precision_bits must be 5 i.e. 2^5 == 32; 
+				 preferably unsigned)
+				 string      = 00 000 000 000 010 =     2 = 0x2 
+				 (note: alias to char(8); 
+				 also precision_bits should be 3 i.e. 2^3 == 8 bytes;
+				 byte_swappable must be == 0 i.e. raw)
+				 yyyymmdd    = 00 000 000 000 100 =     4 = 0x4
+				 (note: preferably unsigned)
+				 hhmmss      = 00 000 000 001 000 =     8 = 0x8
+				 (note: preferably unsigned)
+				 linkoffset_t = 00 000 000 010 000 =    16 = 0x10
+				 (note: preferably unsigned)
+				 linklen_t    = 00 000 000 100 000 =    32 = 0x20
+				 (note: preferably unsigned)
+				 bufr-data   = 00 000 001 000 000 =    64 = 0x40
+				 (note: also byte_swappable must be == 0 i.e. raw;
+				 also precision_bits must be 5 i.e. 2^5 == 32)
+				 grib-data   = 00 000 010 000 000 =   128 = 0x80
+				 (note: also byte_swappable must be == 0 i.e. raw;
+				 also precision_bits must be 5 i.e. 2^5 == 32)
+				 blob        = 00 000 100 000 000 =   256 = 0x100
+				 (note: precision_bits used for length; up to 2^16 bytes; enough ?;
+				 byte_swappable must be == 0 i.e. raw)
+				 long blob   = 00 001 000 000 000 =  512 = 0x200
+				 (note: precision_bits used for length; up to 2^31 bytes; enough ?;
+				 byte_swappable must be == 0 i.e. raw)
+				 char        = 00 010 000 000 000 =  1024 = 0x400
+				 (note: precision_bits used for length;
+				 byte_swappable must be == 0 i.e. raw)
+				 varchar     = 00 100 000 000 000 =  2048 = 0x800
+				 (note: precision_bits used for maximum length;
+				 byte_swappable must be == 0 i.e. raw)
+				 reserved_1  = 01 000 000 000 000 =  4096 = 0x1000
+				 reserved_2  = 10 000 000 000 000 =  8192 = 0x2000
+			      */ 
+#else /* Big endian */
+  unsigned int other_type:14;
+  unsigned int base_type:2;
+  unsigned int precision_bits:6;
+  unsigned int byte_swappable:1;
+  unsigned int signbit:1;
+  unsigned int pmethod:8;
+#endif
+} odb_types_t;
+
+PUBLIC uint get_dtnum(const char *dt);
+PUBLIC  int get_dtsize(const char *dt);
+
+#define EXTRACT_PMETHOD(x)   GET_BITS(x,0,8)
+#define EXTRACT_DATATYPE(x)  GET_BITS(x,8,24)
+#define EXTRACT_SIGNBIT(x)   GET_BITS(x,8,1)
+#define EXTRACT_SWAPPABLE(x) GET_BITS(x,9,1)
+#define EXTRACT_PRECISION(x) GET_BITS(x,10,6)
+#define EXTRACT_BASETYPE(x)  GET_BITS(x,16,2)
+#define EXTRACT_OTHERTYPE(x) GET_BITS(x,18,14)
+
+/* The following is a product of ../tools/typebits.c -program output */
+
+/* signbit=0, byte_swappable=0, precision_bits=0, base_type=0, other_type=0x0 (0) */
+#define DATATYPE_UNDEF                0x0          /* (0 dec) undef */
+
+/* signbit=0, byte_swappable=0, precision_bits=0, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_BIT                  0x100        /* (256 dec) bit : 1 bits, 0 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=3, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_INT1                 0x10f        /* (271 dec) char : 8 bits, 1 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=4, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_INT2                 0x113        /* (275 dec) short : 16 bits, 2 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=5, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_INT4                 0x117        /* (279 dec) int : 32 bits, 4 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=6, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_INT8                 0x11b        /* (283 dec) long long : 64 bits, 8 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=3, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_UINT1                0x10e        /* (270 dec) uchar : 8 bits, 1 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=4, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_UINT2                0x112        /* (274 dec) ushort : 16 bits, 2 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_UINT4                0x116        /* (278 dec) uint : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=6, base_type=1, other_type=0x0 (0) */
+#define DATATYPE_UINT8                0x11a        /* (282 dec) ulonglong : 64 bits, 8 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=2, other_type=0x0 (0) */
+#define DATATYPE_REAL4                0x216        /* (534 dec) float : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=6, base_type=2, other_type=0x0 (0) */
+#define DATATYPE_REAL8                0x21a        /* (538 dec) double : 64 bits, 8 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=7, base_type=2, other_type=0x0 (0) */
+#define DATATYPE_REAL16               0x21e        /* (542 dec) long double : 128 bits, 16 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=6, base_type=3, other_type=0x0 (0) */
+#define DATATYPE_CMPLX4               0x31a        /* (794 dec) complex4 : 64 bits, 8 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=7, base_type=3, other_type=0x0 (0) */
+#define DATATYPE_CMPLX8               0x31e        /* (798 dec) complex8 : 128 bits, 16 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=8, base_type=3, other_type=0x0 (0) */
+#define DATATYPE_CMPLX16              0x322        /* (802 dec) complex16 : 256 bits, 32 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x1 (1) */
+#define DATATYPE_BITFIELD             0x416        /* (1046 dec) Bitfield : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=0, precision_bits=6, base_type=0, other_type=0x2 (2) */
+#define DATATYPE_STRING               0x818        /* (2072 dec) string : 64 bits, 8 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x4 (4) */
+#define DATATYPE_YYYYMMDD             0x1016       /* (4118 dec) yyyymmdd : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x8 (8) */
+#define DATATYPE_HHMMSS               0x2016       /* (8214 dec) hhmmss : 32 bits, 4 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x10 (16) */
+#define DATATYPE_LINKOFFSET           0x4017       /* (16407 dec) linkoffset_t : 32 bits, 4 bytes */
+
+/* signbit=1, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x20 (32) */
+#define DATATYPE_LINKLEN              0x8017       /* (32791 dec) linklen_t : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x40 (64) */
+#define DATATYPE_BUFR                 0x10016      /* (65558 dec) bufr : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=1, precision_bits=5, base_type=0, other_type=0x80 (128) */
+#define DATATYPE_GRIB                 0x20016      /* (131094 dec) grib : 32 bits, 4 bytes */
+
+/* signbit=0, byte_swappable=0, precision_bits=19, base_type=0, other_type=0x100 (256) */
+#define DATATYPE_BLOB                 0x4004c      /* (262220 dec) blob64kB : 65536 bytes */
+
+/* signbit=0, byte_swappable=0, precision_bits=34, base_type=0, other_type=0x200 (512) */
+#define DATATYPE_LONGBLOB             0x80088      /* (524424 dec) blob2GB : 2147483648 bytes */
+
+/* signbit=0, byte_swappable=0, precision_bits=11, base_type=0, other_type=0x400 (1024) */
+#define DATATYPE_CHAR                 0x10002c     /* (1048620 dec) char(1:255) : 256 bytes */
+
+/* signbit=0, byte_swappable=0, precision_bits=11, base_type=0, other_type=0x800 (2048) */
+#define DATATYPE_VARCHAR              0x20002c     /* (2097196 dec) varchar(1:255) : 256 bytes */
+
+#endif
diff --git a/odb/src/include/qtar.h b/odb/src/include/qtar.h
new file mode 100644
index 0000000..6a1730d
--- /dev/null
+++ b/odb/src/include/qtar.h
@@ -0,0 +1,19 @@
+#ifndef _QTAR_H_
+#define _QTAR_H_
+
+/* qtar.h */
+
+#include "odb.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+extern int CloseQTAR(int fd);
+extern int OpenQTAR();
+extern int UpdateQTAR(int fd);
+extern int ExtractQTAR(int fd);
+extern int DeleteQTAR(int fd);
+extern int TocQTAR(int fd);
+extern int QTAR_main(int argc, char *argv[]);
+
+#endif
diff --git a/odb/src/include/regcache.h b/odb/src/include/regcache.h
new file mode 100644
index 0000000..e3078f1
--- /dev/null
+++ b/odb/src/include/regcache.h
@@ -0,0 +1,68 @@
+#ifndef _REGCACHE_H_
+#define _REGCACHE_H_
+
+/* regcache.h */
+
+/* 
+   All common data structures for region searches
+   for use by the gridding of obs in source files:
+
+   1) lib/eq_regions.c
+   2) lib/rgg_regions.c
+*/
+
+typedef enum { eq_cache_kind = 1, rgg_cache_kind = 2 } regcache_kind;
+
+static const char *regcache_names[] = { 
+  "<undef>",
+  "EQ-region", 
+  "Reduced Gaussian Grid",
+  NULL
+};
+
+typedef struct _regcache_t {
+  regcache_kind kind;
+  int n; /* # of eq_regions patches/boxes or rgg_regions Txxxx resolution */
+  int nboxes; /* Actual number of boxes (=n for eq_regions), but calculated for rgg_regions */
+  double resol; /* Approximate resolution in degrees at Equator */
+  int nb; /* number of latitude bands (also known as "ndgl" in rgg_regions.c) */
+  double *latband; /* starting latitudes for each latitude band : size nb+1 */
+  double *midlat; /* mid latitudes for each latitude band : size nb */
+  int *loncnt; /* # of longitude boxes for each latitude band : size nb */
+  int *sum_loncnt; /* Sum of (longitude) boxes BEFORE this latitude band : size nb */
+  double *stlon; /* starting longitudes for each latitude band : size nb */
+  double *deltalon; /* longitudinal delta for each latitude band : size nb */
+  struct {
+    int jb;
+    int lonbox;
+    int boxid;
+    double left, mid, right;
+  } last; /* Results from the last find_latband, find_lonbox */
+  struct _regcache_t *left;
+  struct _regcache_t *right;
+} regcache_t;
+
+extern regcache_t *ODBc_put_regcache(regcache_kind kind,
+				     int n, int nb,
+				     double *latband, double *midlat,
+				     double *stlon, double *deltalon, 
+				     int *loncnt,
+				     regcache_t **(*init_code)(void), regcache_t **regcache);
+
+extern regcache_t **ODBc_init_eq_cache();
+extern regcache_t **ODBc_init_rgg_cache();
+
+extern regcache_t *ODBc_get_rgg_cache(int Txxxx);
+extern regcache_t *ODBc_get_eq_cache(int n);
+
+extern int ODBc_get_boxid(double lat, double lon, int n,
+			  regcache_t *ptr, regcache_t *(*get_cache)(int));
+
+extern double ODBc_get_boxlon(double lat, double lon, double rn,
+			      regcache_t *(*get_cache)(int));
+
+extern double ODBc_get_boxlat(double lat, double lon, double rn,
+			      regcache_t *(*get_cache)(int));
+
+#endif
+
diff --git a/odb/src/include/result.h b/odb/src/include/result.h
new file mode 100644
index 0000000..d201fa1
--- /dev/null
+++ b/odb/src/include/result.h
@@ -0,0 +1,134 @@
+#ifndef _RESULT_H_
+#define _RESULT_H_
+
+/* result.h */
+
+#include "info.h"
+
+/* See info.h for reason why we re-#define the result_t */
+
+#define result_t ODB_result_t
+#define uresult_t ODB_uresult_t
+#define colinfo_t ODB_colinfo_t
+
+typedef struct _result_t {
+  double *mem; /* Allocated (contiguous) memory */
+  int nmem;    /* Number of words allocated for *mem :
+		  nra * nrows_in for row_wise == true
+		  nra * ncols_in for row_wise == false */
+  double **d;  /* 2D-array representation of "mem" */
+  Bool row_wise; /* data in **d row-wise major when "true", else column-wise (Fortran) */
+  int nrows_in;  /* This many rows upon entering ODBc_get_data, usually info->idxlen */
+  int ncols_in;  /* This many columns upon entering ODBc_get_data, usually info->ncols */
+  int nra;       /* Leading dimension of **d
+		    ODBc_lda(ncols_in) for row_wise == true
+		    ODBc_lda(nrows_in) for row_wise == false */
+  int nrows_out; /* Number of rows upon exiting ODBc_get_data <= nrows_in */
+  int ncols_out; /* Number of cols upon exiting ODBc_get_data <= ncols_in */
+  int poolno;    /* The pool number in concern */
+  info_t *info;  /* Based on this SQL info-structure */
+  Bool backup;   /* if "true", then each individual report goes to a backup_file */
+  char *backup_file;
+  unsigned int typeflag; /* up to MAXBITS columns ; used in context of typeflag of idx.h */
+  struct _result_t *next; /* Next result in chain, if applicable */
+} result_t;
+
+
+typedef union {
+  void *parse_tree; /* Parse-tree that replaces EvalMe(S2D_<n>) */
+  result_t *res;
+  double alias;
+  int i[2];
+} uresult_t;
+
+
+typedef struct _colinfo_t {
+  int id;
+  char *name;
+  char *nickname;
+  char *type_name; /* 19/01/2009 AF typename cannot be used in C++ */
+  uint dtnum;
+} colinfo_t;
+
+extern void * /* Returns possibly modified dataset & no. of rows printed in *iret */
+ODBc_print_data(const char *filename, FILE *fp, void *Result, 
+		const char *format, const char *fmt_string,
+		int konvert, int write_title, int joinstr,
+		int the_first_print, int the_final_print, 
+		int *iret);
+
+extern FILE *
+ODBc_print_file(FILE *fp_out, int *fpunit,
+		const char *outfile, const char *format,
+		int poolno, const char *view,
+		Bool first_time,
+		Bool *Reopen_per_view,
+		Bool *Reopen_per_pool,
+		Bool *Use_gzip_pipe); /* Returns old fp_out, re-opened fp_out or NULL */
+
+extern void *  /* Returns a ptr to result_t upon success */
+ODBc_get_data(int handle, void *Result, void *Info, int poolno, 
+	      int begin_row, int end_row, 
+	      Bool do_sort, const Bool *row_wise_preference);
+
+extern void *ODBc_get_data_from_binary_file(const char *filename, Boolean sort_unique);
+
+extern void *ODBc_unget_data(void *Result); /* Returns NULL */
+
+extern int ODBc_lda(int m, int method); /* Returns "leading dimension of 'a'" i.e. value >= m */
+
+extern void *   /* sorts + merges the result-chain and returns new result */
+ODBc_sort(void *Result, const int Keys_override[], int Nkeys_override);
+
+extern void *   /* Manipulates the result-chain according to the whatkey */
+ODBc_operate(void *Result, const char *whatkey);
+
+extern void *ODBc_aggr(void *Result, int phase_id); /* creates result set for aggregate funcs */
+
+extern void * /* Removes duplicates from the given key ("Fortran") -columns and returns
+		 a reduced working set */
+ODBc_remove_duplicates(void *Result, const int keys[], int n_keys);
+
+extern Bool ODBc_set_kolor_map(const char *cmapfile);
+extern Bool ODBc_get_kolor_map(float *value_min, float *value_max, float scale[], 
+			       char *text, int textlen);
+
+extern void ODBc_set_format(const char *format);
+extern Bool ODBc_test_format_1(const char *test_format);
+extern Bool ODBc_test_format_2(const char *format, const char *test_format);
+extern Bool ODBc_test_format_3(const char *format, const char *test_format, int len);
+
+extern Bool ODBc_nothing_to_plot(void *Info);
+extern int ODBc_ODBtool(FILE *fpin, int *fpunit,
+			const char *file, Bool ascii, void *Result, void *Info);
+
+extern void ODBc_DebugPrintRes(const char *when, const result_t *r);
+
+/* Create new result_t set */
+extern void *ODBc_new_res(const char *label, const char *file, int lineno,
+			  int nrows, int ncols, void *Info, Bool row_wise, int poolno);
+
+/* Merge one or more result_t sets into one and make them "row_wise" */
+extern void *ODBc_merge_res(const char *label, const char *file, int lineno,
+			    void *Res, int ncols, void *Info, Bool row_wise);
+
+/* Convert to degrees, if applicable */
+
+extern int ODBc_conv2degrees(void *Res, Bool to_degrees);
+
+/* from lib/eq_regions.c */
+
+extern int ODBc_bsearch(const double key,
+			const int n, 
+			const double x[ /* with n elements */ ],
+			const double sign /* +1 forward and -1 for reverse search */);
+
+extern int ODBc_interval_bsearch(const double key, 
+				 const int n, 
+				 const double x[ /* with n+1 elements */ ],
+				 const double *delta, /* if present, only x[0] will be used */
+				 const double add,
+				 const double sign /* +1 forward and -1 for reverse search */);
+
+#endif /* _RESULT_H_ */
+
diff --git a/odb/src/include/setodbcs.h b/odb/src/include/setodbcs.h
new file mode 100644
index 0000000..4a6e358
--- /dev/null
+++ b/odb/src/include/setodbcs.h
@@ -0,0 +1,37 @@
+#ifndef _SETODBCS_H_
+#define _SETODBCS_H_
+
+/* setodbcs.h */
+
+/* To set up the ODBCS-option properly */
+
+#undef TEST_ODBCS
+
+#ifdef ODBCS
+
+#define TEST_ODBCS ODBCS
+
+#else 
+
+/* Add new ARCH here (defined(ARCH)) after checking their implementation on 
+   TCP/IP & IPv4 communication exists.
+   The new ARCH will then be automatically supported */
+
+#if (defined(LINUX) && !defined(CRAYXT)) || defined(RS6K) || defined(SUN4) || defined(HPPA) || defined(SGI)
+#define TEST_ODBCS 1
+#else
+#define TEST_ODBCS 0
+#endif
+
+#endif /* ODBCS */
+
+#if TEST_ODBCS == 0
+#undef ODBCS
+#else
+#undef ODBCS
+#define ODBCS 1
+#endif
+
+#undef TEST_ODBCS
+
+#endif /* _SETODBCS_H_ */
diff --git a/odb/src/include/static.h b/odb/src/include/static.h
new file mode 100644
index 0000000..fdf2762
--- /dev/null
+++ b/odb/src/include/static.h
@@ -0,0 +1,96 @@
+#include "odb.h"
+
+/* Generic entry points for every recognized database */
+
+#if defined(DUMMY_STATIC_INIT)
+
+/* Dummies */
+
+#define Dummy_Static_Init(db) \
+void \
+db##_static_init() \
+{ \
+  char *msg = #db "_static_init(): You were not supposed to call this routine"; \
+  int len = strlen(msg); \
+  fprintf(stderr,"%s\n",msg); \
+  codb_abort_func_(msg,len); \
+} \
+\
+void \
+db##_print_flags_file() \
+{ \
+  char *msg = #db "_print_flags_file(): You were not supposed to call this routine"; \
+  int len = strlen(msg); \
+  fprintf(stderr,"%s\n",msg); \
+  codb_abort_func_(msg,len); \
+}
+
+#else 
+
+/* Non-dummies */
+
+#define Static_Init(db) if (strequ(p_dbname, #db)) { \
+  extern void db##_static_init(); \
+  ODB_add2funclist(#db, db##_static_init, 0); \
+}
+
+#if !defined(STATIC_C)
+PUBLIC void
+codb_set_entrypoint_(const char *dbname
+		     /* Hidden arguments */
+		     , int dbname_len) 
+     /* Fortran callable */
+{
+  DECL_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(dbname);
+
+#if !defined(CODB_SET_ENTRYPOINT_C)
+  /* Using sed-command, define _MYDB_ and filter this file to produce an additional 
+     entry point to your suit own database needs. 
+
+     For example, database XYZ, do the following:
+
+     (1) sed 's/_MYDB_/XYZ/' < $INCDIR/static.h > glue.c
+     (2) cc -c -I$INCDIR [cflags] glue.c
+     (3) f90 [linkerflags] mainprog.o glue.o -lodb -lXYZ [other_libs] -o a.out
+
+     If you need more than just one new database to be introduced, you
+     have to be more elaborate with the sed-command. For two databases,
+     for instance XYZ & ABC, do the following:
+
+     (1) sed 's/_MYDB_)/XYZ);Static_Init(ABC)/' < $INCDIR/static.h > glue.c
+     (2) cc -c -I$INCDIR [cflags] glue.c
+     (3) f90 [linkerflags] mainprog.o glue.o -lodb -lXYZ -lABC [other_libs] -o a.out
+
+     For more than two databases: just alter the sed-command's filter accordingly!
+
+     Examples assume that you have already managed to create libXYZ.a & libABC.a
+     from XYZ.ddl & ABC.ddl, respectively.
+
+     $INCDIR is the location of general include-files, say /ccvobs/odb/include.
+
+     cc & f90 are C and Fortran90 compilers of a particular computer system and
+     needs to be adjusted to suit your needs.
+  */
+  Static_Init(_MYDB_);
+#endif /* if !defined(CODB_SET_ENTRYPOINT_C) */
+
+  /* Recognized databases (add database entries as required) */
+
+  /* Please check that for given database ABC you also have the dummy
+     file ABC_static_init.c -- contents similar to the ECMA_static_init.c */
+
+#if 0
+  /* No predefined libs as of 11-Apr-2006/SS i.e. all libs as important */
+  Static_Init(ECMA);
+  Static_Init(ECMASCR);
+  Static_Init(CCMA);
+  Static_Init(MTOCOMP);
+  Static_Init(PREODB);
+#endif
+
+  FREE_FTN_CHAR(dbname);
+}
+#endif /* if !defined(STATIC_C) */
+
+#endif /* if defined(DUMMY_STATIC_INIT) ... else ... */
diff --git a/odb/src/include/swapbytes.h b/odb/src/include/swapbytes.h
new file mode 100644
index 0000000..4d30ce8
--- /dev/null
+++ b/odb/src/include/swapbytes.h
@@ -0,0 +1,52 @@
+/* swapbytes.h */
+
+#ifndef _SWAPBYTES_H_
+#define _SWAPBYTES_H_
+
+#include "privpub.h"
+
+/* Swap bytes : Thanks to Linux-file "/usr/include/bits/byteswap.h" for cleaness ;-) */
+
+/* Swap bytes in 8 bit value == does nothing; for convenience  */
+#define bswap8bits(x) (x)
+
+/* Swap bytes in 16 bit value.  */
+#define bswap16bits(x) \
+     (  (((x) >> 8) & 0xff) \
+      | (((x) & 0xff) << 8) )
+
+/* Swap bytes in 32 bit value.  */
+#define bswap32bits(x) \
+     (  (((x) & 0xff000000) >> 24) \
+      | (((x) & 0x00ff0000) >>  8) \
+      | (((x) & 0x0000ff00) <<  8) \
+      | (((x) & 0x000000ff) << 24) )
+
+/* Swap bytes in 64 bit value.  */
+#define bswap64bits(x) \
+     (  (((x) & 0xff00000000000000ull) >> 56) \
+      | (((x) & 0x00ff000000000000ull) >> 40) \
+      | (((x) & 0x0000ff0000000000ull) >> 24) \
+      | (((x) & 0x000000ff00000000ull) >>  8) \
+      | (((x) & 0x00000000ff000000ull) <<  8) \
+      | (((x) & 0x0000000000ff0000ull) << 24) \
+      | (((x) & 0x000000000000ff00ull) << 40) \
+      | (((x) & 0x00000000000000ffull) << 56) )
+
+extern void swap1bytes_
+            (void *v, const int *vlen); /* 8-bit/1-byte word swap : does nothing; for convenience */
+
+extern void swap2bytes_
+            (void *v, const int *vlen); /* 16-bit/2-byte word swap */
+
+extern void swap4bytes_
+            (void *v, const int *vlen); /* 32-bit/4-byte word swap */
+
+extern void swap8bytes_
+            (void *v, const int *vlen); /* 64-bit/8-byte word swap */
+
+extern void
+swapANYbytes(void *v, int elsize, int n, unsigned int dtype, 
+	     const char *dtype_name, const char *varname);
+
+#endif /* _SWAPBYTES_H_ */
diff --git a/odb/src/include/symtab.h b/odb/src/include/symtab.h
new file mode 100644
index 0000000..b4ac59c
--- /dev/null
+++ b/odb/src/include/symtab.h
@@ -0,0 +1,28 @@
+#ifndef _SYMTAB_H_
+#define _SYMTAB_H_
+
+/* symtab.h */
+
+typedef struct _symtab_t {
+  /* Binary tree */
+  char *name;
+  Bool active;
+  double value;
+  double *vec;
+  int nvec;
+  struct _symtab_t *left;  /* strcmp() > 0 */
+  struct _symtab_t *right; /* strcmp() < 0 */
+} symtab_t;
+
+extern void initsym();
+extern double *putsym(const char *s, double value);
+extern double *putsymvec(const char *s, double value, double *vec, int nvec);
+extern double  getsym(const char *s, Bool *on_error);
+extern double *getsymaddr(const char *s);
+extern double *getsymvec(const char *s, int *nvec);
+extern void printsym(void *fp, int it);
+extern double delsym(const char *s, int it);
+extern void delallsym(const int *specific_it);
+extern symtab_t *getsymtab(const char *s);
+
+#endif /* _SYMTAB_H_ */
diff --git a/odb/src/include/vparam.h b/odb/src/include/vparam.h
new file mode 100644
index 0000000..124febd
--- /dev/null
+++ b/odb/src/include/vparam.h
@@ -0,0 +1,12 @@
+#ifndef _VPARAM_H_
+#define _VPARAM_H_
+
+#include <stdarg.h>
+
+/* odbi_client.c */
+
+void Vparam(void *v, int is_a_query, char *fmt, va_list ap);
+
+#endif /* _VPARAM_H_ */
+
+
diff --git a/odb/src/interface/append_num.h b/odb/src/interface/append_num.h
new file mode 100644
index 0000000..c9bc754
--- /dev/null
+++ b/odb/src/interface/append_num.h
@@ -0,0 +1,11 @@
+INTERFACE
+SUBROUTINE append_num(cdout, cdin, knum, cdelim, kdoutlen)
+USE PARKIND1  ,ONLY : JPIM
+implicit none
+character(len=*), intent(out) :: cdout
+character(len=*), intent(in) :: cdin
+character(len=*), intent(in), OPTIONAL :: cdelim
+INTEGER(KIND=JPIM), intent(in) :: knum
+INTEGER(KIND=JPIM), intent(out), OPTIONAL :: kdoutlen
+END SUBROUTINE append_num
+END INTERFACE
diff --git a/odb/src/interface/apply_poolmasking.h b/odb/src/interface/apply_poolmasking.h
new file mode 100644
index 0000000..007ec78
--- /dev/null
+++ b/odb/src/interface/apply_poolmasking.h
@@ -0,0 +1,13 @@
+INTERFACE
+SUBROUTINE apply_poolmasking(khandle, kversion, &
+                             cdlabel, kvlabel, &
+                             ktslot, kobstype, kcodetype, ksensor, &
+                             ksubtype, kbufrtype, ksatinst)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: khandle, kversion, kvlabel
+character(len=*), intent(in) :: cdlabel
+INTEGER(KIND=JPIM), intent(in) :: ktslot, kobstype, kcodetype, ksensor
+INTEGER(KIND=JPIM), intent(in) :: ksubtype, kbufrtype, ksatinst
+END SUBROUTINE apply_poolmasking
+END INTERFACE
diff --git a/odb/src/interface/bsslzr_odb.h b/odb/src/interface/bsslzr_odb.h
new file mode 100644
index 0000000..0284b30
--- /dev/null
+++ b/odb/src/interface/bsslzr_odb.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE BSSLZR_ODB(PBES,KNUM)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(in) :: KNUM
+REAL(KIND=JPRB), intent(out)   :: PBES(KNUM)
+END SUBROUTINE BSSLZR_ODB
+END INTERFACE
diff --git a/odb/src/interface/ckeysort.h b/odb/src/interface/ckeysort.h
new file mode 100644
index 0000000..883424b
--- /dev/null
+++ b/odb/src/interface/ckeysort.h
@@ -0,0 +1,16 @@
+SUBROUTINE ckeysort(pa, kra, krows, kcols, &
+                   & keys, k_nkeys, &
+                   & kidx, k_nidx, k_init_idx, &
+                   & kret)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)    :: kra, krows, kcols, k_nkeys, k_nidx, k_init_idx
+REAL(KIND=JPRB), intent(inout)    :: pa(kra, kcols)
+INTEGER(KIND=JPIM), intent(in)    :: keys(k_nkeys)
+INTEGER(KIND=JPIM), intent(inout) :: kidx(k_nidx)
+INTEGER(KIND=JPIM), intent(out)   :: kret
+
+END SUBROUTINE ckeysort
diff --git a/odb/src/interface/create_iomap.h b/odb/src/interface/create_iomap.h
new file mode 100644
index 0000000..acd2c5b
--- /dev/null
+++ b/odb/src/interface/create_iomap.h
@@ -0,0 +1,12 @@
+SUBROUTINE create_iomap(khandle, kfirst_call, kmaxpools, &
+ & kpoff, kfblk, cdfile, kgrpsize, &
+ & ktblno, cdtbl, &
+ & kpoolno, kfileno, koffset, klength, krows, kcols, &
+ & kret) 
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle, kfblk, kpoff, kgrpsize, krows, kcols
+INTEGER(KIND=JPIM), intent(in)  :: kfirst_call, kmaxpools
+INTEGER(KIND=JPIM), intent(in)  :: ktblno, kpoolno, kfileno, koffset, klength
+INTEGER(KIND=JPIM), intent(out) :: kret
+END SUBROUTINE create_iomap
diff --git a/odb/src/interface/create_statid.h b/odb/src/interface/create_statid.h
new file mode 100644
index 0000000..4d4b2a6
--- /dev/null
+++ b/odb/src/interface/create_statid.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE CREATE_STATID(CDSTATID,kstatid)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+character(len=*), intent(in) :: CDSTATID
+INTEGER(KIND=JPIM), intent(out) :: kstatid
+END SUBROUTINE CREATE_STATID
+END INTERFACE
diff --git a/odb/src/interface/fodb_checkviewreg.h b/odb/src/interface/fodb_checkviewreg.h
new file mode 100644
index 0000000..7d9de50
--- /dev/null
+++ b/odb/src/interface/fodb_checkviewreg.h
@@ -0,0 +1,10 @@
+INTERFACE
+SUBROUTINE fODB_checkviewreg(khandle, cdview, kret, using)
+USE PARKIND1  ,ONLY : JPIM
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: khandle
+character(len=*), intent(in) :: cdview
+INTEGER(KIND=JPIM), intent(out) :: kret
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+END SUBROUTINE fODB_checkviewreg
+END INTERFACE
diff --git a/odb/src/interface/fwrite_iomap.h b/odb/src/interface/fwrite_iomap.h
new file mode 100644
index 0000000..cc2f300
--- /dev/null
+++ b/odb/src/interface/fwrite_iomap.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE fwrite_iomap(khandle, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)    :: khandle
+INTEGER(KIND=JPIM), intent(out)   :: kret
+END SUBROUTINE fwrite_iomap
+END INTERFACE
diff --git a/odb/src/interface/gauaw_odb.h b/odb/src/interface/gauaw_odb.h
new file mode 100644
index 0000000..e46e813
--- /dev/null
+++ b/odb/src/interface/gauaw_odb.h
@@ -0,0 +1,7 @@
+SUBROUTINE GAUAW_ODB(PA,PW,K,KRET)
+USE PARKIND1  ,ONLY : JPIM,JPRB
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(in)  :: K
+REAL(KIND=JPRB), intent(out)    :: PA(K),PW(K)
+INTEGER(KIND=JPIM), intent(out) :: KRET
+END SUBROUTINE GAUAW_ODB
diff --git a/odb/src/interface/iolockdb.h b/odb/src/interface/iolockdb.h
new file mode 100644
index 0000000..24fd1eb
--- /dev/null
+++ b/odb/src/interface/iolockdb.h
@@ -0,0 +1,5 @@
+SUBROUTINE iolockdb(konoff)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: konoff
+END SUBROUTINE iolockdb
diff --git a/odb/src/interface/lnkdb.h b/odb/src/interface/lnkdb.h
new file mode 100644
index 0000000..188ed64
--- /dev/null
+++ b/odb/src/interface/lnkdb.h
@@ -0,0 +1,7 @@
+SUBROUTINE lnkdb(kparent, kpa, kchild, kch, klink, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: kpa, kch
+INTEGER(KIND=JPIM), intent(in)  :: kparent(kpa), kchild(kch)
+INTEGER(KIND=JPIM), intent(out) :: klink(kpa+1), kret
+END SUBROUTINE lnkdb
diff --git a/odb/src/interface/lnkdb2.h b/odb/src/interface/lnkdb2.h
new file mode 100644
index 0000000..f5329cd
--- /dev/null
+++ b/odb/src/interface/lnkdb2.h
@@ -0,0 +1,10 @@
+SUBROUTINE lnkdb2(koffset, &
+                  karr_in, klda, krows, kcol1, kcol2, &
+                  ktarget, karr_out)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: koffset
+INTEGER(KIND=JPIM), intent(in)  :: klda, krows, kcol1, kcol2, ktarget
+INTEGER(KIND=JPIM), intent(in)  :: karr_in(klda, kcol1:kcol2)
+INTEGER(KIND=JPIM), intent(out) :: karr_out(krows + 1)
+END SUBROUTINE lnkdb2
diff --git a/odb/src/interface/msgpass_loaddata.h b/odb/src/interface/msgpass_loaddata.h
new file mode 100644
index 0000000..5f2dea4
--- /dev/null
+++ b/odb/src/interface/msgpass_loaddata.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE msgpass_loaddata(khandle, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+END SUBROUTINE msgpass_loaddata
+END INTERFACE
diff --git a/odb/src/interface/msgpass_loadobs.h b/odb/src/interface/msgpass_loadobs.h
new file mode 100644
index 0000000..3304a86
--- /dev/null
+++ b/odb/src/interface/msgpass_loadobs.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE msgpass_loadobs(khandle, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+END SUBROUTINE msgpass_loadobs
+END INTERFACE
diff --git a/odb/src/interface/msgpass_storedata.h b/odb/src/interface/msgpass_storedata.h
new file mode 100644
index 0000000..24c8842
--- /dev/null
+++ b/odb/src/interface/msgpass_storedata.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE msgpass_storedata(khandle, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+END SUBROUTINE msgpass_storedata
+END INTERFACE
diff --git a/odb/src/interface/msgpass_storeobs.h b/odb/src/interface/msgpass_storeobs.h
new file mode 100644
index 0000000..2b90ad8
--- /dev/null
+++ b/odb/src/interface/msgpass_storeobs.h
@@ -0,0 +1,8 @@
+INTERFACE
+SUBROUTINE msgpass_storeobs(khandle, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+END SUBROUTINE msgpass_storeobs
+END INTERFACE
diff --git a/odb/src/interface/rlnkdb.h b/odb/src/interface/rlnkdb.h
new file mode 100644
index 0000000..c8bb915
--- /dev/null
+++ b/odb/src/interface/rlnkdb.h
@@ -0,0 +1,9 @@
+INTERFACE
+SUBROUTINE rlnkdb(parent, kpa, pchild, kch, klink, kret)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: kpa, kch
+REAL(KIND=JPRB),    intent(in)  :: parent(:), pchild(:)
+INTEGER(KIND=JPIM), intent(out) :: klink(:), kret
+END SUBROUTINE rlnkdb
+END INTERFACE
diff --git a/odb/src/interface/rlnkdb2.h b/odb/src/interface/rlnkdb2.h
new file mode 100644
index 0000000..9c6834f
--- /dev/null
+++ b/odb/src/interface/rlnkdb2.h
@@ -0,0 +1,12 @@
+INTERFACE
+SUBROUTINE rlnkdb2(koffset, &
+                  parr_in, klda, krows, kcol1, kcol2, &
+                  ktarget, karr_out)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: koffset
+INTEGER(KIND=JPIM), intent(in)  :: klda, krows, kcol1, kcol2, ktarget
+REAL(KIND=JPRB)   , intent(in)  :: parr_in(klda, kcol1:kcol2)
+INTEGER(KIND=JPIM), intent(out) :: karr_out(krows + 1)
+END SUBROUTINE rlnkdb2
+END INTERFACE
diff --git a/odb/src/interface/uniquenumdb.h b/odb/src/interface/uniquenumdb.h
new file mode 100644
index 0000000..7f3b1dc
--- /dev/null
+++ b/odb/src/interface/uniquenumdb.h
@@ -0,0 +1,11 @@
+INTERFACE
+SUBROUTINE uniquenumdb(p, kldim, kvals, klen, keff)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: klen, kldim, kvals
+REAL(KIND=JPRB),    intent(in)  :: p(kldim, klen)
+INTEGER(KIND=JPIM), intent(out) :: keff
+END SUBROUTINE uniquenumdb
+END INTERFACE
diff --git a/odb/src/lib/CMakeLists.txt b/odb/src/lib/CMakeLists.txt
new file mode 100644
index 0000000..0553e7e
--- /dev/null
+++ b/odb/src/lib/CMakeLists.txt
@@ -0,0 +1,83 @@
+list(APPEND lib_files
+
+    lib/ae_dump.c
+    lib/aggr.c
+    lib/alist.c
+    lib/append_num.F90
+    lib/apply_poolmasking.F90
+    lib/bsslzr_odb.F90
+    lib/ckeysort.F90
+    lib/cmdbkeys.c
+    lib/codb.c
+    lib/codb_distribute.F90
+    lib/codb_truename.c
+    lib/cread_iomap.c
+    lib/create_iomap.F90
+    lib/create_statid.F90
+    lib/ctransfer.c
+    lib/ctx.c
+    lib/datastream.F90
+    lib/dynlink.c
+    lib/eq_regions.c
+    lib/errtrap.c
+    lib/evaluate.c
+    lib/fodb_checkviewreg.F90
+    lib/fodb_propagate_env.F90
+    lib/forfunc.c
+    lib/funcs.c
+    lib/fwrite_iomap.F90
+    lib/gauaw_odb.F90
+    lib/hashing.c
+    lib/infile.c
+    lib/init_region.c
+    lib/inside.c
+    lib/iolockdb.F90
+    lib/lnkdb.F90
+    lib/lnkdb2.F90
+    lib/msgpass_loaddata.F90
+    lib/msgpass_loadobs.F90
+    lib/msgpass_storedata.F90
+    lib/msgpass_storeobs.F90
+    lib/odb_array_dump.F90
+    lib/orlist.c
+    lib/peinfo.c
+    lib/poolmasking.c
+    lib/poolreg.c
+    lib/prt.c
+    lib/random_odb.c
+    lib/rgg_regions.c
+    lib/rlnkdb.F90
+    lib/rlnkdb2.F90
+    lib/rot.c
+    lib/rsort32_odb.c
+    lib/savelist.c
+    lib/setup_sort.c
+    lib/solar.c
+    lib/stack.c
+    lib/static.c
+    lib/symtab.c
+    lib/tracing.c
+    lib/twindow.c
+    lib/uniquenumdb.F90
+    lib/var.c
+    lib/vecloops.c
+    lib/version.c
+    lib/wildcard.c
+    lib/write_ddl.c
+)
+
+set(odb_lib_files ${lib_files} PARENT_SCOPE)
+
+list(APPEND _odb_dummy_sources
+
+    Dummies.c
+    Codb_set_entrypoint.c
+    Ctxprint.F90
+    Dummyprofile_newio.c
+)
+
+ecbuild_add_library(TARGET odbdummy
+    TYPE ${ODB_LIBS_TYPE}
+    PRIVATE_INCLUDES ${ODB_INCLUDE_DIRS}
+    SOURCES ${_odb_dummy_sources}
+    LIBS odbifsaux)
diff --git a/odb/src/lib/Codb_set_entrypoint.c b/odb/src/lib/Codb_set_entrypoint.c
new file mode 100644
index 0000000..1ec2206
--- /dev/null
+++ b/odb/src/lib/Codb_set_entrypoint.c
@@ -0,0 +1,4 @@
+/* Codb_set_entrypoint.c : Must go to libodbdummy.a */
+
+#define CODB_SET_ENTRYPOINT_C
+#include "static.h"
diff --git a/odb/src/lib/Ctxprint.F90 b/odb/src/lib/Ctxprint.F90
new file mode 100644
index 0000000..4d2762e
--- /dev/null
+++ b/odb/src/lib/Ctxprint.F90
@@ -0,0 +1,9 @@
+SUBROUTINE ctxprint(print_it, msg, dbname)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+!-- A dummy context print for IFS-independent libodbcore
+implicit none
+INTEGER(KIND=JPIM)       , intent(in) :: print_it
+character(len=*), intent(in) :: msg, dbname
+END SUBROUTINE ctxprint
diff --git a/odb/src/lib/Dummies.c b/odb/src/lib/Dummies.c
new file mode 100644
index 0000000..dc324e4
--- /dev/null
+++ b/odb/src/lib/Dummies.c
@@ -0,0 +1,385 @@
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+/* General do-nothing routine */
+
+void 
+Dummies() { }
+
+#ifdef NEED_PB_ROUTINES
+/* In case PB-routines are still involved ... */
+
+FILE *
+pbfp()
+{
+  fprintf(stderr,"pbfp()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+  return NULL;
+}
+
+void
+pbopen_()
+{
+  fprintf(stderr,"pbopen_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+
+void
+pbclose_()
+{
+  fprintf(stderr,"pbclose_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+
+void
+pbread_()
+{
+  fprintf(stderr,"pbread_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+
+void
+pbread2_()
+{
+  fprintf(stderr,"pbread2_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+
+void
+pbwrite_()
+{
+  fprintf(stderr,"pbwrite_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+
+void
+pbbufr_()
+{
+  fprintf(stderr,"pbbufr_()@%s: You were not supposed to call this routine\n",__FILE__);
+  raise(SIGABRT);
+}
+#endif /* NEED_PB_ROUTINES */
+
+/* Some dirty hacks to get the F90-level working */
+
+void 
+codb_getenv_(const char *s, 
+	     char *value,
+	     /* Hidden arguments */
+	     int slen,
+	     const int valuelen) 
+{
+  char *env = NULL;
+  char *p = malloc(slen+1);
+  if (!p) {
+    fprintf(stderr,"codb_getenv_(): Unable to allocate %d bytes of memory\n", slen+1);
+    raise(SIGABRT);
+  }
+  memcpy(p,s,slen); 
+  p[slen]='\0';
+  memset(value, ' ', valuelen);
+  env = getenv(p);
+  if (env) {
+    int len = strlen(env);
+    if (valuelen < len) len = valuelen;
+    memcpy(value,env,len); 
+  }
+  free(p);
+}
+
+void
+codb_getcwd_(char *s, 
+	     /* Hidden arguments */
+	     int slen)
+{ /* Get current working directory */
+  if (!getcwd(s,slen)) {
+    perror("getcwd");
+    memset(s,' ',slen);
+  }
+  else {
+    int len = strlen(s);
+    if (len < slen) memset(&s[len],' ',slen-len);
+  }
+}
+
+void 
+codb_putenv_(const char *s, 
+	     /* Hidden argument */
+	     int slen) 
+{
+  const char *x = &s[slen-1];
+  /* strip trailing blanks first */
+  while (slen > 0 && *x-- == ' ') { slen--; }
+  /* now go ahead */
+  {
+    char *p = malloc(slen+1);
+    if (!p) {
+      fprintf(stderr,"codb_putenv_(): Unable to allocate %d bytes of memory\n", slen+1);
+      raise(SIGABRT);
+    }
+    memcpy(p,s,slen); 
+    p[slen]='\0';
+    putenv(p); 
+    /* Cannot free(p); , since putenv() uses this memory area for good ;-( */
+  }
+}
+
+void
+codb_pause_() 
+{ 
+#if !defined(CRAYXT)
+  (void) pause(); 
+#endif
+}
+
+void 
+codb_raise_(const int *sig)
+{
+  raise(*sig);
+}
+
+void 
+codb_sleep_(const int *seconds)
+{
+  (void) sleep(*seconds);
+}
+
+void
+codb_usleep_(const int *usecs)
+{
+  if (usecs && *usecs > 0) {
+    struct timeval t;
+    t.tv_sec =  (*usecs)/1000000;
+    t.tv_usec = (*usecs)%1000000;
+    (void) select(0, NULL, NULL, NULL, &t);
+  }
+}
+
+void
+codb_wait_(const int *pid, const int *nohang, int *rc)
+{
+  /* CALL CODB_WAIT(-1, 1, iret)   ! Wait any (child) process-id to finish, but do not hang/block */
+  /* CALL CODB_WAIT(ipid, 0, iret) ! Wait until process-id ipid to finished */
+  /* 
+   *rc contains the process-id that has finished, 
+   or -1 in error 
+   or 0 if no-hang was used but process has not yet finished
+  */
+  int status;
+#ifdef CRAYXT
+  *rc = -1;
+#else
+  if (*nohang) {
+    *rc = waitpid(*pid, &status, WNOHANG);
+  }
+  else {
+    *rc = waitpid(*pid, &status, 0);
+  }
+#endif
+  if (*rc < 0) {
+    fprintf(stderr,
+	    "***Error in codb_wait_(pid=%d, nohang=%d) --> retcode = %d\n",
+	    *pid, *nohang, *rc);
+  }
+}
+
+void 
+codb_subshell_(const char *cmd, int *pid
+	       /* Hidden argument */
+	       ,int cmdlen) 
+{
+#ifdef CRAYXT
+  *pid = -1;
+#else
+  *pid = fork();
+  if (*pid == 0) { /* slave process */
+    char *s = malloc(cmdlen+1);
+    int rc;
+    memcpy(s,cmd,cmdlen);
+    s[cmdlen] = '\0';
+    rc = system(s);
+    fflush(stdout);
+    fflush(stderr);
+    free(s);
+    _exit(rc);
+    /* end of slave process */
+  }
+#endif
+  else if (*pid < 0) {
+    /* parent only process : unable to fcuk */
+    fprintf(stderr,
+	    "***Error in codb_subshell_('%*.*s'): Unable to fork --> retcode = %d\n",
+	    cmdlen,cmdlen,cmd,*pid);
+  }
+  else {
+    /* parent only process : check if exited already ; try to gather the exit-code (usually non-zero) */
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+    /* Check if near-immediate abort has occurred */
+    int ret, status = 0;
+    const int usecs = 200000; /* 0.2sec i.e. 200,000 microsecs nap */
+    codb_usleep_(&usecs);
+    ret = waitpid(*pid, &status, WNOHANG);
+    if (ret == *pid) {
+      if (WIFEXITED(status)) {
+	ret = WEXITSTATUS(status);
+	if (ret != 0) {
+	  fprintf(stderr,
+		  "***Error in codb_subshell_('%*.*s') : exited nearly immediately --> retcode = %d (status = %d)\n",
+		  cmdlen,cmdlen,cmd,ret,status);
+	  *pid = -abs(ret);
+	}
+	else
+	  *pid = 0;
+      } /* if (WIFEXITED(status)) */
+    } /* if (ret == *pid) */
+#endif
+  }
+}
+
+void
+codb_system_(const char *s
+	     /* Hidden argument */
+	     ,int slen) 
+{
+  char *p = malloc(slen+1);
+  if (!p) {
+    fprintf(stderr,"codb_system_(): Unable to allocate %d bytes of memory\n", slen+1);
+    raise(SIGABRT);
+  }
+  memcpy(p,s,slen); 
+  p[slen]='\0';
+#ifdef CRAYXT
+  fprintf(stderr,"codb_system_(): Not implemented system(%s)\n",p);
+#else
+  (void) system(p); 
+#endif
+  free(p);
+}
+
+#if defined(HPPA)
+int kill_(int *pid, int *sig) { return kill(*pid,*sig); }
+#endif
+
+#if defined(HPPA)
+int getpid_() { return getpid(); }
+#endif
+
+#if defined(HPPA)
+int signal_(int *sig, void (*func)(int), int *mode)
+{ 
+  return (func != NULL) ? 
+    signal(*sig, func) : 
+      signal(*sig, (void (*)(int))(*mode));
+}
+#endif
+
+#if defined(HPPA)
+void 
+getenv_(const char *s, 
+	char *value,
+	/* Hidden arguments */
+	int slen,
+	const int valuelen) 
+{
+  codb_getenv_(s,value,slen,valuelen);
+}
+#endif
+
+
+#if defined(VPP_SYSTEM_call)
+int 
+system(const char *string)  
+{
+  extern int system_(const char *, int);
+  return system_(string, strlen(string)); /* Use Fortran system_ */
+}
+#endif
+
+void 
+codb_getpid_(pid_t *pid)
+{
+  if (pid) *pid = getpid();
+}
+
+#ifdef RS6K
+/* IBM RS/6000 pmapi.h dummies needed in drhook.c (IFSAUX) */
+/* function prototypes */
+
+double   pm_cycles(void) { return 0; }
+void     pm_error(char *where, int error) 
+{ 
+  fprintf(stderr,"***Error in dummy pm_error(%s): error=%d\n",where,error);
+}
+int      pm_init(int filter, void *pminfo, void *pmgroups) { return 0; }
+int      pm_initialize(int filter, void *pminfo, void *pmgroups, int flag) { return 0; }
+
+int      pm_set_program_mythread(void *prog) { return 0; }
+int      pm_start_mythread(void) { return 0; }
+int      pm_stop_mythread(void) { return 0; }
+int      pm_get_data_mythread(void *data) { return 0; }
+
+#endif /* RS6K */
+
+#if !defined(HAS_LAPACK)
+
+/* 
+   Unless you have LAPACK, use these second() and secondr() functions --
+   both meant to be REAL*8 functions in our environment 
+
+   See also util_cputime_() in ifsaux/support/drhook.c
+   and ifsaux/support/cptime.F, where the mess starts off ;-)
+*/
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#undef MIN
+#undef MAX
+#include <sys/param.h>
+#include <time.h>
+
+#ifdef CRAYXT
+/* Cray XT3/XT4 with catamount microkernel */
+#include <catamount/dclock.h>
+#endif
+
+double second_()
+{
+  double res = 0;
+#if !defined(CRAYXT)
+  extern clock_t times (struct tms *buffer);
+  struct tms tbuf;
+  static double clock_ticks = 0;
+  static int first_time = 1;
+
+  (void) times(&tbuf);
+
+  if (first_time) {
+    clock_ticks = (double) sysconf(_SC_CLK_TCK);
+    first_time = 0;
+  }
+
+  res = (tbuf.tms_utime + tbuf.tms_stime +
+	 tbuf.tms_cutime + tbuf.tms_cstime) / clock_ticks;
+#else
+  res = dclock();
+#endif
+  return res;
+}
+
+double second() { return second_(); }
+
+double secondr_() { return second_(); }
+
+double secondr() { return second_(); }
+
+#endif
diff --git a/odb/src/lib/Dummyprofile_newio.c b/odb/src/lib/Dummyprofile_newio.c
new file mode 100644
index 0000000..7b46c67
--- /dev/null
+++ b/odb/src/lib/Dummyprofile_newio.c
@@ -0,0 +1,20 @@
+
+#include "odb_ioprof.h"
+
+/* Dummy routines for new I/O profiling (newio.c) */
+
+void Profile_newio32_init(int myproc)
+{
+}
+
+void Profile_newio32_flush()
+{
+}
+
+void Profile_newio32_start(int what, int n)
+{
+}
+
+void Profile_newio32_end(int what, int n)
+{
+}
diff --git a/odb/src/lib/ae_dump.c b/odb/src/lib/ae_dump.c
new file mode 100644
index 0000000..512b24d
--- /dev/null
+++ b/odb/src/lib/ae_dump.c
@@ -0,0 +1,188 @@
+
+/* ae_dump.c : 
+   accident & emergency dump of matrices 
+   just after ODB_GET and/or before ODB_PUT
+ */
+
+#ifdef RS6K
+#pragma options noextchk
+#endif
+
+#include "odb.h"
+#include "cmaio.h"
+
+#define DUMP_HDRLEN 9
+
+static boolean first_time = 1;
+
+static int ae_dump = 0;
+static int ae_dump_proc = -1;
+
+static int dump_no = 0;
+
+static char *particular_dtname = NULL;
+
+static int unit = -1;
+
+static FILE *fp = NULL;
+
+#define CHECK_DUMP_ERROR(code, data, datalen, col) \
+if (code != datalen) { \
+  fprintf(stderr, \
+	  "***Warning: Unable to complete dump#%d (rc=%d) for dataname='%s', length=%d, col#%d ; disabled now\n", \
+	  dump_no, code, #data, datalen, col); \
+  unit = -1; \
+  errflg++; \
+  goto finish; \
+}
+
+void
+codb_init_ae_dump_(int *retcode)
+{
+  if (first_time) {
+    int myproc;
+    char *p;
+    p = getenv("ODB_AE_DUMP");
+    if (p) ae_dump = atoi(p);
+    ae_dump = MAX(0,ae_dump);
+    p = getenv("ODB_AE_DUMP_PROC");
+    if (p) ae_dump_proc = atoi(p);
+    codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+    if (ae_dump_proc != -1 && ae_dump_proc != myproc) ae_dump = 0;
+    if (ae_dump > 0) {
+      p = getenv("ODB_AE_DUMP_DATANAME");
+      if (p) particular_dtname = STRDUP(p);
+    }
+    first_time = 0;
+  }
+  *retcode = ae_dump;
+}
+
+void
+codb_ae_dump_(const int *handle,
+	      const int *is_get,
+	      const int *poolno,
+	      const char *dtname,
+	      const int *datatype,
+	      const int *nra,
+	      const int *nrows,
+	      const int *ncols,
+	      const void *data
+	      /* Hidden arguments */
+	      , int dtname_len)
+{
+  int rc = 0;
+  int errflg = 0;
+
+  if (first_time) codb_init_ae_dump_(&rc);
+
+  if (ae_dump > dump_no) {
+    DECL_FTN_CHAR(dtname);
+
+    ALLOC_FASTFTN_CHAR(dtname);
+
+    if (particular_dtname) {
+      /* if (!strequ(p_dtname, particular_dtname)) goto finish; */
+      if (!strstr(particular_dtname, p_dtname)) goto finish;
+    }
+
+    dump_no++;
+
+    if (dump_no == 1) {
+      int myproc = 0;
+      char *p = getenv("ODB_AE_DUMP_FILE");
+      char *pfile = NULL;
+
+      if (!p) p = "ae_dump_file.%d";
+      pfile = STRDUP(p);
+
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+
+      if (strchr(pfile,'%')) {
+	ALLOC(p,strlen(pfile) + 20);
+	sprintf(p,pfile,myproc);
+      }
+      else {
+	p = STRDUP(pfile);
+      }
+      FREE(pfile);
+
+      fprintf(stderr,"***Opening A&E-dumpfile='%s' for PE#%d\n",p,myproc);
+      cma_open_(&unit, p, "w", &rc, strlen(p), 1);
+
+      if (rc < 1) {
+	perror(p);
+	fprintf(stderr,
+	"***Warning from codb_ae_dump_(): Unable to open A&E-dumpfile='%s' --> dump disabled\n",
+		p);
+	unit = -1;
+	errflg++;
+      }
+      FREE(p);
+
+      if (errflg) goto finish;
+
+      {
+	extern FILE *CMA_get_fp(const int *unit);
+	fp = CMA_get_fp(&unit);
+      }
+    }
+
+    { /* write dump */
+      const unsigned char *out = data;
+      int j, size;
+      int intlen = (*datatype)%100;
+      int realen = (*datatype)/100;
+      int lenbytes = MAX(intlen, realen); /* a bit sloppy way to detect datatype, but must suffice right now */
+      int lda = (*nra) * lenbytes;
+      int Nrows = *nrows;
+      int chunk = (*nrows) * lenbytes;
+      int Ncols = (*ncols) + 1; /* +1 because of the 0th column, too */
+      int total = lenbytes * Nrows * Ncols;
+      int hdr[DUMP_HDRLEN];
+      unsigned char buf[80];
+      int lenbuf;
+
+      hdr[0] = dump_no;
+      hdr[1] = *handle;
+      hdr[2] = *is_get;
+      hdr[3] = Nrows;
+      hdr[4] = Ncols;
+      hdr[5] = total;
+      hdr[6] = intlen;
+      hdr[7] = realen;
+      hdr[8] = *poolno;
+
+      size = sizeof(hdr);
+      cma_writeb_(&unit, (const unsigned char *)hdr, &size, &rc); 
+      CHECK_DUMP_ERROR(rc, hdr, size, -1);
+
+      lenbuf = sizeof(buf);
+      memset(buf,' ', lenbuf);
+      lenbuf = MIN(sizeof(buf), dtname_len);
+      memcpy(buf, p_dtname, lenbuf);
+      lenbuf = sizeof(buf);
+      cma_writeb_(&unit, buf, &lenbuf, &rc); 
+      CHECK_DUMP_ERROR(rc, dtname, lenbuf, -1);
+
+      for (j=1; j<=Ncols; j++) {
+	cma_writeb_(&unit, (const unsigned char *)out, &chunk, &rc);
+	CHECK_DUMP_ERROR(rc, out, chunk, j);
+	out += lda;
+      }
+    }
+    
+    if (dump_no > ae_dump) {
+      cma_close_(&unit, &rc);
+      fp = NULL;
+      unit = -1;
+      ae_dump = 0;
+    }
+
+  finish:
+    if (fp) fflush(fp);
+    if (errflg) ae_dump = 0;
+    FREE_FASTFTN_CHAR(dtname);
+  }
+}
+
diff --git a/odb/src/lib/aggr.c b/odb/src/lib/aggr.c
new file mode 100644
index 0000000..5ae9a11
--- /dev/null
+++ b/odb/src/lib/aggr.c
@@ -0,0 +1,1232 @@
+
+/* aggr.c */
+
+#include "odb.h"
+#include "idx.h"
+#include "cdrhook.h"
+#include "pcma_extern.h"
+
+static const double mdi = ABS(RMDI);
+
+#define NAME_FLAG(x) #x, x
+
+typedef struct {
+  const char *name;
+  uint aggr_func_flag;
+} name_flag_t;
+
+PRIVATE name_flag_t 
+name_flag[] = {
+  NAME_FLAG(ODB_AGGR_NONE           ),
+  NAME_FLAG(ODB_AGGR_COUNT          ),
+  NAME_FLAG(ODB_AGGR_COUNT_DISTINCT ),
+  NAME_FLAG(ODB_AGGR_BCOUNT         ),
+  NAME_FLAG(ODB_AGGR_BCOUNT_DISTINCT),
+  NAME_FLAG(ODB_AGGR_MIN            ),
+  NAME_FLAG(ODB_AGGR_MAX            ),
+  NAME_FLAG(ODB_AGGR_SUM            ),
+  NAME_FLAG(ODB_AGGR_SUM_DISTINCT   ),
+  NAME_FLAG(ODB_AGGR_AVG            ),
+  NAME_FLAG(ODB_AGGR_AVG_DISTINCT   ),
+  NAME_FLAG(ODB_AGGR_MEDIAN         ),
+  NAME_FLAG(ODB_AGGR_MEDIAN_DISTINCT),
+  NAME_FLAG(ODB_AGGR_STDEV          ),
+  NAME_FLAG(ODB_AGGR_STDEV_DISTINCT ),
+  NAME_FLAG(ODB_AGGR_RMS            ),
+  NAME_FLAG(ODB_AGGR_RMS_DISTINCT   ),
+  NAME_FLAG(ODB_AGGR_DOTP           ),
+  NAME_FLAG(ODB_AGGR_DOTP_DISTINCT  ),
+  NAME_FLAG(ODB_AGGR_NORM           ),
+  NAME_FLAG(ODB_AGGR_NORM_DISTINCT  ),
+  NAME_FLAG(ODB_AGGR_VAR            ),
+  NAME_FLAG(ODB_AGGR_VAR_DISTINCT   ),
+  NAME_FLAG(ODB_AGGR_COVAR          ),
+  NAME_FLAG(ODB_AGGR_CORR           ),
+  NAME_FLAG(ODB_AGGR_LINREGR_A      ),
+  NAME_FLAG(ODB_AGGR_LINREGR_B      ),
+  NAME_FLAG(ODB_AGGR_MINLOC         ),
+  NAME_FLAG(ODB_AGGR_MAXLOC         ),
+  NAME_FLAG(ODB_AGGR_DENSITY        ),
+  NULL,
+};
+
+PRIVATE const char *get_name_flag(uint aggr_func_flag)
+{
+  static const char *not_found = "<Unrecognized aggregate function>";
+  name_flag_t *p = name_flag;
+  while (p && p->name) {
+    if (p->aggr_func_flag == aggr_func_flag) return p->name;
+    p++;
+  }
+  return not_found;
+}
+
+#define N_AUX 5
+
+typedef struct {
+  /* Auxiliary info for more economic aggregate funcs implementation */
+  uint aggr_func_flag;
+  int num; /* No. of d[N_AUX] entries that will be filled : 0 or 1 or 2 or ... up to N_AUX */
+  int nd; /* Number of values accumulated in d[]'s */
+  int ind; /* Number of values accumulated in d[]'s that satisfy : ABS(value) != mdi */
+  double d[N_AUX]; /* partial sums and/or sum-squares etc. so far */
+  double *uniq; /* A copy of "nd" unique values so far (for xxx_DISTINCT) */
+} Aggr_aux;
+
+
+typedef union {
+  double daddr; /* 8 bytes */
+  Aggr_aux *addr; /* 4 or 8 bytes address */
+} Aggr_address_fudge;
+
+
+PRIVATE int cmp(const void *A, const void *B) {
+  const double *a = A;
+  const double *b = B;
+  if      ( *a < *b ) return -1;
+  else if ( *a > *b ) return  1;
+  else		      return  0;
+}
+
+#define MEDIAN(x,n) ( ((n)%2 == 0) ? (((x)[(n)/2] + (x)[(n)/2 + 1])/2) : (x)[(n)/2] )
+
+PRIVATE void
+CalcAggr0(const int    *aggr_func_flag,
+	  const double  d[],
+	  const double  daux[],
+	  const int    *nd, 
+	  double        rc[])
+{
+  DRHOOK_START(CalcAggr0);
+  if (aggr_func_flag && d && nd && rc) {
+    int Nd = *nd;
+    uint flag = (uint) *aggr_func_flag;
+    double value = RMDI; /* Initialized to missing data indicator */
+    if (Nd >= 0 && flag != ODB_AGGR_NONE) {
+      Aggr_aux *aux = NULL;
+      int j;
+      CALLOC(aux,1);
+      aux->aggr_func_flag = flag;
+      if ((flag & ODB_AGGRMASK_DISTINCT) == ODB_AGGRMASK_DISTINCT) {
+	/* {COUNT|SUM|AVG|MEDIAN|STDEV|RMS|DOTP|NORM|VAR}(DISTINCT arg) */
+	int ncard = 0;
+	int *unique_idx = NULL;
+
+	if (Nd > 0) {
+	  int bailout = -1; /* bailing out turned off; can be slow */
+	  const int ncols = 1;
+	  int lda, nrows;
+	  lda = nrows = Nd;
+	  ALLOC(unique_idx, nrows);
+	  codb_cardinality_(&ncols, &nrows, &lda,
+			    d, &ncard,
+			    unique_idx,
+			    &nrows,
+			    &bailout);
+	}
+	else
+	  ncard = 0;
+
+	aux->num = 0;
+	if (ncard > 0) {
+	  int iNd = 0;
+	  aux->nd = ncard;
+	  ALLOC(aux->uniq, ncard);
+	  for (j=0; j<ncard; j++) {
+	    double dd = d[unique_idx[j]-1];
+	    aux->uniq[j] = dd;
+	    if (ABS(dd) != mdi) ++iNd;
+	  }
+	  aux->ind = iNd;
+	}
+
+	FREE(unique_idx);
+      }
+      else {
+	/* Just {COUNT|SUM|AVG|MEDIAN|STDEV|RMS|MIN|MAX|DOTP|NORM|VAR}(arg) */
+	switch (flag) {
+	case ODB_AGGR_COUNT:
+	  aux->num = 0;
+	  aux->nd = aux->ind = Nd;
+	  value = Nd;
+	  break;
+	case ODB_AGGR_BCOUNT:
+	  {
+	    int ntrue = 0;
+	    for (j=0; j<Nd; j++) if (d[j] != 0) ntrue++;
+	    aux->num = 0;
+	    aux->nd = aux->ind = ntrue;
+	    value = ntrue;
+	  }
+	  break;
+	case ODB_AGGR_RMS:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		value += d[j] * d[j];
+		++iNd;
+	      }
+	    }
+	    aux->num = 1;
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	    aux->d[0] = (iNd > 0) ? value : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MEDIAN:
+	  aux->num = 0;
+	  aux->nd = aux->ind = Nd;
+	  ALLOC(aux->uniq, Nd);
+	  for (j=0; j<Nd; j++) aux->uniq[j] = d[j];
+	  break;
+	case ODB_AGGR_AVG:
+	case ODB_AGGR_SUM:
+	case ODB_AGGR_DENSITY:
+	case ODB_AGGR_DOTP:
+	case ODB_AGGR_NORM:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    if (flag == ODB_AGGR_DENSITY) {
+	      double min_resol = ODB_eq_min_resol();
+	      for (j=0; j<Nd; j++) {
+		if (ABS(d[j]) != mdi) {
+		  value += MAX(d[j],min_resol);
+		  ++iNd;
+		}
+	      }
+	    }
+	    else {
+	      for (j=0; j<Nd; j++) {
+		if (ABS(d[j]) != mdi) {
+		  value += d[j];
+		  ++iNd;
+		}
+	      }
+	    }
+	    aux->num = 1;
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	    aux->d[0] = (iNd > 0) ? value : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_STDEV:
+	case ODB_AGGR_VAR:
+	  {
+	    int iNd = 0;
+	    double sum = 0;
+	    value = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		sum += d[j];
+		value += d[j] * d[j];
+		++iNd;
+	      }
+	    }
+	    aux->num = 2;
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	    aux->d[0] = (iNd > 0) ? sum : RMDI;
+	    aux->d[1] = (iNd > 0) ? value : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MINLOC:
+	case ODB_AGGR_MAXLOC:
+	  {
+	    int iNd = 0;
+	    double loc;
+	    if (daux && Nd > 0) {
+	      int jj = 0;
+	      /* In case the first one is a missing data indicator */
+	      while (jj<Nd && ABS(d[jj]) == mdi) jj++;
+	      if (jj<Nd) {
+		j = jj;
+		loc = daux[j];
+		value = d[j];
+		++iNd;
+		if (flag == ODB_AGGR_MINLOC) {
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi) {
+		      if (value > d[j]) {
+			value = d[j];
+			loc = daux[j];
+		      }
+		      ++iNd;
+		    }
+		  } /* for (j=jj+1; j<Nd; j++) */
+		}
+		else { /* ODB_AGGR_MAXLOC */
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi) {
+		      if (value < d[j]) {
+			value = d[j];
+			loc = daux[j];
+		      }
+		      ++iNd;
+		    }
+		  } /* for (j=jj+1; j<Nd; j++) */
+		}
+	      } /* if (jj<Nd) */
+	    } /* if (daux && Nd > 0) */
+
+	    aux->num = 2;
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	    aux->d[0] = (iNd > 0) ? value : RMDI;
+	    aux->d[1] = (iNd > 0) ? loc : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MIN:
+	case ODB_AGGR_MAX:
+	  {
+	    int iNd = 0;
+	    if (Nd > 0) {
+	      int jj = 0;
+	      /* In case the first one is a missing data indicator */
+	      while (jj<Nd && ABS(d[jj]) == mdi) jj++;
+	      if (jj<Nd) {
+		j = jj;
+		value = d[j];
+		++iNd;
+		if (flag == ODB_AGGR_MIN) {
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi) {
+		      if (value > d[j]) value = d[j];
+		      ++iNd;
+		    }
+		  } /* for (j=jj+1; j<Nd; j++) */
+		}
+		else { /* ODB_AGGR_MAX */
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi) {
+		      if (value < d[j]) value = d[j];
+		      ++iNd;
+		    }
+		  } /* for (j=jj+1; j<Nd; j++) */
+		}
+	      }
+	    } /* if (Nd > 0) */
+	    aux->num = 1;
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	    aux->d[0] = (iNd > 0) ? value : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_LINREGR_A:
+	case ODB_AGGR_LINREGR_B:
+	case ODB_AGGR_CORR:
+	case ODB_AGGR_COVAR:
+	  {
+	    /* y = A + B * x */
+	    int iNd = 0;
+	    value = RMDI;
+	    aux->num = 5;
+	    if (daux && Nd > 0) {
+	      for (j=0; j<aux->num; j++) aux->d[j] = 0;
+	      for (j=0; j<Nd; j++) {
+		if (ABS(d[j]) != mdi && ABS(daux[j]) != mdi) {
+		  aux->d[0] += d[j]; /* x := d[] , sum(x) */
+		  aux->d[1] += daux[j]; /* y := daux[] , sum(y)*/
+		  aux->d[2] += d[j] * d[j]; /* sum(x^2) */
+		  aux->d[3] += daux[j] * daux[j]; /* sum(y^2) */
+		  aux->d[4] += d[j] * daux[j]; /* sum(x * y) */
+		  ++iNd;
+		}
+	      } /* for (j=0; j<Nd; j++) */
+	    }
+	    aux->nd = Nd;
+	    aux->ind = iNd;
+	  }
+	  break;
+	}
+      }
+      if (aux) {
+	Aggr_address_fudge afu;
+	afu.daddr = 0;
+	afu.addr = aux;
+	value = afu.daddr;
+      }
+    }
+    else if (Nd == 1 && flag == ODB_AGGR_NONE) {
+      value = d[0];
+    }
+    *rc = value;
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+CalcAggr1(const int    *aggr_func_flag,
+	  const double  daddr[],
+	  const int    *ndaddr, 
+	  double       *rc)
+{
+  DRHOOK_START(CalcAggr1);
+  if (aggr_func_flag && daddr && ndaddr && rc) {
+    int Ndaddr = *ndaddr;
+    uint flag = (uint) *aggr_func_flag;
+    double value = RMDI; /* Initialized to missing data indicator */
+    if (Ndaddr >= 0 && flag != ODB_AGGR_NONE) {
+      int j, jf;
+
+      if ((flag & ODB_AGGRMASK_DISTINCT) == ODB_AGGRMASK_DISTINCT) {
+	/* {COUNT|SUM|AVG|STDEV|RMS|DOTP|NORM|VAR}(DISTINCT arg) */
+	int ncard = 0;
+	int *unique_idx = NULL;
+	double *d = NULL;
+	int Nd = 0;
+	int iNd = 0;
+	Bool is_count_dist = (flag == ODB_AGGR_COUNT_DISTINCT) ? true : false;
+	int Nfill;
+
+	/* Re-construct d[] */
+	{
+	  for (jf=0; jf<Ndaddr; jf++) {
+	    Aggr_aux *aux;
+	    Aggr_address_fudge afu;
+	    afu.daddr = daddr[jf];
+	    aux = afu.addr;
+	    if (aux && aux->uniq && aux->nd > 0) {
+	      Nd += aux->nd;
+	      iNd += aux->ind;
+	    } /* if (aux) */
+	  } /* for (jf=0; jf<Ndaddr; jf++) */
+
+	  if (Nd > 0) {
+	    int jd = 0;
+	    ALLOC(d, Nd);
+	    for (jf=0; jf<Ndaddr; jf++) {
+	      Aggr_aux *aux;
+	      Aggr_address_fudge afu;
+	      afu.daddr = daddr[jf];
+	      aux = afu.addr;
+	      if (aux && aux->uniq && aux->nd > 0) {
+		int nnd = aux->nd; /* Upper limit ; due to mdi's, this may never get filled that much */
+		for (j=0; j<nnd; j++) {
+		  double dd = aux->uniq[j];
+		  if (is_count_dist || ABS(dd) != mdi) d[jd++] = dd; /* Don't fill mdi's */
+		}
+	      } /* if (aux) */
+	    } /* for (jf=0; jf<Ndaddr; jf++) */
+	  }
+
+	  /* Release aux-space */
+	  for (jf=0; jf<Ndaddr; jf++) {
+	    Aggr_aux *aux;
+	    Aggr_address_fudge afu;
+	    afu.daddr = daddr[jf];
+	    aux = afu.addr;
+	    if (aux) {
+	      FREE(aux->uniq);
+	      FREE(aux);
+	    } /* if (aux) */
+	  } /* for (jf=0; jf<Ndaddr; jf++) */
+	}
+
+	Nfill = is_count_dist ? Nd : iNd;
+
+	if (Nfill > 0) {
+	  int bailout = -1; /* bailing out turned off; can be slow */
+	  const int ncols = 1;
+	  int lda, nrows;
+	  lda = nrows = Nfill;
+	  if (!is_count_dist) ALLOC(unique_idx, nrows);
+	  codb_cardinality_(&ncols, &nrows, &lda,
+			    d, &ncard,
+			    unique_idx,
+			    &nrows,
+			    &bailout);
+	}
+	else
+	  ncard = 0;
+
+	switch (flag) {
+	case ODB_AGGR_COUNT_DISTINCT:
+	  value = ncard; /* Note : we INCLUDE missing datas in count() */
+	  break;
+	case ODB_AGGR_BCOUNT_DISTINCT:
+	  {
+	    int ntrue = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (dd != 0) ntrue++;
+	    }
+	    value = ntrue;
+	  }
+	  break;
+	case ODB_AGGR_RMS_DISTINCT:
+	  value = 0;
+	  for (j=0; j<ncard; j++) {
+	    double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	    value += dd * dd;
+	  }
+	  if (ncard > 0) 
+	    value = (value > 0) ? sqrt(value/ncard) : (double)0;
+	  else 
+	    value = RMDI;
+	  break;
+	case ODB_AGGR_MEDIAN_DISTINCT:
+	  value = RMDI;
+	  if (ncard > 0) {
+	    double *dtmp = NULL;
+	    ALLOC(dtmp, ncard);
+	    for (j=0; j<ncard; j++) dtmp[j] = d[unique_idx[j]-1];
+	    qsort(dtmp, ncard, sizeof(*dtmp), cmp);
+	    value = MEDIAN(dtmp,ncard); /* median */
+	    FREE(dtmp);
+	  }
+	  break;
+	case ODB_AGGR_AVG_DISTINCT:
+	case ODB_AGGR_SUM_DISTINCT:
+	case ODB_AGGR_NORM_DISTINCT:
+	case ODB_AGGR_DOTP_DISTINCT:
+	  value = 0;
+	  for (j=0; j<ncard; j++) {
+	    double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	    value += dd;
+	  }
+	  if (ncard > 0) {
+	    if (flag == ODB_AGGR_AVG_DISTINCT) value /= ncard;
+	    else if (flag == ODB_AGGR_NORM_DISTINCT) value = (value > 0) ? sqrt(value) : (double)0;
+	  }
+	  else
+	    value = RMDI;
+	  break;
+	case ODB_AGGR_STDEV_DISTINCT:
+	case ODB_AGGR_VAR_DISTINCT:
+	  {
+	    double avg = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      avg += dd;
+	    }
+	    if (ncard > 0) {
+	      avg /= ncard;
+	      value = 0;
+	      for (j=0; j<ncard; j++) {
+		double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+		dd -= avg;
+		value += dd * dd;
+	      }
+	    }
+	    if (ncard > 1) {
+	      value = value/(ncard-1);
+	      if (flag == ODB_AGGR_STDEV_DISTINCT) value = sqrt(value);
+	    }
+	    else if (ncard == 1)
+	      value = 0;
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	}
+	FREE(unique_idx);
+	FREE(d);
+      }
+      else {
+	/* Just {COUNT|SUM|AVG|MEDIAN|STDEV|RMS|MIN|MAX|DOTP|NORM|VAR}(arg) */
+	int Nd = 0;
+	int iNd = 0;
+	int N[N_AUX];
+	double **d;
+	double *tmp;
+
+	ALLOCX(d, N_AUX);
+	for (j=0; j<N_AUX; j++) {
+	  N[j] = 0;
+	  d[j] = NULL;
+	}
+
+	for (jf=0; jf<Ndaddr; jf++) {
+	  Aggr_aux *aux;
+	  Aggr_address_fudge afu;
+	  afu.daddr = daddr[jf];
+	  aux = afu.addr;
+	  if (aux) {
+	    Nd += aux->nd;
+	    iNd += aux->ind;
+	    for (j=0; j<aux->num; j++) N[j]++;
+	  } /* if (aux) */
+	} /* for (jf=0; jf<Ndaddr; jf++) */
+
+	if (flag != ODB_AGGR_MEDIAN) {
+	  for (j=0; j<N_AUX; j++) {
+	    if (N[j] > 0) {
+	      int jd = 0;
+	      ALLOC(d[j], N[j]);
+	      tmp = d[j];
+	      for (jf=0; jf<Ndaddr; jf++) {
+	        Aggr_aux *aux;
+		Aggr_address_fudge afu;
+		afu.daddr = daddr[jf];
+		aux = afu.addr;
+		if (aux && aux->num > 0) {
+		  double dd = aux->d[j];
+		  tmp[jd++] = dd; /* Missing datas checked later */
+		}
+	      }
+	    } /* if (N[j] > 0) */
+	  } /* for (j=0; j<N_AUX; j++) */
+	}
+	else { /* flag == ODB_AGGR_MEDIAN */
+	  int jd = 0;
+	  ALLOC(tmp, Nd); /* Upper limit ; due to mdi's, this may never get filled that much */
+	  for (jf=0; jf<Ndaddr; jf++) {
+	    Aggr_aux *aux;
+	    Aggr_address_fudge afu;
+	    afu.daddr = daddr[jf];
+	    aux = afu.addr;
+	    if (aux && aux->uniq && aux->nd > 0 && aux->ind > 0) {
+	      int nnd = aux->nd;
+	      for (j=0; j<nnd; j++) {
+		double dd = aux->uniq[j];
+		if (ABS(dd) != mdi) tmp[jd++] = dd;
+	      }
+	    } /* if (aux && aux->uniq && aux->num > 0) */
+	  } /* for (jf=0; jf<Ndaddr; jf++) */ 
+	}
+
+	/* Release aux-space */
+	for (jf=0; jf<Ndaddr; jf++) {
+	  Aggr_aux *aux;
+	  Aggr_address_fudge afu;
+	  afu.daddr = daddr[jf];
+	  aux = afu.addr;
+	  if (aux) {
+	    FREE(aux->uniq);
+	    FREE(aux);
+	  } /* if (aux) */
+	} /* for (jf=0; jf<Ndaddr; jf++) */
+
+	switch (flag) {
+	case ODB_AGGR_COUNT:
+	case ODB_AGGR_BCOUNT:
+	  value = Nd; /* Note : we INCLUDE missing datas in count() */
+	  break;
+	case ODB_AGGR_MEDIAN:
+	  value = RMDI;
+	  if (iNd > 0) {
+	    qsort(tmp, iNd, sizeof(*tmp), cmp);
+	    value = MEDIAN(tmp,iNd); /* median */
+	  }
+	  FREE(tmp);
+	  break;
+	case ODB_AGGR_RMS:
+	case ODB_AGGR_AVG:
+	case ODB_AGGR_SUM:
+	case ODB_AGGR_DENSITY:
+	case ODB_AGGR_DOTP:
+	case ODB_AGGR_NORM:
+	  value = 0;
+	  tmp = d[0];
+	  if (iNd > 0) {
+	    for (j=0; j<N[0]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) value += dd;
+	    }
+	    if (flag == ODB_AGGR_RMS) value = (value > 0) ? sqrt(value/iNd) : (double)0;
+	    else if (flag == ODB_AGGR_AVG) value /= iNd;
+	    else if (flag == ODB_AGGR_NORM) value = (value > 0) ? sqrt(value) : (double)0;
+	    else if (flag == ODB_AGGR_DENSITY) {
+	      double resol = value/iNd; /* Average resolution, in degrees */
+	      /* Approximate area of a small spherical eq_region [in degrees^2] */
+	      double area  = resol * resol;
+	      value = iNd / area; /* Density = # of points divided by the approx. area  */
+	    }
+	  }
+	  else
+	    value = RMDI;
+	  break;
+	case ODB_AGGR_STDEV:
+	case ODB_AGGR_VAR:
+	  if (iNd > 1) {
+	    /* Now STDEV = sqrt((sumsqr - sum*sum/iNd)/(iNd-1)) */
+	    double sum = 0;    /* i.e. aux->d[0] */
+	    double sumsqr = 0; /* i.e. aux->d[1] */
+	    tmp = d[0];
+	    for (j=0; j<N[0]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sum += dd;
+	    }
+	    tmp = d[1];
+	    for (j=0; j<N[1]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumsqr += dd;
+	    }
+	    if (iNd > 1) {
+	      value = sumsqr - (sum * (sum/iNd));
+	      value = (value > 0) ? (value/(iNd-1)) : (double)0;
+	      if (flag == ODB_AGGR_STDEV) value = sqrt(value);
+	    }
+	    else if (iNd == 1)
+	      value = 0;
+	    else
+	      value = RMDI;
+	  }
+	  else if (iNd == 1)
+	    value = 0;
+	  else
+	    value = RMDI;
+	  break;
+	case ODB_AGGR_MINLOC:
+	case ODB_AGGR_MAXLOC:
+	  value = RMDI;
+	  if (iNd > 0) {
+	    int jj = 0;
+	    double loc = RMDI;
+	    tmp = d[0];
+	    /* In case the first one is a missing data indicator */
+	    while (jj<N[0] && ABS(tmp[jj]) == mdi) jj++;
+	    if (jj<N[0]) {
+	      value = tmp[jj];
+	      loc = d[1][jj];
+	      if (flag == ODB_AGGR_MINLOC) {
+		for (j=jj+1; j<N[0]; j++) {
+		  double dd = tmp[j];
+		  if (ABS(dd) != mdi && value > dd) {
+		    value = dd;
+		    loc = d[1][j];
+		  }
+		} /* for (j=1; j<N[0]; j++) */
+	      }
+	      else { /* ODB_AGGR_MAXLOC */
+		for (j=jj+1; j<N[0]; j++) {
+		  double dd = tmp[j];
+		  if (ABS(dd) != mdi && value < dd) {
+		    value = dd;
+		    loc = d[1][j];
+		  }
+		} /* for (j=1; j<N[0]; j++) */
+	      }
+	    }
+	    value = (ABS(loc) != mdi) ? loc : RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MIN:
+	case ODB_AGGR_MAX:
+	  value = RMDI;
+	  if (iNd > 0) {
+	    int jj = 0;
+	    tmp = d[0];
+	    /* In case the first one is a missing data indicator */
+	    while (jj<N[0] && ABS(tmp[jj]) == mdi) jj++;
+	    if (jj<N[0]) {
+	      value = tmp[jj];
+	      if (flag == ODB_AGGR_MIN) {
+		for (j=jj+1; j<N[0]; j++) {
+		  double dd = tmp[j];
+		  if (ABS(dd) != mdi && value > dd) value = dd;
+		}
+	      }
+	      else { /* ODB_AGGR_MAX */
+		for (j=jj+1; j<N[0]; j++) {
+		  double dd = tmp[j];
+		  if (ABS(dd) != mdi && value < dd) value = dd;
+		}
+	      }
+	    } /* if (jj<N[0]) */
+	  }
+	  break;
+	case ODB_AGGR_LINREGR_A:
+	case ODB_AGGR_LINREGR_B:
+	case ODB_AGGR_CORR:
+	case ODB_AGGR_COVAR:
+	  /* y = A + B * x */
+	  value = RMDI;
+	  if (iNd > 0) {
+	    double sxy, sxx, syy;
+	    double sumx = 0, sumy = 0, sumx2 = 0, sumy2 = 0, sumxy = 0;
+	    double xavg, yavg;
+	    tmp = d[0];
+	    for (j=0; j<N[0]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumx += dd;
+	    }
+	    xavg = sumx/iNd;
+	    tmp = d[1];
+	    for (j=0; j<N[1]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumy += dd;
+	    }
+	    yavg = sumy/iNd;
+	    tmp = d[2];
+	    for (j=0; j<N[2]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumx2 += dd;
+	    }
+	    tmp = d[3];
+	    for (j=0; j<N[3]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumy2 += dd;
+	    }
+	    tmp = d[4];
+	    for (j=0; j<N[4]; j++) {
+	      double dd = tmp[j];
+	      if (ABS(dd) != mdi) sumxy += dd;
+	    }
+	    sxy = sumxy - iNd * xavg * yavg; 
+	    sxx = sumx2 - iNd * xavg * xavg;
+	    syy = sumy2 - iNd * yavg * yavg;
+	    if (flag == ODB_AGGR_CORR) {
+	      value = (sxx != 0 && syy != 0) ? (sxy * sxy)/(sxx * syy) : (double)0;
+	      value = (value > 0) ? sqrt(value) : (double)0;
+	    }
+	    else if (flag == ODB_AGGR_COVAR) {
+	      value = sxy/iNd;
+	    }
+	    else { /* ODB_AGGR_LINREGR_A or ODB_AGGR_LINREGR_B */
+	      double b = (sxx != 0) ? sxy/sxx : 1e-30;
+	      double a = yavg - b * xavg;
+	      value = (flag == ODB_AGGR_LINREGR_B) ? b : a;
+	    }
+	  }
+	  break;
+	}
+
+	for (j=0; j<N_AUX; j++) {
+	  FREE(d[j]);
+	}
+	FREEX(d);
+      }
+    }
+    else if (Ndaddr == 1 && flag == ODB_AGGR_NONE) {
+      value = daddr[0];
+    }
+    *rc = value;
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+CalcAggrAll(const int    *aggr_func_flag,
+	    const double  d[],
+	    const double  daux[],
+	    const int    *nd, 
+	    double        rc[])
+{
+  DRHOOK_START(CalcAggrAll);
+  if (aggr_func_flag && d && nd && rc) {
+    int Nd = *nd;
+    uint flag = (uint) *aggr_func_flag;
+    double value = RMDI; /* Initialized to missing data indicator */
+    double value_aux =  RMDI;
+    if (Nd >= 0 && flag != ODB_AGGR_NONE) {
+      int j;
+      if ((flag & ODB_AGGRMASK_DISTINCT) == ODB_AGGRMASK_DISTINCT) {
+	/* {COUNT|SUM|AVG|MEDIAN|STDEV|RMS|DOTP|NORM|VAR}(DISTINCT arg) */
+	int ncard = 0;
+	int *unique_idx = NULL;
+
+	if (Nd > 0) {
+	  int bailout = -1; /* bailing out turned off; can be slow */
+	  const int ncols = 1;
+	  int lda, nrows;
+	  lda = nrows = Nd;
+	  if (flag != ODB_AGGR_COUNT_DISTINCT) ALLOC(unique_idx, nrows);
+	  codb_cardinality_(&ncols, &nrows, &lda,
+			    d, &ncard,
+			    unique_idx,
+			    &nrows,
+			    &bailout);
+	}
+	else
+	  ncard = 0;
+
+	switch (flag) {
+	case ODB_AGGR_COUNT_DISTINCT:
+	  value = ncard;
+	  break;
+	case ODB_AGGR_BCOUNT_DISTINCT:
+	  {
+	    int ntrue = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (dd != 0) ntrue++;
+	    }
+	    value = ntrue;
+	  }
+	  break;
+	case ODB_AGGR_RMS_DISTINCT:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (ABS(dd) != mdi) {
+		value += dd * dd;
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) 
+	      value = (value > 0) ? sqrt(value/iNd) : (double)0;
+	    else 
+	      value = RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MEDIAN_DISTINCT:
+	  value = RMDI;
+	  if (ncard > 0) {
+	    double *dtmp = NULL;
+	    ALLOC(dtmp, ncard);
+	    for (j=0; j<ncard; j++) 
+	      dtmp[j] = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	    qsort(dtmp, ncard, sizeof(*dtmp), cmp);
+	    value = MEDIAN(dtmp, ncard); /* median */
+	    FREE(dtmp);
+	  }
+	  break;
+	case ODB_AGGR_AVG_DISTINCT:
+	case ODB_AGGR_SUM_DISTINCT:
+	case ODB_AGGR_NORM_DISTINCT:
+	case ODB_AGGR_DOTP_DISTINCT:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (ABS(dd) != mdi) {
+		value += dd;
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) {
+	      if (flag == ODB_AGGR_AVG_DISTINCT) value /= iNd;
+	      else if (flag == ODB_AGGR_NORM_DISTINCT) value = (value > 0) ? sqrt(value) : (double)0;
+	    }
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	case ODB_AGGR_STDEV_DISTINCT:
+	case ODB_AGGR_VAR_DISTINCT:
+	  {
+	    int iNd = 0;
+	    double avg = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (ABS(dd) != mdi) {
+		avg += dd;
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) avg /= iNd;
+	    value = 0;
+	    for (j=0; j<ncard; j++) {
+	      double dd = d[unique_idx[j]-1]; /* -1 since unique_idx[] is Fortran-index >= 1 */
+	      if (ABS(dd) != mdi) {
+		dd -= avg;
+		value += dd * dd;
+	      }
+	    }
+	    if (iNd > 1) {
+	      value = value/(iNd-1);
+	      if (flag == ODB_AGGR_STDEV_DISTINCT) value = sqrt(value);
+	    }
+	    else if (iNd == 1)
+	      value = 0;
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	}
+	FREE(unique_idx);
+      }
+      else {
+	/* Just {COUNT|SUM|AVG|STDEV|RMS|MIN|MAX|DOTP|NORM|VAR}(arg) */
+	switch (flag) {
+	case ODB_AGGR_COUNT:
+	  value = Nd;
+	  break;
+	case ODB_AGGR_BCOUNT:
+	  {
+	    int ntrue = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (d[j] != 0) ntrue++;
+	    }
+	    value = ntrue;
+	  }
+	  break;
+	case ODB_AGGR_RMS:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		value += d[j] * d[j];
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) 
+	      value = (value > 0) ? sqrt(value/iNd) : (double)0;
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MEDIAN:
+	  value = RMDI;
+	  if (Nd > 0) {
+	    int iNd = 0;
+	    double *dtmp = NULL;
+	    ALLOC(dtmp, Nd);
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		dtmp[iNd++] = d[j];
+	      }
+	    }
+	    if (iNd > 0) {
+	      qsort(dtmp, iNd, sizeof(*dtmp), cmp);
+	      value = MEDIAN(dtmp, iNd); /* median */
+	    }
+	    FREE(dtmp);
+	  }
+	  break;
+	case ODB_AGGR_AVG:
+	case ODB_AGGR_SUM:
+	case ODB_AGGR_DENSITY:
+	case ODB_AGGR_DOTP:
+	case ODB_AGGR_NORM:
+	  {
+	    int iNd = 0;
+	    value = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		value += d[j];
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) {
+	      if (flag == ODB_AGGR_AVG) value /= iNd;
+	      else if (flag == ODB_AGGR_NORM) value = (value > 0) ? sqrt(value) : (double)0;
+	      else if (flag == ODB_AGGR_DENSITY) {
+		double resol = value/iNd; /* Average resolution, in degrees */
+		/* Approximate area of a small spherical eq_region [in degrees^2] */
+		double area  = resol * resol;
+		value = iNd / area; /* Density = # of points divided by the approx. area  */
+	      }
+	    }
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	case ODB_AGGR_STDEV:
+	case ODB_AGGR_VAR:
+	  {
+	    int iNd = 0;
+	    double avg = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi) {
+		avg += d[j];
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) avg /= iNd;
+	    value = 0;
+	    for (j=0; j<Nd; j++) {
+	      double dd = d[j];
+	      if (ABS(d[j]) != mdi) {
+		dd -= avg;
+		value += dd * dd;
+	      }
+	    }
+	    if (iNd > 1) {
+	      value = value/(iNd-1);
+	      if (flag == ODB_AGGR_STDEV) value = sqrt(value);
+	    }
+	    else if (iNd == 0)
+	      value = 0;
+	    else
+	      value = RMDI;
+	  }
+	  break;
+	case ODB_AGGR_MINLOC:
+	case ODB_AGGR_MAXLOC:
+	  if (daux && Nd > 0) {
+	    int iNd = 0;
+	    int jj = 0;
+	    /* In case the first one is a missing data indicator */
+	    while (jj<Nd && ABS(d[jj]) == mdi) jj++;
+	    if (jj<Nd) {
+	      j = jj;
+	      value_aux = d[j];
+	      value = daux[j];
+	      ++iNd;
+	      if (flag == ODB_AGGR_MAXLOC) {
+		for (j=jj+1; j<Nd; j++) {
+		  if (ABS(d[j]) != mdi) {
+		    if (value_aux > d[j]) {
+		      value_aux = d[j];
+		      value = daux[j];
+		    }
+		    ++iNd;
+		  }
+		}
+	      }
+	      else { /* ODB_AGGR_MINLOC */
+		for (j=jj+1; j<Nd; j++) {
+		  if (ABS(d[j]) != mdi) {
+		    if (value_aux < d[j]) {
+		      value_aux = d[j];
+		      value = daux[j];
+		    }
+		    ++iNd;
+		  }
+		}
+	      }
+	    } /* if (jj<Nd) */
+	    if (iNd == 0) {
+	      value_aux = RMDI;
+	      value = RMDI;
+	    }
+	  }
+	  break;
+	case ODB_AGGR_MIN:
+	case ODB_AGGR_MAX:
+	  {
+	    value = RMDI;
+	    if (Nd > 0) {
+	      int jj = 0;
+	      /* In case the first one is a missing data indicator */
+	      while (jj<Nd && ABS(d[jj]) == mdi) jj++;
+	      if (jj<Nd) {
+		j = jj;
+		value = d[j];
+		if (flag == ODB_AGGR_MIN) {
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi && value > d[j]) value = d[j];
+		  }
+		}
+		else { /* ODB_AGGR_MAX */
+		  for (j=jj+1; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi && value < d[j]) value = d[j];
+		  }
+		}
+	      } /* if (jj<Nd) */
+	    }
+	  }
+	  break;
+	case ODB_AGGR_LINREGR_A:
+	case ODB_AGGR_LINREGR_B:
+	case ODB_AGGR_CORR:
+	case ODB_AGGR_COVAR:
+	  /* y = A + B * x */
+	  value = RMDI;
+	  if (daux && Nd > 0) {
+	    int iNd = 0;
+	    double xavg = 0, yavg = 0; /* x := d[], y := daux[] */
+	    double top = 0, bot = 0;
+	    for (j=0; j<Nd; j++) {
+	      if (ABS(d[j]) != mdi && ABS(daux[j]) != mdi) {
+		xavg += d[j];
+		yavg += daux[j];
+		++iNd;
+	      }
+	    }
+	    if (iNd > 0) {
+	      xavg /= iNd;
+	      yavg /= iNd;
+	      for (j=0; j<Nd; j++) {
+		if (ABS(d[j]) != mdi && ABS(daux[j]) != mdi) {
+		  double dd = d[j] - xavg;
+		  top += (dd - xavg) * (daux[j] - yavg);
+		  bot += dd * dd;
+		}
+	      }
+	      if (bot == 0) bot = 1e-30;
+	      switch (flag) {
+	      case ODB_AGGR_LINREGR_A:
+		value_aux = top/bot; /* B */
+		value = yavg - value_aux * xavg; /* A */
+		break;
+	      case ODB_AGGR_LINREGR_B:
+		value = top/bot; /* B */
+		value_aux = yavg - value * xavg; /* A */
+		break;
+	      case ODB_AGGR_CORR:
+		{
+		  double sumx2 = 0, sumy2 = 0;
+		  double sumxy = 0;
+		  double sxy, sxx, syy;
+		  for (j=0; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi && ABS(daux[j]) != mdi) {
+		      sumxy += d[j] * daux[j];
+		      sumx2 += d[j] * d[j];
+		      sumy2 += daux[j] * daux[j];
+		    }
+		  }
+		  sxy = sumxy - iNd * xavg * yavg;
+		  sxx = sumx2 - iNd * xavg * xavg;
+		  syy = sumy2 - iNd * yavg * yavg;
+		  value = (sxx != 0 && syy != 0) ? (sxy * sxy)/(sxx * syy) : (double)0;
+		  value_aux = value;
+		  value = (value > 0) ? sqrt(value) : (double)0;
+		}
+		break;
+	      case ODB_AGGR_COVAR:
+		{
+		  double sumxy = 0;
+		  double sxy;
+		  for (j=0; j<Nd; j++) {
+		    if (ABS(d[j]) != mdi && ABS(daux[j]) != mdi) {
+		      sumxy += d[j] * daux[j];
+		    }
+		  }
+		  sxy = sumxy - iNd * xavg * yavg;
+		  value_aux = sxy;
+		  value = sxy / iNd;
+		}
+		break;
+	      }
+	    }
+	    else /* if (iNd > 0) ... */
+	      value = RMDI;
+	  }
+	  break;
+	}
+      }
+    }
+    else if (Nd == 1 && flag == ODB_AGGR_NONE) {
+      value = d[0];
+    }
+    rc[0] = value;
+    if (daux) rc[1] = value_aux;
+  }
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_calc_aggr_(const int    *phase_id,
+		const int    *aggr_func_flag,
+		int          *nrc,
+		double        rc[],
+		const int    *nd, 
+		const double  d[],
+		const double  daux[])
+{
+  DRHOOK_START(codb_calc_aggr_);
+  if (phase_id && aggr_func_flag && d && nd && nrc && rc) {
+    int Phase_id = *phase_id;
+    int Nrc = *nrc;
+    /* Note: Aggregate functions 
+       "covar", "corr", "linregr_a", "linregr_b",
+       are expected to have Nrc == 2 && daux[] specified */
+
+    if (Phase_id == 0) {
+      /* This means: pf->tmp has NOT yet been created i.e. using values from database */
+      CalcAggr0(aggr_func_flag, d, (Nrc==2 && daux) ? daux : NULL, nd, rc);
+    }
+    else if (Phase_id == 1) {
+      /* This means: pf->tmp is available; accumulate results */
+      /* daux[] is irrelevant */
+      CalcAggr1(aggr_func_flag, d, nd, rc);
+    }
+    else { /* Process all in one go: Supposed to be called at least, when ODBMP_nproc > 1 */
+      CalcAggrAll(aggr_func_flag, d, (Nrc==2 && daux) ? daux : NULL, nd, rc);
+    }
+  }
+  DRHOOK_END(0);
+}
diff --git a/odb/src/lib/alist.c b/odb/src/lib/alist.c
new file mode 100644
index 0000000..fb3f97a
--- /dev/null
+++ b/odb/src/lib/alist.c
@@ -0,0 +1,60 @@
+#include "odb.h"
+
+#define DELIM "|"
+
+PRIVATE char *list = NULL;
+
+PUBLIC void
+destroy_alist()
+{
+  FREE(list);
+}
+
+
+PUBLIC char *
+init_alist(const char *p)
+{
+  destroy_alist();
+  if (p) {
+    ALLOC(list, strlen(p) + 3);
+    sprintf(list,"%s%s%s",DELIM,p,DELIM);
+  }
+  else {
+    ALLOC(list,2);
+    strcpy(list,DELIM);
+  }
+  return list;
+}
+
+
+PUBLIC boolean 
+in_alist(const char *p)
+{
+  boolean found = 0;
+  if (list && p) {
+    char *token;
+    ALLOC(token, strlen(p) + 3);
+    sprintf(token,"%s%s%s",DELIM,p,DELIM);
+    found = (strstr(list, token) != NULL);
+    FREE(token);
+  }
+  return found;
+}
+
+PUBLIC char *
+add_alist(const char *p)
+{
+  if (!list) {
+    list = init_alist(p);
+  }
+  else {
+    int lenp = p ? strlen(p) : 0;
+    if (p && lenp > 0) {
+      int lenlist = strlen(list);
+      REALLOC(list, lenlist + lenp + 2);
+      strcat(list, p);
+      strcat(list, DELIM);
+    }
+  }
+  return list;
+}
diff --git a/odb/src/lib/append_num.F90 b/odb/src/lib/append_num.F90
new file mode 100644
index 0000000..205b370
--- /dev/null
+++ b/odb/src/lib/append_num.F90
@@ -0,0 +1,29 @@
+SUBROUTINE append_num(cdout, cdin, knum, cdelim, kdoutlen)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+implicit none
+character(len=*), intent(out) :: cdout
+character(len=*), intent(in) :: cdin
+character(len=*), intent(in), OPTIONAL :: cdelim
+INTEGER(KIND=JPIM), intent(in) :: knum
+INTEGER(KIND=JPIM), intent(out), OPTIONAL :: kdoutlen
+character(len=10) :: ch
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('APPEND_NUM',0,ZHOOK_HANDLE)
+write(ch,'(i10)') abs(knum)
+if (knum >= 0) then
+  if (present(cdelim)) then
+    cdout = trim(cdin)//trim(cdelim)//trim(adjustl(ch))
+  else
+    cdout = trim(cdin)//trim(adjustl(ch))
+  endif
+else ! turn '-' (sign/dash) into '_' (underscore) when no cdelim given
+  if (present(cdelim)) then
+    cdout = trim(cdin)//trim(cdelim)//'-'//trim(adjustl(ch))
+  else
+    cdout = trim(cdin)//'_'//trim(adjustl(ch))
+  endif
+endif
+if (present(kdoutlen)) kdoutlen = len_trim(cdout)
+IF (LHOOK) CALL DR_HOOK('APPEND_NUM',1,ZHOOK_HANDLE)
+END SUBROUTINE append_num
diff --git a/odb/src/lib/apply_poolmasking.F90 b/odb/src/lib/apply_poolmasking.F90
new file mode 100644
index 0000000..95f1d81
--- /dev/null
+++ b/odb/src/lib/apply_poolmasking.F90
@@ -0,0 +1,330 @@
+SUBROUTINE apply_poolmasking(khandle, kversion, &
+ & cdlabel, kvlabel, &
+ & ktslot, kobstype, kcodetype, ksensor, &
+ & ksubtype, kbufrtype, ksatinst) 
+
+!-- Please make sure that this routine is called under OpenMP CRITICAL-section
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+USE odb_module
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in) :: khandle, kversion, kvlabel
+character(len=*), intent(in) :: cdlabel
+INTEGER(KIND=JPIM), intent(in) :: ktslot, kobstype, kcodetype, ksensor
+INTEGER(KIND=JPIM), intent(in) :: ksubtype, kbufrtype, ksatinst
+
+INTEGER(KIND=JPIM), parameter :: OFF = 0
+INTEGER(KIND=JPIM) :: oldvalue, rc, poolno, nrows, ncols, nra, onoff, npools
+INTEGER(KIND=JPIM), allocatable :: pool_list(:,:)
+REAL(KIND=JPRB), allocatable :: zpool_list(:,:)
+INTEGER(KIND=JPIM) :: j, j1, j2
+character(len=9), save :: cvar(7) = (/'$obstype ',  &! 1
+ & '$codetype',  &! 2
+ & '$sensor  ',  &! 3
+ & '$tslot   ',  &! 4
+ & '$subtype ',  &! 5
+ & '$bufrtype',  &! 6
+ & '$satinst '/)  ! 7 
+REAL(KIND=JPRB) :: z(size(cvar))
+INTEGER(KIND=JPIM), parameter :: min_version = 1
+INTEGER(KIND=JPIM), parameter :: max_version = 3
+logical, save :: view_added(min_version:max_version)
+logical, save :: first_time = .TRUE.
+character(len=20) ::  viewname
+
+! Saved poolmask "image" (pimg) ; save NPMCACHE distinct calls in a circular buffer
+TYPE pimg_t 
+!!SEQUENCE -- commented out to eliminate a potential misalignment (SGI/Altix ifort/05-Oct-2005/SS)
+logical   :: in_use
+INTEGER(KIND=JPIM) :: handle, version
+INTEGER(KIND=JPIM) :: tslot, obstype, codetype, sensor
+INTEGER(KIND=JPIM) :: subtype, bufrtype, satinst
+INTEGER(KIND=JPIM) :: nrows, ncols
+INTEGER(KIND=JPIM) :: onoff
+INTEGER(KIND=JPIM), POINTER :: pool_list(:)
+character(len=80) ::  clabel
+END TYPE pimg_t
+INTEGER(KIND=JPIM), parameter :: NPMCACHE_MIN = 10
+INTEGER(KIND=JPIM), parameter :: NPMCACHE_DEFAULT = 100
+INTEGER(KIND=JPIM), save      :: NPMCACHE = NPMCACHE_DEFAULT
+INTEGER(KIND=JPIM), save      :: inext   = 1
+INTEGER(KIND=JPIM), save      :: maxever = 0
+TYPE(pimg_t), allocatable, save :: pimg(:)
+logical, allocatable, save :: poolmask_table_exist(:) ! maxhandle from odbshared.F90
+logical, allocatable, save :: existence_tested(:) ! maxhandle from odbshared.F90
+INTEGER(KIND=JPIM) :: it, inumt
+INTEGER(KIND=JPIM), external :: get_max_threads, get_thread_id
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',0,ZHOOK_HANDLE)
+if (khandle < 0 .OR. khandle > maxhandle .AND. LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+if (khandle < 0 .OR. khandle > maxhandle) return ! Security
+
+it = get_thread_id()
+
+if (first_time) then
+  CALL util_igetenv('ODB_POOLMASK_CACHE', NPMCACHE_DEFAULT, NPMCACHE)
+  if (NPMCACHE < NPMCACHE_MIN) NPMCACHE = NPMCACHE_MIN
+  allocate(pimg(NPMCACHE))
+  do j=1,NPMCACHE
+    pimg(j)%in_use   = .FALSE.
+    pimg(j)%handle   = -1
+    pimg(j)%version  =  0
+    pimg(j)%tslot    = -1
+    pimg(j)%obstype  = -1
+    pimg(j)%codetype = -1
+    pimg(j)%sensor   = -1
+    pimg(j)%subtype  = -1
+    pimg(j)%bufrtype = -1
+    pimg(j)%satinst  = -1
+    pimg(j)%nrows    =  0
+    pimg(j)%ncols    =  0
+    pimg(j)%onoff    = -1
+    nullify(pimg(j)%pool_list)
+    pimg(j)%clabel    = '<undefined>'
+  enddo
+  allocate(poolmask_table_exist(maxhandle))
+  poolmask_table_exist(:) = .FALSE.
+  allocate(existence_tested(maxhandle))
+  existence_tested(:) = .FALSE.
+  view_added(:) = .FALSE.
+  first_time = .FALSE.
+endif
+
+if (kversion ==  0) then
+!-- Release memories populated by khandle
+  do j=1,maxever
+    if (pimg(j)%in_use .AND. pimg(j)%handle == khandle) then
+      pimg(j)%in_use = .FALSE.
+      pimg(j)%handle = -1
+      if (associated(pimg(j)%pool_list)) then
+        deallocate(pimg(j)%pool_list)
+        nullify(pimg(j)%pool_list)
+      endif
+    endif
+  enddo
+
+  poolmask_table_exist(khandle) = .FALSE.
+  existence_tested(khandle) = .FALSE.
+
+  if (it == 1) then ! Only master thread does this
+    inumt = get_max_threads()
+    do j=1,inumt
+      CALL cODB_reset_poolmask(khandle, j)
+    enddo
+  endif
+
+  IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+  return
+endif
+
+if (kversion < 0) then
+!-- Reset whatever was saved from the previous call
+  CALL cODB_reset_poolmask(khandle, it)
+  IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+  return
+endif
+
+if (kversion < min_version .or. kversion > max_version .AND. LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+if (kversion < min_version .or. kversion > max_version) return
+
+!-- Check if we can re-use anything from the most recent call(s) ?
+
+do j=1,maxever
+  if (pimg(j)%in_use .AND. &
+     & pimg(j)%handle   == khandle   .AND. &
+     & pimg(j)%version  == kversion  .AND. &
+     & pimg(j)%tslot    == ktslot    .AND. &
+     & pimg(j)%obstype  == kobstype  .AND. &
+     & pimg(j)%codetype == kcodetype .AND. &
+     & pimg(j)%sensor   == ksensor   .AND. &
+     & pimg(j)%subtype  == ksubtype  .AND. &
+     & pimg(j)%bufrtype == kbufrtype .AND. &
+     & pimg(j)%satinst  == ksatinst  .AND. &
+     & pimg(j)%nrows > 0 .AND. pimg(j)%ncols > 0 .AND. &
+     & associated(pimg(j)%pool_list)) then 
+!!    pimg(j)%clabel = cdlabel
+    write(pimg(j)%clabel,'(a,"-",i12)') trim(cdlabel), kvlabel
+    CALL cODB_set_poolmask(khandle, pimg(j)%nrows, pimg(j)%pool_list(1), pimg(j)%onoff)
+    CALL pm_debug_out()
+    IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+    return
+  endif
+enddo
+
+z(:) = -1
+
+if (kversion == 1) then      ! (obstype,codetype,sensor) present
+
+  j1 = 1
+  j2 = 3
+  z(1) = kobstype
+  if (abs(kobstype ) == abs(ODB_NMDI) .or. kobstype  == -1) j1 = 2
+  z(2) = kcodetype
+  if (abs(kcodetype) == abs(ODB_NMDI) .or. kcodetype == -1) z(2) = -1
+  z(3) = ksensor
+  if (abs(ksensor  ) == abs(ODB_NMDI) .or. ksensor   == -1) j2 = 2
+
+ELSEIF (kversion == 2) then ! (obstype,codetype,sensor,tslot) present
+
+  j1 = 1
+  j2 = 4
+  z(1) = kobstype
+  if (abs(kobstype ) == abs(ODB_NMDI) .or. kobstype  == -1) j1 = 2
+  z(2) = kcodetype
+  if (abs(kcodetype) == abs(ODB_NMDI) .or. kcodetype == -1) z(2) = -1
+  z(3) = ksensor
+  if (abs(ksensor  ) == abs(ODB_NMDI) .or. ksensor   == -1) z(3) = -1
+  z(4) = ktslot
+  if (abs(ktslot   ) == abs(ODB_NMDI) .or. ktslot    == -1) j2 = 3
+
+ELSEIF (kversion == 3) then ! (subtype,bufrtype,satinst) present
+
+  j1 = 5
+  j2 = 7
+  z(5) = ksubtype
+  if (abs(ksubtype ) == abs(ODB_NMDI) .or. ksubtype  == -1) j1 = 6
+  z(6) = kbufrtype
+  if (abs(kbufrtype) == abs(ODB_NMDI) .or. kbufrtype == -1) z(2) = -1
+  z(7) = ksatinst
+  if (abs(ksatinst)  == abs(ODB_NMDI) .or. ksatinst  == -1) j2 = 6
+
+endif
+
+!-- Poolmask is available on EVERY pool; so apply on first mypool i.e. ODBMP_myproc !
+poolno = ODBMP_myproc
+
+!-- Make sure that "poolno" is masked-in i.e. disable any existing poolmasks for the moment
+CALL cODB_toggle_poolmask(khandle, OFF, oldvalue)
+
+!-- Check that @poolmask-table has been created and has > 0 entries
+if (.NOT.existence_tested(khandle)) then
+  CALL cODB_poolmasking_status(khandle, rc)
+  if (rc == 1) then
+    rc = ODB_getsize(khandle, '@poolmask', nrows, ncols, poolno=poolno)
+    poolmask_table_exist(khandle) = (nrows > 0)
+  else
+    poolmask_table_exist(khandle) = .FALSE.
+  endif
+  existence_tested(khandle) = .TRUE.
+endif
+
+if (.NOT.poolmask_table_exist(khandle)) then
+  CALL cODB_toggle_poolmask(khandle, oldvalue, rc)
+  IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+  return
+endif
+
+!-- Construct view name 
+CALL append_num(viewname, 'poolmask_', kversion)
+
+!-- Add view name to the list of known views
+if (.not.view_added(kversion)) then
+  rc = ODB_addview(khandle, viewname)
+  view_added(kversion) = .TRUE.
+endif
+
+!-- Select data : get poolmasks that satisfy SQL to be executed
+rc = ODB_select(khandle, viewname, nrows, ncols, nra=nra, poolno=poolno, &
+ & setvars=cvar(j1:j2), values=z(j1:j2)) 
+
+if (nrows > 0) then
+!-- ODB_select() found something ==> found pools must be turned ON
+  onoff = 1
+  allocate(zpool_list(nra, 0:ncols))
+  rc = ODB_get(khandle, viewname, zpool_list, nrows, ncols, poolno=poolno)
+  allocate(pool_list(nra, ncols))
+  pool_list(1:nrows,1:ncols) = zpool_list(1:nrows,1:ncols)
+  deallocate(zpool_list)
+  CALL keysort(rc, pool_list(1:nrows,1), nrows)
+else
+!-- ODB_select() found nothing ==> ALL pools must be turned OFF
+  onoff = 0
+  npools = db(khandle)%glbNpools
+  nrows = npools
+  ncols = 1
+  allocate(pool_list(nrows,ncols))
+  do j=1,nrows
+    pool_list(j,1) = j
+  enddo
+endif
+
+rc = ODB_cancel(khandle, viewname, poolno=poolno)
+
+!-- Enable (possible) old poolmask
+CALL cODB_toggle_poolmask(khandle, oldvalue, rc)
+
+!-- Change poolmask (internally per OpenMP thread!) & release space occupied by pool_list
+if (allocated(pool_list)) then
+  CALL cODB_set_poolmask(khandle, nrows, pool_list(1,1), onoff)
+  j = inext
+  pimg(j)%in_use   = .TRUE.
+  pimg(j)%handle   = khandle
+  pimg(j)%version  = kversion
+  pimg(j)%tslot    = ktslot
+  pimg(j)%obstype  = kobstype
+  pimg(j)%codetype = kcodetype
+  pimg(j)%sensor   = ksensor
+  pimg(j)%subtype  = ksubtype
+  pimg(j)%bufrtype = kbufrtype
+  pimg(j)%satinst  = ksatinst
+  pimg(j)%nrows    = nrows
+  pimg(j)%ncols    = ncols
+  pimg(j)%onoff    = onoff
+  if (associated(pimg(j)%pool_list)) deallocate(pimg(j)%pool_list)
+  allocate(pimg(j)%pool_list(nrows))
+  pimg(j)%pool_list(1:nrows) = pool_list(1:nrows,1)
+!!  pimg(j)%clabel = cdlabel
+  write(pimg(j)%clabel,'(a,"-",i12)') trim(cdlabel), kvlabel
+
+  maxever = max(maxever, j)
+  inext = mod(inext, NPMCACHE) + 1 ! circularity
+  deallocate(pool_list)
+
+  CALL pm_debug_out()
+endif
+IF (LHOOK) CALL DR_HOOK('APPLY_POOLMASKING',1,ZHOOK_HANDLE)
+
+CONTAINS
+
+subroutine pm_debug_out()
+implicit none
+logical, save :: first_time_here = .TRUE.
+INTEGER(KIND=JPIM), parameter :: ipm_debug_def = 0
+INTEGER(KIND=JPIM), save      :: ipm_debug = 0
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('PM_DEBUG_OUT',0,ZHOOK_HANDLE)
+if (first_time_here) then
+  CALL util_igetenv('ODB_POOLMASK_DEBUG', ipm_debug_def, ipm_debug)
+  if (ipm_debug == -1 .OR. ipm_debug == ODBMP_myproc) then
+    ipm_debug = ODBMP_myproc
+  endif
+  first_time_here = .FALSE.
+endif
+
+if (ipm_debug == ODBMP_myproc) then
+  write(0,*) ODBMP_myproc,': it=',it,' Using pool_list#',j,&
+   & '; poolmask-onoff =',pimg(j)%onoff,&
+   & ' for h,ver,t,ot,cdt,sen,sub,bfr,sat=',&
+   & pimg(j)%handle, pimg(j)%version, &
+   & pimg(j)%tslot, pimg(j)%obstype, pimg(j)%codetype, pimg(j)%sensor, &
+   & pimg(j)%subtype, pimg(j)%bufrtype, pimg(j)%satinst 
+  write(0,*) ODBMP_myproc,': pool_list#, list_length, label=',j,pimg(j)%nrows,&
+   & ' "'//trim(pimg(j)%clabel)//'"' 
+  write(0,'(16i5)') pimg(j)%pool_list(1:pimg(j)%nrows)
+  call flush(0)
+  CALL cODB_print_poolmask(pimg(j)%handle, it)
+endif
+IF (LHOOK) CALL DR_HOOK('PM_DEBUG_OUT',1,ZHOOK_HANDLE)
+end subroutine pm_debug_out
+
+END SUBROUTINE apply_poolmasking
diff --git a/odb/src/lib/bsslzr_odb.F90 b/odb/src/lib/bsslzr_odb.F90
new file mode 100644
index 0000000..06862b1
--- /dev/null
+++ b/odb/src/lib/bsslzr_odb.F90
@@ -0,0 +1,97 @@
+SUBROUTINE BSSLZR_ODB(PBES,KNUM)
+
+!**** *BSSLZR_ODB* - ROUTINE TO RETURN ZEROS OF THE J0 *BESSEL FUNCTION.
+
+!     PURPOSE.
+!     --------
+
+!          *BSSLZR_ODB* RETURNS *KNUM* ZEROS, OR IF *KNUM>50,* *KNUM*
+!     APPROXIMATE ZEROS OF THE *BESSEL FUNCTION J0.
+
+!**   INTERFACE.
+!     ----------
+
+!          *CALL* *BSSLZR_ODB(PBES,KNUM)*
+
+!               *PBES*   - ARRAY, DIMENSIONED *KNUM,* TO RECEIVE THE
+!                          VALUES.
+!               *KNUM*   - NUMBER OF ZEROS REQUESTED.
+
+!     METHOD.
+!     -------
+
+!          THE FIRST 50 VALUES ARE OBTAINED FROM A LOOK UP TABLE. ANY
+!     ADDITIONAL VALUES REQUESTED ARE INTERPOLATED.
+
+!     EXTERNALS.
+!     ----------
+
+!          NONE.
+
+!     REFERENCE.
+!     ----------
+
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+
+INTEGER(KIND=JPIM), intent(in) :: KNUM
+REAL(KIND=JPRB), intent(out)   :: PBES(KNUM)
+! === END OF INTERFACE BLOCK ===
+
+!     LOCAL INTEGER SCALARS
+INTEGER(KIND=JPIM) :: INUM, J
+
+DIMENSION ZBES(50)
+
+!     LOCAL REAL SCALARS
+REAL(KIND=JPRB) :: ZAPI, ZBES, ZPI
+
+DATA ZBES        / 2.4048255577_JPRB,   5.5200781103_JPRB,&
+    &8.6537279129_JPRB,  11.7915344391_JPRB,  14.9309177086_JPRB,  18.0710639679_JPRB,&
+   &21.2116366299_JPRB,  24.3524715308_JPRB,  27.4934791320_JPRB,  30.6346064684_JPRB,&
+   &33.7758202136_JPRB,  36.9170983537_JPRB,  40.0584257646_JPRB,  43.1997917132_JPRB,&
+   &46.3411883717_JPRB,  49.4826098974_JPRB,  52.6240518411_JPRB,  55.7655107550_JPRB,&
+   &58.9069839261_JPRB,  62.0484691902_JPRB,  65.1899648002_JPRB,  68.3314693299_JPRB,&
+   &71.4729816036_JPRB,  74.6145006437_JPRB,  77.7560256304_JPRB,  80.8975558711_JPRB,&
+   &84.0390907769_JPRB,  87.1806298436_JPRB,  90.3221726372_JPRB,  93.4637187819_JPRB,&
+   &96.6052679510_JPRB,  99.7468198587_JPRB, 102.8883742542_JPRB, 106.0299309165_JPRB,&
+  &109.1714896498_JPRB, 112.3130502805_JPRB, 115.4546126537_JPRB, 118.5961766309_JPRB,&
+  &121.7377420880_JPRB, 124.8793089132_JPRB, 128.0208770059_JPRB, 131.1624462752_JPRB,&
+  &134.3040166383_JPRB, 137.4455880203_JPRB, 140.5871603528_JPRB, 143.7287335737_JPRB,&
+  &146.8703076258_JPRB, 150.0118824570_JPRB, 153.1534580192_JPRB, 156.2950342685_JPRB/
+
+
+!     ------------------------------------------------------------------
+
+!*         1.     EXTRACT VALUES FROM LOOK UP TABLE.
+
+
+100 CONTINUE
+ZAPI=2.0_JPRB*ASIN(1.0_JPRB)
+INUM=MIN(KNUM,50)
+
+DO 110 J=1,INUM
+  PBES(J)=ZBES(J)
+110 CONTINUE
+
+!     ------------------------------------------------------------------
+
+!*         2.     INTERPOLATE REMAINING VALUES.
+!                 ----------- --------- -------
+
+200 CONTINUE
+
+IF (KNUM > 50) THEN
+  ZPI=ZAPI
+  DO 210 J=51,KNUM
+    PBES(J)=PBES(J-1)+ZPI
+  210 CONTINUE
+ENDIF
+
+!     ------------------------------------------------------------------
+
+RETURN
+END SUBROUTINE BSSLZR_ODB
diff --git a/odb/src/lib/ckeysort.F90 b/odb/src/lib/ckeysort.F90
new file mode 100644
index 0000000..3413328
--- /dev/null
+++ b/odb/src/lib/ckeysort.F90
@@ -0,0 +1,49 @@
+SUBROUTINE ckeysort(pa, kra, krows, kcols, &
+                   & keys, k_nkeys, &
+                   & kidx, k_nidx, k_init_idx, &
+                   & kret)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE ECSORT_MIX    ,ONLY : KEYSORT
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)    :: kra, krows, kcols, k_nkeys, k_nidx, k_init_idx
+REAL(KIND=JPRB), intent(inout)    :: pa(kra, kcols)
+INTEGER(KIND=JPIM), intent(in)    :: keys(k_nkeys)
+INTEGER(KIND=JPIM), intent(inout) :: kidx(k_nidx)
+INTEGER(KIND=JPIM), intent(out)   :: kret
+
+logical :: LLinit, LLdescending
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CKEYSORT',0,ZHOOK_HANDLE)
+
+kret = krows
+
+if (krows > 1) then
+   if (k_nidx < krows) then
+      if (k_nkeys > 0) then
+         if (k_nkeys == 1 .and. kcols == 1) then
+            LLdescending = (keys(1) < 0)
+            CALL keysort(kret, pa(1:kra,1), krows, descending=LLdescending)
+         else
+            CALL keysort(kret, pa, krows, multikey=keys)
+         endif
+      else
+         CALL keysort(kret, pa, krows)
+      endif
+   else ! use index
+      LLinit = (k_init_idx > 0)
+      if (k_nkeys > 0) then
+         CALL keysort(kret, pa, krows, multikey=keys, index=kidx, init=LLinit)
+      else
+         CALL keysort(kret, pa, krows, index=kidx, init=LLinit)
+      endif
+   endif
+endif
+
+IF (LHOOK) CALL DR_HOOK('CKEYSORT',1,ZHOOK_HANDLE)
+
+END SUBROUTINE ckeysort
diff --git a/odb/src/lib/cmdbkeys.c b/odb/src/lib/cmdbkeys.c
new file mode 100644
index 0000000..6b9f879
--- /dev/null
+++ b/odb/src/lib/cmdbkeys.c
@@ -0,0 +1,748 @@
+
+/* cmdbkeys.c */
+
+#include "odb.h"
+
+/* Fortran-callable functions to associate Fortran MDBxxx -keys
+   with table/view columns at run-time */
+
+/*--- Defines functions:
+
+  Initialization (a scalar):
+  CALL cmdb_reg('lat at hdr', 'MDBLAT', MDBLAT, it, rc)
+
+  Initialization (a vector):
+  CALL cmdb_vecreg('initial at update', 'MDBIOM0', MDBIOM0, 1, JPMXUP, it, rc)
+  CALL cmdb_vecreg('LINK(body)@hdr', 'MLNK_hdr2body', MLNK_hdr2body, 1, 2, it, rc)
+
+  Set MDB column indecides directly by using a vector of MDB-pointer addresses
+  CALL cmdb_vecset(zaddr, n_zaddr, rc)
+
+  Set MDBLAT to actual_column_index:
+  CALL cmdb_set('lat at hdr', actual_column_index, it, rc)
+
+  Reset all MDBxxx -keys to MDIDB:
+  CALL cmdb_reset('*', reset_value, it, rc)
+
+  Resets particular columns MDBxxx value to MDIDB:
+  CALL cmdb_reset('lat at hdr', reset_value, it, rc)
+
+  Inquire current value of MDBxxx -key:
+  CALL cmdb_get('lat at hdr', get_value, it, rc)
+
+  Inquire address of MDBxxx -key:
+  CALL cmdb_addr('lat at hdr', zaddr, it, rc)
+
+  Debug printout to STDERR:
+  CALL cmdb_debug(enforce=[0|1],message)
+
+  Returns string 'MDBxxx' for a given column :
+  character(len=*) cMDBxxx
+  CALL cmdb_name('lat at hdr', cMDBxxx, rc)
+
+  Print 'MDBxxx' and their values and references to STDERR (unit=0; default) or STDOUT (unit=6)
+  CALL cmdb_print(unit, message, only_active, it, rc)
+
+ */
+
+
+#ifndef MDB_HASHSIZE
+#define MDB_HASHSIZE 1031U
+#endif
+
+PRIVATE uint CMDBKEYS_hashsize = 0;
+
+typedef struct _MDB_Hash_Table {
+  char *colname;
+  char *mdbname;
+  int *mdbkey; /* Note: Fortran INTEGER address */
+  int active_cnt;
+  struct _MDB_Hash_Table *collision;
+} MDB_Hash_Table;
+
+typedef  union _MDB_Union {
+  int *mdbptr;
+  double d;
+} MDB_Union;
+
+PRIVATE MDB_Hash_Table **CMDBKEYS_hashtable = NULL;
+
+PRIVATE uint
+Hash(const char *s, int slen, int *lenout)
+{ 
+  uint hashval = 0;
+  const char *ss = s;
+  for (; slen-- > 0 && *s && *s != ' ' ; s++) {
+    hashval = (*s) + 31U * hashval;
+  }
+  hashval = hashval % CMDBKEYS_hashsize;
+  if (lenout) *lenout = s - ss;
+  return hashval;
+}
+
+
+PRIVATE void
+HashInit()
+{
+  if (!CMDBKEYS_hashtable) {
+    MDB_Hash_Table **tmp_CMDBKEYS_hashtable = NULL;
+    int inumt = get_max_threads_();
+    int it;
+    char *p = getenv("ODB_MDB_HASHSIZE");
+    if (p) {
+      CMDBKEYS_hashsize = atoi(p);
+      if (CMDBKEYS_hashsize <= 0) CMDBKEYS_hashsize = MDB_HASHSIZE;
+    }
+    else
+      CMDBKEYS_hashsize = MDB_HASHSIZE;
+    ALLOC(tmp_CMDBKEYS_hashtable, inumt + 1); /* entry 0 is unused, 1..inumt for threads */
+    for (it = 0; it <= inumt ; it++) {
+      CALLOC(tmp_CMDBKEYS_hashtable[it], CMDBKEYS_hashsize);
+    }
+    CMDBKEYS_hashtable = tmp_CMDBKEYS_hashtable;
+  }
+}
+
+PRIVATE MDB_Hash_Table *
+NewEntry(void)
+{
+  MDB_Hash_Table *p;
+  ALLOC(p, 1);
+  p->colname = NULL;
+  p->mdbname = NULL;
+  p->mdbkey  = NULL;
+  p->active_cnt = 0;
+  p->collision = NULL;
+  return p;
+}
+
+PUBLIC void
+init_CMDBKEYS_lock()
+{
+  HashInit();
+}
+
+/*
+  Returns string 'MDBxxx' for a given column :
+  character(len=*) cMDBxxx
+  CALL cmdb_name('lat at hdr', cMDBxxx, rc)
+ */
+
+PUBLIC void 
+cmdb_name_(const char *colname,
+           char mdbname[],
+           int *retcode,
+           /* Hidden arguments */
+                 int colname_len,
+           const int mdbname_len)
+{
+  Bool is_formula = false;
+  int rc = 0;
+
+  if (mdbname_len > 0) {
+    int it = 1; /* In this case getting the "it" from the master thread#1 is ok for any thread */
+    uint index;
+    MDB_Hash_Table *p;
+    DECL_FTN_CHAR(colname);
+    DECL_FTN_CHAR(mdbname);
+
+    ALLOC_FTN_CHAR(colname);
+    ALLOC_OUTPUT_FTN_CHAR(mdbname);
+
+    rc = index = Hash(p_colname, colname_len, NULL);
+    p = &CMDBKEYS_hashtable[it][index];
+
+    if (p && p->colname) {
+      while (p && p->colname) {
+        if (strequ(p->colname, p_colname)) {
+          strncpy(p_mdbname, p->mdbname, mdbname_len);
+          break; /* The first occurence will do */
+        }
+        if (p->collision) 
+          p = p->collision;
+        else {
+	  int myproc = 0;
+	  codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+	  is_formula = strstr(p_colname,"@Formula") ? true : false; /* bailout if a formula */
+          rc = -2;
+/*
+	  if (!is_formula || (is_formula && myproc == 1)) {
+	    fprintf(stderr,
+		    "cmdb_name_:  Unrecognized column name '%s' for it#%d [rc=-2]\n",
+		    p_colname, it);
+	  }
+*/
+          goto finish; /* Unrecognized column name */
+        }
+      } /* while (p && p->colname) */  
+    }
+    else {
+      int myproc = 0;
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      is_formula = strstr(p_colname,"@Formula") ? true : false; /* bailout if a formula */
+      rc = -1;
+      if (!is_formula || (is_formula && myproc == 1)) {
+	fprintf(stderr,
+		"cmdb_name_:  Column '%s' is not registered for it#%d [rc=-1]\n",
+		p_colname, it);
+      }
+      goto finish; /* Column not registered */
+    } /* if (p && p->colname) ... else ... */ 
+
+  finish:
+    COPY_2_FTN_CHAR(mdbname);
+    FREE_FTN_CHAR(colname);
+
+    if (rc < 0 && !is_formula) RAISE(SIGABRT);
+  } /* if (mdbname_len > 0) */
+
+  *retcode = rc;
+}
+
+/*
+ */
+
+/*---
+  Initialization (a scalar):
+  CALL cmdb_reg('lat at hdr', 'MDBLAT', MDBLAT, it, rc)
+  ---*/
+
+PUBLIC void
+cmdb_reg_(const char *colname,
+          const char *mdbname,
+          int *mdbkey,
+          const int *It,
+          int *retcode,
+          /* Hidden arguments */
+          int colname_len,
+          int mdbname_len)
+{
+  int rc = 0;
+  int it = *It;
+  uint index;
+  MDB_Hash_Table *p;
+  DECL_FTN_CHAR(colname);
+  DECL_FTN_CHAR(mdbname);
+
+  ALLOC_FTN_CHAR(colname);
+  ALLOC_FTN_CHAR(mdbname);
+
+  rc = index = Hash(p_colname, colname_len, NULL);
+  p = &CMDBKEYS_hashtable[it][index];
+
+  while (p && p->colname) {
+    if (strequ(p->colname, p_colname)) {
+      if (p->mdbkey != mdbkey) {
+	fprintf(stderr,
+		"cmdb_reg_(it#%d): Cannot re-register colname='%s' to a "
+		"different (mdbname,addr)=('%s',%p)"
+		" since already registered to ('%s',%p, it#%d)\n",
+		it, p_colname, p_mdbname, mdbkey, p->mdbname, p->mdbkey, it);
+	rc = -1;
+	RAISE(SIGABRT);
+      }
+      goto finish; /* Already in list */
+    }
+    if (!p->collision) p->collision = NewEntry();
+    p = p->collision;
+  } /* while (p && p->colname) */
+
+  p->colname = STRDUP(p_colname);
+  p->mdbname = STRDUP(p_mdbname);
+  p->mdbkey  = mdbkey;
+  p->active_cnt = 0;
+
+ finish:
+  FREE_FTN_CHAR(mdbname);
+  FREE_FTN_CHAR(colname);
+
+  *retcode = rc;
+}
+
+/*---
+  Initialization (a vector):
+  CALL cmdb_vecreg('initial at update', 'MDBIOM0', MDBIOM0, 1, JPMXUP, it, rc)
+  CALL cmdb_vecreg('LINK(body)@hdr', 'MLNK_hdr2body', MLNK_hdr2body, 1, 2, it, rc)
+  ---*/
+
+PUBLIC void
+cmdb_vecreg_(const char *colname,
+             const char *mdbname,
+             int vecmdbkey[],
+             const int *low,
+             const int *high,
+             const int *It,
+             int *retcode,
+             /* Hidden arguments */
+             int colname_len,
+             int mdbname_len)
+{
+  int rc = 0;
+  int it = *It;
+  int k1 = *low;
+  int k2 = *high;
+  DECL_FTN_CHAR(colname);
+  DECL_FTN_CHAR(mdbname);
+
+  ALLOC_FTN_CHAR(colname);
+  ALLOC_FTN_CHAR(mdbname);
+
+  if (k1 == 1 && k2 == 2 && strnequ(p_colname,"LINK(",5)) {
+    /* We have to set up for LINKOFFSET (=1) and LINKLEN (=2) */
+    char *col, *mdb;
+    int *addr;
+    int lencol, lenmdb;
+    char *s = strchr(p_colname,'(');
+    
+    lencol = strlen("LINKOFFSET") + strlen(s) + 1;
+    ALLOC(col, lencol);
+    sprintf(col,"LINKOFFSET%s",s);
+    lenmdb = strlen(p_mdbname) + 4;
+    ALLOC(mdb, lenmdb);
+    sprintf(mdb,"%s(1)",p_mdbname);
+    addr = &vecmdbkey[k1-1];
+    cmdb_reg_(col, mdb, addr, It, &rc, lencol, lenmdb);
+    FREE(col);
+    FREE(mdb);
+    if (rc < 0) goto finish;
+
+    lencol = strlen("LINKLEN") + strlen(s) + 1;
+    ALLOC(col, lencol);
+    sprintf(col,"LINKLEN%s",s);
+    lenmdb = strlen(p_mdbname) + 4;
+    ALLOC(mdb, lenmdb);
+    sprintf(mdb,"%s(2)",p_mdbname);
+    addr = &vecmdbkey[k2-1];
+    cmdb_reg_(col, mdb, addr, It, &rc, lencol, lenmdb);
+    FREE(col);
+    FREE(mdb);
+    if (rc < 0) goto finish;
+  }
+  else if (k1 <= k2) {
+    char *col, *mdb;
+    int *addr;
+    int lencol, lenmdb;
+    int k;
+    char *s = strchr(p_colname,'@');
+    char *str;
+    char *p;
+    double d;
+    int numdigits;
+
+    if (!s) {
+      fprintf(stderr,
+              "cmdb_vecreg_: colname='%s' for mdbname='%s' has no '@'-sign\n",
+              p_colname, p_mdbname);
+      rc = -1;
+      RAISE(SIGABRT);
+      goto finish;
+    }
+
+    str = STRDUP(p_colname);
+    p = strchr(str,'@');
+    *p = '\0';
+
+    d = ABS(MAX(ABS(k1), ABS(k2)));
+    d = MAX(d,1);
+    numdigits = log10(d) + 1;
+
+    lencol = strlen(str) + strlen(p+1) + numdigits + 4;
+    ALLOC(col, lencol);
+
+    lenmdb = strlen(p_mdbname) + numdigits + 3;
+    ALLOC(mdb, lenmdb);
+
+    if (k1 < 0) {
+      int kend = MIN(k2,-1);
+      for (k=k1; k<=kend; k++) {
+        sprintf(col,"%s__%d@%s",str,ABS(k),p+1);
+        sprintf(mdb,"%s(%d)",p_mdbname,ABS(k));
+        addr = &vecmdbkey[k-1];
+        cmdb_reg_(col, mdb, addr, It, &rc, strlen(col), strlen(mdb));
+        if (rc < 0) break;
+      }
+      k1 = 0;
+    }
+
+    if (rc == 0 && k1 >= 0) {
+      for (k=k1; k<=k2; k++) {
+        sprintf(col,"%s_%d@%s",str,k,p+1);
+        sprintf(mdb,"%s(%d)",p_mdbname,k);
+        addr = &vecmdbkey[k-1];
+        cmdb_reg_(col, mdb, addr, It, &rc, strlen(col), strlen(mdb));
+        if (rc < 0) break;
+      }
+    }
+
+    FREE(mdb);
+    FREE(col);
+    FREE(str);
+
+    if (rc < 0) goto finish;
+  }
+  else {
+    fprintf(stderr,
+            "cmdb_vecreg_: start index=%d greater than end index=%d in colname='%s', mdbname='%s'\n",
+            k1, k2,
+            p_colname, p_mdbname);
+    rc = -2;
+    RAISE(SIGABRT);
+    goto finish;
+  }
+
+ finish:
+  FREE_FTN_CHAR(mdbname);
+  FREE_FTN_CHAR(colname);
+
+  *retcode = rc;
+}
+
+/*---
+  Set MDB column indecides directly by using a vector of MDB-pointer addresses
+  CALL cmdb_vecset(zaddr, n_zaddr, rc)
+  ---*/
+
+PUBLIC void
+cmdb_vecset_(const double zaddr[],
+	     const int *n_zaddr,
+	     int *retcode)
+{
+  int j, ncols = *n_zaddr;
+  MDB_Union u;
+  for (j=0; j<ncols; j++) {
+    u.d = zaddr[j];
+    if (u.mdbptr) *u.mdbptr = j+1; /* "+1" due to Fortran indexing */
+  }
+  *retcode = ncols;
+}
+
+/*---
+  Set MDBLAT to actual_column_index:
+  CALL cmdb_set('lat at hdr', actual_column_index, it, rc)
+  ---*/
+
+
+PUBLIC void
+cmdb_set_(const char *colname,
+          const int *actual_column_index,
+          const int *It,
+          int *retcode,
+          /* Hidden arguments */
+          int colname_len)
+{
+  /* Note: This routine is optimized i.e. DECL_FTN, ALLOC_FTN -stuff removed 
+           and actual colname_len obtained while evaluating Hash() */
+  int rc = 0;
+  int count = 0;
+  int it = *It;
+  uint index;
+  MDB_Hash_Table *p;
+
+  rc = index = Hash(colname, colname_len, &colname_len);
+  p = &CMDBKEYS_hashtable[it][index];
+
+  while (p && p->colname) {
+    if (strnequ(p->colname, colname, colname_len)) {
+      if (p->mdbkey) *p->mdbkey = *actual_column_index;
+      p->active_cnt++;
+      count++;
+    }
+    p = p->collision;
+  } /* while (p && p->colname) */
+
+  if (count == 0) {
+    fprintf(stderr,
+            "cmdb_set_: Column '%*s' not registered for it#%d\n",
+            colname_len, colname, it);
+    rc = -2;
+    RAISE(SIGABRT);
+    goto finish; /* Column not found */
+  }
+
+ finish:
+
+  *retcode = rc;
+}
+
+
+
+/*---
+  Reset all MDBxxx -keys to MDIDB:
+  CALL cmdb_reset('*', reset_value, it, rc)
+
+  Resets particular columns MDBxxx value to MDIDB:
+  CALL cmdb_reset('lat at hdr', reset_value, it, rc)
+  ---*/
+
+
+PUBLIC void
+cmdb_reset_(const char *colname,
+            int *reset_value,
+            const int *It,
+            int *retcode,
+            /* Hidden arguments */
+            int colname_len)
+{
+  int rc = 0;
+  int it = *It;
+
+  if (strnequ(colname,"*",colname_len)) {
+    uint j;
+    for (j=0; j<CMDBKEYS_hashsize; j++) {
+      MDB_Hash_Table *p = &CMDBKEYS_hashtable[it][j];
+      while (p && p->colname) {
+        if (p->mdbkey) {
+          *p->mdbkey = *reset_value;
+          p->active_cnt = 0;
+        }
+        p = p->collision;
+      } /* while (p && p->colname) */
+    } /* for (j=0; j<CMDBKEYS_hashsize; j++) */
+  }
+  else {
+    cmdb_set_(colname, reset_value, It, &rc, colname_len);
+  }
+
+  /* finish: */
+
+  *retcode = rc;
+}
+
+
+/*---
+  Inquire current value of MDBxxx -key:
+  CALL cmdb_get('lat at hdr', get_value, it, rc)
+  ---*/
+
+
+PUBLIC void
+cmdb_get_(const char *colname,
+          int *get_value,
+          const int *It,
+          int *retcode,
+          /* Hidden arguments */
+          int colname_len)
+{
+  int rc = 0;
+  int it = *It;
+  int found = 0;
+  uint index;
+  MDB_Hash_Table *p;
+  DECL_FTN_CHAR(colname);
+
+  ALLOC_FTN_CHAR(colname);
+
+  rc = index = Hash(p_colname, colname_len, NULL);
+  p = &CMDBKEYS_hashtable[it][index];
+
+  while (p && p->colname) {
+    if (strequ(p->colname, p_colname)) {
+      found = 1;
+      break; /* The first occurence will do */
+    }
+    if (p->collision) 
+      p = p->collision;
+    else 
+      break; /* not found */
+  } /* while (p && p->colname) */
+
+  if (!found) {
+    fprintf(stderr,
+            "cmdb_set_: Column '%s' not registered for it#%d\n",
+            p_colname, it);
+    rc = -2;
+    RAISE(SIGABRT);
+    goto finish; /* Unrecognized column name */
+  }
+  
+  *get_value = p->mdbkey ? *p->mdbkey : 0;
+
+ finish:
+  FREE_FTN_CHAR(colname);
+
+  *retcode = rc;
+}
+
+/*---
+  Inquire address of MDBxxx -key:
+  CALL cmdb_addr('lat at hdr', zaddr, it, rc)
+  ---*/
+
+PUBLIC void
+cmdb_addr_(const char *colname,
+	   double *zaddr,
+	   const int *It,
+	   int *retcode,
+	   /* Hidden arguments */
+	   int colname_len)
+{
+  int rc = 0;
+  int it = *It;
+  int found = 0;
+  uint index;
+  MDB_Hash_Table *p;
+  MDB_Union u;
+  DECL_FTN_CHAR(colname);
+
+  u.d = 0;
+
+  ALLOC_FTN_CHAR(colname);
+
+  rc = index = Hash(p_colname, colname_len, NULL);
+  p = &CMDBKEYS_hashtable[it][index];
+
+  while (p && p->colname) {
+    if (strequ(p->colname, p_colname)) {
+      found = 1;
+      break; /* The first occurence will do */
+    }
+    if (p->collision) 
+      p = p->collision;
+    else 
+      break; /* not found */
+  } /* while (p && p->colname) */
+
+  if (!found) {
+    fprintf(stderr,
+            "cmdb_set_: Column '%s' not registered for it#%d\n",
+            p_colname, it);
+    rc = -2;
+    RAISE(SIGABRT);
+    goto finish; /* Unrecognized column name */
+  }
+  
+  u.mdbptr = p->mdbkey;
+
+ finish:
+  FREE_FTN_CHAR(colname);
+
+  *zaddr = u.d;
+  *retcode = rc;
+}
+
+/*---
+  Debug printout to STDERR:
+  CALL cmdb_debug(enforce=[0|1],message)
+  ---*/
+
+PUBLIC void
+cmdb_debug_(const int *enforce,
+            const char *msg,
+            /* Hidden arguments */
+            int msg_len)
+{
+  DECL_FTN_CHAR(msg);
+  int print_it = *enforce;
+  int j;
+  int entries=0;
+  int hits=0;
+  char *env = getenv("ODB_MDB_DEBUG");
+  
+  if (env) {
+    int ienv = atoi(env);
+    ienv = MAX(0,MIN(1,ienv));
+    print_it |= ienv;
+  }
+
+  if (!print_it) return;
+
+  ALLOC_FTN_CHAR(msg);
+
+  if (msg_len > 0) fprintf(stderr,"cmdb_debug_: %s\n",p_msg);
+  fprintf(stderr,
+          "cmdb_debug_: hashsize=%u, hashtable at %p\n",
+          CMDBKEYS_hashsize, CMDBKEYS_hashtable);
+
+  if (CMDBKEYS_hashtable) {
+    int inumt = get_max_threads_();
+    int it;
+    for (it = 1; it <= inumt ; it++) {
+      for (j=0; j<CMDBKEYS_hashsize; j++) {
+        MDB_Hash_Table *p = &CMDBKEYS_hashtable[it][j];
+        int k=1;
+        if (p->colname) entries++;
+        while (p && p->colname) {
+          fprintf(stderr,
+		  "hash#%d [hit#%d, thread#%d] : '%s' alias '%s' = %d (0x%x) at "
+		  "addr=%p (active_cnt=%d)\n",
+                  j,k,it,
+                  p->colname ? p->colname : NIL, 
+                  p->mdbname ? p->mdbname : NIL,
+                  p->mdbkey ? *p->mdbkey : 0, p->mdbkey ? *p->mdbkey : 0,
+                  p->mdbkey, p->active_cnt);
+          p = p->collision;
+          k++;
+          hits++;
+        } /* while (p && p->colname) */
+      } /* for (j=0; j<CMDBKEYS_hashsize; j++) */
+    } /* for (it = 1; it <= inumt ; it++) */
+  } /* if (CMDBKEYS_hashtable) */
+
+  fprintf(stderr,"cmdb_debug_: Total %d hits in %d hash-entries\n",hits,entries);
+
+  FREE_FTN_CHAR(msg);
+}
+
+/*---
+  Print 'MDBxxx' and their values and references to STDERR (unit=0; default) or STDOUT (unit=6)
+  CALL cmdb_print(unit, message, only_active, it, rc)
+  ---*/
+
+PUBLIC void
+cmdb_print_(const int *unit,
+            const char *msg,
+            const int *only_active,
+            const int *It,
+            int *retcode
+            /* Hidden arguments */
+            ,int msg_len)
+{
+  int it = MAX(1,*It);
+  int Unitno = *unit;
+  FILE *fp = (Unitno == 6) ? stdout : stderr;
+  int Only_Active = (*only_active > 0) ? 1 : 0;
+  int j;
+  int nlp = 0;
+  DECL_FTN_CHAR(msg);
+
+  ALLOC_FTN_CHAR(msg);
+
+  if (!fp) goto finish;
+
+  fprintf(fp,
+          "cmdb_print_(%s, only_active=%d, it#%d): hash: (size,table-addr)=(%u,%p)\n",
+          p_msg, Only_Active, it,
+          CMDBKEYS_hashsize, CMDBKEYS_hashtable);
+  fflush(fp);
+
+  if (CMDBKEYS_hashtable) {
+    for (j=0; j<CMDBKEYS_hashsize; j++) {
+      MDB_Hash_Table *p = &CMDBKEYS_hashtable[it][j];
+      while (p && p->colname) {
+        int print_it = (Only_Active == 0);
+        print_it |= (Only_Active == 1 && (p->active_cnt > 0));
+        if (print_it) {
+          fprintf(fp,
+                  "\t[%s;#%d] : '%s' => '%s' = %d (0x%x) at addr=%p (active#%d)\n",
+                  p_msg, it,
+                  p->colname ? p->colname : NIL, 
+                  p->mdbname ? p->mdbname : NIL,
+                  p->mdbkey? *p->mdbkey : 0, p->mdbkey ? *p->mdbkey : 0,
+                  p->mdbkey, p->active_cnt);
+          fflush(fp);
+          nlp++;
+        } /* if (print_it) */
+        p = p->collision;
+      } /* while (p && p->colname) */
+    } /* for (j=0; j<CMDBKEYS_hashsize; j++) */
+  } /* if (CMDBKEYS_hashtable) */
+
+  fprintf(fp,"End of cmdb_print_(%s): Total lines printed = %d. (it#%d)\n",
+          p_msg, nlp, it);
+  fflush(fp);
+
+ finish:
+  FREE_FTN_CHAR(msg);
+
+  *retcode = nlp;
+}
diff --git a/odb/src/lib/codb.c b/odb/src/lib/codb.c
new file mode 100644
index 0000000..c5d08ab
--- /dev/null
+++ b/odb/src/lib/codb.c
@@ -0,0 +1,3239 @@
+#ifdef RS6K
+#pragma options opt=0
+#endif
+
+/* codb.c: 
+
+   Fortran callable C-interface layer to the ODB-software:
+
+   Layers: (DDL = Data Definition Language)
+
+   Fortran-Application
+      --> Fortran modules (odb.F)
+      (*)--> C-interface layer (codb.c)
+	    --> Low level link between C-interface and DDL (odbpools.c)
+               --> Automatically generated C-code(s) from DDL(s)
+
+*/
+       
+#define ODB_POOLS 1
+
+#include "odb.h"
+#include "evaluate.h"
+#include "idx.h"
+#include "regcache.h"
+#include "cdrhook.h"
+#include "pcma_extern.h"
+
+PRIVATE int max_omp_threads = 0; /* Will be updated (once) in codb_init_omp_locks_() */
+
+#define USING_IT \
+(using_it && *using_it >= 1 && *using_it <= max_omp_threads) ? *using_it : get_thread_id_()
+
+/* #define IT (it-1) */ /* Now defined in privpub.h, included via odb.h -> alloc.h */
+
+#define POOLMASK_SET (p->pm && p->pm->poolmask[IT][0] == 1)
+
+#define MATCHING \
+  (p->inuse \
+   && p->handle == Handle \
+   && (AnyPool || Poolno == p->poolno) \
+   && (!POOLMASK_SET || (p->pm && p->pm->poolmask[IT][p->poolno])) \
+   )
+
+#define DELETE_INTERMED(x) \
+  if (x) { \
+    /* Delete any existing intermediate results */ \
+    int jjc, nnc = x->nc; \
+    for (jjc=0; jjc<nnc; jjc++) { \
+      double *din = x->d[jjc]; \
+      FREE(din); \
+    } \
+    FREE(x); \
+  }
+
+PRIVATE o_lock_t HASHING_mylock = 0; /* A specific OMP-lock; initialized only once in
+					odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+PUBLIC void 
+init_HASHING_lock()
+{ 
+  INIT_LOCKID_WITH_NAME(&HASHING_mylock,"codb.c:HASHING_mylock");
+}
+
+PUBLIC void
+codb_hash_set_lock_()
+{
+  coml_set_lockid_(&HASHING_mylock);
+}
+
+PUBLIC void
+codb_hash_unset_lock_()
+{
+  coml_unset_lockid_(&HASHING_mylock);
+}
+
+PUBLIC void
+codb_init_omp_locks_()
+{
+  /* Initializes all OMP-locks */
+  static Bool first_time = true;
+  if (first_time) {
+    char *env = getenv("ODB_OPENMP_LOCK_DEBUG");
+    int debug_on = env ? atoi(env) : 0;
+    int j, iret;
+    max_omp_threads = get_max_threads_();
+    coml_set_debug_(&debug_on, &iret);
+    coml_init_lock_(); /* initialize master lock (i.e. M_LOCK in ifsaux/module/yomoml.F90) */
+    /* global locks specific to generated C-codes */
+    for (j=0; j<MAX_ODB_GLOBAL_LOCKS_OPENMP; j++) {
+      char lockname[80];
+      snprintf(lockname,80,"codb.c:global_mylock[%d]",j);
+      INIT_LOCKID_WITH_NAME(&ODB_global_mylock[j],lockname);
+    }
+    /* specific locks and/or first-time initializations */
+    {
+      extern void init_VAR_lock();
+      init_VAR_lock();         /* odb/lib/var.c         */
+    }
+    {
+      extern void init_HASHING_lock();
+      init_HASHING_lock();     /* odb/lib/codb.c        */
+    }
+    {
+      extern void init_FORFUNC_lock(); /* -- no locks were required -- */
+      init_FORFUNC_lock();     /* odb/lib/forfunc.c     */
+    }
+    {
+      extern void init_POOLREG_lock(); /* -- no locks were required -- */
+      init_POOLREG_lock();     /* odb/lib/poolreg.c     */
+    }
+    {
+      extern void init_CMDBKEYS_lock(); /* -- no locks were required -- */
+      init_CMDBKEYS_lock();    /* odb/lib/cmdbkeys.c    */
+    }
+    {
+      extern void init_CTX_lock(); /* -- no locks were required -- */
+      init_CTX_lock();         /* odb/lib/ctx.c         */
+    }
+    {
+      extern void init_PEINFO_lock(); /* -- no locks were required -- */
+      init_PEINFO_lock();      /* odb/lib/peinfo.c      */
+    }
+    {
+      extern void init_CMAIO_lock();
+      init_CMAIO_lock();       /* odb/aux/cma_open.c    */
+    }
+    {
+      extern void init_NEWIO_lock();
+      init_NEWIO_lock();       /* odb/aux/newio.c       */
+    }
+    {
+      extern void init_DCA_lock();
+      init_DCA_lock();         /* odb/aux/dca.c         */
+    }
+    {
+      extern void init_PBAR_lock();
+      init_PBAR_lock();        /* odb/lib/tracing.c     */
+    }
+    {
+      /* -- no locks were required -- */
+      /* for protos: see include/regcache.h */
+      (void) ODBc_init_eq_cache();         /* odb/lib/eq_reqions.c     */
+      (void) ODBc_init_rgg_cache();        /* odb/lib/rgg_reqions.c     */
+    }
+    {
+      extern void init_inside();
+      init_inside(); /* odb/lib/inside.c */
+    }
+    /* Possible "first time"-calls on these routine */
+    (void) odb_datetime_(NULL, NULL);              /* odb/lib/funcs.c       */
+    (void) codb_versions_(NULL, NULL, NULL, NULL); /* odb/lib/versions.c    */
+    codb_thin_init_();                             /* odb/lib/orlist.c      */
+    codb_init_latlon_rad_();                       /* odb/lib/funcs.c       */
+    (void) TableIsConsidered(NULL);                /* odb/lib/codb.c        */
+    (void) TableIsWritable(NULL);                   /* odb/lib/codb.c        */
+    init_RANDOM();                                 /* odb/lib/random.c      */
+    (void) Run(NULL,NULL,NULL,NULL,NULL,false);    /* odb/lib/evaluate.c    */
+    extern void InitCard();
+    InitCard();                                    /* odb/aux/cardinality.c */
+    (void) odb_resource_stamp_(NULL);              /* odb/lib/codb.c        */
+    init_proc_funcs();                             /* odb/lib/funcs.c       */
+    codb_init_twindow_();                          /* odb/lib/twindow.c     */
+    first_time = false;
+  }
+}
+
+PUBLIC void 
+ODB_iolock(int onoff) {
+  extern void iolockdb_(int *onoff); /* Fortran-routine */
+  iolockdb_(&onoff);
+}
+
+PUBLIC const char *
+odb_resource_stamp_(const char *label)
+{ /* Now thread safe */
+  char *s = NULL;
+  int len = 0;
+  int it = get_thread_id_();
+  static struct {
+    char *s;
+    int  len;
+  } *ps = NULL;
+  if (!ps) {
+    /* First time only */
+    CALLOC(ps, max_omp_threads);
+  }
+  s = ps[--it].s;
+  FREE(s);
+  if (label) {
+    const char *dtbuf = odb_datetime_(NULL,NULL); /* ptr to a static variable; do not FREE */
+    extern long long int gethwm_(), getrss_();
+    long long int mem = gethwm_()/1048576;
+    long long int rss = getrss_()/1048576;
+    len = STRLEN(label) + STRLEN(dtbuf) + 100;
+    ALLOC(s,len);
+    snprintf(s,len,"%s %s (%lld/%lldMB)",label,dtbuf,mem,rss);
+  }
+  else {
+    s = STRDUP("");
+    len = 0;
+  }
+  ps[it].s = s;
+  ps[it].len = len;
+  return s;
+}
+
+
+PUBLIC void
+codb_datetime_(int *date_out, int *time_out)
+{
+  (void) odb_datetime_(date_out, time_out);
+}
+
+
+PUBLIC void
+codb_analysis_datetime_(int *date_out, int *time_out)
+{
+  int Date=19700101, Time=000000;
+  char *env_date, *env_time;
+  boolean valid_date = 0;
+  
+  env_date = getenv("ODB_ANALYSIS_DATE");
+  if (env_date) Date = atoi(env_date);
+
+  env_time = getenv("ODB_ANALYSIS_TIME");
+  if (env_time) Time = atoi(env_time);
+
+  if (!env_date && !env_time) {
+    /* Last resort: Try from the BASETIME environment variable */
+    char *basetime = getenv("BASETIME");
+    int len = basetime ? strlen(basetime) : 0;
+    if (len >= 10) { /* Some hope now ... */
+      int d,t;
+      int nel = sscanf(basetime, "%8d%2d", &d, &t);
+      if (nel == 2) {
+	Date = d; /* YYYYMMDD */
+	Time = t * 10000; /* HH0000 */
+      }
+    }
+  }
+  
+  if (date_out) *date_out = Date;
+  if (time_out) *time_out = Time;
+
+  valid_date = ODB_twindow(Date, Time,
+			   Date, Time,
+			   0, 0);
+
+  if (!valid_date) {
+    fprintf(stderr,
+	    "*** Warning: Invalid analysis date=%8.8d and/or time=%6.6d\n",
+	    Date, Time);
+  }
+}
+
+
+PUBLIC int
+ODB_min_alloc()
+{
+  static int min_alloc = 0;
+  if (min_alloc == 0) {
+    char *p = getenv("ODB_MIN_ALLOC");
+    if (p) min_alloc = atoi(p);
+    if (min_alloc < 1) min_alloc = MIN_ALLOC;
+  }
+  return min_alloc;
+}
+
+
+PUBLIC int
+ODB_inc_alloc(int nalloc, int min_alloc)
+{
+  static int inc_alloc = 0;
+  int rc = 0;
+  if (inc_alloc == 0) {
+    char *p = getenv("ODB_INC_ALLOC");
+    if (p) inc_alloc = atoi(p);
+    if (inc_alloc < 1) inc_alloc = INC_ALLOC;
+  }
+  if (nalloc > min_alloc) rc = inc_alloc;
+  return rc;
+}
+
+
+PUBLIC int
+ODB_error(const char *where,
+	  int how_much,
+	  const char *what,
+	  const char *srcfile,
+	  int srcline,
+	  int perform_abort)
+{
+  int rc = errno;
+  
+  fprintf(stderr,
+          "ODB_error: %s has failed to allocate %d bytes for '%s' (in \"%s\":%d)\n",
+          where, how_much, what,
+          srcfile, srcline);
+
+  if (perform_abort) {
+    char msg[] = "ODB_error: Aborting ...";
+    codb_abort_func_(msg, strlen(msg));
+    exit(rc);
+  }
+
+  return rc;
+}
+
+
+PUBLIC void
+codb_write_metadata_(const int  *handle,
+		     const int  *iounit,
+		     const int  *npools,
+		     const int   CreationDT[],
+		     const int   AnalysisDT[],
+		     const double  *major,
+		     const double  *minor,
+		     const int  *io_method,
+		     int *retcode)
+{
+  int rc = 0;
+  double Version_Major;
+  double Version_Minor;
+  int Handle = *handle;
+  int Npools = *npools;
+  int IO_method = *io_method;
+  FILE *fp = CMA_get_fp(iounit);
+  ODB_Pool *p;
+  DRHOOK_START(codb_write_metadata_);
+
+  if (!fp) { rc = -1; goto finish; }
+
+  (void) codb_versions_(&Version_Major, &Version_Minor, NULL, NULL); /* preset */
+  if (major && *major >= 0) Version_Major = *major;
+  if (minor && *minor >= 0) Version_Minor = *minor;
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      int Ntables = 0;
+      int CrDate = CreationDT[0];
+      int CrTime = CreationDT[1];
+      int UDate, UTime;
+      int AnDate = AnalysisDT[0];
+      int AnTime = AnalysisDT[1];
+      ODB_Funcs *pf;
+
+      FORFUNC { if (PFCOM->is_table) Ntables++; }
+
+      codb_datetime_(&UDate, &UTime);
+
+      fprintf(fp,"%.0f %.3f %d\n",Version_Major, Version_Minor, IO_method);
+      fprintf(fp,"%8.8d %6.6d\n",CrDate, CrTime); /* Date created */
+      fprintf(fp,"%8.8d %6.6d\n",UDate, UTime);   /* Date last updated */
+      fprintf(fp,"%8.8d %6.6d\n",AnDate, AnTime); /* Analysis date */
+      fprintf(fp,"%d\n",Npools);
+      fprintf(fp,"%d\n",Ntables);
+
+      rc = Ntables;
+
+      break; /* The first occurence would do */
+    }
+  } /* FORPOOL */
+
+ finish:
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_write_metadata2_(const int  *handle,
+		      const int  *iounit,
+		      const int  *npools,
+		      const int  *ntables,
+		      /* const int   fsize[], */ /* Npools x Ntables */
+		      int *retcode)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Npools = *npools;
+  /* int Ntables = *ntables; */
+  FILE *fp = CMA_get_fp(iounit);
+  ODB_Pool *p;
+  DRHOOK_START(codb_write_metadata2_);
+
+  if (!fp) { rc = -1; goto finish; }
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf;
+      int j, k = 0;
+
+      FORFUNC {
+	if (PFCOM->is_table) {
+	  char *name = PFCOM->name;
+	  k++;
+	  /*
+	  fprintf(fp, "%d %s %d", k, name, Npools);
+	  for (j=0; j<Npools; j++) {
+	    fprintf(fp, " %d",fsize[(k-1)*Npools + j]); 
+	  }
+	  fprintf(fp, "\n"); 
+	  */
+	  /* We don't care about file sizes anymore */
+	  fprintf(fp, "%d %s -1\n", k, name);
+	}
+      }
+
+      rc = k;
+
+      FORFUNC {
+	if (PFCOM->is_table) {
+	  int ncols = PFCOM->ncols;
+	  char *name = PFCOM->name;
+	  const ODB_Tags *tags = PFCOM->tags;
+	  fprintf(fp, "%s %d\n", name, ncols);
+	  for (k=0; k<ncols; k++) {
+	    int i, nmem = tags[k].nmem;
+	    if (nmem > 0) {
+	      const char *m = tags[k].memb[nmem-1];
+	      if (strequ(m,UNUSED)) nmem--;
+	    }
+	    fprintf(fp,"  %s  %d\n", tags[k].name, nmem);
+	    for (i=0; i<nmem; i++) fprintf(fp,"    %s\n",tags[k].memb[i]);
+	  }
+	}
+      }
+
+      break; /* The first occurence would do */
+    }
+  } /* FORPOOL */
+
+ finish:
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_write_metadata3_(const int  *handle,
+		      const int  *iounit,
+		      int *retcode)
+     /* Write SET-information */
+{
+  int rc = 0;
+  int Handle = *handle;
+  FILE *fp = CMA_get_fp(iounit);
+  ODB_Pool *p;
+  DRHOOK_START(codb_write_metadata3_);
+
+  if (!fp) { rc = -1; goto finish; }
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      char *dbname = p->dbname;
+      ODB_Setvar *setvar = NULL;
+      int nsetvar = ODB_get_vars(dbname, NULL, 0, 0, NULL);
+      fprintf(fp,"%d\n",nsetvar);
+      if (nsetvar > 0) {
+	ALLOC(setvar, nsetvar);
+	rc = ODB_get_vars(dbname, NULL, 0, nsetvar, setvar);
+	if (rc == nsetvar) {
+	  int j;
+	  for (j=0; j<nsetvar; j++) {
+	    fprintf(fp,"%s %.14g\n",setvar[j].symbol,setvar[j].value);
+	    FREE(setvar[j].symbol);
+	  }
+	}
+	else {
+	  rc = -2; 
+	}
+	FREE(setvar);
+	if (rc < 0) goto finish; 
+      }
+
+      break; /* The first occurence would do */
+    }
+  } /* FORPOOL */
+
+ finish:
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_read_metadata_(const int  *handle,
+		    const int  *iounit,
+		    int  *npools,
+		    int   CreationDT[],
+		    int   AnalysisDT[],
+		    double  *major,
+		    double  *minor,
+		    int  *io_method,
+		    int  *retcode)
+{
+  int rc = 0;
+  /* int Handle = *handle; */
+  double Version_Major, Def_Version_Major;
+  double Version_Minor, Def_Version_Minor;
+  int IO_method = 1;
+  int Npools = 0;
+  int Ntables = 0;
+  int CrDate, CrTime;
+  int UDate, UTime;
+  int AnDate, AnTime;
+  int nel;
+  char line[256];
+  FILE *fp = CMA_get_fp(iounit);
+  DRHOOK_START(codb_read_metadata_);
+
+  if (!fp) { rc = -1; goto finish; }
+
+  (void) codb_versions_(&Def_Version_Major, &Def_Version_Minor, NULL, NULL); /* preset */
+
+  if (fgets(line, sizeof(line), fp)) {
+    nel = sscanf(line,"%lf %lf %d",&Version_Major, &Version_Minor, &IO_method);
+    if (io_method) {
+      if (nel >= 3) { /* since-25r4 */
+	*io_method = IO_method;
+      }
+      else {
+	*io_method = 1; /* the only I/O-method prior to 25r4 */
+      }
+    }
+  }
+  else { rc = -2; goto finish; }
+/*
+  if (Version_Major != Def_Version_Major ||
+      Version_Minor != Def_Version_Minor) {
+       fprintf(stderr,
+	    "***Warning: Recovering from software version mismatch: Expected CY%.0fR%.3f, found=CY%.0fR%.3f\n",
+	    Def_Version_Major, Def_Version_Minor,
+	    Version_Major, Version_Minor);
+  }
+*/
+  fscanf(fp,"%d %d\n",&CrDate, &CrTime); /* Date created */
+  fscanf(fp,"%d %d\n",&UDate, &UTime);   /* Date last updated/accessed */
+  fscanf(fp,"%d %d\n",&AnDate, &AnTime); /* Analysis date */
+  fscanf(fp,"%d\n",&Npools);
+  fscanf(fp,"%d\n",&Ntables);
+
+  if (CreationDT) {
+    CreationDT[0] = CrDate;
+    CreationDT[1] = CrTime;
+  }
+
+  if (AnalysisDT) {
+    AnalysisDT[0] = AnDate;
+    AnalysisDT[1] = AnTime;
+  }
+
+  if (major) *major = Version_Major;
+  if (minor) *minor = Version_Minor;
+
+  if (npools) *npools = Npools;
+  rc = Ntables;
+
+ finish:
+  if (retcode) *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_read_metadata2_(const int  *handle,
+		     const int  *iounit,
+		     const int  *npools,
+		     const int  *ntables,
+		     /*      int   fsize[], *//* Npools x Ntables */
+		     int *retcode)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Npools = *npools;
+  /* int Ntables = *ntables; */
+  FILE *fp = CMA_get_fp(iounit);
+  ODB_Pool *p;
+  DRHOOK_START(codb_read_metadata2_);
+
+  if (!fp) { rc = -1; goto finish; }
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf;
+      char tname[MAXVARLEN+1];
+      int j, k = 0;
+
+      FORFUNC {
+	if (PFCOM->is_table) {
+	  const char *name = PFCOM->name;
+	  int kchk, npchk;
+	  k++;
+	  fscanf(fp, "%d %s %d", &kchk, tname, &npchk);
+	  if (kchk != k || !strequ(tname,name)) {
+	    /* Error */
+	    rc = -2;
+	    goto finish;
+	  }
+	  /*
+	  for (j=0; j<Npools; j++) {
+	    fscanf(fp, "%d",&fsize[(k-1)*Npools + j]); 
+	  }
+	  */
+	}
+      }
+
+      rc = k;
+
+      break; /* The first occurence would do */
+    }
+  } /* FORPOOL */
+
+ finish:
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_envtransf_(const char *in,
+		      char *out,
+		       int *retcode,
+		/* Hidden arguments */
+		      int  in_len,
+		const int  out_len)
+{
+  int rc = 0;
+  DECL_FTN_CHAR(in);
+  DECL_FTN_CHAR(out);
+  DRHOOK_START(codb_envtransf_);
+
+  if (out_len > 0) {
+    extern char *IOresolve_env(const char *str); /* from libioassign.a */
+    char *s;
+    ALLOC_FTN_CHAR(in);
+    ALLOC_OUTPUT_FTN_CHAR(out);
+
+    s = IOresolve_env(p_in);
+    if (!s) s = STRDUP(p_in);
+
+    rc = strlen(s);
+    rc = MIN(rc, out_len);
+    strncpy(p_out, s, rc);
+    p_out[rc] = '\0';
+    FREE(s);
+
+    COPY_2_FTN_CHAR(out);
+    FREE_FTN_CHAR(out);
+    FREE_FTN_CHAR(in);
+  }
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_pc_filter_(const char *in,
+		char *out,
+		const int *procid,
+		int *retcode,
+		/* Hidden arguments */
+		int in_len,
+		const int out_len)
+{
+  int rc = 0;
+  DRHOOK_START(codb_pc_filter_);
+
+  if (out_len > 0) {
+    char *s;
+    DECL_FTN_CHAR(in);
+    DECL_FTN_CHAR(out);
+
+    ALLOC_FTN_CHAR(in);
+    ALLOC_OUTPUT_FTN_CHAR(out);
+
+    if (strchr(p_in,'%')) {
+      rc = in_len + 50;
+      ALLOC(s,rc);
+      sprintf(s,p_in,*procid);
+    }
+    else {
+      s = STRDUP(p_in);
+    }
+
+    rc = strlen(s);
+    rc = MIN(rc, out_len);
+    strncpy(p_out, s, rc);
+    p_out[rc] = '\0';
+    FREE(s);
+
+    COPY_2_FTN_CHAR(out);
+    FREE_FTN_CHAR(out);
+    FREE_FTN_CHAR(in);
+  }
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+/* An error message print-out (printed from many places; unified here) */
+
+PUBLIC void
+ODB_check_considereness(int is_considered,
+			const char *tblname)
+{
+  if (!is_considered) { 
+    /* msgpass_loaddata() didn't load the table and yet it is now requested ==> abort */
+    fprintf(stderr,
+	    "***Error: Table '%s' has not been considered. Please check your ODB_CONSIDER_TABLES\n",
+	    tblname);
+    RAISE(SIGABRT); 
+  }
+}
+
+
+PUBLIC void
+codb_consider_table_(const int *handle,
+		     const char *tblname, /* Must begin with '@' in front of */
+		     int *option_code,
+		     int *retcode,
+		     /* Hidden arguments */
+		     int tblname_len)
+{
+  int rc = -1;
+  int Handle = *handle;
+  int Opcode = *option_code; /* -1=get info, 1/0=set consider/not_consider'ness */
+  DECL_FTN_CHAR(tblname);
+  DRHOOK_START(codb_consider_table_);
+
+  ALLOC_FTN_CHAR(tblname);
+
+  if (IS_TABLE(p_tblname) && (Opcode == -1 || Opcode == 0 || Opcode == 1)) {
+    boolean all_done = 0;
+    int Poolno = -1;
+    boolean AnyPool = (Poolno == -1);
+    int it = get_thread_id_();
+    ODB_Pool *p;
+    const int off = 0;
+    int oldvalue;
+
+    /* switch off poolmasking [for this thread only] temporarely */
+    codb_toggle_poolmask_(&Handle, &off, &oldvalue);
+
+    FORPOOL {
+      if (MATCHING) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_tblname, 1);
+
+	if (pf && PFCOM->is_table && strequ(PFCOM->name, p_tblname)) {
+	  rc = PFCOM->is_considered; /* get existing value for rc */
+	  if (Opcode == -1) { /* get info */
+	    all_done = 1;
+	  }
+	  else if (Opcode == 0 || Opcode == 1) { /* set value */
+	    PFCOM->is_considered = Opcode; /* Update */
+	  }
+	} /* if (pf && PFCOM->is_table && strequ(PFCOM->name, p_tblname)) */
+
+	if (all_done) break; /* FORPOOL */
+      } /* if (MATCHING) */
+    } /* FORPOOL */
+
+    /* reset poolmasking status to whatever it was before */
+    codb_toggle_poolmask_(&Handle, &oldvalue, NULL);
+
+  } /* if (IS_TABLE(p_tblname) && (Opcode == ... */
+
+  FREE_FTN_CHAR(tblname);
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC int
+TableIsConsidered(const char *tblname)
+{ /* Generally a non-thread safe code, 
+     but the non-thread safe part called upon codb_init_omp_locks() */
+  static char *env = NULL;
+  static int envlen = 0;
+  int rc = 0;
+  if (!env) { /* the non-thread safe part */
+    char *p = getenv("ODB_CONSIDER_TABLES");
+    /* Skip leading blanks */
+    if (p) {
+      while (*p) {
+	if (!isspace(*p)) break;
+	++p;
+      }
+    }
+    env = p ? STRDUP(p) : STRDUP("*");
+    p = env;
+    while (*p) {
+      if (isupper(*p)) tolower(*p);
+      ++p;
+    }
+    envlen = strlen(env);
+    /* Ignore trailing blanks */
+    p = &env[envlen-1];
+    while (envlen > 0) {
+      if (!isspace(*p)) break;
+      --p;
+      --envlen;
+    }
+    env[envlen] = '\0';
+    {
+      int myproc = 0, it = 0;
+      codb_procdata_(&myproc, NULL, NULL, &it, NULL);
+      if (myproc == 1 && it == 1) {
+	fprintf(stderr,"ODB_CONSIDER_TABLES=%s\n",env);
+      }
+    }
+  }
+  if (tblname) {
+    if (*tblname == '@') tblname++;
+    if (strequ(env,"*")) {
+      rc = 1;
+    }
+    else {
+      int len = strlen(tblname);
+      char *teststr = NULL;
+      ALLOC(teststr,len + 3);
+      snprintf(teststr,len+3,"/%s/",tblname);
+      if (*env == '*' && envlen > 1) { /* "* except /tb1/tb2/" or "* /tb1/tb2/" or "* but /tb1/tb2/" */
+	if (!strstr(env,teststr)) rc = 1;
+      }
+      else {
+	if (strstr(env,teststr)) rc = 1;
+      }
+      FREE(teststr);
+    }
+  }
+  return rc;
+}
+
+PUBLIC void
+codb_table_is_considered_(const char *tblname,
+			  int *retcode,
+			  /* Hidden arguments */
+			  int tblname_len)
+{
+  if (retcode) {
+    DECL_FTN_CHAR(tblname);
+    ALLOC_FTN_CHAR(tblname);
+    *retcode = TableIsConsidered(p_tblname);
+    FREE_FTN_CHAR(tblname);
+  }
+}
+
+/* Anne Fouilloux 23/02/10 add possibility to write only a subset of tables via ODB_WRITE_TABLES */
+
+
+PUBLIC void
+codb_write_table_(const int *handle,
+		     const char *tblname, /* Must begin with '@' in front of */
+		     int *option_code,
+		     int *retcode,
+		     /* Hidden arguments */
+		     int tblname_len)
+{
+  int rc = -1;
+  int Handle = *handle;
+  int Opcode = *option_code; /* -1=get info, 1/0=set write/not_write'ness */
+  DECL_FTN_CHAR(tblname);
+  DRHOOK_START(codb_consider_table_);
+
+  ALLOC_FTN_CHAR(tblname);
+
+  if (IS_TABLE(p_tblname) && (Opcode == -1 || Opcode == 0 || Opcode == 1)) {
+    boolean all_done = 0;
+    int Poolno = -1;
+    boolean AnyPool = (Poolno == -1);
+    int it = get_thread_id_();
+    ODB_Pool *p;
+    const int off = 0;
+    int oldvalue;
+
+    /* switch off poolmasking [for this thread only] temporarely */
+    codb_toggle_poolmask_(&Handle, &off, &oldvalue);
+
+    FORPOOL {
+      if (MATCHING) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_tblname, 1);
+
+	if (pf && PFCOM->is_table && strequ(PFCOM->name, p_tblname)) {
+	  rc = PFCOM->is_writable; /* get existing value for rc */
+	  if (Opcode == -1) { /* get info */
+	    all_done = 1;
+	  }
+	  else if (Opcode == 0 || Opcode == 1) { /* set value */
+	    PFCOM->is_writable = Opcode; /* Update */
+	  }
+	} /* if (pf && PFCOM->is_table && strequ(PFCOM->name, p_tblname)) */
+
+	if (all_done) break; /* FORPOOL */
+      } /* if (MATCHING) */
+    } /* FORPOOL */
+
+    /* reset poolmasking status to whatever it was before */
+    codb_toggle_poolmask_(&Handle, &oldvalue, NULL);
+
+  } /* if (IS_TABLE(p_tblname) && (Opcode == ... */
+
+  FREE_FTN_CHAR(tblname);
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC int
+TableIsWritable(const char *tblname)
+{ /* Generally a non-thread safe code, 
+     but the non-thread safe part called upon codb_init_omp_locks() */
+  static char *env = NULL;
+  static int envlen = 0;
+  int rc = 0;
+  if (!env) { /* the non-thread safe part */
+    char *p = getenv("ODB_WRITE_TABLES");
+    /* Skip leading blanks */
+    if (p) {
+      while (*p) {
+	if (!isspace(*p)) break;
+	++p;
+      }
+    }
+    env = p ? STRDUP(p) : STRDUP("*");
+    p = env;
+    while (*p) {
+      if (isupper(*p)) tolower(*p);
+      ++p;
+    }
+    envlen = strlen(env);
+    /* Ignore trailing blanks */
+    p = &env[envlen-1];
+    while (envlen > 0) {
+      if (!isspace(*p)) break;
+      --p;
+      --envlen;
+    }
+    env[envlen] = '\0';
+    {
+      int myproc = 0, it = 0;
+      codb_procdata_(&myproc, NULL, NULL, &it, NULL);
+      if (myproc == 1 && it == 1) {
+	fprintf(stderr,"ODB_WRITE_TABLES=%s\n",env);
+      }
+    }
+  }
+  if (tblname) {
+    if (*tblname == '@') tblname++;
+    if (strequ(env,"*")) {
+      rc = 1;
+    }
+    else {
+      int len = strlen(tblname);
+      char *teststr = NULL;
+      ALLOC(teststr,len + 3);
+      snprintf(teststr,len+3,"/%s/",tblname);
+      if (*env == '*' && envlen > 1) { /* "* except /tb1/tb2/" or "* /tb1/tb2/" or "* but /tb1/tb2/" */
+	if (!strstr(env,teststr)) rc = 1;
+      }
+      else {
+	if (strstr(env,teststr)) rc = 1;
+      }
+      FREE(teststr);
+    }
+  }
+  return rc;
+}
+
+PUBLIC void
+codb_table_is_writable_(const char *tblname,
+			  int *retcode,
+			  /* Hidden arguments */
+			  int tblname_len)
+{
+  if (retcode) {
+    DECL_FTN_CHAR(tblname);
+    ALLOC_FTN_CHAR(tblname);
+    *retcode = TableIsWritable(p_tblname);
+    FREE_FTN_CHAR(tblname);
+  }
+}
+
+/* End Anne fouilloux 23/02/10 */
+
+PUBLIC void 
+codb_create_pool_(const int  *handle,
+		  const char *dbname,
+		  const int  *poolno,
+		  const int  *is_new,
+		  const int  *io_method,
+		  const int  *add_vars,
+		  int *retcode,
+		  /* Hidden arguments */
+		  int dbname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int Is_new = *is_new;
+  int IO_method = *io_method;
+  int Add_vars = *add_vars;
+  DECL_FTN_CHAR(dbname);
+  DRHOOK_START(codb_create_pool_);
+
+  ALLOC_FTN_CHAR(dbname);
+
+  if (Poolno > 0) { 
+    ODB_Pool *pool = ODB_create_pool(Handle, p_dbname, Poolno, Is_new, IO_method, Add_vars);
+    if (!pool) { 
+      rc = -Poolno; 
+      goto finish; 
+    }
+    rc = Poolno;
+  }
+
+ finish:
+  FREE_FTN_CHAR(dbname);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_close_(const int *handle,
+	    const int *save,
+	          int *retcode)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int Handle = *handle;
+  int Save = *save;
+  char *dbname = NULL;
+  ODB_Pool *p;
+  int trace_on = 0;
+  DRHOOK_START(codb_close_);
+
+  trace_on = FREEPTR_TRACE(stdout, codb_close_, 1); /* PTR-trace ON, if ODB_MEMORY_FREEPTR_TRACE=1 */
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf;
+
+      if (Save) {
+	rc = p->store(p, 0);
+	if (rc < 0) goto finish;
+	nbytes += rc;
+      }
+
+      FORFUNC { /* correct coding (as of 9-Jan-2004/SS) */
+	PFCOM->swapout(pf->data);
+	DELETE_INTERMED(pf->tmp);
+	/* if (trace_on) */ FREE(pf->data);
+      }
+
+      /* Remove the funcs-chain */
+      {
+	for (pf = p->funcs; pf; ) {
+	  ODB_Funcs *next_pf = pf->next;
+	  nullify_forfunc(p->handle, p->dbname, p->poolno, pf->it, PFCOM->name);
+	  FREE(pf);
+	  pf = next_pf;
+	} /* for (pf = p->funcs; pf; ) */
+	p->funcs = NULL;
+      }
+
+      if (!dbname) dbname = STRDUP(p->dbname);
+
+      FREE(p->dbname);
+      FREE(p->srcpath);
+
+      p->inuse = 0;
+
+      put_poolreg(p->handle, p->poolno, NULL);
+    }
+  } /* FORPOOL */
+
+  trace_on = FREEPTR_TRACE(stdout, codb_close_, 0); /* PTR-trace OFF */
+
+  if (dbname) {
+    /* Unlink from dynamic views */
+    rc = ODB_undo_dynlink(dbname, 1);
+    if (rc < 0) goto finish;
+
+    /* Unlink from DBase itself */
+    rc = ODB_undo_dynlink(dbname, 0);
+    if (rc < 0) goto finish;
+
+    FREE(dbname);
+  }
+
+  (void) DCA_free(Handle);
+ finish:
+  *retcode = (rc < 0) ? rc : nbytes;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_swapout_(const int  *handle,
+	      const int  *poolno,
+	      const char *dataname,
+	      const int  *save,
+	      int  *retcode,
+	      const int  *delete_intermed,
+	      const int  *using_it,
+	      /* Hidden arguments */
+	      int dataname_len)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int DeleteIntermed = *delete_intermed;
+  boolean AnyPool = (Poolno == -1);
+  boolean Save = *save;
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_swapout_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  Save &= IS_TABLE(p_dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) { 
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+      
+      if (pf) {
+	void *data = pf->data;
+	  
+	if (Save) {
+	  rc = PFCOM->store(data);
+	  if (rc < 0) goto finish;
+	  nbytes += rc;
+	}
+	
+	PFCOM->swapout(pf->data); /* Swap out */
+	if (DeleteIntermed) DELETE_INTERMED(pf->tmp);
+      } /* if (pf) */
+    }
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:  
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = (rc < 0) ? rc : nbytes;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_remove_(const int  *handle,
+	     const int  *poolno,
+	     const char *dataname,
+	     int  *retcode,
+	     /* Hidden arguments */
+	     int dataname_len)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = get_thread_id_();
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_remove_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (!IS_TABLE(p_dataname)) goto finish;
+
+  POOLREG_FOR {
+    if (MATCHING) { 
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+      
+      if (pf) {
+	void *data = pf->data;
+	rc = PFCOM->remove(data);  /* Remove data table and fill it with an empty dataset */
+	if (rc < 0) goto finish;
+	nbytes += rc;
+      } /* if (pf) */
+    }
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:  
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = (rc < 0) ? rc : nbytes;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_store_(const int *handle,
+	    const int *poolno,
+	    const int *io_method,
+	    int *retcode)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int IO_method = *io_method;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = get_thread_id_();
+  DRHOOK_START(codb_store_);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      rc = p->store(p, IO_method);
+      if (rc < 0) goto finish;
+      nbytes += rc;
+    }
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:
+  *retcode = (rc < 0) ? rc : nbytes;
+  DRHOOK_END(0);
+}
+	
+  
+PUBLIC void
+codb_load_(const int *handle,
+	   const int *poolno,
+	   const int *io_method,
+	   int *retcode)
+{
+  int rc = 0;
+  int nbytes = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int IO_method = *io_method;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = get_thread_id_();
+  DRHOOK_START(codb_load_);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      rc = p->load(p, IO_method);
+      if (rc < 0) goto finish;
+      nbytes += rc;
+    }
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:
+  *retcode = (rc < 0) ? rc : nbytes;
+  DRHOOK_END(0);
+}
+	
+  
+
+PUBLIC void
+codb_select_(const int *handle,
+             const int *poolno,
+	     const char *dataname,
+	     int *nrows,
+	     int *ncols,
+	     int *retcode,
+	     const int *inform_progress,
+	     const int *using_it,
+	     /* Hidden arguments */
+	     int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Nrows = 0;
+  int Ncols = 0;
+  int Pbar = *inform_progress; /* whether to invoke codb_progress_bar_() or not */
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_select_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if(pf) {
+	void *data = pf->data;
+	int nc = PFCOM->ncols;
+	extern double util_walltime_();
+	double zwall[2];
+
+	if (Pbar) zwall[0] = util_walltime_();
+	
+	rc = PFCOM->select(data, NULL, -1, NULL);
+	
+	if (rc < 0) goto finish;
+	
+	Nrows += rc;
+	Ncols  = nc;
+
+	if (Pbar) {
+	  double wtime;
+	  zwall[1] = util_walltime_();
+	  wtime = zwall[1] - zwall[0];
+	  codb_progress_bar_(NULL,
+			     p_dataname,
+			     &p->poolno,
+			     NULL,
+			     &rc,
+			     NULL,
+			     &wtime,
+			     NULL,
+			     strlen(p_dataname));
+	}
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:
+
+  if (rc >=0 && Ncols == 0) { 
+    /* If no match so far, then must get the correct Ncols */
+    const int some_pool = -1;
+    int dummy;
+    codb_getsize_(handle,
+		  &some_pool,
+		  p_dataname,
+		  &dummy,
+		  &Ncols,
+		  NULL,
+		  NULL,
+		  &it,
+		  /* Hidden arguments */
+#ifdef USE_CTRIM
+		  strlen(p_dataname)+1
+#else
+		  strlen(p_dataname)
+#endif
+		  );
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+
+  *nrows = Nrows;
+  *ncols = Ncols;
+
+  *retcode = (rc >= 0) ? Nrows : rc;
+  DRHOOK_END(Nrows);
+}
+
+
+void
+codb_mp_select_(const int *handle,
+		const int *poolno,
+		const char *dataname,
+		int nrows[],
+		int *ncols,
+		int *retcode,
+		const char *pevar,
+		const int *npes,
+		const int *replicate_PE,
+		const int *using_it,
+		/* Hidden arguments */
+		int dataname_len,
+		int pevar_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Nrows = 0;
+  int Ncols = 0;
+  int PE, Npes;
+  int Poolno = *poolno;
+  boolean is_table = 0;
+  boolean AnyPool = (Poolno == -1);
+  double oldvalue = 0;
+  char *dbname = NULL;
+  ODB_PE_Info PEinfo;
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DECL_FTN_CHAR(pevar);
+  DRHOOK_START(codb_mp_select_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+  ALLOC_FASTFTN_CHAR(pevar);
+
+  Npes = *npes;
+  for (PE=1; PE<=Npes; PE++) nrows[PE-1] = 0;
+
+  is_table = IS_TABLE(p_dataname);
+
+  dbname = NULL;
+  PEinfo.npes = Npes;
+  ALLOC(PEinfo.nrowvec, PEinfo.npes);
+  for (PE=1; PE<=Npes; PE++) PEinfo.nrowvec[PE-1] = 0;
+  PEinfo.varname = p_pevar;
+  PEinfo.varname_len = strlen(p_pevar);
+  PEinfo.addr = NULL;
+  PEinfo.replicate_PE = *replicate_PE;
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	
+      if (pf) {
+	void *data = pf->data;
+	int nc;
+	
+	dbname = STRDUP(p->dbname);
+	PEinfo.addr = ODB_alter_var(dbname, p_pevar, 
+				    is_table ? NULL : p_dataname,
+				    it,
+				    NULL, &oldvalue,
+				    0);
+
+	rc = PFCOM->select(data, &PEinfo, -1, NULL);
+
+	if (rc < 0) goto finish;
+	
+	Nrows += rc;
+	
+	nc = PFCOM->ncols;
+	Ncols = nc;
+
+	if (PEinfo.addr) {
+	  (void) ODB_alter_var(dbname, p_pevar, 
+			       is_table ? NULL : p_dataname,
+			       it,
+			       &oldvalue, NULL,
+			       0);
+	}
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+    
+ finish:
+  if (rc >= 0) {
+    Npes = PEinfo.npes;
+    for (PE=1; PE<=Npes; PE++) nrows[PE-1] = PEinfo.nrowvec[PE-1];
+    FREE(PEinfo.nrowvec);
+    FREE(dbname);
+  }
+  else {
+    nrows[0] = Nrows;
+  }
+
+  if (rc >=0 && Ncols == 0) { 
+    /* If no match so far, then must get the correct Ncols */
+    const int some_pool = -1;
+    int dummy;
+    codb_getsize_(handle,
+		  &some_pool,
+		  p_dataname,
+		  &dummy,
+		  &Ncols,
+		  NULL,
+		  NULL,
+		  &it,
+		  /* Hidden arguments */
+#ifdef USE_CTRIM
+		  strlen(p_dataname)+1
+#else
+		  strlen(p_dataname)
+#endif
+		  );
+  }
+
+  *ncols = Ncols;
+
+  FREE_FASTFTN_CHAR(dataname);
+  FREE_FASTFTN_CHAR(pevar);
+    
+  *retcode = (rc >= 0) ? Nrows : rc;
+  DRHOOK_END(Nrows);
+}
+
+
+PUBLIC void
+codb_get_npes_(const int *handle,
+	       const int *poolno,
+	       const char *dataname,
+	       int *replicate_PE,
+	       int *retcode,
+	       const int *using_it,
+	       /* Hidden arguments */
+	       int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int Npes = 0;
+  int Replicate_PE = 0;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	ODB_PE_Info PEinfo;
+	PFCOM->peinfo(data, &PEinfo);
+	Npes = MAX(Npes, PEinfo.npes);
+	Replicate_PE = PEinfo.replicate_PE;
+      } /* if (pf) */
+    } /* MATCHING */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+  FREE_FASTFTN_CHAR(dataname);
+
+  *replicate_PE = Replicate_PE;
+
+  *retcode = (rc >= 0) ? Npes : rc;
+}
+
+
+PUBLIC void
+codb_get_rowvec_(const int *handle,
+		 const int *poolno,
+		 const char *dataname,
+		 int  nrows[],
+		 const int *npes,
+		 int *retcode,
+		 const int *using_it,
+		 /* Hidden arguments */
+		 int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int Npes = *npes;
+  int PE;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_get_rowvec_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  for (PE=1; PE<=Npes; PE++) nrows[PE-1] = 0;
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	ODB_PE_Info PEinfo;
+	PFCOM->peinfo(data, &PEinfo);
+	if (PEinfo.npes > 0 && PEinfo.nrowvec) {
+	  Npes = MIN(*npes, PEinfo.npes);
+	  for (PE=1; PE<=Npes; PE++) {
+	    nrows[PE-1] += PEinfo.nrowvec[PE-1];
+	  }
+	} /* if (PEinfo.npes > 0 && PEinfo.nrowvec) */
+      } /* if (pf) */
+    } /* MATCHING */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = (rc >= 0) ? *npes : rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_cancel_(const int  *handle,
+             const int  *poolno,
+	     const char *dataname,
+	     int *retcode,
+	     const int  *delete_intermed,
+	     const int *using_it,
+	     /* Hidden arguments */
+	     int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  int DeleteIntermed = *delete_intermed;
+  int is_table;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_cancel_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  is_table = IS_TABLE(p_dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	if (PFCOM->cancel) PFCOM->cancel(data);
+	if (DeleteIntermed) DELETE_INTERMED(pf->tmp);
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_getindex_(const int *handle,
+	       const int  *poolno,
+	       const char *viewname,
+	       const char *tablename,
+	       const int *idxlen,
+	       int idx[],
+	       int *retcode,
+	       const int *using_it,
+	       /* Hidden arguments */
+	       int viewname_len,
+	       int tablename_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1); /* Actually works only for one pool at a time */
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(viewname);
+  DECL_FTN_CHAR(tablename);
+  DRHOOK_START(codb_getindex_);
+
+  ALLOC_FASTFTN_CHAR(viewname);
+  ALLOC_FASTFTN_CHAR(tablename);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_viewname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	int *this_idx = PFCOM->getindex(data, p_tablename, &rc);
+	if (rc <= *idxlen && this_idx) {
+	  int i;
+	  for (i=0; i<rc; i++) {
+	    idx[i] = this_idx[i];
+	  }
+	}
+	else if (!this_idx) {
+	  rc = -2; /* No index vector was not found */
+	  goto finish;
+	}
+	else {
+	  rc = -1; /* Not enough space left for outgoing index-vector */
+	  goto finish;
+	}
+	break;  /* for now (... since works only for one pool at a time) */
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+ finish:
+  FREE_FASTFTN_CHAR(viewname);
+  FREE_FASTFTN_CHAR(tablename);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+/* 
+   A very dangerous routine: 
+   == With the following routine you can easily destroy/crash
+   your database handling software 
+
+ */
+
+PUBLIC void
+codb_putindex_(const int *handle,
+	       const int  *poolno,
+	       const char *viewname,
+	       const char *tablename,
+	       const int *idxlen,
+	       const int idx[],
+	       int *retcode,
+	       const int *using_it,
+	       /* Hidden arguments */
+	       int viewname_len,
+	       int tablename_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1); /* Actually works only for one pool at a time */
+  POOLREG_DEF;
+  int it = USING_IT;
+  DECL_FTN_CHAR(viewname);
+  DECL_FTN_CHAR(tablename);
+  DRHOOK_START(codb_putindex_);
+
+  ALLOC_FASTFTN_CHAR(viewname);
+  ALLOC_FASTFTN_CHAR(tablename);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_viewname, 1);
+
+      if (pf) {
+	if (*idxlen > 0) {
+	  void *data = pf->data;
+	  rc = PFCOM->putindex(data, p_tablename, *idxlen, (int *)idx, 0);
+	  break; /* for now (... since works only for one pool at a time) */
+	}
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+  FREE_FASTFTN_CHAR(viewname);
+  FREE_FASTFTN_CHAR(tablename);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+/* Put & Get functions */
+
+#undef REAL_VERSION
+
+#define REAL_VERSION 8
+#include "codb.h"
+#undef REAL_VERSION
+
+
+PUBLIC void
+codb_getsize_(const int *handle,
+              const int *poolno,
+	      const char *dataname,
+	      int *nrows,
+	      int *ncols,
+	      const int *recur,
+	      int *retcode,
+	      const int *using_it,
+	      /* Hidden arguments */
+	      int dataname_len)
+{
+  int rc = 0;
+  int Recur = recur ? *recur : 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  int Nrows = 0;
+  int Ncols = 0;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START_RECUR(codb_getsize_,Recur);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	int HasInterMed = pf->tmp ? 1 : 0;
+	void *data = pf->data;
+	int nc = PFCOM->ncols;
+
+	if (!HasInterMed) {
+	  nc = PFCOM->ncols;
+	}
+	else {
+	  nc = pf->tmp->nc;
+	}
+
+	if (nrows) {
+	  int nr;
+	  if (!HasInterMed) {
+	    PFCOM->dim(data, &nr, NULL, NULL, -1);
+	  }
+	  else {
+	    nr = pf->tmp->nr;
+	  }
+	  Nrows += nr;
+	}
+
+	Ncols  = nc;
+	if (!nrows) break;
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+
+  if (rc >=0 && Ncols == 0 && ncols && Recur == 0) { 
+    /* If no match so far, then must get the correct Ncols at least */
+    const int off = 0;
+    int oldvalue;
+    const int some_pool = -1;
+
+    /* switch poolmasking temporarely off [for this thread only] */
+    codb_toggle_poolmask_(&Handle, &off, &oldvalue);
+
+    ++Recur;
+    codb_getsize_(handle,
+		  &some_pool,
+		  p_dataname,
+		  NULL,
+		  &Ncols,
+		  &Recur,
+		  NULL,
+		  &it,
+		  /* Hidden arguments */
+#ifdef USE_CTRIM
+		  strlen(p_dataname)+1
+#else
+		  strlen(p_dataname)
+#endif
+		  );
+    --Recur;
+
+    /* reset poolmasking status to whatever it was before */
+    codb_toggle_poolmask_(&Handle, &oldvalue, NULL);
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+
+  if (nrows) *nrows = Nrows;
+  if (ncols) *ncols = Ncols;
+
+  if (retcode) *retcode = Nrows;
+  DRHOOK_END_RECUR(0,Recur);
+}
+
+
+PUBLIC void
+codb_getsize_aux_(const int *handle,
+		  const int  *poolno,
+		  const char *dataname,
+		  const int *ncols,
+		  int *ncols_aux,
+		  int  colaux[],
+		  const int *colaux_len,
+		  int *retcode,
+		  const int  *using_it,
+		  /* Hidden arguments */
+		  int dataname_len)
+{
+  int Handle = *handle;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  POOLREG_DEF;
+  int it = USING_IT;
+  int Ncols = *ncols;
+  int Ncols_aux = 0;
+  int Colaux_len = *colaux_len;
+  int filled = 0;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_getsize_aux_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  POOLREG_FOR {
+    if (MATCHING) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	Ncols_aux = PFCOM->ncols_aux;
+	if (PFCOM->colaux) filled = PFCOM->colaux(data, colaux, Colaux_len);
+	break; /* One result suffice */
+      } /* if (pf) */
+    } /* if (MATCHING) */
+    POOLREG_BREAK;
+  } /* POOLREG_FOR */
+
+  /* finish: */
+
+  if (!filled && Colaux_len > 0 && Ncols > 0) {
+    int j, n = MIN(Ncols, Colaux_len);
+    for (j=0; j<n; j++) colaux[j] = j+1; /* Fortran-index */
+    filled = n;
+  }
+
+  if (ncols_aux) *ncols_aux = Ncols_aux;
+
+#if 0
+  {
+    int j, n = filled;
+    fprintf(stderr,
+	    "codb_getsize_aux_(%s): filled = %d, (Ncols=%d, Ncols_aux=%d) and colaux[] to follow ...:\n",
+	    p_dataname,filled,Ncols,Ncols_aux);
+    for (j=0; j<n; j++) {
+      fprintf(stderr," (%d)=%d",j+1,colaux[j]);
+    }
+    fprintf(stderr,"\n");
+  }
+#endif
+
+  if (filled > 0) { /* Check that every filled colaux[j] has value >= 1 && <= Ncols or zero */
+    int j, n = filled;
+    boolean do_abort = 0;
+    for (j=0; j<n; j++) {
+      if (colaux[j] == 0) continue; /* Ignore zeros */
+      if (colaux[j] < 1 || colaux[j] > Ncols) {
+	fprintf(stderr,
+		"codb_getsize_aux_(%s): COLAUX(Fortran-index j = %d) = %d is not between column range [ %d .. %d ]\n",
+		p_dataname, j+1, colaux[j], 1, Ncols);
+	do_abort = 1;
+      }
+    }
+    if (do_abort) RAISE(SIGABRT);
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = filled; /* Ret.code indicates how many elements in colaux[] were actually filled */
+  DRHOOK_END(0);
+}
+
+
+PRIVATE char *
+map2ftntype(const char *s, boolean *is_flp, int *maxbits)
+{
+  char *p = NULL;
+  char *cmp;
+  boolean Flpnt = 0;
+  int Maxbits = 0;
+  DRHOOK_START(map2ftntype);
+
+  ALLOC(cmp,strlen(s) + 3);
+  sprintf(cmp,"/%s/",s);
+
+  if (strstr("/int/uint/integer4/pk1int/pk2int/pk3int/pk4int/pk5int/pk9int/",cmp)) {
+    p = STRDUP("INTEGER(4)");
+    Flpnt = 0;
+    Maxbits = 32;
+  }
+  else if (strstr("/linkoffset_t/linklen_t/",cmp)) {
+    p = STRDUP("INTEGER(4)");
+    Flpnt = 0;
+    Maxbits = 32;
+  }
+  else if (strstr("/double/real8/pk2real/pk3real/pk4real/pk5real/pk9real/real/Formula/",cmp)) {
+    p = STRDUP("REAL(8)");
+    Flpnt = 1;
+    Maxbits = 64;
+  }
+  else if (strstr("/string/",cmp)) {
+    p = STRDUP("REAL(8)");
+    Flpnt = 1;
+    Maxbits = 64;
+  }
+  else if (strstr("/pk11real/pk12real/pk13real/pk14real/pk15real/pk16real/pk17real/pk18real/pk19real/",cmp)) {
+    p = STRDUP("REAL(8)");
+    Flpnt = 1;
+    Maxbits = 64;
+  }
+  else if (strstr("/pk21real/pk22real/pk23real/pk24real/pk25real/pk26real/pk27real/pk28real/pk29real/",cmp)) {
+    p = STRDUP("REAL(8)");
+    Flpnt = 1;
+    Maxbits = 64;
+  }
+  else if (strstr("/pk31real/pk32real/pk33real/pk34real/pk35real/pk36real/pk37real/pk38real/pk39real/",cmp)) {
+    p = STRDUP("REAL(8)");
+    Flpnt = 1;
+    Maxbits = 64;
+  }
+  else if (strstr("/Bitfield/hex4/yyyymmdd/hhmmss/integer/bufr/grib/",cmp)) {
+    p = STRDUP("INTEGER(4)");
+    Flpnt = 0;
+    Maxbits = 32;
+  }
+  else if (strstr("/integer2/short/ushort/",cmp)) {
+    p = STRDUP("INTEGER(2)");
+    Flpnt = 0;
+    Maxbits = 32;
+  }
+  else if (strstr("/byte/integer1/uchar/char/boolean/",cmp)) {
+    p = STRDUP("INTEGER(1)");
+    Flpnt = 0;
+    Maxbits = 32;
+  }
+  else if (strstr("/float/real4/",cmp)) {
+    p = STRDUP("REAL(4)");
+    Flpnt = 1;
+    Maxbits = 32;
+  }
+  else {
+    ALLOC(p, 20);
+    strcpy(p,"UNKNOWN");
+    Flpnt = 0;
+    Maxbits = 0;
+  }
+
+  FREE(cmp);
+
+  if (is_flp)   *is_flp  = Flpnt;
+  if (maxbits)  *maxbits = Maxbits;
+
+  DRHOOK_END(0);
+  return p;
+}
+
+
+PRIVATE char *
+parse_name(int what, const char *in, boolean *is_flp, int *maxbits, const char *varname)
+{
+  int a_what = what%100;
+  char *s = STRDUP(in);
+  char *pstart = s;
+  char *x = NULL;
+  char *ftntype = NULL;
+  boolean found = 0;
+  DRHOOK_START(parse_name);
+
+  if (a_what == 1 || a_what == 11) { /* get datatype or ftntype */
+    if (what == a_what) {
+      char *pend = pstart;
+      
+      while (*pend) {
+	if (*pend == ':') {
+	  *pend = '\0';
+	  break;
+	}
+	pend++;
+      } /* while (*pend) */
+      
+      found = 1;
+      
+      if (a_what == 11) { /* Map type to FORTRAN-type */
+	pstart = ftntype = map2ftntype(pstart, is_flp, maxbits);
+      }
+    }
+    else { /* a bit-member */
+      int nbits = 0;
+      int n = sscanf(in,"%s %d",pstart,&nbits);
+      if (n == 2 && nbits > 0 && nbits <= MAXBITS) {
+	if (a_what == 11) { /* Map type to FORTRAN-type */
+	  FREE(s);
+	  s = STRDUP("INTEGER(1)"); /* The smallest type we can offer */
+	}
+	else { /* ODB (sub-)type */
+	  FREE(s);
+	  s = STRDUP("bitxxx");
+	  sprintf(s,"bit%d",nbits);
+	}
+	pstart = s;
+	found = 1;
+      }
+    }
+  }
+  else if (a_what == 2) { /* get varname */
+    if (what == a_what) {
+      char *pend = strchr(pstart, ':');
+      if (pend) {
+	pstart = ++pend;
+	found = 1;
+      } /* if (pend) */
+    }
+    else { /* a bit-member */
+      int nbits = 0;
+      int n = sscanf(in,"%s %d",pstart,&nbits);
+      if (n == 2 && nbits > 0 && nbits <= MAXBITS) {
+	char *save = s;
+	char *v = STRDUP(varname);
+	int slen = strlen(v) + strlen(pstart) + 3;
+	char *colname = v;
+	char *tblname = strchr(v,'@');
+	ALLOC(s,slen);
+	if (tblname) { *tblname++ = '\0'; }
+	sprintf(s,"%s.%s%s%s",colname,pstart,
+		tblname ? "@" : "",
+		tblname ? tblname : "");
+	pstart = s;
+	FREE(save);
+	FREE(v);
+	found = 1;
+      }
+    }
+  }
+  else if (what == 3 || what == 33) { /* get tablename */
+    /* obsolete */
+    char *pend = strchr(pstart, '@');
+    if (pend) {
+      pstart = pend;
+      found = 1;
+    } /* if (pend) */
+  }
+
+  x = (found) ? STRDUP(pstart) : STRDUP(in);
+
+  FREE(s);
+  FREE(ftntype);
+
+  DRHOOK_END(0);
+  return x;
+}
+
+
+PRIVATE const ODB_PrepTags *Get_PrepTags(const ODB_Funcs *pf, int What)
+{
+  const ODB_PrepTags *preptag = NULL;
+  if (pf && PFCOM->preptags && PFCOM->npreptag > 0) {
+    int andy = 0;
+    switch (What) {
+    case   1: andy = preptag_type    ; break;
+    case   2: andy = preptag_name    ; break;
+    case 101: andy = preptag_exttype ; break;
+    case 102: andy = preptag_extname ; break;
+    case  33: andy = preptag_tblname ; break;
+    } /* switch (What) */
+    if (andy > 0) {
+      int j, n = PFCOM->npreptag;
+      for (j=0; j<n; j++) { 
+	/* always a short loop; length 3 for views, and 2 or 4 for tables */
+	if ((PFCOM->preptags[j].tagtype & andy) == andy) { 
+	  /* Found ! */
+	  preptag = &PFCOM->preptags[j];
+	  break;
+	}
+      }
+    } /* if (andy > 0) */
+  }
+  return preptag;
+}
+
+
+PUBLIC void
+codb_tag_delim_(char *output
+		/* Hidden arguments */
+		, const int output_len)
+{ /* This routine makes sure that ODB_tag_delim from privpub.h is also used in F90-side */
+  const char *tag_delim = ODB_tag_delim;
+  if (tag_delim) {
+    if (output && output_len >= 1) {
+      *output = *tag_delim;
+      if (output_len > 1) memset(output+1,' ',output_len-1);
+    }
+  }
+}
+
+
+PUBLIC void 
+codb_getnames_(const int *handle,
+	       const char *dataname,
+	       const int *what, /* 1 = datatype, 
+				   2 = varname, 
+				   3 = tablename,
+				   4 = viewname,
+				  11 = ftntype, 
+				 101 = exttype,    (same as datatype, but adds bit<#> for bitfield members)
+				 102 = extname,    (same as varname, but gets bitfield members)
+				 111 = extftntype, (same as ftntype, but handles bitfield members)
+				*/
+	       char *output,    /* Output string: ";xxx;yyy;zzz;" (see ";" for ODB_tag_delim in privpub.h) */
+	       int *actual_output_len, /* # of bytes written into *output, excluding '\0' */
+	       int *retcode,    /* # of cols resolved */
+	       /* Hidden arguments */
+	       int dataname_len,
+	       const int output_len)
+{
+  int rc = 0;
+  int len = 0;
+  int Handle = *handle;
+  int is_table;
+  ODB_Pool *p;
+  int aWhat, What = *what;
+  DECL_FTN_CHAR(dataname);
+  DECL_FTN_CHAR(output);
+  DRHOOK_START(codb_getnames_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+  ALLOC_OUTPUT_FTN_CHAR(output);
+
+  is_table = IS_TABLE(p_dataname);
+
+  if (What == 3 && (*p_dataname != '*' && !is_table)) {
+    /* Get table names associated with this view */
+    What = 33;
+  }
+
+  aWhat = What%100;
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf;
+
+      if (What == 3 || What == 4) {
+	/* Get all table or view names available in the DB */
+	/* Tables always start with '@' */
+
+	int kcols = 0;
+
+	len = 1;
+	FORFUNC {
+	  char *s = PFCOM->name;
+	  int lens = strlen(s);
+	  if ((What == 3 &&  PFCOM->is_table)||
+	      (What == 4 && !PFCOM->is_table && pf->it == 1)) {
+	    len += lens + 1;
+	    kcols++;
+	  }
+	} /* FORFUNC */
+
+	if (output_len <= 0) {
+	  rc = kcols;
+	  len = 0;
+	  goto finish;
+	}
+
+	if (output_len > len) {
+	  strcpy(p_output, ODB_tag_delim);
+	  FORFUNC {
+	    char *s = PFCOM->name;
+	    if ((What == 3 &&  PFCOM->is_table)||
+		(What == 4 && !PFCOM->is_table && pf->it == 1)) {
+	      strcat(p_output,s);
+	      strcat(p_output,ODB_tag_delim);
+	    }
+	  } /* FORFUNC */
+	  rc = kcols;
+	}
+	else {
+	  rc = output_len - len; /* This many chars too short */
+	  len = 0;
+	}
+
+	goto finish;
+      }
+      else if (What == 33) {
+	FORFUNC {
+	  if (strequ(PFCOM->name, p_dataname)) {
+	    const ODB_PrepTags *preptags = Get_PrepTags(pf, What);
+	    int ntot = PFCOM->ntables;
+	    
+	    if (output_len <= 0) {
+	      rc = ntot;
+	      len = 0;
+	      goto finish;
+	    }
+
+	    len = preptags->longname_len;
+
+	    if (output_len > len) {
+	      strcpy(p_output, preptags->longname);
+	      rc = ntot;
+	    }
+	    else {
+	      rc = output_len - len; /* This many chars too short */
+	      len = 0;
+	    }
+	    
+	    goto finish;
+	  }
+	} /* FORFUNC */
+      } 
+      else if (What == 111) {
+	FORFUNC {
+	  if (strequ(PFCOM->name, p_dataname)) {
+	    int k;
+	    const ODB_Tags *tags = PFCOM->tags;
+	    int ncols = PFCOM->ncols - PFCOM->ncols_aux;
+	    int nmem = PFCOM->nmem;
+	    int ntot = ncols + nmem;
+
+	    if (output_len <= 0) {
+	      rc = ntot;
+	      len = 0;
+	      goto finish;
+	    }
+
+	    len = 1;
+
+	    for (k=0; k<ncols; k++) {
+	      char *ptag = parse_name(aWhat, tags[k].name, NULL, NULL, NULL);
+	      int lens = strlen(ptag);
+	      len += lens + 1;
+	      FREE(ptag);
+	    } /* for (k=0; k<ncols; k++) */
+
+	    if (nmem > 0) {
+	      for (k=0; k<ncols; k++) {
+		int n = tags[k].nmem;
+		if (n > 0) {
+		  char *ptag = (aWhat == 2) ? parse_name(aWhat, tags[k].name, NULL, NULL, NULL) : NULL;
+		  char *varname = (aWhat == 2) ? STRDUP(ptag) : NULL;
+		  int i, lens;
+		  FREE(ptag);
+		  for (i=0; i<n; i++) {
+		    ptag = parse_name(What, tags[k].memb[i], NULL, NULL, varname);
+		    lens = strlen(ptag);
+		    len += lens + 1;
+		    FREE(ptag);
+		  } /* for (i=0; i<n; i++) */
+		  FREE(varname);
+		} /* if (n > 0) */
+	      } /* for (k=0; k<ncols; k++) */
+	    } /* if (nmem > 0) */
+	    
+	    if (output_len > len) {
+	      strcpy(p_output, ODB_tag_delim);
+	      for (k=0; k<ncols; k++) {
+		char *ptag = parse_name(aWhat, tags[k].name, NULL, NULL, NULL);
+		strcat(p_output,ptag);
+		strcat(p_output,ODB_tag_delim);
+		FREE(ptag);
+	      } /* for (k=0; k<ncols; k++) */
+
+	      if (nmem > 0) {
+		for (k=0; k<ncols; k++) {
+		  int n = tags[k].nmem;
+		  if (n > 0) {
+		    char *ptag = (aWhat == 2) ? parse_name(aWhat, tags[k].name, NULL, NULL, NULL) : NULL;
+		    char *varname = (aWhat == 2) ? STRDUP(ptag) : NULL;
+		    int i;
+		    FREE(ptag);
+		    for (i=0; i<n; i++) {
+		      ptag = parse_name(What, tags[k].memb[i], NULL, NULL, varname);
+		      strcat(p_output,ptag);
+		      strcat(p_output,ODB_tag_delim);
+		      FREE(ptag);
+		    } /* for (i=0; i<n; i++) */
+		    FREE(varname);
+		  } /* if (n > 0) */
+		} /* for (k=0; k<ncols; k++) */
+	      } /* if (nmem > 0) */
+
+	      rc = ntot;
+	    }
+	    else {
+	      rc = output_len - len; /* This many chars too short */
+	      len = 0;
+	    }
+	    
+	    goto finish;
+	  }
+	} /* FORFUNC */
+      }
+      else if (aWhat == 1 || aWhat == 2) {
+	FORFUNC {
+	  if (strequ(PFCOM->name, p_dataname)) {
+	    const ODB_PrepTags *preptags = Get_PrepTags(pf, What);
+	    int ncols = PFCOM->ncols - PFCOM->ncols_aux;
+	    int nmem = (What == aWhat) ? 0 : PFCOM->nmem;
+	    int ntot = ncols + nmem;
+
+	    if (output_len <= 0) {
+	      rc = ntot;
+	      len = 0;
+	      goto finish;
+	    }
+
+	    len = preptags->longname_len;
+
+	    if (output_len > len) {
+	      strcpy(p_output, preptags->longname);
+	      rc = ntot;
+	    }
+	    else {
+	      rc = output_len - len; /* This many chars too short */
+	      len = 0;
+	    }
+
+	    goto finish;
+	  }
+	}
+      }
+      else {
+	FORFUNC {
+	  if (strequ(PFCOM->name, p_dataname)) {
+	    int k;
+	    const ODB_Tags *tags = PFCOM->tags;
+	    int ncols = PFCOM->ncols - PFCOM->ncols_aux;
+	    
+	    if (output_len <= 0) {
+	      rc = ncols;
+	      goto finish;
+	    }
+
+	    len = 1;
+	    for (k=0; k<ncols; k++) {
+	      char *ptag = parse_name(What, tags[k].name, NULL, NULL, NULL);
+	      int lens = strlen(ptag);
+	      len += lens + 1;
+	      FREE(ptag);
+	    }
+	    
+	    if (output_len > len) {
+	      strcpy(p_output, ODB_tag_delim);
+	      for (k=0; k<ncols; k++) {
+		char *ptag = parse_name(What, tags[k].name, NULL, NULL, NULL);
+		strcat(p_output,ptag);
+		strcat(p_output,ODB_tag_delim);
+		FREE(ptag);
+	      }
+	      rc = ncols;
+	    }
+	    else {
+	      rc = output_len - len; /* This many chars too short */
+	      len = 0;
+	    }
+	    
+	    goto finish;
+	  }
+	} /* FORFUNC */
+      } /* if (What == 3 || What == 4) ... else if's ... else ... */
+    } /* if (p->inuse && p->handle == Handle) */
+  } /* FORPOOL */
+
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+  if (output_len > 0) {
+    if (actual_output_len && len > 0) {
+      COPY_2_FTN_CHARv2(output, len);
+    }
+    else {
+      COPY_2_FTN_CHAR(output);
+    }
+  }
+  FREE_FTN_CHAR(output);
+
+  if (actual_output_len) *actual_output_len = len;
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PRIVATE boolean
+Digital(const char *s)
+{
+  int len = strlen(s);
+  int count = 0;
+  DRHOOK_START(Digital);
+
+  while ( *s ) {
+    if (isdigit(*s)) count++;
+    s++;
+  }
+
+  DRHOOK_END(0);
+  return (count == len);
+}
+
+
+
+PUBLIC void 
+codb_getprecision_(const int *handle,
+		   const char *dataname,
+		   int *maxbits,
+		   int *anyflp,
+		   int *retcode,
+		   /* Hidden arguments */
+		   int dataname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  ODB_Pool *p;
+  int it = get_thread_id_(); /* Any thread id >= 1 will do -> no messing with "using_it" */
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_getprecision_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  *maxbits = 0;
+  *anyflp = 0;
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+
+      if (pf) {
+	void *data = pf->data;
+	int k;
+	boolean Anyflp;
+	int Maxbits;
+	const ODB_Tags *tags = PFCOM->tags;
+	int ncols = PFCOM->ncols - PFCOM->ncols_aux;
+	
+	Anyflp = 0;
+	Maxbits = 0;
+	
+	for (k=0; k<ncols; k++) {
+	  boolean xAnyflp;
+	  int xMaxbits;
+	  int What = 11;
+	  char *ftntype = parse_name(What, tags[k].name, &xAnyflp, &xMaxbits, NULL);
+	  
+	  Anyflp |= xAnyflp;
+	  Maxbits = MAX(Maxbits, xMaxbits);
+	  FREE(ftntype);
+	}
+	
+	*maxbits = Maxbits;
+	*anyflp = Anyflp;
+	
+	rc = ncols;
+	  
+	goto finish;
+      } /* if (pf) */
+    } /* if (p->inuse && p->handle == Handle) */
+  } /* FORPOOL */
+
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_getval_(const char   *dbname,
+	     const char   *varname,
+	     const char   *viewname,
+	     double *value,
+	     const int *using_it,
+	     /* Hidden arguments */
+	     int dbname_len,
+	     int varname_len,
+	     int viewname_len)
+{
+  DRHOOK_START(codb_getval_);
+  if (value) {
+    int vlen;
+    int it = USING_IT;
+    DECL_FTN_CHAR(dbname);
+    DECL_FTN_CHAR(varname);
+    DECL_FTN_CHAR(viewname);
+    
+    ALLOC_FASTFTN_CHAR(dbname);
+    ALLOC_FASTFTN_CHAR(varname);
+    ALLOC_FASTFTN_CHAR(viewname);
+    
+    vlen = p_viewname ? strlen(p_viewname) : 0;
+    *value = ODB_getval_var(p_dbname, 
+			    p_varname, 
+			    (vlen > 0) ? p_viewname : NULL,
+			    it);
+    
+    FREE_FASTFTN_CHAR(dbname);
+    FREE_FASTFTN_CHAR(varname);
+    FREE_FASTFTN_CHAR(viewname);
+  }
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_setval_(const char   *dbname,
+	     const char   *varname,
+	     const char   *viewname,
+	     const double *newvalue,
+	           double *oldvalue,
+	     const int *using_it,
+	     /* Hidden arguments */
+	     int dbname_len,
+	     int varname_len,
+	     int viewname_len)
+{
+  int vlen;
+  int it = using_it ? *using_it : get_thread_id_();
+  int lo, hi;
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(varname);
+  DECL_FTN_CHAR(viewname);
+  DRHOOK_START(codb_setval_);
+
+  ALLOC_FASTFTN_CHAR(dbname);
+  ALLOC_FASTFTN_CHAR(varname);
+  ALLOC_FASTFTN_CHAR(viewname);
+
+  vlen = STRLEN(p_viewname);
+  if (it == -1) {
+    lo = 1;
+    hi = max_omp_threads;
+  }
+  else if (it == 0) {
+    lo = hi = USING_IT;
+  }
+  else {
+    lo = hi = it;
+  }
+  for (it=hi; it>=lo; it--) {
+    (void) ODB_alter_var(p_dbname, 
+			 p_varname, 
+			 (vlen > 0) ? p_viewname : NULL, 
+			 it,
+			 newvalue,
+			 oldvalue,
+			 0);
+  }
+
+  FREE_FASTFTN_CHAR(dbname);
+  FREE_FASTFTN_CHAR(varname);
+  FREE_FASTFTN_CHAR(viewname);
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void	     
+codb_packer_(const int  *handle,
+             const int  *poolno,
+	     const char *dataname,
+	     const int  *pack_it,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int dataname_len)
+{
+  int rc = 0;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  int it = get_thread_id_();
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_packer_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (IS_TABLE(p_dataname)) {
+    int Handle = *handle;
+    boolean Pack = (*pack_it > 0) ? 1 : 0;
+    POOLREG_DEF;
+    int Nbytes = 0;
+
+    POOLREG_FOR {
+      if (MATCHING) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	
+	if (pf) {
+	  void *data = pf->data;  
+	  int (*func)(void *p) = Pack ? PFCOM->pack : PFCOM->unpack;
+	  rc = func(data);
+	  if (rc < 0) goto finish; /* Error */
+	  Nbytes += rc;
+	} /* if (pf) */
+      } /* if (MATCHING) */
+      POOLREG_BREAK;
+    } /* POOLREG_FOR */
+
+    rc = Nbytes;
+  } /* if (IS_TABLE(p_dataname)) */
+
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC int
+ODB_add_funcs(ODB_Pool *p, ODB_Funcs *funcs, int it)
+{
+  int nfuncs = 0;
+  DRHOOK_START(ODB_add_funcs);
+
+  if (p) {
+    nfuncs = p->nfuncs;
+
+    if (funcs) {
+      boolean is_table = IS_TABLE(funcs->common->name);
+      ODB_Funcs *plast  = NULL;
+      ODB_Funcs *pf, *this = NULL, *next;
+      int ret = 0;
+
+      FORFUNC {
+	if (strequ(PFCOM->name,funcs->common->name) &&
+	    (is_table || (!is_table && pf->it == it))) {
+	  this = pf;
+	  break;
+	}
+	plast = pf;
+      }
+
+      funcs->it = it;
+
+      if (!this) { /* Create a new entry */
+	this = funcs;
+	next = NULL;
+	nfuncs++;
+      }
+      else { /* Replace an existing entry */
+	next = this->next;
+	this = funcs;
+      }
+
+      ret = put_forfunc(this, p->handle, p->dbname, p->poolno, funcs->it, funcs->common->name);
+      if (ret < 0) {
+	char msg[] = "put_forfunc failed";
+	codb_abort_func_(msg, strlen(msg));
+      }
+
+      this->next = next;
+
+      if (plast) plast->next = this;
+      
+      if (!p->funcs) p->funcs = this; /* Start chaining now */
+	
+      p->nfuncs = nfuncs;
+    } /* if (funcs) */
+  } /* if (p) */
+
+  DRHOOK_END(0);
+  return nfuncs;
+}
+
+
+PUBLIC void 
+codb_gethandle_(const int *handle,
+		const char *dataname,
+		int *retcode,
+		const int *using_it,
+		/* Hidden arguments */
+		int dataname_len)
+{
+  int rc = -1;
+  int Handle = *handle;
+  ODB_Pool *p;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_gethandle_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+  
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 0);
+
+      if (pf) {
+#define odbrand(x,it) ((((x) & 0x007fffff) << 8) + (it))
+	typedef union _ODB_odbrand {
+	  unsigned long long int i;
+	  void (*f)();
+	  struct {
+	    unsigned int lo;
+	    unsigned int hi;
+	  } s;
+	} ODB_odbrand;
+	ODB_odbrand jack;
+	jack.i = 0; /* ... in case pointers were just 32-bit */
+	jack.f = (void (*)())PFCOM->init;
+	/* This used to be "vhandle" */
+	rc = odbrand(jack.s.lo|jack.s.hi,it); /* Return VIEW or TABLE handle ; different for each thread (it) */
+	goto finish;
+      } /* if (pf) */
+    } /* if (p->inuse && p->handle == Handle) */
+  } /* FORPOOL */
+  
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void 
+codb_get_view_info_(const int *handle,
+		    const char *dataname,
+		    int view_info[],
+		    const int *nview_info,
+		    int *retcode,
+		    /* Hidden arguments */
+		    int dataname_len)
+{
+  int rc = 0;
+  int Nview_info = *nview_info;
+  int Handle = *handle;
+  ODB_Pool *p;
+  int it = get_thread_id_(); /* Any thread id >= 1 will do -> no messing with "using_it" */
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_get_view_info_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	
+      if (pf) {
+	if (Nview_info >= 1) {
+	  view_info[0] = PFCOM->has_select_distinct; /* Fortran index#1 */
+	  rc++;
+	}
+	goto finish;
+      } /* if (pf) */
+    } /* if (p->inuse && p->handle == Handle) */
+  } /* FORPOOL */
+  
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void 
+codb_sortkeys_(const int *handle,
+	       const char *dataname,
+	       int *nkeys,
+	       int  mkeys[],
+	       int *retcode,
+	       /* Hidden arguments */
+	       int dataname_len)
+{
+  int rc = 0;
+  int Nkeys = *nkeys;
+  int Handle = *handle;
+  ODB_Pool *p;
+  int it = get_thread_id_(); /* Any thread id >= 1 will do -> no messing with "using_it" */
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_sortkeys_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (!IS_TABLE(p_dataname)) {
+    FORPOOL {
+      if (p->inuse && p->handle == Handle) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	
+	if (pf) {
+	  void *data = pf->data;
+	  int *keys = PFCOM->sortkeys ? PFCOM->sortkeys(data, &rc) : NULL;
+	  if (keys && rc > 0) {
+	    int j, minkeys = MIN(rc, Nkeys);
+	    for (j=0; j<minkeys; j++) {
+	      /* Usually short(ish) loop */
+	      mkeys[j] = keys[j];
+	    } /* for (j=0; j<minkeys; j++) */
+	  }
+	  goto finish;
+	} /* if (pf) */
+
+      } /* if (p->inuse && p->handle == Handle) */
+    } /* FORPOOL */
+  }
+  
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void 
+codb_update_info_(const int *handle,
+		  const char *dataname,
+		  const int *ncols,
+		  int  can_UPDATE[],
+		  int *retcode,
+		  /* Hidden arguments */
+		  int dataname_len)
+{
+  int rc = 0;
+  int Ncols = *ncols;
+  int Handle = *handle;
+  ODB_Pool *p;
+  int it = get_thread_id_(); /* Any thread id >= 1 will do -> no messing with "using_it" */
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_update_info_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (!IS_TABLE(p_dataname)) {
+    FORPOOL {
+      if (p->inuse && p->handle == Handle) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	if (pf) {
+	  void *data = pf->data;
+	  rc = PFCOM->update_info(data, Ncols, can_UPDATE);
+	  goto finish;
+	} /* if (pf) */
+      } /* if (p->inuse && p->handle == Handle) */
+    } /* FORPOOL */
+  }
+  else {
+    int j;
+    for (j=0; j<Ncols; j++) can_UPDATE[j] = 1; /* All updatable */
+    rc = Ncols;
+  }
+  
+ finish:
+  FREE_FASTFTN_CHAR(dataname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void 
+codb_aggr_info_(const int  *handle,
+		const int  *poolno,
+		const char *dataname,
+		const int  *ncols,
+		int  aggr_func_flag[],
+		int *phase_id,
+		const int *using_it,
+		int *retcode,
+		/* Hidden arguments */
+		int dataname_len)
+{
+  int rc = 0;
+  int Poolno = *poolno;
+  boolean AnyPool = (Poolno == -1);
+  int Ncols = *ncols;
+  int Phase_Id = -1;
+  boolean zero_all = 0;
+  boolean check_env = 0;
+  int it = USING_IT;
+  DECL_FTN_CHAR(dataname);
+  DRHOOK_START(codb_aggr_info_);
+
+  ALLOC_FASTFTN_CHAR(dataname);
+
+  if (!IS_TABLE(p_dataname)) {
+    int Handle = *handle;
+    POOLREG_DEF;
+
+    POOLREG_FOR {
+      if (MATCHING) {
+	ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	if (pf) {
+	  void *data = pf->data;
+	  boolean finito = 0;
+	  if (PFCOM->aggr_info) {
+	    rc = PFCOM->aggr_info(data, Ncols, (Ncols > 0) ? aggr_func_flag : NULL);
+	    if (pf->tmp) {
+	      Phase_Id = 1;
+	      check_env = 0;
+	      finito = 1;
+	    }
+	    else if (!AnyPool) {
+	      check_env = 1;
+	      finito = 1;
+	    }
+	  }
+	  else {
+	    zero_all = 1;
+	    finito = 1;
+	  }
+	  if (finito) goto finish;
+	} /* if (pf) */
+      } /* if (MATCHING) */
+      POOLREG_BREAK;
+    } /* POOLREG_FOR */
+  }
+  else {
+    zero_all = 1;
+  }
+
+ finish:
+
+  if (zero_all) {
+    int j;
+    for (j=0; j<Ncols; j++) aggr_func_flag[j] = ODB_AGGR_NONE; /* All non-aggregate functions */
+    rc = 0;
+  }
+  else if (check_env || (AnyPool && Phase_Id == -1)) {
+    char *env = getenv("CODB_AGGR_PHASE_ID");
+    Phase_Id = 0;
+    if (env) {
+      int val = atoi(env);
+      if (val == -1) Phase_Id = -1;
+    }
+  }
+
+  FREE_FASTFTN_CHAR(dataname);
+  
+  *retcode = rc;
+  *phase_id = Phase_Id;
+  DRHOOK_END(0);
+}
+
+
+/* codb_calc_aggr_(....) moved to aggr.c on 18-Aug-2006/SS */
+
+
+PUBLIC void
+codb_sqlprint_(const int *handle,
+	       const char *dataname,
+	       int *retcode,
+	       /* Hidden arguments */
+	       int dataname_len)
+{
+  int rc = 0;
+  char *env = getenv("ODB_PRINT_SQL");
+  int print_sql = 1;
+  DRHOOK_START(codb_sqlprint_);
+
+  if (env) print_sql = atoi(env);
+  
+  if (print_sql == 1) {
+    FILE *fp = ODB_getprt_FP();
+
+    if (fp) {
+      int Handle = *handle;
+      int Poolno = -1;
+      boolean AnyPool = 1;
+      ODB_Pool *p;
+      int it = get_thread_id_();
+      DECL_FTN_CHAR(dataname);
+      
+      ALLOC_FTN_CHAR(dataname);
+      
+      FORPOOL {
+	if (MATCHING) {
+	  ODB_Funcs *pf = get_forfunc(p->handle, p->dbname, p->poolno, it, p_dataname, 1);
+	  
+	  if (pf) {
+	    rc = PFCOM->sql(fp, 0, ": ", NULL, NULL);
+	    goto finish;
+	  } /* if (pf) */
+	} /* if (MATCHING) */
+      } /* FORPOOL */
+      
+    finish:
+      FREE_FTN_CHAR(dataname);
+    } /* if (fp) */
+  } /* if (print_sql == 1) */
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_filesize_(const char *filename,
+	       int *retcode,
+	       /* Hidden arguments */
+	       int filename_len)
+{
+  /* from libioassign.a */
+  extern char *IOtruename(const char *name, const int *len_str);
+  extern int   IOgetsize(const char *path, int *filesize, int *blksize);
+
+  char *p;
+  int size = 0;
+  DRHOOK_START(codb_filesize_);
+
+  p = IOtruename(filename, &filename_len); 
+  (void) IOgetsize(p, &size, NULL); 
+  FREE(p);
+  
+  *retcode = size;
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_remove_file_(const char *filename,
+		  int *retcode,
+                  /* Hidden arguments */
+                  int filename_len)
+{
+  int rc;
+  DECL_FTN_CHAR(filename);
+  DRHOOK_START(codb_remove_file_);
+
+  ALLOC_FTN_CHAR(filename);
+
+  rc = remove_file_(p_filename);
+  if (retcode) *retcode = rc;
+
+  FREE_FTN_CHAR(filename);
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_rename_file_(const char *oldfile,
+		  const char *newfile,
+		  int *retcode,
+                  /* Hidden arguments */
+                  int oldfile_len,
+                  int newfile_len)
+{
+  int rc;
+  DECL_FTN_CHAR(oldfile);
+  DECL_FTN_CHAR(newfile);
+  DRHOOK_START(codb_rename_file_);
+
+  ALLOC_FTN_CHAR(oldfile);
+  ALLOC_FTN_CHAR(newfile);
+
+  rc = rename_file_(p_oldfile, p_newfile);
+  if (retcode) *retcode = rc;
+
+  FREE_FTN_CHAR(oldfile);
+  FREE_FTN_CHAR(newfile);
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_remove_tablefile_(const char *dbname,
+		       const char *table,
+		       const int  *poolno,
+		       int *retcode,
+		       /* Hidden arguments */
+		       int dbname_len,
+		       int table_len)
+{
+  char *name;
+  int rc, Poolno = *poolno;
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(table);
+  DRHOOK_START(codb_remove_tablefile_);
+
+  ALLOC_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(table);
+
+  MakeFileName(name, p_dbname, p_table, Poolno); /* A macro */
+
+  FREE_FTN_CHAR(dbname);
+  FREE_FTN_CHAR(table);
+
+  rc = remove_file_(name);
+
+  FREEX(name);
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_tablesize_(const char *dbname,
+		const char *table,
+		const int  *poolno,
+		int *retcode,
+		/* Hidden arguments */
+		int dbname_len,
+		int table_len)
+{
+  char *name;
+  int size;
+  int Poolno = *poolno;
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(table);
+  DRHOOK_START(codb_tablesize_);
+
+  ALLOC_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(table);
+
+  MakeFileName(name, p_dbname, p_table, Poolno); /* A macro */
+
+  FREE_FTN_CHAR(dbname);
+  FREE_FTN_CHAR(table);
+
+  codb_filesize_(name, &size, strlen(name));
+
+  FREEX(name);
+  *retcode = size;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_d2u_(const double *d, uint *u) 
+{ 
+  /* RS6K does the following wrong for negative *d's : 
+   *u = (uint) *d; ==> need an alternative */
+  int tmp = *d;
+  /* DRHOOK_START(codb_d2u_); */
+  *u = tmp;
+  /* DRHOOK_END(0); */
+}
+
+PUBLIC double
+ODB_duint(double d)
+{
+  uint u;
+  d = trunc(d);
+  if (d >= -INT_MAX && d <= INT_MAX) {
+    int tmp = d;
+    uint u = tmp;
+    d = u;
+  }
+  else if (d < 0) {
+    /* Not correct ? */
+    d = -d;
+  }
+  return d;
+}
+
+PUBLIC double
+ODB_dfloat(double d)
+{
+  float f = d;
+  d = f;
+  return d;
+}
+
+/* Byte stream distribution */
+
+#ifdef INCLUDE_THIS
+PUBLIC void
+codb_dist_(char s[],
+	   void (*func)(char *s, const int *len, const int *with, int *rc),
+	   const int *with,
+	   const int *dim2len,
+	   int *retcode,
+	   /* Hidden arguments */
+	   const int s_len)
+{
+  int rc = 0;
+  if (func) {
+    int len = s_len * (*dim2len);
+    func(s, &len, with, &rc);
+  }
+  else {
+    rc = -1; /* Error */
+  }
+  *retcode = rc;
+}
+#endif
+
diff --git a/odb/src/lib/codb_distribute.F90 b/odb/src/lib/codb_distribute.F90
new file mode 100644
index 0000000..02a3dfa
--- /dev/null
+++ b/odb/src/lib/codb_distribute.F90
@@ -0,0 +1,54 @@
+!OPTION! -O nodarg
+! E. Sevault 18-May-2009 : SX9 compiler de-optimisation for safety reasons.
+
+SUBROUTINE cODB_idistribute(s, slen, with, rc)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE odbmp, only : ODBMP_distribute
+implicit none
+INTEGER(KIND=JPIM), intent(in)    :: slen, with
+INTEGER(KIND=JPIM), intent(inout) :: s(slen)
+INTEGER(KIND=JPIM), intent(out)   :: rc
+CALL ODBMP_distribute(s, slen, with, rc)
+END SUBROUTINE cODB_idistribute
+
+SUBROUTINE codb_distribute_str(s, func, with, rc)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE odbshared, only : ODB_SIZEOF_INT
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: with
+INTEGER(KIND=JPIM), intent(out) :: rc
+character(len=*), intent(inout) :: s
+external func
+INTEGER(KIND=JPIM), parameter :: sizeof_int = ODB_SIZEOF_INT
+INTEGER(KIND=JPIM) :: slen, xlen
+INTEGER(KIND=JPIM), allocatable :: x(:)
+slen = len(s)
+xlen = (slen+sizeof_int-1)/sizeof_int
+allocate(x(xlen))
+call ctransfer(1,1,s,x)
+CALL func(x, xlen, with, rc)
+call ctransfer(-1,1,s,x)
+deallocate(x)
+if (rc == xlen) rc = slen
+END SUBROUTINE codb_distribute_str
+
+SUBROUTINE codb_distribute_vecstr(s, func, with, dim2len, rc)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE odbshared, only : ODB_SIZEOF_INT
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: with, dim2len
+INTEGER(KIND=JPIM), intent(out) :: rc
+character(len=*), intent(inout) :: s(dim2len)
+external func
+INTEGER(KIND=JPIM), parameter :: sizeof_int = ODB_SIZEOF_INT
+INTEGER(KIND=JPIM) :: slen, xlen
+INTEGER(KIND=JPIM), allocatable :: x(:)
+slen = len(s) * dim2len
+xlen = (slen+sizeof_int-1)/sizeof_int
+allocate(x(xlen))
+call ctransfer(1,dim2len,s,x)
+CALL func(x, xlen, with, rc)
+call ctransfer(-1,dim2len,s,x)
+deallocate(x)
+if (rc == xlen) rc = slen
+END SUBROUTINE codb_distribute_vecstr
diff --git a/odb/src/lib/codb_truename.c b/odb/src/lib/codb_truename.c
new file mode 100644
index 0000000..6de8a2c
--- /dev/null
+++ b/odb/src/lib/codb_truename.c
@@ -0,0 +1,36 @@
+#include "odb.h"
+#include "cmaio.h"
+
+/* Fortran-interface to convert logical (CMAIO) name
+   into physical filename, with any possible environment 
+   variables resolved */
+
+void 
+codb_truename_(const char *in,
+	             char *out,
+		     int  *retcode,
+	       /* Hidden arguments */
+	             int  in_len,
+	       const int  out_len)
+{
+  int rc = 0;
+
+  {
+    char *s;
+    DECL_FTN_CHAR(out);
+
+    ALLOC_OUTPUT_FTN_CHAR(out);
+
+    s = IOtruename(in, &in_len);
+    rc = strlen(s);
+    rc = MIN(rc, out_len);
+    strncpy(p_out, s, rc);
+    p_out[rc] = '\0'; /* Don't worry: p_out always +1 char longer than out */
+    FREE(s);
+
+    COPY_2_FTN_CHAR(out);
+    FREE_FTN_CHAR(out);
+  }
+
+  *retcode = rc;
+}
diff --git a/odb/src/lib/cread_iomap.c b/odb/src/lib/cread_iomap.c
new file mode 100644
index 0000000..7f24e7c
--- /dev/null
+++ b/odb/src/lib/cread_iomap.c
@@ -0,0 +1,127 @@
+
+/* cread_iomap.c */
+
+#include "cmaio.h"
+
+#define MAXLEN 512
+
+typedef const int cint_t;
+extern void create_iomap_( /* A Fortran routine in "odb/lib/create_iomap.F90" */
+    cint_t *khandle, cint_t *kfirst_call, cint_t *kmaxpools,
+    cint_t *kpoff, cint_t *kfblk, const char *cdfile, cint_t *kgrpsize,
+    cint_t *ktblno, const char *cdtbl,
+    cint_t *kpoolno, cint_t *kfileno, cint_t *koffset, cint_t *klength, cint_t *krows, cint_t *kcols,
+    int *kret
+    /* Hidden arguments */
+    , int cdfile_len, int cdtbl_len);
+
+PUBLIC void
+cread_iomap_(const int *handle,
+	     const char *file,
+	     int *fileblockno,
+	     int *pool_offset,
+	     int *retcode
+	     /* Hidden arguments */
+	     , int file_len)
+{
+  int Handle = *handle;
+  int Fblk = *fileblockno;
+  int Poff = *pool_offset;
+  int io, rc, fmt=0;
+  int nelem = 0;
+  static int myproc = 0;
+  char s[MAXLEN+1];
+  FILE *fp = NULL;
+  DECL_FTN_CHAR(file);
+  extern void codb_procdata_(int *myproc, int *nproc, int *pid,
+			     int *it, int *inumt);
+
+  if (myproc == 0) codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+
+  ALLOC_FTN_CHAR(file);
+  io = -1;
+  if (myproc == 1) fprintf(stderr, "Opening IOMAP-file='%s' for reading\n",p_file);
+  cma_open_(&io, p_file, "r", &rc, file_len, strlen("r"));
+  if (rc != 1) goto finish;
+
+  fp = CMA_get_fp(&io);
+  if (!fp) goto finish;
+
+  nelem = fscanf(fp, "%d\n", &fmt);
+  if (myproc == 1) fprintf(stderr, "\tFormat=%d\n",fmt);
+
+  if (fmt == 1) { /* Automatically created */
+    int maxtables=0, maxpools=0, grpsize=0, pad=0, io_method=0, length_multiplier=0;
+    nelem = fscanf(fp, "%s\n%d %d %d\n%d %d %d\n", 
+		   s, &maxtables, &maxpools, &grpsize,
+		   &pad, &io_method, &length_multiplier);
+    if (nelem == 7) {
+      int first_call = 1;
+      Fblk++;
+      if (myproc == 1) {
+	fprintf(stderr, 
+	"\tFile block#%d: tables=%d, maxpools=%d, grpsize=%d, pad=%d, io_method=%d, lenmult=%d\n",
+	   Fblk, maxtables, maxpools, grpsize, pad, io_method, length_multiplier);
+      }
+      for (;;) { /* TABLE_LOOP */
+	char *tblname = s;
+	int tblno=0, ncols=0;
+	nelem = fscanf(fp, "%d %d %s\n", &tblno, &ncols, tblname);
+	/*
+	if (myproc == 1) {
+	  fprintf(stderr,
+		  "\t tbl#%d, ncols=%d, tblname='%s', nelem=%d\n", 
+		  tblno, ncols, tblname, nelem);
+	}
+	*/
+	if (nelem != 3 || tblno < 1 || tblno > maxtables) break; /* TABLE_LOOP */
+	for (;;) { /* POOL_LOOP */
+	  int poolno=0, fileno=0, offset=0, length=0, nrows=0;
+	  nelem = fscanf(fp, "%d %d %d %d %d\n",  &poolno, &fileno, &offset, &length, &nrows);
+/*AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ *AF 24/08/09 bug found - if several "empty" databases are created and merged together
+ *AF it does not create the iomap structure (%nfileblocks is then 0) and cannot write it back
+ *AF when we close the database (because if a database exists but it empty we have -1 for poolno in
+ *AF the iomap file
+ *AF as a workaround, do create a table ("desc") which is then overwritten. */
+	  if (nelem != 5 || poolno < 1 || poolno > maxpools) break; /* POOL_LOOP */
+	  /* Pass data to Fortran-layer (after scaling offset & length to be byte-units) */
+	  if (length_multiplier > 1) {
+	    offset *= length_multiplier;
+	    length *= length_multiplier;
+	  }
+	  /* if (first_call && myproc == 1) { fprintf(stderr,"\t first_call; Fblk#%d\n", Fblk); } */
+	  create_iomap_(&Handle, &first_call, &maxpools,
+			&Poff, &Fblk, p_file, &grpsize,
+			&tblno, tblname,
+			&poolno, &fileno, &offset, &length, &nrows, &ncols,
+			&rc,
+			strlen(p_file), strlen(tblname));
+	  first_call = 0;
+	} /* POOL_LOOP */
+      } /* TABLE_LOOP */
+      Poff += maxpools;
+    } /* if (nelem == 6) */
+  }
+  else if (fmt == 2) { /* Created normally by a script */
+    char *next_iomap_file = s;
+    for (;;) { /* FILEBLK_LOOP */
+      if (feof(fp)) break; /* FILEBLK_LOOP */
+      /* get another iomap-file */
+      nelem = fscanf(fp, "%s\n", next_iomap_file);
+      if (nelem != 1) break; /* FILEBLK_LOOP */
+      cread_iomap_(&Handle, next_iomap_file, 
+		   &Fblk, &Poff, 
+		   &rc, strlen(next_iomap_file));
+    } /* FILEBLK_LOOP */
+  }
+  
+  cma_close_(&io, &rc);
+  *pool_offset = Poff;
+  *fileblockno = Fblk;
+
+ finish: 
+  FREE_FTN_CHAR(file);
+
+  *retcode = rc;
+}
diff --git a/odb/src/lib/create_iomap.F90 b/odb/src/lib/create_iomap.F90
new file mode 100644
index 0000000..28e0416
--- /dev/null
+++ b/odb/src/lib/create_iomap.F90
@@ -0,0 +1,110 @@
+SUBROUTINE create_iomap(khandle, kfirst_call, kmaxpools, &
+ & kpoff, kfblk, cdfile, kgrpsize, &
+ & ktblno, cdtbl, &
+ & kpoolno, kfileno, koffset, klength, krows, kcols, &
+ & kret) 
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+use odb_module
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle, kfblk, kpoff, kgrpsize, krows, kcols
+INTEGER(KIND=JPIM), intent(in)  :: kfirst_call, kmaxpools
+INTEGER(KIND=JPIM), intent(in)  :: ktblno, kpoolno, kfileno, koffset, klength
+INTEGER(KIND=JPIM), intent(out) :: kret
+
+character(len=*), intent(in) :: cdfile, cdtbl
+INTEGER(KIND=JPIM) :: itblno, ipoolno, ntables, jt, j, naid
+logical :: has_at, LL_first
+character(len=maxvarlen), POINTER :: cltable(:)
+INTEGER(KIND=JPIM), POINTER :: ioaid(:,:,:) ! Shorthand
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CREATE_IOMAP',0,ZHOOK_HANDLE)
+kret = 0
+
+if (ODBMP_myproc /= 1 .AND. LHOOK) CALL DR_HOOK('CREATE_IOMAP',1,ZHOOK_HANDLE)
+if (ODBMP_myproc /= 1)      return
+if (.NOT.db(khandle)%inuse .AND. LHOOK) CALL DR_HOOK('CREATE_IOMAP',1,ZHOOK_HANDLE)
+if (.NOT.db(khandle)%inuse) return
+
+naid = db(khandle)%naid
+
+if (naid == 0 .AND. LHOOK) CALL DR_HOOK('CREATE_IOMAP',1,ZHOOK_HANDLE)
+if (naid == 0)  return
+
+if (kfblk <= 0 .AND. LHOOK) CALL DR_HOOK('CREATE_IOMAP',1,ZHOOK_HANDLE)
+if (kfblk <= 0)             return
+
+LL_first = (kfirst_call == 1)
+
+if (LL_first .AND. kfblk > db(khandle)%nfileblocks) then
+  db(khandle)%ciomap(kfblk) = cdfile
+  db(khandle)%grpsize(kfblk) = kgrpsize
+  db(khandle)%nfileblocks = max(db(khandle)%nfileblocks, kfblk)
+  if (.not.associated(db(khandle)%ctables)) then ! Enforce db(khandle)%ctables(1:ntables) into the cache
+!    write(0,*) 'create_iomap.F90: before ODB_getnames(... "table")'
+    ntables = ODB_getnames(khandle, '*', 'table')
+!    write(0,*) 'create_iomap.F90: ntables[1]=',ntables
+    allocate(cltable(ntables))
+    ntables = ODB_getnames(khandle, '*', 'table', cltable)
+!    write(0,*) 'create_iomap.F90: ntables[2]=',ntables
+    deallocate(cltable)
+    nullify(cltable)
+  endif
+endif
+
+cltable => db(khandle)%ctables
+ntables = size(cltable)
+
+has_at = .FALSE.
+if (len(cdtbl) > 0) then
+  has_at = (cdtbl(1:1) == '@')
+endif
+
+itblno = -1
+if (ktblno >= 1 .AND. ktblno <= ntables) then
+  if ((has_at .AND. cltable(ktblno) == cdtbl) .OR. &
+     & cltable(ktblno)(2:) == cdtbl) then 
+    itblno = ktblno
+  endif
+endif
+
+if (itblno == -1) then ! search ...
+  LOOP: do jt=1,ntables
+    if ((has_at .AND. cltable(jt) == cdtbl) .OR. &
+       & cltable(jt)(2:) == cdtbl) then 
+      itblno = jt
+      exit LOOP
+    endif
+  enddo LOOP
+endif
+
+nullify(cltable)
+
+if (itblno == -1) then
+  CALL ODB_abort('CREATE_IOMAP()', 'Unable to locate table="'//trim(cdtbl)//'"', ktblno)
+endif
+
+ioaid => db(khandle)%ioaid
+
+if (LL_first) then ! Supply sane initial settings for ALL tables in the pool-range
+  ioaid(kpoff+1:kpoff+kmaxpools, :, IOAID_FBLOCK)  = kfblk
+  ioaid(kpoff+1:kpoff+kmaxpools, :, IOAID_GRPSIZE) = kgrpsize
+  do j=1,kmaxpools
+    ipoolno = kpoff + j
+    ioaid(ipoolno, :, IOAID_POOLNO) = j
+  enddo
+endif
+
+ipoolno = kpoff + kpoolno
+ioaid(ipoolno, itblno, IOAID_POOLNO)  = kpoolno ! A possible override
+ioaid(ipoolno, itblno, IOAID_FILENO)  = kfileno
+ioaid(ipoolno, itblno, IOAID_OFFSET)  = koffset
+ioaid(ipoolno, itblno, IOAID_LENGTH)  = klength
+ioaid(ipoolno, itblno, IOAID_NROWS)   = krows
+ioaid(ipoolno, itblno, IOAID_NCOLS)   = kcols
+
+nullify(ioaid)
+IF (LHOOK) CALL DR_HOOK('CREATE_IOMAP',1,ZHOOK_HANDLE)
+
+END SUBROUTINE create_iomap
diff --git a/odb/src/lib/create_statid.F90 b/odb/src/lib/create_statid.F90
new file mode 100644
index 0000000..c5793ac
--- /dev/null
+++ b/odb/src/lib/create_statid.F90
@@ -0,0 +1,13 @@
+SUBROUTINE CREATE_STATID(CDSTATID,kstatid)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+implicit none
+character(len=*), intent(in) :: CDSTATID
+INTEGER(KIND=JPIM), intent(out) :: kstatid
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('CREATE_STATID',0,ZHOOK_HANDLE)
+kstatid = 0
+read(CDSTATID,*,end=99,err=99) kstatid
+99 continue
+IF (LHOOK) CALL DR_HOOK('CREATE_STATID',1,ZHOOK_HANDLE)
+END SUBROUTINE CREATE_STATID
diff --git a/odb/src/lib/ctransfer.c b/odb/src/lib/ctransfer.c
new file mode 100644
index 0000000..6d0e843
--- /dev/null
+++ b/odb/src/lib/ctransfer.c
@@ -0,0 +1,25 @@
+#include "odb.h"
+
+/* 
+   A F90 TRANSFER-function substitution for SUN4, since
+   character <=> integer-array transfer didn't work.
+
+   Called from codb_distrubute (... _str())
+
+*/
+
+void 
+ctransfer_(const int *mode,
+	   const int *mult,
+	   char s[],
+	   int x[],
+	   /* Hidden arguments */
+	   const int s_len)
+{
+  if (*mode == 1) { /* Character to integer */
+    memcpy(x, s, (*mult) * s_len * sizeof(*s));
+  }
+  else { /* Integer to character */
+    memcpy(s, x, (*mult) * s_len * sizeof(*s));
+  }
+}
diff --git a/odb/src/lib/ctx.c b/odb/src/lib/ctx.c
new file mode 100644
index 0000000..c1374cc
--- /dev/null
+++ b/odb/src/lib/ctx.c
@@ -0,0 +1,295 @@
+
+/* ctx.c */
+
+#include "odb.h"
+
+/* Fortran-callable functions to associate
+   database & retrieval into a context */
+
+/*--- Defines functions:
+
+  character(len=*) dbname, retr
+  integer version, ctxid, retcode, ifailmsg
+  CALL ctxreg(dbname, retr, version, ctxid, retcode)
+  ifailmsg = 0 ! Dont want a printout when retcode becomes == -2
+  ifailmsg = 1 ! Will have a printout when retcode becomes == -2
+  CALL ctxid(dbname, retr, version, ctxid, ifailmsg, retcode)
+
+  character(len=*) message
+  integer enforce
+  CALL ctxdebug(enforce=[0|1],message)
+
+  ---*/
+
+#ifndef CTX_HASHSIZE
+#define CTX_HASHSIZE 223U
+#endif
+
+PRIVATE uint CTX_hashsize = 0;
+
+typedef struct _CTX_Hash_Table {
+  uint  version;
+  char *retr;
+  char *dbname;
+  int   ctxid;
+  struct _CTX_Hash_Table *collision;
+} CTX_Hash_Table;
+
+PRIVATE CTX_Hash_Table **CTX_hashtable = NULL;
+
+PRIVATE uint CTX_hashmin = INT_MAX;
+PRIVATE uint CTX_hashmax = 0;
+
+PRIVATE uint
+Hash(const uint u, const char *s1, const char *s2)
+{ 
+  uint hashval = u;
+  for (; *s1 ; s1++) {
+    hashval = (*s1) + 31U * hashval;
+  }
+  for (; *s2 ; s2++) {
+    hashval = (*s2) + 31U * hashval;
+  }
+  hashval = hashval % CTX_hashsize;
+  return hashval;
+}
+
+
+PRIVATE void
+HashInit()
+{
+  if (!CTX_hashtable) {
+    CTX_Hash_Table **tmp_CTX_hashtable = NULL;
+    char *p = getenv("ODB_CTX_HASHSIZE");
+    if (p) {
+      CTX_hashsize = atoi(p);
+      if (CTX_hashsize <= 0) CTX_hashsize = CTX_HASHSIZE;
+    }
+    else
+      CTX_hashsize = CTX_HASHSIZE;
+    CALLOC(tmp_CTX_hashtable, CTX_hashsize);
+    CTX_hashtable = tmp_CTX_hashtable;
+  }
+}
+
+
+PRIVATE CTX_Hash_Table *
+NewEntry(void)
+{
+  CTX_Hash_Table *p;
+  ALLOC(p, 1);
+  p->version = 0;
+  p->retr = NULL;
+  p->dbname = NULL;
+  p->ctxid = 0;
+  p->collision = NULL;
+  return p;
+}
+
+PUBLIC void
+init_CTX_lock()
+{
+  HashInit();
+}
+
+/*---
+  CALL ctxreg(dbname, retr, version, ctxid, retcode)
+  ---*/
+
+PUBLIC void
+ctxreg_(const char *dbname,
+	const char *retr,
+	const int  *version,
+	const int  *ctxid,
+	int *retcode,
+	/* Hidden arguments */
+	int dbname_len,
+	int retr_len)
+{
+  int rc = 0;
+  uint Version = *version;
+  int Ctxid = *ctxid;
+  uint index;
+  CTX_Hash_Table *p;
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(retr);
+
+  ALLOC_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(retr);
+
+  rc = index = Hash(Version, p_retr, p_dbname);
+
+  CTX_hashmin = MIN(CTX_hashmin, index);
+  CTX_hashmax = MAX(CTX_hashmax, index);
+
+  p = CTX_hashtable[index];
+
+  if (!p) {
+    p = NewEntry();
+    CTX_hashtable[index] = p;
+  }
+  
+  while (p->dbname && p->retr) {
+    if (Version == p->version &&
+	strequ(p->dbname, p_dbname) &&
+	strequ(p->retr, p_retr)) {
+      if (Ctxid != p->ctxid) {
+        fprintf(stderr,
+                "ctxreg_[ctxid=%d]: (version,db,retr)=(%u,'%s','%s') already registered with a different ctxid=%d\n",
+                Ctxid, Version, p_dbname, p_retr, p->ctxid);
+        rc = -1;
+      }
+      goto finish; /* Already in list (whether bad or good, doesn't matter) */
+    }
+    if (!p->collision) p->collision = NewEntry();
+    p = p->collision;
+  } /* while (p->dbname && p->retr) */
+
+  p->version  = Version;
+  p->retr   = STRDUP(p_retr);
+  p->dbname = STRDUP(p_dbname);
+  p->ctxid  = Ctxid;
+
+ finish:
+  FREE_FTN_CHAR(dbname);
+  FREE_FTN_CHAR(retr);
+
+  *retcode = rc;
+}
+
+
+/*---
+  CALL ctxid(dbname, retr, version, ctxid, retcode)
+  ---*/
+
+
+PUBLIC void
+ctxid_(const char *dbname,
+       const char *retr,
+       const int *version,
+       int *ctxid,
+       const int *ifailmsg,
+       int *retcode,
+       /* Hidden arguments */
+       int dbname_len,
+       int retr_len)
+{
+  int rc = 0;
+  uint Version = *version;
+  int Ctxid = 0; /* Correct range starts from 1 */
+  uint index;
+  CTX_Hash_Table *p;
+  DECL_FTN_CHAR(dbname);
+  DECL_FTN_CHAR(retr);
+
+  ALLOC_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(retr);
+
+  rc = index = Hash(Version, p_retr, p_dbname);
+  p = CTX_hashtable[index];
+
+  if (!p) {
+    /*
+    fprintf(stderr,
+	    "ctxid_: Unregistered (version,db,retr)=(%u,'%s','%s')\n",
+	    Version, p_dbname, p_retr);
+	    */
+    rc = -1;
+    goto finish; /* Unrecognized triplet */
+  }
+  
+  while (p->dbname && p->retr) {
+    if (p->version == Version &&
+	strequ(p->dbname, p_dbname) &&
+	strequ(p->retr, p_retr)) break; /* Found */
+    if (p->collision) 
+      p = p->collision;
+    else {
+      if (*ifailmsg) {
+	fprintf(stderr,
+		"ctxid_: (version,db,retr)=(%u,'%s','%s') not registered\n",
+		Version, p_dbname, p_retr);
+      }
+      rc = -2;
+      goto finish; /* Unrecognized triplet */
+    }
+  } /* while (p->dbname && p->retr) */
+  
+  Ctxid = p->ctxid;
+
+ finish:
+  FREE_FTN_CHAR(dbname);
+  FREE_FTN_CHAR(retr);
+
+  *ctxid = Ctxid;
+  *retcode = rc;
+}
+
+/*---
+  Debug printout to STDERR:
+  CALL ctxdebug(enforce=[0|1],message)
+  ---*/
+
+PUBLIC void
+ctxdebug_(const int *enforce,
+	  const char *msg,
+	  /* Hidden arguments */
+	  int msg_len)
+{
+  DECL_FTN_CHAR(msg);
+  int print_it = *enforce;
+  int j;
+  int entries=0;
+  int hits=0;
+  char *env = getenv("ODB_CTX_DEBUG");
+  char blank = ' ';
+  
+  if (env) {
+    int myproc = 0;
+    int ienv = atoi(env);
+    codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+    if (ienv == -1 || ienv == myproc) ienv = 1;
+    else ienv = 0;
+    print_it |= ienv;
+  }
+
+  if (!print_it) return;
+
+  {
+    extern void ctxprint_(const int *print_it, const char *msg, const char *dbname
+			  /* Hidden arguments */
+			  , int msg_len, int dbname_len);
+    ctxprint_(&print_it, msg, &blank, msg_len, 1); /* A genuine Fortran-routine */
+  }
+
+  ALLOC_FTN_CHAR(msg);
+
+  if (msg_len > 0) fprintf(stderr,"ctxdebug_: %s\n",p_msg);
+  fprintf(stderr,
+	  "ctxdebug_: hashsize=%u, hashmin=%u, hashmax=%u, hashtable at %p\n",
+	  CTX_hashsize, CTX_hashmin, CTX_hashmax, CTX_hashtable);
+
+  if (CTX_hashtable) {
+    for (j=CTX_hashmin; j<=CTX_hashmax; j++) {
+      CTX_Hash_Table *p = CTX_hashtable[j];
+      int k=1;
+      if (p) entries++;
+      while (p) {
+	fprintf(stderr,
+		"hash#%d [hit#%d] : version=%u, retr='%s', db='%s', ctxid=%d\n",
+		j,k,
+		p->version,
+		p->retr ? p->retr : NIL,
+		p->dbname ? p->dbname : NIL, 
+		p->ctxid);
+	p = p->collision;
+	k++;
+	hits++;
+      } /* while (p) */
+    } /* for (j=CTX_hashmin; j<=CTX_hashmax; j++) */
+  } /* if (CTX_hashtable) */
+
+  fprintf(stderr,"ctxdebug_: Total %d hits in %d hash-entries\n",hits,entries);
+
+  FREE_FTN_CHAR(msg);
+}
diff --git a/odb/src/lib/datastream.F90 b/odb/src/lib/datastream.F90
new file mode 100644
index 0000000..7079ae9
--- /dev/null
+++ b/odb/src/lib/datastream.F90
@@ -0,0 +1,60 @@
+FUNCTION DATASTREAM(BUFRTYPE,BUFRSUBTYPE,&
+ &   GEN_CENTRE,GEN_SUBCENTRE,SATID)
+
+USE PARKIND1  ,ONLY : JPRB
+
+IMPLICIT NONE
+
+REAL(KIND=JPRB)   :: DATASTREAM
+
+REAL(KIND=JPRB), INTENT(IN)   :: BUFRTYPE
+REAL(KIND=JPRB), INTENT(IN)   :: BUFRSUBTYPE
+REAL(KIND=JPRB), INTENT(IN)   :: GEN_CENTRE
+REAL(KIND=JPRB), INTENT(IN)   :: GEN_SUBCENTRE
+REAL(KIND=JPRB), INTENT(IN)   :: SATID
+
+
+!  11/11/2008   I. Genkova     Modify db MODIS datastream
+!======================================
+
+
+DATASTREAM = 0._JPRB          ! Global data is default
+
+IF(          BUFRTYPE    == 3._JPRB            & ! SATEM
+ &     .AND. BUFRSUBTYPE == 55._JPRB ) THEN      ! ATOVS
+
+  ! Special streams for ATOVS data
+  !-------------------------------
+
+  IF(          GEN_CENTRE    == 254._JPRB      &   ! EUMETSAT
+   &     .AND. GEN_SUBCENTRE > 0._JPRB ) THEN      ! Some sub-centre
+    DATASTREAM = 1._JPRB                            ! EARS
+
+  ELSEIF(     GEN_CENTRE <= 69._JPRB .OR. GEN_CENTRE == 110 ) THEN      
+    DATASTREAM = 2._JPRB                            ! Pacific RARS
+
+  ENDIF
+
+ELSEIF(       BUFRTYPE    == 5._JPRB            & ! SATOB/AMV
+ &      .AND. BUFRSUBTYPE == 87._JPRB ) THEN      ! Ext. AMV with QI
+
+  ! Special streams for AMVs 
+  !-------------------------
+
+
+
+  IF( ( GEN_CENTRE == 173._JPRB .OR. GEN_CENTRE == 176._JPRB  & ! CIMSS
+   &    .OR.( GEN_CENTRE == 160._JPRB              & ! NESDIS
+   &          .AND. GEN_SUBCENTRE > 0._JPRB )  )   &
+   &  .AND. ( SATID == 783 .OR. SATID == 784) ) THEN
+    DATASTREAM = 1._JPRB                             ! Direct broadcast MODIS
+  ENDIF
+
+ELSEIF(       BUFRTYPE    == 12._JPRB            & ! SCATT
+ &      .AND. BUFRSUBTYPE == 139._JPRB           & ! ASCAT
+ &      .AND. GEN_SUBCENTRE > 0._JPRB  ) THEN      ! Non-EUMETSAT 
+    DATASTREAM = 1._JPRB                           ! EARS
+END IF
+
+
+END FUNCTION DATASTREAM
diff --git a/odb/src/lib/dynlink.c b/odb/src/lib/dynlink.c
new file mode 100644
index 0000000..ad954ca
--- /dev/null
+++ b/odb/src/lib/dynlink.c
@@ -0,0 +1,1019 @@
+#include "odb.h"
+#include "cdrhook.h"
+
+extern char *IOresolve_env(const char *str); /* from libioassign.a */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern int ODBstatic_mode;
+
+PRIVATE const char spath[] = "ODB_SRCPATH";
+PRIVATE const char outpath[] = "ODB_OUTPATH";
+
+PRIVATE void
+fixenv(const char *name, const char *value)
+{
+  char *env;
+  int len = strlen(name) + strlen(value) + 2;
+  ALLOC(env, len);
+  sprintf(env,"%s=%s",name,value);
+  /* fprintf(stderr,"fixenv: %s\n",env); */
+  putenv(env);
+}
+
+typedef struct _ODB_StatFunc {
+  char *dbname;
+  char *viewname;
+  ODB_Funcs *(*anchor)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars);
+  struct _ODB_StatFunc *next;
+} ODB_StatFunc;
+
+PRIVATE ODB_StatFunc *first_st = NULL;
+PRIVATE ODB_StatFunc *last_st = NULL;
+
+typedef struct _Dyn_Handles {
+  void *handle;
+  char *dbname;
+  char *viewname;
+  char *symname;
+  char *so_file;
+  union {
+    void *entry;
+    ODB_Funcs *(*func)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars);
+  } u;
+  ODB_Funcs *(*anchor)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars);
+  struct _Dyn_Handles *next;
+} Dyn_Handles;
+
+PRIVATE Dyn_Handles *dynlink_start = NULL;
+PRIVATE Dyn_Handles *dynlink_last  = NULL;
+
+
+#ifdef STATIC_LINKING
+
+/* Dummies for dlopen(), dlsym(), dlclose() and dlerror() */
+
+PRIVATE char dl_errmsg[] = "An attempt to perform dynamic linking when it was turned off";
+
+PRIVATE void *dlopen(const char *pathname, int mode) { return NULL; }
+PRIVATE int dlclose(void *handle) { return 1; /* Indicates error */ } 
+PRIVATE void *dlsym(void *handle, const char *name) { return NULL; }
+PRIVATE char *dlerror(void) { return dl_errmsg; }
+
+#define DYNAMIC_ERROR(where,error_text)         fprintf(stderr,"%s : %s\n",where,error_text); perror(dlerror())
+#define DYNAMIC_OPEN(handle, path, ormode)      handle = dlopen(path, 0 | ormode); DYNAMIC_ERROR("dlopen", path);
+#define DYNAMIC_CLOSE(handle, rc)               rc = dlclose(handle); DYNAMIC_ERROR("dlclose", "");
+#define DYNAMIC_SYMBOL(handle, name, entry, rc) entry = dlsym(handle, name); rc = -1; DYNAMIC_ERROR("dlsym", name);
+
+#else
+
+/* Genuinely a dynamic version (relies on -ldl) */
+
+#ifdef HPPA
+/* This can be set to 0, when HP-UX 11.xx is in place 
+   (it has got dlopen() etc. proper stuff) */
+#define HP_SHL_LOAD 1
+#else
+#define HP_SHL_LOAD 0
+#endif
+
+#if HP_SHL_LOAD == 1
+#include <dl.h>
+#define DYNAMIC_OPEN(handle, path, ormode)           handle = shl_load(path, \
+								  runtime_load_now ? BIND_IMMEDIATE | ormode : \
+						 		       BIND_DEFERRED | BIND_VERBOSE | ormode \
+								  , 0L) ; \
+                                                { if (handle && Myproc == 1) { fprintf(stderr,"shl_load: Successfully loaded '%s'\n", path); } } \
+                                                { if (!handle && Myproc == 1) { DYNAMIC_ERROR("shl_load", path); } }
+#define DYNAMIC_CLOSE(handle, rc)               rc = shl_unload(handle)
+#define DYNAMIC_SYMBOL(handle, name, entry, rc) rc = shl_findsym((shl_t *)&handle, name, TYPE_UNDEFINED, &entry)
+#define DYNAMIC_ERROR(where, error_text)        fprintf(stderr,"%s : %s\n",where,error_text); perror(error_text)
+#else
+#include <dlfcn.h>
+#define DYNAMIC_OPEN(handle, path, ormode)      handle = dlopen(path, runtime_load_now ? RTLD_NOW | ormode : RTLD_LAZY | ormode) ; \
+                                                { if (handle && Myproc == 1) { fprintf(stderr,"dlopen: Successfully loaded '%s'\n", path); } } \
+                                                { if (!handle && Myproc == 1) { DYNAMIC_ERROR("dlopen", path); } }
+#define DYNAMIC_CLOSE(handle, rc)               rc = dlclose(handle)
+#define DYNAMIC_SYMBOL(handle, name, entry, rc) entry = dlsym(handle, name); rc = (!entry) ? -1 : 0
+#define DYNAMIC_ERROR(where,error_text)         fprintf(stderr,"***Problems; %s : %s\n",where,error_text) ; perror(dlerror())
+#endif
+
+#endif
+
+
+
+PUBLIC void
+ODB_addstatfunc(const char *dbname,
+		const char *viewname,
+		ODB_Funcs *(*anchor)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars))
+{
+  DRHOOK_START(ODB_addstatfunc);
+  if (dbname && anchor) {
+    ODB_StatFunc *pst;
+    boolean found = 0;
+    
+    if (viewname) {
+      for (pst = first_st; pst != NULL; pst = pst->next) {
+	if (pst->viewname &&
+	    strequ(pst->viewname, viewname) &&
+	    strequ(pst->dbname, dbname)) {
+	  found = 1;
+	  break;
+	}
+      }
+    }
+    else {
+      for (pst = first_st; pst != NULL; pst = pst->next) {
+	if (!pst->viewname &&
+	    strequ(pst->dbname, dbname)) {
+	  found = 1;
+	  break;
+	}
+      }
+    }
+    
+    if (!found) {
+      ALLOC(pst, 1);
+      if (first_st) last_st->next = pst;
+      else          first_st = pst;
+      last_st = pst;
+      
+      pst->dbname = STRDUP(dbname);
+      pst->viewname = viewname ? STRDUP(viewname) : NULL;
+      pst->anchor = anchor;
+      pst->next = NULL;
+    }
+  }
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+ODB_linkview_static(const int *handle, 
+		    const char *viewname,
+		    int *retcode,
+		    /* Hidden arguments */
+		    int viewname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  ODB_StatFunc *st = NULL;
+  ODB_Pool *p;
+  DECL_FTN_CHAR(viewname);
+  DRHOOK_START(ODB_linkview_static);
+
+  ALLOC_FTN_CHAR(viewname);
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      boolean found = 0;
+      ODB_StatFunc *pst = NULL;
+      char *dbname  = p->dbname;
+
+      for (pst = first_st; pst != NULL; pst = pst->next) {
+	if (pst->viewname && 
+	    strequ(pst->viewname, p_viewname) &&
+	    strequ(pst->dbname, dbname)) {
+	  st = pst;
+	  found = 1;
+	  break;
+	}
+      }
+      if (!found) rc = -1; /* Not statically declared */
+      break;
+    }
+  }
+
+  if (st) {
+    /* Anchor the static view and register it to the pools it belongs to */
+    int inumt = get_max_threads_();
+    int add_vars = 1;
+    FORPOOL {
+      if (p->inuse && p->handle == Handle) {
+	int it;
+	for (it = 1; it <= inumt ; it++) {
+	  ODB_Funcs *pf = st->anchor(NULL, p, NULL, it, add_vars);
+	  ODB_add_funcs(p, pf, it);
+	} /* for (it = 1; it <= inumt ; it++) */
+	add_vars = 0;
+      }
+    } /* FORPOOL */
+  }
+
+  /* finish: */
+  FREE_FTN_CHAR(viewname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void
+ODB_linkdb_static(const char *dbname,
+		  int *retcode,
+		  /* Hidden arguments */
+		  int dbname_len)
+{
+  int rc = 0;
+  boolean found = 0;
+  ODB_StatFunc *st = NULL;
+  ODB_StatFunc *pst;
+  DECL_FTN_CHAR(dbname);
+  DRHOOK_START(ODB_linkdb_static);
+
+  ALLOC_FTN_CHAR(dbname);
+
+  for (pst = first_st; pst != NULL; pst = pst->next) {
+    if (!pst->viewname &&
+	strequ(pst->dbname, p_dbname)) {
+      st = pst;
+      found = 1;
+      break;
+    }
+  }
+  if (!found) rc = -1; /* Not statically declared */
+
+  if (st) {
+    /* Get no. of TABLEs (indepedent of pools) */
+    st->anchor(NULL, NULL, &rc, 0, 0);
+  }
+
+  /* finish: */
+  FREE_FTN_CHAR(dbname);
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PRIVATE ODB_Pool *
+ODB_create_pool_static(int handle, 
+		       const char *dbname, 
+		       int poolno, 
+		       int is_new,
+		       int io_method,
+		       int add_vars)
+{
+  ODB_Pool *p = NULL;
+  DRHOOK_START(ODB_create_pool_static);
+
+  if (dbname) {
+    ODB_Funcs *(*anchor)(void *V, ODB_Pool *pool, int *ntables, int it, int add_vars) = NULL;
+    ODB_StatFunc *pst;
+
+    for (pst = first_st; pst != NULL; pst = pst->next) {
+      if (!pst->viewname &&
+	  strequ(pst->dbname, dbname)) {
+	anchor = pst->anchor;
+	break;
+      }
+    }
+
+    if (anchor) {
+      ODB_Anchor_Funcs func = { NULL, NULL, NULL };
+
+      ALLOC(p, 1);
+      if (first_pool) last_pool->next = p;
+      else            first_pool = p;
+      last_pool = p;
+
+      p->handle = handle;
+      p->dbname = STRDUP(dbname);
+      p->srcpath = STRDUP("");
+      p->poolno = poolno;
+      
+      p->pm = ODB_get_poolmask_by_handle(handle);
+
+      p->add_var = ODB_add_var;
+      anchor(&func, p, NULL, 0, add_vars);
+      
+      p->load = func.load;
+      p->store = func.store;
+      
+      p->funcs  = NULL;
+      p->nfuncs = 0;
+      p->nfuncs = func.create_funcs(p, is_new, io_method, 0);
+      
+      p->next = NULL;
+      p->inuse = 1;
+
+      put_poolreg(handle, poolno, p);
+    }
+  }
+
+  DRHOOK_END(0);
+  return p;
+}
+
+
+PUBLIC void
+codb_makeview_(const int  *handle,
+               const char *viewname,
+	       const char *viewfile,
+               const char *select,
+               const char *uniqueby,
+               const char *from,
+               const char *where,
+               const char *orderby,
+	       const char *set,
+	       const char *query,
+               int *retcode,
+	       /* Hidden arguments */
+               int viewname_len,
+               int viewfile_len,
+	       int select_len,
+	       int uniqueby_len,
+	       int from_len,
+	       int where_len,
+	       int orderby_len,
+	       int set_len,
+	       int query_len)
+{
+#ifdef DEBUG
+  const char Pwd[] = "pwd;";
+#else
+  const char Pwd[] = "";
+#endif
+  static char *odb_compiler = NULL;
+  int rc = 0;
+  int Handle = *handle;
+  ODB_Pool *p;
+  DECL_FTN_CHAR(viewname);
+  DECL_FTN_CHAR(viewfile);
+  DECL_FTN_CHAR(select);
+  DECL_FTN_CHAR(uniqueby);
+  DECL_FTN_CHAR(from);
+  DECL_FTN_CHAR(where);
+  DECL_FTN_CHAR(orderby);
+  DECL_FTN_CHAR(set);
+  DECL_FTN_CHAR(query);
+  DRHOOK_START(codb_makeview_);
+
+  if (ODBstatic_mode) {
+    rc = -1; /* N/A in static mode */
+    goto finish;
+  }
+
+  ALLOC_FTN_CHAR(viewname);
+  ALLOC_FTN_CHAR(viewfile);
+  ALLOC_FTN_CHAR(select);
+  ALLOC_FTN_CHAR(uniqueby);
+  ALLOC_FTN_CHAR(from);
+  ALLOC_FTN_CHAR(where);
+  ALLOC_FTN_CHAR(orderby);
+  ALLOC_FTN_CHAR(set);
+  ALLOC_FTN_CHAR(query);
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      char *dbname  = p->dbname;
+      char *srcpath = p->srcpath;
+      FILE *fp;
+      char *filename, *so_file;
+      char *cmd;
+      int len;
+      
+      if (!odb_compiler) {
+	char *s = getenv("ODB_COMPILER");
+	odb_compiler = s ? STRDUP(s) : STRDUP(ODB_COMPILER_DEFAULT);
+      }
+
+      len = strlen(srcpath) + strlen(p_viewname) + strlen(dbname);
+      ALLOC(so_file, len + 8);
+      sprintf(so_file,"%s/%s_%s.so", srcpath, dbname, p_viewname);
+
+      if (viewfile_len > 0) {
+	filename = STRDUP(p_viewfile);
+      }
+      else {
+	/* Generate automatically */
+	int unit;
+
+	len = strlen(srcpath) + strlen(dbname) + strlen(p_viewname);
+	ALLOC(filename, len + 10);
+	sprintf(filename, "%s/%s_%s.sql", srcpath, dbname, p_viewname);
+	
+	cma_open_(&unit, filename, "w", &rc, strlen(filename), 1);
+	if (rc != 1) {
+	  perror(filename);
+	  rc = -1;
+	  goto finish;
+	}
+
+	fp = CMA_get_fp(&unit);
+	fprintf(fp,"// Automatically created for view '%s' :\n",p_viewname);
+	if (set_len > 0) fprintf(fp,"%s",p_set);
+	fprintf(fp,"\nCREATE VIEW %s AS",p_viewname);
+	if (query_len > 0) {
+	  fprintf(fp,"%s",p_query);
+	}
+	else {
+	  fprintf(fp,"\n\t  SELECT %s",p_select);
+	  if (uniqueby_len > 0) fprintf(fp,"\n\tUNIQUEBY %s",p_uniqueby);
+	  fprintf(fp,"\n\t    FROM %s",p_from);
+	  if (where_len > 0)    fprintf(fp,"\n\t   WHERE %s",p_where);
+	  if (orderby_len > 0)  fprintf(fp,"\n\t ORDERBY %s",p_orderby);
+	}
+	fprintf(fp,"\n;\n");
+	fclose(fp);
+      }
+
+      len = 
+	strlen(filename) + 2 * strlen(so_file) + strlen(odb_compiler) + 
+	  2 * strlen(dbname) + strlen(srcpath) + strlen(filename);
+      ALLOC(cmd, len + 100);
+#ifdef HPPA
+      sprintf(cmd,
+	      "\n\t%s\n\tcat %s;\n\t/bin/mv -f %s __hppa.so;\n\t%s -w -l %s -D%s -o %s %s;\n\tls -l %s",
+	      Pwd, filename, so_file,
+	      odb_compiler,dbname,dbname,srcpath,filename,so_file);
+#else
+      sprintf(cmd,
+	      "\n\t%s\n\tcat %s;\n\t/bin/rm -f %s;\n\t%s -w -l %s -D%s -o %s %s;\n\tls -l %s",
+	      Pwd, filename, so_file,
+	      odb_compiler,dbname,dbname,srcpath,filename,so_file);
+#endif
+      fprintf(stderr,">> Compiling: %s\n",cmd);
+
+      {
+	char *pp = getenv("ODB_LIBS_KEEP"); /* if == 1, keep ODB_LIBS unaltered for views */
+	int keep = pp ? atoi(pp) : 0; /* The default for compatibility is to *ALTER* $ODB_LIBS */
+	char *p = getenv("ODB_LIBS");
+	char *odb_libs = p ? STRDUP(p) : NULL;
+
+	if (!keep && odb_libs) { /* Make ODB_LIBS empty */
+	  fixenv("ODB_LIBS", "");
+	} /* if (!keep && odb_libs) */
+	 
+	system(cmd);
+
+	if (!keep && odb_libs) { /* Reset ODB_LIBS back */
+	  fixenv("ODB_LIBS", odb_libs);
+	} /* if (!keep && odb_libs) */
+
+	FREE(odb_libs);
+      }
+
+      FREE(cmd);
+      FREE(filename);
+
+      /* if (viewfile_len <= 0) */
+      {
+	char *tmp = IOresolve_env(so_file);
+	struct stat buf;
+	if (stat(tmp, &buf) == -1) {
+	  fprintf(stderr,"Shareable object file '%s' (alias '%s') not found\n",so_file,tmp);
+	  perror(so_file);
+	  rc = -1;
+	}
+	FREE(tmp);
+      }
+
+      FREE(so_file);
+
+      break;
+    }
+  }
+
+ finish:
+  FREE_FTN_CHAR(viewname);
+  FREE_FTN_CHAR(viewfile);
+  FREE_FTN_CHAR(select);
+  FREE_FTN_CHAR(uniqueby);
+  FREE_FTN_CHAR(from);
+  FREE_FTN_CHAR(where);
+  FREE_FTN_CHAR(orderby);
+  FREE_FTN_CHAR(set);
+  FREE_FTN_CHAR(query);
+
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PRIVATE void *
+link_dynamically(const char *dbname, 
+		 const char *viewname, 
+		 const char *symname, 
+		 const char *so_file,
+		 int *retcode)
+{
+  int rc = 0;
+  int dlretcode = 0;
+  Dyn_Handles *dynlink = NULL;
+  Dyn_Handles *d = dynlink_start;
+  FILE *do_trace = ODB_trace_fp(); 
+  ODB_Trace TracE;
+  const char trace_text[] = "link_dynamically :";
+  static int Myproc = 0;
+  char *rldpath = getenv("ODB_RLDPATH");
+  char *rldpath_only = getenv("ODB_RLDPATH_ONLY");
+  char *rld_now = getenv("ODB_RLD_NOW");  
+  char *rld_ormode = getenv("ODB_RLD_ORMODE");
+  int value_rldpath_only = 0;
+  int runtime_load_now = 0;
+  int runtime_load_ormode = 0;
+
+  if (rldpath && rldpath_only) value_rldpath_only = atoi(rldpath_only);
+  if (rld_now) runtime_load_now = atoi(rld_now);
+
+  if (Myproc == 0) codb_procdata_(&Myproc, NULL, NULL, NULL, NULL);
+
+  if (do_trace) {
+    TracE.handle = -1;
+    TracE.msglen = 
+      (dbname ? strlen(dbname) : strlen(NIL)) + 
+	(viewname ? strlen(viewname) : strlen(NIL)) +
+	  (symname ? strlen(symname) : strlen(NIL)) +
+	      strlen(trace_text) + 10;
+    ALLOC(TracE.msg,TracE.msglen);
+    sprintf(TracE.msg,"%s (%s,%s,%s)",
+	    trace_text, 
+	    dbname ? dbname : NIL, 
+	    viewname ? viewname : NIL, 
+	    symname ? symname : NIL); 
+    TracE.numargs = 0;
+    TracE.mode = 1;
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, &TracE.numargs, TracE.msglen);
+  }
+
+  while (d) {
+    if (strequ(d->dbname, dbname) && 
+	strequ(d->symname, symname)) {
+      dynlink = d;
+      break;
+    }
+    d = d->next;
+  }
+
+  if (!dynlink) {
+    ALLOC(d, 1);
+    d->handle = NULL;
+    d->dbname = STRDUP(dbname);
+    d->viewname = viewname ? STRDUP(viewname) : NULL;
+    d->symname = STRDUP(symname);
+    d->so_file = IOresolve_env(so_file);
+    d->u.entry = NULL;
+    d->anchor = NULL;
+    d->next = NULL;
+    dynlink = d;
+    
+    if (!dynlink_start) {
+      dynlink_start = dynlink;
+    }
+    else {
+      dynlink_last->next = dynlink;
+    }
+    dynlink_last = dynlink;
+  }
+  
+  if (dynlink->handle) {
+    int inumt = get_max_threads_();
+    int it;
+    for (it = 1; it <= inumt; it++) {
+      ODB_del_vars(dbname, dynlink->viewname, it);
+    }
+    DYNAMIC_CLOSE(dynlink->handle, dlretcode);
+    if (dlretcode != 0) { /* Failed : Cannot close */
+      DYNAMIC_ERROR("dlclose",dynlink->dbname);
+      rc = -1;
+      goto finish;
+    }      
+  }
+  
+  dynlink->handle = NULL;
+  FREE(dynlink->so_file);
+  dynlink->u.entry = NULL;
+  dynlink->anchor  = NULL;
+      
+  /* Perform the actual dynamic linking */
+  
+  dynlink->so_file = IOresolve_env(so_file);
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  ">> Dynamic linking of symbol '%s' from DSO-file '%s'\n",
+	  symname, so_file);
+#endif
+
+  if (value_rldpath_only <= 0) {
+    DYNAMIC_OPEN(dynlink->handle, dynlink->so_file, runtime_load_ormode);
+  }
+  if (!dynlink->handle || value_rldpath_only > 0) { /* Failed : Cannot get handle */
+    /* Giving a second try ? rely on ODB_RLDPATH */
+
+    char *bname = strrchr(dynlink->so_file,'/');
+
+    if (rldpath && bname) {
+      char *saved = STRDUP(rldpath);
+      char *token = strtok(saved,":");
+      char *basename;
+      int len, baselen;
+      bname++;
+      basename = STRDUP(bname);
+      baselen = strlen(basename);
+      /* fprintf(stderr,"ODB_RLDPATH='%s'\n",rldpath); */
+      while (!dynlink->handle && token) {
+	/* fprintf(stderr,"token='%s' : basename='%s'\n",token,basename); */
+	len = strlen(token) + baselen;
+	FREE(dynlink->so_file);
+	ALLOC(dynlink->so_file, len + 2);
+	sprintf(dynlink->so_file, "%s/%s", token, basename);
+	DYNAMIC_OPEN(dynlink->handle, dynlink->so_file, runtime_load_ormode);
+	token = strtok(NULL,":");
+      }
+      FREE(saved);
+      FREE(basename);
+    }
+
+    if (!dynlink->handle) { /* Failed : Cannot get handle */
+      DYNAMIC_ERROR("dlopen",dynlink->so_file);
+      rc = -2;
+      goto finish;
+    }
+  }
+  
+  DYNAMIC_SYMBOL(dynlink->handle, symname, dynlink->u.entry, dlretcode);
+  if (dlretcode != 0) { /* Failed : No such entry */
+    DYNAMIC_ERROR("dlsym",symname);
+    rc = -3;
+    goto finish;
+  }
+  
+  dynlink->anchor = dynlink->u.func; /* For convenience */
+
+  if (!viewname) {
+    /* Get no. of TABLEs (indepedent of pools) */
+    dynlink->anchor(NULL, NULL, &rc, 0, 0);
+  }
+
+ finish:
+
+  if (do_trace) {
+    TracE.args[0] = rc;
+    TracE.numargs = 1;
+    TracE.mode = 0;
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, &TracE.numargs, TracE.msglen);
+    FREE(TracE.msg);
+  }
+
+  if (retcode) *retcode = rc;
+
+  return (rc == 0 && dynlink) ? dynlink : NULL;
+}
+
+
+PUBLIC int
+ODB_undo_dynlink(const char *dbname, boolean views_only)
+{
+  int rc = 0;
+  int dlretcode = 0;
+  Dyn_Handles *dynlink = dynlink_start;
+  int count = 0;
+  FILE *do_trace = ODB_trace_fp(); 
+  ODB_Trace TracE;
+  const char trace_text[] = "undo_dynlink for ";
+
+  if (ODBstatic_mode) 
+    return 0; /* N/A in static mode => return code = 0 is okay */
+
+  if (do_trace) {
+    TracE.handle = -1;
+    TracE.msglen = strlen(dbname) + strlen(trace_text) + 1;
+    ALLOC(TracE.msg,TracE.msglen);
+    sprintf(TracE.msg,"%s%s",trace_text,dbname);
+    TracE.args[0] = views_only;
+    TracE.numargs = 1;
+    TracE.mode = 1;
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, &TracE.numargs, TracE.msglen);
+  }
+
+#ifdef DEBUG
+  fprintf(stderr,
+	  "Running ODB_undo_dynlink: dbname=%s, views_only=%d\n",
+	  dynlink->dbname,
+	  (int)views_only);
+#endif
+
+  while (dynlink) {
+    if (dynlink->handle &&
+	strequ(dynlink->dbname, dbname)) {
+      
+      if ((views_only && dynlink->viewname) || !views_only) {
+	char *viewname = views_only ? dynlink->viewname : NULL;
+	int it = 0;
+	if (viewname) {
+	  int inumt = get_max_threads_();
+	  for (it = 1; it <= inumt ; it++) {
+	    ODB_del_vars(dbname, viewname, it);
+	  }
+	}
+	else {
+	  ODB_del_vars(dbname, viewname, it);
+	}
+	
+	count++;
+#ifdef DEBUG
+	fprintf(stderr,
+		"#%d: dbname=%s, viewname=%s, handle=%x\n",
+		count,
+		dynlink->dbname,
+		dynlink->viewname ? dynlink->viewname : NIL,
+		dynlink->handle);
+#endif
+
+	DYNAMIC_CLOSE(dynlink->handle, dlretcode);
+	if (dlretcode != 0) {
+	  DYNAMIC_ERROR("dlclose", dynlink->dbname);
+	  rc = -1;
+	  goto finish;
+	}
+	
+	dynlink->handle = NULL;
+	if (!views_only) goto finish; /* Only one anchor per DBase */
+      }
+    }
+
+    dynlink = dynlink->next;
+  } /* while (dynlink) */
+
+ finish:
+
+  if (do_trace) {
+    TracE.args[0] = views_only;
+    TracE.args[1] = count;
+    TracE.args[2] = rc;
+    TracE.numargs = 3;
+    TracE.mode = 0;
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, &TracE.numargs, TracE.msglen);
+    FREE(TracE.msg);
+  }
+
+  return rc;
+}
+
+
+PUBLIC void
+codb_linkview_(const int *handle, 
+	       const char *viewname,
+	       int *retcode,
+	       /* Hidden arguments */
+	       int viewname_len)
+{
+  int rc = 0;
+  int Handle = *handle;
+  Dyn_Handles *dynlink = NULL;
+  ODB_Pool *p;
+  DECL_FTN_CHAR(viewname);
+  DRHOOK_START(codb_linkview_);
+
+  if (ODBstatic_mode) {
+    ODB_linkview_static(handle, viewname, &rc, viewname_len);
+    goto finish;
+  }
+
+  ALLOC_FTN_CHAR(viewname);
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      char *dbname  = p->dbname;
+      char *srcpath = p->srcpath;
+      char *symname;
+      char *so_file;
+      int len;
+
+      len = strlen("Anchor2") + strlen(p_viewname) + strlen(dbname);
+      ALLOC(symname, len + 2);
+      sprintf(symname,"Anchor2%s_%s",dbname,p_viewname);
+
+      len = strlen(srcpath) + strlen(p_viewname) + strlen(dbname);
+
+      ALLOC(so_file, len + 6);
+      sprintf(so_file, "%s/%s_%s.so", srcpath, dbname, p_viewname);
+
+      dynlink = link_dynamically(dbname, p_viewname, symname, so_file, &rc);
+
+      FREE(symname);
+      FREE(so_file);
+
+      if (rc < 0) goto finish;
+
+      break;
+    }
+  }
+
+  if (dynlink) {
+    /* Anchor the dynamic view and register it to the pools it concerns */
+    int inumt = get_max_threads_();
+    int add_vars = 0;
+    FORPOOL {
+      if (p->inuse && p->handle == Handle) {
+	int it;
+	for (it = 1; it <= inumt ; it++) {
+	  ODB_Funcs *pf = dynlink->anchor(NULL, p, NULL, it, add_vars);
+	  ODB_add_funcs(p, pf, it);
+	} /* for (it = 1; it <= inumt ; it++) */
+	add_vars = 0;
+      }
+    } /* FORPOOL */
+  }
+
+ finish:
+  FREE_FTN_CHAR(viewname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_linkdb_(const char *dbname,
+	     int *retcode,
+	     /* Hidden arguments */
+	     int dbname_len)
+{
+  int rc = 0;
+  Dyn_Handles *dynlink = NULL;
+  DECL_FTN_CHAR(dbname);
+  DRHOOK_START(codb_linkdb_);
+
+  if (ODBstatic_mode) {
+    ODB_linkdb_static(dbname, &rc, dbname_len);
+    goto finish;
+  }
+
+  ALLOC_FTN_CHAR(dbname);
+
+  {
+    char *symname;
+    char *so_file;
+    char *dollar_path = NULL;
+    char *srcpath = NULL;
+    int len;
+
+    len = strlen(spath) + strlen(p_dbname) + 2;
+    ALLOC(dollar_path, len);
+    sprintf(dollar_path, "%s_%s", spath, p_dbname);
+
+    srcpath = getenv(dollar_path);
+
+    if (!srcpath) {
+      srcpath = getenv(spath);
+      if (srcpath) {
+	fixenv(dollar_path, srcpath);
+	FREE(dollar_path);
+	dollar_path = STRDUP(spath);
+      }
+      else {
+	fprintf(stderr,
+		"*** Error in codb_linkdb_(): Either %s or %s must be defined\n",
+		dollar_path, spath);
+	rc = -1;
+	goto finish;
+      }
+    }
+    
+    FREE(dollar_path);
+
+    len = strlen("Anchor2") + strlen(p_dbname);
+    ALLOC(symname, len + 1);
+    sprintf(symname,"Anchor2%s",p_dbname);
+    
+    len = strlen(srcpath) + strlen(p_dbname);
+
+    ALLOC(so_file, len + 5);
+    sprintf(so_file, "%s/%s.so", srcpath, p_dbname);
+
+    dynlink = link_dynamically(p_dbname, NULL, symname, so_file, &rc);
+    
+    FREE(symname);
+    FREE(so_file);
+    
+    if (rc < 0 || !dynlink) goto finish;
+  }
+
+ finish:
+  FREE_FTN_CHAR(dbname);
+  
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC ODB_Pool *
+ODB_create_pool(int handle, 
+		const char *dbname, 
+		int poolno, 
+		int is_new,
+		int io_method,
+		int add_vars)
+{
+  ODB_Pool *p = NULL;
+  DRHOOK_START(ODB_create_pool);
+
+  if (ODBstatic_mode) {
+    p = ODB_create_pool_static(handle, dbname, poolno, is_new, io_method, add_vars);
+    goto finish;
+  }
+
+  if (dbname) {
+    ODB_Anchor_Funcs func = { NULL, NULL, NULL };
+    Dyn_Handles *dynlink = NULL;
+
+    char *srcpath = NULL;
+    char *dollar_path = NULL;
+
+    {
+      int len;
+      
+      len = strlen(spath) + strlen(dbname) + 2;
+      ALLOC(dollar_path, len);
+      sprintf(dollar_path, "%s_%s", spath, dbname);
+
+      srcpath = getenv(outpath);
+
+      if (!srcpath) {
+	srcpath = getenv(dollar_path);
+      }
+      else {
+	fixenv(dollar_path, srcpath);
+	FREE(dollar_path);
+	dollar_path = STRDUP(outpath);
+      }
+
+      if (!srcpath) {
+	srcpath = getenv(spath);
+	if (srcpath) {
+	  fixenv(dollar_path, srcpath);
+	  FREE(dollar_path);
+	  dollar_path = STRDUP(spath);
+	}
+	else {
+	  fprintf(stderr,
+		  "*** Error in ODB_create_pool(): Either %s or %s must be defined\n",
+		  dollar_path, spath);
+	  goto finish;
+	}
+      }
+    }  
+
+    {
+      Dyn_Handles *d = dynlink_start;
+      
+      while (d) {
+	if (!d->viewname && strequ(d->dbname, dbname)) {
+	  dynlink = d;
+	  break;
+	}
+	d = d->next;
+      }
+
+      if (!dynlink) {
+	fprintf(stderr,
+		"*** Error: Database %s is not linked\n",
+		dbname);
+	goto finish;
+      }
+    }
+
+
+    ALLOC(p, 1);
+    if (first_pool) last_pool->next = p;
+    else            first_pool = p;
+    last_pool = p;
+
+    p->handle = handle;
+    p->dbname = STRDUP(dbname);
+    ALLOC(p->srcpath, strlen(dollar_path) + 2);
+    sprintf(p->srcpath,"$%s",dollar_path);
+    p->poolno = poolno;
+
+    p->pm = ODB_get_poolmask_by_handle(handle);
+
+    p->add_var = ODB_add_var;
+    (void) dynlink->anchor(&func, p, NULL, 0, add_vars);
+
+    p->load = func.load;
+    p->store = func.store;
+
+    p->funcs  = NULL;
+    p->nfuncs = 0;
+    p->nfuncs = func.create_funcs(p, is_new, io_method, 0);
+
+    p->next = NULL;
+    p->inuse = 1;
+
+    put_poolreg(handle, poolno, p);
+
+    FREE(dollar_path);
+  }
+
+ finish:
+
+  DRHOOK_END(0);
+  return p;
+}
diff --git a/odb/src/lib/eq_regions.c b/odb/src/lib/eq_regions.c
new file mode 100644
index 0000000..e4f6279
--- /dev/null
+++ b/odb/src/lib/eq_regions.c
@@ -0,0 +1,1701 @@
+/* eq_regions.c */
+
+/*
+  A PARTITION OF THE UNIT SPHERE INTO REGIONS OF EQUAL AREA AND SMALL DIAMETER
+  Algorithm by Paul Leopardi, School of Mathematics, University of South Wales
+*/
+
+#include "odb.h"
+#include "regcache.h"
+#include "result.h"
+#include "cdrhook.h"
+
+#define swap(T, vi, vj) { register T temp = vi; vi = vj; vj = temp; }
+
+#define NINT(x) F90nint(x)
+
+#define ERROR(msg) { if (msg) fprintf(stderr,"%s\n",msg); RAISE(SIGABRT); }
+
+PRIVATE int
+gcd(int a, int b)
+{
+  int m = ABS(a);
+  int n = ABS(b);
+  if ( m > n ) swap(int, m, n);
+  return (m == 0) ? n : gcd(n%m, m);
+}
+
+
+PRIVATE double
+my_gamma(double x)
+{
+  const double p0  =  0.999999999999999990e0;
+  const double p1  = -0.422784335098466784e0;
+  const double p2  = -0.233093736421782878e0;
+  const double p3  =  0.191091101387638410e0;
+  const double p4  = -0.024552490005641278e0;
+  const double p5  = -0.017645244547851414e0;
+  const double p6  =  0.008023273027855346e0;
+  const double p7  = -0.000804329819255744e0;
+  const double p8  = -0.000360837876648255e0;
+  const double p9  =  0.000145596568617526e0;
+  const double p10 = -0.000017545539395205e0;
+  const double p11 = -0.000002591225267689e0;
+  const double p12 =  0.000001337767384067e0;
+  const double p13 = -0.000000199542863674e0;
+  int n = NINT(x - 2);
+  double w = x - (n + 2);
+  double y = ((((((((((((p13 * w + p12) * w + p11) * w + p10) *
+		      w + p9) * w + p8) * w + p7) * w + p6) * w + p5) *
+		 w + p4) * w + p3) * w + p2) * w + p1) * w + p0;
+  int k;
+  if (n > 0) {
+    w = x - 1;
+    for (k = 2; k <= n; k++) w *= (x - k);
+  }
+  else {
+    int nn = -n - 1;
+    w = 1;  
+    for (k=0; k <= nn; k++) y *= (x + k);
+  }
+  return w / y;
+}
+
+
+PRIVATE double
+circle_offset(int n_top, int n_bot)
+{
+  /*
+    !
+    !CIRCLE_OFFSET Try to maximize minimum distance of center points for S^2 collars
+    !
+    ! Given n_top and n_bot, calculate an offset.
+    !
+    ! The values n_top and n_bot represent the numbers of
+    ! equally spaced points on two overlapping circles.
+    ! The offset is given in multiples of whole rotations, and
+    ! consists of three parts;
+    ! 1) Half the difference between a twist of one sector on each of bottom and top.
+    ! This brings the centre points into alignment.
+    ! 2) A rotation which will maximize the minimum angle between
+    ! points on the two circles.
+    !
+  */
+  double co = 
+    (double)(1/(double)(n_bot) - 1/(double)(n_top))/2 + 
+    (double)(gcd(n_top,n_bot))/(2*(double)(n_top)*(double)(n_bot));
+  return co;
+}
+
+/* Please note that in Fortran: real*8 region(dim,2) */
+
+#define region(i,j) reg[((j)-1)*dim + (i) - 1]
+
+PRIVATE void
+sphere_region(int dim, double reg[])
+{
+  /* 
+     !
+     ! An array of two points representing S^dim as a region.
+     !
+  */
+  if ( dim == 1 ) {
+    region(1,1)=0;
+    region(1,2)=two_pi;
+  }
+  else if ( dim == 2 ) {
+    /* 
+       ! sphere_region_1 = sphere_region(dim-1);
+       !  region = [[sphere_region_1(:,1); 0],[sphere_region_1(:,2); pi]] ;
+    */
+    region(1,1)=0;
+    region(1,2)=two_pi;
+    region(2,1)=0;
+    region(2,2)=pi;
+  }
+  else {
+    ERROR("sphere_region: dim > 2 not supported");
+  }
+}
+
+
+PRIVATE void
+top_cap_region(int dim, double a_cap, double reg[])
+{
+  /*
+    !
+    ! An array of two points representing the top cap of radius a_cap as a region.
+    !
+  */
+  if ( dim == 1 ) {
+    region(1,1)=0;
+    region(1,2)=a_cap;
+  }
+  else if ( dim == 2 ) {
+    /*
+      ! sphere_region_1 = sphere_region(dim-1);
+      ! region = [[sphere_region_1(:,1); 0], [sphere_region_1(:,2); a_cap]];
+    */
+    region(1,1)=0;
+    region(1,2)=two_pi;
+    region(2,1)=0;
+    region(2,2)=a_cap;
+  }
+  else {
+    ERROR("top_cap_region: dim > 2 not supported");
+  }
+}
+
+
+PRIVATE void
+bot_cap_region(int dim, double a_cap, double reg[])
+{
+  /*
+    !
+    ! An array of two points representing the bottom cap of radius a_cap as a region.
+    !
+  */
+  if ( dim == 1 ) {
+    region(1,1)=two_pi-a_cap;
+    region(1,2)=two_pi;
+  }
+  else if ( dim == 2 ) {
+    /*
+      ! sphere_region_1 = sphere_region(dim-1);
+      ! region = [[sphere_region_1(:,1); pi-a_cap],[sphere_region_1(:,2); pi]];
+    */
+    region(1,1)=0;
+    region(1,2)=two_pi;
+    region(2,1)=pi-a_cap;
+    region(2,2)=pi;
+  }
+  else {
+    ERROR("bot_cap_region: dim > 2 not supported");
+  }
+}
+
+
+PRIVATE double
+area_of_cap(int dim, double s_cap)
+{
+  /*
+    !AREA_OF_CAP Area of spherical cap
+    !
+    !Syntax
+    ! area = area_of_cap(dim, s_cap);
+    !
+    !Description
+    ! AREA = AREA_OF_CAP(dim, S_CAP) sets AREA to be the area of an S^dim spherical
+    ! cap of spherical radius S_CAP.
+    !
+    ! The argument dim must be a positive integer.
+    ! The argument S_CAP must be a real number or an array of real numbers.
+    ! The result AREA will be an array of the same size as S_CAP.
+    !
+  */
+  double area;
+  if ( dim == 1 ) {
+    area = 2 * s_cap;
+  }
+  else if ( dim == 2 ) {
+    area = four_pi * pow(sin(s_cap/2),2);
+  }
+  else {
+    ERROR("area_of_cap: dim > 2 not supported");
+  }
+  return area;
+}
+
+
+PRIVATE double
+area_of_collar(int dim, double a_top, double a_bot)
+{
+  /* 
+     !
+     !AREA_OF_COLLAR Area of spherical collar
+     !
+     !Syntax
+     ! area = area_of_collar(dim, a_top, a_bot);
+     !
+     !Description
+     ! AREA = AREA_OF_COLLAR(dim, A_TOP, A_BOT) sets AREA to be the area of
+     ! an S^dim spherical collar specified by A_TOP, A_BOT, where
+     ! A_TOP is top (smaller) spherical radius,
+     ! A_BOT is bottom (larger) spherical radius.
+     !
+     ! The argument dim must be a positive integer.
+     ! The arguments A_TOP and A_BOT must be real numbers or arrays of real numbers,
+     ! with the same array size.
+     ! The result AREA will be an array of the same size as A_TOP.
+     !
+  */
+  return area_of_cap(dim, a_bot) - area_of_cap(dim, a_top);
+}
+
+
+PRIVATE double
+sradius_of_cap(int dim, double area)
+{
+  /*
+    !
+    ! S_CAP = SRADIUS_OF_CAP(dim, AREA) returns the spherical radius of
+    ! an S^dim spherical cap of area AREA.
+    !
+  */
+  double radius = 0;
+  if ( dim == 1 ) {
+    radius = area/2;
+  }
+  else if ( dim == 2 ) {
+    radius = 2*asin(sqrt(area/pi)/2);
+  }
+  else {
+    ERROR("sradius_of_cap: dim > 2 not supported");
+  }
+  return radius;
+}
+
+
+PRIVATE double
+area_of_sphere(int dim)
+{
+  /*
+    ! 
+    ! AREA = AREA_OF_SPHERE(dim) sets AREA to be the area of the sphere S^dim
+    !
+  */
+  double power = (double)(dim+1)/(double)2;
+  return 2*pow(pi,power)/my_gamma(power);
+}
+
+
+PRIVATE double
+area_of_ideal_region(int dim, int n)
+{
+  /*
+    !
+    ! AREA = AREA_OF_IDEAL_REGION(dim,N) sets AREA to be the area of one of N equal
+    ! area regions on S^dim, that is 1/N times AREA_OF_SPHERE(dim).
+    !
+    ! The argument dim must be a positive integer.
+    ! The argument N must be a positive integer or an array of positive integers.
+    ! The result AREA will be an array of the same size as N.
+    !
+  */
+  double area = area_of_sphere(dim)/n;
+  return area;
+}
+
+
+PRIVATE double
+polar_colat(int dim, int n)
+{
+  /*
+    !
+    ! Given dim and N, determine the colatitude of the North polar spherical cap.
+    !
+  */
+  double colat;
+  if ( n == 1 ) colat=pi;
+  else if ( n == 2 ) colat=half_pi;
+  else if ( n > 2 ) {
+    double area = area_of_ideal_region(dim,n);
+    colat=sradius_of_cap(dim,area);
+  }
+  return colat;
+}
+
+
+PRIVATE void
+cap_colats(int dim, int n, int n_collars, double c_polar,
+	   const int n_regions[/* n_collars+2 */], 
+	   double c_caps[/* n_collars+2 */])
+{
+  /*
+    !
+    !CAP_COLATS Colatitudes of spherical caps enclosing cumulative sum of regions
+    !
+    ! Given dim, N, c_polar and n_regions, determine c_caps,
+    ! an increasing list of colatitudes of spherical caps which enclose the same area
+    ! as that given by the cumulative sum of regions.
+    ! The number of elements is n_collars+2.
+    ! c_caps[1] is c_polar.
+    ! c_caps[n_collars+1] is Pi-c_polar.
+    ! c_caps[n_collars+2] is Pi.
+    !
+  */
+
+  int subtotal_n_regions, collar_n;
+  double ideal_region_area = area_of_ideal_region(dim,n);
+  c_caps[0] = c_polar;
+  subtotal_n_regions = 1;
+  for (collar_n = 1; collar_n <= n_collars; collar_n++) {
+    subtotal_n_regions += n_regions[collar_n];
+    c_caps[collar_n] = sradius_of_cap(dim,subtotal_n_regions*ideal_region_area);
+  }
+  c_caps[n_collars+1] = pi;
+}
+
+
+PRIVATE void
+round_to_naturals(int n, int n_collars,
+		  const double r_regions[/* n_collars+2 */],
+		  int n_regions[/* n_collars+2 */])
+{
+  /*
+    !
+    !ROUND_TO_NATURALS Round off a given list of numbers of regions
+    !
+    ! Given N and r_regions, determine n_regions,
+    ! a list of the natural number of regions in each collar and the polar caps.
+    ! This list is as close as possible to r_regions, using rounding.
+    ! The number of elements is n_collars+2.
+    ! n_regions[1] is 1.
+    ! n_regions[n_collars+2] is 1.
+    ! The sum of n_regions is N.
+    !
+  */
+  int j;
+  double discrepancy = 0;
+  for (j=0; j<n_collars+2; j++) {
+    n_regions[j] = NINT(r_regions[j]+discrepancy);
+    discrepancy += r_regions[j]-n_regions[j];
+  }
+}
+
+
+PRIVATE double
+ideal_collar_angle(int dim, int n)
+{
+  /*
+    !
+    !IDEAL_COLLAR_ANGLE The ideal angle for spherical collars of an EQ partition
+    !
+    !Syntax
+    ! angle = ideal_collar_angle(dim,N);
+    !
+    !Description
+    ! ANGLE = IDEAL_COLLAR_ANGLE(dim,N) sets ANGLE to the ideal angle for the
+    ! spherical collars of an EQ partition of the unit sphere S^dim into N regions.
+    !
+    ! The argument dim must be a positive integer.
+    ! The argument N must be a positive integer or an array of positive integers.
+    ! The result ANGLE will be an array of the same size as N.
+    !
+  */
+  return pow(area_of_ideal_region(dim,n),(1/(double)(dim)));
+}
+
+
+PRIVATE void
+ideal_region_list(int dim, int n, double c_polar,
+		  int n_collars, double r_regions[/* n_collars+2 */])
+{
+  /*
+    !
+    !IDEAL_REGION_LIST The ideal real number of regions in each zone
+    !
+    ! List the ideal real number of regions in each collar, plus the polar caps.
+    !
+    ! Given dim, N, c_polar and n_collars, determine r_regions,
+    ! a list of the ideal real number of regions in each collar,
+    ! plus the polar caps.
+    ! The number of elements is n_collars+2.
+    ! r_regions[1] is 1.
+    ! r_regions[n_collars+2] is 1.
+    ! The sum of r_regions is N.
+    !
+  */
+  r_regions[0] = 1;
+  if ( n_collars > 0 ) {
+    /*
+      !
+      ! Based on n_collars and c_polar, determine a_fitting,
+      ! the collar angle such that n_collars collars fit between the polar caps.
+      !
+    */
+    int collar_n;
+    double a_fitting = (pi-2*c_polar)/n_collars;
+    double ideal_region_area = area_of_ideal_region(dim,n);
+    for (collar_n=1; collar_n<=n_collars; collar_n++) {
+      double ideal_collar_area = area_of_collar(dim, c_polar+(collar_n-1)*a_fitting, 
+						c_polar+collar_n*a_fitting);
+      r_regions[collar_n] = ideal_collar_area / ideal_region_area;
+    }
+  } /* if ( n_collars > 0 ) */
+  r_regions[n_collars+1] = 1;
+}
+
+
+PRIVATE int
+num_collars(int n, double c_polar, double a_ideal)
+{
+  /*
+    !
+    !NUM_COLLARS The number of collars between the polar caps
+    !
+    ! Given N, an ideal angle, and c_polar,
+    ! determine n_collars, the number of collars between the polar caps.
+    !
+  */
+  int num_c;
+  /*
+    ! n_collars = zeros(size(N));
+    ! enough = (N > 2) & (a_ideal > 0);
+    ! n_collars(enough) = max(1,round((pi-2*c_polar(enough))./a_ideal(enough)));
+  */
+  Bool enough = ((n > 2) && (a_ideal > 0)) ? true : false;
+  if ( enough ) {
+    num_c = NINT((pi-2*c_polar)/a_ideal);
+    if (num_c < 1) num_c = 1;
+  }
+  else {
+    num_c = 0;
+  }
+  return num_c;
+}
+
+
+PRIVATE void
+eq_caps(int dim, int n, 
+	double s_cap[/* n */],
+	int n_regions[/* n */],
+	int *N_collars)
+{
+  int j;
+  double c_polar;
+  int n_collars = *N_collars;
+
+  if ( n == 1 ) {
+    /*
+      !
+      ! We have only one region, which must be the whole sphere.
+      !
+    */
+    s_cap[0]=pi;
+    n_regions[0]=1;
+    *N_collars=0;
+    return;
+  }
+
+  if ( dim == 1 ) {
+    /*
+      !
+      ! We have a circle. Return the angles of N equal sectors.
+      !
+      !sector = 1:N;
+      !
+      ! Make dim==1 consistent with dim>1 by
+      ! returning the longitude of a sector enclosing the
+      ! cumulative sum of arc lengths given by summing n_regions.
+      !
+      !s_cap = sector*two_pi/N;
+      !n_regions = ones(size(sector));
+    */
+    for (j=0; j<n; j++) {
+      s_cap[j]=(j+1)*two_pi/(double)n;
+      n_regions[j]=1;
+    }
+    *N_collars=0;
+    return;
+  }
+
+  if ( dim == 2 ) {
+    /*
+      !
+      ! Given dim and N, determine c_polar
+      ! the colatitude of the North polar spherical cap.
+      !
+    */
+
+    c_polar = polar_colat(dim,n);
+
+    /*
+      !
+      ! Given dim and N, determine the ideal angle for spherical collars.
+      ! Based on N, this ideal angle, and c_polar,
+      ! determine n_collars, the number of collars between the polar caps.
+      !
+    */
+
+    n_collars = *N_collars = num_collars(n,c_polar,ideal_collar_angle(dim,n));
+
+    /*
+      !
+      ! Given dim, N, c_polar and n_collars, determine r_regions,
+      ! a list of the ideal real number of regions in each collar,
+      ! plus the polar caps.
+      ! The number of elements is n_collars+2.
+      ! r_regions[1] is 1.
+      ! r_regions[n_collars+2] is 1.
+      ! The sum of r_regions is N.
+      !
+      ! r_regions = ideal_region_list(dim,N,c_polar,n_collars)
+    */
+
+    {
+      double *r_regions = NULL;
+      CALLOC(r_regions,n_collars+2);
+      ideal_region_list(dim,n,c_polar,n_collars,r_regions);
+      
+      /*
+	!
+	! Given N and r_regions, determine n_regions,
+	! a list of the natural number of regions in each collar and
+	! the polar caps.
+	! This list is as close as possible to r_regions.
+	! The number of elements is n_collars+2.
+	! n_regions[1] is 1.
+	! n_regions[n_collars+2] is 1.
+	! The sum of n_regions is N.
+	!
+	! n_regions = round_to_naturals(N,r_regions)
+      */
+      
+      round_to_naturals(n,n_collars,r_regions,n_regions);
+      FREE(r_regions);
+    }
+    
+    /*
+      !
+      ! Given dim, N, c_polar and n_regions, determine s_cap,
+      ! an increasing list of colatitudes of spherical caps which enclose the same area
+      ! as that given by the cumulative sum of regions.
+      ! The number of elements is n_collars+2.
+      ! s_cap[1] is c_polar.
+      ! s_cap[n_collars+1] is Pi-c_polar.
+      ! s_cap[n_collars+2] is Pi
+      ! 
+      ! s_cap = cap_colats(dim,N,c_polar,n_regions)
+    */
+
+    cap_colats(dim,n,n_collars,c_polar,n_regions,s_cap);
+  }
+}
+
+
+#define regions(i,j,k)   regs  [ ((k)-1)*dim*2     + ((j)-1)*dim     + (i) - 1 ]
+#define regions_1(i,j,k) regs_1[ ((k)-1)*(dim-1)*2 + ((j)-1)*(dim-1) + (i) - 1 ]
+
+PRIVATE void
+eq_regions(int recur, int dim, int n, double regs[])
+{
+  /*
+    !
+    ! REGIONS = EQ_REGIONS(dim,N) uses the recursive zonal equal area sphere
+    ! partitioning algorithm to partition S^dim (the unit sphere in dim+1
+    ! dimensional space) into N regions of equal area and small diameter.
+    !
+    ! The arguments dim and N must be positive integers.
+    !
+    ! The result REGIONS is a (dim by 2 by N) array, representing the regions
+    ! of S^dim. Each element represents a pair of vertex points in spherical polar
+    ! coordinates.
+    ! 
+    ! Each region is defined as a product of intervals in spherical polar
+    ! coordinates. The pair of vertex points regions(:,1,n) and regions(:,2,n) give
+    ! the lower and upper limits of each interval.
+    !
+  */
+
+  double *regs_1 = NULL;
+  double *s_cap = NULL, r_top[2], r_bot[2], c_top, c_bot, offset;
+  int *n_regions = NULL, collar_n, n_collars, n_in_collar, region_1_n, region_n;
+  int i, j, k;
+  DRHOOK_START_RECUR(eq_regions,recur);
+
+  CALLOC(s_cap, n+2);
+  CALLOC(n_regions, n+2);
+
+  if ( n == 1 ) {
+    /*
+      !
+      ! We have only one region, which must be the whole sphere.
+      !
+      ! regions(:,:,1)=sphere_region(dim)
+    */
+    sphere_region(dim,&regions(1,1,1));
+    goto finish;
+  }
+
+  /*
+    !
+    ! Start the partition of the sphere into N regions by partitioning
+    ! to caps defined in the current dimension.
+    !
+    ! [s_cap, n_regions] = eq_caps(dim,N)
+  */
+
+  eq_caps(dim,n,s_cap,n_regions,&n_collars);
+
+  /*
+    !
+    ! s_cap is an increasing list of colatitudes of the caps.
+    !
+  */
+
+  if ( dim == 1 ) {
+    /*
+      !
+      ! We have a circle and s_cap is an increasing list of angles of sectors.
+      !
+      !
+      ! Return a list of pairs of sector angles.
+      !
+    */
+
+    for (k=1; k<=n; k++)
+      for (j=1; j<=2; j++)
+	for (i=1; i<=dim; i++)
+	  regions(i,j,k) = 0;
+
+    for (k=2; k<=n; k++) {
+      regions(1,1,k) = s_cap[k-2];
+    }
+
+    for (k=1; k<=n; k++) {
+      regions(1,2,k) = s_cap[k-1];
+    }
+  }
+  else {
+    /*
+      !
+      ! We have a number of zones: two polar caps and a number of collars.
+      ! n_regions is the list of the number of regions in each zone.
+      !
+      ! n_collars = size(n_regions,2)-2
+      !
+      ! Start with the top cap
+      !
+      ! regions(:,:,1) = top_cap_region(dim,s_cap(1))
+    */
+    
+    top_cap_region(dim,s_cap[0],&regions(1,1,1));
+    region_n = 1;
+
+    /*
+      !
+      ! Determine the dim-regions for each collar
+      !
+    */
+
+    if ( dim == 2 ) offset=0;
+
+    for (collar_n=1; collar_n<=n_collars; collar_n++) {
+      int size_regions_1_3;
+      /*
+	!
+	! c_top is the colatitude of the top of the current collar.
+	!
+      */
+
+      c_top = s_cap[collar_n-1];
+
+      /*
+	!
+	! c_bot is the colatitude of the bottom of the current collar.
+	!
+      */
+
+      c_bot = s_cap[collar_n];
+
+      /*
+	!
+	! n_in_collar is the number of regions in the current collar.
+	!
+      */
+
+      n_in_collar = n_regions[collar_n];
+
+      /*
+	!
+	! The top and bottom of the collar are small (dim-1)-spheres,
+	! which must be partitioned into n_in_collar regions.
+	! Use eq_regions recursively to partition the unit (dim-1)-sphere.
+	! regions_1 is the resulting list of (dim-1)-region pairs.
+	!
+	! regions_1 = eq_regions(dim-1,n_in_collar)
+      */
+
+      size_regions_1_3 = n_in_collar;
+      ALLOC(regs_1,(dim-1)*2*n_in_collar);
+      eq_regions(1, dim-1,n_in_collar,regs_1);
+
+      /*
+	!
+	! Given regions_1, determine the dim-regions for the collar.
+	! Each element of regions_1 is a (dim-1)-region pair for the (dim-1)-sphere.
+      */
+
+      if ( dim == 2 ) {
+	/*
+	  !
+	  !  The (dim-1)-sphere is a circle
+	  !  Offset each sector angle by an amount which accumulates over
+	  !  each collar.
+	*/
+
+	for (region_1_n=1; region_1_n<=n_in_collar; region_1_n++) {
+	  /*
+	    !
+	    ! Top of 2-region
+	    ! The first angle is the longitude of the top of
+	    ! the current sector of regions_1, and
+	    ! the second angle is the top colatitude of the collar
+	    !
+	    ! r_top = [mod(regions_1(1,1,region_1_n)+two_pi*offset,two_pi); c_top]
+	  */
+
+	  r_top[0]=fmod(regions_1(1,1,region_1_n)+two_pi*offset,two_pi);
+	  r_top[1]=c_top;
+
+	  /*
+	    !
+	    ! Bottom of 2-region
+	    ! The first angle is the longitude of the bottom of
+	    ! the current sector of regions_1, and
+	    ! the second angle is the bottom colatitude of the collar
+	    !
+	    ! r_bot = [mod(regions_1(1,2,region_1_n)+two_pi*offset,two_pi); c_bot]
+	  */
+
+	  r_bot[0]=fmod(regions_1(1,2,region_1_n)+two_pi*offset,two_pi);
+	  r_bot[1]=c_bot;
+	  if ( r_bot[0] <= r_top[0] ) {
+	    r_bot[0] += two_pi;
+	  }
+	  region_n++;
+	  /* regions(:,:,region_n) = [r_top,r_bot] */
+	  regions(1,1,region_n) = r_top[0];
+	  regions(1,2,region_n) = r_bot[0];
+	  regions(2,1,region_n) = r_top[1];
+	  regions(2,2,region_n) = r_bot[1];
+	}
+
+	/*
+	  !
+	  ! Given the number of sectors in the current collar and
+	  ! in the next collar, calculate the next offset.
+	  ! Accumulate the offset, and force it to be a number between 0 and 1.
+	  ! 
+	*/
+
+	offset += circle_offset(n_in_collar,n_regions[1+collar_n]);
+	offset -= floor(offset);
+      }
+      else {
+	for (region_1_n=1; region_1_n <= size_regions_1_3; region_1_n++) {
+	  region_n++;
+
+	  /*
+	    !
+	    ! Dim-region;
+	    ! The first angles are those of the current (dim-1) region of regions_1.
+	    !
+	  */
+
+	    for (j=1; j<=2; j++)
+	      for (i=1; i<=dim-1; i++)
+		regions(i,j,region_n) = regions_1(i,j,region_1_n);
+
+	  /*
+	    !
+	    ! The last angles are the top and bottom colatitudes of the collar.
+	    !
+	    ! regions(dim,:,region_n) = [c_top,c_bot]
+	  */
+
+	  regions(dim,1,region_n) = c_top;
+	  regions(dim,2,region_n) = c_bot;
+	}
+      }
+      FREE(regs_1);
+    } /* for (collar_n=1; collar_n<=n_collars; collar_n++) */
+
+    /*
+      !
+      ! End with the bottom cap.
+      !
+      ! regions(:,:,N) = bot_cap_region(dim,s_cap(1))
+    */
+
+    bot_cap_region(dim,s_cap[0],&regions(1,1,n));
+  }
+
+  FREE(s_cap);
+  FREE(n_regions);
+ finish:
+  DRHOOK_END_RECUR(n,recur);
+}
+
+
+static const int dim = 2;
+
+/* Cached regs, per each resolution encountered, per thread-id */
+
+#define eq_cache_t regcache_t
+
+static eq_cache_t **eq_cache = NULL;
+
+PUBLIC eq_cache_t **
+ODBc_init_eq_cache()
+{
+  if (!eq_cache) {
+    DEF_INUMT;
+    CALLOC(eq_cache, inumt);
+  }
+  return eq_cache;
+}
+
+
+PUBLIC regcache_t *
+ODBc_put_regcache(regcache_kind kind,
+		  int n, int nb,
+		  double *latband, double *midlat,
+		  double *stlon, double *deltalon, 
+		  int *loncnt,
+		  regcache_t **(*init_code)(void), regcache_t **regcache)
+{
+  DEF_IT;
+  regcache_t *p;
+  DRHOOK_START(ODBc_put_regcache);
+  {
+    FILE *fp = ODBc_get_debug_fp();
+    if (fp) {
+      int jb;
+      for (jb=0; jb<nb; jb++) {
+	fprintf(fp, "[%d] latband=[%.14g .. %.14g%s, midlat=%.14g, "
+		"stlon=%.14g, deltalon=%.14g, loncnt=%d\n",
+		jb, latband[jb], latband[jb+1],
+		(jb < nb-1) ? ")" : "]", midlat[jb],
+		stlon[jb], deltalon[jb], loncnt[jb]);
+      }
+    }
+  }
+  CALLOC(p,1);
+  p->kind = kind;
+  p->n = n;
+  p->nb = nb;
+  p->latband = latband;
+  p->midlat = midlat;
+  p->stlon = stlon;
+  p->deltalon = deltalon;
+  p->loncnt = loncnt;
+  {
+    int jb, sum = 0;
+    CALLOC(p->sum_loncnt, nb);
+    for (jb=0; jb<nb; jb++) {
+      p->sum_loncnt[jb] = sum;
+      sum += loncnt[jb];
+    }
+    p->nboxes = sum;
+  }
+  p->last.jb = -1;
+  p->last.lonbox = -1;
+  p->last.boxid = -1;
+  {
+    FILE *fp = ODBc_get_debug_fp();
+    if (fp) {
+      int jb;
+      fprintf(fp,
+	      "ODBc_put_regcache(kind=%d ('%s'), n=%d, nb=%d, p->nboxes=%d, latband=%p, "
+	      "midlat=%p, stlon=%p, deltalon=%p, loncnt=%p)\n",
+	      (int)kind, regcache_names[(int)kind], n, nb, p->nboxes, latband, 
+	      midlat, stlon, deltalon, loncnt);
+
+      for (jb=0; jb<nb; jb++) {
+	fprintf(fp,"Band#%d = [ %.4f .. %.4f ] with midlat=%.4f, loncnt = %d, sum_loncnt = %d, "
+		"lon-starts at %.4f with delta = %.4f\n",
+		jb+1,latband[jb],latband[jb+1],midlat[jb],
+		loncnt[jb],p->sum_loncnt[jb],
+		stlon[jb],deltalon[jb]);
+      }
+    }
+  }
+  if (!regcache) regcache = init_code(); /* Normally not called */
+  if (regcache[IT]) {
+    regcache_t *top = regcache[IT];
+    while (top) {
+      regcache_t *next = NULL;
+      if (n < top->n) {
+	if (!top->left) { top->left = p; } else { next = top->left; }
+      }
+      else {
+	if (!top->right) { top->right = p; } else { next = top->right; }
+      }
+      top = next; /* If next == NULL => new position in tree found => get out */
+    } /* while (top) */
+  }
+  else {
+    regcache[IT] = p;
+  }
+  DRHOOK_END(n);
+  return p;
+}
+
+
+PUBLIC eq_cache_t *
+ODBc_get_eq_cache(int n)
+{
+  DEF_IT;
+  eq_cache_t *p = NULL;
+  DRHOOK_START(ODBc_get_eq_cache);
+  {
+    if (!eq_cache) eq_cache = ODBc_init_eq_cache(); /* Normally not called */
+    p = eq_cache[IT];
+
+    while (p) {
+      if (n == p->n || p->kind == eq_cache_kind) {
+	/* Matched */
+	break;
+      }
+      p = (n < p->n) ? p->left : p->right;
+    } /* while (p) */
+
+    if (!p) {
+
+      /* This is done only once per "n", per "it" */
+
+      double *regs = NULL;
+      int jb, nb = 0;
+      double *latband = NULL;
+      double *midlat = NULL;
+      int *loncnt = NULL;
+      double *stlon = NULL;
+      double *deltalon = NULL;
+
+      CALLOC(regs,dim*2*n);
+      eq_regions(0, dim,n,&regions(1,1,1));
+
+      {
+	/* 
+	   After eq_regions() function call, latitudes & longitudes are in radians
+	   and between [ 0 .. pi ] and [ 0 .. two_pi ], respectively.
+
+	   Pay special attention to cap regions (j=1 & j=n), where starting and
+	   ending longitude has the same constant value; make them -180 and +180, respectively .
+	*/
+
+	int j;
+	for (j=1; j<=n; j++) {
+	  /* In radians */
+	  double startlon = regions(1,1,j);
+	  double startlat = regions(2,1,j);
+	  double endlon   = regions(1,2,j);
+	  double endlat   = regions(2,2,j);
+
+	  /* shift latitudes to start from -half_pi, not 0 */
+	  startlat -= half_pi;
+	  endlat -= half_pi;
+
+	  if (j == 1 || j == n) { /* cap regions */
+	    endlon = startlon;
+	  }
+
+	  /* Replace values in regions, still in radians */
+	  regions(1,1,j) = startlon;
+	  regions(2,1,j) = startlat;
+	  regions(1,2,j) = endlon;
+	  regions(2,2,j) = endlat;
+	}
+      }
+
+      {
+	/*
+	  Derive how many (nb) latitude bands we have i.e. keep track how often 
+	  the consecutive (startlat,endlat)-pairs change their value.
+	*/
+	
+	int j = 1;
+	int ncnt;
+	double three_sixty = 360;
+	double last_startlat = regions(2,1,j);
+	double last_endlat   = regions(2,2,j);
+
+	nb = 1; /* Southern polar cap */
+	for (j=2; j<n; j++) { /* All but caps */
+	  double startlat = regions(2,1,j);
+	  double endlat   = regions(2,2,j);
+	  if (last_startlat == startlat && last_endlat == endlat) {
+	    /* No change i.e. we are still in the same latitude band */
+	    continue;
+	  }
+	  else {
+	    /* New latitude band */
+	    ++nb;
+	    last_startlat = startlat;
+	    last_endlat   = endlat;
+	  }
+	} /* for (j=2; j<n; j++) */
+	if (n > 1) { /* Northern polar cap */
+	  ++nb;
+	}
+
+	/* 
+	   We have now in total "nb" latitude bands.
+	   Lets store their starting and ending latitudes for much faster lookup.
+	*/
+
+	ALLOC(latband, nb + 1);
+	CALLOC(loncnt, nb);
+	CALLOC(stlon, nb);
+	CALLOC(deltalon, nb);
+
+	jb = -1;
+
+	j = 1;
+	last_startlat = regions(2,1,j);
+	last_endlat   = regions(2,2,j);
+	loncnt[++jb] = 1;
+	latband[jb] = -R2D(last_startlat); /* Reverse latitudes from S->N to N->S pole */
+
+	for (j=2; j<n; j++) { /* All but caps */
+	  double startlat = regions(2,1,j);
+	  double endlat   = regions(2,2,j);
+	  if (last_startlat == startlat && last_endlat == endlat) {
+	    /* Increase longitude count by one for this latitude band */
+	    loncnt[jb]++;
+	  }
+	  else {
+	    /* For previous latitude band ... */
+	    ncnt = loncnt[jb];
+	    deltalon[jb] = three_sixty/ncnt;
+	    stlon[jb] = -deltalon[jb]/2; /* Starting longitude at 0 GMT minus half longitudinal delta */
+	    /* New latitude band */
+	    last_startlat = startlat;
+	    last_endlat   = endlat;
+	    loncnt[++jb] = 1;
+	    latband[jb] = -R2D(last_startlat); /* Reverse latitudes from S->N to N->S pole */
+	  }
+	} /* for (j=2; j<n; j++) */
+
+	if (n > 1) { /* Northern polar cap (mapped to be the South pole, in fact) */
+	  ncnt = loncnt[jb];
+	  deltalon[jb] = three_sixty/ncnt;
+	  stlon[jb] = -deltalon[jb]/2; /* Starting longitude at 0 GMT minus half longitudinal delta */
+	  j = n;
+	  last_startlat = regions(2,1,j);
+	  last_endlat   = regions(2,2,j);
+	  loncnt[++jb] = 1;
+	  latband[jb] = -R2D(last_startlat); /* Reverse latitudes from S->N to N->S pole */
+	}
+
+	{
+	  ncnt = loncnt[jb];
+	  deltalon[jb] = three_sixty/ncnt;
+	  stlon[jb] = -deltalon[jb]/2; /* Starting longitude at 0 GMT minus half longitudinal delta */
+	  j = n+1;
+	  latband[++jb] = -R2D(last_endlat); /* Reverse latitudes from S->N to N->S pole */
+	}
+      }
+
+      /* Release space allocated by regs */
+
+      FREE(regs);
+
+      /* Calculate mid latitudes for each band by a simple averaging process */
+
+      ALLOC(midlat, nb);
+      for (jb=0; jb<nb; jb++) {
+	midlat[jb] = (latband[jb] + latband[jb+1])/2;
+      }
+
+      /* Store in cache */
+      p = ODBc_put_regcache(eq_cache_kind,
+			    n, nb, 
+			    latband, midlat,
+			    stlon, deltalon, 
+			    loncnt,
+			    ODBc_init_eq_cache, eq_cache);
+
+      p->resol = ODB_eq_resol(n);
+    }
+  }
+  DRHOOK_END(n);
+  return p;
+}
+
+
+PUBLIC int
+ODBc_bsearch(const double key,
+	     const int n, 
+	     const double x[ /* with n elements */ ],
+	     const double sign /* +1 forward and -1 for reverse search */)
+{
+  int lo = 0;
+  int hi = n-1;
+  while (lo <= hi) {
+    int k = (lo+hi)/2;
+    double xk = sign*x[k];
+    if (key == xk) {
+      /* A match has been found */
+      return k;
+    }
+    else if (key < xk) {
+      /* Search the lower section */
+      hi = k-1;
+    }
+    else {
+      /* Search the upper section */
+      lo = k+1;
+    }
+  } /* while (lo <= hi) */
+  /* No EXACT match */
+  return -1;
+}
+
+
+PUBLIC int
+ODBc_interval_bsearch(const double key, 
+		      const int n, 
+		      const double x[ /* with n+1 elements */ ],
+		      const double *delta, /* if present, only x[0] will be used */
+		      const double add,
+		      const double sign /* +1 forward and -1 for reverse search */)
+{
+  const double eps = 1.0e-7;
+  double Delta = delta ? *delta : 0;
+  Bool wrap_around = (delta && add != 0) ? true : false;  
+  double halfDelta = Delta/2;
+  double x0 = x[0] + halfDelta;
+  double Key = wrap_around ? sign*fmod(key + halfDelta + add, add) : sign*(key + halfDelta);
+  int lo = 0, hi = n-1;
+  while (lo <= hi) {
+    int k = (lo+hi)/2;
+    double xk = wrap_around ? sign*fmod(x0 + k*Delta + add, add) : sign*(x[k] + halfDelta);
+    if (wrap_around && k > 0 && ABS(xk) < eps) xk = add;
+    if (Key < xk) {
+      /* Search the lower section */
+      hi = k-1;
+    }
+    else {
+      int kp1 = k+1;
+      double xkp1 = wrap_around ? sign*fmod(x0 + kp1*Delta + add, add) : sign*(x[kp1] + halfDelta);
+      if (wrap_around && ABS(xkp1) < eps) xkp1 = add;
+      if (Key > xkp1) {
+	/* Search the upper section */
+	lo = kp1;
+      }
+      else {
+	/* The interval has been found */
+	return k;
+      }
+    }
+  } /* while (lo <= hi) */
+#if 0
+  if (wrap_around) {
+    /* Check if between [-halfDelta,0] */
+    FILE *fp = ODBc_get_debug_fp();
+    Key = fmod(key + add, add);
+    ODB_fprintf(fp, "key = %.14g, add = %.14g --> Key = %.14g\n",key,add,Key);
+    halfDelta = -Delta/2;
+    ODB_fprintf(fp, "halfDelta = %.14g --> ",halfDelta);
+    halfDelta = fmod(halfDelta + add, add);
+    ODB_fprintf(fp, "halfDelta = %.14g\n",halfDelta);
+    if (Key >= halfDelta && Key <= add) return 0; /* First box */
+    ODB_fprintf(fp, "\t%.14g not between %.14g and %.14g\n",Key,halfDelta,add);
+    halfDelta = Delta/2;
+    if (Key >= 0 && Key <= halfDelta) return 0; /* First box */
+    ODB_fprintf(fp, "\t%.14g not between %.14g and %.14g\n",Key,(double)0,halfDelta);
+  }
+#endif
+  /* No INTERVAL match */
+  return -1;
+}
+
+
+PRIVATE int
+find_latband(regcache_t *p, const double lat)
+{
+  int jb, lastjb = p->last.jb;
+  if (lastjb >= 0 &&
+      /* Note: In the following we go from N->S pole, not S->N ==> thus the minus sign!! */
+      -lat >= -p->latband[lastjb] && -lat < -p->latband[lastjb+1]) {
+    jb = lastjb;
+  }
+  else if (lastjb == p->nb - 1 && lat == p->latband[lastjb+1]) {
+    /* Exactly at the South pole */
+    jb = lastjb;
+  }
+  else {
+    jb = ODBc_interval_bsearch(lat, p->nb, p->latband, NULL, 0, -1);
+    if (jb != -1) {
+      /* New latitude band found */
+      p->last.jb = jb;
+      /* Don't know anything about the final box numbers yet */
+      p->last.lonbox = -1;
+      p->last.boxid = -1;
+    }
+    {
+      FILE *fp = ODBc_get_debug_fp();
+      if (fp) {
+	fprintf(fp,"find_latband: jb = %d",jb);
+	fprintf(fp,", p->nb = %d, lat = %.4f", p->nb, lat);
+	if (jb != -1) {
+	  fprintf(fp,", p->midlat[jb] = %.4f", p->midlat[jb]);
+	  if (jb > 0) fprintf(fp,", p->latband[jb-1] = %.4f",p->latband[jb-1]);
+	  fprintf(fp,", p->latband[jb] = %.4f",p->latband[jb]);
+	  if (jb < p->nb-1) fprintf(fp,", p->latband[jb+1] = %.4f",p->latband[jb+1]);
+	}
+	fprintf(fp,"\n");
+      }
+    }
+  }
+  return jb;
+}
+
+
+PRIVATE int
+find_lonbox(regcache_t *p, const int jb, const double lon, 
+	    double *midlon,
+	    double *leftlon, double *rightlon)
+{
+  const double three_sixty = 360;
+  double mid   = RMDI;
+  double left  = RMDI;
+  double right = RMDI;
+  int boxid = -1;
+  if (jb >= 0 && jb < p->nb) {
+    double Lon = fmod(lon + three_sixty, three_sixty);
+    double deltalon = p->deltalon[jb];
+
+    if (p->last.boxid >= 0) {
+      int k = p->last.lonbox;
+      double startlon = p->stlon[jb] + k * deltalon;
+      double endlon = p->stlon[jb] + (k+1) * deltalon;
+      startlon = fmod(startlon + three_sixty, three_sixty);
+      endlon = fmod(endlon + three_sixty, three_sixty);
+      if (endlon >= startlon) {
+	if (Lon >= startlon && Lon < endlon) boxid = p->last.boxid;
+      }
+      else {
+	if ((Lon >= 0 && Lon < endlon) || (Lon >= startlon && Lon < three_sixty)) boxid = p->last.boxid;
+      }
+    }
+
+    if (boxid == -1) {
+      const double *stlon = &p->stlon[jb];
+      int loncnt = p->loncnt[jb];
+      int lonbox = ODBc_interval_bsearch(lon, loncnt, stlon, &deltalon, three_sixty, +1);
+      if (lonbox != -1) {
+	int k = lonbox;
+	left = (*stlon) + k * deltalon;
+	mid = (*stlon) + (k+0.5) * deltalon;
+	right = (*stlon) + (k+1) * deltalon;
+
+	p->last.left  = left  = fmod(left + three_sixty, three_sixty);
+	p->last.mid   = mid   = fmod(mid + three_sixty, three_sixty);
+	p->last.right = right = fmod(right + three_sixty, three_sixty);
+	
+	p->last.jb = jb;
+	p->last.lonbox = k;
+	p->last.boxid = boxid = p->sum_loncnt[jb] + k;
+      }
+      {
+	FILE *fp = ODBc_get_debug_fp();
+	if (fp) {
+	  fprintf(fp,"find_lonbox: boxid = %d, jb = %d",boxid, jb);
+	  fprintf(fp,", loncnt = %d, lon/Lon = %.4f/%.4f", loncnt, lon, Lon);
+	  fprintf(fp,", *stlon = %.4f, deltalon = %.4f, lonbox = %d, left/mid/right = %.14g/%.14g/%.14g\n", 
+		  *stlon, deltalon, lonbox, 
+		  left, mid, right); 
+	}
+      }
+    }
+    else {
+      left  = p->last.left;
+      mid   = p->last.mid;
+      right = p->last.right;
+    }
+  }
+  if (midlon) {
+    const double one_eighty = 180;
+    if (mid > one_eighty) mid -= three_sixty;
+    *midlon = mid;
+  }
+  if (leftlon) *leftlon = left;
+  if (rightlon) *rightlon = right;
+  return boxid;
+}
+
+
+/* Please note that in the subsequent routines (lat,lon,resol)
+   are all assumed to be in degrees, not radians */
+
+const double sphere_area = four_pi; /* Actually: 4 * pi * R^2 */
+const double min_resol = 0.1e0; /* => Smallest patch ~ 0.1-by-0.1 degree^2 */
+
+PUBLIC double ODB_eq_min_resol() { return min_resol; }
+
+PUBLIC double
+ODB_eq_area(double rn)
+{
+  int n = rn;
+  double eq_area = (sphere_area/n);
+  return eq_area;
+}
+
+
+PUBLIC double
+ODB_eq_area_with_resol(double resol)
+{
+  return Func_eq_area(resol); /* from odb.h */
+}
+
+
+PUBLIC double
+ODB_eq_resol(double rn)
+{
+  double eq_area = ODB_eq_area(rn);
+  double resol = sqrt(eq_area) * recip_pi_over_180; /* In degrees ~ at Equator for small resol's */
+  if (resol < min_resol) resol = min_resol;
+  return resol;
+}
+
+
+PUBLIC double
+ODB_eq_n(double resol)
+{
+  double dres = ( resol <  min_resol ? min_resol : resol ) * pi_over_180;
+  double eq_area = dres * dres ; /* Actually: (resol*pi/180)^2 * R^2 (approx.) */
+  int n = NINT(sphere_area/eq_area); /* Note: R^2's would have been divided away */
+  return n;
+}
+
+
+PUBLIC double ODB_eq_max_n() { return ODB_eq_n(min_resol); }
+
+
+PUBLIC int
+ODBc_get_boxid(double lat, double lon, int n, 
+	      regcache_t *ptr, regcache_t *(*get_cache)(int))
+{
+  int boxid = -1; 
+  DRHOOK_START(ODBc_get_boxid);
+  {
+    regcache_t *p = ptr ? ptr : get_cache(n);
+    int jb = find_latband(p, lat);
+    boxid = find_lonbox(p, jb, lon, NULL, NULL, NULL);
+  }
+  DRHOOK_END(0);
+  return boxid;
+}
+
+
+PUBLIC double
+ODB_eq_boxid(double lat, double lon, double rn)
+{
+  return ODBc_get_boxid(lat, lon, rn, NULL, ODBc_get_eq_cache);
+}
+
+
+PUBLIC double
+ODB_eq_boxid_with_resol(double lat, double lon, double resol)
+{
+  return Func_eq_boxid(lat, lon, resol); /* from odb.h */
+}
+
+
+PUBLIC double
+ODBc_get_boxlat(double lat, double lon, double rn,
+		regcache_t *(*get_cache)(int))
+{
+  double res = RMDI;
+  DRHOOK_START(ODBc_get_boxlat);
+  {
+    int n = rn;
+    regcache_t *p = get_cache(n);
+    int jb = find_latband(p, lat);
+    if (jb >= 0 && jb < p->nb) {
+      res = p->midlat[jb];
+    }
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC double
+ODB_eq_boxlat(double lat, double lon, double rn)
+{
+  return ODBc_get_boxlat(lat, lon, rn, ODBc_get_eq_cache);
+}
+
+
+PUBLIC double
+ODB_eq_boxlat_with_resol(double lat, double lon, double resol)
+{
+  return Func_eq_boxlat(lat, lon, resol); /* from odb.h */
+}
+
+
+PUBLIC double
+ODBc_get_boxlon(double lat, double lon, double rn,
+		regcache_t *(*get_cache)(int))
+{
+  double res = RMDI;
+  DRHOOK_START(ODBc_get_boxlon);
+  {
+    int n = rn;
+    regcache_t *p = get_cache(n);
+    int jb = find_latband(p, lat);
+    int boxid = find_lonbox(p, jb, lon, &res, NULL, NULL);
+  }
+  DRHOOK_END(0);
+  return res;
+}
+
+
+PUBLIC double
+ODB_eq_boxlon(double lat, double lon, double rn)
+{
+  return ODBc_get_boxlon(lat, lon, rn, ODBc_get_eq_cache);
+}
+
+
+PUBLIC double
+ODB_eq_boxlon_with_resol(double lat, double lon, double resol)
+{
+  return Func_eq_boxlon(lat, lon, resol); /* from odb.h */
+}
+
+
+PUBLIC double
+ODB_eq_truearea(double lat, double lon, double rn)
+{
+  double truearea = RMDI;
+  int n = rn;
+  double startlon;
+  double   endlon;
+  eq_cache_t *p = ODBc_get_eq_cache(n);
+  int jb = find_latband(p, lat);
+  int boxid = find_lonbox(p, jb, lon, NULL, &startlon, &endlon);
+  if (jb >= 0 && jb < p->nb &&
+      boxid >= 0 && boxid < n) {
+    double startlat = p->latband[jb];    /* Starting latitude, range = [ -90 .. 90 ] */
+    double   endlat = p->latband[jb+1];  /* Ending latitude  , range = [ -90 .. 90 ] */
+    const double three_sixty = 360;
+    if (endlon < startlon) endlon += three_sixty;
+    truearea = 
+      (sin(pi_over_180 * endlat) - sin(pi_over_180 * startlat)) *
+      (endlon - startlon) * pi_over_180; /* Note: R^2 left away */
+  }
+  return truearea;
+}
+
+
+PUBLIC double
+ODB_eq_truearea_with_resol(double lat, double lon, double resol)
+{
+  return Func_eq_truearea(lat, lon, resol); /* from odb.h */
+}
+
+
+PUBLIC double
+ODB_eq_latband(double bandnum, double rn)
+{
+  double res = RMDI;
+  int band_no = bandnum;
+  int n = rn;
+  eq_cache_t *p = ODBc_get_eq_cache(n);
+  if (band_no >= 1 && band_no <= p->nb + 1) {
+    res = p->latband[--band_no];
+  } 
+  return res;
+}
+
+
+PUBLIC double
+ODB_eq_latband_with_resol(double bandnum, double resol)
+{
+  return Func_eq_latband(bandnum, resol);  /* from odb.h */
+}
+
+
+/* The following may become obsolete (moved from orlist.c) */
+
+
+PRIVATE
+int boxid(double x, double deltax, double xmin, double xmax,
+	  Bool wrap_around)
+{
+  int id = NMDI;
+  if (deltax < 0) deltax = -deltax;
+  if (deltax != 0 && xmin < xmax) {
+    double xspan = xmax - xmin;
+    int n = (int)(xspan/deltax);
+    id = (int)((x - xmin)/deltax);
+    if (id < 0 || id >= n) {
+      if (wrap_around) {
+	if (id < 0) id = n-1;
+	else if (id >= n) id = 0;
+      }
+      else {
+	if (id < 0) id = 0;
+	else if (id >= n) id = n-1;
+      }
+    }
+  }
+  return id;
+}
+
+PRIVATE
+double box(double x, double deltax, double xmin, double xmax,
+	   Bool wrap_around)
+{
+  double value = RMDI;
+  if (deltax < 0) deltax = -deltax;
+  if (deltax != 0 && xmin < xmax) {
+    int id = boxid(x,deltax,xmin,xmax,wrap_around);
+    value = xmin + id * deltax + 0.5 * deltax;
+  }
+  return value;
+}
+
+PUBLIC
+double ODB_boxid_lat(double lat, double deltalat)
+{
+  const double latmax = 90;
+  return boxid(lat,deltalat,-latmax,+latmax,false);
+}
+
+PUBLIC
+double ODB_boxlat(double lat, double deltalat)
+{
+  const double latmax = 90;
+  return box(lat,deltalat,-latmax,+latmax,false);
+}
+
+PUBLIC
+double ODB_boxid_lon(double lon, double deltalon)
+{
+  const double lonmax = 180;
+  return boxid(lon,deltalon,-lonmax,+lonmax,true);
+}
+
+PUBLIC
+double ODB_boxlon(double lon, double deltalon)
+{
+  const double lonmax = 180;
+  return box(lon,deltalon,-lonmax,+lonmax,true);
+}
+
+PUBLIC 
+double ODB_boxid(double lat, double lon, double deltalat, double deltalon)
+{
+  const double latmax = 90;
+  int nlat = ODB_boxid_lat(latmax,deltalat);
+  int idlat = ODB_boxid_lat(lat,deltalat);
+  int idlon = ODB_boxid_lon(lon,deltalon);
+  int id = idlon * nlat + idlat;
+  return id;
+}
+
+
+#if 0
+#ifdef TESTING
+
+/* Testing, testing, ... */
+
+static void 
+prt(FILE *fp, double resol, eq_cache_t *p)
+{
+  if (fp && p) {
+    fprintf(fp,"++++++++++++++++++++ n=%d, resol=%.20g\n",p->n,resol);
+    {
+#if 1
+      int jb, nb = p->nb;
+      for (jb=0; jb<nb; jb++) {
+	double avglat = (p->latband[jb] + p->latband[jb+1])/2;
+	int j;
+	int j1 = p->jband[jb];
+	int j2 = p->jband[jb+1]-1;
+	fprintf(fp,
+		"---> Band#%d/%d: j1=%d, j2=%d, latband=[%10.4f .. %10.4f]\n",
+		jb+1,nb,j1,j2,p->latband[jb],p->latband[jb+1]);
+	for (j=j1; j<=j2; j++) {
+	  double startlon = p->stlon[j];
+	  double endlon   = (p->stlon[j+1] < startlon) ? p->stlon[j+1] + 360 : p->stlon[j+1];
+	  double avglon = (startlon + endlon)/2;
+	  int boxid = ODB_eq_boxid(avglat, avglon, resol);
+	  if (avglon > 180) avglon -= 360;
+	  fprintf(fp,"regions(:,:,%d) = [boxid=%d, avg (lat,lon)=(%10.4f,%10.4f)]\n",
+		  j+1,boxid,avglat,avglon);
+	  fprintf(fp,"\tlat = [%10.4f .. %10.4f]\tlon = [%10.4f .. %10.4f]\n",
+		  p->latband[jb], p->latband[jb+1],
+		  startlon, endlon);
+	}
+      }
+#else
+      int j;
+      for (j=1; j<=n; j++) {
+	double avglat = (regions(2,1,j) + regions(2,2,j))/2;
+	double avglon = (regions(1,1,j) + regions(1,2,j))/2;
+	int boxid = ODB_eq_boxid(avglat, avglon, resol);
+	fprintf(fp,"regions(:,:,%d) = [boxid=%d, avg (lat,lon)=(%10.4f,%10.4f)]\n",
+		j,boxid,avglat,avglon);
+	fprintf(fp,"\tlat = [%10.4f .. %10.4f]\tlon = [%10.4f .. %10.4f]\n",
+		regions(2,1,j),regions(2,2,j),
+		regions(1,1,j),regions(1,2,j));
+      }
+#endif
+    }
+  }
+}
+
+int main(int argc, char *argv[])
+{
+#define size_ilist 12
+  const int ilist[size_ilist]= { 1,2,3,4,5,31,128,256,512,1024,2048,4096 };
+  int jj;
+  int nlist;
+
+  if (argc > 1) {
+#ifdef INPUT_FILE
+    int jp, np = 0;
+    double *lat, *lon;
+    scanf("%d\n",&np);
+    ALLOC(lat,np);
+    ALLOC(lon,np);
+    for (jp=0; jp<np; jp++) scanf("%lf %lf\n",&lat[jp],&lon[jp]);
+#endif
+    nlist = argc;
+    for (jj=1; jj<nlist; jj++) {
+      double resol = atof(argv[jj]);
+      int n = ODB_eq_n(resol);
+      double eq_area = ODB_eq_area(n);
+      eq_cache_t *p = ODBc_get_eq_cache(n);
+#if 0
+      prt(stderr, resol, p);
+#endif
+#ifdef INPUT_FILE
+      printf(">>> np = %d, resol = %.14g, n = %d <<<\n",np,resol,n);
+      for (jp=0; jp<np; jp++) {
+	printf("(lat,lon) = (%10.4f,%10.4f)\n",lat[jp],lon[jp]);
+	{
+	  int boxid = ODB_eq_boxid_with_resol(lat[jp], lon[jp], resol);
+	  double boxlat = ODB_eq_boxlat_with_resol(lat[jp], lon[jp], resol);
+	  double boxlon = ODB_eq_boxlon_with_resol(lat[jp], lon[jp], resol);
+	  printf("(lat,lon) = (%10.4f,%10.4f) --> boxid=%d, box (lat,lon) = (%10.4f,%10.4f)\n",
+		 lat[jp],lon[jp],boxid,boxlat,boxlon);
+	}
+      }
+#endif
+    }
+  }
+  else {
+    nlist = size_ilist;
+    for (jj=0; jj<nlist; jj++) {
+      int n = ilist[jj];
+      double resol = ODB_eq_resol(n);
+      double eq_area = ODB_eq_area(n);
+      eq_cache_t *p = ODBc_get_eq_cache(n);
+      prt(stderr, resol, p);
+    } /* for (jj=0; jj<nlist; jj++) */
+  }
+  return 0;
+}
+
+#endif
+
+#endif
diff --git a/odb/src/lib/errtrap.c b/odb/src/lib/errtrap.c
new file mode 100644
index 0000000..cdffa3e
--- /dev/null
+++ b/odb/src/lib/errtrap.c
@@ -0,0 +1,441 @@
+#include "odb.h"
+#include "pcma_extern.h"
+
+#ifdef VPP
+#include <ucontext.h>
+#endif
+
+#ifdef RS6K
+extern void xl__trbk_();
+extern void xl__trce_(int sig, siginfo_t *sigcode, void *sigcontextptr);
+#endif
+
+/* Error trapping */
+
+PRIVATE char *abfunc_name = NULL;
+
+extern void errtra_();
+
+PRIVATE int Myproc = 0;
+PRIVATE int Nproc = 0;
+PRIVATE int Pid = 0;
+
+PUBLIC void
+ODB_packing_trace(int mode,
+		  const char *type, const char *name, const char *table,
+		  int pmethod, int pmethod_from_datatype,
+		  int dlen, int sizeof_dlen, int pdlen, uint datatype)
+{
+  FILE *fp = ODB_trace_fp();
+  if (fp) {
+    int packed = pdlen;
+    int unpacked = dlen * sizeof_dlen;
+    double ratio;
+    ODB_Trace TracE;
+
+    TracE.handle = -1; /* Irrelevant and/or unknown */
+    TracE.mode = mode;
+    TracE.msg = NULL;
+    TracE.msglen = 64;
+    TracE.numargs = 7;
+
+    TracE.args[0] = pmethod;
+    TracE.args[1] = pmethod_from_datatype;
+    TracE.args[2] = dlen;
+    TracE.args[3] = sizeof_dlen;
+    TracE.args[4] = packed;
+    TracE.args[5] = unpacked;
+    TracE.args[6] = datatype;
+    
+    ratio = PKRATIO(unpacked, packed);
+    
+    if (TracE.mode == 0) {
+      TracE.msglen += strlen(type) + strlen(name) + strlen(table);
+      ALLOC(TracE.msg, TracE.msglen);
+      sprintf(TracE.msg, "Unpacking(%s:%s@%s,%.2f%%)", type, name, table, ratio);
+    }
+    else if (TracE.mode == 1) {
+      TracE.msglen += strlen(type) + strlen(name) + strlen(table);
+      ALLOC(TracE.msg, TracE.msglen);
+      sprintf(TracE.msg, "Packing(%s:%s@%s,%.2f%%)", type, name, table, ratio);
+    }
+    else if (TracE.mode == 2) {
+      TracE.msglen += strlen(type) + strlen(name) + strlen(table);
+      ALLOC(TracE.msg, TracE.msglen);
+      sprintf(TracE.msg, "Enforced packing(%s:%s@%s,%.2f%%)", type, name, table, ratio);
+    }
+    else {
+      return;
+    }
+
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, &TracE.numargs, TracE.msglen);
+    
+    FREE(TracE.msg);
+  }
+}
+
+/* ODB_packing() moved here to ../aux/pcma_9.c on 09/03/2005 by SS */
+
+PUBLIC void
+ODB_packing_setup(int *Prtmsg, int *Threshold, double *Factor)
+{
+  static int prtmsg = 0;
+  static int threshold = 8192;
+  static double factor = 2.0;
+  static boolean first_time = 0;
+  if (!first_time) {
+    char *p;
+    p = getenv("ODB_PACK_PRTMSG");
+    if (p) {
+      prtmsg = atoi(p);
+      prtmsg = MAX(0,prtmsg);
+    }
+    p = getenv("ODB_PACK_THRESHOLD");
+    if (p) {
+      threshold = atoi(p);
+      threshold = MAX(0,threshold);
+    }
+    p = getenv("ODB_PACK_FACTOR");
+    if (p) {
+      factor = atof(p);
+      factor = MAX(0,factor);
+    }
+    first_time = 1;
+  }
+  if (Prtmsg) *Prtmsg = prtmsg;
+  if (Threshold) *Threshold = threshold;
+  if (Factor)    *Factor = factor;
+}
+
+PUBLIC void
+codb_procdata_(int *myproc,
+	       int *nproc,
+	       int *pid,
+	       int *it,
+	       int *inumt)
+{
+  if (myproc) *myproc = Myproc;
+  if (nproc)  *nproc  = Nproc;
+  if (pid)    *pid    = Pid;
+  if (it)     *it     = get_thread_id_();
+  if (inumt)  *inumt  = get_max_threads_();
+}
+
+PUBLIC void
+codb_test_index_range_(const int vec[],
+		       const int *veclen,
+		       const int *low,
+		       const int *high,
+		       int *retcode)
+{
+  /* Count how many values in vec[] are OUTSIDE of the valid range [low:high], both inclusive */
+
+  int rc = 0;
+  int j;
+  int N = *veclen;
+  int Lo = *low;
+  int Hi = *high;
+  static int do_test = 0;
+  static int first_time = 1;
+
+  if (first_time) {
+    /* ODB_TEST_INDEX_RANGE : 0 = no test, procid [1..NPES] or -1 (=all procs) test(s) */
+    char *env = getenv("ODB_TEST_INDEX_RANGE"); 
+    if (env) {
+      int myproc = 0;
+      int value = atoi(env);
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      do_test = (value == -1 || value == myproc) ? 1 : 0;
+    }
+    first_time = 0;
+  }
+
+  if (do_test) {
+    for (j=0; j<N; j++) {
+      if (vec[j] < Lo || vec[j] > Hi) rc++;
+    }
+    if (rc > 0) {
+      const int maxcount = 10;
+      int cnt = 0;
+      int it = 0;
+      int myproc = 0;
+      codb_procdata_(&myproc, NULL, NULL, &it, NULL);
+      fprintf(stderr,
+	      "\n*** Error: Total %d incides (out of %d) are out of bounds [%d,%d]"
+	      " on thread at task = %d@%d. For example:\n",
+	      rc, N, Lo, Hi, it, myproc);
+      for (j=0; j<N; j++) {
+	if (vec[j] < Lo || vec[j] > Hi) {
+	  fprintf(stderr,
+		  ">>> %d@%d: index[%d] = %d\n",
+		  it, myproc,j,vec[j]);
+	  if (++cnt >= maxcount) break;
+	}
+      }
+      RAISE(SIGABRT);
+    }
+  }
+
+  *retcode = rc;
+}
+
+PUBLIC void
+codb_init_(const int *myproc, 
+	   const int *nproc)
+{
+  Myproc = myproc ? *myproc : 1;
+  Nproc  = nproc ? *nproc : 1;
+  Pid = getpid();
+  if (Nproc > 1) {
+    /* Line-bufferize stderr when Nproc > 1 to avoid messy outputs */
+    int rc = 0;
+    char *buf = NULL;
+    ALLOC(buf, BUFSIZ+8);
+    rc = setvbuf(stderr, buf, _IOLBF, BUFSIZ);
+    if (rc != 0) {
+      /* Report problem; do not abort for this */
+      perror("codb_init_(): setvbuf(stderr) failed");
+    }
+  }
+  setup_sort_(NULL, NULL);
+}
+
+
+PUBLIC void 
+codb_register_abort_func_(const char *name,
+                          /* Hidden arguments */
+                          int name_len)
+{
+  DECL_FTN_CHAR(name);
+  ALLOC_FTN_CHAR(name);
+  if (abfunc_name) FREE(abfunc_name);
+  ALLOC(abfunc_name,strlen(p_name)+1);
+  strcpy(abfunc_name,p_name);
+  FREE_FTN_CHAR(name);
+}
+
+
+#if defined(SGI) || defined(RS6K_OLD)
+PUBLIC void 
+errtra_()
+{
+  char *p = getenv("ODB_ERRTRA");
+  int value = p ? atoi(p) : 0;
+  if (value > 0) {
+    char cmd[1024];
+#ifdef SGI
+    static char def[] = "/usr/bin/echo where | /usr/bin/dbx -c /dev/null -p";
+#endif
+#ifdef RS6K_OLD
+    static char def[] = "/usr/bin/echo where | /usr/bin/dbx -c /dev/null -F -x -a";
+#endif
+    char *x = getenv("ODB_ERRTRA_CMD");
+    boolean x_given = 0;
+    if (!x) x = def;
+    else x_given = 1;
+    sprintf(cmd,"%s %d",x,getpid());
+    if (x_given) fprintf(stderr,"\nerrtra_(): Executing '%s' ...\n",cmd);
+    fflush(stderr);
+    fflush(stdout);
+    system(cmd);
+    fflush(stderr);
+    fflush(stdout);
+  }
+}
+#endif
+
+#ifdef RS6K
+PUBLIC void 
+errtra_()
+{
+  xl__trbk_();
+}
+#endif
+
+
+PUBLIC void
+codb_abort_func_(const char *msg,
+		 /* Hidden arguments */
+		 int msg_len)
+{
+  char *messy_output = getenv("ODB_MESSY_OUTPUT");
+  int enforce = 1;
+  static boolean trace_done = 0;
+  ODB_iolock(-1); /* To avoid messy tracebacks */
+  if (messy_output) {
+    int imessy = atoi(messy_output);
+    if (imessy > 0) {
+      print_forfunc_(&enforce, msg, msg_len);
+      ctxdebug_(&enforce, msg, msg_len);
+      cmdb_debug_(&enforce, msg, msg_len);
+      codb_print_vars_(&enforce, msg, msg_len);
+    }
+  }
+  
+  if (!trace_done) {
+#if defined(SGI) || defined(RS6K)
+    errtra_();
+#endif
+#ifdef VPP
+    _TraceCalls(NULL);
+#endif
+    trace_done = 1;
+  }
+
+  ODB_iolock(-1);
+  if (abfunc_name && strequ(abfunc_name,"cmpl_abort")) {
+    extern void cmpl_abort_(const char s[], 
+			    /* Hidden arguments */
+			    int slen);
+    fprintf(stderr,
+	    "%s: Calling abort function '%s' on PE#%d (pid=%d)\n",
+	    "codb_abort_func_()", abfunc_name, Myproc, Pid);
+#ifdef VPP
+    sleep(5);
+#endif
+
+    if (msg && msg_len > 0) {
+      fprintf(stderr,"%*.*s\n",msg_len,msg_len,msg);
+    }
+
+    /* sometimes gets stuck --> commented out */
+    /* cmpl_abort_(msg, msg_len); */
+
+    /* instead the following should work */
+    RAISE(SIGABRT);
+  }
+  abort(); /* No bail outs ! */
+}
+
+#ifdef RS6K
+PRIVATE void
+trce_alarm(int sig)
+{
+  if (sig == SIGALRM) {
+    fflush(stdout);
+    fflush(stderr);
+    RAISE(SIGKILL);
+  }
+}
+
+PUBLIC void 
+my_xl__trce_(int sig, siginfo_t *si, void *uctext)
+{
+  extern long long int gethwm_();
+  long long int maxmem = gethwm_();
+  int tid = get_thread_id_();
+
+  maxmem /= 1048576U;
+  fprintf(stderr,
+	  "my_xl__trce_(): Received signal#%d (PE#%d, tid#%d). Maxmem: %d MB. Aborting ...\n",
+	  sig,Myproc,tid,(int)maxmem);
+  signal(SIGALRM, trce_alarm);
+  alarm(5);
+  xl__trce_(sig, si, uctext);
+  raise(SIGKILL); /* you are not supposed to get here */
+}
+
+PUBLIC void 
+my_xl__trce(int sig, siginfo_t *si, void *uctext)
+{
+  my_xl__trce_(sig, si, uctext); /* for non -qextname cases in Fortran */
+}
+#endif
+
+PUBLIC void
+codb_set_signals_()
+{
+  static int done = 0;
+  if (!done) {
+    FILE *fp = ODB_trace_fp();
+    /* Original codehas been removed and replaced with a call to Dr.Hook */
+    extern void c_drhook_init_signals_(const int *enforce);
+    const int enforce = 1;
+    c_drhook_init_signals_(&enforce);
+    if (fp) {
+      fprintf(fp,">> Library compiled on %s  %s\n",__DATE__,__TIME__);
+      fprintf(fp,">> Signals maybe caught via Dr.Hook\n");
+    }
+    done = 1;
+  }
+}
+
+PUBLIC void
+codb_ignore_alarm_()
+{
+  signal(SIGALRM, SIG_IGN);
+}
+
+PRIVATE void
+catch_alarm(int sig)
+{
+  if (sig == SIGALRM) codb_ignore_alarm_();
+}
+
+PUBLIC void
+codb_catch_alarm_(int *sig)
+{
+  catch_alarm(*sig);
+}
+
+PUBLIC void
+codb_set_alarm_()
+{
+  signal(SIGALRM, catch_alarm);
+}
+
+PUBLIC void
+codb_send_alarm_(int *pid)
+{
+  kill(*pid, SIGALRM);
+}
+
+
+#ifdef DYNAMIC_LINKING
+/* Make certain ($#*@?!) dynamic linkers happy ! */
+
+void
+exec_dummy(int dummy, ...) { }
+
+void 
+cdummy_load_()
+{
+  int dummy = 0;
+  exec_dummy(dummy, ODB_iolock);
+  exec_dummy(dummy, ODB_unpack_UINT);
+  exec_dummy(dummy, ODB_pack_DBL);
+  exec_dummy(dummy, ODB_packing);
+  exec_dummy(dummy, ODB_add_funcs);
+  exec_dummy(dummy, ODB_get_packing_consts);
+  exec_dummy(dummy, ODB_pack_INT);
+  exec_dummy(dummy, ODB_error);
+  exec_dummy(dummy, ODB_packing_setup);
+  exec_dummy(dummy, ODB_packing_trace);
+  exec_dummy(dummy, ODB_pack_UINT);
+  exec_dummy(dummy, ODB_min_alloc);
+  exec_dummy(dummy, ODB_inc_alloc);
+  exec_dummy(dummy, ODB_unpack_INT);
+  exec_dummy(dummy, ODB_trace_fp);
+  exec_dummy(dummy, ODB_unpack_DBL);
+  exec_dummy(dummy, ODB_getval_var);
+  exec_dummy(dummy, ODB_WildCard);
+}
+#endif
+
+/* Some dirty hacks to get the F90-level working (needed at MF!!)*/
+
+#if defined(VPP5000) || defined(HPPA)
+void 
+putenv_(const char *s, 
+	int slen) 
+{
+  char *p = NULL;
+  ALLOC(p, slen+1);
+  strncpy(p,s,slen); 
+  p[slen]='\0';
+  putenv(p); 
+  /* FREE(p); */
+}
+#endif
+
diff --git a/odb/src/lib/evaluate.c b/odb/src/lib/evaluate.c
new file mode 100644
index 0000000..4ab700d
--- /dev/null
+++ b/odb/src/lib/evaluate.c
@@ -0,0 +1,1451 @@
+
+/* evaluate.c */
+
+#include <ctype.h>
+#include <math.h>
+
+#include "evaluate.h"
+#include "node.h"
+#include "pcma_extern.h"
+
+static FILE *devnull = NULL;
+
+static thsafe_parse_t *thsp = NULL;
+
+#define LastreS   thsp[IT].lastres
+#define RecursioN thsp[IT].recursion
+#define NparenS   thsp[IT].nparens
+#define In_funC   thsp[IT].in_func
+#define NumelemS  thsp[IT].numelems
+#define UnarY     thsp[IT].unary
+
+#define FOLLOW(s,c) ((s) && *((s)+1) == (c)) 
+
+PRIVATE Bool IsWordBegin(char ch)
+{ return (isalpha(ch) || ch == '_' || ch == '$' || ch == '#' || ch == '\\') ? true : false; }
+
+PRIVATE Bool IsWord(char ch)
+{ return (isalnum(ch) || ch == '_' || ch == '@' || ch == '.' || ch == '#') ? true : false; }
+
+PRIVATE Bool IsBlank(char ch)
+{ return (ch == ' ' || ch == '\t' || ch == '\n') ? true : false; }
+
+PRIVATE Bool IsNumberBegin(char ch)
+{ return (isdigit(ch) || ch == '.') ? true : false; }
+
+PRIVATE Bool IsSemi(char ch)
+{ return (ch == ';') ? true : false; }
+
+PRIVATE Bool IsSemiOrBlank(char ch)
+{ return (ch == ';' || IsBlank(ch)) ? true : false; }
+
+PUBLIC char ToLower(char ch)
+{ return isupper(ch) ? tolower(ch) : ch; }
+
+PUBLIC char ToUpper(char ch)
+{ return islower(ch) ? toupper(ch) : ch; }
+
+PRIVATE Bool IsOper(char ch)
+{
+  return (ch  == '*' || ch  == '+' || ch == '=' ||
+	  ch  == '/' || ch  == '%' || ch == ':' ||
+	  ch  == '|' || ch  == '&' || 
+	  ch  == '>' || ch  == '<' || ch == '!' ||
+	  ch  == '-' || ch  == '^') ? true : false;
+}
+
+PRIVATE Bool IsDot(const char *s)
+{
+  return (s && s[0] == '.' && !isalnum(s[1])) ? true : false;
+}
+
+PRIVATE Bool IsAssignOper(const char *s)
+{
+  if (s && *s == '=' && !FOLLOW(s,'=')) return true;
+  if (FOLLOW(s,'=')) {
+    return (*s == ':' || 
+	    *s == '+' ||
+	    *s == '-' ||
+	    *s == '*' ||
+	    *s == '/' ||
+	    *s == '%' ||
+	    *s == '^' ) ? true : false;
+  }
+  return false;
+}
+
+
+#define SKIP_WHITE_SPACE(s)  while (s < s_end && IsBlank(*(s))) (s)++
+
+#define ISFUNC(s) (*(s) == '`' && IsWordBegin(*((s)+1)))
+
+PUBLIC const char *
+KindStr(Kind_t kind)
+{
+  static char *s = NULL;
+  switch (kind) {
+  case NAME: s="NAME"; break;
+  case NUMBER: s="NUMBER"; break;
+  case FUNC: s="FUNC"; break;
+  case UNARY_PLUS: s="`+"; break;
+  case UNARY_MINUS: s="`-"; break;
+  case PLUS: s="+"; break;
+  case MINUS: s="-"; break;
+  case MUL: s="*"; break;
+  case DIV: s="/"; break;
+  case MOD: s="%"; break;
+  case POWER: s="**"; break;
+  case LT: s="<"; break;
+  case LE: s="<="; break;
+  case GT: s=">"; break;
+  case GE: s=">="; break;
+  case EQ: s="=="; break;
+  case NE: s="!="; break;
+  case NOT: s="!"; break;
+  case AND: s="&&"; break;
+  case OR: s="||"; break;
+  case LSHIFT: s="<<"; break;
+  case RSHIFT: s=">>"; break;
+  case SEMI: s=";"; break;
+  case ASSIGN: s=":="; break;
+  case LP: s="("; break;
+  case RP: s=")"; break;
+  case INCR: s="++"; break;
+  case DECR: s="--"; break;
+  case INCR_ASSIGN: s="+="; break;
+  case DECR_ASSIGN: s="-="; break;
+  case MUL_ASSIGN: s="*="; break;
+  case DIV_ASSIGN: s="/="; break;
+  case MOD_ASSIGN: s="%="; break;
+  case POWER_ASSIGN: s="^="; break;
+  case COMMA: s=","; break;
+  case COLON: s=":"; break;
+  case QMARK: s="?"; break;
+  case EMPTY: s="EMPTY"; break;
+  case CMP: s="<=>"; break;
+  case DOT: s="."; break;
+  default: s = "UNKNOWN"; break;
+  }
+  return s;
+}
+
+PRIVATE Kind_t 
+WhatKind(const char *s, int *inc, Bool unary, int *nargs, Bool *left_assoc)
+{
+  Kind_t kind = UNKNOWN;
+  int Inc = 0;
+  int Nargs = 0;
+  Bool La = true; /* left associativity */
+  if (s) {
+    Nargs = 2;
+    switch (*s) {
+    case '*':
+      if (FOLLOW(s,'*')) { kind = POWER; Inc += 2; }           /*  X ** Y */
+      else if (FOLLOW(s,'=')) { kind = MUL_ASSIGN; Inc += 2; } /*  X *= Y i.e. X = X * Y */
+      else { kind = MUL; Inc++; }                              /*  X * Y  */
+      break;
+    case '/':
+      if (FOLLOW(s,'=')) { kind = DIV_ASSIGN; Inc += 2; }  /* X /= Y  i.e. X = X / Y */
+      else { kind = DIV; Inc++; }                          /* X / Y  */
+      break;
+    case '%':
+      if (FOLLOW(s,'=')) { kind = MOD_ASSIGN; Inc += 2; }  /* X %= Y  i.e. X = X % Y */
+      else { kind = MOD; Inc++; }                          /* X % Y  */
+      break;
+    case '!':
+      if (FOLLOW(s,'=')) { kind = NE; Inc += 2; } /* X != Y */
+      else { kind = NOT; Inc++; }                 /* !X     */
+      break;
+    case '+':
+      if (FOLLOW(s,'=')) { kind = INCR_ASSIGN; Inc += 2; } /* X += Y i.e. X = X + Y */
+      else if (FOLLOW(s,'+')) { kind = INCR; }             /* X++ or ++X : not supported */
+      else { kind = unary ? UNARY_PLUS : PLUS; Inc++; }    /* +X or X-Y  */
+      break;
+    case '-':
+      if (FOLLOW(s,'=')) { kind = DECR_ASSIGN; Inc += 2; } /* X -= Y     */
+      else if (FOLLOW(s,'-')) { kind = DECR; }             /* X-- or --X : not supported */
+      else { kind = unary ? UNARY_MINUS : MINUS; Inc++; }  /* -X or X-Y  */
+      break;
+    case '`':
+      if (FOLLOW(s,'-')) { kind = UNARY_MINUS; Inc += 2; }
+      else if (FOLLOW(s,'+')) { kind = UNARY_PLUS; Inc += 2; }
+      break;
+    case '^':
+      if (FOLLOW(s,'=')) { kind = POWER_ASSIGN; Inc += 2; }  /* X ^= Y  i.e. X = X ^ Y */
+      else { kind = POWER; Inc++; }                          /* X ^ Y  i.e. X ** Y */
+      break;
+    case ':': 
+      if (FOLLOW(s,'=')) { kind = ASSIGN; Inc += 2; } /* X := Y */
+      break;
+    case '=': 
+      if (FOLLOW(s,'=')) { kind = EQ; Inc += 2; } /* X == Y     */
+      else { kind = ASSIGN; Inc++; }              /* X = <expr> */
+      break;
+    case '>':
+      if (FOLLOW(s,'=')) { kind = GE; Inc += 2; }          /* X >= Y */
+      else if (FOLLOW(s,'>')) { kind = RSHIFT; Inc += 2; } /* X >> Y */
+      else { kind = GT; Inc++; }                           /* X > Y  */
+      break;
+    case '<':
+      if (FOLLOW(s,'=') && FOLLOW(s+1,'>')) { kind = CMP; Inc += 3; } /* X <=> Y */
+      else if (FOLLOW(s,'=')) { kind = LE; Inc += 2; }                /* X <= Y  */
+      else if (FOLLOW(s,'<')) { kind = LSHIFT; Inc += 2; }            /* X << Y  */
+      else if (FOLLOW(s,'>')) { kind = NE; Inc += 2; }                /* X <> Y  */
+      else { kind = LT; Inc++; }                                      /* X < Y   */
+      break;
+    case '|': 
+      if (FOLLOW(s,'|')) { kind = OR; Inc += 2; }  /* X || Y */
+      break;
+    case '&': 
+      if (FOLLOW(s,'&')) { kind = AND; Inc += 2; } /* X && Y */
+      break;
+    default:
+      Nargs = 0;
+      break;
+    } /* switch (*s) */
+    if (nargs) {
+      if (kind == UNARY_MINUS || kind == UNARY_PLUS || kind == NOT) Nargs = 1;
+    }
+    if (left_assoc) {
+      if (kind == UNARY_MINUS || kind == UNARY_PLUS  || kind == NOT  ||
+	  kind == POWER       || kind == DECR        || kind == INCR ||
+	  kind == ASSIGN      || kind == DECR_ASSIGN || kind == INCR_ASSIGN ||
+	  kind == MUL_ASSIGN  || kind == DIV_ASSIGN  || kind == MOD_ASSIGN) La = false;
+    }
+  }    
+  if (inc) *inc = Inc;
+  if (nargs) *nargs = Nargs;
+  if (left_assoc) *left_assoc = La;
+  return kind;
+}
+
+
+PRIVATE Bool
+cmp_priorities(Bool o1_left_assoc, double o1prio, double o2prio)
+{ /* Shunting yard algorithm by Edsger Dijkstra */
+  if (o1_left_assoc && (o1prio <= o2prio)) return true;
+  if (!o1_left_assoc && (o1prio < o2prio)) return true;
+  return false;
+}
+
+
+PRIVATE double
+priority(Kind_t kind)
+{
+  if (kind == UNARY_PLUS || kind == UNARY_MINUS || kind == NOT)          return 11;
+  else if (kind == POWER)                                                return 10;
+  else if (kind == MUL || kind == DIV || kind == MOD)                    return 9;
+  else if (kind == PLUS || kind == MINUS)                                return 8;
+  else if (kind == RSHIFT || kind == LSHIFT)                             return 7;
+  else if (kind == LT || kind == LE || kind == GE || kind == GT)         return 6;
+  else if (kind == EQ || kind == NE || kind == CMP)                      return 5;
+  else if (kind == AND)                                                  return 4;
+  else if (kind == OR)                                                   return 3;
+  else if (kind == INCR_ASSIGN || kind == DECR_ASSIGN)                   return 2;
+  else if (kind == MUL_ASSIGN  || kind == DIV_ASSIGN)                    return 2;
+  else if (kind == MOD_ASSIGN || kind == POWER_ASSIGN)                   return 2;
+  else if (kind == ASSIGN)                                               return 1;
+  else                                                                   return 0;
+}
+
+
+typedef struct _cmd_list_t {
+  char *cmd;
+  char *rpn;
+  int rpn_alloc;
+  struct _cmd_list_t *next;
+} cmd_list_t;
+
+
+typedef struct _THSAFE_NodeStack_t {
+  Node_t **stack;
+} THSAFE_NodeStack_t;
+
+static THSAFE_NodeStack_t *node = NULL;
+static int  *top_node_stack = NULL;
+static int  *max_node_stack = NULL;
+
+
+PRIVATE cmd_list_t *
+ScanCmds(const char *s)
+{
+  cmd_list_t *cl = NULL;
+  if (s) {
+    cmd_list_t *plast = NULL;
+#if 0
+    FprintF(StderR,"ScanCmds(%s)\n",s);
+#endif
+    while (IsSemiOrBlank(*s)) s++;
+    while (*s) {
+      char *p, *out;
+      int outlen;
+      outlen = STRLEN(s);
+      ALLOC(out, outlen + 1);
+      p = out;
+      while (*s && !IsSemi(*s)) { *p++ = ToLower(*s++); }
+      *p = '\0';
+      if (STRLEN(out) > 0) {
+	cmd_list_t *pc;
+	CALLOC(pc,1);
+	if (!plast) { cl = plast = pc; } 
+	else { plast->next = pc; plast = pc; }
+	pc->cmd = out;
+      }
+      else {
+	FREE(out);
+      }
+      while (IsSemiOrBlank(*s)) s++;
+    }
+  }
+  return cl;
+}
+
+PUBLIC void
+SetTHSPio(int it
+	  , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+	  , void *chan_out                            /* like stdout */
+	  , void *chan_err                            /* like stderr */
+	  )
+{
+  if (!thsp) InitTHSP(); /* Should never be called from here */
+  FprintF = prtfunc;
+  StdouT = chan_out;
+  StderR = chan_err; 
+}
+
+PUBLIC void
+InitTHSP()
+{
+  if (!thsp) {
+    DEF_INUMT;
+    int it;
+    CALLOC(thsp, inumt);
+    for (it=1; it<=inumt; it++) {
+      Aggr_argnO = 1; /* by default return the 1st argument of multi-arg. aggr. func ;
+		         See also include/funcs.h */
+    }
+  }
+  { /* Set I/O defaults */
+    DEF_INUMT;
+    int it;
+    for (it=1; it<=inumt; it++) {
+      SetTHSPio(it,
+		(int (*)(void *, const char *, ...))fprintf,
+		stdout,
+		stderr);
+    }
+    if (!devnull) devnull = fopen("/dev/null", "w");
+  }
+  if (!node) {
+    DEF_INUMT;
+    CALLOC(node, inumt);
+    CALLOC(top_node_stack, inumt);
+    CALLOC(max_node_stack, inumt);
+  }
+}
+
+PUBLIC const void *
+GetTHSP()
+{
+  return thsp;
+}
+
+
+
+PRIVATE int
+ParseInput(const char *s_in, char *rpn, int *rpnlen)
+{
+  DEF_IT;
+  const char *s = s_in;
+  int rc = 0;
+  int init_stack_len = OpStackLen();
+
+  if (RecursioN == 0) {
+    NparenS = 0;
+    In_funC = 0;
+    NumelemS = 0;
+    UnarY = true;
+  }
+
+  if (s_in) {
+    int nparens_in = NparenS;
+    const char *s_begin = s;
+    int slen = STRLEN(s);
+    const char *s_end = s + slen;
+
+#if 0
+    FprintF(StderR,
+	    "ParseInput(%s) [RecursioN=%d]: init_stack_len = %d, rpn='%s', *rpnlen=%d\n",
+	    s,RecursioN,init_stack_len,rpn,*rpnlen);
+    FprintF(StderR,
+	    "\tnparens_in = %d, In_funC = %d, LastreS = %.14g\n",nparens_in,In_funC,LastreS);
+#endif
+
+    RecursioN++;
+    SKIP_WHITE_SPACE(s);
+
+    while (s < s_end) {
+      Bool inword = false;
+      Bool assign = false;
+
+      if (IsBlank(*s)) {
+	SKIP_WHITE_SPACE(s);
+	continue; /* while (s < s_end) */
+      }
+
+#if 0
+      PrintOpStack(StderR,s);
+#endif
+
+      if (*s == ',') { /* Comma found: function call argument list */
+	if (!In_funC) {
+	  ERROR("A comma-character (',') found while outside function call",-1);
+	}
+	s++;
+	SKIP_WHITE_SPACE(s);
+	UnarY = true;
+	NumelemS++;
+	break; /* while (s < s_end) */
+      }
+
+      if (IsDot(s)) { /* Remember the last result (as in "bc" : . ) */
+	*rpnlen -= snprintf(rpn,*rpnlen,". ");
+	rpn += 2;
+	s++;
+	UnarY = false;
+	goto eof_while;
+      }
+
+      if (IsNumberBegin(*s)) { /* Operands : (flp) numbers */
+        char *endptr = NULL;
+	double value = strtod(s, &endptr);
+	int dlen = endptr - s;
+	*rpnlen -= snprintf(rpn,*rpnlen,"%*.*s ",dlen,dlen,s);
+	rpn += dlen+1;
+	s = endptr;
+	UnarY = false;
+	goto eof_while;
+      }
+
+      if (IsWordBegin(*s)) { /* Operands : words */
+	int wlen = 0;
+        const char *save_s = s++;
+	while (IsWord(*s)) s++;
+	wlen = s-save_s;
+	SKIP_WHITE_SPACE(s);
+	if (*s == '(') {
+	  char *funcname;
+	  int j, nargs = 0;
+	  int save_nparens = NparenS++;
+	  inword = false;
+	  In_funC++;
+	  s++;
+	  ALLOC(funcname,wlen+1);
+	  snprintf(funcname,wlen+1,"%*.*s",wlen,wlen,save_s);
+	  SKIP_WHITE_SPACE(s);
+	  UnarY = true;
+	  while (s < s_end) {
+	    SKIP_WHITE_SPACE(s);
+	    if (*s == ')') {
+	      NparenS--;
+	      s++;
+	      break; /* while (s < s_end) */
+	    }
+	    nargs++;
+	    {
+	      int save_rpnlen = *rpnlen;
+	      slen = ParseInput(s,rpn,rpnlen);
+	      if (slen == 0) { 
+		ERROR1("No progress when processing function arg. list for '%s'",
+		       -2, funcname); }
+	      else if (slen < 0) { 
+		ERROR1("Error encountered while processing function arg. list for '%s'",
+		       -3,funcname); 
+	      }
+	      rpn += (save_rpnlen - (*rpnlen));
+	      s += slen;
+	    }
+	  } /* while (s < s_end) */
+	  In_funC--;
+	  if (!checkfunc(funcname,nargs)) {
+	    ERROR1("# of args mismatch or function '%s' not installed",-4,funcname);
+	  }
+	  if (NparenS != save_nparens) {
+	    ERROR1("Mismatch in function '%s' closing parenthesis",-5,funcname);
+	  }
+	  slen = snprintf(rpn,*rpnlen,"`%s %d ",funcname,nargs);
+	  *rpnlen -= slen;
+	  rpn += slen;
+	  FREE(funcname);
+	  goto eof_while;
+	}
+	else {
+	  *rpnlen -= snprintf(rpn,*rpnlen,"%*.*s ",wlen,wlen,save_s);
+	  rpn += wlen+1;
+	  inword = true;
+	  UnarY = false;
+	}
+	SKIP_WHITE_SPACE(s);
+      }
+
+      if (IsAssignOper(s)) assign = true;
+
+      if (assign && (!inword || NumelemS != 0)) {
+	ERROR("Invalid assignment statement; "
+	      "Expecting word followed by one of the "
+	      "{ '=', ':=', '+=', '-=', '*=', '/=', '%=', '^=' }",-6);
+      }
+
+      if (*s  == '(') {/* Opening Parenthesis */
+        NparenS++;
+	PushOpStack(LP);
+	s++;
+	UnarY = true;
+	goto eof_while; /* while (*s) */
+      }
+      else if (IsOper(*s)) {
+	int nargs = 0;
+	int inc = 0;
+	Bool left_assoc = true;
+	Kind_t kind = WhatKind(s, &inc, UnarY, NULL, &left_assoc);
+	if (kind <= UNKNOWN || inc == 0) {
+	  const char *skind = KindStr(kind);
+	  char errmsg[100];
+	  int errlen = sizeof(errmsg);
+	  snprintf(errmsg,errlen,"Invalid operator '%s' found near character '%c'",skind,*s);
+	  ERROR(errmsg,-7);
+	}
+	if (OpStackLen() > init_stack_len) {
+	  double priokind = priority(kind);
+	  Kind_t oprkind = PopOpStack();
+	  while (cmp_priorities(left_assoc, priokind, priority(oprkind))) {
+	    slen = snprintf(rpn,*rpnlen,"%s ",KindStr(oprkind));
+	    *rpnlen -= slen;
+	    rpn += slen;
+	    if (OpStackLen() > init_stack_len) {
+	      oprkind = PopOpStack();
+	    }
+	    else {
+	      oprkind = UNKNOWN;
+	      break;
+	    }
+	  }
+	  PushOpStack(oprkind);
+	}
+	PushOpStack(kind);
+	s += inc;
+	if (kind == ASSIGN || 
+	    kind == LT || kind == LE || kind == GE || kind == GT ||
+	    kind == EQ || kind == NE || kind == CMP ||
+	    kind == INCR_ASSIGN || kind == DECR_ASSIGN ||
+	    kind == MUL_ASSIGN  || kind == DIV_ASSIGN  ||
+	    kind == MOD_ASSIGN  || kind == POWER_ASSIGN ) {
+	  UnarY = true;
+	}
+	goto eof_while;
+      }
+      else if (*s  == ')') { /* Closing Parenthesis */
+#if 0
+	FprintF(StderR,"Closing Parenthesis found where s='%s'\n",s);
+#endif
+	if (OpStackLen() > init_stack_len) {
+	  Kind_t oprkind = PopOpStack();
+	  while (oprkind != LP) {
+	    slen = snprintf(rpn,*rpnlen,"%s ",KindStr(oprkind));
+	    *rpnlen -= slen;
+	    rpn += slen;
+	    if (OpStackLen() == init_stack_len) break;
+	    oprkind = PopOpStack();
+	  }
+	}
+	NparenS--;
+	if (NparenS < nparens_in) {
+	  if (In_funC) {
+	    NparenS++;
+#if 0
+	    FprintF(StderR,
+		    "--> Before the break while In_funC = %d : nparens_in = %d"
+		    ", NparenS now = %d, where s='%s'\n",
+		    In_funC, nparens_in, NparenS,s);
+#endif
+	    break;
+	  }
+	  else {
+	    ERROR("Mismatch in closing parenthesis",-8);
+	  }
+	}
+	s++;
+	goto eof_while;
+      }
+      else if (inword) {
+	goto eof_while;
+      }
+      else if (*s) { /* Syntax error ? */
+	FprintF(StderR,"Why I am here ? where s='%s'\n",s);
+	ERROR("Why I am here ? Syntax/programming error ?",-9);
+      }
+
+    eof_while:
+#if 0
+      FprintF(StderR,"[eof_while: s='%s']\n",s);
+      PrintOpStack(StderR,NULL);
+#endif
+      NumelemS++;
+      continue;
+
+    } /* while (*s) */
+
+    while (OpStackLen() > init_stack_len) {/* While stack is not empty */
+      Kind_t oprkind = PopOpStack();
+      slen = snprintf(rpn,*rpnlen,"%s ",KindStr(oprkind));
+      *rpnlen -= slen;
+      rpn += slen;
+    }
+      
+    rc = s - s_begin;
+    RecursioN--;
+  } /* if (s) */
+  if (RecursioN == 0) {
+    if (NparenS > 0) { ERROR("Mismatch in opening parenthesis",-10); }
+    if (OpStackLen() > 0) { ERROR("OpStack not emptied",-11); }
+  }
+ finish:
+  return rc;
+}
+
+
+PRIVATE int
+CreateRPN(cmd_list_t *cmdlist)
+{
+  DEF_IT;
+  int rc = 0;
+  cmd_list_t *cl = cmdlist;
+  int maxdepth = 0;
+  while (cl) {
+    int rpnlen = cl->rpn_alloc = (STRLEN(cl->cmd)+1) * 4;
+    CALLOC(cl->rpn, rpnlen);
+    initOpStack();
+#if 0
+    FprintF(StderR,"CreateRPN: Going to ParseInput(s=%s, rpn=%p, rpnlen=%d);\n",
+	    cl->cmd, cl->rpn, rpnlen);
+#endif
+    RecursioN = 0; /* Must reset or otherwise doesn't recover from previous errors properly */
+    rc = ParseInput(cl->cmd, cl->rpn, &rpnlen);
+#if 0
+    FprintF(StderR,"CreateRPN: Out. rc=%d; rpnlen=%d;\n",rc,rpnlen);
+#endif
+    if (rc < 0) goto finish;
+    maxdepth = MAX(maxdepth,OpStackMaxLen());
+    cl = cl->next;
+  } /* while (cl) */
+ finish:
+  initOpStack();
+  if (rc >= 0) {
+    maxdepth += 100;
+  }
+  else {
+    maxdepth = rc;
+  }
+#if 0
+    FprintF(StderR,"CreateRPN: maxdepth = %d\n",maxdepth);
+#endif
+  return maxdepth;
+}
+
+
+PRIVATE void
+PushNodeStack(Node_t *p, int *retcode)
+{
+  int rc = 0;
+  DEF_IT;
+  if (top_node_stack[IT] == max_node_stack[IT] - 1) {
+    ERROR("Node stack is full",-1);
+  }
+  else {
+    node[IT].stack[++top_node_stack[IT]] = p;
+  }
+ finish:
+  if (retcode) *retcode = rc;
+  return;
+}
+
+
+PRIVATE Node_t *
+PopNodeStack(int *retcode)
+{
+  int rc = 0;
+  DEF_IT;
+  Node_t *p = NULL;
+  if (top_node_stack[IT] == -1) {
+    ERROR("Node stack is empty",-2);
+  }
+  else {
+    p = node[IT].stack[top_node_stack[IT]--];
+  }
+ finish:
+  if (retcode) *retcode = rc;
+  return p;
+}
+
+
+PRIVATE Node_t *
+CreateExprTree(const char *s_in, int *retcode)
+{
+  int rc;
+  Node_t *p = NULL;
+  const char *s = s_in;
+  if (s) {
+    const char *s_begin = s;
+    int slen = STRLEN(s);
+    const char *s_end = s + slen;
+    Node_t *pfirst = NULL;
+    Node_t *plast = NULL;
+    int k = 0;
+#if 0
+    FprintF(StderR,"CreateExprTree(%s)\n",s);
+#endif
+    while (s < s_end) {
+      if (IsBlank(*s)) {
+	SKIP_WHITE_SPACE(s);
+	continue; /* while (s < s_end) */
+      }
+      
+      CALLOC(p, 1);
+      s_begin = s;
+
+      if (IsDot(s)) { /* Last result (LastreS) */
+	s++;
+	p->kind = DOT;
+	goto push_it;
+      }
+      
+      if (IsWordBegin(*s)) { /* Operands : words */
+	const char *save_s = s++;
+	while (IsWord(*s)) s++;
+	slen = s - save_s;
+	ALLOC(p->name, slen+1);
+	strncpy(p->name,save_s,slen);
+	p->name[slen] = '\0';
+	p->kind = NAME;
+	goto push_it;
+      }
+
+      if (ISFUNC(s)) { /* Operands : function followed by # of args */
+	const char *save_s = ++s;
+	while (IsWord(*s)) s++;
+	slen = s - save_s;
+	ALLOC(p->name, slen+1);
+	strncpy(p->name,save_s,slen);
+	p->name[slen] = '\0';
+	p->kind = FUNC;
+	p->funcptr = NULL;
+	SKIP_WHITE_SPACE(s);
+	/* fall through : the next MUST BE an integer == # of args */
+      }
+
+      if (IsNumberBegin(*s)) { /* Operands : (flp) numbers */
+	char *endptr = NULL;
+	double value = strtod(s, &endptr);
+	s = endptr;
+	p->value = value;
+	if (p->kind == FUNC) {
+	  int j, nargs = value;
+	  ALLOC(p->args, nargs);
+	  for (j=nargs-1; j>=0; j--) {
+	    p->args[j] = PopNodeStack(&rc);
+	    if (rc != 0) goto finish;
+	  }
+	  p->numargs = nargs;
+	  p->funcptr = getfunc(p->name, nargs); 
+	}
+	else {
+	  p->kind = NUMBER;
+	}
+      }
+      else {
+	int inc = 0;
+	int unary = false;
+	int j, nargs = 0;
+	Kind_t kind = WhatKind(s, &inc, false, &nargs, NULL);
+	p->kind = kind;
+	ALLOC(p->args, nargs);
+	for (j=nargs-1; j>=0; j--) {
+	  p->args[j] = PopNodeStack(&rc);
+	  if (rc != 0) goto finish;
+	}
+	p->numargs = nargs;
+	s += inc;
+      }
+
+    push_it:
+      slen = s - s_begin;
+#if 0
+      k++;
+      FprintF(StderR,"CreateExprTree: push_it#%d, kind=%s, s='%*.*s'\n",
+	      k,KindStr(p->kind),slen,slen,s_begin);
+#endif
+      PushNodeStack(p,&rc);
+      if (rc != 0) goto finish;
+      if (plast) { plast->next = p; plast = p; }
+      else { pfirst = plast = p; }
+      s++;
+    } /* while (s < s_end) */
+
+    p = PopNodeStack(&rc);
+  } /* if (s) */
+ finish:
+  if (retcode) *retcode = rc;
+  return p;
+}
+
+
+PUBLIC void
+PrintNode(void *fp, void *pnode)
+{
+  if (fp) {
+    static int ntabs = 0;
+    int j;
+    Node_t *p = pnode;
+    if (p) {
+      DEF_IT;
+      for (j=0; j<ntabs; j++) FprintF(fp," ");
+      FprintF(fp,"PrintNode : %p, kind=%s, name=%s, value=%.14g, numargs=%d\n",
+	      p, KindStr(p->kind), 
+	      p->name ? p->name : "<undef>",
+	      p->value, p->numargs);
+      if (p->numargs > 0 && p->args) {
+	ntabs++;
+	for (j=0; j<p->numargs; j++) PrintNode(fp, p->args[j]);
+	ntabs--;
+      } /* if (p->numargs > 0 && p->args) */
+    } /* if (p) */
+  } /* if (fp) */
+}
+
+
+PUBLIC void
+PrintTree(void *fp, void *ptree)
+{
+  if (fp) {
+    Node_t *p = ptree;
+    while (p) {
+      PrintNode(fp, p);
+      p = p->next;
+    } /* while (p) */
+  } /* if (fp) */
+}
+
+
+PRIVATE Node_t *
+RPNtoTree(cmd_list_t *cmdlist, int maxdepth, int *retcode)
+{
+  int rc = 0;
+  Node_t *p = NULL;
+  if (maxdepth >= 0) {
+    DEF_IT;
+    cmd_list_t *cl = cmdlist;
+    Node_t *plast = NULL;
+    while (cl) {
+      CALLOC(node[IT].stack,maxdepth);
+      top_node_stack[IT] = -1;
+      max_node_stack[IT] = maxdepth;
+      {
+	Node_t *root = CreateExprTree(cl->rpn,&rc);
+	if (rc == 0) {
+	  if (plast) { plast->next = root; plast = root; }
+	  else { p = plast = root; }
+	}
+      }
+      FREE(node[IT].stack);
+      if (rc != 0) break;
+      cl = cl->next;
+    }
+  }
+  else {
+    rc = maxdepth;
+  }
+ finish:
+  if (retcode) *retcode = rc;
+  return p;
+}
+
+
+#define ASSIGN_MACRO_1(what,assop,err) \
+  double oldvalue; \
+  char *name = (p->args && p->args[0]) ? p->args[0]->name : NULL; \
+  if (!name) { \
+    ERROR("Invalid syntax : Expecting " #what " assignment in 'variable " #assop " expression'",err); \
+  } \
+  oldvalue = getsym(name,&on_error); \
+  if (on_error) { \
+    ERROR1("Attempt to use uninitialized variable '%s' in 'variable " #assop " expression'",err-1,name); \
+  } \
+  value = RunNode(p->args[1], &rc); \
+  if (rc != 0) goto finish; \
+  { double *newvalue = p->args[0]->symval; \
+    if (!newvalue) p->args[0]->symval = newvalue = putsym(name,oldvalue assop value); \
+    else *newvalue = oldvalue assop value; \
+    value = *newvalue; }
+
+#define ASSIGN_MACRO_2(what,assop,func,err) \
+  double oldvalue; \
+  char *name = (p->args && p->args[0]) ? p->args[0]->name : NULL; \
+  if (!name) { \
+    ERROR("Invalid syntax : Expecting " #what " assignment in 'variable " #assop " expression'",err); \
+  } \
+  oldvalue = getsym(name,&on_error); \
+  if (on_error) { \
+    ERROR1("Attempt to use uninitialized variable '%s' in 'variable " #assop " expression'",err-1,name); \
+  } \
+  value = RunNode(p->args[1], &rc); \
+  if (rc != 0) goto finish; \
+  { double *newvalue = p->args[0]->symval; \
+    if (!newvalue) p->args[0]->symval = newvalue = putsym(name,func(oldvalue,value)); \
+    else *newvalue = func(oldvalue,value); \
+    value = *newvalue; }
+
+PUBLIC double
+RunNode(void *pnode, int *retcode)
+{
+  DEF_IT;
+  int rc = 0;
+  Node_t *p = pnode;
+  double value = RMDI;
+  if (retcode) *retcode = rc; /* All ok */
+  if (p) {
+    Kind_t kind = p->kind;
+    Bool on_error = false;
+    Bool is_fun = (kind == FUNC  ) ? true : false;
+    Bool is_sym = (kind == NAME  ) ? true : false;
+    Bool is_num = (kind == NUMBER) ? true : false;
+    Bool is_dot = (kind == DOT   ) ? true : false;
+    if (is_fun) {
+      value = callfunc(p, &rc); /* Neat, uh ? */
+    }
+    else if (is_sym) {
+      double *testvalue = p->symval;
+      if (!testvalue) {
+	testvalue = getsymaddr(p->name);
+	if (testvalue) p->symval = testvalue;
+      }
+      if (testvalue) {
+	value = *testvalue;
+      }
+      else {
+	ERROR1("Attempt to use uninitialized variable '%s'",-101,p->name?p->name:NIL);
+      }
+    }
+    else if (is_num) {
+      value = p->value;
+    }
+    else if (is_dot) {
+      value = LastreS;
+    }
+    else if (kind == ASSIGN) {
+      char *name = (p->args && p->args[0]) ? p->args[0]->name : NULL;
+      if (!name) {
+	ERROR("Invalid syntax : Expecting assignment 'variable = expression'",-102);
+      }
+      value = RunNode(p->args[1], &rc);
+      if (rc != 0) goto finish;
+      if (!p->args[0]->symval) {
+	p->args[0]->symval = putsym(name,value);
+      }
+      else {
+	*p->args[0]->symval = value;
+      }
+    }
+    else if (kind == INCR_ASSIGN) {
+      ASSIGN_MACRO_1(increment,+=,-103);
+    }
+    else if (kind == DECR_ASSIGN) {
+      ASSIGN_MACRO_1(decrement,-=,-105);
+    }
+    else if (kind == MUL_ASSIGN) {
+      ASSIGN_MACRO_1(multiplicative,*=,-107);
+    }
+    else if (kind == DIV_ASSIGN) { /* no FPE checks at the moment */
+      ASSIGN_MACRO_1(division,/=,-109);
+    }
+    else if (kind == MOD_ASSIGN) { /* no FPE checks at the moment */
+      ASSIGN_MACRO_2(modulo,%=,fmod,-111);
+    }
+    else if (kind == POWER_ASSIGN) { /* no FPE checks at the moment */
+      ASSIGN_MACRO_2(modulo,*=,pow,-113);
+    }
+    else if (p->numargs == 1) {
+      double y = RunNode(p->args[0], &rc);
+      if (rc != 0) goto finish;
+      switch(kind) {
+      case UNARY_PLUS  : value =  y;  break;
+      case UNARY_MINUS : value = -y;  break;
+      case NOT         : value =(y == 0); break;
+      default: { ERROR("Unrecognized unary-operation",-114); } ; break;
+      }
+    }
+    else if (p->numargs == 2 && kind == OR) {
+      value = (RunNode(p->args[0], &rc) != 0) ? 1 : 0;
+      if (rc != 0) goto finish;
+      if (value == 0) {
+	/* Run only if value in previous expression was 0 */
+	value = (RunNode(p->args[1], &rc) != 0) ? 1 : 0;
+      }
+    }
+    else if (p->numargs == 2 && kind == AND) {
+      value = (RunNode(p->args[0], &rc) != 0) ? 1 : 0;
+      if (rc != 0) goto finish;
+      if (value == 1) {
+	/* Run only if value in previous expression was 1 */
+	value = (RunNode(p->args[1], &rc) != 0) ? 1 : 0;
+      }
+    }
+    else if (p->numargs == 2) {
+      double x, y;
+      x = RunNode(p->args[0], &rc);
+      if (rc != 0) goto finish;
+      y = RunNode(p->args[1], &rc);
+      if (rc != 0) goto finish;
+      switch(kind) {
+      case PLUS   : value=x+y;       break;
+      case MINUS  : value=x-y;       break;
+      case MUL    : value=x*y;       break;
+      case DIV    : value=x/y;       break; /* no FPE checks at the moment */
+      case MOD    : value=fmod(x,y); break; /* no FPE checks at the moment  */
+      case POWER  : value=pow(x,y);  break; /* no FPE checks at the moment */
+      case EQ     : value=(x==y);    break;
+      case NE     : value=(x!=y);    break;
+      case CMP    : value=((x < y) ? -1 : ((x > y) ? +1 : 0)); break;
+      case LT     : value=(x<y);     break;
+      case LE     : value=(x<=y);    break;
+      case GT     : value=(x>y);     break;
+      case GE     : value=(x>=y);    break;
+      case LSHIFT : value=((u_ll_t)x << (u_ll_t)y);  break;
+      case RSHIFT : value=((u_ll_t)x >> (u_ll_t)y);  break;
+      default: { ERROR("Unrecognized binary-operation",-115); } ; break;
+      }
+    }
+    else {
+      ERROR("Unrecognized command in RunNode",-116); 
+    }
+  }
+  else {
+    ERROR("An attempt to run an empty command in RunNode",-117);
+  }
+ finish:
+  if (retcode) *retcode = rc;
+  return value;
+}
+
+
+PUBLIC double
+RunTree(void *ptree, void *fp, int *retcode)
+{
+  DEF_IT;
+  int rc = 0;
+  double value = 0;
+  Node_t *p = ptree;
+#if 0
+  PrintTree(StderR,p);
+#endif
+  while (p) {
+    rc = 0;
+    value = RunNode(p, &rc);
+    if (rc != 0) break;
+    if (fp) FprintF(fp,"%.14g\n",value);
+    LastreS = value; /* Remember the last result (as in "bc" : . ) */
+    p = p->next;
+  }
+  if (retcode) *retcode = rc;
+  return value;
+}
+
+
+PUBLIC void *
+ParseTree(const char *cmds, int *retcode)
+{
+  int rc = 0;
+
+  /* Split cmds into a semi-colon separated list of commands */
+ 
+  cmd_list_t *cmdlist = ScanCmds(cmds);
+
+  /* Create RPN (Reverse Polish Notation) for each command */
+
+  int maxdepth = CreateRPN(cmdlist);
+
+  /* 
+     Create parse-tree out of RPN 
+     Note : 
+     If maxdepth were < 0, then RPNtoTree assigns maxdepth to rc
+     and ptree points to NULL 
+  */
+
+  Node_t *ptree = RPNtoTree(cmdlist, maxdepth, &rc);
+
+  /* Purge cmdlist */
+
+  int cmdno = 0;
+  cmd_list_t *p = cmdlist;
+  while (p) {
+    cmd_list_t *save_next = p->next;
+#if 0
+    FprintF(StderR,"#%d:[%s] rpn=[%s] (alloc=%d,actual=%d)\n",
+	    ++cmdno,p->cmd,p->rpn,
+	    p->rpn_alloc,STRLEN(p->rpn));
+#endif
+    FREE(p->cmd);
+    FREE(p->rpn);
+    FREE(p);
+    p = save_next;
+  }
+
+  /* Return parse tree */
+
+ finish:
+  if (rc != 0) {
+    DEF_IT;
+    FprintF(StderR,"***Error#%d in ParseTree(%s:%d): Unable to parse '%s'\n",
+	    rc,__FILE__,__LINE__,cmds?cmds:NIL);
+    (void) DelParseTree(ptree);
+    ptree = NULL;
+  }
+  if (retcode) *retcode = rc;
+  return ptree;
+}
+
+
+PUBLIC int
+DelParseTree(void *ptree)
+{
+  Node_t *p = ptree;
+  int cnt = 0;
+  while (p) {
+    Node_t *save_next = p->next;
+    FREE(p->name);
+    FREE(p);
+    cnt++;
+    p = save_next;
+  } /* while (p) */
+  return cnt;
+}
+
+
+PUBLIC double
+Run(const char *cmds
+    , int *retcode
+    , int (*prtfunc)(void *, const char *, ...) /* like fprintf */
+    , void *chan_out /* like stdout */
+    , void *chan_err /* like stderr */
+    , Bool output2devnull
+    )
+{
+  DEF_IT;
+  int rc = 0;
+  double value = 0;
+  InitTHSP();
+  if (output2devnull) {
+    prtfunc = (int (*)(void *, const char *, ...))fprintf;
+    chan_out = chan_err = devnull;
+  }
+  else {
+    if (!prtfunc) prtfunc = (int (*)(void *, const char *, ...))fprintf;
+    /* if (!chan_out) chan_out = stdout; */
+    if (!chan_err) chan_err = stderr;
+  }
+  SetTHSPio(it, prtfunc, chan_out, chan_err);
+  extern void init_RANDOM(); /* odb/lib/random_odb.c */
+  init_RANDOM();
+  initsym();
+  initfunc();
+  initOpStack();
+  if (cmds && STRLEN(cmds) > 0) {
+    void *ptree = ParseTree(cmds, &rc);
+    if (rc == 0) {
+      value = RunTree(ptree, chan_out, &rc);
+    }
+    initOpStack();
+    (void) DelParseTree(ptree);
+  }
+ finish:
+  if (retcode) *retcode = rc;
+  return value;
+}
+
+
+PRIVATE char *
+StripBlanks(const char *s, Bool remove_white_space)
+{
+  char *out = (char *)s;
+  if (s && remove_white_space) {
+    char *p = out = STRDUP(s);
+    while (*s) {
+      if (!IsBlank(*s)) *p++ = *s++;
+      else s++;
+    }
+    *p = '\0';
+  }
+  return out;
+}
+
+
+PUBLIC const char *
+StrCaseStr(const char *haystack, const char *needle, Bool ignore_case)
+{ /* Case insensitive strstr(), when ignore_case == true  */
+  const char *rc = NULL;
+  if (!needle || !*needle) {
+    rc = haystack;
+  }
+  else if (!ignore_case) {
+    rc = strstr(haystack, needle);
+  }
+  else {
+    /* Case insensitive -part */
+    if (haystack) {
+      for ( ; *haystack ; ++haystack ) {
+	if ( ToUpper(*haystack) == ToUpper(*needle) ) {
+	  /*
+	   * Matched starting char -- loop through remaining chars.
+	   */
+	  const char *h = haystack, *n = needle;
+	  for ( ; *h && *n ; ++h, ++n ) {
+	    if ( ToUpper(*h) != ToUpper(*n) ) break; /* for ( ; *h && *n ; ++h, ++n ) */
+	  } /* for ( ; *h && *n ; ++h, ++n ) */
+	  if ( !*n ) {
+	    /* matched all of 'needle' to null termination */
+	    rc = haystack; /* return the start of the match */
+	    break; /* for ( ; *haystack ; ++haystack ) */
+	  }
+	}
+      } /* for ( ; *haystack ; ++haystack ) */
+    }
+  }
+  return rc;
+}
+
+
+PUBLIC char *
+ReplaceSubStrings(const char *haystack, 
+		  const char *needle, 
+		  const char *repl_with, 
+		  Bool all_occurences,
+		  Bool remove_white_space,
+		  Bool ignore_case)
+{ 
+  /* 
+     Finds substring "needle" from the input string "haystack" and replaces
+     all or just the first occurence(s) with the "repl_with" string 
+
+     For example: 
+     - Replace the FIRST substring "count(*)" with "#1" in "count(*)/4 + cOUNt( * )"
+     - Remove white space (' ', '\t', '\n') as well, but BEFORE the replacement
+     - Ignore case
+
+     ReplaceSubStrings("count(*)/4 + cOUNt( * )", "count(*)", "#1", false, true, true) 
+     --> "#1/4+count(*)"
+  */
+
+  char *out = NULL;
+  if (haystack && needle && repl_with) {
+    char *phaystack = StripBlanks(haystack,remove_white_space);
+    int cnt = 0;
+    int lenhs = STRLEN(phaystack);
+    int len = lenhs;
+    int lenndl = STRLEN(needle);
+    int lenwith = STRLEN(repl_with);
+    const char *p = StrCaseStr(phaystack, needle, ignore_case);
+    while (p) {
+      cnt++;
+      len += (lenwith - lenndl);
+      if (!all_occurences) break;
+      p = StrCaseStr(p+lenndl, needle, ignore_case);
+    }
+    if (cnt == 0) { /* No match ==> no change */
+      out = STRDUP(phaystack);
+    }
+    else {
+      const char *x = phaystack;
+      char *s;
+      ALLOC(out,len+1);
+      s = out;
+      while (cnt-- >= 0) {
+	p = StrCaseStr(x, needle, ignore_case);
+	if (!p) p = phaystack + lenhs;
+	while (x < p) *s++ = *x++;
+	if (p == phaystack + lenhs) break;
+	strncpy(s,repl_with,lenwith);
+	s += lenwith;
+	x = p+lenndl;
+      }
+      *s = '\0';
+    }
+    if (phaystack != haystack) FREE(phaystack);
+  }
+  return out;
+}
+
+
+PUBLIC char *
+ReplaceSubStringsBetween(const char *str, 
+			 const char *mark_begin, const char *mark_end,
+			 const char *repl_with, 
+			 Bool all_occurences,
+			 Bool remove_white_space,
+			 Bool ignore_case)
+{
+  /* 
+     Replaces all (or only the first) occurences between
+     "str_begin" and "str_end" (inclusive) in "str" with string "repl_with" 
+
+     For example : 
+     - Replace text between all "<{" and "}>" markers in string "<{count(*)>}/4 + <{count( * )}>"
+     - Do NOT remove the white space (that would have removed BEFORE substitution)
+     - Be case sensitive i.e. do NOT ignore the case
+
+     ReplaceSubStringsBetween("<{count(*)>}/4 + <{count( * )}>", "<{", "}>", "#1", true, false, false) 
+     --> "#1/4 + #1"
+  */
+  
+  char *out = NULL;
+  if (str && mark_begin && mark_end && repl_with) {
+    char *pstr = StripBlanks(str,remove_white_space);
+    int cnt = 0;
+    int lenstr = STRLEN(pstr);
+    int len = lenstr;
+    int lenbegin = STRLEN(mark_begin);
+    int lenend = STRLEN(mark_end);
+    int lenwith = STRLEN(repl_with);
+    const char *p1 = StrCaseStr(pstr,mark_begin, ignore_case);
+    const char *p2 = p1 ? StrCaseStr(p1+lenbegin,mark_end, ignore_case) : NULL;
+    while (p1 && p2) {
+      cnt++;
+      len += (lenwith - (p2 + lenend - p1));
+      if (!all_occurences) break;
+      p2 += lenend;
+      p1 = StrCaseStr(p2,mark_begin, ignore_case);
+      p2 = p1 ? StrCaseStr(p1+lenbegin,mark_end, ignore_case) : NULL;
+    }
+    if (cnt == 0) {
+      out = STRDUP(pstr);
+    }
+    else {
+      const char *x = pstr;
+      char *s;
+      ALLOC(out,len+1);
+      s = out;
+      p2 = x;
+      while (cnt-- >= 0) {
+	p1 = StrCaseStr(p2, mark_begin, ignore_case);
+	if (p1) while (x < p1) *s++ = *x++;
+	p2 = p1 ? StrCaseStr(p1+lenbegin,mark_end, ignore_case) : NULL;
+	if (!p2) {
+	  p2 = pstr + lenstr;
+	  while (x < p2) *s++ = *x++;
+	  break;
+	}
+	strncpy(s,repl_with,lenwith);
+	s += lenwith;
+	x = (p2 += lenend);
+      }
+      *s = '\0';
+    }
+    if (pstr != str) FREE(pstr);
+  }
+  return out;
+}
+
+#include "info.h"
+
+PUBLIC char *
+GetLHSwhenSimpleExpr(const char *exprstr, int *oper, double *rhsvalue, 
+		     const void *Set, int nset)
+{
+  char *lhsstr = NULL;
+  if (oper) *oper = UNKNOWN;
+  if (rhsvalue) *rhsvalue = 0;
+  if (exprstr && oper && rhsvalue) {
+    int iret = 0;
+    Node_t *expr = ParseTree(exprstr, &iret);
+
+    if (expr && iret == 0) {
+      Node_t *p = expr;
+
+      if (p->numargs == 2 && p->args) { 
+	Node_t *lhs = p->args[0];
+	Node_t *rhs = p->args[1];
+
+	if (lhs && rhs &&
+	    lhs->numargs == 0 && rhs->numargs == 0) {
+	  Bool swap = false;
+
+	  if (p->kind != LE && p->kind != LT &&
+	      p->kind != GE && p->kind != GT &&
+	      p->kind != EQ && p->kind != NE) {
+	    /* Operator not one of (LE, GE, EQ, NE, LT, GT) */
+	    goto bailout;
+	  }
+
+	  if (Set && nset > 0) {
+	    const set_t *set = Set;
+	    int j;
+	    const char *s = NULL;
+
+	    s = lhs->name;
+	    if (lhs->kind == NAME && IS_DOLLAR(s) && !IS_USDHASH(s)) {
+	      for (j=0; j<nset; j++) {
+		if (strequ(set[j].name, s)) {
+		  lhs->value = set[j].value;
+		  lhs->kind = NUMBER;
+		  break;
+		}
+	      } /* for (j=0; j<nset; j++) */
+	    }
+
+	    s = rhs->name;
+	    if (rhs->kind == NAME && IS_DOLLAR(s) && !IS_USDHASH(s)) {
+	      for (j=0; j<nset; j++) {
+		if (strequ(set[j].name, s)) {
+		  rhs->value = set[j].value;
+		  rhs->kind = NUMBER;
+		  break;
+		}
+	      } /* for (j=0; j<nset; j++) */
+	    }
+	  } /* if (set && nset > 0) */
+
+	  if (lhs->kind == NUMBER && rhs->kind == NAME) {
+	    /* Interchange "NUMBER oper NAME" to "NAME oper NUMBER" */
+	    Node_t *tmp = lhs;
+	    lhs = rhs;
+	    rhs = tmp;
+	    swap = true;
+	  }
+
+	  if (lhs->kind != NAME || rhs->kind != NUMBER) {
+	    /* Expression not simple enough */
+	    goto bailout;
+	  }
+
+	  if (swap) {
+	    switch(p->kind) {
+	    case LE: p->kind = GE; break;
+	    case LT: p->kind = GT; break;
+	    case GE: p->kind = LE; break;
+	    case GT: p->kind = LT; break;
+	    default: /* do nothing */ break;
+	    } /* switch(p->kind) */
+	  }
+
+	  /* Plain sailing !! */
+	  lhsstr = STRDUP(lhs->name);
+	  *oper = p->kind;
+	  *rhsvalue = rhs->value;
+	} /* if (lhs && rhs && ... ) */
+
+      } /* if (p->numargs == 2 && p->args) */
+    } /* if (expr && iret == 0) */
+  bailout:
+    (void) DelParseTree(expr);
+  } /* if (exprstr && oper && rhsvalue) */
+  return lhsstr;
+}
+
diff --git a/odb/src/lib/fodb_checkviewreg.F90 b/odb/src/lib/fodb_checkviewreg.F90
new file mode 100644
index 0000000..1a5b228
--- /dev/null
+++ b/odb/src/lib/fodb_checkviewreg.F90
@@ -0,0 +1,33 @@
+SUBROUTINE fODB_checkviewreg(khandle, cdview, kret, using)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE odb_module
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: khandle
+character(len=*), intent(in) :: cdview
+INTEGER(KIND=JPIM), intent(out) :: kret
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+INTEGER(KIND=JPIM) j
+logical is_table, is_star
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('FODB_CHECKVIEWREG',0,ZHOOK_HANDLE)
+
+is_table = .FALSE.
+if (len(cdview) >= 1) is_table = (cdview(1:1) == '@')
+
+is_star = .FALSE.
+if (.not.is_table) then
+  if (len(cdview) >= 1) is_star = (cdview(1:1) == '*')
+endif
+
+if (is_table .or. is_star) then
+  kret = -1
+  do j=1,len_trim(cdview)
+    kret = kret - ichar(cdview(j:j)) ! a stupid negative return code
+  enddo
+else ! call ODB_addview() if cdview has not been registered yet
+  kret = ODB_gethandle(khandle, cdview, addview=.TRUE., using=using)
+endif
+
+IF (LHOOK) CALL DR_HOOK('FODB_CHECKVIEWREG',1,ZHOOK_HANDLE)
+END SUBROUTINE fODB_checkviewreg
diff --git a/odb/src/lib/fodb_propagate_env.F90 b/odb/src/lib/fodb_propagate_env.F90
new file mode 100644
index 0000000..920851b
--- /dev/null
+++ b/odb/src/lib/fodb_propagate_env.F90
@@ -0,0 +1,124 @@
+subroutine fodb_propagate_env(kenforce, kverbose)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+use odb_module ! , only : ODB_distribute, ODBMP_myproc, ODBMP_nproc, ODBMP_global
+use mpl_module, only : MPL_BUFFER_METHOD, MPL_MBX_SIZE, MPL_METHOD
+#ifdef NAG
+use f90_unix_proc, only: system
+#endif
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: kenforce ! =0 don't enforce, <> 0 enforce to reset the env.vars
+INTEGER(KIND=JPIM), intent(in) :: kverbose ! <> 0, do verbose output for proc == kverbose
+INTEGER(KIND=JPIM) :: icount_env, iret, j, iloc, iprop, ipid, imbxsize
+logical LLfirst_time, LLenforce, LLverbose
+character(len=8192) env, oldenv
+character(len=1024) pwd, home, file, deffile
+character(len=80)   cpid
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('FODB_PROPAGATE_ENV',0,ZHOOK_HANDLE)
+
+!write(0,*) ODBMP_myproc,': FODB_PROPAGATE_ENV : nproc, kenforce, kverbose',&
+!         &                                ODBMP_nproc, kenforce, kverbose
+
+if (ODBMP_nproc == 1) goto 9999
+LLenforce = (kenforce /= 0)
+
+iprop = 0                               ! Do not propagate by default
+CALL codb_getpid(ipid)
+write(cpid,*) ipid
+cpid = adjustl(trim(cpid))
+CALL codb_getenv('HOME',home)
+if (home == ' ') home = '.'
+deffile = trim(home)//'/odb_propagate_env.'//trim(cpid) ! If you do propagate, use this file by default
+file = deffile
+
+if (ODBMP_myproc == 1) then
+  CALL codb_getenv('ODB_PROPAGATE_ENV',env)
+!  write(0,*) ODBMP_myproc,': ODB_PROPAGATE_ENV="'//trim(env)//'"'
+  if (env /= ' ') then
+    iloc = scan(env,',')
+!    write(0,*) ODBMP_myproc,': iloc=',iloc
+    if (iloc > 1) then
+      read(env(1:iloc-1),*,err=8888,end=8888) iprop
+      read(env(iloc+1:),'(a)',err=8888,end=8888) file
+      file = adjustl(trim(file))
+    else
+      read(env,*,err=8888,end=8888) iprop
+    endif
+  endif
+  goto 300
+ 8888 continue
+   iprop = 0
+ 300  continue
+   if (file == ' ') file = deffile
+!   write(0,*) ODBMP_myproc,': file,iprop : "'//trim(file)//'"',iprop
+endif
+CALL ODBMP_global('SUM',iprop)
+
+if (iprop == 0) goto 9999
+
+LLverbose = (kverbose == ODBMP_myproc .or. kverbose == -1 &
+            & .or. iprop > 1 .or. iprop == -ODBMP_myproc)
+
+!write(0,*) ODBMP_myproc,': iprop, kverbose, LLverbose, ODBMP_myproc=', &
+!         &                 iprop, kverbose, LLverbose, ODBMP_myproc
+
+if (ODBMP_myproc == 1) then
+  CALL codb_remove_file(trim(file),iret)
+  CALL codb_system('printenv | sort > '//trim(file))
+  open(1,file=trim(file),status='old')
+  LLfirst_time = .TRUE.
+  icount_env = 0
+ 200  continue
+  do
+    if (LLfirst_time) then
+      read(1,'(a)',err=100,end=100)
+      icount_env = icount_env + 1
+    else
+      read(1,'(a)',err=100,end=100) env
+      iret = ODB_distribute(env)
+    endif
+  enddo
+ 100  continue
+  if (LLfirst_time) then
+    rewind(1)
+    if (LLverbose) write(0,*) ODBMP_myproc,': broadcasting icount_env=',icount_env
+    iret = ODB_distribute(icount_env)
+    LLfirst_time = .FALSE.
+    if (icount_env > 0) goto 200
+  endif
+  close(1)
+  CALL codb_remove_file(trim(file),iret)
+else
+  iret = ODB_distribute(icount_env)
+  if (LLverbose) write(0,*) ODBMP_myproc,': received icount_env=',icount_env
+  oldenv = ' '
+  do j=1,icount_env
+    iret = ODB_distribute(env)
+    iloc = scan(env,'=')
+    if (iloc > 0) then
+      iloc = iloc - 1
+      if (.not. LLenforce) CALL codb_getenv(env(1:iloc),oldenv)
+      if (LLenforce .or. oldenv == ' ') then
+        if (LLverbose) write(0,*) ODBMP_myproc,': Accepting '//env(1:iloc)
+        CALL codb_putenv(trim(env))
+      else
+        if (LLverbose) write(0,*) ODBMP_myproc,': Rejecting '//env(1:iloc)//' since already defined'
+      endif
+    endif
+  enddo
+endif
+! Finally, make sure the $PWD is set correctly
+CALL codb_getcwd(pwd)
+if (pwd == ' ') pwd = '.'
+CALL codb_putenv('PWD='//trim(pwd))
+if (LLverbose) write(0,*) ODBMP_myproc,': PWD was set to "'//trim(pwd)//'"'
+call util_igetenv('MPL_MBX_SIZE',MPL_MBX_SIZE,imbxsize)
+if (imbxsize /= MPL_MBX_SIZE) then
+  if (LLverbose) write(0,*) ODBMP_myproc,': Re-setting MPL_MBX_SIZE to ',imbxsize
+  call MPL_BUFFER_METHOD(MPL_METHOD,KMBX_SIZE=imbxsize)
+endif
+ 9999 continue
+IF (LHOOK) CALL DR_HOOK('FODB_PROPAGATE_ENV',1,ZHOOK_HANDLE)
+end subroutine fodb_propagate_env
diff --git a/odb/src/lib/forfunc.c b/odb/src/lib/forfunc.c
new file mode 100644
index 0000000..80630bd
--- /dev/null
+++ b/odb/src/lib/forfunc.c
@@ -0,0 +1,334 @@
+
+/* forfunc.c */
+
+#include "odb.h"
+
+/* Routines to ensure faster access to triplet (handle, poolno, "dataname") */
+
+/*--- Defines functions: "DBNAME" there only for diagnostix
+
+  Registration: [returns hash index]
+  put_forfunc(funcs, handle, "DBNAME", poolno, it, "dataname");
+
+  Get funcs pointer: do abort, if not found
+  funcs = get_forfunc(handle, "DBNAME", poolno, it, "dataname", 1);
+
+  Get funcs pointer: do *not* abort, if not found
+  funcs = get_forfunc(handle, "DBNAME", poolno, it, "dataname", 0);
+
+  Disable particular funcs at triplet: [returns nothing; may become active again (dyn.linking)]
+  nullify_forfunc(handle, "DBNAME",poolno, it, "dataname");
+  
+  Print contents of hash-tables: (is also Fortran-callable)
+  integer enforce
+  character(len=*),parameter :: msg = 'Print message'
+  enforce = 1
+  CALL print_forfunc(enforce, msg)
+
+  ---*/
+
+#ifndef FORFUNC_HASHSIZE
+#define FORFUNC_HASHSIZE 1021U
+#endif
+
+PRIVATE uint FORFUNC_hashsize = 0;
+
+typedef struct _FORFUNC_Hash_Table {
+  int handle;
+  int poolno;
+  char *dataname;
+  ODB_Funcs *key;
+  struct _FORFUNC_Hash_Table *collision;
+} FORFUNC_Hash_Table;
+
+PRIVATE FORFUNC_Hash_Table **FORFUNC_hashtable = NULL;
+
+PRIVATE uint
+Hash(int handle, int poolno, const char *s)
+{ 
+  uint hashval = 100 * poolno + handle; /* handle typically << 100 */
+  for (; *s ; s++) {
+    hashval = (*s) + 31U * hashval;
+  }
+  hashval = hashval % FORFUNC_hashsize;
+  return hashval;
+}
+
+
+PRIVATE void
+HashInit()
+{
+  if (!FORFUNC_hashtable) {
+    FORFUNC_Hash_Table **tmp_FORFUNC_hashtable = NULL;
+    int inumt = get_max_threads_();
+    int it;
+    char *p = getenv("ODB_FORFUNC_HASHSIZE");
+    if (p) {
+      FORFUNC_hashsize = atoi(p);
+      if (FORFUNC_hashsize <= 0) FORFUNC_hashsize = FORFUNC_HASHSIZE;
+    }
+    else
+      FORFUNC_hashsize = FORFUNC_HASHSIZE;
+    ALLOC(tmp_FORFUNC_hashtable, inumt + 1); /* entries 0 for TABLEs, 1..inumt for VIEWs */
+    for (it = 0; it <= inumt ; it++) {
+      CALLOC(tmp_FORFUNC_hashtable[it], FORFUNC_hashsize);
+    }
+    FORFUNC_hashtable = tmp_FORFUNC_hashtable;
+  }
+}
+
+PRIVATE FORFUNC_Hash_Table *
+NewEntry(void)
+{
+  FORFUNC_Hash_Table *p;
+  ALLOC(p, 1);
+  p->handle    = 0;
+  p->poolno    = 0;
+  p->dataname  = NULL;
+  p->key       = NULL;
+  p->collision = NULL;
+  return p;
+}
+
+PUBLIC void
+init_FORFUNC_lock()
+{
+  HashInit();
+}
+
+/*---
+  Registration: [returns hash index]
+  put_forfunc(funcs, handle, "DBNAME", poolno, it, "dataname");
+  ---*/
+
+PUBLIC int
+put_forfunc(ODB_Funcs *funcs,
+            int handle,
+	    const char *dbname,
+            int poolno, 
+	    int it,
+            const char *dataname)
+{
+  int rc = 0;
+  uint index;
+  FORFUNC_Hash_Table *p;
+
+  rc = index = Hash(handle, poolno, dataname);
+  if (IS_TABLE(dataname)) it = 0;
+  p = &FORFUNC_hashtable[it][index];
+
+  while (p && p->dataname) {
+    if (p->handle == handle &&
+	p->poolno == poolno &&
+	strequ(p->dataname, dataname)) {
+      extern int ODBstatic_mode;
+      if (p->key && ODBstatic_mode) {
+	/* Do not allow reassignment in static mode; be more relaxed in dynamic one */
+	if (p->key != funcs) {
+	  fprintf(stderr,
+		  "put_forfunc: (handle,dbname,poolno,it,dataname)="
+		  "(%d,%s,%d,%d,'%s') already assigned to address=%p, funcs=%p\n",
+		  p->handle, dbname, p->poolno, it, p->dataname, p->key, funcs);
+	  rc = -1;
+	  RAISE(SIGABRT);
+	}
+	goto finish; /* Already in list */
+      }
+      else {
+	/* otherwise: Re-use this entry (had been disabled) */
+	FREE(p->dataname);
+	break;
+      }
+    }
+    if (!p->collision) p->collision = NewEntry();
+    p = p->collision;
+  } /* while (p && p->dataname) */
+
+  p->handle   = handle;
+  p->poolno   = poolno;
+  p->dataname = STRDUP(dataname);
+  p->key      = funcs;
+
+ finish:
+  return rc;
+}
+
+
+/*---
+  Get funcs pointer:
+  funcs = get_forfunc(handle, "DBNAME", poolno, it, "dataname", do_abort);
+  ---*/
+
+
+PUBLIC ODB_Funcs *
+get_forfunc(int handle,
+	    const char *dbname,
+            int poolno, 
+            int it, 
+            const char *dataname,
+	    int do_abort)
+{
+  ODB_Funcs *retfunc = NULL;
+  uint index;
+  FORFUNC_Hash_Table *p;
+
+  index = Hash(handle, poolno, dataname);
+  if (IS_TABLE(dataname)) it = 0;
+  p = &FORFUNC_hashtable[it][index];
+
+  if (!p->dataname) {
+    if (do_abort) {
+      fprintf(stderr,
+	      "get_forfunc: Unregistered (handle,dbname,poolno,it,dataname)="
+	      "(%d,%s,%d,%d,'%s')\n",
+	      handle,dbname,poolno,it,dataname);
+      RAISE(SIGABRT);
+    }
+  }
+  else {
+#ifndef NECSX
+    while (p && p->dataname) {
+#else
+    while (p!=NULL && p->dataname!=NULL) {
+#endif
+      if (p->handle == handle &&
+	  p->poolno == poolno &&
+#ifndef NECSX
+	  strequ(p->dataname, dataname)) {
+#else
+          /* strequ(p->dataname, dataname) */
+          p->dataname!=0 &&
+          dataname!=0 &&
+          strcmp(p->dataname,dataname) == 0
+                                         ) {
+#endif
+	if (!p->key) {
+	  if (do_abort) {
+	    fprintf(stderr,
+		    "get_forfunc: In (handle,dbname,poolno,it,dataname)="
+		    "(%d,%s,%d,%d,'%s') key-address was NULL\n",
+		    handle,dbname,poolno,it,dataname);
+	    RAISE(SIGABRT);
+	  }
+	}
+	else {
+	  /* Valid and found */
+	  retfunc = p->key;
+	}
+	break;
+      }
+      if (p->collision) 
+	p = p->collision;
+      else {
+	if (do_abort) {
+	  fprintf(stderr,
+		  "get_forfunc: (handle,dbname,poolno,it,dataname)="
+		  "(%d,%s,%d,%d,'%s') unregistered\n",
+		  handle,dbname,poolno,it,dataname);
+	  RAISE(SIGABRT);
+	}
+	break;
+      }
+    } /* while (p && p->dataname) */
+  }
+
+  return retfunc;
+}
+
+/*---
+  Disable particular funcs at triplet: [returns nothing; may become active again (dyn.linking)]
+  nullify_forfunc(handle, "DBNAME", poolno, it, "dataname");
+  ---*/
+
+PUBLIC void
+nullify_forfunc(int handle,
+		const char *dbname,
+		int poolno, 
+		int it,
+		const char *dataname)
+{
+  uint index;
+  FORFUNC_Hash_Table *p;
+
+  index = Hash(handle, poolno, dataname);
+  if (IS_TABLE(dataname)) it = 0;
+  p = &FORFUNC_hashtable[it][index];
+
+  while (p && p->dataname) {
+    if (p->handle == handle &&
+	p->poolno == poolno &&
+	strequ(p->dataname, dataname)) {
+      p->key = NULL; /* Disable (this entry should be the only one) */
+      break;
+    }
+    if (p->collision) 
+      p = p->collision;
+    else {
+      break;
+    }
+  } /* while (p && p->dataname) */
+}
+
+/*---
+  Print contents of hash-tables: (is also Fortran-callable)
+  CALL print_forfunc(enforce, msg)
+  print_forfunc_(&enforce, msg, strlen(msg));
+  ---*/
+
+PUBLIC void
+print_forfunc_(const int *enforce,
+	       const char *msg,
+	       /* Hidden arguments */
+	       int msg_len)
+{
+  DECL_FTN_CHAR(msg);
+  int print_it = *enforce;
+  int j;
+  int entries=0;
+  int hits=0;
+  char *env = getenv("ODB_FORFUNC_DEBUG");
+  
+  if (env) {
+    int ienv = atoi(env);
+    ienv = MAX(0,MIN(1,ienv));
+    print_it |= ienv;
+  }
+
+  if (!print_it) return;
+
+  ALLOC_FTN_CHAR(msg);
+
+  if (msg_len > 0) fprintf(stderr,"print_forfunc_: %s\n",p_msg);
+  fprintf(stderr,
+	  "print_forfunc_: hashsize=%u, hashtable at %p\n",
+	  FORFUNC_hashsize, FORFUNC_hashtable);
+
+  if (FORFUNC_hashtable) {
+    int inumt = get_max_threads_();
+    int it;
+    for (it = 0; it <= inumt ; it++) {
+      for (j=0; j<FORFUNC_hashsize; j++) {
+	FORFUNC_Hash_Table *p = &FORFUNC_hashtable[it][j];
+	int k=1;
+	if (p->dataname) entries++;
+	while (p && p->dataname) {
+	  fprintf(stderr,
+		  "hash#%d [hit#%d] : (hdle=%d,pool=%d,it=%d,'%s') maps to address=%p\n",
+		  j,k,
+		  p->handle, 
+		  p->poolno, 
+		  it, 
+		  p->dataname ? p->dataname : NIL, 
+		  p->key);
+	  p = p->collision;
+	  k++;
+	  hits++;
+	} /* while (p) */
+      } /* for (j=0; j<FORFUNC_hashsize; j++) */
+    } /* if (FORFUNC_hashtable) */
+  }
+
+  fprintf(stderr,"print_forfunc_: Total %d hits in %d hash-entries\n",hits,entries);
+
+  FREE_FTN_CHAR(msg);
+}
diff --git a/odb/src/lib/funcs.c b/odb/src/lib/funcs.c
new file mode 100644
index 0000000..a75c2a4
--- /dev/null
+++ b/odb/src/lib/funcs.c
@@ -0,0 +1,482 @@
+
+/* funcs.c */
+
+#include "odb.h"
+#include "evaluate.h"
+#include "node.h"
+#include "pcma_extern.h"
+
+#define FUNCS_C 1
+#include "funcs.h"
+
+#define CHASE_A_BUG 0
+
+#if CHASE_A_BUG == 1
+/* export from ../include/info.h */
+extern FILE *ODBc_get_debug_fp(); /* Returns current debug file pointer */
+#else
+#undef CHASE_A_BUG
+#endif
+
+PRIVATE int
+cmpstr(const void *A, const void *B)
+{
+  const funcs_t *a = A;
+  const funcs_t *b = B;
+  return strcasecmp(a->name, b->name);
+}
+
+
+PRIVATE int
+print1func(void *fp, const funcs_t *pf)
+{
+  int len = 0;
+  if (fp && pf) {
+    DEF_IT;
+    const thsafe_parse_t *thsp = GetTHSP();
+    const char *s = pf->name;
+    int j, nargs = pf->numargs;
+#if 0
+    FprintF(fp,"@%p>> %s ; nargs=%d\n", pf, s, nargs);
+#else
+    len += FprintF(fp,"   %s",s);
+    if (nargs > 0) {
+      for (j=1; j<=nargs; j++) {
+	len += FprintF(fp,"%carg#%d",(j==1)?'(':',',j);
+      }
+      len += FprintF(fp,")");
+    }
+    else if (nargs == 0) {
+      len += FprintF(fp,"()");
+    }
+    else {
+      len += FprintF(fp,"(<var.args>)");
+    }
+#endif
+  }
+  return len;
+}
+
+
+PUBLIC void
+printfunc(void *fp)
+{
+  if (fp) {
+    DEF_IT;
+    const thsafe_parse_t *thsp = GetTHSP();
+    int totlen = 0;
+    int j;
+    if (NfuncS == 0) initfunc(); /* Normally not needed */
+    FprintF(fp,"=== Currently available functions:\n");
+    for (j=0; j<NfuncS; j++) {
+      const funcs_t *pf = &Func[j];
+      totlen += print1func(fp, pf);
+      if (totlen > 60) {
+	FprintF(fp,"\n");
+	totlen = 0;
+      }
+    } /* for (j=0; j<NfuncS; j++) */
+    if (totlen > 0) FprintF(fp,"\n");
+  }
+}
+
+
+PUBLIC void
+initfunc()
+{
+  if (NfuncS == 0) {
+    DEF_IT;
+    const thsafe_parse_t *thsp = GetTHSP();
+    funcs_t *pf = Func;
+    while (pf->name) {
+      if (!pf->u.compile_time) pf->u.compile_time = pf->f.run_time;
+      NfuncS++;
+      pf++;
+    }
+    qsort(Func, NfuncS, sizeof(funcs_t), cmpstr);
+#if 0
+    printfunc(StderR);
+#endif
+  } /* if (NfuncS == 0) */
+}
+
+
+PUBLIC const void *
+getfunc(const char *s, int numargs)
+{
+  funcs_t *pf = NULL;
+  funcs_t key;
+#if 0
+  if (s && *s == '_') s++; /* Was an aggregate function */
+#endif
+  key.name = (char *)s;
+  pf = bsearch(&key, Func, NfuncS, sizeof(funcs_t), cmpstr);
+  if (!(pf && (pf->numargs == numargs || pf->numargs == -1))) pf = NULL;
+  return pf;
+}
+
+
+PUBLIC Bool
+checkfunc(const char *s, int numargs)
+{
+  const funcs_t *p = getfunc(s, numargs);
+  return p ? true : false;
+}
+
+
+PUBLIC double
+callfunc(void *pnode, int *retcode)
+{
+  DEF_IT;
+  const thsafe_parse_t *thsp = GetTHSP();
+  int rc = 0;
+  double value = RMDI;
+  double *d = NULL;
+  Node_t *p = pnode;
+  if (p) {
+#if defined(CHASE_A_BUG)
+    FILE *fp_echo = ODBc_get_debug_fp();
+#endif
+    const char *s = p->name;
+    int numargs = p->numargs;
+    const funcs_t *pf = p->funcptr ? p->funcptr : getfunc(s, numargs);
+#if defined(CHASE_A_BUG)
+    ODB_fprintf(fp_echo, "callfunc: '%s' %d pf=%p\n",s,numargs,pf);
+#endif
+    if (pf) {
+      Bool funcresult_to_degrees = (pf->deg2rad > 0 && ((pf->deg2rad & 0x2) == 0x2)) ? true : false;
+      int j, nargs = (pf->numargs == -1) ? numargs : pf->numargs;
+      Bool use_vararg = (pf->numargs == -1) ? true : false;
+#if defined(CHASE_A_BUG)
+      ODB_fprintf(fp_echo, "callfunc('%s', numargs=%d) : expected # of args = %d\n",
+		  s, numargs, nargs);
+#endif
+      if (numargs != nargs) {
+	ERROR1("callfunc() : # of args mismatch in function %s",-1,s);
+      }
+#if defined(CHASE_A_BUG)
+      ODB_fprintf(fp_echo, "callfunc: --> %s(",s);
+#endif
+      if (nargs > 0) {
+	Bool arg_to_radians = (pf->deg2rad > 0 && ((pf->deg2rad & 0x1) == 0x1)) ? true : false;
+	CALLOC(d,nargs);
+	for (j=0; j<nargs; j++) {
+	  d[j] = RunNode(p->args[j], &rc);
+	  if (rc != 0) goto finish;
+	  if (arg_to_radians) d[j] = D2R(d[j]);
+	  else if (pf->deg2rad < 0 && ABS(pf->deg2rad) != j+1) { /* [hack] */
+	    d[j] = D2R(d[j]);
+	  }
+#if defined(CHASE_A_BUG)
+	  ODB_fprintf(fp_echo, "%s%.14g",(j>0) ? "," : "",d[j]); 
+#endif
+	}
+      }
+#if defined(CHASE_A_BUG)
+      ODB_fprintf(fp_echo, ")");
+#endif
+      if (use_vararg) {
+	value = pf->u.vararg(nargs, d);
+      }
+      else {
+	switch (nargs) {
+	case 0: value = pf->u.zeroarg (); break;
+	case 1: value = pf->u.onearg  (d[0]); break;
+	case 2: value = pf->u.twoarg  (d[0], d[1]); break;
+	case 3: value = pf->u.threearg(d[0], d[1], d[2]); break;
+	case 4:	value = pf->u.fourarg (d[0], d[1], d[2], d[3]); break;
+	case 5:	value = pf->u.fivearg (d[0], d[1], d[2], d[3], d[4]); break;
+	case 6:	value = pf->u.sixarg  (d[0], d[1], d[2], d[3], d[4], d[5]); break;
+	default: value = pf->u.vararg (nargs, d); break;
+	} /* switch (nargs) */
+      }
+      if (funcresult_to_degrees) value = R2D(value);
+#if defined(CHASE_A_BUG)
+      ODB_fprintf(fp_echo, " = %.14g\n",value);
+#endif
+    }
+    else {
+      ERROR1("callfunc(): Unable to locate function %s",-2,s);
+    } /* if (pf) else ... */
+  } /* if (p) */
+  else {
+    ERROR("callfunc(): Nothing to run ???",-3);
+  }
+ finish:
+  FREE(d);
+  if (retcode) *retcode = rc;
+  return value;
+}
+
+
+PUBLIC const char *
+odb_datetime_(int *date_out, int *time_out)
+{ /* Thread safe if initialized from within codb_init_omp_locks_() */
+  int Date=0, Time=0;
+  time_t tp;
+  const int bufsize = 80;
+  static char **buf = NULL;
+  int it = get_thread_id_();
+
+  if (!buf) {
+    int j, inumt = get_max_threads_();
+    CALLOC(buf,inumt);
+    for (j=0; j<inumt; j++) {
+      CALLOC(buf[j],bufsize);
+    }
+  }
+
+  /* Are the next two lines re-entrant & thread safe ?? */
+  time(&tp);
+  strftime(buf[--it], bufsize, "%Y%m%d %H%M%S", localtime(&tp));
+
+  if (date_out || time_out) {
+    sscanf(buf[it],"%d %d", &Date, &Time);
+    if (date_out) *date_out = Date;
+    if (time_out) *time_out = Time;
+  }
+
+  return buf[it];
+}
+
+
+PRIVATE int latlon_rad = -2; /* Not initialized */
+
+PUBLIC int
+codb_change_latlon_rad_(const int *newvalue)
+{ /* Not thread safe */
+  int oldvalue = latlon_rad;
+  if (newvalue) {
+    latlon_rad = *newvalue;
+    if (latlon_rad != -1 &&
+	latlon_rad !=  0 && 
+	latlon_rad !=  1) latlon_rad = -1; /* i.e. as if undefined */
+  }
+  return oldvalue;
+}
+
+PUBLIC void
+codb_init_latlon_rad_()
+{ /* Not thread safe, but executed once only */
+  if (latlon_rad == -2) {
+    /* The same as is ../compiler/odb98.c */
+    char *p = getenv("ODB_LATLON_RAD"); /* 1 = radians, 0 = not-radians i.e. degrees, -1 = undefined */
+    if (p) {
+      latlon_rad = atoi(p);
+      if (latlon_rad != -1 &&
+	  latlon_rad !=  0 && 
+	  latlon_rad !=  1) latlon_rad = -1; /* i.e. as if undefined */
+    }
+    else
+      latlon_rad = -1; /* i.e. as if undefined */
+  }
+}
+
+PUBLIC double
+ODB_lldegrees(double d)
+{
+  /* Convert argument 'd' to degrees, unless 
+     the environment variable $ODB_LATLON_RAD was set 0
+     indicating that no conversion is needed, since 'd' 
+     was already supplied in degrees */
+  if (latlon_rad != 0) d = R2D(d);
+  /* if (d > 180) d -= 360; */
+  return d;
+}
+
+PUBLIC double
+ODB_degrees(double d)
+{
+  /* Convert argument 'd' to degrees, unconditionally */
+  d = R2D(d);
+  return d;
+}
+
+PUBLIC double
+ODB_llradians(double d)
+{
+  /* Convert argument 'd' to radians, unless 
+     the environment variable $ODB_LATLON_RAD was set 1
+     indicating that no conversion is needed, since 'd'
+     was already supplied in radians */
+  if (latlon_rad != 1) d = D2R(d);
+  /* if (d > pi) d -= 2*pi; */
+  return d;
+}
+
+PUBLIC double
+ODB_radians(double d)
+{
+  /* Convert argument 'd' to radians, unconditionally */
+  d = D2R(d);
+  return d;
+}
+
+PUBLIC double
+ODB_timestamp(double indate, double intime)
+{ /* Merge "YYYYMMDD" and "HHMMSS" into "YYYYMMDDHHMMSS" */
+  double outstamp = RMDI; /* Initialized to missing data indicator ; indicates error */
+  if (indate >= 0 && indate <= INT_MAX &&
+      intime >= 0 && intime <= 240000) {
+    long long int lldate = (long long int)indate;
+    long long int lltime = (long long int)intime;
+    long long int tstamp = lldate * 1000000ll + lltime;
+    outstamp = tstamp;
+    outstamp = trunc(outstamp);
+  }
+  return outstamp;
+}
+
+PUBLIC double
+ODB_basetime(double indate, double intime)
+{ /* Merge "YYYYMMDD" and "HHMMSS" into "YYYYMMDDHH" */
+  double outstamp = RMDI; /* Initialized to missing data indicator ; indicates error */
+  if (indate >= 0 && indate <= INT_MAX &&
+      intime >= 0 && intime <= 240000) {
+    long long int lldate = (long long int)indate;
+    long long int lltime = (long long int)intime;
+    long long int tstamp = lldate * 1000000ll + (lltime/10000ll);
+    outstamp = tstamp;
+    outstamp = trunc(outstamp);
+  }
+  return outstamp;
+}
+
+PUBLIC double
+ODB_now()
+{
+  int indate, intime;
+  (void) odb_datetime_(&indate, &intime);
+  return ODB_timestamp(indate, intime);
+}
+
+PUBLIC double
+ODB_date_now()
+{
+  int indate;
+  (void) odb_datetime_(&indate, NULL);
+  return (double)indate;
+}
+
+PUBLIC double
+ODB_time_now()
+{
+  int intime;
+  (void) odb_datetime_(NULL, &intime);
+  return (double)intime;
+}
+
+PUBLIC double
+ODB_binlo(double x, double deltax)
+{
+  return binlo(x, deltax);
+}
+
+PUBLIC double
+ODB_binhi(double x, double deltax)
+{
+  return binhi(x, deltax);
+}
+
+PRIVATE Boolean
+InGenList(double target, double begin, double end, double step)
+{
+  if (begin > end) {
+    /* Swap begin with end and negate step */
+    double tmp = begin;
+    begin = end;
+    end = tmp;
+    step = -step;
+  }
+  if (target < begin || target > end) return false; /* definitely not inside */
+  {
+    double j;
+    for (j=begin; j<=end; j += step) {
+      if (target == j) return true; /* found exact match */
+      if (step <= 0) break; /* Illegal step; ABS(step) must be > 0 */
+    }
+  }
+  return false; /* not inside */
+}
+
+PUBLIC double
+ODB_InGenList(double target, double begin, double end, double step)
+{
+  return (double) InGenList(target, begin, end, step);
+}
+
+PUBLIC double
+ODB_pi()
+{
+  return pi; /* A macro #define from privpub.h */
+}
+
+PUBLIC double
+ODB_speed(double u, double v)
+{
+  return Speed(u,v);
+}
+
+PUBLIC double
+ODB_dir(double u, double v)
+{
+  return Dir(u,v);
+}
+
+PUBLIC double
+ODB_ucom(double dd, double ff)
+{
+  return Ucom(dd,ff);
+}
+
+PUBLIC double
+ODB_vcom(double dd, double ff)
+{
+  return Vcom(dd,ff);
+}
+
+PUBLIC double
+ODB_myproc()
+{ /* Thread-safe, since static variable initialized once, outside the OpenMP parallel region */
+  static int myproc = -1;
+  if (myproc == -1) codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+  return myproc;
+}
+
+PUBLIC double
+ODB_nproc()
+{ /* Thread-safe, since static variable initialized once, outside the OpenMP parallel region */
+  static int nproc = -1;
+  if (nproc == -1) codb_procdata_(NULL, &nproc, NULL, NULL, NULL);
+  return nproc;
+}
+
+PUBLIC double
+ODB_pid()
+{ /* Thread-safe, since static variable initialized once, outside the OpenMP parallel region */
+  static int pid = -1;
+  if (pid == -1) codb_procdata_(NULL, NULL, &pid, NULL, NULL);
+  return pid;
+}
+
+PUBLIC double
+ODB_tid()
+{ /* Thread-safe */
+  int tid = get_thread_id_();
+  return tid;
+}
+
+PUBLIC double
+ODB_nthreads()
+{ /* Thread-safe */
+  int nthreads = get_max_threads_();
+  return nthreads;
+}
+
+PUBLIC void
+init_proc_funcs()
+{
+  (void) ODB_myproc();
+  (void) ODB_nproc();
+  (void) ODB_pid();
+}
diff --git a/odb/src/lib/fwrite_iomap.F90 b/odb/src/lib/fwrite_iomap.F90
new file mode 100644
index 0000000..a3a685d
--- /dev/null
+++ b/odb/src/lib/fwrite_iomap.F90
@@ -0,0 +1,168 @@
+SUBROUTINE fwrite_iomap(khandle, kret)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+USE odb_module , tmp_fwrite_iomap => fwrite_iomap
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)    :: khandle
+INTEGER(KIND=JPIM), intent(out)   :: kret
+
+INTEGER(KIND=JPIM), parameter :: fmt  = 1 ! Format/flavor of iomap-file(s)
+INTEGER(KIND=JPIM), parameter :: npad = 1 ! Always pad data bytes to the next INTEGER*4 boundary
+INTEGER(KIND=JPIM), parameter :: lenmult = 1 ! Unit of offsets & lengths is 1 byte
+character(len=*), parameter :: NL  = char(10)  ! Newline-character
+character(len=*), parameter :: TAB = char( 9)  ! TAB-character
+INTEGER(KIND=JPIM), parameter :: EOR = -1 ! End of record -marker
+INTEGER(KIND=JPIM) :: jfblk, io, rc, ntables, npools, ilen, nfblk
+INTEGER(KIND=JPIM) :: jt, j, jj, ipools, imax, imin, ngrpsize, io_method, naid
+INTEGER(KIND=JPIM) :: nrows, ncols
+INTEGER(KIND=JPIM) :: ifileno, ioffset
+logical LLfix
+!!logical LL_dormant
+character(len=80) ::  CLbuf
+character(len=maxfilen) :: CLiomap_file
+character(len=maxvarlen), allocatable :: cltable(:)
+INTEGER(KIND=JPIM), POINTER :: ioaid(:,:,:) ! Shorthand
+INTEGER(KIND=JPIM), ALLOCATABLE :: ipoolset(:)
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('FWRITE_IOMAP',0,ZHOOK_HANDLE)
+kret = 0
+
+naid = db(khandle)%naid
+ioaid => db(khandle)%ioaid
+
+if (naid > 0 .AND. ODBMP_myproc == 1) then ! Metadata written by PE#1 only
+  ntables = ODB_getnames(khandle, '*', 'table')
+  allocate(cltable(ntables))
+  ntables = ODB_getnames(khandle, '*', 'table', cltable)
+
+  npools = db(khandle)%glbNpools
+  allocate(ipoolset(npools))
+
+  nfblk = db(khandle)%nfileblocks
+  io_method = db(khandle)%io_method
+
+  IOMAP_BLOCK_LOOP: do jfblk=1,nfblk
+    if (      COUNT(ioaid(:,:,IOAID_FBLOCK) == jfblk) > 0  ) then
+      imax = MAXVAL(ioaid(:,:,IOAID_POOLNO), &
+       & MASK=ioaid(:,:,IOAID_FBLOCK) == jfblk) 
+      imin = MINVAL(ioaid(:,:,IOAID_POOLNO), &
+       & MASK=ioaid(:,:,IOAID_FBLOCK) == jfblk) 
+      imin = max(1,imin)
+      ipools = imax - imin + 1
+    else
+      ipools = 0
+    endif
+    
+!!    if (ipools <= 0) cycle IOMAP_BLOCK_LOOP ! Quite bad ;-( Shouldn't we abort ??
+
+    CLiomap_file = db(khandle)%ciomap(jfblk)
+    ngrpsize = db(khandle)%grpsize(jfblk)
+    io = -1
+    write(0,'(a)') "Opening IOMAP-file='"//trim(CLiomap_file)//"' for writing"
+    CALL cma_open(io, trim(CLiomap_file), "w", rc)
+
+    write(CLbuf,'(i15)') fmt
+    write(0,'(a,i1)') TAB//'Format=',fmt
+    ilen = len_trim(CLbuf)
+    CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+    CLbuf = CLiomap_file
+    ilen = len_trim(CLbuf)
+    CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+    write(CLbuf,'(3i15)') ntables, ipools, ngrpsize ! Can't have Npools here
+    ilen = len_trim(CLbuf)
+    CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+    write(CLbuf,'(3i15)') npad, io_method, lenmult
+    ilen = len_trim(CLbuf)
+    CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+    write(0,'(a,i2,a,i3,a,i5,a,i5)') &
+     & TAB//'File block#',jfblk,': tables=',ntables,&
+     & ', maxpools=',ipools,', grpsize=',ngrpsize 
+
+    TABLE_LOOP: do jt=1,ntables
+      ncols = MAXVAL(ioaid(1:npools,jt,IOAID_NCOLS))
+      if (ncols <= 0) ncols = EOR
+      write(CLbuf,'(2i15,1x,a)') jt, ncols, trim(cltable(jt))
+      ilen = len_trim(CLbuf)
+      CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+      ipoolset(:) = 0
+      do j=1,npools
+         if ( ioaid(j,jt,IOAID_FBLOCK) == jfblk .AND. &
+            & ioaid(j,jt,IOAID_LENGTH) > 0 ) then
+           ipoolset(j) = j
+         endif
+      enddo
+
+      !-- 26/6/2008 by SS: ioaid(j,jt,IOAID_FILENO) could be wrong due to 
+      !   $ODB_IO_BACKUP_ENABLE being zero (0) and use odb odbprune-script. Fix it.
+      !   Discovered by Yannick Tremolet, ECMWF, when running 48h (long) time window 4dvar:
+      !   He specified too low NPES_AN in prepIFS and then changed the # of PEs
+      !   on the fly in SMS. As result odbprune-script stripped off some data files ;-(
+
+      LLfix = .FALSE.
+      ifileno = 0
+      ioffset = 2147483647
+
+      do jj=1,npools
+        j = ipoolset(jj)
+        if ( j > 0 ) then
+          if (ioaid(j,jt,IOAID_OFFSET) < ioffset) then ! New file
+            LLfix = (ioaid(j,jt,IOAID_FILENO) /= ioaid(j,jt,IOAID_POOLNO))
+            if (LLfix) ifileno = ioaid(j,jt,IOAID_POOLNO) ! This is the fix
+          endif
+          if (LLfix) ioaid(j,jt,IOAID_FILENO) = ifileno
+          ioffset = ioaid(j,jt,IOAID_OFFSET) + ioaid(j,jt,IOAID_LENGTH)
+        endif
+      enddo ! jj=1,npools
+
+!!      LL_dormant = .TRUE.
+      do jj=1,npools
+        j = ipoolset(jj)
+        if ( j > 0 ) then
+          write(CLbuf,'(5i15)') &
+           & ioaid(j,jt,IOAID_POOLNO),  &! Original LOCAL pool#
+           & ioaid(j,jt,IOAID_FILENO),  &! Now fixed i.e. $NPES_AN 
+           & ioaid(j,jt,IOAID_OFFSET), &
+           & ioaid(j,jt,IOAID_LENGTH), &
+           & ioaid(j,jt,IOAID_NROWS) 
+          ilen = len_trim(CLbuf)
+          CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+!!          LL_dormant = .FALSE. ! At least one record
+        endif ! if (ioaid(j,jt,IOAID_FBLOCK) == jfblk ...
+      enddo ! jj=1,npools
+
+!!      if (LL_dormant) then
+!!        write(0,'(a)') TAB//">>> Warning: Dormant table='"//trim(cltable(jt))//"'"
+!!      endif
+
+      write(CLbuf,'(5i15)') EOR, EOR, EOR, EOR, EOR
+      ilen = len_trim(CLbuf)
+      CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+    enddo TABLE_LOOP ! jt=1,ntables
+
+    !-- End of tables (and EOF) for this iomap-file
+    write(CLbuf,'(2i15,1x,a)') EOR, EOR, 'EOF'
+    ilen = len_trim(CLbuf)
+    CALL cma_writeb(io, CLbuf(1:ilen)//NL, ilen+1, rc)
+
+    CALL cma_close(io, rc)
+    io = -1
+  enddo IOMAP_BLOCK_LOOP
+
+  deallocate(ipoolset)
+  deallocate(cltable)
+  nullify(ioaid)
+endif
+IF (LHOOK) CALL DR_HOOK('FWRITE_IOMAP',1,ZHOOK_HANDLE)
+
+END SUBROUTINE fwrite_iomap
+
diff --git a/odb/src/lib/gauaw_odb.F90 b/odb/src/lib/gauaw_odb.F90
new file mode 100644
index 0000000..4b2d354
--- /dev/null
+++ b/odb/src/lib/gauaw_odb.F90
@@ -0,0 +1,141 @@
+SUBROUTINE GAUAW_ODB(PA,PW,K,KRET)
+
+!**** *GAUAW_ODB* - COMPUTE ABSCISSAS AND WEIGHTS FOR *GAUSSIAN INTEGRATION.
+
+!     PURPOSE.
+!     --------
+
+!          *GAUAW_ODB* IS CALLED TO COMPUTE THE ABSCISSAS AND WEIGHTS REQUIR
+!     TO PERFORM *GAUSSIAN INTEGRATION.
+
+!**   INTERFACE.
+!     ----------
+
+!          *CALL* *GAUAW_ODB(PA,PW,K)*
+
+!               *PA*     - ARRAY, LENGTH AT LEAST *K,* TO RECEIVE ABSCISSAS.
+!               *PW*     - ARRAY, LENGTH AT LEAST *K,* TO RECEIVE WEIGHTS.
+
+!     METHOD.
+!     -------
+
+!     -------
+
+!          THE ZEROS OF THE *BESSEL FUNCTIONS ARE USED AS STARTING
+!     APPROXIMATIONS FOR THE ABSCISSAS. NEWTON ITERATION IS USED TO
+!     IMPROVE THE VALUES TO WITHIN A TOLLERENCE OF *EPS.*
+
+!     EXTERNAL.
+!     ---------
+
+!          *BSSLZR_ODB* - ROUTINE TO OBTAIN ZEROS OF *BESSEL FUNCTIONS.
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+IMPLICIT NONE
+
+#include "bsslzr_odb.h"
+
+INTEGER(KIND=JPIM), intent(in)  :: K
+REAL(KIND=JPRB), intent(out)    :: PA(K),PW(K)
+INTEGER(KIND=JPIM), intent(out) :: KRET
+! === END OF INTERFACE BLOCK ===
+
+REAL(KIND=JPRB) :: ZEPS = 1E-14_JPRB
+REAL(KIND=JPRB) :: ZPI, ZC, ZXZ, ZKM2, ZKM1, ZFN, ZPK, ZKMRK, ZSP, ZVSP
+INTEGER(KIND=JPIM) :: IFK, IKK, JS, ITER, JN, IL
+
+!     ------------------------------------------------------------------
+
+!*         1.     SET CONSTANTS AND FIND ZEROS OF BESSEL FUNCTION.
+!                 --- --------- --- ---- ----- -- ------ ---------
+
+KRET = 0
+
+ZPI=2.0_JPRB*ASIN(1.0_JPRB)
+ZC=(1.0_JPRB-(2.0_JPRB/ZPI)**2)*0.25_JPRB
+IFK=K
+IKK=K/2
+
+CALL BSSLZR_ODB(PA,IKK)
+
+DO JS=1,IKK
+  ZXZ=COS(PA(JS)/SQRT((IFK+0.5_JPRB)**2+ZC))
+!*                 GIVING THE FIRST APPROXIMATION FOR *ZXZ.*
+  ITER=0
+
+!     ------------------------------------------------------------------
+
+!*         2.     COMPUTE ABSCISSAS AND WEIGHTS.
+!                 ------- --------- --- -------
+
+!*         2.1     SET VALUES FOR NEXT ITERATION.
+
+  210    CONTINUE
+  ZKM2=1.0_JPRB
+  ZKM1=ZXZ
+  ITER=ITER+1
+  IF(ITER > 10) GO TO 300
+
+!*         2.2     COMPUTATION OF THE *LEGENDRE POLYNOMIAL.
+
+  DO JN=2,K
+    ZFN=JN
+    ZPK=((2.0_JPRB*ZFN-1.0_JPRB)*ZXZ*ZKM1-(ZFN-1.0_JPRB)*ZKM2)/ZFN
+    ZKM2=ZKM1
+    ZKM1=ZPK
+  ENDDO
+
+  ZKM1=ZKM2
+  ZKMRK=(IFK*(ZKM1-ZXZ*ZPK))/(1.0_JPRB-ZXZ**2)
+  ZSP=ZPK/ZKMRK
+  ZXZ=ZXZ-ZSP
+  ZVSP=ABS(ZSP)
+  IF(ZVSP > ZEPS) GO TO 210
+
+!*         2.3     ABSCISSAS AND WEIGHTS.
+
+  PA(JS)=ZXZ
+  PW(JS)=(2.0_JPRB*(1.0_JPRB-ZXZ**2))/(IFK*ZKM1)**2
+
+!*         2.4     ODD *K* COMPUTATION OF WEIGHT AT THE EQUATOR.
+
+  IF (K /= IKK*2) THEN
+    PA(IKK+1)=0.
+    ZPK=2.0_JPRB/IFK**2
+
+    DO JN=2,K,2
+      ZFN=JN
+      ZPK=ZPK*ZFN**2/(ZFN-1.0_JPRB)**2
+    ENDDO
+
+    PW(IKK+1)=ZPK
+  ELSE
+
+!*         2.5     USE SYMMETRY TO OBTAIN REMAINING VALUES.
+
+    DO JN=1,IKK
+      IL=K+1-JN
+      PA(IL)=-PA(JN)
+      PW(IL)=PW(JN)
+    ENDDO
+
+  ENDIF
+ENDDO
+
+RETURN
+
+!     ------------------------------------------------------------------
+
+!*         3.     ERROR PROCESSING.
+!                 ----- -----------
+
+300 CONTINUE
+!WRITE(6,9901)
+! 9901 FORMAT(//,'  GAUAW_ODB FAILED TO CONVERGE AFTER 10 ITERATIONS.')
+!STOP
+KRET = 10
+
+!     ------------------------------------------------------------------
+
+END
diff --git a/odb/src/lib/hashing.c b/odb/src/lib/hashing.c
new file mode 100644
index 0000000..e96d643
--- /dev/null
+++ b/odb/src/lib/hashing.c
@@ -0,0 +1,359 @@
+
+/* hashing.c */
+
+#ifdef RS6K
+#pragma options noextchk
+#endif
+
+#include "odb.h"
+
+/* Hash function : Specific for UNIQUE BY -keyword processing */
+
+#ifndef HASHSIZE
+#define HASHSIZE 3019U
+#endif
+
+PRIVATE uint Hashsize = HASHSIZE;
+
+#ifndef HASHHITS
+#define HASHHITS 5
+#endif
+
+PRIVATE int  Hashhits = HASHHITS;
+
+typedef struct _ODB_Hash_Table {
+  int tag;
+  int nhashval;
+  double *d;
+  int hits;
+  struct _ODB_Hash_Table *next;
+} ODB_Hash_Table;
+
+PRIVATE ODB_Hash_Table **ODB_hashptr = NULL;
+
+PUBLIC int  ODB_hashmin = INT_MAX;
+PUBLIC int  ODB_hashmax = 0;
+PRIVATE int  ODB_hashdebug = 0;
+PRIVATE int  ODB_hashcalls = 0;
+PRIVATE int *ODB_hashhits = NULL;
+
+
+PRIVATE uint
+Hashfunc(int n, const uint u[]) 
+{ 
+  int j; 
+  uint h = 0;
+#ifdef NECSX
+  /* for now ... */
+#pragma cdir novector
+#endif
+  for (j=0; j<n; j++) {
+    h = HASHFUNC(h, u[j], Hashsize);
+  } 
+  h %= Hashsize;
+  ODB_hashmin = MIN(ODB_hashmin, h);
+  ODB_hashmax = MAX(ODB_hashmax, h);
+  return h; 
+}
+
+PUBLIC uint
+ODB_Hashsize()
+{
+  static boolean first_time = 1;
+
+  if (first_time) {
+    char *p = getenv("ODB_HASHDEBUG");
+    if (p) ODB_hashdebug = atoi(p);
+    p = getenv("ODB_HASHSIZE");
+    if (p) {
+      Hashsize = atoi(p);
+      if (Hashsize <= 0) Hashsize = HASHSIZE;
+    }
+    else
+      Hashsize = HASHSIZE;
+
+    CALLOC(ODB_hashptr, Hashsize);
+    CALLOC(ODB_hashhits, Hashsize);
+
+    Hashhits = HASHHITS;
+    p = getenv("ODB_HASHHITS");
+    if (p) {
+      int value = atoi(p);
+      if (value > 0) Hashhits = value;
+    }
+
+    first_time = 0;
+  }
+
+  return Hashsize;
+}
+
+
+PUBLIC void
+codb_hash_init_()
+{
+  int j;
+
+  (void) ODB_Hashsize();
+  if (ODB_hashdebug) ODB_Hash_print(NULL);
+
+  for (j=ODB_hashmin; j<=ODB_hashmax; j++) {
+    ODB_Hash_Table *p = ODB_hashptr[j];
+    if (p) {
+      while (p) {
+	ODB_Hash_Table *next = p->next;
+	FREE(p->d);
+	FREE(p);
+	p = next;
+      }
+      ODB_hashptr[j] = NULL; /* Since the previous FREE(p) freed already */
+    }
+  }
+  if (ODB_hashdebug) {
+    ODB_hashcalls = 0;
+    for (j=ODB_hashmin; j<=ODB_hashmax; j++) ODB_hashhits[j] = 0;
+  }
+  ODB_hashmin = INT_MAX;
+  ODB_hashmax = 0;
+}
+
+
+PUBLIC void
+codb_hash_reset_()
+{
+  int j;
+
+  (void) ODB_Hashsize();
+  if (ODB_hashdebug) ODB_Hash_print(NULL);
+
+  for (j=ODB_hashmin; j<=ODB_hashmax; j++) {
+    ODB_Hash_Table *p = ODB_hashptr[j];
+    while (p) {
+      p->hits = 0;
+      p = p->next;
+    }
+  }
+
+  if (ODB_hashdebug) ODB_hashcalls = 0;
+}
+
+
+PUBLIC void
+codb_d_unique_(const int *nval,
+	       const double d[],
+	       const uint *hash,
+	       int *is_unique,
+	       int *tag,
+	       uint *hash_out)
+{
+  int n = *nval;
+  *is_unique = 1;
+  if (hash_out) *hash_out = -1;
+
+  (void) ODB_Hashsize();
+  if (ODB_hashdebug) ODB_hashcalls++;
+
+  if (n > 0) {
+    ODB_Hash_Table *p;
+    int nuint = n * (sizeof(*d)/sizeof(uint));
+    /* A hash might already be calculated in the vectorizable routine */
+    uint h = hash ? *hash : Hashfunc(nuint, (const uint *)d);
+
+    if (hash_out) *hash_out = h;
+
+    p = ODB_hashptr[h];
+    if (!p) {
+      ALLOC(p,1);
+      p->tag = tag ? *tag : 0;
+      p->nhashval = n;
+      ALLOC(p->d, n);
+      ODB_dbl2dbl(p->d, d, n);
+      p->hits = 1;
+      p->next = NULL;
+      ODB_hashptr[h] = p;
+      if (ODB_hashdebug) ODB_hashhits[h]++;
+    }
+    else {
+      for (;;) {
+	if ((p->nhashval == n) && 
+	    ODB_uint_equal((const uint *)p->d, (const uint *)d, nuint)) {
+	  if (++p->hits > 1) {
+	    *is_unique = 0;
+	    if (tag) *tag = p->tag;
+	  }
+	  break;
+	}
+	else {
+	  if (p->next) {
+	    p = p->next;
+	  }
+	  else {
+	    ALLOC(p->next,1);
+	    p = p->next;
+	    p->tag = tag ? *tag : 0;
+	    p->nhashval = n;
+	    ALLOC(p->d, n);
+	    ODB_dbl2dbl(p->d, d, n);
+	    p->hits = 1;
+	    p->next = NULL;
+	    if (ODB_hashdebug) ODB_hashhits[h]++;
+	    break;
+	  }
+	}
+      } /* for (;;) */
+    }
+  }
+
+  if (tag && *is_unique) *tag = 0;
+
+  if (ODB_hashdebug < 0) {
+    int arg = -ODB_hashdebug;
+    if (ODB_hashcalls%arg == 0) ODB_Hash_print(NULL);
+  }
+}
+
+
+PUBLIC void
+codb_ui_unique_(const int *nval,
+		const uint ui[],
+		const uint *hash,
+		int *is_unique,
+		int *tag,
+		uint *hash_out)
+{
+  int n = *nval;
+  *is_unique = 1;
+
+  if (n > 0) {
+    double *d = NULL;
+    ALLOC(d, n);
+    ODB_uint2dbl(d, ui, n);
+    codb_d_unique_(nval, d, hash, is_unique, tag, hash_out);
+    FREE(d);
+  }
+}
+
+
+PUBLIC void
+codb_r_unique_(const int *nval,
+	       const float r[],
+	       const uint *hash,
+	       int *is_unique,
+	       int *tag,
+	       uint *hash_out)
+{
+  int n = *nval;
+  *is_unique = 1;
+
+  if (n > 0) {
+    double *d = NULL;
+    ALLOC(d, n);
+    ODB_float2dbl(d, r, n);
+    codb_d_unique_(nval, d, hash, is_unique, tag, hash_out);
+    FREE(d);
+  }
+}
+
+
+PUBLIC int
+ODB_Unique(const int n, ...)
+{
+  int is_unique = 1;
+  if (n > 0) {
+    double *d = NULL;
+    ALLOC(d, n);
+    {
+      int j;
+      va_list ap;
+      va_start(ap, n);
+      for (j=0; j<n; j++) {
+	d[j] = va_arg(ap, double);
+      }
+      va_end(ap);
+    }
+    codb_d_unique_(&n, d, NULL, &is_unique, NULL, NULL);
+    FREE(d);
+  }
+  return is_unique;
+}
+
+PUBLIC double
+ODBunique(const int n, const double args[])
+{
+  int is_unique = 1;
+  if (n > 0) {
+    codb_d_unique_(&n, args, NULL, &is_unique, NULL, NULL);
+  }
+  return is_unique;
+}
+
+PRIVATE char *
+d2str(double d)
+{
+  int j;
+  const int ns = sizeof(double);
+  static union {
+    double dval;
+    char   s[sizeof(double)+1];
+  } u;
+  u.dval = d;
+  for (j=0; j<ns; j++) {
+    int c = u.s[j];
+    if (!isprint(c)) u.s[j] = '?';
+  }
+  u.s[ns] = '\0';
+  return u.s;
+}
+
+
+PUBLIC void
+ODB_Hash_print(FILE *fp)
+{
+  (void) ODB_Hashsize();
+
+  if (!fp) fp = stderr;
+
+  if (ODB_hashdebug) {
+    int j, nunique = 0;
+    int *count;
+    CALLOC(count, Hashhits);
+    for (j=ODB_hashmin; j<=ODB_hashmax; j++) {
+      if (ODB_hashhits[j] < Hashhits) count[ODB_hashhits[j]]++;
+      nunique += ODB_hashhits[j];
+    }
+    fprintf(fp,
+	    " *** Hashing statistics : Hashsize = %d, Hashhits = %d\n",
+	    Hashsize, Hashhits);
+    fprintf(fp,"     (MIN,MAX)-hash = (%d, %d)\n",
+	    ODB_hashmin, ODB_hashmax);
+    fprintf(fp,"\tNo. of calls = %d\n",ODB_hashcalls);
+    fprintf(fp,"\tNo. of unique keys found = %d\n",nunique);
+    for (j=0; j<Hashhits; j++) {
+      fprintf(fp,"\tCount = %d : hit #%d times\n",j,count[j]);
+    }
+    FREE(count);
+    if (ODB_hashdebug > 1 && ODB_hashcalls > 0) {
+      /* More extensive output */
+      for (j=ODB_hashmin; j<=ODB_hashmax; j++) {
+	ODB_Hash_Table *p = ODB_hashptr[j];
+	if (p) fprintf(fp,"\tHash#%d :\n",j);
+	while (p) {
+	  int k;
+	  fprintf(fp,"\tHits=%d, # of values=%d :",p->hits,p->nhashval);
+	  for (k=0; k<p->nhashval; k++) {
+	    fprintf(fp," %.14g ('%s') ",p->d[k], d2str(p->d[k]));
+	  }
+	  fprintf(fp,"\n");
+	  p = p->next;
+	}
+      } /* for (j=ODB_hashmin; j<=ODB_hashmax; j++) */
+    } /* if (ODB_hashdebug > 1) */
+  } /* if (ODB_hashdebug) */
+}
+
+PUBLIC boolean
+odb_debug_print_(const double arg)
+{
+  fprintf(stderr,"debug_print: value=%.14g ('%s')\n",arg,d2str(arg));
+  return 1;
+}
diff --git a/odb/src/lib/infile.c b/odb/src/lib/infile.c
new file mode 100644
index 0000000..3c6e9c0
--- /dev/null
+++ b/odb/src/lib/infile.c
@@ -0,0 +1,68 @@
+
+/* infile.c */
+
+/* A very slow implementation for the moment */
+
+#include "odb.h"
+
+#define GET_NEXT(d) (fscanf(fp, "%lf", &d) == 1)
+
+PUBLIC double
+ODB_InFile(const char *filename, double target)
+{
+  /* Search from file/pipe and stop immediately when matched */
+  Boolean found = 0;
+  Boolean is_pipe = (filename && *filename == '|');
+  FILE *fp = is_pipe ? popen(++filename,"r") : fopen(filename,"r");
+  if (fp) {
+    double d;
+    while (GET_NEXT(d)) {
+      if (Func_uintequal(d, target)) {
+	found = 1;
+	break;
+      }
+    }
+    is_pipe ? pclose(fp) : fclose(fp);
+  }
+  return (double)found;
+}
+
+PUBLIC double
+ODBinfile(double filename, double target)
+{
+  /* Note: filename is interpreted as an address to a character string (saddr) */
+  S2D_Union u;
+  u.dval = filename;
+  return ODB_InFile(u.saddr, target);
+}
+
+
+PUBLIC double
+ODB_NotInFile(const char *filename, double target)
+{
+  /* Search from file/pipe and stop immediately when matched */
+  Boolean notfound = 1;
+  Boolean is_pipe = (filename && *filename == '|');
+  FILE *fp = is_pipe ? popen(++filename,"r") : fopen(filename,"r");
+  if (fp) {
+    double d;
+    while (GET_NEXT(d)) {
+      if (Func_uintequal(d, target)) {
+	notfound = 0;
+	break;
+      }
+    }
+    is_pipe ? pclose(fp) : fclose(fp);
+  }
+  return (double)notfound;
+}
+
+
+PUBLIC double
+ODBnotinfile(double filename, double target)
+{
+  /* Note: filename is interpreted as an address to a character string (saddr) */
+  S2D_Union u;
+  u.dval = filename;
+  return ODB_NotInFile(u.saddr, target);
+}
diff --git a/odb/src/lib/init_region.c b/odb/src/lib/init_region.c
new file mode 100644
index 0000000..52209a6
--- /dev/null
+++ b/odb/src/lib/init_region.c
@@ -0,0 +1,40 @@
+
+/* Initializes region with a predefined 4-byte string */
+
+#ifdef RS6K
+#pragma options noextchk
+#endif
+
+#include "odb.h"
+
+static boolean Init_Region = 0;
+
+void 
+init_region_(int array[], 
+	     const int *nbytes, 
+	     const int *the_magic_4bytes)
+{
+  static boolean first_time = 1; 
+
+  if (first_time) {
+    char *p = getenv("ODB_INIT_REGION");
+    Init_Region = p ? atoi(p) : 0;
+    Init_Region = (Init_Region > 0) ? 1 : 0;
+    if (Init_Region) {
+      int Myproc;
+      codb_procdata_(&Myproc, NULL, NULL, NULL, NULL);
+      if (Myproc == 1) 
+	fprintf(stderr,
+	"***init_region_(): Return matrices will be initialized with ODB_UNDEF/UNDEFDB in ODB_GET()\n");
+    }
+    first_time = 0;
+  }
+
+  if (Init_Region) {
+    int Nwords = (*nbytes)/4; /* truncated down to the nearest 4-byte bdry */
+    int Magics = *the_magic_4bytes;
+    int j;
+    for (j=0; j<Nwords; j++) array[j] = Magics;
+  }
+}
+
diff --git a/odb/src/lib/inside.c b/odb/src/lib/inside.c
new file mode 100644
index 0000000..c719611
--- /dev/null
+++ b/odb/src/lib/inside.c
@@ -0,0 +1,1125 @@
+#include "odb.h"
+#include "info.h"
+#include "result.h"
+#include "evaluate.h"
+#include "symtab.h"
+#include "cdrhook.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* GIS = Geographic Information System */
+
+PRIVATE Bool InSidePolygon(float lat, float lon, int n,
+			   const float edgelat[], const float edgelon[])
+{
+  Bool found = false;
+  DRHOOK_START(InSidePolygon);
+  {
+    int cnt = 0;
+    int j, ne = n-1;
+    for (j=0; j<ne; j++) {
+      const float *p1lat = &edgelat[j];
+      const float *p2lat = p1lat + 1; /* &edgelat[j+1]; */
+      /* Trivially outside the lat-boundaries ? */
+      if (*p1lat <  lat && *p2lat <  lat) continue;
+      if (*p1lat >= lat && *p2lat >= lat) continue;
+      { 
+	/* Find a possible intersection point S = (sx,sy) */
+	/*
+	  sy - p1lat = [(p2lat-p1lat)/(p2lon-p1lon)] * (sx-p1lon)
+	  sy = lat
+	  sx = p1lon + [(lat-p1lat) * (p2lon-p1lon)]/(p2lat-p1lat)
+	*/
+	const float eps = 1e-6;
+	const float *p1lon = &edgelon[j];
+	const float *p2lon = p1lon + 1; /* &edgelon[j+1]; */
+	float latdiff = (*p2lat - *p1lat);
+	int sign = (latdiff >= 0) ? 1 : -1;
+	float div = (ABS(latdiff) < eps) ? sign*eps : latdiff;
+	float sx = *p1lon + ((lat - *p1lat) * (*p2lon - *p1lon))/div;
+	if (sx >= lon) ++cnt;
+      }
+    } /* for (j=0; j<ne; j++) */
+    found = (cnt%2 == 1) ? true : false;
+  }
+  DRHOOK_END(n);
+  return found;
+}
+
+typedef struct {
+  float minlat;
+  float maxlat;
+  float minlon;
+  float maxlon;
+} Box_t;
+
+typedef struct _Edge_Cache_t {
+  int poolno; /* Pool number the region belongs to */
+  int id; /* Region id */
+  int partno; /* Part number */
+  Box_t box; /* Bounding box */
+  int n; /* Number of vertices (closed region => the last & the first (lat,lon) are the same) */
+  float *lat;
+  float *lon;
+} Edge_Cache_t;
+
+typedef struct _Region_Cache_t {
+  char *name; /* Country or region name or polygon filename */
+  int flag; /* 1=country/region, 2=polygon */
+  Box_t box; /* Bounding box */
+  int nparts; /* Consists of this many subregions */
+  Edge_Cache_t *part;  /* Part/edge information */
+  struct _Region_Cache_t *next; /* Next (main) region in chain */
+} Region_Cache_t;
+
+static Region_Cache_t *region_start = NULL;
+static Region_Cache_t *region_last = NULL;
+
+static char *odb_gisroot = NULL;
+static char *odb_gisworld = NULL;
+static char *odb_gisplace = NULL;
+
+/* Reference location (by default ECMWF, Reading, UK ~ 51.4N, 1W) */
+static double odb_gislat = 51.4;
+static double odb_gislon = -1;
+
+PRIVATE o_lock_t INSIDE_mylock = 0; /* A specific OMP-lock; initialized only once in
+				       odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+PUBLIC void init_inside()
+{
+  char *env;
+  INIT_LOCKID_WITH_NAME(&INSIDE_mylock,"inside.c:INSIDE_mylock");
+  coml_set_lockid_(&INSIDE_mylock);
+  if (!odb_gisroot) {
+    env = getenv("ODB_GISROOT");
+    if (env) odb_gisroot = STRDUP(env);
+  }
+  if (!odb_gisworld) {
+    env = getenv("ODB_GISWORLD");
+    if (env) odb_gisworld = STRDUP(env);
+  }
+  if (!odb_gisplace) {
+    env = getenv("ODB_GISPLACE");
+    if (env) odb_gisplace = STRDUP(env);
+  }
+  {
+    env = getenv("ODB_GISLAT");
+    if (env) odb_gislat = atof(env);
+  }
+  {
+    env = getenv("ODB_GISLON");
+    if (env) odb_gislon = atof(env);
+  }
+  coml_unset_lockid_(&INSIDE_mylock);
+}
+
+
+PRIVATE int
+cmpNvertices(const void *A, const void *B)
+{
+  const Edge_Cache_t *a = A;
+  const Edge_Cache_t *b = B;
+  return (a->n < b->n) ? -1 : ((a->n > b->n) ? 1 : 0);
+}
+
+
+PRIVATE char *
+RcpFile(const char *file, Bool *rm)
+{
+  char *s = NULL;
+  if (rm) *rm = false;
+  if (file) {
+    struct stat st;
+    if (stat(file, &st) == -1) {
+      /* Not found ? Perhaps on another machine ? Use rcp */
+      const char *colon = strchr(file,':');
+      if (colon) {
+	const char *basename = strrchr(file,'/');
+	char *cmd = NULL;
+	int cmdlen;
+	char *tmpdir = getenv("TMPDIR");
+	if (!tmpdir) tmpdir = ".";
+	if (!basename) basename = colon + 1;
+	cmdlen = STRLEN(file) + STRLEN(tmpdir) + STRLEN(basename) + 30;
+	ALLOC(cmd, cmdlen);
+	snprintf(cmd, cmdlen, "/usr/bin/rcp %s\t%s/%s", file, tmpdir, basename);
+	if (system(cmd) == 0) { /* All ok */
+	  const char *tab = strchr(cmd, '\t');
+	  if (tab) { ++tab; s = STRDUP(tab); if (rm) *rm = true; }
+	}
+      } /* if (colon) */
+    }
+  }
+  if (!s) s = STRDUP(file);
+  return s;
+}
+
+PRIVATE Region_Cache_t *
+LoadPolygonFile(const char *polygon_filename)
+{
+  Region_Cache_t *reg = NULL;
+  DRHOOK_START(LoadPolygonFile);
+  if (polygon_filename) {
+    /* Polygon file format, version#1 : text format */
+    /* 
+       rec#1 : POLT 1
+       rec#2 : Number of polygons (nparts)
+       For each polygon:
+         rec#1 : Number of vertices (n)
+         rec#2..n+1 : (lat,lon) pair
+       End-of-file marker: -1 (optional)
+
+       Note: if given polygon is not a closed polygon,
+       it will be closed by adding one extra (lat,lon) vertex,
+       which is the very first vertex for this polygon
+    */
+
+    /* A quick hack */
+    int rc = 0;
+    Bool rm = false;
+    char *pf = RcpFile(polygon_filename, &rm);
+    FILE *fp = fopen(pf,"r");
+    if (fp) {
+      int nel, nparts, n;
+      char magicword[80];
+      int version;
+      nel = fscanf(fp,"%s %d\n",magicword,&version);
+      if (nel == 2 && strequ(magicword,"POLT") && version == 1) {
+	CALLOC(reg, 1);
+	reg->name = STRDUP(polygon_filename);
+	reg->flag = 2;
+	nel = fscanf(fp, "%d\n",&nparts);
+	if (nel == 1 && nparts > 0) {
+	  int jp;
+	  reg->nparts = nparts;
+	  CALLOC(reg->part, nparts);
+	  for (jp=0; jp<nparts; jp++) {
+	    nel = fscanf(fp, "%d\n", &n);
+	    if (nel == 1 && n > 0) {
+	      int j;
+	      Edge_Cache_t *e = &reg->part[jp];
+	      e->poolno = 0;
+	      e->id     = 0;
+	      e->partno = jp+1;
+	      e->n      = n;
+	      ALLOC(e->lat, n+1); /* One extra in case polygon wasn't closed */
+	      ALLOC(e->lon, n+1); /* One extra in case polygon wasn't closed */
+	      for (j=0; j<n; j++) {
+		double xlat, xlon;
+		nel = fscanf(fp, "%lf %lf\n",&xlat,&xlon);
+		if (nel == 2) {
+		  e->lat[j] = xlat;
+		  e->lon[j] = xlon;
+		}
+		else {
+		  FREE(e->lat);
+		  FREE(e->lon);
+		  fprintf(stderr,
+			  "LoadPolygonFile(%s): Couldn't read (lat,lon) for vertex#%d of polygon#%d [rc=-5]\n",
+			  polygon_filename,j+1,jp+1);
+		  rc = -5;
+		  goto bailout;
+		}
+	      } /* for (j=0; j<n; j++) */
+
+	      if (e->lat[0] != e->lat[n-1] || e->lon[0] != e->lon[n-1]) {
+		/* Polygon wasn't closed --> close it now */
+		e->lat[n] = e->lat[0];
+		e->lon[n] = e->lon[0];
+		e->n = ++n;
+	      }
+	    }
+	    else {
+	      fprintf(stderr,
+		      "LoadPolygonFile(%s): Couldn't read the number of vertices for polygon#%d [rc=-4]\n",
+		      polygon_filename,jp+1);
+	      rc = -4;
+	      goto bailout;
+	    }
+	  } /* for (jp=0; jp<nparts; jp++) */
+	}
+	else {
+	  fprintf(stderr,
+		  "LoadPolygonFile(%s): Couldn't read the number of polygons [rc=-3]\n",polygon_filename);
+	  rc = -3;
+	  goto bailout;
+	}
+      }
+      else {
+	fprintf(stderr,
+		"LoadPolygonFile(%s): Couldn't read the first line [rc=-2]\n",polygon_filename);
+	rc = -2;
+	goto bailout;
+      }
+    bailout:
+      fclose(fp);
+    }
+    else {
+      fprintf(stderr,
+	      "LoadPolygonFile(%s): Couldn't open the file [rc=-1]\n",polygon_filename);
+      rc = -1;
+    }
+    if (rc < 0) {
+      if (reg) {
+	FREE(reg->name);
+	FREE(reg->part);
+	FREE(reg);
+      }
+    }
+    if (rm) remove_file_(pf);
+    FREE(pf);
+  }
+  DRHOOK_END(0);
+  return reg;
+}
+
+
+PRIVATE Region_Cache_t *
+LoadPolygons(const char *region_name)
+{
+  Region_Cache_t *reg = NULL;
+  DRHOOK_START(LoadPolygons);
+  if (odb_gisworld && region_name) {
+    /* At present we cannot just call ODBc_open() etc. since IOASSIGN
+       is static and refers to already opened database;
+       But in the future this indeed is a prospect!
+       For now, we 'ave use the "boring" odbsql-approach & unix-pipes */
+
+    int nparts = 0;
+    int ntotal = 0;
+
+    typedef struct _texas_chainsaw_t {
+      int poolno, id, partno, n;
+      Box_t box;
+      struct _texas_chainsaw_t *next;
+    } texas_chainsaw_t;
+    texas_chainsaw_t *cs = NULL;
+    texas_chainsaw_t *pcs;
+
+    {
+      uresult_t u;
+
+      static const char fmt[] = /* A short query */
+	"SELECT $#,id,partno,hdr.len "
+	"FROM region,part "
+	"WHERE name[1:$namelen] LIKE \"%s\" "
+	"ORDERBY 1,2,3";
+
+      char *query = NULL;
+      int len = STRLEN(fmt) + STRLEN(region_name) + 1;
+      ALLOCX(query, len);
+      snprintf(query, len, fmt, region_name);
+
+      u.alias = ODB_SubQuery(4, "-1", odb_gisworld, query, (double)0);
+      FREEX(query);
+      if (u.res) {
+	result_t *r = u.res;
+	if (r->ncols_out == 4 && r->nrows_out > 0) {
+	  Bool row_wise = r->row_wise;
+	  int j;
+	  nparts = r->nrows_out; /* Just one result-set, since ORDERBY was used */
+	  for (j=0; j<nparts; j++) {
+	    texas_chainsaw_t *pcsnew;
+	    CALLOC(pcsnew, 1);
+	    pcsnew->poolno = row_wise ? r->d[j][0] : r->d[0][j];
+	    pcsnew->id     = row_wise ? r->d[j][1] : r->d[1][j];
+	    pcsnew->partno = row_wise ? r->d[j][2] : r->d[2][j];
+	    pcsnew->n      = row_wise ? r->d[j][3] : r->d[3][j];
+	    pcsnew->next = NULL;
+	    ntotal += pcsnew->n;
+	    if (!cs) {
+	      pcs = cs = pcsnew;
+	    }
+	    else {
+	      pcs->next = pcsnew;
+	      pcs = pcsnew;
+	    }
+	  } /* for (j=0; j<nparts; j++) */
+	} /* if (r->ncols_out == 4 && r->nrows_out > 0) */
+	u.res = ODBc_unget_data(u.res);
+      } /* if (u.res) */
+    }
+
+    if (nparts > 0) {
+      uresult_t u;
+
+      static const char fmt[] = /* Can produce thousands of lines of output */
+	"SELECT lat,lon "
+	"FROM region,part,hdr "
+	"WHERE name[1:$namelen] LIKE \"%s\"";
+
+      char *query = NULL;
+      int len = STRLEN(fmt) + STRLEN(region_name) + 1;
+      ALLOCX(query, len);
+      snprintf(query, len, fmt, region_name);
+
+      u.alias = ODB_SubQuery(4, "-1", odb_gisworld, query, (double)0);
+      FREEX(query);
+      if (u.res) {
+	result_t *r = u.res;
+	if (r->ncols_out == 2) {
+	  int nrows = 0;
+	  while (r) {
+	    nrows += r->nrows_out;
+	    r = r->next;
+	  } /* while (r) */
+	  if (nrows == ntotal) {
+	    int jj, jp;
+	    CALLOC(reg, 1);
+	    reg->name = STRDUP(region_name);
+	    reg->flag = 1;
+	    reg->nparts = nparts;
+	    CALLOC(reg->part, nparts);
+	    pcs = cs;
+	    r = u.res; jj = 0;
+	    for (jp=0; jp<nparts; jp++) {
+	      Bool row_wise = r->row_wise;
+	      int j, n = pcs->n;
+	      Edge_Cache_t *e = &reg->part[jp];
+	      e->poolno = pcs->poolno;
+	      e->id     = pcs->id;
+	      e->partno = pcs->partno;
+	      e->n      = n;
+	      ALLOC(e->lat, n);
+	      ALLOC(e->lon, n);
+	      for (j=0; j<n; j++) {
+		float xlat = row_wise ? r->d[jj][0] : r->d[0][jj];
+		float xlon = row_wise ? r->d[jj][1] : r->d[1][jj];
+		e->lat[j] = xlat;
+		e->lon[j] = xlon;
+		++jj;
+	      } /* for (j=0; j<n; j++) */
+	      pcs = pcs->next;
+	      if (jj >= r->nrows_out) { r = r->next; jj = 0; } /* Go for the next chunk */
+	    } /* for (jp=0; jp<nparts; jp++) */
+	  }
+	} /* if (r->ncols_out == 2) */
+	u.res = ODBc_unget_data(u.res);
+      } /* if (u.res) */
+    }
+
+    if (cs) {
+      /* Release tmp space reserved by Texas chain-saw ... */
+      pcs = cs;
+      while (pcs) {
+	texas_chainsaw_t *pcs_next = pcs->next;
+	FREE(pcs);
+	pcs = pcs_next;
+      }
+    } /* if (cs) */
+
+  } /* if (odb_gisworld && region_name) */
+  DRHOOK_END(0);
+  return reg;
+}
+
+
+PRIVATE int Common4Insiders(int flag,
+			    const char *region_name, double lat, double lon)
+{
+  int rc = 0;
+  DRHOOK_START(Common4Insiders);
+  if (region_name && ( (flag == 1 && odb_gisworld) || flag == 2 ) ) {
+    unsigned int code = *region_name++;
+    Region_Cache_t *reg = NULL;
+    Bool add2chain = false;
+    
+    coml_set_lockid_(&INSIDE_mylock);
+    {
+      reg = region_start;
+      while (reg) {
+	if (reg->flag == flag && 
+	    ODB_Common_StrEqual(reg->name,
+				region_name,
+				0, NULL,
+				(flag == 1) ? true : false)) {
+	  break; /* matched !! */
+	}
+	reg = reg->next;
+      }
+    }
+    coml_unset_lockid_(&INSIDE_mylock);
+    
+    if (!reg) {
+      reg = (flag == 1) ? LoadPolygons(region_name) : LoadPolygonFile(region_name);
+      if (reg) add2chain = true;
+    }
+    
+    if (!reg) {
+      /* Still not found --> create an empty region to disable further invocations of odbsql */
+      CALLOC(reg, 1);
+      reg->name = STRDUP(region_name);
+      reg->flag = flag;
+      add2chain = true;
+    }
+
+    if (add2chain && reg) {
+      /* Calculate bounding boxes, sort parts w.r.t. no. of vertices etc. */
+      int nparts = reg->nparts;
+      if (nparts > 0) {
+	int jp;
+	Edge_Cache_t *e = reg->part;
+	reg->box.minlat =  9999;
+	reg->box.maxlat = -9999;
+	reg->box.minlon =  9999;
+	reg->box.maxlon = -9999;
+	for (jp=0; jp<nparts; jp++) {
+	  int j, n = e->n;
+	  e->partno = jp+1; /* renumbered */
+	  e->box.minlat =  9999;
+	  e->box.maxlat = -9999;
+	  e->box.minlon =  9999;
+	  e->box.maxlon = -9999;
+	  for (j=0; j<n; j++) {
+	    float xlat = e->lat[j];
+	    float xlon = e->lon[j];
+	    e->box.minlat = MIN(e->box.minlat, xlat);
+	    e->box.maxlat = MAX(e->box.maxlat, xlat);
+	    e->box.minlon = MIN(e->box.minlon, xlon);
+	    e->box.maxlon = MAX(e->box.maxlon, xlon);
+	  }
+	  reg->box.minlat = MIN(reg->box.minlat, e->box.minlat);
+	  reg->box.maxlat = MAX(reg->box.maxlat, e->box.maxlat);
+	  reg->box.minlon = MIN(reg->box.minlon, e->box.minlon);
+	  reg->box.maxlon = MAX(reg->box.maxlon, e->box.maxlon);
+	  ++e;
+	}
+	if (nparts > 1) qsort(reg->part, nparts, sizeof(Edge_Cache_t), cmpNvertices);
+      } /* if (nparts > 0) */
+      reg->next = NULL;
+
+      coml_set_lockid_(&INSIDE_mylock);
+      if (!region_start) {
+	region_last = region_start = reg;
+      }
+      else {
+	region_last->next = reg;
+	region_last = reg;
+      }
+      coml_unset_lockid_(&INSIDE_mylock);
+    } /* if (add2chain && reg) */
+
+    if (reg && reg->nparts > 0) {
+      /* Find if (lat,lon) is inside the region */
+      int nparts = reg->nparts;
+      if ((code & 0x1) == 0x1) lat = ODB_lldegrees(lat);
+      if (lat >= reg->box.minlat && lat <= reg->box.maxlat) {
+	if ((code & 0x2) == 0x2) lon = ODB_lldegrees(lon);
+	if (lon >= reg->box.minlon && lon <= reg->box.maxlon) {
+	  int jp;
+	  Edge_Cache_t *e = reg->part;
+	  /* Note: Parts have been sorted with smallest number of polylines first */
+	  for (jp=0; jp<nparts; jp++) {
+	    int n = e->n;
+	    if (n > 0 &&
+		lat >= e->box.minlat && lat <= e->box.maxlat &&
+		lon >= e->box.minlon && lon <= e->box.maxlon) {
+	      Bool inside = InSidePolygon(lat, lon, n, e->lat, e->lon);
+	      if (inside) {
+		rc = 1;
+		break; /* for (jp=0; jp<nparts; jp++) */
+	      }
+	    }
+	    ++e;
+	  } /* for (jp=0; jp<nparts; jp++) */
+	} /* if (lon >= reg->box.minlon && lon <= reg->box.maxlon) */
+      } /* if (lat >= reg->box.minlat && lat <= reg->box.maxlat) */
+    } /* if (reg && reg->nparts > 0) */
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+PUBLIC int
+ODB_Inside(const char *region_name, double lat, double lon)
+{
+  int rc = 0;
+  DRHOOK_START(ODB_Inside);
+  rc = Common4Insiders(1, region_name, lat, lon);
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC double
+ODBinside(double region_name, double lat, double lon)
+{
+  double rc = 0;
+  if (odb_gisworld) {
+    /* Note: region_name is interpreted as an address to a character string (saddr) */
+    char *str = NULL;
+    S2D_Union u;
+    u.dval = region_name;
+    str = u.saddr;
+    rc = (double)ODB_Inside(str, lat, lon);
+  }
+  return rc;
+}
+
+
+PUBLIC int
+ODB_InPolygon(const char *polygon_filename, double lat, double lon)
+{
+  int rc = 0;
+  DRHOOK_START(ODB_InPolygon);
+  rc = Common4Insiders(2, polygon_filename, lat, lon);
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC double
+ODBinpolygon(double polygon_filename, double lat, double lon)
+{
+  double rc = 0;
+  /* Note: polygon_filename is interpreted as an address to a character string (saddr) */
+  char *str = NULL;
+  S2D_Union u;
+  u.dval = polygon_filename;
+  str = u.saddr;
+  rc = (double)ODB_InPolygon(str, lat, lon);
+  return rc;
+}
+
+
+typedef struct _Place_t {
+  char *name;
+  double dis; /* distance to a reference (lat,lon)-location */
+  double lat;
+  double lon;
+  double alt;
+  double pop;
+} Place_t;
+
+static int nplaces = 0;
+static Place_t *places = NULL;
+
+PRIVATE Place_t *
+FindPlace(const char *place_name, int *n)
+{
+  int nfound = 0;
+  Place_t *pl = NULL;
+  if (odb_gisplace && place_name) {
+    int j;
+    for (j=0; j<nplaces; j++) {
+      Place_t *p = &places[j];
+      if (ODB_Common_StrEqual(p->name,
+			      place_name,
+			      0, NULL,
+			      true)) {
+	pl = p; /* found */
+	nfound = 1;
+	break;
+      }
+    } /* for (j=0; j<nplaces; j++) */
+
+    if (!pl) {
+      /* Not found --> run a query */
+      uresult_t u;
+
+      static const char fmt[] =
+	"SELECT distance(lat,lon,%.3f,%.3f) as dis,lat,lon,alt,pop "
+	"FROM hdr "
+	"WHERE name[1:$namelen] LIKE \"%s\" "
+	"ORDERBY 1";
+
+      char *query = NULL;
+      int len = STRLEN(fmt) + STRLEN(place_name) + 100;
+      ALLOCX(query, len);
+      snprintf(query, len, fmt, odb_gislat, odb_gislon, place_name);
+
+      u.alias = ODB_SubQuery(4, "-1", odb_gisplace, query, (double)0);
+      FREEX(query);
+      if (u.res) {
+	result_t *r = u.res;
+	if (r->ncols_out == 5) {
+	  int nrows = r->nrows_out; /* Just one result-set, since ORDERBY was used */
+	  if (nrows > 0) {
+	    Bool row_wise = r->row_wise;
+	    int last = nplaces;
+	    int i, offset = last;
+	    nplaces += nrows;
+	    REALLOC(places, nplaces);
+	    for (i=0; i<nrows; i++) {
+	      double dis = row_wise ? r->d[i][0] : r->d[0][i];
+	      double lat = row_wise ? r->d[i][1] : r->d[1][i];
+	      double lon = row_wise ? r->d[i][2] : r->d[2][i];
+	      double alt = row_wise ? r->d[i][3] : r->d[3][i];
+	      double pop = row_wise ? r->d[i][4] : r->d[4][i];
+	      places[offset+i].name = STRDUP(place_name);
+	      places[offset+i].dis = dis;
+	      places[offset+i].lat = lat;
+	      places[offset+i].lon = lon;
+	      places[offset+i].alt = alt;
+	      places[offset+i].pop = pop;
+	      if (++nfound == 1) pl = &places[last];
+	    }
+	  } /* if (nrows > 0) */
+	}
+	u.res = ODBc_unget_data(u.res);
+      }
+      if (!pl) {
+	/* SQL did not find this place => do not search again */
+	int last = nplaces++;
+	REALLOC(places, nplaces);
+	places[last].name = STRDUP(place_name);
+	places[last].dis = mdi;
+	places[last].lat = mdi;
+	places[last].lon = mdi;
+	places[last].alt = mdi;
+	places[last].pop = mdi;
+	pl = &places[last];
+	nfound = 1;
+      }
+    }
+  } /* if (odb_gisplace && place_name) */
+  if (n) *n = nfound;
+  return pl;
+}
+
+
+PUBLIC double
+ODB_Near(const char *place_name, double lat, double lon)
+{
+  double distance = mdi;
+  coml_set_lockid_(&INSIDE_mylock);
+  if (place_name) {
+    /* Must be locked at this level due to potentially changing "pl" of FindPlace() */
+    int nfound = 0;
+    unsigned int code = *place_name++;
+    Place_t *pl = FindPlace(place_name, &nfound);
+    if (nfound > 0 && pl && pl->lat != mdi && pl->lon != mdi) {
+      if ((code & 0x1) == 0x1) lat = ODB_lldegrees(lat);
+      if ((code & 0x2) == 0x2) lon = ODB_lldegrees(lon);
+      distance = Func_distance(lat, lon, pl->lat, pl->lon); /* A macro from odb.h */
+    }
+  }
+  coml_unset_lockid_(&INSIDE_mylock);
+  return distance;
+}
+
+
+PUBLIC double
+ODBnear(double place_name, double lat, double lon)
+{
+  double rc = mdi;
+  if (odb_gisplace) { /* $ODB_GISROOT/PLACE -database */
+    /* Note: place_name is interpreted as an address to a character string (saddr) */
+    char *str = NULL;
+    S2D_Union u;
+    u.dval = place_name;
+    str = u.saddr;
+    rc = ODB_Near(str, lat, lon);
+  }
+  return rc;
+}
+
+#define ODB_LATITUDE   1
+#define ODB_LONGITUDE  2
+#define ODB_ALTITUDE   3
+#define ODB_POPULATION 4
+
+PRIVATE double CommonStrFunc1(int key,
+			      const char *place_name,
+			      double dplace_name)
+{
+  double value = mdi;
+  if (odb_gisplace && key > 0) { /* F.ex. $ODB_GISROOT/PLACE -database */
+    coml_set_lockid_(&INSIDE_mylock);
+    { /* Must be locked at this level due to potentially changing "pl" of FindPlace() */
+      int nfound = 0;
+      Place_t *pl = FindPlace(place_name, &nfound);
+      if (nfound > 0 && pl) {
+	char *str = place_name ? (char *)place_name : NULL;
+	if (!str) {
+	  /* Note: dplace_name is interpreted as an address to a character string (saddr) */
+	  S2D_Union u;
+	  u.dval = dplace_name;
+	  str = u.saddr;
+	}
+	switch (key) {
+	case ODB_LATITUDE   : value = pl->lat; break;
+	case ODB_LONGITUDE  : value = pl->lon; break;
+	case ODB_ALTITUDE   : value = pl->alt; break;
+	case ODB_POPULATION : value = pl->pop; break;
+	}
+      } /* if (nfound > 0 && pl) */
+    }
+    coml_unset_lockid_(&INSIDE_mylock);
+  }
+  return value;
+}
+
+PUBLIC double ODB_Lat(const char *place_name)
+{ return CommonStrFunc1(ODB_LATITUDE, place_name, 0); }
+
+PUBLIC double ODBlat(double place_name)
+{ return CommonStrFunc1(ODB_LATITUDE, NULL, place_name); }
+
+PUBLIC double ODB_Lon(const char *place_name)
+{ return CommonStrFunc1(ODB_LONGITUDE, place_name, 0); }
+
+PUBLIC double ODBlon(double place_name)
+{ return CommonStrFunc1(ODB_LONGITUDE, NULL, place_name); }
+
+PUBLIC double ODB_Alt(const char *place_name)
+{ return CommonStrFunc1(ODB_ALTITUDE, place_name, 0); }
+
+PUBLIC double ODBalt(double place_name)
+{ return CommonStrFunc1(ODB_ALTITUDE, NULL, place_name); }
+
+PUBLIC double ODB_Pop(const char *place_name)
+{ return CommonStrFunc1(ODB_POPULATION, place_name, 0); }
+
+PUBLIC double ODBpop(double place_name)
+{ return CommonStrFunc1(ODB_POPULATION, NULL, place_name); }
+
+/* SUB-query processing */
+
+PUBLIC double
+ODBsubquery(const int nargs, const double args[])
+{
+  FILE *fp_echo = ODBc_get_debug_fp();
+  double rc = 0; /* uresult_t's alias */
+  if (fp_echo) ODB_fprintf(fp_echo, "ODBsubquery: nargs=%d\n", nargs);
+  if (nargs >= 4 && args) {
+    uresult_t u;
+    S2D_Union u1, u2, u3;
+    char *poolmask = NULL;
+    char *db = NULL;
+    char *query = NULL;
+    double make_sort_unique;
+    int n = nargs - 4; /* No. of additional (double) SET-parameters */
+    int dblen = 0;
+    u.res = NULL;
+    u1.dval = args[0]; poolmask = u1.saddr;
+    u2.dval = args[1]; db = u2.saddr;
+    u3.dval = args[2]; query = u3.saddr;
+    make_sort_unique = args[3];
+    dblen = STRLEN(db);
+    if (dblen >= 0) {
+      /* For the moment using *ONLY* odbsql ... */
+      static const char fmt[] = 
+	"|$ODB_BINPATH/odbsql -q '%s%s'%s%s -NBT -e /dev/null -p'%s' -f binary";
+      char *cmd = NULL;
+      int len = STRLEN(fmt) + STRLEN(query) + dblen + 50 + STRLEN(poolmask);
+      char *set = NULL;
+      if (n > 0) { /* SET-params */
+	const char setfmt[] = "SET $%d = %.14g;";
+	char *aset = NULL;
+	int asetlen = STRLEN(setfmt) + 100;
+	int j, lenset = n * asetlen;
+	ALLOC(set, lenset);
+	*set = '\0';
+	ALLOCX(aset, asetlen);
+	for (j=0; j<n; j++) {
+	  snprintf(aset, asetlen, setfmt, j+1, args[3+j]);
+	  strcat(set, aset);
+	}
+	FREEX(aset);
+      }
+      ALLOCX(cmd, len);
+      snprintf(cmd, len, fmt, 
+	       set ? set : "",
+	       query,
+	       (dblen > 0) ? " -i" : "",
+	       (dblen > 0) ? db : "",
+	       poolmask);
+      if (fp_echo) ODB_fprintf(fp_echo, "ODBsubquery: cmd='%s', make_sort_unique = %d\n", 
+			       cmd,(int)make_sort_unique);
+      /* true below means: make column oriented, with sorted unique values across rows */
+      u.res = ODBc_get_data_from_binary_file(cmd, 
+					     (int)make_sort_unique ? true : false); 
+      FREEX(cmd);
+      FREE(set);
+    }
+#if 0
+    else {
+      /* Use faster method, since the current database (BUT IS BROKEN ...) */
+      /* Need to make IOASSIGN more dynamic first */
+      int handle = ODBc_get_handle(NULL);
+      info_t *info = ODBc_sql_prepare(handle, query, NULL, 0);
+      if (info) {
+	result_t *res = NULL;
+	if (poolno > 0) {
+	  int nrows = ODBc_sql_exec(handle, info, poolno, NULL, NULL);
+	  res = (nrows > 0) ? ODBc_get_data(handle, NULL, info, poolno, 1, nrows, false, NULL) : NULL;
+	}
+	else {
+	  /* Also this is not quite right !! What if global_oper ? 
+	     See odbsql.c for correct way in dealing with this */
+	  int jp, npools = info->npools;
+	  for (jp=1; jp<=npools; jp++) {
+	    int iret = ODBc_sql_exec(handle, info, jp, NULL, NULL);
+	    if (iret > 0) {
+	      res = ODBc_get_data(handle, res, info, jp, 1, iret, false, NULL);
+	    }
+	  } /* for (jp=1; jp<=npools; jp++) */
+	}
+	u.res = res;
+	(void) ODBc_sql_cancel(info);
+      }
+    }
+#endif
+    rc = u.res ? u.alias : 0;
+    if (fp_echo) ODB_fprintf(fp_echo, 
+			     "ODBsubquery: u.res = %p, u.alias = %.14g, u.i[0:1] = (%d, %d)\n",
+			     u.res, u.alias, u.i[0], u.i[1]);
+  }
+  return rc;
+}
+
+
+PUBLIC double
+ODB_SubQuery(const int n, 
+	     /* const char *poolmask, const char *db, const char *query, double make_sort_unique */ ...)
+{
+  double rc = 0;
+  if (n >= 4) {
+    int j;
+    double *args = NULL;
+    char *poolmask, *db, *query;
+    S2D_Union u1, u2, u3;
+    double make_sort_unique;
+    va_list ap;
+    va_start(ap, n);
+
+    ALLOCX(args, n);
+
+    poolmask = va_arg(ap, char *);
+    u1.saddr = poolmask;
+    args[0] = u1.dval;
+
+    db = va_arg(ap, char *);
+    u2.saddr = db;
+    args[1] = u2.dval;
+
+    query = va_arg(ap, char *);
+    u3.saddr = query;
+    args[2] = u3.dval;
+
+    make_sort_unique = va_arg(ap, double);
+
+    for (j=4; j<n; j++) {
+      args[j] = va_arg(ap, double);
+    }
+    rc = ODBsubquery(n, args);
+    FREEX(args);
+    va_end(ap);
+  }
+  return rc; /* uresult_t's alias */
+}
+
+
+PUBLIC double
+ODB_InQuery(const int num_expr, const int nummatch, 
+	    double subquery, double runonce, /* double expr1, [double expr2, ... ] */ ...)
+{
+  double rc = 0;
+  if (num_expr >= 5) {
+    int j, n = num_expr;
+    double *args = NULL;
+    va_list ap;
+    va_start(ap, runonce);
+    ALLOCX(args, n);
+    args[0] = num_expr;
+    args[1] = nummatch;
+    args[2] = subquery;
+    args[3] = runonce;
+    for (j=4; j<n; j++) {
+      args[j] = va_arg(ap, double);
+    }
+    rc = ODBinquery(n, args);
+    FREEX(args);
+    va_end(ap);
+  }
+  return rc; /* uresult_t's alias */
+}
+
+
+PUBLIC double
+ODBinquery(const int nargs, const double args[])
+{
+  double rc = 0; /* Not found in query */
+
+  if (nargs >= 5) {
+    FILE *fp_echo = ODBc_get_debug_fp();
+    int j, num_expr = (int)args[0] - 4;
+    int nummatch = (int)args[1];
+    double subquery = args[2];
+    double runonce = args[3];
+    const double *expr = &args[4];
+    uresult_t u;
+
+    u.alias = subquery;
+
+    if (fp_echo) {
+      ODB_fprintf(fp_echo, 
+		  "ODBinquery([nargs=%d] ; num_expr = %d, nummatch = %d,"
+		  " subquery = %.14g, runonce = %.14g",
+		  nargs, num_expr, nummatch, subquery, runonce);
+      for (j=0; j<num_expr; j++) ODB_fprintf(fp_echo,", %.14g",expr[j]);
+      ODB_fprintf(fp_echo,")\n");
+      ODB_fprintf(fp_echo, 
+		  "ODBinquery: u.res = %p, u.alias = %.14g, u.i[0:1] = (%d, %d)\n",
+		  u.res, u.alias, u.i[0], u.i[1]);
+    }
+
+    if (u.res) {
+      result_t *r = u.res;
+      int ncols = r->ncols_out;
+      int nrows = r->nrows_out;
+
+      if (fp_echo) {
+	static int cnt = 0; /* not thread safe */
+	ODB_fprintf(fp_echo,
+		    "ODBinquery: num_expr = %d, ncols = %d, nrows = %d, poolno = %d\n",
+		    num_expr, ncols, nrows, r->poolno);
+	if (cnt++ < 5) ODBc_DebugPrintRes("ODBinquery", r);
+      }
+
+      if (nummatch == 0) {
+	num_expr = MIN(num_expr, ncols);
+	if (nrows > 0 && num_expr >= 1) {
+	  /* Subquery is in a "stream-lined" (nrows x ncols), with 1st column sorted */
+	  const double *col_1 = &r->d[0][0];
+	  int k = ODBc_bsearch(expr[0], nrows, col_1, +1);
+	  if (k >= 0 && num_expr == 1) {
+	    rc = 1; /* Found */
+	  }
+	  else if (k >= 0 && num_expr > 1) {
+	    Bool found = false;
+	    int kpivot = k; /* pivot point */
+	    
+	    ODB_fprintf(fp_echo,"\tkpivot = %d, *col_1 = %.14g\n", kpivot, *col_1);
+	    
+	    while (!found && k < nrows) { /* Search forward */
+	      Bool match = (expr[0] == col_1[k]) ? true : false;
+	      if (!match) break; /* Not even the first column the same anymore */
+	      for (j=1; match && j<num_expr; j++) {
+		double value = r->d[j][k];
+		if (expr[j] != value) match = false;
+	      }
+	      if (match) found = true;
+	      ++k;
+	    } /* while (!found && k < nrows) */
+	    
+	    k = kpivot;
+	    while (!found && k > 0) { /* Search backward */
+	      Bool match = (expr[0] == col_1[--k]) ? true : false;
+	      if (!match) break; /* Not even the first column the same anymore */
+	      for (j=1; match && j<num_expr; j++) {
+		double value = r->d[j][k];
+		if (expr[j] != value) match = false;
+	      }
+	      if (match) found = true;
+	    } /* while (!found && k > 0) */
+	    
+	    if (found) rc = 1;
+	  } /* if (k >= 0 && num_expr > 1) */
+	} /* if (nrows > 0 && num_expr >= 1) */
+      }
+      else if (nummatch > 0) { /* Ought to be 1 */
+	/* loop over nrows */
+	/* for each row assign values to \1, \2, ..., \ncols -variables in succession */
+	/* stop when first match */
+	uresult_t e;
+	e.alias = expr[0];
+	ODB_fprintf(fp_echo, 
+		    "ODBinquery: e.parse_tree = %p, e.alias = %.14g, e.i[0:1] = (%d, %d)\n",
+		    e.parse_tree, e.alias, e.i[0], e.i[1]);
+	if (e.parse_tree && nrows > 0) {
+	  DEF_IT;
+	  thsafe_parse_t *thsp = fp_echo ? (thsafe_parse_t *)GetTHSP() : NULL;
+	  void *save_chan_err = thsp ? thsp[IT].chan_err : NULL;
+	  Bool found = false;
+	  double value;
+	  int iret, ir, jc;
+	  typedef struct {
+	    char tmp[16];
+	    symtab_t *stab;
+	    double *value;
+	    double *vec;
+	  } tmp_stab_t;
+	  tmp_stab_t *st;
+	  static int cnt = 0; /* not thread safe */
+
+	  if (thsp) thsp[IT].chan_err = fp_echo;
+
+	  if (fp_echo && cnt < 5) {
+	    PrintNode(fp_echo,e.parse_tree);
+	    ODB_fprintf(fp_echo,"\tnrows = %d, ncols = %d\n", nrows, ncols);
+	  }
+
+	  /* Allocate \<number>-variables to provide fastest possible access & update */
+	  CALLOC(st, ncols);
+	  for (jc=0; jc<ncols; jc++) {
+	    tmp_stab_t *pst = &st[jc];
+	    snprintf(pst->tmp, sizeof(pst->tmp), "\\%d", jc+1);
+	    pst->value = putsymvec(pst->tmp, mdi, r->d[jc], nrows);
+	    pst->stab = getsymtab(pst->tmp);
+	    pst->vec = pst->stab->vec; /* alias r->d[jc] */
+	    if (fp_echo && cnt < 5) {
+	      ODB_fprintf(fp_echo,
+			  "[init: jc=%d] \t%s = %.14g (r->d[jc] = 0x%x, pst->vec = %p, pst->value = 0x%x)\n", 
+			  jc, pst->tmp, *pst->value, r->d[jc], pst->vec, pst->value);
+	    }
+	  } /* for (jc=0; jc<ncols; jc++) */
+
+	  for (ir=0; !found && ir<nrows; ir++) {
+	    if (fp_echo && cnt < 5 && ir < 100) ODB_fprintf(fp_echo,"[ir = %d] : ", ir);
+	    for (jc=0; jc<ncols; jc++) {
+	      /* Quick & direct update \<number>-variables */
+	      tmp_stab_t *pst = &st[jc];
+	      *pst->value =  *pst->vec++;
+	      if (fp_echo && cnt < 5 && ir < 100) {
+		ODB_fprintf(fp_echo,"[%d:%s] = %.14g ", jc, pst->tmp, *pst->value);
+	      }
+	    } /* for (jc=0; jc<ncols; jc++) */
+	    if (fp_echo && cnt < 5 && ir < 100) ODB_fprintf(fp_echo, "\n");
+	    /* value = RunTree(e.parse_tree, NULL, &iret); */
+	    /* The following is better than RunTree(), since only one expr/condition, no chain */
+	    value = RunNode(e.parse_tree, &iret); 
+	    if (iret != 0) {
+	      /* Should not happen */
+	      fprintf(stderr, 
+		      "***Error in ODBinquery() [iret = %d] : "
+		      "Could not evaluate (nummatch = %d) ; ir=%d, nrows=%d, ncols=%d\n",
+		      iret, nummatch, ir, nrows, ncols);
+	      PrintNode(stderr,e.parse_tree);
+	      RAISE(SIGABRT);
+	    }
+	    if (value != 0) found = true;
+	  } /* for (ir=0; !found && ir<nrows; ir++) */
+	  ++cnt;
+
+	  if (found) rc = 1;
+
+	  /* De-activate \<number>-variables quickly */
+	  for (jc=0; jc<ncols; jc++) {
+	    tmp_stab_t *pst = &st[jc];
+	    pst->stab->active = false;
+	  } /* for (jc=0; jc<ncols; jc++) */
+	  FREE(st);
+
+	  if (thsp) thsp[IT].chan_err = save_chan_err;
+	}
+      }
+
+      if (fp_echo) {
+	ODB_fprintf(fp_echo, " --> rc = %d [nummatch was %d]\n", (int)rc, nummatch);
+      }
+    } /* if (u.res) */
+
+    /* When the subquery-parameter wasn't a RunOnceQuery(), 
+       then perform cleanup every time (==> very, very slow search) */
+    if (u.res && runonce != 1) {
+      if (fp_echo) ODB_fprintf(fp_echo, "ODBinquery: u.res && runonce = %g != 1\n", runonce);
+      u.res = ODBc_unget_data(u.res);
+    }
+  }
+
+  return rc;
+}
diff --git a/odb/src/lib/iolockdb.F90 b/odb/src/lib/iolockdb.F90
new file mode 100644
index 0000000..b803c5a
--- /dev/null
+++ b/odb/src/lib/iolockdb.F90
@@ -0,0 +1,11 @@
+SUBROUTINE iolockdb(konoff)
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE odbshared, only : haveiolock
+USE odbmp    , only : ODBMP_locking
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: konoff
+INTEGER(KIND=JPIM) :: iret
+if (haveiolock > 0 .or. konoff == -1)  &
+ & iret = ODBMP_locking(haveiolock, konoff) 
+END SUBROUTINE iolockdb
diff --git a/odb/src/lib/lnkdb.F90 b/odb/src/lib/lnkdb.F90
new file mode 100644
index 0000000..a5ecf51
--- /dev/null
+++ b/odb/src/lib/lnkdb.F90
@@ -0,0 +1,41 @@
+SUBROUTINE lnkdb(kparent, kpa, kchild, kch, klink, kret)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: kpa, kch
+INTEGER(KIND=JPIM), intent(in)  :: kparent(kpa), kchild(kch)
+INTEGER(KIND=JPIM), intent(out) :: klink(kpa+1), kret
+
+!-- Correct code (even if some parents have no childs)
+INTEGER(KIND=JPIM) :: actlen(kpa) ! automatic array
+INTEGER(KIND=JPIM) :: jpa, icount, target
+INTEGER(KIND=JPIM) :: jchstart, jchend, jch
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('LNKDB',0,ZHOOK_HANDLE)
+kret = 0
+if (kpa > 0) then
+  jchend = 0
+  do jpa=1,kpa
+    target = kparent(jpa)
+    jchstart = jchend + 1
+    icount = 0
+    do jch=jchstart,kch
+      if (kchild(jch) /= target) exit
+      icount = icount + 1
+    enddo
+    actlen(jpa) = icount
+    jchend = jchend + icount
+  enddo
+  klink(1) = 1
+  do jpa=2,kpa+1
+    klink(jpa) = klink(jpa-1) + actlen(jpa-1)
+  enddo
+  kret = kpa+1
+endif
+IF (LHOOK) CALL DR_HOOK('LNKDB',1,ZHOOK_HANDLE)
+
+END SUBROUTINE lnkdb
diff --git a/odb/src/lib/lnkdb2.F90 b/odb/src/lib/lnkdb2.F90
new file mode 100644
index 0000000..3102bc4
--- /dev/null
+++ b/odb/src/lib/lnkdb2.F90
@@ -0,0 +1,33 @@
+SUBROUTINE lnkdb2(koffset, &
+ & karr_in, klda, krows, kcol1, kcol2, &
+ & ktarget, karr_out) 
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: koffset
+INTEGER(KIND=JPIM), intent(in)  :: klda, krows, kcol1, kcol2, ktarget
+INTEGER(KIND=JPIM), intent(in)  :: karr_in(klda, kcol1:kcol2)
+INTEGER(KIND=JPIM), intent(out) :: karr_out(krows + 1)
+INTEGER(KIND=JPIM) :: j, imin, imax
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('LNKDB2',0,ZHOOK_HANDLE)
+if (krows > 0) then
+  imin =  huge(krows)
+  imax = -huge(krows)
+  do j=1,krows
+    imin = min(imin,karr_in(j,ktarget))
+    imax = max(imax,karr_in(j,ktarget))
+  enddo
+  if (imax == imin) then
+    do j=1,krows + 1
+      karr_out(j) = koffset + (j-1) * imax
+    enddo
+  else
+    karr_out(1) = koffset
+    do j=2,krows + 1
+      karr_out(j) = karr_out(j-1) + karr_in(j-1,ktarget)
+    enddo
+  endif
+endif
+IF (LHOOK) CALL DR_HOOK('LNKDB2',1,ZHOOK_HANDLE)
+END SUBROUTINE lnkdb2
diff --git a/odb/src/lib/msgpass_loaddata.F90 b/odb/src/lib/msgpass_loaddata.F90
new file mode 100644
index 0000000..8007116
--- /dev/null
+++ b/odb/src/lib/msgpass_loaddata.F90
@@ -0,0 +1,757 @@
+SUBROUTINE msgpass_loaddata(khandle, kret)
+
+! A routine to exchange ODB-data between processors
+! Called from module ODB: ODB_open():open_db 
+
+! P. Marguinaud : 10-10-2013 : Nullify pointers
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+use oml_mod, only : oml_set_lock, oml_unset_lock, oml_my_thread
+USE odb_module
+USE mpl_module
+USE odbio_msgpass
+USE str, ONLY : sadjustl 
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+
+INTEGER(KIND=JPIM)              :: io_method, jt, j, jj, ntables, iret, maxbytes
+INTEGER(KIND=JPIM)              :: nw, nwmax, nbytes, nrows, ncols, npad, igrpsize, ipoolno, npools
+INTEGER(KIND=JPIM)              :: itag, pe, destPE, io, isendreq, max_iope, iprev, idx
+INTEGER(KIND=JPIM), allocatable :: itags(:,:)
+INTEGER(KIND=JPIM)              :: iexpect_len
+INTEGER(KIND=JPIM), allocatable :: iope_map(:,:)
+character(len=maxvarlen), allocatable :: cltable(:)
+logical, allocatable            :: LL_mypool(:), LL_include_tbl(:)
+logical                         :: LL_readonly
+logical                         :: LL_check_len
+logical, save                   :: LL_first_time = .TRUE.
+logical, save                   :: LL_write_empty = .FALSE.
+INTEGER(KIND=JPIM), save        :: iwrite_empty = 0
+INTEGER(KIND=JPIM), parameter   :: io_filesize_default = 32 ! in megabytes; see ../aux/newio.c, too
+INTEGER(KIND=JPIM), save        :: io_filesize = 1
+INTEGER(KIND=JPIM), save        :: io_grpsize = -1
+INTEGER(KIND=JPIM), parameter   :: io_trace_default = 0
+INTEGER(KIND=JPIM), save        :: io_trace = 0
+INTEGER(KIND=JPIM), parameter   :: io_msgpass_trace_default = 0
+INTEGER(KIND=JPIM), save        :: io_msgpass_trace = 0
+logical, save                   :: LLiotrace = .FALSE.
+logical, save                   :: LLiomsgpasstrace = .FALSE.
+character(len=1), parameter     :: CLtab = char(9)
+character(len=1)                :: CLmode='r', CLtmp
+character(len=maxvarlen)        :: dbname, CLtbl, CLbytes
+character(len=4096)             :: clenv, filename, CLdirname, CLbasename
+
+INTEGER(KIND=JPIM), parameter   :: maxsize_mb = 1000 ! Maximum filesize in megabytes for HC32-file
+INTEGER(KIND=JPIM)              :: nread
+INTEGER(KIND=JPIM)              :: jmin, jmax, it, is_compressed
+INTEGER(KIND=JPIM), allocatable :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), parameter   :: NHDR = 6
+INTEGER(KIND=JPIM)              :: ihdr(NHDR), idum(1), this_io_grpsize, itables, cur_io_grpsize
+INTEGER(KIND=JPIM)              :: nactive_tables, jtact, iope, icnt_not_active
+INTEGER(KIND=JPIM)              :: itime(8),imsgpass_Time,imsgpass_Date,i_consider,jsta, i_write
+INTEGER(KIND=JPIM), pointer     :: incore(:)
+!J---Start---
+INTEGER(KIND=JPIM), parameter   :: MMSGSND = 1000
+INTEGER(KIND=JPIM), pointer     :: jncore(:)
+INTEGER(KIND=JPIM)              :: MJNCORE = 10000000
+INTEGER(KIND=JPIM)              :: msgoff, msgsnd, njmax
+INTEGER(KIND=JPIM)              :: jsendreq(MMSGSND)
+!J---End---
+INTEGER(KIND=JPIM), save        :: hc32(0:1) = (/0,0/) ! "HC32" & its reverse/byteswap (to be filled) 
+INTEGER(KIND=JPIM), parameter   :: reset_updated_flag = 1
+INTEGER(KIND=JPIM), POINTER     :: ioaid(:,:,:) ! A shorthand notation
+REAL(KIND=JPRB), allocatable    :: data_bytes(:) ! nactive_tables
+REAL(KIND=JPRB)                 :: datavolume(0:ODBMP_nproc), waltim(2), sum_datavolume
+INTEGER(KIND=JPIM)              :: nfiles, idummy_arr(1), npermcnt
+INTEGER(KIND=JPIM), allocatable :: perm_list(:), global_pool_offset(:)
+logical, allocatable            :: LL_poolmask(:), LL_filemask(:), LL_lastpool(:)
+REAL(KIND=JPRB), external       :: util_walltime  ! now [23/1/04] from ifsaux/support/drhook.c
+INTEGER(KIND=JPIM)              :: fast_physproc, xfast, nfblk, irefblk
+INTEGER(KIND=JPIM)              :: imp_type
+LOGICAL                         :: L2,L3,L4
+INTEGER(KIND=JPIM)              :: nfileno
+REAL(KIND=JPRB)                 :: ZHOOK_HANDLE
+
+
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK('MSGPASS_LOADDATA',0,ZHOOK_HANDLE)
+
+incore => null ()
+jncore => null ()
+ioaid  => null ()
+
+call MPL_barrier(cdstring='MSGPASS_LOADDATA')
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_LOADDATA : Begin'
+kret = 0
+itables = 0
+it = oml_my_thread()
+
+if (.NOT.db(khandle)%inuse) goto 99999
+
+io_method = db(khandle)%io_method
+if (io_method /= 4) goto 99999 ! only applicable for ODB_IO_METHOD=4
+
+LL_readonly = db(khandle)%readonly
+
+#if defined(NECSX) && defined(BOM)
+imp_type = JP_BLOCKING_STANDARD
+#else
+imp_type = JP_NON_BLOCKING_STANDARD
+#endif
+
+dbname = db(khandle)%name
+
+CALL ODBMP_sync()
+
+waltim(1) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  write(0,'(1x,a,i8.8,2x,i6.6)') &
+  '=== MSGPASS_LOADDATA of db="'//trim(dbname)// &
+  '" for mode='//CLmode//' started on ',imsgpass_date,imsgpass_time
+endif
+
+datavolume(:) = 0
+nfiles = 0 ! no. of opened files on this PE
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_LOADDATA ==='
+if (LL_first_time) then
+!$ CALL OML_SET_LOCK()
+!$OMP FLUSH(LL_first_time)
+ if (LL_first_time) then
+  !-- HC32-magic number
+  CALL get_magic_hc32(0, hc32(0))
+  !-- HC32-magic number byteswap i.e. reverse
+  CALL get_magic_hc32(1, hc32(1))
+  !-- I/O tracing
+  CALL util_igetenv('ODB_IO_TRACE', io_trace_default, io_trace)
+  LLiotrace = (io_trace /= 0)
+  !-- Message pass tracing
+  CALL util_igetenv('ODB_IO_MSGPASS_TRACE', io_msgpass_trace_default, io_msgpass_trace)
+  LLiomsgpasstrace = (io_msgpass_trace /= 0)
+  !-- Make sure these stay consistent with the ones obtained in ../aux/newio.c !
+  CALL util_igetenv('ODB_IO_FILESIZE', io_filesize_default, io_filesize) ! in megabytes
+  if (io_filesize <= 0) io_filesize = io_filesize_default
+  if (io_filesize > maxsize_mb) io_filesize = maxsize_mb ! never exceed this many megabytes
+  CALL util_igetenv('ODB_IO_GRPSIZE', 0, io_grpsize)
+  if (io_grpsize <= 0) then ! try $NPES_AN
+    CALL util_igetenv('NPES_AN', 0, io_grpsize)
+  endif
+  if (io_grpsize <= 0) io_grpsize = ODBMP_nproc
+  CALL util_igetenv('ODB_WRITE_EMPTY_FILES', 0, iwrite_empty)
+!*AF  LL_write_empty = (iwrite_empty /= 0)
+  LL_write_empty = (iwrite_empty == 1)
+  if (ODBMP_myproc == 1) then
+    write(0,*)'                 HC32=',hc32
+    write(0,*)'         ODB_IO_TRACE=',io_trace
+    write(0,*)' ODB_IO_MSGPASS_TRACE=',io_msgpass_trace
+    write(0,*)'      ODB_IO_FILESIZE=',io_filesize,' MBytes'
+    write(0,*)'       ODB_IO_GRPSIZE=',io_grpsize
+    write(0,*)'ODB_WRITE_EMPTY_FILES=',iwrite_empty, LL_write_empty
+  endif
+  LL_first_time = .FALSE.
+!$OMP FLUSH(LL_first_time)
+ endif
+!$ CALL OML_UNSET_LOCK()
+endif
+
+if (ODBMP_myproc == 1) then
+  write(0,*) ODBMP_myproc,&
+   & ': MSGPASS_LOADDATA() khandle=',&
+   & khandle
+endif
+
+npools = db(khandle)%glbNpools
+this_io_grpsize = min(npools,io_grpsize) 
+
+!if (ODBMP_myproc == 1) write(0,*) 'this_io_grpsize, npools=',&
+!                                   this_io_grpsize, npools
+
+allocate(LL_poolmask(npools))
+LL_poolmask(1:npools) =  .TRUE. ! true means that take all these pools
+
+allocate(LL_filemask(npools))
+allocate(LL_lastpool(npools))
+if (LL_readonly) then
+  CALL cODB_get_permanent_poolmask(khandle, 0, idummy_arr, npermcnt)
+  npermcnt = abs(npermcnt)
+  if (npermcnt > 0) then
+    allocate(perm_list(npermcnt))
+    perm_list(:) = 0
+    CALL cODB_get_permanent_poolmask(khandle, npermcnt, perm_list, iret)
+    LL_poolmask(1:npools) = .FALSE. ! By default: do *not* take these pools
+    do j=1,npermcnt
+      jj = perm_list(j)
+      if (jj >= 1 .and. jj <= npools)  LL_poolmask(jj) = .TRUE.
+    enddo
+    deallocate(perm_list)
+  endif
+endif
+
+if (ODBMP_myproc == 1) then
+  if (ALL(LL_poolmask(1:npools))) then
+    write(0,'(1x,a,i5,a,i5,a)') &
+      & 'MSGPASS_LOADDATA: All pools in range [1..npools] will processed'
+  else
+    write(0,*)'MSGPASS_LOADDATA: Only the following pools will be processed:'
+    jj = 0
+    do j=1,npools
+      if (LL_poolmask(j)) then
+        write(0,'(1x,i7)',advance='no') j
+        jj = jj + 1
+        if (mod(jj,10) == 0 .AND. j < npools) write(0,*)
+      endif
+    enddo
+    if (jj > 0) write(0,*)
+  endif
+endif
+
+CALL comm_iomap(khandle, 1, iret) ! Get up to date IOAID
+
+ioaid => db(khandle)%ioaid
+
+allocate(global_pool_offset(npools))
+global_pool_offset(:) = 0
+nfblk = db(khandle)%nfileblocks
+ipoolno = 0 
+irefblk = 0
+do j=1,npools
+  if (ioaid(j,1,IOAID_FBLOCK) /= irefblk) then
+    irefblk = ioaid(j,1,IOAID_FBLOCK)
+    ipoolno = j - 1
+  endif
+  global_pool_offset(j) = ipoolno
+enddo
+
+ntables = ODB_getnames(khandle, '*', 'table')
+allocate(cltable(ntables))
+ntables = ODB_getnames(khandle, '*', 'table', cltable)
+
+allocate(LL_mypool(npools))
+allocate(LL_include_tbl(ntables))
+
+do j=1,npools
+  pe = fast_physproc(j)
+  LL_mypool(j) = (pe == ODBMP_myproc)
+enddo
+
+!-- New approach (5-Sep-2006/SS)
+do jt=1,ntables
+  CALL cODB_table_is_considered(cltable(jt), i_consider)
+  LL_include_tbl(jt) = (i_consider == 1)
+enddo
+
+icnt_not_active = COUNT(.not.LL_include_tbl(:))
+nactive_tables = ntables - icnt_not_active
+if (ODBMP_myproc == 1) then
+  write(0,*)'***INFO: Considering the following ',&
+   & nactive_tables,' tables for database="'//trim(dbname)//'" :' 
+! do jt=1,ntables
+!   if (LL_include_tbl(jt)) write(0,*)'  '//trim(cltable(jt))
+! enddo
+  if (icnt_not_active == 0) then
+    write(0,*)'***INFO: All tables considered'
+  endif
+endif
+
+do jt=1,ntables
+  i_consider = 1
+  if (.not.LL_include_tbl(jt)) i_consider = 0
+  CALL cODB_consider_table(khandle, trim(cltable(jt)), i_consider, iret)
+enddo
+
+if (nactive_tables <= 0) then
+  if (ODBMP_myproc == 1) write(0,*)'***INFO: No active tables'
+  kret = 0
+  goto 99999
+endif
+
+allocate(istat(nstat,npools,nactive_tables))
+
+allocate(iope_map(npools+1,nactive_tables))
+
+allocate(data_bytes(nactive_tables))
+
+
+!-- Get current status of incore items
+istat(:,:,:) = 0
+jtact = 0
+STAT_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle STAT_LOOP 
+  jtact = jtact + 1
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- Gather size information of incore items for memory allocations
+  do j=1,npools
+    if (LL_mypool(j)) then
+      CALL newio_status_incore32(khandle, j, istat(1,j,jtact), nstat, CLtbl, iret)
+!*AF      write(0,*) 'msgpass_loaddata table = ', trim(CLtbl), ' pool = ', j, ' nrows = ', istat(2,j,jtact), ' ncols = ', istat(3,j,jtact), &
+!*AF                 'updated = ', istat(4,j,jtact)
+    endif
+  enddo
+enddo STAT_LOOP
+
+!-- Make istat-information globally available
+CALL ODBMP_global('MAX', istat)
+
+!J---Start----
+!-- Initialisation for NON BLOCKING message passing------------
+call allocate_jncore(jncore, MJNCORE,iret)
+njmax=MJNCORE
+msgsnd = 0
+msgoff = 0
+!J---End---
+
+!-- Get iope_map for ALL applicable tables in one go
+iope_map(:,:) = -1 ! Means: Any PE
+jtact = 0
+LOAD_IOPES: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle LOAD_IOPES
+  jtact = jtact + 1
+  data_bytes(jtact) = 0
+
+!-- If any bytes have been loaded, then prevent overwriting existing incore-structures from disk
+  maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+  if (maxbytes > 0) cycle LOAD_IOPES  ! already loaded --> skip
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- Determine which pools have files present ==> pool owner-PEs become I/O-PEs
+  do j=1,npools
+    !-- ipoolno below is LOCAL (not global) poolno with respect to fileblock ioaid(j,jt,IOAID_FBLOCK) in concern
+    if (ioaid(j,jt,IOAID_GRPSIZE) > 0) then
+      ipoolno = mod(ioaid(j,jt,IOAID_POOLNO)-1,ioaid(j,jt,IOAID_GRPSIZE)) + 1 
+    else
+      ipoolno = 0
+    endif
+    if ( LL_mypool(j) .and. ipoolno > 0 .and. &
+       & ipoolno == ioaid(j,jt,IOAID_FILENO) ) then
+
+!-- The expected length in bytes can be calculated as follows :
+      jmin = max(j,1)
+      jmax = min(j+ioaid(j,jt,IOAID_GRPSIZE)-1,size(ioaid,dim=1))
+      iexpect_len = SUM(  ioaid(jmin:jmax,jt,IOAID_LENGTH), &
+                  & mask=(ioaid(jmin:jmax,jt,IOAID_FILENO) == ipoolno .and. &
+                  &       ioaid(jmin:jmax,jt,IOAID_FBLOCK) == ioaid(j,jt,IOAID_FBLOCK)))
+
+      LL_check_len = .TRUE.
+      if (iexpect_len > 0) then
+        iexpect_len = iexpect_len + sizeof_int   ! Plus length of the MAGIC-word (HC32)
+        CALL codb_tablesize(dbname, CLtbl, j, iret)
+        if (iret > 0 .and. iret /= iexpect_len) then
+           CALL makefilename(dbname, CLtbl, j, filename)
+           CALL cma_is_externally_compressed(trim(filename), 'r', is_compressed)
+!             write(0,*)'msgpass_loaddata: filename='//trim(filename)//' : is_compressed=',is_compressed
+!             write(0,*)'msgpass_loaddata: iret,iexpect_len=',iret,iexpect_len
+           LL_check_len = (is_compressed == 0)
+        endif
+      else
+        iret = 0
+      endif
+
+      if (LLiotrace .or. LLiomsgpasstrace) then 
+        write(0,'(1x,i5,a,2i12,5i7)') &
+        & ODBMP_myproc,': tablesize for "'//trim(CLtbl)//'" & poolno=',&
+        & iret,ioaid(j,jt,IOAID_LENGTH),j,ioaid(j,jt,IOAID_POOLNO),&
+        & ioaid(j,jt,IOAID_FILENO),jtact,ipoolno
+      endif
+
+      if (iret == iexpect_len .or. .not.LL_check_len) then
+        if (iret > 0) then
+          iope_map(j,jtact) = ODBMP_myproc
+          data_bytes(jtact) = data_bytes(jtact) + iret
+        endif
+      else
+        write(0,*) ODBMP_myproc,': Expected length disagrees with the actual'
+        write(0,'(1x,i5,a,3i12)') ODBMP_myproc,': table, poolno, iret, iexpect_len : "'// &
+        &                                   trim(CLtbl)//'"', j, iret, iexpect_len
+        CALL ODB_abort('MSGPASS_LOADDATA', &
+                      &'Expected length disagrees with the actual', &
+                      & iret)
+      endif
+    endif
+  enddo
+enddo LOAD_IOPES
+
+!-- Make iope-information globally available
+call ODBMP_global('MAX', iope_map)
+
+!-- Make data_bytes-information available for PE#1
+CALL ODBMP_global('SUM', data_bytes, LDREPROD=.false., root=1)
+
+!-- Debug output
+if ( (LLiotrace .or. LLiomsgpasstrace) .and. ODBMP_myproc == 1) then 
+  jtact = 0
+  do jt=1,ntables
+    if (.not.LL_include_tbl(jt)) cycle
+    jtact = jtact + 1
+    CLtbl = cltable(jt)(2:)
+    write(0,'(1x,2(a,i5),a,f20.1,a)') &
+    & 'I/O-pe map for table "'//trim(CLtbl)//'", pool range=[1..npools], total ',&
+    & data_bytes(jtact),' bytes :'
+    write(0,'((10(1x,i5)))' ) (iope_map(j,jtact),j=1,npools)
+  enddo
+endif
+
+!-- Predefine message tags for all used table,pools combinations 
+!   (global not local - as need to know tags of incoming messages from other tasks)
+! Loop through all table/pool combinations and determine if a message will need to be sent,
+!   if so, then define a tag for the send/recv to use. 
+allocate(itags(npools+1,ntables))
+itags(:,:) = -1
+itag = 0
+TABLE_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle TABLE_LOOP
+  jj = 1
+  do while (jj <= npools)
+    if (LL_poolmask(jj)) then
+      j = jj
+      if (ioaid(j,jt,IOAID_LENGTH) > 0) then
+           itags(jj,jt) = itag
+      itag = itag + 1
+      endif
+    endif
+    jj = jj + 1
+  enddo ! jj <=npools 
+enddo TABLE_LOOP
+if (ODBMP_myproc == 1) write(0,*) 'Created itags array with MAX: ',MAXVAL(itags(:,:)), ' and MIN: ',MINVAL(itags(:,:))
+
+
+
+!-- A procedure for loading data from disk (horizontal concatenation; io_method=4)
+jtact = 0
+LOAD_TABLE: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle LOAD_TABLE
+  jtact = jtact + 1
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- If all PEs in the receiving end, then there is obviously no data behind any PE !
+  max_iope = MAXVAL(iope_map(1:npools,jtact))
+  if (max_iope == -1) then
+!     if (ODBMP_myproc == 1) write(0,*) &
+!      & '***Warning: LOADing table="'//trim(CLtbl)//'" skipped since empty (or already loaded)' 
+    cycle LOAD_TABLE
+  endif
+
+  if (ODBMP_myproc == 1) then
+    write(CLbytes,'(f20.1)') data_bytes(jtact)
+    jj = index(CLbytes,'.')
+    if (jj > 0) CLbytes(jj:) = ' '
+    write(0,'(1x,a)')'LOADing table="'//trim(CLtbl)//'" total = '//&
+     & trim(CLbytes)//' bytes' 
+  endif
+
+!-- Worker-loop: perform read-I/O & send/recv data
+  isendreq=0
+  nread = 0
+  io = -1
+  iprev = -1
+  CALL codb_strblank(filename)
+
+  LL_filemask(:) = .FALSE. ! .TRUE. only if file is to be processed at all
+  LL_lastpool(:) = .FALSE. ! .TRUE. only if pool is beyond the last to be processed in its file
+
+  j = 1
+  jj = 1
+  iprev = 0
+  FILEMASK_LOOP: do while (j <= npools)
+    if (LL_poolmask(j)) then
+      LL_filemask(jj) = .TRUE.
+      LL_filemask(j) = .TRUE.
+      iprev = j ! last pool so far which we care about for this file #jj
+    endif
+    if (j < npools) then
+      !-- detect the change of file: next chunk will be read from different file
+      if ( ioaid(j+1,jt,IOAID_FBLOCK) /= ioaid(j,jt,IOAID_FBLOCK) .OR. &
+          (ioaid(j+1,jt,IOAID_LENGTH)  > 0 .AND. &
+           ioaid(j+1,jt,IOAID_OFFSET) <= ioaid(j,jt,IOAID_OFFSET))) then
+        if (iprev > 0) LL_lastpool(iprev+1:j) = .TRUE. ! skip the reading these pools
+        iprev = 0
+        jj = j + 1
+      endif
+    endif
+    j = j + 1
+  enddo FILEMASK_LOOP
+  j=min(npools,j)
+  if (iprev > 0) LL_lastpool(iprev+1:j) = .TRUE. ! skip the reading these pools
+
+  if ( (LLiotrace .or. LLiomsgpasstrace) .AND. ODBMP_myproc == 1) then
+    write(0,*)'LL_filemask='
+    write(0,'((32(1x,L1)))') (LL_filemask(j),j=1,npools)
+    write(0,*)'LL_poolmask='
+    write(0,'((32(1x,L1)))') (LL_poolmask(j),j=1,npools)
+    write(0,*)'LL_lastpool='
+    write(0,'((32(1x,L1)))') (LL_lastpool(j),j=1,npools)
+  endif
+
+  jj = 1
+  LOAD_LOOP: do while (jj <= npools)
+   if (LL_filemask(jj) .AND. .not.LL_lastpool(jj)) then
+    nw = 0
+
+    if (iope_map(jj,jtact) == ODBMP_myproc) then
+      jsta = jj
+
+      j = jj
+      cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+
+      nread = 0
+      CALL io_checkopen(dbname, filename, CLtbl, io, j, nread, cur_io_grpsize, LDread=.TRUE.,&
+                        LLiotrace=LLiotrace, hc32=hc32, global_pool_offset=global_pool_offset, &
+                        kfileno=nfileno, kret=iret)
+
+      iprev = -1
+      IO_LOOP: DO
+
+        if (ioaid(j,jt,IOAID_LENGTH) > 0) then
+          ihdr(:) = 0
+          CALL cma_readi(io, ihdr(1), NHDR, iret) ! readI ==> prepare for be2le conversion
+          if (iret == -1) then ! Unexpected EOF encountered
+            CALL io_error('***MSGPASS_LOADDATA(io_error): Unexpected EOF encountered while reading file', &
+             & iret, NHDR, j, filename, kdata=ioaid(jsta:j,jt,IOAID_OFFSET)) 
+          endif          
+
+          if (iret /= NHDR) CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to read header data', iret, NHDR, j, &
+           & filename, kdata=ihdr(1:NHDR)) 
+          
+          ipoolno = ihdr(1)
+          igrpsize = ihdr(2)
+          nbytes = ihdr(3)
+          nrows = ihdr(4)
+          ncols = ihdr(5)
+          npad = ihdr(6) ! ... not used for anything (else) yet ...
+          nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+
+          if (ioaid(j,jt,IOAID_LENGTH) /= nw * sizeof_int) then
+            CALL io_error('***MSGPASS_LOADDATA(io_error): Inconsistent no. of bytes', &
+             & nw * sizeof_int, ioaid(j,jt,IOAID_LENGTH), j, filename, &
+             & kdata=ioaid(jsta:j,jt,IOAID_LENGTH)) 
+          endif
+
+          if (ioaid(j,jt,IOAID_OFFSET) /= nread) then
+            CALL io_error('***MSGPASS_LOADDATA(io_error): Data expected from different byte-offset', &
+             & nread, ioaid(j,jt,IOAID_OFFSET), j, &
+             & filename, kdata=ioaid(jsta:j,jt,IOAID_OFFSET)) 
+          endif
+
+          nread = nread + iret * sizeof_int
+
+          destPE = fast_physproc(j)
+
+          if (LL_poolmask(j)) then
+            CALL allocate_incore(incore, nw + 1, iret)
+            incore(1:NHDR) = ihdr(1:NHDR)
+            CALL cma_readb(io, incore(NHDR+1), (nw - NHDR) * sizeof_int, iret) ! readB; raw data xfer
+            if (iret /= (nw - NHDR) * sizeof_int) then
+              CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to read data', iret, &
+                            (nw - NHDR) * sizeof_int, j, filename)
+            endif
+          else ! just seek forward [=1] (should work for gzip'ped files, too; don't rewind though!)
+            CALL cma_seekb(io, (nw - NHDR) * sizeof_int, 1, iret)
+            if (iret /= 0) then
+              CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to seek past data', iret, &
+                            (nw - NHDR) * sizeof_int, j, filename)
+            endif
+            iret = (nw - NHDR) * sizeof_int
+          endif
+          nread = nread + iret
+
+          if (LL_poolmask(j)) then ! care only about poolmask'ed ones
+            if (LL_mypool(j)) then ! Copy-to-myself
+              CALL newio_put_incore32(khandle, j, incore(NHDR+1), nbytes, &
+                                      nrows, ncols, CLtbl, iret)
+              if (iret /= nbytes) then
+                CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to [1]put_incore() correct no. of bytes', &
+                              iret, nbytes, j, filename)
+              endif
+            else
+            if (LLiomsgpasstrace) &
+                & write(0,'(i5,a,i5,a,2i12)') &
+                & ODBMP_myproc,':LOAD: Sending to ',destPE,', tag,nw=',itag,nw
+!J---Start----
+!J              if (iwrite_empty == 2) then
+!J                CALL mpl_send(incore(1:nw), KDEST=destPE, KTAG=itag, &
+!J                   & CDSTRING='LOAD: Send data to data-owner PE; table=@'//trim(CLtbl))
+!j              else
+!J                CALL mpl_send(incore(1:nw), KDEST=destPE, KTAG=itag, &
+!J                   & KMP_TYPE=imp_type, KREQUEST=ISENDREQ, &
+!J                   & CDSTRING='LOAD: Send data to data-owner PE; table=@'//trim(CLtbl))
+!J              end if
+              if(msgoff+nw > njmax .or. msgsnd .eq. MMSGSND) then
+                if(msgsnd > 0 ) then
+!                   write(0,*)'msgsnd,MMSGSND',msgsnd,MMSGSND
+                  CALL mpl_wait(jncore, KREQUEST=JSENDREQ(1:msgsnd),CDSTRING="MSGPASS_LOADDATA Wait")
+                endif
+                if(nw .gt. njmax) then
+                  njmax=nw
+                  CALL allocate_jncore(jncore, njmax, iret)
+                endif
+                msgsnd=0
+                msgoff=0
+              endif
+              jncore(msgoff+1:msgoff+nw)=incore(1:nw)
+              msgsnd=msgsnd+1
+
+            itag = itags(j,jt)
+
+              if (itag == -1) CALL ODB_abort('MSGPASS_LOADDATA', 'itag not set correctly for mpl_send ',iret)
+
+              CALL mpl_send(jncore(msgoff+1:msgoff+nw), KDEST=destPE, KTAG=itag, &
+                  & KMP_TYPE=imp_type, KREQUEST=JSENDREQ(msgsnd), &
+                  & CDSTRING='LOAD: Send data to data-owner PE; table=@'//trim(CLtbl))
+              msgoff=msgoff+nw
+
+!J---End----
+              if (LLiomsgpasstrace) &
+                & write(0,'(i5,a,i5,a,2i12)') &
+                & ODBMP_myproc,':LOAD: Sent to ',destPE,', tag,isendreq=',itag,isendreq
+!J              if (iwrite_empty /=2 .and. imp_type == JP_NON_BLOCKING_STANDARD) CALL mpl_wait(incore, KREQUEST=ISENDREQ)
+              if (LLiomsgpasstrace) &
+                & write(0,'(i5,a,i12)') &
+                & ODBMP_myproc,':LOAD: Wait finished on isendreq=',ISENDREQ
+            endif
+!            else
+!              if (LL_mypool(j) .AND. LLiotrace) &
+!                write(0,*) ODBMP_myproc,': Rejecting pool#',j,' due to permanent poolmask'
+          endif
+          iprev = ioaid(j,jt,IOAID_OFFSET)
+        endif ! if (ioaid(j,jt,IOAID_LENGTH) > 0)
+
+        j = j + 1
+        jj = j
+        if (j > npools) exit IO_LOOP
+
+        if (LL_lastpool(j)) exit IO_LOOP
+
+        if (ioaid(j,jt,IOAID_FBLOCK) /= ioaid(j-1,jt,IOAID_FBLOCK)) exit IO_LOOP
+
+        if (ioaid(j,jt,IOAID_LENGTH) > 0 .AND. &
+         & ioaid(j,jt,IOAID_OFFSET) <= iprev) exit IO_LOOP 
+      ENDDO IO_LOOP
+
+      CALL io_close(filename, io, nread, j-1, nfiles, datavolume, LLiotrace, iret)
+      cycle LOAD_LOOP
+
+    ELSEIF (LL_mypool(jj)) then
+      j = jj
+      pe = iope_map(j,jtact)
+      nw = ioaid(j,jt,IOAID_LENGTH)/sizeof_int
+
+      itag = itags(j,jt)
+
+      if (LL_poolmask(j) .AND. nw > 0) then
+        CALL allocate_incore(incore, nw + 1, iret)
+        if (LLiomsgpasstrace) &
+          & write(0,'(i5,a,i5,a,2i12)') &
+          & ODBMP_myproc,':LOAD: Receiving from ',pe,', tag,nw=',itag,nw
+        if (pe == -1) then ! "ANY"-source : at present KSOURCE-parameter must be left out
+          if (itag == -1) CALL ODB_abort('MSGPASS_LOADDATA', 'itag not set correctly for mpl_recv ',iret)
+          CALL mpl_recv(incore(1:nw), KTAG=itag, KOUNT=iret, &
+           & KFROM=pe,   &! Upon return the "pe" contains the actual "from-PE"
+           & CDSTRING='LOAD: Recv data from I/O-PE; table=@'//trim(CLtbl)) 
+        else
+          if (itag == -1) CALL ODB_abort('MSGPASS_LOADDATA', 'itag not set correctly for mpl_recv ',iret)
+          CALL mpl_recv(incore(1:nw), KSOURCE=pe, KTAG=itag, KOUNT=iret, &
+           & CDSTRING='LOAD: Recv data from I/O-PE; table=@'//trim(CLtbl)) 
+        endif
+        if (LLiomsgpasstrace) &
+          & write(0,'(i5,a,i5,a,2i12)') &
+          & ODBMP_myproc,':LOAD: Received from ',pe,', tag,iret=',itag,iret
+
+        if (iret /= nw) then
+          CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to receive correct amount of data from I/O-PE', &
+           & iret, nw, j, filename)
+        endif
+
+        nbytes = incore(3)
+        nrows = incore(4)
+        ncols = incore(5)
+        CALL newio_put_incore32(khandle, j, incore(NHDR+1), nbytes, &
+         & nrows, ncols, CLtbl, iret) 
+        if (iret /= nbytes) then
+          CALL io_error('***MSGPASS_LOADDATA(io_error): Unable to [2]put_incore() correct no. of bytes', &
+                        iret, nbytes, j, filename)
+        endif
+!        else if (.not.LL_poolmask(j) .AND. nw > 0) then
+!          if (LLiotrace) &
+!            write(0,*) ODBMP_myproc,': Rejecting pool#',j,' due to permanent poolmask'
+      endif ! if (LL_poolmask(j) .AND. nw > 0) else if ...
+    endif ! if (iope_map(jj,jtact) == ODBMP_myproc) then ... else if (LL_mypool(jj)) ...
+
+   endif ! if (LL_filemask(jj)) then ...
+   jj = jj + 1
+  enddo LOAD_LOOP
+!J---Start----
+  if(msgsnd > 0 ) then
+    CALL mpl_wait(jncore, KREQUEST=JSENDREQ(1:msgsnd),CDSTRING="MSGPASS_LOADDATA Wait")
+  endif
+  msgsnd=0
+  msgoff=0
+!J---End----
+
+  CALL io_close(filename, io, nread, npools, nfiles, datavolume, LLiotrace, iret)
+
+  itables = itables + 1
+enddo LOAD_TABLE
+
+kret = itables ! No. of tables stored/loaded
+
+datavolume(0) = nfiles
+CALL ODBMP_global('SUM', datavolume, LDREPROD=.false., root=1)
+nfiles = datavolume(0)
+
+waltim(2) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  sum_datavolume = sum(datavolume(1:ODBMP_nproc))/(1024 * 1024)
+
+  write(0,'(1x,a,i8.8,2x,i6.6,/, &
+   &        1x,a,f8.1,a,i5,a,f7.2,a,f8.1,a,i3,a)') &
+   & '=== MSGPASS_LOADDATA of db="'//trim(dbname)// &
+   & '" for mode='//CLmode//' on all tables ended on ',imsgpass_date,imsgpass_time,&
+   & '=== MSGPASS_LOADDATA : ',sum_datavolume,' MBytes (',&
+   & nfiles,' files) in ',waltim(2) - waltim(1),&
+   & ' secs (',sum_datavolume/(waltim(2) - waltim(1) + epsilon(waltim(1))),&
+   & ' MB/s) (it#',it ,')'
+endif
+
+99999 continue
+
+if (allocated(iope_map))           deallocate(iope_map)
+if (allocated(LL_mypool))          deallocate(LL_mypool)
+if (allocated(LL_include_tbl))     deallocate(LL_include_tbl)
+if (associated(incore))             deallocate(incore)
+!J---Start---
+if (associated(jncore))             deallocate(jncore)
+!J---End---
+if (allocated(istat))              deallocate(istat)
+if (allocated(data_bytes))         deallocate(data_bytes)
+if (allocated(cltable))            deallocate(cltable)
+if (allocated(LL_poolmask))        deallocate(LL_poolmask)
+if (allocated(LL_filemask))        deallocate(LL_filemask)
+if (allocated(LL_lastpool))        deallocate(LL_lastpool)
+if (allocated(global_pool_offset)) deallocate(global_pool_offset)
+if (allocated(itags))              deallocate(itags)
+
+nullify(ioaid)
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_LOADDATA : End'
+IF (LHOOK) CALL DR_HOOK('MSGPASS_LOADDATA',1,ZHOOK_HANDLE)
+      
+END SUBROUTINE msgpass_loaddata
+
diff --git a/odb/src/lib/msgpass_loadobs.F90 b/odb/src/lib/msgpass_loadobs.F90
new file mode 100644
index 0000000..6ef3d7f
--- /dev/null
+++ b/odb/src/lib/msgpass_loadobs.F90
@@ -0,0 +1,418 @@
+SUBROUTINE msgpass_loadobs(khandle, kret)
+
+! A routine to exchange ODB-data between processors
+! Called from module ODB: ODB_open():open_db 
+
+! P. Marguinaud : 10-10-2013 : Nullify pointers
+! P. Lean       : 25-11-2014 : Code refactor to allow greater parallelism in io for improved scalability.
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE oml_mod, only : oml_set_lock, oml_unset_lock, oml_my_thread
+USE odb_module
+USE mpl_module
+USE odbio_msgpass
+USE str, ONLY : sadjustl 
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+
+INTEGER(KIND=JPIM)              :: io_method, jt, j, jj, ntables, iret, maxbytes
+INTEGER(KIND=JPIM)              :: nw, nbytes, nrows, ncols, npad, igrpsize, ipoolno, npools
+INTEGER(KIND=JPIM)              :: itag, pe, destPE, io
+INTEGER(KIND=JPIM), allocatable :: itags(:,:)
+INTEGER(KIND=JPIM), allocatable :: iope_map(:,:)
+CHARACTER(len=maxvarlen), allocatable :: cltable(:)
+LOGICAL, allocatable            :: LL_mypool(:), LL_include_tbl(:)
+LOGICAL                         :: LL_readonly
+LOGICAL, save                   :: LL_first_time = .TRUE.
+INTEGER(KIND=JPIM), parameter   :: io_filesize_default = 32 ! in megabytes; see ../aux/newio.c, too
+INTEGER(KIND=JPIM), save        :: io_filesize = 1
+INTEGER(KIND=JPIM), save        :: io_grpsize = -1
+LOGICAL, save                   :: LLiotrace = .FALSE.
+LOGICAL, save                   :: LLiomsgpasstrace = .FALSE.
+CHARACTER(len=1)                :: CLmode='r'
+CHARACTER(len=maxvarlen)        :: dbname, CLtbl, CL_called_from
+CHARACTER(len=4096)             :: filename
+INTEGER(KIND=JPIM)              :: jsta   ! start pool for the currently open file
+INTEGER(KIND=JPIM)              :: nread
+INTEGER(KIND=JPIM)              :: it
+INTEGER(KIND=JPIM), allocatable :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), parameter   :: NHDR = 6
+INTEGER(KIND=JPIM)              :: this_io_grpsize, n_tables_read,prev_fblk,prev_fileno
+INTEGER(KIND=JPIM)              :: nactive_tables, jtact
+INTEGER(KIND=JPIM), pointer     :: incore(:)
+INTEGER(KIND=JPIM), pointer     :: jncore(:)
+INTEGER(KIND=JPIM)              :: msgoff, nsent
+INTEGER(KIND=JPIM), allocatable :: jsendreq(:)
+INTEGER(KIND=JPIM), save        :: hc32(0:1) = (/0,0/) ! "HC32" & its reverse/byteswap (to be filled) 
+INTEGER(KIND=JPIM), pointer     :: ioaid(:,:,:) ! A shorthand notation
+REAL(KIND=JPRB), allocatable    :: data_bytes(:) ! nactive_tables
+INTEGER(KIND=JPIM), allocatable :: active_table_id(:)
+REAL(KIND=JPRB)                 :: datavolume(0:ODBMP_nproc), waltim(2)
+INTEGER(KIND=JPIM)              :: nfiles, idummy_arr, npermcnt
+INTEGER(KIND=JPIM), allocatable :: perm_list(:), global_pool_offset(:)
+LOGICAL, allocatable            :: LL_poolmask(:), LL_filemask(:), LL_lastpool(:)
+INTEGER(KIND=JPIM)              :: fast_physproc, xfast, n_messages_required
+INTEGER(KIND=JPIM)              :: imp_type
+INTEGER(KIND=JPIM)              :: nfileno
+REAL(KIND=JPRB)                 :: ZHOOK_HANDLE
+
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK('MSGPASS_LOADOBS',0,ZHOOK_HANDLE)
+
+incore => null ()
+jncore => null ()
+ioaid  => null ()
+
+CL_called_from = 'MSGPASS_LOADOBS'
+call MPL_barrier(cdstring='MSGPASS_LOADOBS')
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_LOADOBS : Begin'
+kret = 0
+n_tables_read = 0
+it = oml_my_thread()
+
+!**********************************************
+! Pick up some database metadata
+!**********************************************
+io_method = db(khandle)%io_method
+LL_readonly = db(khandle)%readonly
+dbname = db(khandle)%name
+npools = db(khandle)%glbNpools
+
+!**********************************************
+! Skip message passing if necessary
+!**********************************************
+if (.NOT.db(khandle)%inuse) goto 99999
+if (io_method /= 4) goto 99999 ! only applicable for ODB_IO_METHOD=4
+
+!***************************************************************
+! Define whether using blocking or non-blocking message passing
+!***************************************************************
+#if defined(NECSX) && defined(BOM)
+imp_type = JP_BLOCKING_STANDARD
+#else
+imp_type = JP_NON_BLOCKING_STANDARD
+#endif
+
+call ODBMP_sync()
+
+!***************************************************************
+! Output diagnostics: database info
+!***************************************************************
+call output_db_diagnostics(waltim,CL_called_from,khandle,dbname,LLiotrace,CLmode,io_filesize,io_filesize_default,io_grpsize,hc32,LL_first_time)
+! Initialize a few variables
+datavolume(:) = 0
+nfiles = 0 ! no. of opened files on this PE
+this_io_grpsize = min(npools,io_grpsize)
+
+allocate(LL_poolmask(npools))
+allocate(LL_filemask(npools))
+allocate(LL_lastpool(npools))
+allocate(LL_mypool(npools))
+
+!***************************************************************
+! Define poolmask
+!***************************************************************
+LL_poolmask(1:npools) =  .TRUE. ! true means that take all these pools
+if (LL_readonly) then
+  call cODB_get_permanent_poolmask(khandle, 0, idummy_arr, npermcnt)
+  npermcnt = abs(npermcnt)
+  if (npermcnt > 0) then
+    allocate(perm_list(npermcnt))
+    perm_list(:) = 0
+    call cODB_get_permanent_poolmask(khandle, npermcnt, perm_list, iret)
+    LL_poolmask(1:npools) = .FALSE. ! By default: do *not* take these pools
+    do j=1,npermcnt
+      jj = perm_list(j)
+      if (jj >= 1 .and. jj <= npools)  LL_poolmask(jj) = .TRUE.
+    enddo
+    deallocate(perm_list)
+  endif
+endif
+
+
+!***************************************************************
+! Output diagnostics: poolmask
+!***************************************************************
+if (ODBMP_myproc == 1) then
+  if (all(LL_poolmask(1:npools))) then
+    write(0,'(1x,a,i5,a,i5,a)') &
+      & 'MSGPASS_LOADOBS: All pools in range [1..npools] will processed'
+  else
+    write(0,*)'MSGPASS_LOADOBS: Only the following pools will be processed:'
+    jj = 0
+    do j=1,npools
+      if (LL_poolmask(j)) then
+        write(0,'(1x,i7)',advance='no') j
+        jj = jj + 1
+        if (mod(jj,10) == 0 .AND. j < npools) write(0,*)
+      endif
+    enddo
+    if (jj > 0) write(0,*)
+  endif
+endif
+
+
+!***************************************************************
+! Get up-to-date IOAID database metadata
+!***************************************************************
+call comm_iomap(khandle, 1, iret)
+ioaid => db(khandle)%ioaid
+
+!***************************************************************
+! Calculate offset between
+! local pool numbers (within a fileblock) and global pool numbers
+! using IOAID db info
+!***************************************************************
+allocate(global_pool_offset(npools))
+call calculate_global_local_pool_offset(global_pool_offset,npools,ioaid,khandle)
+
+!***************************************************************
+! Pick up table names
+!***************************************************************
+ntables = ODB_getnames(khandle, '*', 'table')
+allocate(cltable(ntables))
+ntables = ODB_getnames(khandle, '*', 'table', cltable)
+
+allocate(LL_include_tbl(ntables))
+
+!***************************************************************
+! Construct mask of considered tables -> LL_include_tbl
+!***************************************************************
+call construct_mask_of_considered_tables(khandle,dbname,ntables,cltable,LL_include_tbl,nactive_tables)
+
+! If no tables to load then skip to end
+if (nactive_tables <= 0) then
+  if (ODBMP_myproc == 1) write(0,*)'***INFO: No active tables'
+  kret = 0
+  goto 99999
+endif
+
+!***************************************************************
+! Construct map between table id and active table id -> active_table_id
+!***************************************************************
+allocate(active_table_id(ntables))
+call construct_active_table_id_map(active_table_id,LL_include_tbl,ntables)
+
+!***************************************************************
+! Construct mask of pools owned by this task
+!***************************************************************
+do j=1,npools
+  pe = fast_physproc(j)
+  LL_mypool(j) = (pe == ODBMP_myproc)
+enddo
+
+
+!***************************************************************
+! Get current status of incore items -> ISTAT
+!***************************************************************
+allocate(istat(nstat,npools,nactive_tables))
+call get_status_of_incore_data(istat,npools,ntables,active_table_id,cltable,khandle,LL_mypool,LL_include_tbl)
+
+!-- Make istat-information globally available
+call ODBMP_global('MAX', istat)
+
+
+!************************************************************
+! Define IOPEs - IOPE_MAP maps each pool, table to an IO task
+!************************************************************
+allocate(iope_map(npools+1,nactive_tables))
+iope_map(:,:) = -1 ! Means: Any PE
+call assign_iopes(iope_map, ioaid, istat, io_filesize, this_io_grpsize, npools, global_pool_offset, LL_include_tbl, ntables, active_table_id, .TRUE.)
+
+
+!************************************************************
+! Calculate volume of data in each considered table
+!************************************************************
+allocate(data_bytes(nactive_tables))
+data_bytes(:) = 0
+call calculate_table_sizes(dbname, cltable, ioaid, istat, data_bytes, npools, ntables, LL_include_tbl, LL_mypool, LLiotrace, LLiomsgpasstrace, maxbytes, active_table_id)
+
+!-- Make data_bytes-information available for PE#1
+call ODBMP_global('SUM', data_bytes, LDREPROD=.false., root=1)
+
+!***************************************************************
+! Debug output
+!***************************************************************
+if ( (LLiotrace .or. LLiomsgpasstrace) .and. ODBMP_myproc == 1) then 
+  jtact = 0
+  do jt=1,ntables
+    if (.not.LL_include_tbl(jt)) cycle
+    jtact = active_table_id(jt)
+    CLtbl = cltable(jt)(2:)
+    write(0,'(1x,2(a,i5),a,f20.1,a)') &
+    & 'I/O-pe map for table "'//trim(CLtbl)//'", pool range=[1..npools], total ',&
+    & data_bytes(jtact),' bytes :'
+    write(0,'((10(1x,i5)))' ) (iope_map(j,jtact),j=1,npools)
+  enddo
+endif
+
+!***************************************************************
+! Predefine message tags for all used table,pools combinations 
+!   (global not local - as need to know tags of incoming messages from other tasks)
+! Loop through all table/pool combinations and determine if a message will need to be sent,
+!   if so, then define a tag for the send/recv to use. 
+!***************************************************************
+allocate(itags(npools+1,ntables))
+itags(:,:) = -1
+itag = 0 
+msgoff = 0
+n_messages_required = 0
+
+do jt=1,ntables
+  if (LL_include_tbl(jt)) then
+    !call define_filemask_for_this_table(LL_filemask, LL_lastpool, LL_poolmask, jt, npools, ioaid)
+    jtact = active_table_id(jt)
+    if (maxval(ioaid(1:npools,jt,IOAID_LENGTH),dim=1)>0) then
+      do j=1,npools
+        if (LL_poolmask(j)) then
+          if (ioaid(j,jt,IOAID_LENGTH)>0) then
+            destPE = fast_physproc(j)
+            !if (destPE /= ODBMP_myproc)then ! send message to owner pe, only if this pe is not the owner
+              itags(j,jt) = itag
+              itag = itag + 1
+              if (fast_physproc(iope_map(j,jtact))==ODBMP_myproc) then ! If this task is an iope for this pool/table
+  
+                nw = ioaid(j,jt,IOAID_LENGTH)/sizeof_int
+                msgoff = msgoff + nw ! Add up total volume of data that needs to be sent by this PE as required for jncore allocation
+                n_messages_required = n_messages_required + 1
+              endif
+            !endif
+          endif
+        endif
+      enddo
+    endif
+  endif
+enddo
+if (ODBMP_myproc == 1) write(0,*) 'Created itags array with MAX: ',maxval(itags(:,:)), ' and MIN: ',minval(itags(:,:))
+
+call allocate_jncore(jncore, msgoff, iret)
+
+allocate(jsendreq(n_messages_required))
+
+
+!***************************************************************
+!-- Main loops
+!***************************************************************
+
+!***************************************************************
+! Initialisation for NON BLOCKING message passing------------
+!***************************************************************
+nsent = 0
+msgoff = 0
+
+!************************************************************
+! Read / send section
+!************************************************************
+nsent = 0
+nread = 0
+nfiles = 0
+datavolume(:) = 0    ! Total volume of data stored on disk (by this PE)
+
+! If this PE is an IOPE for any tables/pools then read those files
+do jt=1,ntables
+  if (LL_include_tbl(jt)) then
+    jtact = active_table_id(jt)
+    if (maxval(ioaid(1:npools,jt,IOAID_LENGTH),dim=1)>0) then
+    !if (maxval(iope_map(1:npools,jtact))/=-1) then  ! only proceed with this table if there is data in it
+      CLtbl = cltable(jt)(2:) !-- Strip off the leading '@'-character
+      call diagnostic_output_table(data_bytes,jtact,CLtbl,CL_called_from)
+      io = -1 ! reset file handle as new table must also mean a new file
+      prev_fblk = -1
+      prev_fileno = -1
+      call define_filemask_for_this_table(LL_filemask, LL_lastpool, LL_poolmask, jt, npools, ioaid)
+      do j=1,npools
+        if (fast_physproc(iope_map(j,jtact))==ODBMP_myproc) then  ! If this pe is an iope for this pool/table
+          ! If non-zero data for this pool then read data from file
+          if (LL_poolmask(j).and.(ioaid(j,jt,IOAID_LENGTH)>0)) then
+            nw = ioaid(j,jt,IOAID_LENGTH)/sizeof_int
+            call allocate_incore(incore, nw + 1, iret)
+            call read_next_pool_from_hc32_file(dbname, filename, CLtbl, incore,ioaid,global_pool_offset,npools,io,hc32,NHDR,j,   &
+      &                                        jt,ipoolno,igrpsize,nbytes,nrows,ncols,npad,nw,jsta,nread, &
+      &                                        nfiles,datavolume,LL_poolmask,LL_lastpool,LLiotrace,prev_fblk,prev_fileno)
+            ! Send message (if required)
+            destPE = fast_physproc(j)
+            if (destPE /= ODBMP_myproc)then ! send message to owner pe, only if this pe is not the owner
+                itag = itags(j,jt)
+                call send_message_to_pe(nw,incore,jncore,msgoff,destPE,itag,imp_type,jsendreq,LLiomsgpasstrace, CLtbl,nsent)
+            else ! if this pe owns the pool, then no need to send message - put incore directly
+                call allocate_incore(incore, nw + 1, iret)
+                call put_data_incore_for_this_pool_table(khandle,CLtbl,filename,j,incore,NHDR)
+            endif
+          end if
+        endif
+      enddo
+      call io_close(filename, io, nread, npools, nfiles, datavolume, LLiotrace, iret)
+      n_tables_read = n_tables_read + 1
+    endif
+  endif
+enddo
+
+!************************************************************
+! Recieve section
+!************************************************************
+do jt=1,ntables
+  if (LL_include_tbl(jt)) then
+    CLtbl = cltable(jt)(2:) !-- Strip off the leading '@'-character
+    jtact = active_table_id(jt)
+    if (maxval(ioaid(1:npools,jt,IOAID_LENGTH),dim=1)>0) then
+      do j=1,npools
+        pe = fast_physproc(iope_map(j,jtact))   ! Source PE
+        if (pe /= ODBMP_myproc)then ! If source pe is not this PE, then receive message, otherwise the data has already been put incore so do nothing
+          if (LL_mypool(j)) then
+            nw = ioaid(j,jt,IOAID_LENGTH)/sizeof_int
+            if (LL_poolmask(j) .AND. nw > 0) then
+              itag = itags(j,jt)
+              call allocate_incore(incore, nw + 1, iret)
+              call receive_message_for_this_pool_table(pe,nw,itag,j,LLiomsgpasstrace,incore,filename,CLtbl,CL_called_from)
+              call put_data_incore_for_this_pool_table(khandle,CLtbl,filename,j,incore,NHDR)
+            endif
+          endif
+        endif
+      enddo
+    endif
+  endif
+enddo
+
+kret = n_tables_read ! Return code of msgpass_loadobs = No. of tables stored/loaded
+
+datavolume(0) = nfiles
+call ODBMP_global('SUM', datavolume, LDREPROD=.false., root=1)
+nfiles = datavolume(0)
+
+!***************************************************************
+! Output: Summary
+!***************************************************************
+call output_diagnostics_final(waltim,CL_called_from,datavolume,dbname,CLmode,it,nfiles)
+
+99999 continue
+
+!***************************************************************
+! Tidy up
+!***************************************************************
+if (allocated(iope_map))           deallocate(iope_map)
+if (allocated(LL_mypool))          deallocate(LL_mypool)
+if (allocated(LL_include_tbl))     deallocate(LL_include_tbl)
+if (associated(incore))            deallocate(incore)
+if (associated(jncore))            deallocate(jncore)
+if (allocated(istat))              deallocate(istat)
+if (allocated(data_bytes))         deallocate(data_bytes)
+if (allocated(cltable))            deallocate(cltable)
+if (allocated(LL_poolmask))        deallocate(LL_poolmask)
+if (allocated(LL_filemask))        deallocate(LL_filemask)
+if (allocated(LL_lastpool))        deallocate(LL_lastpool)
+if (allocated(global_pool_offset)) deallocate(global_pool_offset)
+if (allocated(itags))              deallocate(itags)
+if (allocated(jsendreq))           deallocate(jsendreq)
+if (allocated(active_table_id))    deallocate(active_table_id)
+
+nullify(ioaid)
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_LOADOBS : End'
+IF (LHOOK) CALL DR_HOOK('MSGPASS_LOADOBS',1,ZHOOK_HANDLE)
+      
+END SUBROUTINE msgpass_loadobs
+
diff --git a/odb/src/lib/msgpass_storedata.F90 b/odb/src/lib/msgpass_storedata.F90
new file mode 100644
index 0000000..e08a46d
--- /dev/null
+++ b/odb/src/lib/msgpass_storedata.F90
@@ -0,0 +1,769 @@
+SUBROUTINE msgpass_storedata(khandle, kret)
+
+! A routine to exchange ODB-data between processors
+! Called from module ODB: ODB_close()
+
+! P. Marguinaud : 10-10-2013 : Nullify pointers
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+use oml_mod   ,only : oml_set_lock, oml_unset_lock, oml_my_thread
+USE odb_module
+USE mpl_module
+USE odbio_msgpass
+USE str       ,ONLY : sadjustl 
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+
+INTEGER(KIND=JPIM)              :: io_method, jt, j, jj, ntables, iret, maxbytes
+INTEGER(KIND=JPIM)              :: nw, nwmax, nbytes, nrows, ncols, npad, igrpsize, ipoolno, npools
+INTEGER(KIND=JPIM)              :: itag, pe, destPE, io, isendreq, max_iope, iprev, idx
+INTEGER(KIND=JPIM), allocatable :: itags(:,:)
+INTEGER(KIND=JPIM)              :: iexpect_len
+INTEGER(KIND=JPIM), allocatable :: iope_map(:,:)
+character(len=maxvarlen), allocatable :: cltable(:)
+logical, allocatable            :: LL_mypool(:), LL_include_tbl(:), LL_write_tbl(:), LL_has_backup(:,:)
+logical                         :: LL_readonly
+logical                         :: LL_check_len
+logical, save                   :: LL_first_time = .TRUE.
+logical, save                   :: LL_write_empty = .FALSE.
+INTEGER(KIND=JPIM), save        :: iwrite_empty = 0
+INTEGER(KIND=JPIM), parameter   :: io_filesize_default = 32 ! in megabytes; see ../aux/newio.c, too
+INTEGER(KIND=JPIM), save        :: io_filesize = 1
+INTEGER(KIND=JPIM), save        :: io_grpsize = -1
+INTEGER(KIND=JPIM), save        :: io_backup_enable = 0 ! By default do *NOT* enable back ups (thanks Bob C.!!)
+INTEGER(KIND=JPIM), parameter   :: io_trace_default = 0
+INTEGER(KIND=JPIM), save        :: io_trace = 0
+INTEGER(KIND=JPIM), parameter   :: io_msgpass_trace_default = 0
+INTEGER(KIND=JPIM), save        :: io_msgpass_trace = 0
+logical, save                   :: LLiotrace = .FALSE.
+logical, save                   :: LLiomsgpasstrace = .FALSE.
+character(len=1), parameter     :: CLtab = char(9)
+character(len=1)                :: CLmode='w', CLtmp
+character(len=maxvarlen)        :: dbname, CLtbl, CLbytes
+character(len=4096)             :: clenv, filename, CLdirname, CLbasename
+
+INTEGER(KIND=JPIM), parameter   :: maxsize_mb = 1000 ! Maximum filesize in megabytes for HC32-file
+INTEGER(KIND=JPIM)              :: nwrite, nfileno
+INTEGER(KIND=JPIM)              :: jmin, jmax, it, is_compressed
+INTEGER(KIND=JPIM), allocatable :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), parameter   :: NHDR = 6
+INTEGER(KIND=JPIM)              :: ihdr(NHDR), idum(1), this_io_grpsize, itables, cur_io_grpsize
+INTEGER(KIND=JPIM)              :: nactive_tables, jtact, iope, icnt_not_active
+INTEGER(KIND=JPIM)              :: itime(8),imsgpass_Time,imsgpass_Date,i_consider,jsta, i_write
+INTEGER(KIND=JPIM), pointer     :: incore(:)
+!J---Start---
+INTEGER(KIND=JPIM), parameter   :: MMSGSND = 1000
+INTEGER(KIND=JPIM), pointer     :: jncore(:)
+INTEGER(KIND=JPIM)              :: MJNCORE = 20000000
+INTEGER(KIND=JPIM)              :: msgoff, msgsnd, njmax, j1, j2, jreset
+INTEGER(KIND=JPIM)              :: jsendreq(MMSGSND)
+!J---End---
+INTEGER(KIND=JPIM), save        :: hc32(0:1) = (/0,0/) ! "HC32" & its reverse/byteswap (to be filled) 
+INTEGER(KIND=JPIM), parameter   :: reset_updated_flag = 1
+INTEGER(KIND=JPIM), POINTER     :: ioaid(:,:,:) ! A shorthand notation
+REAL(KIND=JPRB), allocatable    :: data_bytes(:) ! nactive_tables
+REAL(KIND=JPRB)                 :: datavolume(0:ODBMP_nproc), waltim(2), sum_datavolume
+INTEGER(KIND=JPIM)              :: nfiles, idummy_arr, npermcnt
+INTEGER(KIND=JPIM), allocatable :: perm_list(:), global_pool_offset(:)
+REAL(KIND=JPRB), external       :: util_walltime  ! now [23/1/04] from ifsaux/support/drhook.c
+INTEGER(KIND=JPIM)              :: fast_physproc, xfast, nfblk, irefblk
+INTEGER(KIND=JPIM)              :: imp_type
+LOGICAL                         :: L2,L3,L4
+REAL(KIND=JPRB)                 :: ZHOOK_HANDLE
+
+real(KIND=JPRB)                 :: t0,timef,ttab,tloop,ttloop
+real(KIND=JPRB)                 :: tprebar,tpostbar
+real(KIND=JPRB), allocatable    :: ttwrite(:),ttsend(:),ttrecv(:),ttwait(:),ttclose(:)
+real(KIND=JPRB), allocatable    :: tbar(:), ttable(:), ttcomm(:)
+real(KIND=JPRB), allocatable    :: sendmb(:),recvmb(:)
+integer(kind=JPIM), allocatable :: sendcnt(:),recvcnt(:)
+integer(kind=JPIM)              :: JWRITE=0
+
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK('MSGPASS_STOREDATA',0,ZHOOK_HANDLE)
+
+incore => null ()
+jncore => null ()
+ioaid  => null ()
+
+call MPL_barrier(cdstring='MSGPASS_STOREDATA')
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_STOREDATA : Begin'
+kret = 0
+itables = 0
+it = oml_my_thread()
+
+if (.NOT.db(khandle)%inuse) goto 99999
+
+io_method = db(khandle)%io_method
+if (io_method /= 4) goto 99999 ! only applicable for ODB_IO_METHOD=4
+
+LL_readonly = db(khandle)%readonly
+
+if (LL_readonly) goto 99999
+
+#if defined(NECSX) && defined(BOM)
+imp_type = JP_BLOCKING_STANDARD
+#else
+imp_type = JP_NON_BLOCKING_STANDARD
+#endif
+
+dbname = db(khandle)%name
+
+CALL ODBMP_sync()
+
+waltim(1) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  write(0,'(1x,a,i8.8,2x,i6.6)') &
+  '=== MSGPASS_STOREDATA of db="'//trim(dbname)// &
+  '" for mode='//CLmode//' started on ',imsgpass_date,imsgpass_time
+endif
+
+datavolume(:) = 0
+nfiles = 0 ! no. of opened files on this PE
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_STOREDATA ==='
+if (LL_first_time) then
+!$ CALL OML_SET_LOCK()
+!$OMP FLUSH(LL_first_time)
+ if (LL_first_time) then
+  !-- HC32-magic number
+  CALL get_magic_hc32(0, hc32(0))
+  !-- HC32-magic number byteswap i.e. reverse
+  CALL get_magic_hc32(1, hc32(1))
+  !-- I/O tracing
+  CALL util_igetenv('ODB_IO_TRACE', io_trace_default, io_trace)
+  LLiotrace = (io_trace /= 0)
+  !-- Message pass tracing
+  CALL util_igetenv('ODB_IO_MSGPASS_TRACE', io_msgpass_trace_default, io_msgpass_trace)
+  LLiomsgpasstrace = (io_msgpass_trace /= 0)
+  !-- Make sure these stay consistent with the ones obtained in ../aux/newio.c !
+  CALL util_igetenv('ODB_IO_FILESIZE', io_filesize_default, io_filesize) ! in megabytes
+  if (io_filesize <= 0) io_filesize = io_filesize_default
+  if (io_filesize > maxsize_mb) io_filesize = maxsize_mb ! never exceed this many megabytes
+  CALL util_igetenv('ODB_IO_GRPSIZE', 0, io_grpsize)
+  if (io_grpsize <= 0) then ! try $NPES_AN
+    CALL util_igetenv('NPES_AN', 0, io_grpsize)
+  endif
+  if (io_grpsize <= 0) io_grpsize = ODBMP_nproc
+  CALL util_igetenv('ODB_IO_BACKUP_ENABLE', 0, io_backup_enable)
+  CALL util_igetenv('ODB_WRITE_EMPTY_FILES', 0, iwrite_empty)
+!*AF  LL_write_empty = (iwrite_empty /= 0)
+  LL_write_empty = (iwrite_empty == 1)
+  if (ODBMP_myproc == 1) then
+    write(0,*)'                 HC32=',hc32
+    write(0,*)'         ODB_IO_TRACE=',io_trace
+    write(0,*)' ODB_IO_MSGPASS_TRACE=',io_msgpass_trace
+    write(0,*)'      ODB_IO_FILESIZE=',io_filesize,' MBytes'
+    write(0,*)'       ODB_IO_GRPSIZE=',io_grpsize
+    write(0,*)'ODB_WRITE_EMPTY_FILES=',iwrite_empty, LL_write_empty
+    write(0,*)' ODB_IO_BACKUP_ENABLE=',io_backup_enable
+  endif
+  LL_first_time = .FALSE.
+!$OMP FLUSH(LL_first_time)
+ endif
+!$ CALL OML_UNSET_LOCK()
+endif
+
+if (ODBMP_myproc == 1) then
+  write(0,*) ODBMP_myproc,&
+   & ': MSGPASS_STOREDATA() khandle=',&
+   & khandle
+endif
+
+npools = db(khandle)%glbNpools
+this_io_grpsize = min(npools,io_grpsize) 
+
+!if (ODBMP_myproc == 1) write(0,*) 'this_io_grpsize, npools=',&
+!                                   this_io_grpsize, npools
+
+if (ODBMP_myproc == 1) then
+  write(0,'(1x,a,i5,a,i5,a)') &
+    & 'MSGPASS_STOREDATA: All pools in range [1..npools] will processed'
+endif
+
+CALL comm_iomap(khandle, 1, iret) ! Get up to date IOAID
+
+ioaid => db(khandle)%ioaid
+
+allocate(global_pool_offset(npools))
+global_pool_offset(:) = 0
+nfblk = db(khandle)%nfileblocks
+ipoolno = 0 
+irefblk = 0
+do j=1,npools
+  if (ioaid(j,1,IOAID_FBLOCK) /= irefblk) then
+    irefblk = ioaid(j,1,IOAID_FBLOCK)
+    ipoolno = j - 1
+  endif
+  global_pool_offset(j) = ipoolno
+enddo
+
+ntables = ODB_getnames(khandle, '*', 'table')
+allocate(cltable(ntables))
+ntables = ODB_getnames(khandle, '*', 'table', cltable)
+
+allocate(LL_mypool(npools))
+allocate(LL_include_tbl(ntables))
+allocate(LL_write_tbl(ntables))
+
+if(JWRITE>0) then
+  allocate(ttable(ntables))
+  allocate(tbar(ntables))
+  allocate(ttwrite(ntables))
+  allocate(ttsend(ntables))
+  allocate(ttrecv(ntables))
+  allocate(ttwait(ntables))
+  allocate(ttclose(ntables))
+  allocate(ttcomm(ntables))
+  allocate(sendmb(ntables))
+  allocate(recvmb(ntables))
+  allocate(sendcnt(ntables))
+  allocate(recvcnt(ntables))
+endif
+
+do j=1,npools
+  pe = fast_physproc(j)
+  LL_mypool(j) = (pe == ODBMP_myproc)
+enddo
+
+!-- New approach (5-Sep-2006/SS)
+do jt=1,ntables
+  CALL cODB_table_is_considered(cltable(jt), i_consider)
+  LL_include_tbl(jt) = (i_consider == 1)
+enddo
+
+!-- Anne Fouilloux (23/02/10)
+do jt=1,ntables
+  CALL cODB_table_is_writable(cltable(jt), i_write)
+  LL_write_tbl(jt) = (i_write == 1)
+enddo
+
+icnt_not_active = COUNT(.not.LL_include_tbl(:))
+nactive_tables = ntables - icnt_not_active
+if (ODBMP_myproc == 1) then
+  write(0,*)'***INFO: Considering the following ',&
+   & nactive_tables,' tables for database="'//trim(dbname)//'" :' 
+! do jt=1,ntables
+!   if (LL_include_tbl(jt)) write(0,*)'  '//trim(cltable(jt))
+! enddo
+  if (icnt_not_active == 0) then
+    write(0,*)'***INFO: All tables considered'
+  endif
+endif
+
+if (nactive_tables <= 0) then
+  if (ODBMP_myproc == 1) write(0,*)'***INFO: No active tables'
+  kret = 0
+  goto 99999
+endif
+
+allocate(istat(nstat,npools,nactive_tables))
+
+allocate(iope_map(npools+1,1))
+if (io_backup_enable /= 0) then
+  allocate(LL_has_backup(npools,ntables))
+  LL_has_backup(:,:) = .FALSE.
+endif
+
+allocate(data_bytes(nactive_tables))
+
+!-- Get current status of incore items
+istat(:,:,:) = 0
+jtact = 0
+STAT_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle STAT_LOOP 
+  if (.not.LL_write_tbl(jt)) cycle STAT_LOOP  ! do not proceed if the table is not writable (store only)
+  jtact = jtact + 1
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- Gather size information of incore items for memory allocations
+  do j=1,npools
+    if (LL_mypool(j)) then
+      CALL newio_status_incore32(khandle, j, istat(1,j,jtact), nstat, CLtbl, iret)
+!*AF      write(0,*) 'msgpass_storedata table = ', trim(CLtbl), ' pool = ', j, ' nrows = ', istat(2,j,jtact), ' ncols = ', istat(3,j,jtact), &
+!*AF                 'updated = ', istat(4,j,jtact)
+    endif
+  enddo
+enddo STAT_LOOP
+
+!-- Make istat-information globally available
+CALL ODBMP_global('MAX', istat)
+
+!J---Start----
+!-- Initialisation for NON BLOCKING message passing------------
+call allocate_jncore(jncore, MJNCORE,iret)
+njmax=MJNCORE
+! msgsnd = 0
+! msgoff = 0
+!J---End---
+
+
+
+!-- Predefine message tags for all used table,pools combinations 
+!  (global not local - as need to tags of incoming messages from other tasks)
+! Loop through all table/pool combinations and determine if a message will need to be sent,
+!   if so, then define a tag for the send/recv to use. 
+allocate(itags(npools+1,ntables))
+itags(:,:) = -1
+itag = 0
+jtact =0
+TABLE_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle TABLE_LOOP
+  if (.not.LL_write_tbl(jt)) cycle TABLE_LOOP ! do not proceed if table is not writable
+  jtact = jtact + 1
+
+  if (MAXVAL(istat(ISTAT_UPDATED,1:npools,jtact)) <= 0) then
+    cycle TABLE_LOOP
+  endif
+
+  maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+  if (.not. LL_write_empty .AND. maxbytes <= 0) then
+    cycle TABLE_LOOP
+  endif
+
+  j2=0
+  jreset=0
+  STORE_WHILE0: do while (j2.lt.npools)
+   j1=j2+1
+   STORE_SEND_LOOP0: do j=j1,npools    ! Send Loop
+
+    nbytes = istat(ISTAT_NBYTES,j,jtact)
+    nrows = istat(ISTAT_NROWS,j,jtact)
+    if ((nbytes > 0 .and. (iwrite_empty /= 2 .or. nrows > 0)) .OR. (nbytes <= 0 .AND. LL_write_empty)) then
+   itags(j,jt) = itag
+        itag = itag + 1
+    endif
+    j2=j  ! Last j successfully completed
+   enddo STORE_SEND_LOOP0
+  enddo STORE_WHILE0
+enddo TABLE_LOOP
+
+!-- A procedure for storing data to disk (horizontal concatenation; io_method=4)
+jtact = 0
+if(JWRITE>0) then
+  ttloop=0.d0
+  ttwrite=0.d0
+  ttrecv=0.d0
+  ttsend=0.d0
+  ttwait=0.d0
+  ttclose=0.d0
+  sendmb=0.d0
+  recvmb=0.d0
+  sendcnt=0
+  recvcnt=0
+  call MPL_BARRIER()
+  ttab=timef()
+  tpostbar=timef()
+endif
+
+STORE_TABLE: do jt=1,ntables
+  if(JWRITE>0) then
+    tprebar=timef()
+    ttable(jt-1)=tprebar-tpostbar
+    call MPL_BARRIER()
+    tpostbar=timef()
+    tbar(jt-1)=tpostbar-tprebar
+  endif
+  if (.not.LL_include_tbl(jt)) cycle STORE_TABLE
+  if (.not.LL_include_tbl(jt)) cycle STORE_TABLE
+  if (.not.LL_write_tbl(jt)) cycle STORE_TABLE ! do not proceed if table is not writable
+  jtact = jtact + 1
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+  if(JWRITE>0) write(0,*) "JJJ jt, TABLE =",jt,trim(CLtbl) 
+
+!-- No updates found ==> bail out & continue with the next table
+  if (MAXVAL(istat(ISTAT_UPDATED,1:npools,jtact)) <= 0) then
+!   if (ODBMP_myproc == 1) write(0,*) &
+!    & '***Warning: STOREing table="'//trim(CLtbl)//'" skipped since not updated' 
+    cycle STORE_TABLE
+  endif
+
+!-- To start with : *rename* any existing table-files into backup file
+  do j=1,npools
+!! The following call to codb_remove_tablefile() has been removed since
+!! if job finished/aborted before updated version has been written to disk
+!! the whole database would be corrupt (SS/4-Jul-2003)
+!! Instead, backup files will be created and then removed at the very end
+!!      if (LL_mypool(j)) CALL codb_remove_tablefile(dbname, CLtbl, j, iret)
+    if (io_backup_enable /= 0) then
+      if (LL_mypool(j)) then ! More failsafe
+        CALL makefilename(dbname, CLtbl, j, filename)
+        CALL true_dirname_and_basename(trim(filename), CLdirname, CLbasename)
+        CALL codb_rename_file(trim(filename), trim(CLdirname)//'/'//trim(CLbasename)//'.BACKUP', iret)
+        LL_has_backup(j,jt) = (iret == 0)
+      endif
+    endif
+    ioaid(j,jt,IOAID_FILENO) = 0
+    ioaid(j,jt,IOAID_OFFSET) = 0
+    ioaid(j,jt,IOAID_LENGTH) = 0
+    if (ioaid(j,jt,IOAID_GRPSIZE) == 0) ioaid(j,jt,IOAID_GRPSIZE) = this_io_grpsize
+    ioaid(j,jt,IOAID_NROWS)  = 0
+  enddo
+
+!-- If no. of bytes to be stored never > 0, then bail out & continue with the next table
+  maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+  if (.not. LL_write_empty .AND. maxbytes <= 0) then
+!     if (ODBMP_myproc == 1) write(0,*) &
+!      & '***Warning: STOREing table="'//trim(CLtbl)//'" skipped since empty' 
+    cycle STORE_TABLE
+  endif
+
+!-- Allocate data buffer
+  nwmax = NHDR + max(1,(maxbytes + sizeof_int - 1)/sizeof_int)
+  CALL allocate_incore(incore, nwmax, iret)
+!J---Start---
+  if(nwmax .gt. njmax) then
+    njmax=nwmax
+    CALL allocate_jncore(jncore, njmax, iret)
+  endif 
+!J---End---
+
+!-- Determine I/O-PEs
+  CALL make_iopes(iope_map, jtact, io_filesize, this_io_grpsize, npools, global_pool_offset, istat)
+
+!-- Gather total no. of bytes information in advance
+  data_bytes(jtact) = 0
+  do j=1,npools
+    nw = 0
+    cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+    nbytes = istat(ISTAT_NBYTES,j,jtact)
+    nrows = istat(ISTAT_NROWS,j,jtact)
+!*AF  if ODB_WRITE_EMPTY_FILES=2 we do not really write...
+    if ((nbytes > 0 .and. (iwrite_empty /= 2 .or. nrows > 0)) .OR. (nbytes <= 0 .AND. LL_write_empty)) then
+      nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+    endif
+    if (iope_map(j,1) /= iope_map(j+1,1) .OR. &
+       & mod(j-global_pool_offset(j), cur_io_grpsize) == 0 .OR. &
+       & j == npools) then 
+      !-- Account for yet another file ending and allocate space for "HC32" 
+      !   i.e. 4 bytes which was so far unaccounted for when file was "opened"
+      nw = nw + 1
+    endif
+    data_bytes(jtact) = data_bytes(jtact) + nw * sizeof_int
+  enddo
+
+  if (ODBMP_myproc == 1) then
+    write(CLbytes,'(f20.1)') data_bytes(jtact)
+    jj = index(CLbytes,'.')
+    if (jj > 0) CLbytes(jj:) = ' '
+    write(0,'(1x,a)')'STOREing table="'//trim(CLtbl)//'" total = '//&
+     & trim(CLbytes)//' bytes' 
+  endif
+
+!-- Worker-loop: send/recv data and perform write-I/O
+  isendreq=0
+  nwrite = 0
+  nfileno = 0
+  io = -1
+  CALL codb_strblank(filename)
+
+  if(JWRITE>1)  then
+    if(trim(CLtbl).eq."body") then
+      do j=1,npools
+        write(0,'(a,a,a,3i4)') "JJJ CLtbl,j,pe,iope",trim(CLtbl), &
+          & " ",j,fast_physproc(j),fast_physproc(iope_map(j,1))
+      enddo
+    endif
+  endif
+  if(JWRITE>0) tloop=timef()
+!J---Start---
+!-- Initialisation for NON BLOCKING message passing------------
+  msgsnd = 0
+  msgoff = 0
+  j2=0
+  jreset=0
+  STORE_WHILE: do while (j2.lt.npools)
+   j1=j2+1
+!  STORE_SEND_LOOP: do j=1,npools    ! Send Loop
+   STORE_SEND_LOOP: do j=j1,npools    ! Send Loop
+!J---End---
+
+    itag = itags(j,jt)
+
+    iope = fast_physproc(iope_map(j,1))
+    pe = fast_physproc(j)
+    nw = 0
+    cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+    nbytes = istat(ISTAT_NBYTES,j,jtact)
+    nrows = istat(ISTAT_NROWS,j,jtact)
+!*AF  if ODB_WRITE_EMPTY_FILES=2 we do not really write...
+    if ((nbytes > 0 .and. (iwrite_empty /= 2 .or. nrows > 0)) .OR. (nbytes <= 0 .AND. LL_write_empty)) then
+!*AF        write(0,*) 'pool = ', j, ' LL_mypool(j) = ', LL_mypool(j), ' nrows = ', nrows, iwrite_empty, nbytes
+      if (LL_mypool(j)) then ! This is my pool
+        nrows = istat(ISTAT_NROWS,j,jtact)
+        ncols = istat(ISTAT_NCOLS,j,jtact)
+        npad = 1
+        nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+        if (mod(nbytes,sizeof_int) /= 0) incore(nw) = 0 ! make sure the last word is FULLY zeroed first
+        ipoolno = mod(j-1-global_pool_offset(j),cur_io_grpsize) + 1 ! Pool# relative to the beginning of this IO_GRP
+        incore(1) = ipoolno
+        incore(2) = cur_io_grpsize
+        incore(3) = nbytes
+        incore(4) = nrows
+        incore(5) = ncols
+        incore(6) = npad ! Data padded to the nearest INTEGER*4 word boundary
+        CALL newio_get_incore32(khandle, j, incore(NHDR + 1), maxbytes, &
+         & reset_updated_flag, CLtbl, iret) 
+        if (iret /= nbytes) then
+          CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to get_incore() correct no. of bytes', iret, nbytes, j, &
+           & filename, kdata=incore(1:NHDR)) 
+        endif
+
+        nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+
+!J      if (iope /= ODBMP_myproc) then ! I am *not* an I/O-PE ==> send to the I/O-PE
+                                       ! Send always
+          destPE = iope
+          if (LLiomsgpasstrace) &
+            & write(0,'(i5,a,i5,a,2i12)') &
+            & ODBMP_myproc,':STORE: Sending to ',destPE,', tag,nw=',itag,nw
+          if(msgoff+nw > njmax .or. msgsnd .eq. MMSGSND) then
+            if(j>j1) then
+              jreset=jreset+1
+              if(JWRITE>0) write(0,*) "JJJ Reset jncore: jreset,jt,j,j1,msgoff,nw,MJNCORE,msgsnd,MSGSND=", &
+                 & jreset,jt,j,j1,msgoff,nw,njmax,msgsnd,MMSGSND
+              EXIT
+            else
+              if(msgsnd .gt. 0) then
+                if(JWRITE>0) t0=timef()
+                  CALL mpl_wait(jncore, KREQUEST=JSENDREQ(1:msgsnd),CDSTRING="MSGPASS_STOREDATA Wait")
+                if(JWRITE>0) ttwait(jt)=ttwait(jt)+timef()-t0
+              endif
+              msgsnd=0
+              msgoff=0
+            endif
+          endif
+          msgsnd=msgsnd+1
+          jncore(msgoff+1:msgoff+nw)=incore(1:nw)
+          if(JWRITE>0) then
+            t0=timef()
+            sendmb(jt)=sendmb(jt)+4.0d-6*nw
+            sendcnt(jt)=sendcnt(jt)+1
+          endif
+          if (itag == -1) CALL ODB_abort('MSGPASS_STOREDATA', 'Aborting : itag not set correctly for mpl_send ',iret)
+          CALL mpl_send(jncore(msgoff+1:msgoff+nw), KDEST=destPE, KTAG=itag, &
+             & KMP_TYPE=imp_type,KREQUEST=JSENDREQ(msgsnd), &
+             & CDSTRING='STORE: Send data to I/O-PE; table=@'//trim(CLtbl)) 
+          if(JWRITE>0) ttsend(jt)=ttsend(jt)+timef()-t0
+          msgoff=msgoff+nw
+          if (LLiomsgpasstrace) &
+            & write(0,'(i5,a,i5,a,2i12)') &
+            & ODBMP_myproc,':STORE: Sent to ',destPE,', tag,isendreq=',itag,isendreq
+!J          if (iwrite_empty /= 2 .and. imp_type == JP_NON_BLOCKING_STANDARD) CALL mpl_wait(incore, KREQUEST=ISENDREQ)
+!J      endif  ! Am sending always
+      endif
+    endif ! if (nbytes > 0 .OR. (nbytes <= 0 .AND. ...
+    j2=j  ! Last j successfully completed
+  enddo STORE_SEND_LOOP
+
+  if(JWRITE>0) then
+    if(jreset == 0)  then
+      call mpl_barrier()
+      write(0,*) "JJJ Calling Barrier: jt=",jt
+    endif
+  endif
+
+! STORE_RECV_LOOP: do j=1,npools ! Recv loop
+  STORE_RECV_LOOP: do j=j1,j2                                ! Recv
+
+    itag = itags(j,jt)
+
+    iope = fast_physproc(iope_map(j,1))
+    pe = fast_physproc(j)
+    nw = 0
+    cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+    nbytes = istat(ISTAT_NBYTES,j,jtact)
+    nrows = istat(ISTAT_NROWS,j,jtact)
+!*AF  if ODB_WRITE_EMPTY_FILES=2 we do not really write...
+    if ((nbytes > 0 .and. (iwrite_empty /= 2 .or. nrows > 0)) .OR. (nbytes <= 0 .AND. LL_write_empty)) then
+!*AF        write(0,*) 'pool = ', j, ' LL_mypool(j) = ', LL_mypool(j), ' nrows = ', nrows, iwrite_empty, nbytes
+      if (iope == ODBMP_myproc) then
+        if (LLiomsgpasstrace) &
+          & write(0,'(i5,a,i5,a,2i12)') &
+          & ODBMP_myproc,':STORE: Receiving from ',pe,', tag,nw(max)=',itag,size(incore)
+        if(JWRITE>0) t0=timef()
+        if (itag == -1) CALL ODB_abort('MSGPASS_STOREDATA', 'Aborting: itag not set correctly for mpl_recv ',iret)
+        CALL mpl_recv(incore, KSOURCE=pe, KTAG=itag, KOUNT=nw, &
+         & CDSTRING='STORE: Recv data for I/O-PE; table=@'//trim(CLtbl)) 
+        if(JWRITE>0) then
+          ttrecv(jt)=ttrecv(jt)+timef()-t0
+          recvmb(jt)=recvmb(jt)+4.0d-6*nw
+          recvcnt(jt)=recvcnt(jt)+1
+        endif
+        if (LLiomsgpasstrace) &
+          & write(0,'(i5,a,i5,a,2i12)') &
+          & ODBMP_myproc,':STORE: Received from ',pe,', tag,nw=',itag,nw
+      endif
+    endif ! if (nbytes > 0 .OR. (nbytes <= 0 .AND. ...
+
+    if (nw > 0 .AND. iope == ODBMP_myproc) then 
+      !-- I am an I/O-PE, but not necessarely the owner of the pool;
+      !   however, I know the file offsets & lengths, so I should record them in ioaid
+
+      CALL io_checkopen(dbname, filename, CLtbl, io, j, nwrite, cur_io_grpsize, LDread=.FALSE., &
+                        LLiotrace=LLiotrace, hc32=hc32, global_pool_offset=global_pool_offset, &
+                        kfileno=nfileno, kret=iret)
+      nrows = incore(4)
+      ncols = incore(5)
+
+      if(JWRITE>1) write(0,*) "JJJ write bytes,filename=",4*nw,trim(filename)
+      if(JWRITE>0) t0=timef()
+      CALL cma_writei(io, incore(1), NHDR, iret) ! writeI; prepare for be2le conversion
+      if (iret /= NHDR) CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to write data header', iret, NHDR, j, &
+       & filename, kdata=incore(1:NHDR)) 
+  
+      CALL cma_writeb(io, incore(NHDR+1), (nw - NHDR) * sizeof_int, iret) ! writeB; raw data xfer
+      if (iret /= (nw - NHDR) * sizeof_int) then
+        CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to write actual data', iret, &
+                      (nw - NHDR) * sizeof_int, j, filename)
+      endif
+      if(JWRITE>0) ttwrite(jt)=ttwrite(jt)+timef()-t0
+
+      ioaid(j,jt,IOAID_FILENO) = nfileno
+      ioaid(j,jt,IOAID_OFFSET) = nwrite
+      ioaid(j,jt,IOAID_LENGTH) = nw * sizeof_int
+      ioaid(j,jt,IOAID_NROWS)  = nrows
+      ioaid(j,jt,IOAID_NCOLS)  = ncols
+
+      nwrite = nwrite + nw * sizeof_int
+    endif
+
+    if (io /= -1 .AND. &
+       & (iope_map(j,1) /= iope_map(j+1,1) .OR. &
+       & mod(j-global_pool_offset(j), cur_io_grpsize) == 0)) then 
+      if(JWRITE>0) write(0,*) "JJJ close table,filename=",trim(CLtbl)," ",trim(filename)
+      if(JWRITE>0) t0=timef()
+      CALL io_close(filename, io, nwrite, j, nfiles, datavolume, LLiotrace, iret)
+      if(JWRITE>0) ttclose(jt)=ttclose(jt)+timef()-t0
+    endif
+   enddo STORE_RECV_LOOP
+   if(JWRITE>0) ttloop=ttloop+timef()-tloop
+!J---Start----
+  enddo STORE_WHILE
+  if(msgsnd.ge.1) then
+    if(JWRITE>0) t0=timef()
+    CALL mpl_wait(jncore, KREQUEST=JSENDREQ(1:msgsnd),CDSTRING="MSGPASS_STOREDATA Wait")
+    if(JWRITE>0) ttwait(jt)=ttwait(jt)+timef()-t0
+    msgsnd=0
+    msgoff=0
+  endif
+!J---End----
+
+  if(JWRITE>0) write(0,*) "JJJ close table,filename=",trim(CLtbl)," ",trim(filename)
+  if(JWRITE>0) t0=timef()
+  CALL io_close(filename, io, nwrite, npools, nfiles, datavolume, LLiotrace, iret)
+  if(JWRITE>0) ttclose(jt)=ttclose(jt)+timef()-t0
+
+  itables = itables + 1
+enddo STORE_TABLE
+
+if(JWRITE>0) then
+  ttable(ntables)=timef()-tpostbar
+  tprebar=timef()
+  call mpl_barrier()
+  tbar(ntables)=timef()-tprebar
+  ttab=timef()-ttab
+  do jt=1,ntables
+    ttcomm(jt)=ttsend(jt)+ttrecv(jt)+ttwait(jt)
+  enddo
+  write(0,'(a,10f10.0)') "JJJ time tab,loop=",ttab,ttloop
+  write(0,'(a,50f9.0)') "JJJ send MB     =",(sendmb(jt),jt=1,ntables)
+  write(0,'(a,50i9)')   "JJJ send count  =",(sendcnt(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ send time   =",(ttsend(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ wait time   =",(ttwait(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ close time  =",(ttclose(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ recv MB     =",(recvmb(jt),jt=1,ntables)
+  write(0,'(a,50i9)')   "JJJ recv count  =",(recvcnt(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ recv time   =",(ttrecv(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ comm time   =",(ttcomm(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ write time  =",(ttwrite(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ table time  =",(ttable(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ barier time =",(tbar(jt),jt=1,ntables)
+  deallocate(ttable,tbar,ttcomm)
+  deallocate(ttwrite,ttsend,ttrecv,ttwait,ttclose,sendmb,recvmb,sendcnt,recvcnt)
+endif
+
+kret = itables ! No. of tables stored/loaded
+
+CALL comm_iomap(khandle, 2, iret) ! Propagate up to date IOAID's
+
+!-- Remove backup files where created
+jtact = 0
+REMOVE_BACKUPS: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle REMOVE_BACKUPS
+  if (.not.LL_write_tbl(jt)) cycle REMOVE_BACKUPS ! do not proceed if table is not writable
+  jtact = jtact + 1
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+  if (io_backup_enable /= 0) then
+    do j=1,npools
+      if (LL_has_backup(j,jt)) then
+        CALL makefilename(dbname, CLtbl, j, filename)
+        CALL true_dirname_and_basename(trim(filename), CLdirname, CLbasename)
+        CALL codb_remove_file(trim(CLdirname)//'/'//trim(CLbasename)//'.BACKUP', iret)
+      endif
+    enddo
+  endif
+enddo REMOVE_BACKUPS
+
+datavolume(0) = nfiles
+CALL ODBMP_global('SUM', datavolume, LDREPROD=.false., root=1)
+nfiles = datavolume(0)
+
+waltim(2) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  sum_datavolume = sum(datavolume(1:ODBMP_nproc))/(1024 * 1024)
+
+  write(0,'(1x,a,i8.8,2x,i6.6,/, &
+   &        1x,a,f8.1,a,i5,a,f7.2,a,f8.1,a,i3,a)') &
+   & '=== MSGPASS_STOREDATA of db="'//trim(dbname)// &
+   & '" for mode='//CLmode//' on all tables ended on ',imsgpass_date,imsgpass_time,&
+   & '=== MSGPASS_STOREDATA : ',sum_datavolume,' MBytes (',&
+   & nfiles,' files) in ',waltim(2) - waltim(1),&
+   & ' secs (',sum_datavolume/(waltim(2) - waltim(1) + epsilon(waltim(1))),&
+   & ' MB/s) (it#',it ,')'
+endif
+
+99999 continue
+
+
+if (allocated(iope_map))           deallocate(iope_map)
+if (allocated(LL_has_backup))      deallocate(LL_has_backup)
+if (allocated(LL_mypool))          deallocate(LL_mypool)
+if (allocated(LL_include_tbl))     deallocate(LL_include_tbl)
+if (allocated(LL_write_tbl))     deallocate(LL_write_tbl)
+if (associated(incore))             deallocate(incore)
+!J---Start---
+if (associated(jncore))             deallocate(jncore)
+!J---End---
+if (allocated(istat))              deallocate(istat)
+if (allocated(data_bytes))         deallocate(data_bytes)
+if (allocated(cltable))            deallocate(cltable)
+if (allocated(global_pool_offset)) deallocate(global_pool_offset)
+if (allocated(itags))              deallocate(itags)
+
+nullify(ioaid)
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_STOREDATA : End'
+IF (LHOOK) CALL DR_HOOK('MSGPASS_STOREDATA',1,ZHOOK_HANDLE)
+
+END SUBROUTINE msgpass_storedata
+
diff --git a/odb/src/lib/msgpass_storeobs.F90 b/odb/src/lib/msgpass_storeobs.F90
new file mode 100644
index 0000000..72a4a42
--- /dev/null
+++ b/odb/src/lib/msgpass_storeobs.F90
@@ -0,0 +1,464 @@
+SUBROUTINE msgpass_storeobs(khandle, kret)
+
+! A routine to exchange ODB-data between processors
+! Called from module ODB: ODB_close()
+
+! P. Marguinaud : 10-10-2013 : Nullify pointers
+! P. Lean       : 25-11-2014 : Code refactor to allow greater parallelism in io for improved scalability.
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE oml_mod   ,only : oml_set_lock, oml_unset_lock, oml_my_thread
+USE odb_module
+USE mpl_module
+USE odbio_msgpass
+USE str       ,ONLY : sadjustl 
+
+IMPLICIT NONE
+
+INTEGER(KIND=JPIM), intent(in)  :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(out) :: kret    ! return code
+
+INTEGER(KIND=JPIM)              :: io_method, jt, j, ntables, iret, maxbytes
+INTEGER(KIND=JPIM)              :: nw, nwmax, nbytes, npools
+INTEGER(KIND=JPIM)              :: itag, pe, destPE, io
+INTEGER(KIND=JPIM), allocatable :: itags(:,:)
+INTEGER(KIND=JPIM), allocatable :: iope_map(:,:)
+CHARACTER(len=maxvarlen), allocatable :: cltable(:)
+LOGICAL, allocatable            :: LL_mypool(:), LL_include_tbl(:), LL_write_tbl(:), LL_has_backup(:,:)
+LOGICAL                         :: LL_readonly
+LOGICAL, save                   :: LL_first_time = .TRUE.
+INTEGER(KIND=JPIM), parameter   :: io_filesize_default = 32 ! in megabytes; see ../aux/newio.c, too
+INTEGER(KIND=JPIM), save        :: io_filesize = 1
+INTEGER(KIND=JPIM), save        :: io_grpsize = -1
+INTEGER(KIND=JPIM), save        :: io_backup_enable = 0 ! By default do *NOT* enable back ups (thanks Bob C.!!)
+INTEGER(KIND=JPIM), save        :: iwrite_empty = 0
+LOGICAL, save                   :: LL_write_empty = .FALSE.
+LOGICAL, save                   :: LLiotrace = .FALSE.
+LOGICAL, save                   :: LLiomsgpasstrace = .FALSE.
+CHARACTER(len=1)                :: CLmode='w'
+CHARACTER(len=maxvarlen)        :: dbname, CLtbl, CL_called_from
+CHARACTER(len=4096)             :: filename
+CHARACTER(len=4096)             :: CLdirname, CLbasename
+INTEGER(KIND=JPIM)              :: nwrite
+INTEGER(KIND=JPIM)              :: it
+INTEGER(KIND=JPIM), allocatable :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), parameter   :: NHDR = 6
+INTEGER(KIND=JPIM)              :: this_io_grpsize, itables, cur_io_grpsize
+INTEGER(KIND=JPIM)              :: nactive_tables, jtact
+INTEGER(KIND=JPIM)              :: i_write
+INTEGER(KIND=JPIM), pointer     :: incore(:)
+INTEGER(KIND=JPIM), pointer     :: jncore(:)
+INTEGER(KIND=JPIM)              :: msgoff, nsent, nfileno
+INTEGER(KIND=JPIM), allocatable :: jsendreq(:)
+INTEGER(KIND=JPIM), allocatable :: active_table_id(:)
+INTEGER(KIND=JPIM), save        :: hc32(0:1) = (/0,0/) ! "HC32" & its reverse/byteswap (to be filled) 
+INTEGER(KIND=JPIM), pointer     :: ioaid(:,:,:) ! A shorthand notation
+REAL(KIND=JPRB), allocatable    :: data_bytes(:) ! nactive_tables
+REAL(KIND=JPRB)                 :: datavolume(0:ODBMP_nproc), waltim(2)
+INTEGER(KIND=JPIM)              :: nfiles
+INTEGER(KIND=JPIM), allocatable :: global_pool_offset(:)
+INTEGER(KIND=JPIM)              :: fast_physproc, xfast, n_messages_required
+INTEGER(KIND=JPIM)              :: imp_type
+REAL(KIND=JPRB)                 :: ZHOOK_HANDLE
+
+REAL(KIND=JPRB)                 :: timef,ttab,ttloop
+REAL(KIND=JPRB)                 :: tprebar,tpostbar
+REAL(KIND=JPRB), allocatable    :: ttwrite(:),ttsend(:),ttrecv(:),ttwait(:),ttclose(:)
+REAL(KIND=JPRB), allocatable    :: tbar(:), ttable(:), ttcomm(:)
+REAL(KIND=JPRB), allocatable    :: sendmb(:),recvmb(:)
+INTEGER(kind=JPIM), allocatable :: sendcnt(:),recvcnt(:)
+INTEGER(kind=JPIM)              :: JWRITE=0
+
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK('MSGPASS_STOREOBS',0,ZHOOK_HANDLE)
+
+incore => null ()
+jncore => null ()
+ioaid  => null ()
+
+CL_called_from = 'MSGPASS_STOREOBS'
+call MPL_barrier(cdstring='MSGPASS_STOREOBS')
+
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_STOREOBS : Begin'
+kret = 0
+itables = 0
+it = oml_my_thread()
+
+!**********************************************
+! Pick up some database metadata
+!**********************************************
+LL_readonly = db(khandle)%readonly
+io_method = db(khandle)%io_method
+npools = db(khandle)%glbNpools
+
+
+!**********************************************
+! Skip message passing if necessary
+!**********************************************
+if (.NOT.db(khandle)%inuse) goto 99999
+
+if (io_method /= 4) goto 99999 ! only applicable for ODB_IO_METHOD=4
+
+if (LL_readonly) goto 99999
+
+
+!***************************************************************
+! Define whether using blocking or non-blocking message passing
+!***************************************************************
+#if defined(NECSX) && defined(BOM)
+imp_type = JP_BLOCKING_STANDARD
+#else
+imp_type = JP_NON_BLOCKING_STANDARD
+#endif
+
+dbname = db(khandle)%name
+
+call ODBMP_sync()
+
+!***************************************************************
+! Output diagnostics: database info
+!***************************************************************
+call output_db_diagnostics(waltim,CL_called_from,khandle,dbname,LLiotrace,CLmode,io_filesize,io_filesize_default,io_grpsize,hc32,LL_first_time,.TRUE.)
+
+! Intialize a few things
+datavolume(:) = 0    ! Total volume of data stored on disk (by this PE)
+nfiles = 0           ! Number of opened files on this PE
+this_io_grpsize = min(npools,io_grpsize)   ! This has to come after output_db_diagnostics call
+
+!***************************************************************
+! Get up-to-date IOAID database metadata
+!***************************************************************
+call comm_iomap(khandle, 1, iret) ! Get up to date IOAID
+ioaid => db(khandle)%ioaid
+
+!***************************************************************
+! Calculate offset between
+! local pool numbers (within a fileblock) and global pool numbers
+! using IOAID db info
+!***************************************************************
+allocate(global_pool_offset(npools))
+call calculate_global_local_pool_offset(global_pool_offset,npools,ioaid,khandle)
+
+!***************************************************************
+! Pick up table names
+!***************************************************************
+ntables = ODB_getnames(khandle, '*', 'table')
+allocate(cltable(ntables))
+ntables = ODB_getnames(khandle, '*', 'table', cltable)
+
+allocate(LL_mypool(npools))
+allocate(LL_include_tbl(ntables))
+allocate(LL_write_tbl(ntables))
+
+! Allocate storage arrays for extra diagnostic output
+if(JWRITE>0) then
+  allocate(ttable(ntables))
+  allocate(tbar(ntables))
+  allocate(ttwrite(ntables))
+  allocate(ttsend(ntables))
+  allocate(ttrecv(ntables))
+  allocate(ttwait(ntables))
+  allocate(ttclose(ntables))
+  allocate(ttcomm(ntables))
+  allocate(sendmb(ntables))
+  allocate(recvmb(ntables))
+  allocate(sendcnt(ntables))
+  allocate(recvcnt(ntables))
+endif
+
+
+!***************************************************************
+! Construct mask of pools owned by this task
+!***************************************************************
+do j=1,npools
+  pe = fast_physproc(j)
+  LL_mypool(j) = (pe == ODBMP_myproc)
+enddo
+
+!***************************************************************
+! Construct mask of considered tables -> LL_include_tbl and nactive_tables
+!***************************************************************
+call construct_mask_of_considered_tables(khandle,dbname,ntables,cltable,LL_include_tbl, nactive_tables)
+
+! If no tables to load then skip to end
+if (nactive_tables <= 0) then
+  if (ODBMP_myproc == 1) write(0,*)'***INFO: No active tables'
+  kret = 0
+  goto 99999
+endif
+
+!***************************************************************
+! Construct map between table id and active table id -> active_table_id
+!***************************************************************
+allocate(active_table_id(ntables))
+call construct_active_table_id_map(active_table_id,LL_include_tbl,ntables)
+
+!***************************************************************
+! Construct mask of writable tables -> LL_write_tbl
+!***************************************************************
+!-- Anne Fouilloux (23/02/10)
+do jt=1,ntables
+  call cODB_table_is_writable(cltable(jt), i_write)
+  LL_write_tbl(jt) = (i_write == 1)
+enddo
+
+
+! Allocate backup mask
+if (io_backup_enable /= 0) then
+  allocate(LL_has_backup(npools,ntables))
+  LL_has_backup(:,:) = .FALSE.
+endif
+
+
+!***************************************************************
+! Define ISTAT: current status of incore items
+!***************************************************************
+allocate(istat(nstat,npools,nactive_tables))
+call get_status_of_incore_data(istat,npools,ntables,active_table_id,cltable,khandle,LL_mypool,LL_include_tbl,LL_write_tbl)
+
+!-- Make istat-information globally available
+call ODBMP_global('MAX', istat)
+
+!***************************************************************
+! Initialisation for NON BLOCKING message passing------------
+!***************************************************************
+
+
+!***************************************************************
+!-- Main loops
+!***************************************************************
+
+!-- A procedure for storing data to disk (horizontal concatenation; io_method=4)
+jtact = 0
+if(JWRITE>0) then
+  ttloop=0.d0
+  ttwrite=0.d0
+  ttrecv=0.d0
+  ttsend=0.d0
+  ttwait=0.d0
+  ttclose=0.d0
+  sendmb=0.d0
+  recvmb=0.d0
+  sendcnt=0
+  recvcnt=0
+  call MPL_BARRIER()
+  ttab=timef()
+  tpostbar=timef()
+endif
+
+!************************************************************
+! Define IOPEs for all tables and pools
+!************************************************************
+allocate(iope_map(npools+1,nactive_tables))
+iope_map(:,:) = -1 ! Means: Any PE
+call assign_iopes(iope_map, ioaid, istat, io_filesize, this_io_grpsize, npools, global_pool_offset, LL_include_tbl, ntables, active_table_id,.FALSE.)
+
+!***************************************************************
+! Calculate output file sizes -> data_bytes
+!***************************************************************
+allocate(data_bytes(nactive_tables))
+data_bytes(:) = 0
+call calculate_size_of_output_file(istat,ioaid,iope_map,this_io_grpsize,global_pool_offset,data_bytes,ntables,npools,NHDR,iwrite_empty, LL_write_empty, active_table_id)
+
+!***************************************************************
+! Predefine message tags for all used table,pools combinations 
+!   (global not local - as need to know tags of incoming messages from other tasks)
+! Loop through all table/pool combinations and determine if a message will need to be sent,
+!   if so, then define a tag for the send/recv to use. 
+!***************************************************************
+n_messages_required = 0
+allocate(itags(npools+1,ntables))
+itags(:,:) = -1
+itag = 0
+msgoff = 0
+nwrite=0
+do jt=1,ntables
+  jtact = active_table_id(jt)
+  if (LL_include_tbl(jt).and.LL_write_tbl(jt).and.(maxval(istat(ISTAT_NBYTES,1:npools,jtact))>0).and.maxval(istat(ISTAT_UPDATED,1:npools,jtact))>0)then  ! If table updated, has non-zero data and is write enabled 
+    do j=1,npools
+      destPE = fast_physproc(iope_map(j,jtact))
+      !if (destPE/=ODBMP_myproc)then  ! Only get data and send message if iope is not this pe (otherwise, get data in the write loop directly)
+        nw = NHDR + (istat(ISTAT_NBYTES,j,jtact) + sizeof_int - 1)/sizeof_int 
+        if (LL_mypool(j)) then     ! If message needs to be sent for this PE then 
+              msgoff = msgoff + nw ! Add up total volume of data that needs to be sent by this PE as required for jncore allocation
+              n_messages_required = n_messages_required + 1
+        endif
+        nbytes = istat(ISTAT_NBYTES,j,jtact)
+        if (nbytes > 0) then
+          itags(j,jt) = itag
+          itag = itag + 1
+        endif
+      !endif
+    enddo
+  endif
+enddo
+if (ODBMP_myproc == 1) write(0,*) 'Created itags array with MAX: ',MAXVAL(itags(:,:)), ' and MIN: ',MINVAL(itags(:,:))
+
+call allocate_jncore(jncore, msgoff, iret)
+allocate(jsendreq(n_messages_required))
+
+!************************************************************
+! Send section
+!************************************************************
+nsent = 0
+msgoff = 0
+do jt=1,ntables
+  jtact = active_table_id(jt)
+  io = -1
+  call codb_strblank(filename)
+  if (LL_include_tbl(jt).and.LL_write_tbl(jt).and.(maxval(istat(ISTAT_NBYTES,1:npools,jtact))>0).and.maxval(istat(ISTAT_UPDATED,1:npools,jtact))>0)then  ! If table updated, has non-zero data and is write enabled 
+    CLtbl = cltable(jt)(2:) ! Strip off the @
+    do j=1,npools
+      destPE = fast_physproc(iope_map(j,jtact))
+      if (destPE/=ODBMP_myproc)then  ! Only get data and send message if iope is not this pe (otherwise, get data in the write loop directly)
+          if (LL_mypool(j)) then
+            nbytes = istat(ISTAT_NBYTES,j,jtact)
+            if (nbytes > 0) then
+              nw = NHDR + (istat(ISTAT_NBYTES,j,jtact) + sizeof_int - 1)/sizeof_int
+              call allocate_incore_jncore(incore,jncore,istat,npools,jtact,NHDR,maxbytes)
+              call get_incore_data_for_this_pool_table(khandle,ioaid,istat,NHDR,j,jt,jtact,CLtbl,this_io_grpsize,global_pool_offset,nw,maxbytes,incore)
+              itag = itags(j,jt)
+              call send_message_to_pe(nw,incore,jncore,msgoff,destPE,itag,imp_type,jsendreq,LLiomsgpasstrace, CLtbl,nsent)
+            endif
+          endif
+      endif
+    enddo
+  endif
+enddo
+
+!************************************************************
+! Receive/write section
+!************************************************************
+do jt=1,ntables
+  jtact = active_table_id(jt)
+  io = -1
+  nfileno=0
+  if (LL_include_tbl(jt).and.LL_write_tbl(jt).and.(maxval(istat(ISTAT_NBYTES,1:npools,jtact))>0).and.maxval(istat(ISTAT_UPDATED,1:npools,jtact))>0)then  ! If table updated, has non-zero data and is write enabled 
+    CLtbl = cltable(jt)(2:) ! Strip off the @
+    call make_temporary_backups_of_table_files(dbname,CLtbl,jt,npools,LL_mypool,LL_has_backup,ioaid,this_io_grpsize)
+    call diagnostic_output_table(data_bytes,jtact,CLtbl,CL_called_from)
+    ! Allocate incore
+    maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+    nwmax = NHDR + max(1,(maxbytes + sizeof_int - 1)/sizeof_int)
+    CALL allocate_incore(incore, nwmax, iret)
+    do j=1,npools
+      if (fast_physproc(iope_map(j,jtact))==ODBMP_myproc) then
+        nbytes = istat(ISTAT_NBYTES,j,jtact)
+        cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+        if (nbytes > 0) then
+          nw = NHDR + (istat(ISTAT_NBYTES,j,jtact) + sizeof_int - 1)/sizeof_int
+          itag = itags(j,jt)
+          pe = fast_physproc(j)  ! Source PE
+          if (pe/=ODBMP_myproc)then  ! If source pe isn't this pe, then receive message
+              call receive_message_for_this_pool_table(pe,nw,itag,j,LLiomsgpasstrace,incore,filename,CLtbl,CL_called_from)
+          else  ! if source pe is this pe, then just get data from incore
+              call get_incore_data_for_this_pool_table(khandle,ioaid,istat,NHDR,j,jt,jtact,CLtbl,this_io_grpsize,global_pool_offset,nw,maxbytes,incore)
+          endif
+          call write_pool_to_hc32_file(incore,ioaid,iope_map,io,dbname,Cltbl,j,jt,jtact,NHDR,datavolume,nw,nwrite,nfiles,nfileno,cur_io_grpsize,LLiotrace,hc32,global_pool_offset)
+        endif
+        ! Close if end of this group (e.g. last pool in current ECMA.x)
+        if ((io /= -1).and.(mod(j-global_pool_offset(j), cur_io_grpsize) == 0))then
+          call io_close(filename, io, nwrite, npools, nfiles, datavolume, LLiotrace, iret)
+        endif
+      endif
+    enddo
+    call io_close(filename, io, nwrite, npools, nfiles, datavolume, LLiotrace, iret)
+  endif ! LL_write_tbl
+enddo
+
+!************************************************************
+! Debug output
+!************************************************************
+if(JWRITE>0) then
+  ttable(ntables)=timef()-tpostbar
+  tprebar=timef()
+  call mpl_barrier()
+  tbar(ntables)=timef()-tprebar
+  ttab=timef()-ttab
+  do jt=1,ntables
+    ttcomm(jt)=ttsend(jt)+ttrecv(jt)+ttwait(jt)
+  enddo
+  write(0,'(a,10f10.0)') "JJJ time tab,loop=",ttab,ttloop
+  write(0,'(a,50f9.0)') "JJJ send MB     =",(sendmb(jt),jt=1,ntables)
+  write(0,'(a,50i9)')   "JJJ send count  =",(sendcnt(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ send time   =",(ttsend(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ wait time   =",(ttwait(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ close time  =",(ttclose(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ recv MB     =",(recvmb(jt),jt=1,ntables)
+  write(0,'(a,50i9)')   "JJJ recv count  =",(recvcnt(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ recv time   =",(ttrecv(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ comm time   =",(ttcomm(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ write time  =",(ttwrite(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ table time  =",(ttable(jt),jt=1,ntables)
+  write(0,'(a,50f9.0)') "JJJ barier time =",(tbar(jt),jt=1,ntables)
+  deallocate(ttable,tbar,ttcomm)
+  deallocate(ttwrite,ttsend,ttrecv,ttwait,ttclose,sendmb,recvmb,sendcnt,recvcnt)
+endif
+
+
+kret = itables ! No. of tables stored/loaded
+
+call comm_iomap(khandle, 2, iret) ! Propagate up to date IOAID's
+
+
+!************************************************************
+! Remove backup files where created
+!************************************************************
+jtact = 0
+REMOVE_BACKUPS: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle REMOVE_BACKUPS
+  if (.not.LL_write_tbl(jt)) cycle REMOVE_BACKUPS ! do not proceed if table is not writable
+  jtact = active_table_id(jt)
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+  if (io_backup_enable /= 0) then
+    do j=1,npools
+      if (LL_has_backup(j,jt)) then
+        call makefilename(dbname, CLtbl, j, filename)
+        call true_dirname_and_basename(trim(filename), CLdirname, CLbasename)
+        call codb_remove_file(trim(CLdirname)//'/'//trim(CLbasename)//'.BACKUP', iret)
+      endif
+    enddo
+  endif
+enddo REMOVE_BACKUPS
+
+datavolume(0) = nfiles
+call ODBMP_global('SUM', datavolume, LDREPROD=.false., root=1)
+nfiles = datavolume(0)
+
+call mpl_barrier()
+
+!************************************************************
+! Output diagnostics
+!************************************************************
+call output_diagnostics_final(waltim,CL_called_from,datavolume,dbname,CLmode,it,nfiles)
+
+99999 continue
+
+!************************************************************
+! Tidy up
+!************************************************************
+if (allocated(iope_map))           deallocate(iope_map)
+if (allocated(LL_has_backup))      deallocate(LL_has_backup)
+if (allocated(LL_mypool))          deallocate(LL_mypool)
+if (allocated(LL_include_tbl))     deallocate(LL_include_tbl)
+if (allocated(LL_write_tbl))       deallocate(LL_write_tbl)
+if (associated(incore))            deallocate(incore)
+if (associated(jncore))            deallocate(jncore)
+if (allocated(istat))              deallocate(istat)
+if (allocated(data_bytes))         deallocate(data_bytes)
+if (allocated(cltable))            deallocate(cltable)
+if (allocated(global_pool_offset)) deallocate(global_pool_offset)
+if (allocated(itags))              deallocate(itags)
+if (allocated(jsendreq))           deallocate(jsendreq)
+if (allocated(active_table_id))    deallocate(active_table_id)
+
+nullify(ioaid)
+if (ODBMP_myproc == 1) write(0,*)'=== MSGPASS_STOREOBS : End'
+IF (LHOOK) CALL DR_HOOK('MSGPASS_STOREOBS',1,ZHOOK_HANDLE)
+
+END SUBROUTINE msgpass_storeobs
+
diff --git a/odb/src/lib/odb_array_dump.F90 b/odb/src/lib/odb_array_dump.F90
new file mode 100644
index 0000000..b35bb2e
--- /dev/null
+++ b/odb/src/lib/odb_array_dump.F90
@@ -0,0 +1,115 @@
+SUBROUTINE odb_darray_dump(khandle, dump_name, viewname, colname, colflag, mdbname, ncolname, &
+ & iu, d, nra, nrows, ncols, ncol_start) 
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB     ,JPIB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+
+use odbshared
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in) :: khandle, ncolname, iu, nra, nrows, ncols, ncol_start
+character(len=*), intent(in) :: dump_name, viewname, colname(ncolname), mdbname(ncolname)
+logical, intent(in)   :: colflag(ncolname)
+REAL(KIND=JPRB), intent(in)   :: d(nra, ncol_start:ncols)
+INTEGER(KIND=JPIM), parameter :: jinc = 100
+logical :: LLoutput, LLstatid, LLsame
+INTEGER(KIND=JPIM) :: jrow, jcol, maxrows, j1, j2
+INTEGER(KIND=JPIM), allocatable :: rownum(:), poolno(:)
+INTEGER(KIND=JPIB), external :: loc_addr
+REAL(KIND=JPRB) :: refval
+REAL(KIND=JPRB) ::    dbuf(jinc)
+INTEGER(KIND=JPIM) :: ibuf(jinc * 2)
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+EQUIVALENCE (dbuf,ibuf)  ! Yeah, I know this is bad, Mats, but it is just for STATID diagnostix !
+
+IF (LHOOK) CALL DR_HOOK('ODB_DARRAY_DUMP',0,ZHOOK_HANDLE)
+if (dump_count > max_dump_count .AND. LHOOK) CALL DR_HOOK('ODB_DARRAY_DUMP',1,ZHOOK_HANDLE)
+if (dump_count > max_dump_count) return
+dump_count = dump_count + 1
+
+maxrows = min(nrows,nra)
+
+write(iu,'(1x,a,z16.16)')&
+ & 'ODB_DARRAY_DUMP of '//trim(dump_name)//' for view='//trim(viewname)//' at addr=0x',loc_addr(d) 
+write(iu,*)'nra, nrows, ncols, ncol_start, maxrows, ncolname=',&
+ & nra, nrows, ncols, ncol_start, maxrows, ncolname
+
+if (maxrows > 0) then
+  do jcol=ncol_start,ncols
+    if (jcol == 0) then ! hexdump only
+      allocate(rownum(maxrows))
+      allocate(poolno(maxrows))
+      write(iu,*)'column#',jcol,' (control column) ; values are : the col#0-value, poolwise-rownum & poolno'
+      CALL cODB_get_rownum(d(1,0), 0, maxrows, 0, 0, rownum)
+      CALL cODB_get_poolnos(d(1,0), 0, maxrows, 0, poolno)
+      j2 = 0
+      LOOPZ: do
+        j1 = j2+1
+        j2 = min(j2+jinc,maxrows)
+        if (j2 < j1) exit LOOPZ
+        write(iu,&
+         & '(1x,i7," - ",i7,5(:,1x,i12,1x,i7,1x,i3),:,/,(:,18x,5(:,1x,i12,1x,i7,1x,i3)))') &
+         & j1,j2, (int(d(jrow,jcol)), rownum(jrow), poolno(jrow), jrow=j1,j2) 
+        if (j2 >= maxrows) exit LOOPZ
+      enddo LOOPZ
+    else
+      LLoutput = .TRUE.
+      LLstatid = .FALSE.
+      if (jcol <= ncolname) then
+        write(iu,*)'column#',jcol, ' : '//trim(colname(jcol))//' alias '//trim(mdbname(jcol))//&
+         & ' for view='//trim(viewname) 
+        LLstatid = (colname(jcol) == 'statid at hdr')
+        LLoutput = colflag(jcol)
+      else
+        write(iu,*)'column#',jcol, ' :  for view='//trim(viewname)
+      endif
+      if (LLoutput) then
+        j2 = 0
+        LOOP: do
+          j1 = j2+1
+          j2 = min(j2+jinc,maxrows)
+          if (j2 < j1) exit LOOP
+          refval = d(j1,jcol)
+          LLsame = ALL(d(j1:j2,jcol) == refval)
+          if (LLstatid) then
+            if (LLsame) then
+              dbuf(1) = refval
+              write(iu,'(1x,i7," - ",i7,1x,a8,2(1x,i11),1x,a)') &
+               & j1,j2, refval, ibuf(1), ibuf(2), '(all values are the same)' 
+            else
+              do jrow=j1,j2
+                dbuf(jrow-j1+1) = d(jrow,jcol)
+              enddo
+              write(iu,'(1x,i7," - ",i7,5(:,1x,a8,2(1x,i11)),:,/,(:,18x,5(:,1x,a8,2(1x,i11))))') &
+               & j1,j2, (d(jrow,jcol), ibuf(2*(jrow-j1+1)-1), ibuf(2*(jrow-j1+1)), jrow=j1,j2) 
+            endif
+          else
+            if (LLsame) then
+              write(iu,'(1x,i7," - ",i7,1p,1x,g19.10,1x,a)') &
+               & j1,j2, refval, '(all values are the same)' 
+            else
+              write(iu,'(1x,i7," - ",i7,1p,5(:,1x,g19.10),:,/,(:,18x,5(:,1x,g19.10)))') &
+               & j1,j2, (d(jrow,jcol), jrow=j1,j2) 
+            endif
+          endif
+          if (j2 >= maxrows) exit LOOP 
+        enddo LOOP
+      endif ! if (LLoutput) then
+    endif
+    call flush(iu)
+  enddo
+endif
+
+if (allocated(rownum)) deallocate(rownum)
+if (allocated(poolno)) deallocate(poolno)
+
+write(iu,*)'End of ODB_DARRAY_DUMP of '//trim(dump_name)//' for view='//trim(viewname)
+call flush(iu)
+IF (LHOOK) CALL DR_HOOK('ODB_DARRAY_DUMP',1,ZHOOK_HANDLE)
+
+END SUBROUTINE odb_darray_dump
diff --git a/odb/src/lib/orlist.c b/odb/src/lib/orlist.c
new file mode 100644
index 0000000..a05ecbf
--- /dev/null
+++ b/odb/src/lib/orlist.c
@@ -0,0 +1,324 @@
+
+/* orlist.c */
+
+#include "odb.h"
+#include "odbcrc.h"
+#include "pcma_extern.h"
+
+PUBLIC double
+ODB_maxval(const int n, ...)
+{
+  const double mdi = ABS(RMDI);
+  double dmax = mdi;
+  va_list ap;
+  va_start(ap, n);
+  if (n > 0) { 
+    double d = mdi;
+    int jj=0;
+    while (jj<n) {
+      d = va_arg(ap, double);
+      if (ABS(d) != mdi) break;
+      jj++;
+    }
+    if (jj<n) {
+      int j;
+      dmax = d;
+      for (j=jj+1; j<n; j++) {
+	d = va_arg(ap, double);
+	if (ABS(d) != mdi && dmax < d) dmax = d;
+      }
+    }
+  } /* if (n > 0) */
+  va_end(ap);
+  return dmax;
+}
+
+PUBLIC double
+ODB_minval(const int n, ...)
+{
+  const double mdi = ABS(RMDI);
+  double dmin = mdi;
+  va_list ap;
+  va_start(ap, n);
+  if (n > 0) { 
+    double d = mdi;
+    int jj=0;
+    while (jj<n) {
+      d = va_arg(ap, double);
+      if (ABS(d) != mdi) break;
+      jj++;
+    }
+    if (jj<n) {
+      int j;
+      dmin = d;
+      for (j=jj+1; j<n; j++) {
+	d = va_arg(ap, double);
+	if (ABS(d) != mdi && dmin > d) dmin = d;
+      }
+    }
+  } /* if (n > 0) */
+  va_end(ap);
+  return dmin;
+}
+
+PUBLIC double
+ODB_Cksum32(const int n, ...)
+{
+  unsigned int crc32 = 0;
+  int keylen = n * sizeof(double);
+  if (n > 0) {
+    int j;
+    va_list ap;
+    va_start(ap, n);
+    for (j=0; j<n; j++) {
+      double d = va_arg(ap, double);
+      crc32 = ODB_cksum32((const char *)&d, sizeof(double), crc32);
+    }
+    va_end(ap);
+  } /* if (n > 0) */
+  crc32 = ODB_pp_cksum32(keylen, crc32);
+  return (double)crc32;
+}
+
+typedef struct _thin_info_t {
+  int cnt;
+  int last_taken;
+  double key;
+  double first_value;
+  double second_value;
+  unsigned int datakey;
+  struct _thin_info_t *next;
+} ThinInfo_t;
+
+
+static ThinInfo_t **thinfo = NULL;
+static int inumt = 0;
+
+PUBLIC void
+codb_thin_init_()
+{
+  if (!thinfo) {
+    inumt = get_max_threads_();
+    CALLOC(thinfo, inumt);
+  }
+}
+
+PUBLIC void
+codb_thin_reset_(const int *It)
+{
+  if (!thinfo) codb_thin_init_(); /* Not thread-safe, but normally not called */
+  if (It) {
+    int it = *It;
+    if (it >= 1 && it <= inumt) {
+      ThinInfo_t *p = thinfo[--it];
+      while (p) {
+	p->cnt = 0;
+	p = p->next;
+      }
+    }
+  }
+}
+
+PRIVATE ThinInfo_t *
+find_thinfo(const double key, int it)
+{
+  ThinInfo_t *p, *plast;
+  if (!thinfo) codb_thin_init_(); /* Not thread-safe, but normally not called */
+  p = plast = thinfo[--it];
+  while (p) {
+    plast = p;
+    if (p->cnt > 0 && p->key == key) break;
+    if (p->cnt == 0) break;
+    p = p->next;
+  }
+  if (!p) {
+    CALLOC(p, 1);
+    if (!thinfo[it]) thinfo[it] = p;
+    if (plast) plast->next = p; /* chain */
+  }
+  return p;
+}
+
+PUBLIC double
+ODB_vthin(const int N, const double d[])
+{
+  boolean take_this;
+  int every_nth;
+  double key = 0;
+  double Every_nth = 0;
+  int n = N;
+  if (n >= 2) {
+    key = d[0];
+    Every_nth = d[1];
+  }
+  n -= 2;
+  every_nth = (n >= 0 && Every_nth >= 0 && Every_nth <= INT_MAX) ? (int)Every_nth : 0;
+  take_this = (n >= 0 && every_nth >= 1) ? 1 : 0;
+  if (n >= 0 && every_nth > 1) {
+    DEF_IT;
+    ThinInfo_t *th = find_thinfo(key, it);
+    unsigned int datakey = n;
+    double first_value = 0;
+    double second_value = 0;
+
+    if (n > 0) {
+      int j, keylen = 0;
+      if (n == 1) {
+	first_value = d[2];
+      }
+      else if (n == 2) {
+	first_value = d[3];
+	second_value = d[4];
+      }
+      else { /* n > 2 */
+	for (j=0; j<n; j++) {
+	  double dd = d[2+j];
+	  if (j==0) first_value = dd;
+	  else if (j==1) second_value = dd;
+	  datakey = ODB_cksum32((const char *)&dd, sizeof(dd), datakey);
+	  keylen += sizeof(dd);
+	}
+	datakey = ODB_pp_cksum32(keylen, datakey);
+      }
+    }
+
+    if (th->cnt == 0) { /* Start "recording" */
+      (th->cnt)++;
+      th->last_taken = 1;
+      th->key = key;
+      th->first_value = first_value;
+      th->second_value = second_value;
+      th->datakey = datakey;
+      take_this = 1;
+    }
+    else if (th->last_taken && 
+	     datakey == th->datakey && 
+	     first_value == th->first_value &&
+	     second_value == th->second_value) {
+      /* Take only values that are consecutively the same ; do not increment counter */
+      take_this = 1;
+    }
+    else {
+      (th->cnt)++;
+      if ((th->cnt)%every_nth == 1) {
+	th->last_taken = 1;
+	th->first_value = first_value;
+	th->second_value = second_value;
+	th->datakey = datakey;
+	take_this = 1;
+      }
+      else {
+	th->last_taken = 0; /* Breaks "consecutiveness" */
+	take_this = 0;
+      }
+    }
+  }
+  return (double)take_this;
+}
+
+PUBLIC double
+ODB_thin(const int n, /* double key, double Every_nth, */...)
+{
+  double take_this = 0;
+  va_list ap;
+  va_start(ap, n);
+  if (n > 0) {
+    int j;
+    double *d = NULL;
+    ALLOCX(d,n);
+    for (j=0; j<n; j++) {
+      d[j] = va_arg(ap, double);
+    }
+    take_this = ODB_vthin(n, d);
+    FREEX(d);
+  }
+  va_end(ap);
+  return take_this;
+}
+
+
+typedef struct _In_Vector_t {
+  double *d;
+  int *i;
+  int nd;
+} In_Vector_t;
+
+
+typedef union _Union_Vector_t {
+  double addr;
+  In_Vector_t *iv;
+} Union_Vector_t;
+
+
+void fodb_register_in_vector_(void *d, const int *nd, const int *is_int, double *addr)
+{
+  if (d && nd && *nd > 0 && is_int && addr) {
+    boolean IsInt = (*is_int != 0) ? 1 : 0;
+    Union_Vector_t uv;
+    In_Vector_t *iv = NULL;
+    CALLOC(iv, 1);
+    iv->nd = *nd;
+    if (IsInt) {
+      iv->d = NULL;
+      iv->i = d;
+    }
+    else {
+      iv->d = d;
+      iv->i = NULL;
+    }
+    uv.iv = iv;
+    *addr = uv.addr;
+  }
+  else if (addr) {
+    *addr = 0;
+  }
+}
+
+void fodb_unregister_in_vector_(double *addr)
+{
+  if (addr) {
+    Union_Vector_t uv;
+    uv.addr = *addr;
+    if ( uv.iv != (In_Vector_t *) NULL ) {
+      In_Vector_t *iv = NULL;
+      uv.addr = *addr;
+      iv = uv.iv;
+      FREE(iv);
+      *addr = 0;
+    }
+  }
+}
+
+double ODB_in_vector(double var, double addr)
+{
+  double rc = 0; /* false */
+  Union_Vector_t uv;
+  uv.addr = addr;
+  if (uv.iv != (In_Vector_t *) NULL) {
+    In_Vector_t *iv = NULL;
+    iv = uv.iv;
+    if (iv && (iv->d || iv->i) && iv->nd > 0) {
+      int j, nd = iv->nd;
+      double *d = iv->d;
+      int *i = iv->i;
+      if (d) {
+	for (j=0; j<nd; j++) {
+	  if (d[j] == var) {
+	    rc = 1; /* true */
+	    break;
+	  }
+	}
+      }
+      else {
+	int ivar = var;
+	for (j=0; j<nd; j++) {
+	  if (i[j] == ivar) {
+	    rc = 1; /* true */
+	    break;
+	  }
+	}
+      }
+    } /* if (iv && (iv->d || iv->i) && iv->nd > 0) */
+  }
+  return rc;
+}
diff --git a/odb/src/lib/peinfo.c b/odb/src/lib/peinfo.c
new file mode 100644
index 0000000..ef50db5
--- /dev/null
+++ b/odb/src/lib/peinfo.c
@@ -0,0 +1,152 @@
+#include "odb.h"
+
+typedef struct List {
+  int selected;
+  int vhandle;
+  int replicate_PE;
+  int npes;
+  struct List *collision;
+} List_t;
+
+#ifndef PEINFO_HASHSIZE
+#define PEINFO_HASHSIZE 223U
+#endif
+
+PRIVATE uint PEINFO_hashsize = 0;
+PRIVATE List_t **PEINFO_hashtable = NULL;
+
+
+PRIVATE List_t *
+NewEntry() 
+{
+  List_t *p;
+  CALLOC(p,1);
+  return p;
+}
+
+
+#define HASH(x) (((uint)(x)) % PEINFO_hashsize)
+
+
+PRIVATE void 
+HashInit()
+{
+  if (!PEINFO_hashtable) {
+    List_t **tmp_PEINFO_hashtable = NULL;
+    int inumt = get_max_threads_();
+    int it;
+    char *p = getenv("ODB_PEINFO_HASHSIZE");
+    if (p) {
+      PEINFO_hashsize = atoi(p);
+      if (PEINFO_hashsize <= 0) PEINFO_hashsize = PEINFO_HASHSIZE;
+    }
+    else {
+      PEINFO_hashsize = PEINFO_HASHSIZE;
+    }
+    ALLOC(tmp_PEINFO_hashtable, inumt);
+    for (it=0; it<inumt; it++) {
+      /* CALLOC below implies that tmp_PEINFO_hashtable[it]->selected is zero */
+      CALLOC(tmp_PEINFO_hashtable[it],PEINFO_hashsize); 
+    }
+    PEINFO_hashtable = tmp_PEINFO_hashtable;
+  }
+}
+
+
+PUBLIC void
+init_PEINFO_lock()
+{
+  HashInit();
+}
+
+PUBLIC void 
+codb_save_peinfo_(const int *vhandle,
+		  const int *replicate_PE, 
+		  const int *npes)
+{
+  int it = get_thread_id_();
+  FILE *do_trace = ODB_trace_fp();
+  int found = 0;
+  List_t *p;
+  uint index;
+
+  index = HASH(*vhandle);
+  p = &PEINFO_hashtable[--it][index];
+
+  while (p) {
+    if (!p->selected) {
+      p->selected = 1;
+      p->vhandle = *vhandle;
+      p->replicate_PE = *replicate_PE;
+      p->npes = *npes;
+      found = 1;
+      break; /* found */
+    }
+    if (!p->collision) p->collision = NewEntry();
+    p = p->collision;
+  } /* while (p) */
+
+  if (do_trace) {
+    ODB_Trace TracE;
+    TracE.handle = -1;
+    TracE.msglen = 256;
+    TracE.msg = NULL;
+    ALLOC(TracE.msg, TracE.msglen);
+    TracE.numargs = 0; 
+    TracE.mode = -1;
+    sprintf(TracE.msg,
+	    "save_peinfo: vhandle=%d, found=%d, repl_PE=%d, npes=%d, it=%d",
+	    *vhandle, found, *replicate_PE, *npes, it+1);
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, 
+		&TracE.numargs, TracE.msglen);
+    FREE(TracE.msg);
+  } /* if (do_trace) */
+}
+
+
+PUBLIC void 
+codb_restore_peinfo_(const int *vhandle,
+		     int *replicate_PE, 
+		     int *npes)
+{
+  int it = get_thread_id_();
+  FILE *do_trace = ODB_trace_fp();
+  int found = 0;
+  List_t *p;
+  uint index;
+
+  index = HASH(*vhandle);
+  p = &PEINFO_hashtable[--it][index];
+
+  *replicate_PE = 0;
+  *npes = 0;
+
+  while (p) {
+    if (p->selected && p->vhandle == *vhandle) {
+      *replicate_PE = p->replicate_PE;
+      *npes = p->npes;
+      p->selected = 0;
+      found = 1;
+      break; /* found */
+    }
+    p = p->collision;
+  } /* while (p) */
+
+  if (do_trace) {
+    ODB_Trace TracE;
+    TracE.handle = -1;
+    TracE.msglen = 256;
+    TracE.msg = NULL;
+    ALLOC(TracE.msg, TracE.msglen);
+    TracE.numargs = 0; 
+    TracE.mode = -1;
+    sprintf(TracE.msg,
+	    "restore_peinfo: vhandle=%d, found=%d, repl_PE=%d, npes=%d, it=%d",
+	    *vhandle, found, *replicate_PE, *npes, it+1);
+    codb_trace_(&TracE.handle, &TracE.mode,
+		TracE.msg, TracE.args, 
+		&TracE.numargs, TracE.msglen);
+    FREE(TracE.msg);
+  } /* if (do_trace) */
+}
diff --git a/odb/src/lib/poolmasking.c b/odb/src/lib/poolmasking.c
new file mode 100644
index 0000000..4ce8122
--- /dev/null
+++ b/odb/src/lib/poolmasking.c
@@ -0,0 +1,515 @@
+#include "odb.h"
+
+/* To activate poolmasking, set export ODB_POOLMASKING=1 (valid for ALL databases)
+   or set ODB_PERMANENT_POOLMASK          (valid for ALL databases; see below)
+   or set ODB_PERMANENT_POOLMASK_<dbname> (see below) */
+
+#define IT (it-1)
+
+/* Handle (i.e. database) specific permanent poolmask items */
+
+typedef struct db_perm_t_ {
+ int npermcnt;
+ int nperm;
+ unsigned char *perm_list;
+} db_perm_t;
+
+PRIVATE int MaxHandle = 0;
+PRIVATE db_perm_t *db = NULL;
+PRIVATE ODB_PoolMask *db_pm = NULL;
+
+static int
+raise_signal(int sig, const char *msg, int code, const char *file, int linenum)
+{
+  fprintf(stderr,"\n***Error in %s:%6.6d (signal#%d): %s (code=%d)\n",file,linenum,sig,msg,code);
+  RAISE(sig);
+  /* Should never end up here */
+  _exit(1);
+  return sig;
+}
+
+#define RAISE_SIGNAL(sig,msg,code) raise_signal(sig, msg, code, __FILE__, __LINE__)
+
+#define SET_PDB(h) \
+db_perm_t *pdb = (db && (h) >= 1 && (h) <= MaxHandle) ? &db[(h)-1] : \
+( RAISE_SIGNAL(SIGABRT, "In SET_PDB-macro : handle out of range, thus pdb not allocated", h), \
+ (db_perm_t *)NULL )
+
+#define TEST_PM(h) (db_pm && (h) >= 1 && (h) <= MaxHandle)
+
+#define GET_PM(h) (TEST_PM(h) && db_pm[(h)-1].handle == (h)) ? &db_pm[(h)-1] : NULL
+
+#define SETPM(poolno, onoff) \
+( (pdb->perm_list && (poolno >= 1 && poolno <= pdb->nperm)) ? \
+  (pdb->perm_list[poolno] & onoff) : ((pdb->nperm > 0) ? 0 : onoff ) )
+
+#define NEWPERM(j) { maxval = MAX(maxval, j); n++; \
+/*fprintf(stderr,">>NEWPERM: j=%d, maxval=%d, n=%d\n",j,maxval,n);*/ }
+#define SETPERM(j) { if (j > 0 && j <= pdb->nperm) { pdb->perm_list[j] = 1; n++; \
+/*fprintf(stderr,">>SETPERM: j=%d, n=%d\n",j,n);*/ }}
+
+#define WHILE_BLOCK(makro) \
+while (*c) { \
+  int cnt, val, lo, hi; \
+  while (*c == ' ') c++; \
+  if (!*c) break; \
+  cnt = sscanf(c, "%s", tmpstr); \
+  if (cnt != 1) break; \
+  cnt = sscanf(tmpstr, "%d-%d", &lo, &hi); \
+  if (cnt == 2) { \
+    lo = MIN(lo, npools); \
+    hi = MIN(hi, npools); \
+    if (lo <= hi) { \
+      int j; \
+      for (j=lo; j<=hi; j++) makro(j); \
+    } \
+    cnt = 1; \
+  } \
+  else { \
+    cnt = sscanf(tmpstr, "%d", &val); \
+    if (cnt == 1) { val = MIN(val, npools); makro(val); } \
+  } \
+  if (cnt != 1) break; \
+  c += strlen(tmpstr); \
+  if (!*c || (int)(c - ca) >= ca_len) break; \
+} /* while (*c) */
+
+PRIVATE int
+permanent_poolmask(const int *handle,
+		   const char *dbname,
+		   int npools)
+{
+  /* 
+     This routine will enable to set the PERMANENT poolmask for the given execution;
+     Set f.ex. export ODB_PERMANENT_POOLMASK="1 7 8 10"
+     or range  export ODB_PERMANENT_POOLMASK="11-15"
+     or both   export ODB_PERMANENT_POOLMASK="1,7,8,10 11:15 20-35"
+     and in the given run you will NEVER access any other pool than specified in the list ;
+     Applies to ALL opened databases at the same time ;
+
+     *** Per database is fully implemented now *** :
+
+     export ODB_PERMANENT_POOLMASK_ECMA="1 7 8 10"
+     export ODB_PERMANENT_POOLMASK_CCMA="11-15"
+
+   */
+
+  int maxval = 0;
+  int len;
+  char *envname = NULL;
+  const char prefix[] = "ODB_PERMANENT_POOLMASK";
+  char *perm_pm;
+  int myproc = 0;
+  codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+
+  len = strlen(prefix) + strlen(dbname) + 2;
+  ALLOC(envname,len);
+  sprintf(envname,"%s_%s",prefix,dbname);
+  perm_pm = getenv(envname);
+  if (!perm_pm) perm_pm = getenv(prefix);
+
+  if (perm_pm && !strequ(perm_pm,"-1")) {
+    SET_PDB(*handle);
+    int n = 0;
+    char *ca = STRDUP(perm_pm);
+    int ca_len = strlen(ca);
+    char *tmpstr = NULL;
+    char *c;
+
+    ALLOC(tmpstr,ca_len+1);
+
+    c = ca;
+    if (c) {
+      while (*c) {
+	if (isspace(*c) || *c == ',') *c = ' ';
+	if (*c == ':') *c = '-';
+	c++;
+      }
+    }
+
+    c = ca;
+    if (c) {
+      WHILE_BLOCK(NEWPERM);
+    }
+
+    pdb->nperm = MIN(maxval, npools);
+    pdb->nperm = MAX(pdb->nperm, 0);
+
+    FREE(pdb->perm_list);
+    CALLOC(pdb->perm_list, pdb->nperm+1);
+
+    if (n > 0) {
+      n = 0;
+      c = ca;
+      WHILE_BLOCK(SETPERM);
+
+      if (myproc == 1) {
+	int j;
+	fprintf(stderr,
+	"***INFO: Only the following pools will be accessed (dbname='%s', count=%d, nperm=%d)\n", 
+	dbname, n, pdb->nperm);
+	fprintf(stderr,
+		"            ODB_PERMAMENT_POOLMASK_%s=%s\n==>",dbname,perm_pm);
+	for (j=1; j<=pdb->nperm; j++) {
+	  if (pdb->perm_list[j]) fprintf(stderr,"%d ", j);
+	} /* for (j=0; j<pdb->nperm; j++) */
+	fprintf(stderr,"\n");
+      }
+    } /* if (n > 0) */
+
+    FREE(tmpstr);
+    FREE(ca);
+
+    { /* calculate "pdb->npermcnt" i.e. number of active pools permanently poolmasked */
+      int j;
+      pdb->npermcnt = 0;
+      for (j=1; j<=pdb->nperm; j++) {
+	if (pdb->perm_list[j]) pdb->npermcnt++;
+      }
+    }
+  } /* if (perm_pm) */
+
+  FREE(envname);
+  return maxval;
+}
+
+PUBLIC ODB_PoolMask *
+ODB_get_poolmask_by_handle(int handle)
+{
+  ODB_PoolMask *pm = GET_PM(handle);
+  return pm;
+}
+
+
+PUBLIC void
+codb_toggle_poolmask_(const int *handle, const int *onoff, int *oldvalue)
+{
+  /* Disable/enable poolmask testing w/o touching poolmask[] itself */
+  /* Note: thread specific, thus thread safe */
+  ODB_PoolMask *pm = GET_PM(*handle);
+  if (oldvalue) *oldvalue = -1; /* undefined */
+  if (pm) {
+    DEF_IT;
+    if (oldvalue) *oldvalue = pm->poolmask[IT][0]; /* old value */
+    pm->poolmask[IT][0] = (*onoff > 0) ? 1 : 0;
+  }
+}
+
+PUBLIC void
+codb_print_poolmask_(const int *handle, const int *ithread)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  if (pm) {
+    SET_PDB(*handle);
+    char *buf;
+    int buflen;
+    int it = *ithread;
+    int inumt = 0;
+    int j, npools;
+    int j1, j2;
+    int myproc = 0;
+    codb_procdata_(&myproc, NULL, NULL, NULL, &inumt);
+    npools = pm->npools;
+    if (it >= 1 && it <= inumt) { j1 = it; j2 = it;    }
+    else                        { j1 =  1; j2 = inumt; }
+    fprintf(stderr,
+	    "%d: codb_print_poolmask_() for h=%d, thread range [%d..%d]; pm=%p; nperm=%d\n",
+	    myproc, *handle, j1, j2, pm, pdb->nperm);
+    buflen = (1 + npools) * 12 + 200;
+    ALLOC(buf, buflen);
+    for (it=j1; it<=j2; it++) {
+      char *c = buf;
+      int inc = sprintf(c,
+			"%d: it=%d: pm[0]=%d --> pm[1..%d]=\n%d:  ",
+			myproc,it,pm->poolmask[IT][0],npools,myproc);
+      c += inc;
+      for (j=1; j<=npools; j++) {
+	inc = sprintf(c,"%d ",pm->poolmask[IT][j]);
+	c += inc;
+	if (j%32 == 0 && j<npools) {
+	  inc = sprintf(c,"\n%d:  ",myproc);
+	  c += inc;
+	}
+      }
+      fprintf(stderr,"%s\n", buf);
+    }
+    FREE(buf);
+  }
+}
+
+PUBLIC void
+codb_reset_poolmask_(const int *handle, const int *ithread)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  if (pm) {
+    int it = *ithread;
+    int j, npools;
+    npools = pm->npools;
+    if (pm->poolmask[IT][0] != 0) {
+      /* Poolmasking is OFF by default i.e. poolmask is NOT checked, 
+	 unless permanent poolmask has been employed */
+      SET_PDB(*handle);
+      int set = (pdb->nperm > 0) ? 1 : 0;
+      pm->poolmask[IT][0] = set;
+      for (j=1; j<=npools; j++) {
+	/* If Poolmasking was ON, then EXCLUDE all pools by default */
+	/* Pool number j will NOT be processed, unless poolmasking is OFF */
+	pm->poolmask[IT][j] = SETPM(j,set);
+      }
+    } /* if (pm->poolmask[IT][0] != 0) */
+  }
+}
+
+PUBLIC void
+codb_end_poolmask_(const int *handle)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  if (pm) {
+    const int version = 0;
+    const int idummy = -1;
+
+    /* Release pool_list-space(s), if allocated, with version == 0 */
+
+    apply_poolmasking_(handle, &version, 
+		       "", &idummy,
+                       &idummy, &idummy, &idummy, &idummy,
+		       &idummy, &idummy, &idummy
+		       ,0);
+
+    FREE(pm->dbname);
+    pm->handle = -pm->handle;
+  }
+  {
+    SET_PDB(*handle);
+    pdb->nperm = 0;
+    pdb->npermcnt = 0;
+    FREE(pdb->perm_list);
+  }
+}
+
+PUBLIC void
+codb_init_poolmask_(const int *handle,
+		    const char *dbname,
+		    const int *num_poolnos_in
+		    /* Hidden arguments */
+		    ,int dbname_len)
+{
+  int it, inumt, j, npools, maxval;
+  ODB_PoolMask *pm = NULL;
+  char *p = getenv("ODB_POOLMASKING");
+  int value = p ? atoi(p) : 0;
+  int poolmasking = (value == 1) ? 1 : 0;
+  DECL_FTN_CHAR(dbname);
+
+  ALLOC_FTN_CHAR(dbname);
+
+  npools = *num_poolnos_in;
+
+  maxval = permanent_poolmask(handle, p_dbname, npools);
+
+  if (!poolmasking && maxval == 0) {
+      int myproc = 0;
+      codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+      if (myproc == 1) 
+	fprintf(stderr,
+		"***INFO: Poolmasking ignored altogether for database '%s'\n",
+		p_dbname);
+  }
+  else if (maxval > 0) {
+    poolmasking = 1;
+  }
+
+  /* Pointer pm doesn't get initialized at all 
+     ==> behaves as if poolmasking doesn't exist at all */
+
+  if (!poolmasking) goto finish;
+
+  if (TEST_PM(*handle)) {
+    pm = &db_pm[(*handle)-1];
+  }
+  else { /* Bailing out */
+    goto finish;
+  }
+
+  inumt = get_max_threads_();
+
+  pm->handle = *handle;
+  pm->npools = npools;
+  pm->inumt = inumt;
+  if (pm->poolmask) {
+    for (it=1; it<=inumt; it++) {
+      FREE(pm->poolmask[IT]);
+    }
+    FREE(pm->poolmask);
+  }
+  FREE(pm->dbname);
+  pm->dbname = STRDUP(p_dbname);
+
+  ALLOC(pm->poolmask, inumt);
+  for (it=1; it<=inumt; it++) {
+    ALLOC(pm->poolmask[IT], 1 + npools);
+    /* Poolmasking is still uninitialized, but the
+       subsequent codb_reset_poolmask_() will do the job */
+    pm->poolmask[IT][0] = -1;
+    codb_reset_poolmask_(handle, &it);
+  }
+
+ finish:
+  FREE_FTN_CHAR(dbname);
+}
+
+PUBLIC void
+codb_get_permanent_poolmask_(const int *handle,
+			     const int *num_poolnos_in,
+			     int  poolnos[],
+			     int *num_poolnos_out)
+{
+  int n = 0;
+  SET_PDB(*handle);
+  if (*num_poolnos_in >= pdb->npermcnt) {
+    int i=0, j;
+    for (j=1; j<=pdb->nperm; j++) {
+      if (pdb->perm_list[j]) poolnos[i++] = j;
+    }
+    if (pdb->npermcnt - i != 0) {
+      RAISE_SIGNAL(SIGABRT, "Programming error: pdb->npermcnt - i != 0", pdb->npermcnt - i);
+    }
+    *num_poolnos_out = pdb->npermcnt;
+  }
+  else {
+    *num_poolnos_out = -pdb->npermcnt; /* *num_poolnos_in needs to be bigger i.e. ABS(-npermcnt) */
+  }
+}
+
+
+PUBLIC int *
+ODB_get_permanent_poolmask(int handle, int *npools)
+{
+  int n = -1;
+  int *poolnos = NULL;
+  ODB_PoolMask *pm = GET_PM(handle);
+  if (pm) {
+    int nout = 0;
+    SET_PDB(handle);
+    n = pdb->npermcnt;
+    CALLOC(poolnos, n);
+    codb_get_permanent_poolmask_(&handle, &n, poolnos, &nout);
+    if (npools) *npools = nout;
+  }
+  else if (npools) {
+    int j;
+    n = *npools;
+    ALLOC(poolnos, n);
+    for (j=1; j<=n; j++) poolnos[j-1] = j;
+  }
+  return poolnos; /* Watch for memory leaks here */
+}
+
+
+PUBLIC void
+codb_in_permanent_poolmask_(const int *handle,
+			    const int *poolno,
+			    int *retcode)
+{ 
+  /* 
+     Returns 1 (=true), the Poolno is in valid range and if
+
+     1) it is found from the permanent poolmask list
+     2) if the permanent poolmask is not defined at all
+     3) if the poolmasking is off
+
+     Otherwise returns 0 (=false)
+  */
+
+  int rc = 0;
+  int Handle = *handle;
+  int Poolno = *poolno;
+  ODB_PoolMask *pm = GET_PM(Handle);
+  if (pm) {
+    SET_PDB(*handle);
+    if (pdb->npermcnt > 0 && pdb->perm_list &&
+	Poolno >= 1 && Poolno <= pdb->nperm && 
+	pdb->perm_list[Poolno]) rc = 1;
+  }
+  else { 
+    /* Poolmasking and/or permanent poolmask was off for this database
+       Note: Upper bound range could not be checked; assumed ok */
+    if (Poolno >= 1) rc = 1;
+  }
+  *retcode = rc;
+}
+			    
+PUBLIC int
+ODB_in_permanent_poolmask(int handle, int poolno)
+{
+  int rc = 0;
+  codb_in_permanent_poolmask_(&handle, &poolno, &rc);
+  return rc;
+}
+
+PUBLIC void
+codb_get_poolmask_(const int *handle,
+		   const int *num_poolnos_in,
+		         int  poolnos[],
+		         int *poolmask_set,
+		         int *num_poolnos_out)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  *poolmask_set = -1;
+  *num_poolnos_out = 0;
+  if (pm) {
+    DEF_IT;
+    int j, npools;
+    npools = MIN(*num_poolnos_in, pm->npools);
+    for (j=1; j<=npools; j++) {
+      poolnos[j-1] = pm->poolmask[IT][j];
+    }
+    *poolmask_set = pm->poolmask[IT][0];
+    *num_poolnos_out = npools;
+  }
+}
+
+
+PUBLIC void
+codb_set_poolmask_(const int *handle,
+		   const int *num_poolnos_in,
+		   const int  poolnos[],
+		   const int *onoff)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  if (pm) {
+    DEF_IT;
+    int OnOff = *onoff;
+    int j, npools;
+    SET_PDB(*handle);
+    codb_reset_poolmask_(handle, &it);
+    npools = *num_poolnos_in;
+    for (j=0; j<npools; j++) {
+      int poolno = poolnos[j];
+      if (poolno >= 1 && poolno <= pm->npools) {
+	/* include (= On i.e. 1) / exclude (= Off i.e. 0) 
+	   the pool number "poolno" from the execution */
+	pm->poolmask[IT][poolno] = SETPM(poolno,OnOff); 
+      }
+    }
+    pm->poolmask[IT][0] = 1;
+  }
+}
+
+PUBLIC void
+codb_poolmasking_status_(const int *handle,
+			 int *retcode)
+{
+  ODB_PoolMask *pm = GET_PM(*handle);
+  int rc = pm ? 1 : 0;
+  *retcode = rc;
+}
+
+PUBLIC void
+codb_alloc_poolmask_(const int *maxhandle)
+{
+  if (db || !maxhandle) return;
+  MaxHandle = *maxhandle;
+  CALLOC(db, MaxHandle);
+  CALLOC(db_pm, MaxHandle);
+}
diff --git a/odb/src/lib/poolreg.c b/odb/src/lib/poolreg.c
new file mode 100644
index 0000000..3a5caea
--- /dev/null
+++ b/odb/src/lib/poolreg.c
@@ -0,0 +1,113 @@
+/* poolreg.c */
+
+/* Provides cached/hashed access to (handle,poolno)-pair */
+
+/* Note : Similar to forfunc.c, but independent of "it" -- thread id */
+
+#include "odb.h"
+
+#ifndef POOLREG_HASHSIZE
+#define POOLREG_HASHSIZE 1021U
+#endif
+
+PRIVATE uint POOLREG_hashsize = 0;
+
+typedef struct _POOLREG_cache {
+  int handle;
+  int poolno;
+  ODB_Pool *pool;
+  struct _POOLREG_cache *collision;
+} POOLREG_cache;
+
+PRIVATE POOLREG_cache *POOLREG_ht = NULL;
+
+PRIVATE uint
+Hash(int handle, int poolno)
+{
+  uint hashval = 100 * poolno + handle; /* handle typically << 100 */
+  hashval %= POOLREG_hashsize;
+  return hashval;
+}
+
+PRIVATE void
+HashInit()
+{
+  if (!POOLREG_ht) {
+    POOLREG_cache *tmp_POOLREG_ht = NULL;
+    char *p = getenv("ODB_POOLREG_HASHSIZE");
+    if (p) {
+      POOLREG_hashsize = atoi(p);
+      if (POOLREG_hashsize <= 0) POOLREG_hashsize = POOLREG_HASHSIZE;
+    }
+    else
+      POOLREG_hashsize = POOLREG_HASHSIZE;
+    CALLOC(tmp_POOLREG_ht, POOLREG_hashsize);
+    POOLREG_ht = tmp_POOLREG_ht;
+  }
+}
+
+PUBLIC void
+init_POOLREG_lock()
+{
+  HashInit();
+}
+
+PUBLIC ODB_Pool *
+get_poolreg(int handle, int poolno)
+{
+  ODB_Pool *pool = NULL;
+  if (handle >= 1 && poolno >= 1) {
+    uint index = Hash(handle, poolno);
+    POOLREG_cache *p = &POOLREG_ht[index];
+    while (p) {
+      if (p->handle == handle && p->poolno == poolno && p->pool) {
+	pool = p->pool;
+	break;
+      }
+      p = p->collision;
+    }
+  }
+  return pool;
+}
+
+
+PRIVATE POOLREG_cache *
+NewEntry(int handle, int poolno, ODB_Pool *pool)
+{
+  POOLREG_cache *p;
+  ALLOC(p, 1);
+  p->handle    = handle;
+  p->poolno    = poolno;
+  p->pool      = pool;
+  p->collision = NULL;
+  return p;
+}
+
+PUBLIC void
+put_poolreg(int handle, int poolno, ODB_Pool *pool)
+{
+  if (handle >= 1 && poolno >= 1) {
+    uint index = Hash(handle, poolno);
+    POOLREG_cache *p = &POOLREG_ht[index];
+    if (p->handle == 0) { /* Allocated (upon HashInit), but not in use yet */
+      p->handle = handle;
+      p->poolno = poolno;
+      p->pool   = pool;
+    }
+    else {
+      POOLREG_cache *lastp = NULL;
+      do { /* Re-use an existing position ? */
+	lastp = p;
+	if (p->handle == handle && p->poolno == poolno) {
+	  p->pool = pool;
+	  break;
+	}
+	p = p->collision;
+      } while (p);
+      if (!p) {
+	p = NewEntry(handle, poolno, pool);
+	lastp->collision = p; /* chain */
+      }
+    }
+  }
+}
diff --git a/odb/src/lib/prt.c b/odb/src/lib/prt.c
new file mode 100644
index 0000000..89103f8
--- /dev/null
+++ b/odb/src/lib/prt.c
@@ -0,0 +1,473 @@
+#include "odb.h"
+#include "cmaio.h"
+#include "cdrhook.h"
+
+PRIVATE FILE *fpcached = NULL;
+PRIVATE int fprtio = -1;
+PRIVATE char *iobuf = NULL;
+#define default_iobufsize  1048576
+PRIVATE int iobufsize = default_iobufsize;
+
+PUBLIC FILE *
+ODB_getprt_FP()
+{
+  FILE *fp = (fprtio >= 0) ? CMA_get_fp(&fprtio) : stdout;
+  DRHOOK_START(ODB_getprt_FP);
+  fpcached = fp;
+  DRHOOK_END(0);
+  return fp;
+}
+
+PUBLIC void
+codb_flushprt_(int *retcode)
+{
+  DRHOOK_START(codb_flushprt_);
+  *retcode = 0;
+  if (fpcached) fflush(fpcached);
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_closeprt_(int *retcode)
+{
+  DRHOOK_START(codb_closeprt_);
+  *retcode = 0;
+  if (fprtio >= 0) {
+    cma_close_(&fprtio, retcode);
+    FREE(iobuf);
+    fprtio = -1;
+    fpcached = NULL;
+  }
+  else if (fpcached) {
+    fflush(fpcached);
+  }
+  DRHOOK_END(0);
+}
+
+PUBLIC void
+codb_openprt_(const char *filename,
+	      const int *append_mode,
+	      int *retcode,
+	      /* Hidden arguments */
+	      int filename_len)
+{
+  int rc = 0;
+  DRHOOK_START(codb_openprt_);
+  codb_closeprt_(&rc);
+  if (strnequ(filename,"stdout",filename_len)) {
+    fpcached = stdout;
+    rc = 1;
+  }
+  else if (strnequ(filename,"stderr",filename_len)) {
+    fpcached = stderr;
+    rc = 1;
+  }
+  else {
+    cma_open_(&fprtio, filename, (*append_mode) ? "a" : "w", &rc, filename_len, 1);
+    if (rc == 1) {
+      FILE *fp = ODB_getprt_FP();
+      if (fp) {
+	char *env = getenv("ODB_IO_BUFSIZE");
+	if (env) iobufsize = atoi(env);
+	if (iobufsize < default_iobufsize) iobufsize = default_iobufsize;
+	FREE(iobuf);
+	ALLOC(iobuf, iobufsize + 8);
+	if (iobuf) setvbuf(fp, iobuf, _IOFBF, iobufsize);
+      }
+    }
+  }
+  *retcode = rc;
+  DRHOOK_END(0);
+}
+
+
+PUBLIC void
+codb_lineprt_(const unsigned char *line,
+	      int *retcode,
+	      /* Hidden arguments */
+	      int line_len)
+{
+  int rc = -1;
+  DRHOOK_START(codb_lineprt_);
+  if (fprtio >= 0) {
+    cma_writeb_(&fprtio, line, &line_len, &rc);
+  }
+  else if (fpcached) {
+    rc = fwrite(line, sizeof(*line), line_len, fpcached);
+  }
+  *retcode = rc;
+  DRHOOK_END(line_len);
+}
+
+
+/* -- 
+   Much faster C-based formatting for use by 
+   prtdata() in module/odbprint.F90 
+
+   See also module/odbshared.F90 for "prt_t" format definitions
+   -- */
+
+#define DELIMPRT ((delim && delim_len > 0) ? delim : " ")
+#define DELIMLEN ((delim && delim_len > 0) ? ( (*delim == '\0') ? 0 : strlen(delim) ) : 1)
+
+void
+codb_fill_trueint_(const int *print_immediately,
+		   const char *delim,
+		   const char *fmt,
+		   const int *i,
+		   char *buf,
+		   int *retcode
+		   /* Hidden arguments (ignored) */
+		   ,const int delim_len
+		   ,const int fmt_len
+		   ,const int buf_len)
+{
+  /* pint          = prt_t( 1, 13, '(1x,a12)', "%s%*lld"//char(0)) */
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_trueint_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen,(long long int)*i)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen,(long long int)*i);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_yyyymmdd_(const int *print_immediately,
+		    const char *delim,
+		    const char *fmt,
+		    const int *i,
+		    char *buf,
+		    int *retcode
+		    /* Hidden arguments (ignored) */
+		    ,const int delim_len
+		    ,const int fmt_len
+		    ,const int buf_len)
+{
+  /* pyyyymmdd     = prt_t( 7, 14, '(6x,i8.8)', "%s%*.8lld"//char(0)) */
+  /* or with ODB_PRINT_PRETTY_DATE_TIME=1, using */
+  /* pyyyymmdd_pdt = prt_t(17, 14, '(3x,i2.2,"-",a3,"-",i4.4)', "%s%s"//char(0)) */
+  DRHOOK_START(codb_fill_yyyymmdd_);
+  {
+    int yyyymmdd = *i;
+    int yyyy = (yyyymmdd/10000)%10000;
+    int mm = (yyyymmdd/100)%100;
+    int dd = yyyymmdd%100;
+    char s[15];
+    const char *mon[1+12] = 
+      { 
+	"???", 
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+      };
+    snprintf(s,sizeof(s),"   %2.2d-%s-%4.4d",
+	     dd, (mm >= 1 && mm <= 12) ? mon[mm] : mon[0], yyyy);
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,fmt,DELIMPRT,s)
+      : snprintf(buf,buf_len,fmt,DELIMPRT,s);
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_hhmmss_(const int *print_immediately,
+		  const char *delim,
+		  const char *fmt,
+		  const int *i,
+		  char *buf,
+		  int *retcode
+		  /* Hidden arguments (ignored) */
+		  ,const int delim_len
+		  ,const int fmt_len
+		  ,const int buf_len)
+{
+  /* phhmmss       = prt_t( 8, 12, '(6x,i6.6)', "%s%*.6lld"//char(0)) */
+  /* or with ODB_PRINT_PRETTY_DATE_TIME=1, using */
+  /* phhmmss_pdt   = prt_t(18, 12, '(4x,i2.2,":",i2.2,":",i2.2)', "%s%s"//char(0)) */
+  DRHOOK_START(codb_fill_hhmmss_);
+  {
+    int hhmmss = *i;
+    int hh = (hhmmss/10000)%100;
+    int mm = (hhmmss/100)%100;
+    int ss = hhmmss%100;
+    char s[13];
+    snprintf(s,sizeof(s),"    %2.2d:%2.2d:%2.2d",hh,mm,ss);
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,fmt,DELIMPRT,s)
+      : snprintf(buf,buf_len,fmt,DELIMPRT,s);
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_truehex_(const int *print_immediately,
+		   const char *delim,
+		   const char *fmt,
+		   const unsigned int *u,
+		   char *buf,
+		   int *retcode
+		   /* Hidden arguments (ignored) */
+		   ,const int delim_len
+		   ,const int fmt_len
+		   ,const int buf_len)
+{
+  /* phex          = prt_t( 6, 12, '(2x,"0x",z8.8)', "%s%*s0x%8.8llx"//char(0)) */
+  int blen = buf_len - DELIMLEN - 8;
+  DRHOOK_START(codb_fill_truehex_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen," ",(unsigned long long int)*u)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen," ",(unsigned long long int)*u);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_ctrlw_(const int *print_immediately,
+		 const char *delim,
+		 const char *fmt,
+		 /* In the following two: "unsigned int" rather than "int"
+		    just to avoid seeing the sign (which would be wrong anyway) */
+		 const unsigned int *poolno, /* the correct range [0..2147483647] */
+		 const unsigned int *rownum, /* the correct range [0..2147483647] */
+		 char *buf,
+		 int *retcode
+		 /* Hidden arguments (ignored) */
+		 ,const int delim_len
+		 ,const int fmt_len
+		 ,const int buf_len)
+{
+  /* pdbidx        = prt_t( 9, 20, '(i10,i10.10)', "%s%10u%10.10u"//char(0)) */
+  DRHOOK_START(codb_fill_ctrlw_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,*poolno,*rownum)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,*poolno,*rownum);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_truelonglongint_(const int *print_immediately,
+			   const char *delim,
+			   const char *fmt,
+			   const long long int *ll,
+			   char *buf,
+			   int *retcode
+			   /* Hidden arguments (ignored) */
+			   ,const int delim_len
+			   ,const int fmt_len
+			   ,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_truelonglongint_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen,*ll)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen,*ll);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_longlongint_(const int *print_immediately,
+		       const char *delim,
+		       const char *fmt,
+		       const double *d,
+		       char *buf,
+		       int *retcode
+		       /* Hidden arguments (ignored) */
+		       ,const int delim_len
+		       ,const int fmt_len
+		       ,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_longlongint_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen,(long long int)*d)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen,(long long int)*d);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_ulonglongint_(const int *print_immediately,
+			const char *delim,
+			const char *fmt,
+			const double *d,
+			char *buf,
+			int *retcode
+			/* Hidden arguments (ignored) */
+			,const int delim_len
+			,const int fmt_len
+			,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_ulonglongint_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen,(unsigned long long int)*d)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen,(unsigned long long int)*d);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_dble_(const int *print_immediately,
+		const char *delim,
+		const char *fmt,
+		const double *d,
+		char *buf,
+		int *retcode
+		/* Hidden arguments (ignored) */
+		,const int delim_len
+		,const int fmt_len
+		,const int buf_len)
+{
+  /* preal         = prt_t( 3, 22, '(1x,1p,g21.14)', "%s%*.14g"//char(0)) */
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_dble_);
+  *retcode = 
+    (*print_immediately && fpcached)
+    ? fprintf(fpcached,fmt,DELIMPRT,blen,*d)
+    : snprintf(buf,buf_len,fmt,DELIMPRT,blen,*d);
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_varprec_(const int *print_immediately,
+		   const char *delim,
+		   const char *fmt,
+		   const double *d,
+		   char *buf,
+		   int *retcode
+		   /* Hidden arguments (ignored) */
+		   ,const int delim_len
+		   ,const int fmt_len
+		   ,const int buf_len)
+{
+  /* pvarprec      = prt_t(10, 22, '(1x,1p,g21.14)', "%s%*.*g"//char(0)) */
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_varprec_);
+  {
+    int prec = MAX(8,blen-5); /* precision in digits */
+    prec = MIN(prec,blen);
+    prec = MIN(prec,14);
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,fmt,DELIMPRT,blen,prec,*d)
+      : snprintf(buf,buf_len,fmt,DELIMPRT,blen,prec,*d);
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_string_(const int *print_immediately,
+		  const char *delim,
+		  const char *fmt,
+		  const double *d,
+		  char *buf,
+		  int *retcode
+		  /* Hidden arguments (ignored) */
+		  ,const int delim_len
+		  ,const int fmt_len
+		  ,const int buf_len)
+{
+  /* pstring       = prt_t( 4, 12, "(2x,'''',a8,'''')", "%s%*s'%8s'"//char(0)) */
+  int blen = buf_len - DELIMLEN - 10;
+  DRHOOK_START(codb_fill_string_);
+  {
+    int j;
+    register char *c;
+    S2D_Union u;
+    u.dval = *d;
+    if (u.llu == S2D_all_blanks) {
+      c = &u.str[sizeof(double)];
+    }
+    else {
+      c = u.str;
+      for (j=0; j<sizeof(double); j++) {
+	if (!isprint(*c)) *c = '?';
+	c++;
+      }
+    }
+    *c = 0;
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,fmt,DELIMPRT,blen," ",u.str)
+      : snprintf(buf,buf_len,fmt,DELIMPRT,blen," ",u.str);
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_null_(const int *print_immediately,
+		const char *delim,
+		const int *len,
+		char *buf,
+		int *retcode
+		/* Hidden arguments (ignored) */
+		,const int delim_len
+		,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_null_);
+  {
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,"%s%*s",DELIMPRT,blen,"NULL")
+      : snprintf(buf,buf_len,"%s%*s",DELIMPRT,blen,"NULL");
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_unknown_(const int *print_immediately,
+		   const char *delim,
+		   const int *len,
+		   char *buf,
+		   int *retcode
+		   /* Hidden arguments (ignored) */
+		   ,const int delim_len
+		   ,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_unknown_);
+  {
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,"%s%*s",DELIMPRT,blen,"<what>")
+      : snprintf(buf,buf_len,"%s%*s",DELIMPRT,blen,"<what>");
+  }
+  DRHOOK_END(0);
+}
+
+void
+codb_fill_bitfield_(const int *print_immediately,
+		    const char *delim,
+		    const int *len,
+		    const unsigned int *u,
+		    char *buf,
+		    int *retcode
+		    /* Hidden arguments (ignored) */
+		    ,const int delim_len
+		    ,const int buf_len)
+{
+  int blen = buf_len - DELIMLEN;
+  DRHOOK_START(codb_fill_bitfield_);
+  {
+    char s[MAXBITS+1]; /* MAXBITS == 32 from "privpub.h" */
+    char *c = s;
+    unsigned int one = 1U << (MAXBITS - 1); /* 1 << 31 */
+    int ilen = MAX(MAXBITS,blen);
+    int j;
+    for (j=0; j<MAXBITS; j++) {
+      *c++ = (*u & one) ? '1' : '0';
+      one >>= 1;
+    }
+    *c = 0;
+    *retcode = 
+      (*print_immediately && fpcached)
+      ? fprintf(fpcached,"%s%*s",DELIMPRT,ilen,s)
+      : snprintf(buf,buf_len,"%s%*s",DELIMPRT,ilen,s);
+  }
+  DRHOOK_END(0);
+}
diff --git a/odb/src/lib/random_odb.c b/odb/src/lib/random_odb.c
new file mode 100644
index 0000000..55e3e85
--- /dev/null
+++ b/odb/src/lib/random_odb.c
@@ -0,0 +1,57 @@
+/* random_odb.c */
+
+#include "odb.h"
+
+#define ODB_RAND_MAX (32767.0)
+
+static unsigned int *seed = NULL;
+
+PRIVATE double
+myrand(unsigned int *next) {
+    /* Returns a random number between [0 .. 1] double floating point */
+    (*next) = (*next) * 1103515245 + 12345;
+    return ( ((*next)/65536U) % 32768U )/ODB_RAND_MAX;
+}
+
+
+PUBLIC void
+init_RANDOM()
+{
+  if (!seed) {
+    DEF_INUMT;
+    int j;
+    ALLOC(seed, inumt);
+    for (j=0; j<inumt; j++) seed[j] = 1;
+  }
+}
+
+
+PUBLIC double
+ODB_seed(double myseed)
+{
+  double oldseed;
+  int is_parallel_region = 0;
+  coml_in_parallel_(&is_parallel_region);
+  if (is_parallel_region) {
+    DEF_IT;
+    oldseed = seed[--it];
+    seed[it] = myseed;
+  }
+  else {
+    DEF_INUMT;
+    int j;
+    if (!seed) init_RANDOM(); /* Normally not called */
+    oldseed = seed[0];
+    for (j=0; j<inumt; j++) seed[j] = myseed;
+  }
+  return oldseed;
+}
+
+
+PUBLIC double
+ODB_random()
+{
+  DEF_IT;
+  if (!seed) init_RANDOM(); /* Normally not called */
+  return myrand(&seed[--it]);
+}
diff --git a/odb/src/lib/rgg_regions.c b/odb/src/lib/rgg_regions.c
new file mode 100644
index 0000000..d0da72a
--- /dev/null
+++ b/odb/src/lib/rgg_regions.c
@@ -0,0 +1,258 @@
+
+/* rgg_regions.c */
+
+/* Maps (lat,lon) into its Reduced Gaussian Grid box at resolution Txxxx */
+
+/* A big thanks to Lars Isaksen, ECMWF, 14/3/2008 !!! */
+
+#include "odb.h"
+#include "regcache.h"
+#include "cmaio.h"
+#include "cdrhook.h"
+
+extern void gauaw_odb_(double PA[],
+		       double PW[],
+		       const int *K,
+		       int *KRET);         /* See lib/gauaw_odb.F90 */
+
+#define rgg_cache_t regcache_t
+
+#define ERROR(msg) { if (msg) fprintf(stderr,"%s\n",msg); RAISE(SIGABRT); }
+
+static rgg_cache_t **rgg_cache = NULL;
+
+PRIVATE int *
+read_rtablel_2_file(int Txxxx, int *NRGRI_len, int *Nlons)
+{
+  /* Reads F90 namelist file $ODB_RTABLE_PATH/rtablel_2<xxxx>
+     to find out how many latitude bands there are (must be xxxx+1)
+     and how many longitudes boxes per latband there are */
+
+  int *NRGRI = NULL;
+  int nb = 0;
+  int nlons = 0;
+  int nexp = Txxxx + 1; /* Expect this many latitude bands */
+
+  char *rtable_file = NULL;
+  const char fmt[] = "$ODB_RTABLE_PATH/rtablel_2%3.3d";
+  int len = STRLEN(fmt) + 10;
+  FILE *fp = NULL;
+  int iounit = -1;
+  int iret = 0;
+
+  ALLOCX(rtable_file, len);
+  snprintf(rtable_file, len, fmt, Txxxx);
+
+  cma_open_(&iounit, rtable_file, "r", &iret, STRLEN(rtable_file), 1);
+  fp = (iounit >= 0 && iret == 1) ? CMA_get_fp(&iounit) : NULL;
+
+  if (fp) {
+    char line[80];
+    CALLOC(NRGRI, nexp);
+
+    while (!feof(fp) && fgets(line, sizeof(line), fp)) {
+      char *lb = strchr(line,'(');
+      char *rb = lb ? strchr(line,')') : NULL;
+      char *eq = rb ? strchr(line,'=') : NULL;
+      if (lb && rb && rb) {
+	if (lb < rb && rb < eq) {
+	  char *comma = strchr(line,',');
+	  int id = 0;
+	  int npts = 0;
+	  if (comma && eq < comma) *comma = '\0';
+	  ++lb;
+	  *rb = '\0';
+	  ++eq;
+	  id = atoi(lb) - 1;
+	  npts = atoi(eq);
+	  if (id >= 0 && id < nexp && npts > 0) {
+	    NRGRI[id] = npts;
+	    nlons += npts;
+	  }
+	} /* if (lb < rb && rb < eq) */
+      } /* if (lb && rb && rb) */
+    } /* while (!feof(fp) ... ) */
+
+    cma_close_(&iounit, &iret);
+    nb = nexp;
+  }
+  else {
+    char *env = getenv("ODB_RTABLE_PATH");
+    fprintf(stderr,
+	    "read_rtablel_2_file(): Unsupported resolution Txxxx = %d or $ODB_RTABLE_PATH not defined\n", Txxxx);
+    if (env) {
+      const char cmd[] = 
+	"/bin/ls -C1 $ODB_RTABLE_PATH/rtablel_2* | /bin/sed 's|^.*/rtablel_2||' | /bin/sort -n >&2";
+      fprintf(stderr,
+	      "                      Currently supported resolutions are:\n");
+      fflush(stderr);
+      system(cmd);
+    }
+    ERROR(NULL);
+  }
+
+  if (NRGRI_len) *NRGRI_len = nb;
+  if (Nlons) *Nlons = nlons;
+
+  FREEX(rtable_file);
+
+  return NRGRI;
+}
+
+
+PUBLIC rgg_cache_t **
+ODBc_init_rgg_cache()
+{
+  if (!rgg_cache) {
+    DEF_INUMT;
+    CALLOC(rgg_cache, inumt);
+  }
+  return rgg_cache;
+}
+
+
+PUBLIC rgg_cache_t *
+ODBc_get_rgg_cache(int n)
+{
+  /* Here "n" is the "xxxx" of resolution "Txxxx" */
+  DEF_IT;
+  rgg_cache_t *p = NULL;
+  DRHOOK_START(ODBc_get_rgg_cache);
+  {
+    if (!rgg_cache) rgg_cache = ODBc_init_rgg_cache(); /* Normally not called */
+    p = rgg_cache[IT];
+
+    while (p) {
+      if (n == p->n || p->kind == rgg_cache_kind) {
+	/* Matched */
+	break;
+      }
+      p = (n < p->n) ? p->left : p->right;
+    } /* while (p) */
+
+    if (!p) {
+
+      /* This is done only once per "n", per "it" */
+
+      int iret = 0;
+      int ndgl = n + 1; /* Number of latitude bands i.e. "nb" */
+      int nlons = 0;
+      int *loncnt = read_rtablel_2_file(n, &ndgl, &nlons);
+      double *latband = NULL;
+      double *midlat = NULL;
+      double *stlon = NULL;
+      double *deltalon = NULL;
+      double *zlmu = NULL;
+      double *zw = NULL;
+      double *zlatedge = NULL;
+      const double zfact = recip_pi_over_180;
+      double zfact2 = ((double)45)/atan(1);
+      int ii, iequator = ndgl/2;
+
+#if 0
+      fprintf(stderr,"ndgl = %d = nb, iequator = %d\n", ndgl, iequator);
+#endif
+
+      ALLOC(zlmu, ndgl);
+      ALLOC(zw, ndgl);
+      gauaw_odb_(zlmu,zw,&ndgl,&iret);
+
+      midlat = zlmu;
+      for (ii=0; ii<ndgl; ii++) {
+	midlat[ii] = zfact2*asin(zlmu[ii]);
+      }
+
+      /* FREE(zlmu); */
+
+      ALLOC(zlatedge, ndgl + 1);
+      zlatedge[0] = half_pi;
+      for (ii=0; ii<ndgl/2; ii++) {
+	zlatedge[ii+1] = asin( MAX(-1, MIN(1,sin(zlatedge[ii])-zw[ii]) ) );
+      }
+
+      FREE(zw);
+      
+      zlatedge[iequator] = 0;
+
+      for (ii=iequator+1; ii<ndgl+1; ii++) {
+	/* fprintf(stderr, "\t[%d] = -[%d]\n", ii, ndgl-ii); */
+	zlatedge[ii] = -zlatedge[ndgl-ii];
+      }
+
+      /* Latitude bands : from North (+90) to South (-90) */
+
+      ALLOC(latband, ndgl + 1);
+      for (ii=0; ii<ndgl+1; ii++) {
+	latband[ii] = zfact*zlatedge[ii];
+      }
+
+      FREE(zlatedge);
+
+      /* Starting longitudes, deltalon's */
+      
+      ALLOC(stlon, ndgl);
+      ALLOC(deltalon, ndgl);
+
+      for (ii=0; ii<ndgl; ii++) {
+	int cnt = loncnt[ii];
+	const double three_sixty = 360;
+	double delta = three_sixty/cnt;
+	deltalon[ii] = delta;
+	stlon[ii] = -delta/2;
+      }
+
+#if 0
+      {
+	for (ii=0; ii<ndgl; ii++) {
+	  fprintf(stderr,"%d: (%d) latband[] = %.4f, loncnt[] = %d\n",
+		  ii, ii+1, latband[ii], loncnt[ii]);
+	}
+	fprintf(stderr,"and : latband[%d] = %.4f\n",
+		ii, latband[ii]);
+      }
+#endif
+	
+      /* Store in cache */
+      p = ODBc_put_regcache(rgg_cache_kind,
+			    n, ndgl, 
+			    latband, midlat,
+			    stlon, deltalon, 
+			    loncnt,
+			    ODBc_init_rgg_cache, rgg_cache);
+
+      p->resol = (deltalon[iequator] + deltalon[iequator+1])/2;
+#if 0
+      fprintf(stderr,"Equator resolution is %.2f degrees\n", p->resol);
+#endif
+
+    }
+  }
+  DRHOOK_END(n);
+  return p;
+}
+
+PUBLIC double 
+ODB_rgg_boxid(double lat, double lon, double Txxxx)
+{
+  return ODBc_get_boxid(lat, lon, Txxxx, NULL, ODBc_get_rgg_cache);
+}
+
+PUBLIC double 
+ODB_rgg_boxlat(double lat, double lon, double Txxxx)
+{
+  return ODBc_get_boxlat(lat, lon, Txxxx, ODBc_get_rgg_cache);
+}
+
+PUBLIC double 
+ODB_rgg_boxlon(double lat, double lon, double Txxxx)
+{
+  return ODBc_get_boxlon(lat, lon, Txxxx, ODBc_get_rgg_cache);
+}
+
+PUBLIC double
+ODB_rgg_resol(double Txxxx)
+{
+  rgg_cache_t *p = ODBc_get_rgg_cache(Txxxx);
+  double resol = p ? p->resol : 0;
+  return resol;
+}
diff --git a/odb/src/lib/rlnkdb.F90 b/odb/src/lib/rlnkdb.F90
new file mode 100644
index 0000000..c5b4064
--- /dev/null
+++ b/odb/src/lib/rlnkdb.F90
@@ -0,0 +1,42 @@
+SUBROUTINE rlnkdb(parent, kpa, pchild, kch, klink, kret)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+implicit none
+
+INTEGER(KIND=JPIM), intent(in)  :: kpa, kch
+REAL(KIND=JPRB),    intent(in)  :: parent(:), pchild(:)
+INTEGER(KIND=JPIM), intent(out) :: klink(:), kret
+
+
+!-- Correct code (even if some parents have no childs)
+INTEGER(KIND=JPIM) :: actlen(kpa) ! automatic array
+INTEGER(KIND=JPIM) :: jpa, icount, target
+INTEGER(KIND=JPIM) :: jchstart, jchend, jch
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('RLNKDB',0,ZHOOK_HANDLE)
+kret = 0
+if (kpa > 0) then
+  jchend = 0
+  do jpa=1,kpa
+    target = parent(jpa)
+    jchstart = jchend + 1
+    icount = 0
+    do jch=jchstart,kch
+      if (pchild(jch) /= target) exit
+      icount = icount + 1
+    enddo
+    actlen(jpa) = icount
+    jchend = jchend + icount
+  enddo
+  klink(1) = 1
+  do jpa=2,kpa+1
+    klink(jpa) = klink(jpa-1) + actlen(jpa-1)
+  enddo
+  kret = kpa+1
+endif
+IF (LHOOK) CALL DR_HOOK('RLNKDB',1,ZHOOK_HANDLE)
+
+END SUBROUTINE rlnkdb
diff --git a/odb/src/lib/rlnkdb2.F90 b/odb/src/lib/rlnkdb2.F90
new file mode 100644
index 0000000..31deae0
--- /dev/null
+++ b/odb/src/lib/rlnkdb2.F90
@@ -0,0 +1,33 @@
+SUBROUTINE rlnkdb2(koffset, &
+ & parr_in, klda, krows, kcol1, kcol2, &
+ & ktarget, karr_out) 
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: koffset
+INTEGER(KIND=JPIM), intent(in)  :: klda, krows, kcol1, kcol2, ktarget
+REAL(KIND=JPRB)   , intent(in)  :: parr_in(klda, kcol1:kcol2)
+INTEGER(KIND=JPIM), intent(out) :: karr_out(krows + 1)
+INTEGER(KIND=JPIM) :: j, imin, imax
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('RLNKDB2',0,ZHOOK_HANDLE)
+if (krows > 0) then
+  imin =  huge(krows)
+  imax = -huge(krows)
+  do j=1,krows
+    imin = min(imin,int(parr_in(j,ktarget)))
+    imax = max(imax,int(parr_in(j,ktarget)))
+  enddo
+  if (imax == imin) then
+    do j=1,krows + 1
+      karr_out(j) = koffset + (j-1) * imax
+    enddo
+  else
+    karr_out(1) = koffset
+    do j=2,krows + 1
+      karr_out(j) = karr_out(j-1) + int(parr_in(j-1,ktarget))
+    enddo
+  endif
+endif
+IF (LHOOK) CALL DR_HOOK('RLNKDB2',1,ZHOOK_HANDLE)
+END SUBROUTINE rlnkdb2
diff --git a/odb/src/lib/rot.c b/odb/src/lib/rot.c
new file mode 100644
index 0000000..ce3c7e2
--- /dev/null
+++ b/odb/src/lib/rot.c
@@ -0,0 +1,184 @@
+/* rot.c */
+
+#include "odb.h"
+
+static const double small = 1e-6;
+
+/*
+  The sign transfer function SIGN(X,Y)  takes the sign of the second argument and
+  puts it on the first argument, ABS(X)  if Y >= 0  and -ABS(X)  if Y < 0.
+*/
+
+#define SIGN(X,Y) (((Y) >= 0) ? ABS(X) : -ABS(X))
+
+PRIVATE void
+RotArea(double lat, double lon,
+	double rpole1, double rpole2,
+	double *Rlat, double *Rlon)
+{
+  /* Originates from UK MetOffice Unified Model's Fortran-routine "rotarea" */
+
+  /*
+    !-----------------------------------------------------------------------
+    !
+    ! subroutine    : rotarea
+    !
+    ! purpose       : to calculate latitude and longitude of an observation
+    !               : if placed on a grid where the pole is has been moved
+    !
+    ! description   : the transformation formula are described in the
+    !               : unified model on-line documentation paper s1
+    !
+    ! arguments     : lat    - i/p, real value of latitude to be rotated
+    !               : lon    - i/p, real value of longitude to be rotated
+    !               : rpole1 - i/p, real value of latitude pole coordinate
+    !               : rpole2 - i/p, real value of longitude pole coordinate
+    !               : rlat   - o/p, real value of rotated latitude
+    !               : rlon   - o/p, real value of rotated longitude
+    !-----------------------------------------------------------------------
+  */
+
+  /*
+    !-----------------------------------------------------------------------
+    ! declare real variables (in alphabetical order)
+    !-----------------------------------------------------------------------
+  */
+
+  double a_lambda;            /* !- following variables declared and      */
+  double a_phi;               /* !- initialized are expressions or values */
+  double arg;                 /* !- of the rotated coords.                */
+  double cos_phi_pole;
+  double e_lambda;            /* !- used in the calculation               */
+  double e_phi;
+  double lambda_zero;
+  double rlat;                /* !- rotated latitude                      */
+  double rpole_lat;           /* !- latitude of rotated pole from rpole   */
+  double rlon;                /* !- rotated longitude                     */
+  double rpole_lon;           /* !- longitude of rotated pole from rpole  */
+  double sin_phi_pole;
+  double term1;
+  double term2;
+
+  /*
+    !-----------------------------------------------------------------------
+    ! initialize variables
+    !-----------------------------------------------------------------------
+  */
+
+  rpole_lat=rpole1;
+  rpole_lon=rpole2;
+  lambda_zero=rpole_lon+180;
+  sin_phi_pole=sin(pi_over_180*rpole_lat);
+  cos_phi_pole=cos(pi_over_180*rpole_lat);
+
+  /*
+    !----------------------------------------------------------------------
+    ! check latitude and longitude values are sensible.
+    !----------------------------------------------------------------------
+  */
+
+  if (lat <= 90 && lat >= -90 && lon <= 180 && lon >= -180) {
+
+    /*
+      !----------------------------------------------------------------------
+      ! scale longitude to range -180 to +180 degrees
+      !----------------------------------------------------------------------
+    */
+    
+    a_lambda=lon-lambda_zero;
+    if (a_lambda >  180) a_lambda=a_lambda-360;
+    if (a_lambda < -180) a_lambda=a_lambda+360;
+
+
+    /*
+      !----------------------------------------------------------------------
+      ! convert latitude and longitude to radians
+      !----------------------------------------------------------------------
+    */
+
+    a_lambda=pi_over_180*a_lambda;
+    a_phi=pi_over_180*lat;
+    
+    /*
+      !----------------------------------------------------------------------
+      ! calculate rotated latitude using equation 4.6 in UM documentation
+      !----------------------------------------------------------------------
+    */
+    
+    arg=-cos_phi_pole*cos(a_lambda)*cos(a_phi)+sin(a_phi)*sin_phi_pole;
+    arg=MIN(arg,1);
+    arg=MAX(arg,-1);
+    e_phi=asin(arg);
+    rlat=recip_pi_over_180*e_phi;
+
+    /*
+      !----------------------------------------------------------------------
+      ! compute rotated longitude using equation 4.6 in um documentation
+      !----------------------------------------------------------------------
+    */
+
+    term1=(cos(a_phi)*cos(a_lambda)*sin_phi_pole+sin(a_phi)*cos_phi_pole);
+    term2=cos(e_phi);
+    
+    if (term2 < small) {
+      e_lambda=0;
+    }
+    else {
+      arg=term1/term2;
+      arg=MIN(arg,1);
+      arg=MAX(arg,-1);
+      e_lambda=recip_pi_over_180*acos(arg);
+      e_lambda=SIGN(e_lambda,a_lambda);
+    }
+
+    /*
+      !----------------------------------------------------------------------
+      ! scale longitude to range 0 to 360 degs
+      !----------------------------------------------------------------------
+    */
+
+    if (e_lambda >= 360) e_lambda=e_lambda-360;
+    if (e_lambda <    0) e_lambda=e_lambda+360;
+
+    /*
+      !----------------------------------------------------------------------
+      ! we want the longitude in the range -180 to 180 degs so..
+      !----------------------------------------------------------------------
+    */
+
+    if (e_lambda > 180) e_lambda=e_lambda-360;
+    rlon=e_lambda;
+  }
+  else {
+
+    /*
+      !----------------------------------------------------------------------
+      ! bad lat/lon, rotated lat/lon = input lat/lon
+      !----------------------------------------------------------------------
+    */
+    
+    rlat=lat;
+    rlon=lon;
+  }
+
+  if (Rlat) *Rlat = rlat;
+  if (Rlon) *Rlon = rlon;
+}
+
+
+PUBLIC double
+ODB_rotlat(double lat, double lon, double polelat, double polelon)
+{
+  double rlat;
+  RotArea(lat,lon,polelat,polelon,&rlat,NULL);
+  return rlat;
+}
+
+
+PUBLIC double
+ODB_rotlon(double lat, double lon, double polelat, double polelon)
+{
+  double rlon;
+  RotArea(lat,lon,polelat,polelon,NULL,&rlon);
+  return rlon;
+}
diff --git a/odb/src/lib/rsort32_odb.c b/odb/src/lib/rsort32_odb.c
new file mode 100644
index 0000000..17e5d6c
--- /dev/null
+++ b/odb/src/lib/rsort32_odb.c
@@ -0,0 +1,344 @@
+#ifdef RS6K
+/* for now ... */
+#pragma options optimize=2
+#endif
+
+#include "alloc.h"
+
+/* rsort32_odb_() : 32-bit Fortran-callable RADIX-sort */
+
+/* 
+   by Sami Saarinen, ECMWF, 3/2/1998 
+         - " -              1/2/2000 : BIG_ENDIAN & LITTLE_ENDIAN labels renamed to *_INDIAN
+                                       since they may conflict with the ones in <sys/endian.h>
+         - " -              3/1/2001 : reference to valloc() removed; ALLOC() modified
+	 - " -	           25/1/2001 : BIG_INDIAN removed (as label)
+			               LITTLE_INDIAN called as LITTLE
+         - " -            ??/9?/2001 : Speedup in rsort32 [hmmm ... under investigation]
+         - " -             14/3/2002 : rsort32_func implemeted to enable to run alternative sorting
+                                       routine than rsort32
+         - " -            18/02/2005 : Handle 64-bit (signed) ints
+         - " -            22/02/2005 : Some optimization & endian detection on-the-fly
+         - " -            07/07/2005 : Mods in index_adj & bitsum
+	                               Added support for 64-bit unsigned ints
+
+   Thanks to Mike Fisher, ECMWF
+   and Cray SCILIB ORDERS()-function developers
+*/
+
+/* 
+   Methods:
+
+   0 : Unsigned 32-bit ints
+   1 :   Signed 32-bit ints
+   2 :          64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
+   3 :          32-bit floats  (IEEE) : signbit +  8-bit exp + 23-bits mantissa
+   4 :   Signed 64-bit ints
+   5 : Unsigned 64-bit ints
+
+*/
+
+typedef unsigned int  Uint32;
+typedef unsigned char Uchar;
+
+#ifdef __uxppx__
+#ifndef VPP
+#define VPP
+#endif
+#endif
+
+#ifdef VPP
+#pragma global noalias
+#pragma global novrec
+#elif defined(NECSX)
+#pragma cdir options -pvctl,nodep
+#endif
+
+#if defined(VPP) || defined(NECSX)
+/* .. or any vector machine */
+PUBLIC int rsort32_odb_SpeedUp = 0;
+#else
+/* scalar prozezzorz */
+PUBLIC int rsort32_odb_SpeedUp = 1;
+#endif
+
+#define SORT_UINT 0
+#define SORT_INT  1
+#define SORT_R64  2
+#define SORT_R32  3
+#define SORT_I64  4
+#define SORT_U64  5
+
+#define BITSUM(x) bitsum[x] += ((item >> x) & 1U)
+
+#define SIGNBIT32   0x80000000
+#define MASKALL32   0xFFFFFFFF
+#define ZEROALL32   0x00000000
+
+#define CVMGM(a,b,c) ( ((c) & SIGNBIT32) ? (a) : (b) )
+
+#define N32BITS 32
+
+void 
+rsort32_odb_(const    int *Mode,
+	     const    int *N,
+	     const    int *Inc,
+	     const    int *Start_addr,
+	           Uint32  Data[],
+	     int           index[],
+	     const    int *Index_adj,
+	              int *retc)
+{
+  int mode = *Mode;
+  int method = mode%10;
+  int n = *N;
+  int rc = n;
+  int inc = *Inc;
+  int index_adj = *Index_adj;
+  int addr = (*Start_addr) - 1; /* Fortran to C */
+  int i, j, jj;
+  Uchar xorit = 0;
+  Uchar copytmp = 0;
+  Uchar alloc_data = 0;
+  Uint32 *data = NULL;
+  int *tmp = NULL;
+  Uint32 bitsum[N32BITS];
+  int lsw, msw;
+
+  if (method != SORT_UINT   &&
+      method != SORT_INT    &&
+      method != SORT_R64    &&
+      method != SORT_R32    &&
+      method != SORT_I64    &&
+      method != SORT_U64 ) {
+    rc = -1;
+    goto finish;
+  }
+
+  if (n <= 0) {
+    if (n < 0) rc = -2;
+    goto finish;
+  }
+
+  if (inc < 1) {
+    rc = -3;
+    goto finish;
+  }
+
+  { /* Little/big-endian selection */
+    extern int ec_is_little_endian();
+    int i_am_little = ec_is_little_endian();
+
+    if (i_am_little) { 
+      /* We are on little-endian machine */
+      lsw   =  0;
+      msw   =  1;
+    }
+    else { 
+      /* We are on big-endian machine */
+      lsw   =  1;
+      msw   =  0;
+    }
+  }
+
+  if (method == SORT_R64    || 
+      method == SORT_I64    ||
+      method == SORT_U64) {
+    inc  *= 2;
+    addr *= 2;
+  }
+
+  if (mode < 10) {
+    /* index[] needs to be initialized */
+    for (i=0; i<n; i++) index[i] = i + index_adj;
+  }
+
+  alloc_data = ((inc > 1) 
+		|| (method == SORT_R32) 
+		|| (method == SORT_R64)
+		|| (method == SORT_I64)
+		|| (method == SORT_U64)
+		);
+  if (alloc_data) ALLOC(data, n);
+
+  if (method == SORT_R32) {
+    j = addr;
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, SIGNBIT32, Data[j]);
+      data[i] = Data[j] ^ mask;
+      j += inc;
+    }
+
+    method = SORT_UINT;
+  }
+  else if (method == SORT_R64) {
+    int Method = 10 + SORT_UINT;
+    const int aStart_addr = 1;
+    int aN = n;
+    const int aInc = 1;
+    int aIndex_adj = index_adj;
+
+    /* Least significant word */
+    j  = addr + lsw;
+    jj = addr + msw;
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, ZEROALL32, Data[jj]);
+      data[i] = Data[j] ^ mask;
+      j += inc;
+      jj += inc;
+    }
+
+    rsort32_odb_(&Method, &aN, &aInc, &aStart_addr, data, index, &aIndex_adj, &rc);
+
+    if (rc != n) goto finish;
+
+    /* Most significant word */
+    jj = addr + msw;
+    for (i=0; i<n; i++) {
+      Uint32 mask = CVMGM(MASKALL32, SIGNBIT32, Data[jj]);
+      data[i] = Data[jj] ^ mask;
+      jj += inc;
+    }
+
+    method = SORT_UINT;
+  }
+  else if (method == SORT_I64 || method == SORT_U64) {
+    int Method = 10 + SORT_UINT;
+    const int aStart_addr = 1;
+    int aN = n;
+    const int aInc = 1;
+    int aIndex_adj = index_adj;
+
+    /* Least significant word */
+    jj = addr + lsw;
+    for (i=0; i<n; i++) {
+      data[i] = Data[jj];
+      jj += inc;
+    }
+
+    {
+	extern void rsort32_(const    int *Mode,
+			     const    int *N,
+			     const    int *Inc,
+			     const    int *Start_addr,
+			           Uint32  Data[],
+			     int           index[],
+			     const    int *Index_adj,
+			              int *retc);
+	rsort32_(&Method, &aN, &aInc, &aStart_addr, data, index, &aIndex_adj, &rc);
+    }
+
+    if (rc != n) goto finish;
+
+    /* Most significant word */
+    if (method == SORT_I64) {
+      jj = addr + msw;
+      for (i=0; i<n; i++) {
+	data[i] = Data[jj] ^ SIGNBIT32;
+	jj += inc;
+      }
+    }
+    else { /* unsigned 64-bit ints i.e. method == SORT_U64 */
+      jj = addr + msw;
+      for (i=0; i<n; i++) {
+	data[i] = Data[jj];
+	jj += inc;
+      }
+    }
+
+    method = SORT_UINT;
+  }
+  else if (inc > 1) {
+    j = addr;
+    for (i=0; i<n; i++) {
+      data[i] = Data[j];
+      j += inc;
+    }
+  }
+  else {
+    data = &Data[addr];
+  }
+
+  xorit = (method == SORT_INT);
+
+  /* Check whether particular "bit-columns" are all zero or one */
+
+  for (j=0; j<N32BITS; j++) bitsum[j] = 0;
+
+  for (i=0; i<n; i++) {
+    Uint32 item;
+    if (xorit) data[i] ^= SIGNBIT32;
+    item = data[i];
+    /* Unrolled, full vector */
+    BITSUM(0) ; BITSUM(1) ; BITSUM(2) ; BITSUM(3) ;
+    BITSUM(4) ; BITSUM(5) ; BITSUM(6) ; BITSUM(7) ;
+    BITSUM(8) ; BITSUM(9) ; BITSUM(10); BITSUM(11);
+    BITSUM(12); BITSUM(13); BITSUM(14); BITSUM(15);
+    BITSUM(16); BITSUM(17); BITSUM(18); BITSUM(19);
+    BITSUM(20); BITSUM(21); BITSUM(22); BITSUM(23);
+    BITSUM(24); BITSUM(25); BITSUM(26); BITSUM(27);
+    BITSUM(28); BITSUM(29); BITSUM(30); BITSUM(31);
+  }
+
+  ALLOC(tmp, n);
+
+  jj = 0;
+  for (j=0; j<N32BITS; j++) {
+    int sum = bitsum[j];
+    if (sum > 0 && sum < n) { /* if 0 or n, then the whole column of bits#j 0's or 1's */
+      Uint32 mask = (1U << j);
+      int *i1, *i2;
+      
+      if (jj%2 == 0) {
+	i1 = index;
+	i2 = tmp;
+	copytmp = 1;
+      }
+      else {
+	i1 = tmp;
+	i2 = index;
+	copytmp = 0;
+      }
+      
+      if (rsort32_odb_SpeedUp == 0) {
+	int k = 0;
+	for (i=0; i<n; i++) /* Gather zero bits */
+	  if ( (data[i1[i]-index_adj] & mask) ==    0 ) i2[k++] = i1[i];
+	
+	for (i=0; i<n; i++) /* Gather one bits */
+	  if ( (data[i1[i]-index_adj] & mask) == mask ) i2[k++] = i1[i];
+      }
+      else
+      {
+	int k1 = 0, k2 = n-sum;
+	for (i=0; i<n; i++) { /* Gather zero & one bits in a single sweep */
+	  Uint32 value = data[i1[i]-index_adj] & mask;
+	  i2[value == 0 ? k1++ : k2++] = i1[i];
+	} /* for (i=0; i<n; i++) */
+	if (k1 + sum != n || k2 != n) {
+	  fprintf(stderr,
+		  "***Programming error in rsort32_odb_(): k1 + sum != n || k2 != n; k1=%d,k2=%d,sum=%d,n=%d\n",
+		  k1,k2,sum,n);
+	  RAISE(SIGABRT);
+	}
+      }
+      
+      jj++;
+    }
+  }
+
+  if (copytmp) for (i=0; i<n; i++) index[i] = tmp[i];
+
+  FREE(tmp);
+
+  if (!alloc_data && xorit && inc == 1) {
+    /* 32-bit signed ints : backward */
+    for (i=0; i<n; i++) data[i] ^= SIGNBIT32;
+  }
+
+  if (alloc_data) FREE(data);
+
+ finish:
+
+  *retc = rc;
+}
diff --git a/odb/src/lib/savelist.c b/odb/src/lib/savelist.c
new file mode 100644
index 0000000..f1c89d6
--- /dev/null
+++ b/odb/src/lib/savelist.c
@@ -0,0 +1,115 @@
+#include "odb.h"
+
+/* savelist.c */
+
+/* === Note: Not at all optimized ; to be done */
+
+/* 
+   Checks whether particular column is in the savelist
+   (i.e. ODB_SAVELIST or ODB_SAVELIST_<dbname>)
+   and will make sure ODB_close() updates-to-disk *ONLY*
+   such columns which are in the list.
+   Other columns remain unchanged, even if their values
+   have been changed during the course of program execution.
+
+   Examples: 
+
+   1) save physically to disk only "an_depar at body" for any database:
+
+   export ODB_SAVELIST="an_depar at body"
+
+   2) save physically to disk only "an_depar at body,fg_depar at body" for database CCMA:
+
+   export ODB_SAVELIST_CCMA="an_depar at body,fg_depar at body"
+
+*/
+
+
+static int
+SearchEnv(const char *env, const char *name)
+{
+  int rc = 0; /* Since we are indeed calling this utility, env-variable has a value */
+  int name_len = strlen(name);
+  const char *pos = env;
+  const char *last = env + strlen(env);
+  for (;;) {
+    const char *loc = strstr(pos,name);
+    if (loc) {
+      const char delims[] = " ,/|\t";
+      char lo = (loc == pos) ? 0 : loc[-1];
+      char hi = (loc + name_len < last) ? loc[name_len] : 0;
+      if (
+	  (lo == 0 || strchr(delims,lo)) &&
+	  ((lo == hi) || (hi == 0 || strchr(delims,hi)))
+	 ) {
+	rc = 1; /* found !! */
+	break;
+      }
+      pos = loc + name_len;
+      if (pos >= last) break; /* cannot be found */
+    }
+    else {
+      break; /* no chance to find */
+    } /* if (loc) else ... */
+  } /* for (;;) */
+  return rc;
+}
+
+
+int 
+ODB_savelist(const char *dbname, /* NULL or f.ex. "ECMA" */
+	     const char *name)   /* Like "colname at tablename" */
+{
+  /* 
+     Returns 0, if :
+     (ODB_SAVELIST_<dbname> OR ODB_SAVELIST) is defined AND
+     "colname at tablename" is *NOT* found in the environment variable;
+     consequently forces the use of saved_data[]
+
+     Returns 1, if :
+     (ODB_SAVELIST_<dbname> OR ODB_SAVELIST) is defined AND 
+     "colname at tablename" *IS* defined within the environment variable;
+     forces the use of updated data (d[] or pd[])
+
+     Returns -1, if : (the default)
+     (ODB_SAVELIST_<dbname> OR ODB_SAVELIST) is NOT defined;
+     forces the use of updated data (d[] or pd[])
+  */
+
+  int rc = -1;
+  int done = 0;
+
+  if (!name) goto finish;
+
+  if (dbname) {
+    int envname_len = strlen("ODB_SAVELIST") + 1 + strlen(dbname) + 1;
+    char *envname;
+    ALLOC(envname,envname_len);
+    snprintf(envname,envname_len,"ODB_SAVELIST_%s",dbname);
+    {
+      char *env = getenv(envname);
+      if (env) {
+	rc = SearchEnv(env,name);
+	done = 1;
+      }
+    }
+    FREE(envname);
+  } /* if (dbname) */
+
+  if (!done) {
+    static int first_time = 1; /* not thread safe */
+    static char *env = NULL;
+    if (first_time) {
+      env = getenv("ODB_SAVELIST");
+      first_time = 0;
+    }
+    if (env) {
+      rc = SearchEnv(env,name);
+      done = 2;
+    }
+  } /* if (!done) */
+
+ finish:
+  /* fprintf(stderr,"ODB_savelist(%s, %s): done=%d, rc=%d\n",dbname,name,done,rc); */
+  return rc;
+}
diff --git a/odb/src/lib/setup_sort.c b/odb/src/lib/setup_sort.c
new file mode 100644
index 0000000..e63c41b
--- /dev/null
+++ b/odb/src/lib/setup_sort.c
@@ -0,0 +1,133 @@
+#include "odb.h"
+
+/* routine to change the default sorting functions nearly on the fly */
+
+#define MAX_KNOWN_FUNC 6
+
+#ifdef RS6K
+static int prev_fun = 4;
+#elif defined(VPP) || defined(NECSX)
+/* .. or any other vector machine */
+static int prev_fun = 0;
+#else
+/* scalar prozezzorz */
+static int prev_fun = 1;
+#endif
+
+/* From IFSAUX */
+
+extern void 
+rsort32_setup_(void (*func)(const    int *Mode,
+			    const    int *N,
+			    const    int *Inc,
+			    const    int *Start_addr,
+			    unsigned int Data[],
+			    int      index[],
+			    const    int *Index_adj,
+			    int     *retc),
+	       int *speedup);
+
+/* Known function  0 & 1 */
+
+extern void 
+rsort32_(const    int *Mode,
+	 const    int *N,
+	 const    int *Inc,
+	 const    int *Start_addr,
+	 unsigned int  Data[],
+	          int  index[],
+	 const    int *Index_adj,
+	          int *retc);
+
+/* From ODB */
+
+/* Known function  2 & 3 */
+
+extern void 
+rsort32_odb_(const    int *Mode,
+	     const    int *N,
+	     const    int *Inc,
+	     const    int *Start_addr,
+	     unsigned int  Data[],
+	              int  index[],
+	     const    int *Index_adj,
+	              int *retc);
+
+/* Known function 4 & 5 (rsort32_ibm_ genuinely invokes jsort.F only on RS6K) */
+
+extern void 
+rsort32_ibm_(const    int *Mode,
+	     const    int *N,
+	     const    int *Inc,
+	     const    int *Start_addr,
+	     unsigned int  Data[],
+	              int  index[],
+	     const    int *Index_adj,
+	              int *retc);
+
+extern int rsort32_odb_SpeedUp; /* for now */
+
+void
+setup_sort_(const int *func_no,
+	    int *prev_func_no)
+{
+  int Func_no = prev_fun;
+
+  if (func_no) {
+    Func_no = *func_no;
+  }
+  else {
+    char *p = getenv("ODB_SORTING_FUNCTION");
+    if (p) Func_no = atoi(p);
+  }
+
+  if (prev_func_no) *prev_func_no = prev_fun;
+
+  if (Func_no >= 0 && Func_no <= MAX_KNOWN_FUNC) {
+    boolean changed = 0;
+    int speedup;
+    int Myproc;
+
+    codb_procdata_(&Myproc, NULL, NULL, NULL, NULL);
+
+    changed = (Func_no != prev_fun) ? 1 : 0;
+
+    switch (Func_no) {
+    case 0: /* link-time default (on non-IBM/RS600 machines & vector machines) */
+      speedup = 0;
+      rsort32_setup_(rsort32_, &speedup);
+      break;
+    case 1:/* link-time default (on non-IBM/RS600 machines & scalar machines) */
+      speedup = 1;
+      rsort32_setup_(rsort32_, &speedup);
+      break;
+    case 2:
+      rsort32_odb_SpeedUp = speedup = 0;
+      rsort32_setup_(rsort32_odb_, &speedup);
+      break;
+    case 3:
+      rsort32_odb_SpeedUp = speedup = 1;
+      rsort32_setup_(rsort32_odb_, &speedup);
+      break;
+    case 4: /* link-time default (on IBM/RS600 machines only) */
+      speedup = 0;
+      rsort32_setup_(rsort32_ibm_, &speedup);
+      break;
+    case 5:
+      speedup = 1;
+      rsort32_setup_(rsort32_ibm_, &speedup);
+      break;
+    default:
+      changed = 0;
+      break;
+    } /* switch (Func_no) */
+
+    if (Myproc == 1 && changed) {
+      fprintf(stderr, 
+	      "setup_sort_(): ODB_SORTING_FUNCTION changed from %d to %d (speedup param.=%d)\n",
+	      prev_fun, Func_no, speedup);
+    }
+
+    prev_fun = Func_no;
+  }
+}
diff --git a/odb/src/lib/solar.c b/odb/src/lib/solar.c
new file mode 100644
index 0000000..a87bef3
--- /dev/null
+++ b/odb/src/lib/solar.c
@@ -0,0 +1,163 @@
+
+/* solar.c */
+
+/* Various solar angle/time related functions */
+
+#include "odb.h"
+
+
+PUBLIC double
+ODB_time_angle(double Time, double lon)
+{ /* Assume time in format HHMMSS */
+  /* Assume lon(gitude) in degrees [-180 .. +180] */
+  double ta = 15 * (ODB_hours_utc(Time) - 12) + lon;
+  if (ta <= -180) {
+    ta = ta + 360;
+  }else if (ta > 180){
+    ta = ta - 360;
+  }
+  return ta;
+}
+PUBLIC void /* Fortran callable */
+codb_time_angle_(double *Time, double *lon, double *Result)
+{
+  if (lon && Time && Result) *Result = ODB_time_angle(*Time, *lon);
+}
+
+
+PUBLIC double
+ODB_hour_angle(double Time)
+{ /* Assume time in format HHMMSS */
+  /* Assume lon(gitude) in degrees [-180 .. +180] */
+  double ha = ODB_time_angle(Time, 0);
+  return ha;
+}
+PUBLIC void /* Fortran callable */
+codb_hour_angle_(double *Time, double *Result)
+{
+  if (Time && Result) *Result = ODB_hour_angle(*Time);
+}
+
+
+PRIVATE double
+fraction_through_year(double Date, double Time)
+{
+  double Year0101 = 10000*((int)Date/10000) +  101;
+  double Year1231 = 10000*((int)Date/10000) + 1231;
+  double days_per_year = ODB_datenum(Year1231) - ODB_datenum(Year0101) + 1;
+  double result = (ODB_datenum(Date) - ODB_datenum(Year0101) + 10 + ODB_hours_utc(Time)/24);
+  result /= days_per_year;
+  return result;
+}
+
+
+PUBLIC double
+ODB_solar_declination(double Date, double Time)
+{
+  double sda;
+  sda = -23.45 * cos(fraction_through_year(Date, Time) * two_pi);
+  return sda;
+}
+PUBLIC void /* Fortran callable */
+codb_solar_declination_(double *Date, double *Time, double *Result)
+{
+  if (Date && Time && Result) *Result = ODB_solar_declination(*Date, *Time);
+}
+
+
+PUBLIC double
+ODB_solar_zenith(double Date, double Time, double lat, double lon)
+{ /* Assume date in format YYYYMMDD */
+  /* Assume time in format HHMMSS */
+  /* Assume lat(itude) in degrees [-90 .. +90] */
+  /* Assume lon(gitude) in degrees [-180 .. +180] */
+  double sza;
+  double ta = ODB_time_angle(Time, lon) * pi_over_180;
+  double sda = ODB_solar_declination(Date, Time) * pi_over_180;
+  lat *= pi_over_180;
+  sza = acos(sin(lat) * sin(sda) + cos(lat) * cos(sda) * cos(ta)) * recip_pi_over_180;
+  return sza;
+}
+PUBLIC void /* Fortran callable */
+codb_solar_zenith_(double *Date, double *Time, double *lat, double *lon, double *Result)
+{
+  if (lat && lon && Date && Time && Result) *Result = ODB_solar_zenith(*Date, *Time, *lat, *lon);
+}
+
+
+PUBLIC double
+ODB_daynight(double Date, double Time, double lat, double lon)
+{
+  /* Input arguments : same as in ODB_solar_zenith()-function above
+
+     Calculates day/night fraction [-1..++1] using solar zenith angle (sza)
+     When sza > 90 (degrees), then its considered ~ night time
+
+     The result is scaled so that values >= 0 == day, < 0 night.
+
+     Note: sza's range is [0..180] degrees.
+  */
+  double sza = ODB_solar_zenith(Date, Time, lat, lon);
+  return (double)(1 - sza/90);
+}
+PUBLIC void /* Fortran callable */
+codb_daynight_(double *Date, double *Time, double *lat, double *lon, double *Result)
+{
+  if (lat && lon && Date && Time && Result) *Result = ODB_daynight(*Date, *Time, *lat, *lon);
+}
+
+
+PUBLIC double
+ODB_solar_elevation(double Date, double Time, double lat, double lon)
+{ /* Also known as "solar altitude angle" */
+  /* Assume date in format YYYYMMDD */
+  /* Assume time in format HHMMSS */ 
+  /* Assume lat(itude) in degrees [-90 .. +90] */
+  /* Assume lon(gitude) in degrees [-180 .. +180] */
+  double sela = 90 - ODB_solar_zenith(Date, Time, lat, lon);
+  return sela;
+}
+PUBLIC void /* Fortran callable */
+codb_solar_elevation_(double *Date, double *Time, double *lat, double *lon, double *Result)
+{
+  if (lat && lon && Date && Time && Result) *Result = ODB_solar_elevation(*Date, *Time, *lat, *lon);
+}
+
+
+PUBLIC double
+ODB_solar_azimuth(double Date, double Time, double lat, double lon)
+{ /* Assume date in format YYYYMMDD */
+  /* Assume time in format HHMMSS */
+  /* Assume lat(itude) in degrees [-90 .. +90] */
+  /* Assume lon(gitude) in degrees [-180 .. +180] */
+  /* Routine gives azimuth clockwise from north.  */
+
+  /* The working version of this routine was kindly provided 
+     by Niels Bormann, ECMWF, 24-Jul-2007 ; Cheers Niels !! */ 
+
+  double saza = RMDI;                                                    /* Az */
+
+  double sza = ODB_solar_zenith(Date, Time, lat, lon) * pi_over_180;    /* solar zenith angle */
+  double denom = sin(sza);
+  double ta = ODB_time_angle(Time, lon);                                /* time angle */
+  double lat_R = lat * pi_over_180;                                     /* latitude */
+  double sda = ODB_solar_declination(Date, Time) * pi_over_180;         /* solar declination angle */
+  double nom = sin(sda) * cos(lat_R) - cos(sda) * sin(lat_R) * cos(ta * pi_over_180);
+  if (ABS(denom) < 0.001 || ABS(nom) > ABS(denom)) {
+    saza = RMDI;
+  }
+  else {
+    double frac = nom / denom;
+    saza = acos(frac) * recip_pi_over_180;
+    if (ta > 0) { 
+      saza = -saza;
+    }
+  }
+
+  return saza;
+}
+PUBLIC void /* Fortran callable */
+codb_solar_azimuth_(double *Date, double *Time, double *lat, double *lon, double *Result)
+{
+  if (lat && lon && Date && Time && Result) *Result = ODB_solar_azimuth(*Date, *Time, *lat, *lon);
+}
diff --git a/odb/src/lib/stack.c b/odb/src/lib/stack.c
new file mode 100644
index 0000000..61b17b4
--- /dev/null
+++ b/odb/src/lib/stack.c
@@ -0,0 +1,114 @@
+
+/* stack.c */
+
+#include "evaluate.h"
+
+typedef struct _opstk_t {
+  Kind_t kind;
+  struct _opstk_t *prev;
+  struct _opstk_t *next;
+} opstk_t;
+
+static opstk_t **OpStack_begin = NULL;
+static opstk_t **OpStack_end = NULL;
+static int *OpStack_len = NULL;
+static int *OpStack_maxlen = NULL;
+
+PUBLIC void
+initOpStack()
+{
+  Bool initialized = false;
+  if (!initialized) {
+    DEF_INUMT;
+    CALLOC(OpStack_begin, inumt);
+    CALLOC(OpStack_end, inumt);
+    CALLOC(OpStack_len, inumt);
+    CALLOC(OpStack_maxlen, inumt);
+    initialized = true;
+  }
+  {
+    DEF_IT;
+    opstk_t *p = OpStack_begin[IT];
+    while (p) {
+      opstk_t *save_next = p->next;
+      FREE(p);
+      p = save_next;
+    }
+    OpStack_begin[IT] = OpStack_end[IT] = NULL;
+    OpStack_len[IT] = -1;
+    OpStack_maxlen[IT] = -1;
+    PushOpStack(EMPTY);
+  }
+}
+
+
+PUBLIC int
+OpStackLen()
+{
+  DEF_IT;
+  return OpStack_len[IT];
+}
+
+
+PUBLIC int
+OpStackMaxLen()
+{
+  DEF_IT;
+  return OpStack_maxlen[IT];
+}
+
+
+PUBLIC void
+PushOpStack(Kind_t kind)
+{
+  if (kind != UNKNOWN) {
+    DEF_IT;
+    opstk_t *p;
+    CALLOC(p,1);
+    p->kind = kind;
+    if (!OpStack_begin[IT]) {
+      OpStack_begin[IT] = OpStack_end[IT] = p;
+    }
+    else {
+      p->prev = OpStack_end[IT];
+      OpStack_end[IT]->next = p;
+      OpStack_end[IT] = p;
+    }
+    OpStack_len[IT]++;
+    if (OpStack_len[IT] > OpStack_maxlen[IT]) OpStack_maxlen[IT] = OpStack_len[IT];
+  }
+}
+
+
+PUBLIC Kind_t
+PopOpStack()
+{
+  opstk_t *p = NULL;
+  if (OpStackLen() > 0) { 
+    DEF_IT;
+    p = OpStack_end[IT];
+    OpStack_end[IT] = p->prev;
+    OpStack_len[IT]--;
+  }
+  return p ? p->kind : UNKNOWN;
+}
+
+
+PUBLIC void
+PrintOpStack(void *fp, const char *msg)
+{
+  if (fp) {
+    DEF_IT;
+    const thsafe_parse_t *thsp = GetTHSP();
+    opstk_t *p = OpStack_begin[IT];
+    int j = -1;
+    FprintF(fp,"PrintOpStack : len=%d : %s :",OpStackLen(),msg?msg:"");
+    while (p) {
+      if (j >= OpStackLen()) break;
+      if (j >= 0) FprintF(fp,"[%d]='%s' ",j,KindStr(p->kind));
+      j++;
+      p = p->next;
+    }
+    if (j > -1) FprintF(fp,"\n");
+  }
+}
diff --git a/odb/src/lib/static.c b/odb/src/lib/static.c
new file mode 100644
index 0000000..3ff3dd4
--- /dev/null
+++ b/odb/src/lib/static.c
@@ -0,0 +1,182 @@
+#define STATIC_C
+#include "static.h"
+
+/* Note: Static linking is now on by default (12/2/2003 by SS) */
+
+#ifdef DYNAMIC_LINKING
+PUBLIC int ODBstatic_mode = 0;
+#else
+PUBLIC int ODBstatic_mode = 1;
+#endif
+
+#define BIGNUM 999999
+
+/* Statically supported databases and their initiators */
+
+typedef struct _static_func_t_ {
+  char *dbname;
+  void (*initfunc)();
+  void (*flagsfilefunc)();
+  struct _static_func_t_ *next;
+} Static_func_t;
+
+PRIVATE Static_func_t *f = NULL;
+PRIVATE Static_func_t *flast = NULL;
+
+PUBLIC void
+ODB_add2funclist(const char *dbname, 
+		 void (*func)(),
+		 int ifuncno)
+{
+  Static_func_t *pfound = NULL;
+  Static_func_t *p = f;
+
+  for (;p;) {
+    if (strequ(dbname,p->dbname)) {
+      pfound = p;
+      break;
+    }
+    p = p->next;
+  }
+
+  if (!pfound) {
+    ALLOC(p, 1);
+    p->dbname = STRDUP(dbname);
+    p->initfunc = NULL;
+    p->flagsfilefunc = NULL;
+    p->next = NULL;
+    if (!f) {
+      f = flast = p;
+    }
+    else {
+      flast->next = p;
+      flast = flast->next;
+    }
+    pfound = p;
+  }
+
+  if (pfound) {
+    p = pfound;
+    if (ifuncno == 0) p->initfunc = func;
+    else if (ifuncno == 1) p->flagsfilefunc = func;
+  }
+}
+
+
+PRIVATE void
+ODB_print_flags_file(const char *dbname,
+		     int *retcode,
+		     /* Hidden arguments */
+		     int dbname_len)
+{
+  int rc = 0;
+  int j = 0;
+  Static_func_t *p = f;
+  DECL_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(dbname);
+  rc = -1;
+  j = 0;
+  for (;p;) {
+    if (strequ(p_dbname,p->dbname)) {
+      if (p->flagsfilefunc) p->flagsfilefunc();
+      rc = j;
+      break;
+    }
+    j++;
+    p = p->next;
+  }
+  FREE_FTN_CHAR(dbname);
+  *retcode = rc;
+}
+
+
+PUBLIC void
+codb_print_flags_file_(const char *dbname,
+		       const int *myproc,
+		       int *retcode,
+		       /* Hidden arguments */
+		       int dbname_len)
+{
+  *retcode = BIGNUM;
+  if (*myproc == 1) {
+    ODB_print_flags_file(dbname, retcode, dbname_len);
+  }
+}
+
+
+PRIVATE void
+ODB_static_init(const char *dbname,
+		int *retcode,
+		/* Hidden arguments */
+		int dbname_len)
+{
+  int rc = 0;
+  int j = 0;
+  Static_func_t *p = f;
+  DECL_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(dbname);
+  rc = -1;
+  j = 0;
+  for (;p;) {
+    if (strequ(p_dbname,p->dbname)) {
+      if (p->initfunc) {
+	p->initfunc();
+      }
+      else {
+	fprintf(stderr,
+		"ODB_static_init(): Undefined or invalid init-function for db=\"%s\"\n",
+		p_dbname);
+	RAISE(SIGABRT);
+      }
+      rc = j;
+      break;
+    }
+    j++;
+    p = p->next;
+  }
+  FREE_FTN_CHAR(dbname);
+  *retcode = rc;
+}
+
+
+PUBLIC void
+codb_static_init_(const char *a_out,
+		  const char *dbname,
+		  const int *myproc,
+		  int *retcode,
+		  /* Hidden arguments */
+		  int a_out_len,
+		  int dbname_len)
+{
+  char *env = getenv("ODB_STATIC_LINKING");
+  boolean is_static = env ? atoi(env) : ODBstatic_mode;
+  static boolean first_time = 1;
+  DECL_FTN_CHAR(dbname);
+  ALLOC_FTN_CHAR(dbname);
+
+  *retcode = BIGNUM;
+  if (is_static) { /* static mode */
+    if (first_time && *myproc == 1) {
+      fprintf(stderr,">>> Assuming static linking mode\n");
+    }
+    {
+      char *p = p_dbname;
+      int plen = dbname_len;
+      while (plen > 0) { /* strip leading blanks */
+	if (*p != ' ') break;
+	p++; plen--;
+      }
+      codb_set_entrypoint_(p, plen);
+      ODB_static_init(p, retcode, plen);
+    }
+  }
+  else { /* dynamic mode */
+    if (first_time && *myproc == 1) {
+      fprintf(stderr,">>> Assuming dynamic linking mode\n");
+    }
+  }
+  first_time = 0;
+
+  ODBstatic_mode = is_static;
+  FREE_FTN_CHAR(dbname);
+}
diff --git a/odb/src/lib/symtab.c b/odb/src/lib/symtab.c
new file mode 100644
index 0000000..8772d7f
--- /dev/null
+++ b/odb/src/lib/symtab.c
@@ -0,0 +1,245 @@
+
+/* symtab.c */
+
+#include "alloc.h"
+#include "symtab.h"
+#include "evaluate.h"
+#include "info.h"
+
+static symtab_t **begin_sym = NULL;
+
+PUBLIC void
+initsym()
+{
+  if (!begin_sym) {
+    DEF_INUMT;
+    CALLOC(begin_sym, inumt);
+  }
+}
+
+
+PUBLIC double *
+putsymvec(const char *s, double value, double *vec, int nvec)
+{
+  double *addr = NULL;
+  if (s) {
+    DEF_IT;
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) break; /* A match */
+      p = (cmp < 0) ? p->left : p->right;
+    }
+    if (!p) {
+      CALLOC(p,1);
+      p->name = STRDUP(s);
+      if (begin_sym[IT]) {
+	symtab_t *top = begin_sym[IT];
+	while (top) {
+	  int cmp = strcmp(top->name,p->name);
+	  symtab_t *next = NULL;
+	  if (cmp < 0) {
+	    if (!top->left) { top->left = p; } else { next = top->left; }
+	  }
+	  else {
+	    if (!top->right) { top->right = p; } else { next = top->right; }
+	  }
+	  top = next; /* If next == NULL => new position in tree found => get out */
+	}
+      }
+      else {
+	begin_sym[IT] = p;
+      }
+    }
+    p->value = value;
+    p->active = true;
+    p->vec = vec;
+    p->nvec = nvec;
+    addr = &p->value;
+  }
+  return addr;
+}
+
+PUBLIC double *
+putsym(const char *s, double value)
+{
+  return putsymvec(s, value, NULL, 0);
+}
+
+PRIVATE void
+print1sym(void *fp, const symtab_t *p, int it)
+{
+  if (fp && p) {
+    const thsafe_parse_t *thsp = GetTHSP();
+    const char *s = p->name;
+    double value = p->value;
+    FprintF(fp,"(it#%d)@%p>> %s = %.12g (active ? %s) : left=%p, right=%p\n",
+	    it,p,
+	    s,value,p->active ? "yes" : "no",
+	    p->left, p->right);
+    print1sym(fp,p->left,it);
+    print1sym(fp,p->right,it);
+  }
+}
+
+PUBLIC void
+printsym(void *fp, int it)
+{
+  if (fp) {
+    const thsafe_parse_t *thsp = GetTHSP();
+    const symtab_t *p = begin_sym[IT];
+    FprintF(fp,"---------------------\n");
+    print1sym(fp, p, it);
+  }
+}
+
+PUBLIC double
+getsym(const char *s, Bool *on_error)
+{
+  double value = mdi;
+  if (s) {
+    DEF_IT;
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) { /* A match */
+	value = p->value;
+	if (!p->active) p = NULL;
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+    if (on_error) {
+      if (!p) {
+	/* "Variable not initialized/defined/active" */
+	*on_error = true;
+      }
+      else {
+	*on_error = false;
+      }
+    }
+  }
+  else {
+    if (on_error) *on_error = true;
+  }
+  return value;
+}
+
+PUBLIC double *
+getsymaddr(const char *s)
+{
+  double *addr = NULL;
+  if (s) {
+    DEF_IT;
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) { /* A match */
+	if (!p->active) p = NULL;
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+    addr = p ? &p->value : NULL;
+  }
+  return addr;
+}
+
+PUBLIC double *
+getsymvec(const char *s, int *nvec)
+{
+  if (s) {
+    DEF_IT;
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) { /* A match */
+	if (!p->active) p = NULL;
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+    if (nvec && p) *nvec = p->nvec;
+    else if (nvec) *nvec = 0;
+    return p ? p->vec : NULL;
+  }
+  else {
+    if (nvec) *nvec = 0;
+    return NULL;
+  }
+}
+
+PUBLIC double
+delsym(const char *s, int it)
+{
+  double value = mdi;
+  if (s) {
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) { /* A match */
+	if (*s != '$') {
+	  /* De-activate all but $-variables */
+	  /* Please note that only delentry() [called by delallsym()]
+	     de-activates ALL symbols regardless of their kind */
+	  p->active = false;
+	}
+	value = p->value; /* Its latest value */
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+  }
+  return value;
+}
+
+PRIVATE void
+delentry(symtab_t *p)
+{
+  while (p) {
+    p->active = false;
+    delentry(p->left);
+    p = p->right;
+  }
+}
+
+
+PUBLIC void
+delallsym(const int *specific_it)
+{
+  if (begin_sym) {
+    DEF_INUMT;
+    int it;
+    int it_start = 1, it_end = inumt;
+    if (specific_it) {
+      int sit = *specific_it;
+      if (sit < 1 || sit > inumt) return;
+      it_start = it_end = sit;
+    }
+    for (it=it_start; it<=it_end; it++) {
+      symtab_t *p = begin_sym[IT];
+      delentry(p);
+    }
+  } /* if (begin_sym) */
+}
+
+
+PUBLIC symtab_t *
+getsymtab(const char *s)
+{
+  symtab_t *stab = NULL;
+  if (s) {
+    DEF_IT;
+    symtab_t *p = begin_sym[IT];
+    while (p) {
+      int cmp = strcmp(p->name,s);
+      if (cmp == 0) { /* A match */
+	if (!p->active) p = NULL;
+	break;
+      }
+      p = (cmp < 0) ? p->left : p->right;
+    }
+    stab = p;
+  }
+  return stab;
+}
diff --git a/odb/src/lib/tracing.c b/odb/src/lib/tracing.c
new file mode 100644
index 0000000..49c2377
--- /dev/null
+++ b/odb/src/lib/tracing.c
@@ -0,0 +1,532 @@
+#include "odb.h"
+
+/* Run-time tracing stuff */
+
+PRIVATE FILE *fp_trace = NULL;
+PRIVATE boolean trace_atexit_done = 0;
+PRIVATE int trace_flush_freq = 0;
+PRIVATE int trace_proc = -1;
+
+PRIVATE o_lock_t PBAR_mylock = 0; /* A specific OMP-lock; initialized only once in
+				    odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+/* from libifsaux.a */
+extern double util_walltime_();        /* Wall clock time in seconds */
+extern double util_cputime_();         /* CPU-times (user+system+child(s)) in seconds */
+extern int util_ihpstat_(int *option); /* Peak memory usage in 8 byte words */
+
+#define KILO 1024.0
+#define MEGA 1048576.0
+#define GIGA 1073741824.0
+
+#ifdef VPP
+PRIVATE long long
+getstackusage_odb()
+{
+  extern long long getstackusage_();
+  long long stack_now;
+  static long long init_stack = 0;
+  static int first_time = 1;
+  if (first_time) {
+    init_stack = getstackusage_();
+    first_time = 0;
+  }
+  stack_now = getstackusage_() - init_stack;
+  return stack_now;
+}
+#endif
+
+PRIVATE char *
+trace_stat(boolean final_call)
+{
+  static char buf[1024];
+#ifdef VPP
+  extern long long int gethwm_();
+#elif defined(SGI)
+  PRIVATE long long int gethwm();
+  PRIVATE void pr_infos(double *size, double *rssize);
+#elif defined(RS6K)
+  extern long long int getstk_();
+  extern long long int gethwm_();
+  extern long long int getrss_();
+  extern long long int getcurheap_();
+  extern long long int getpag_();
+#elif defined(LINUX)
+  extern long long int gethwm_();
+  extern long long int getrss_();
+#else
+  int option = 1;
+#endif
+  double hwm, maxrss, rssnow, stack, paging;
+  double wall, cpu;
+
+#ifdef VPP
+  hwm = gethwm_();
+  maxrss = hwm;
+  rssnow = maxrss;
+  stack = getstackusage_odb();
+  paging = 0;
+#elif defined(SGI)
+  pr_infos(&hwm, &stack); /* stack is misleading; is actually maxrss for SGI */
+  maxrss = stack;
+  rssnow = maxrss;
+  paging = 0;
+#elif defined(RS6K)
+  hwm = gethwm_(); 
+  maxrss = getrss_();
+  rssnow = getcurheap_();
+  stack = getstk_();
+  paging = getpag_();
+#elif defined(LINUX)
+  hwm = gethwm_(); 
+  maxrss = getrss_();
+  rssnow = getrss_();
+  stack = 0;
+  paging = 0;
+#else
+  hwm = 8.0 * util_ihpstat_(&option);
+  maxrss = hwm;
+  rssnow = maxrss;
+  stack = 0;
+  paging = 0;
+#endif
+  wall = util_walltime_();
+  cpu = util_cputime_();
+
+  if (hwm > GIGA || maxrss > GIGA || rssnow > GIGA || stack > GIGA) {
+    sprintf(buf,"%.1fG\t%.1fG\t%.1fG\t%.1fG\t%.0f\t%.2f\t%.2f",
+	    hwm/GIGA, 
+	    maxrss/GIGA, 
+	    rssnow/GIGA, 
+	    stack/GIGA,
+	    paging,
+	    wall,
+	    cpu);
+  }
+  else if (hwm > MEGA || maxrss > MEGA || rssnow > MEGA || stack > MEGA) {
+    sprintf(buf,"%.1fM\t%.1fM\t%.1fM\t%.1fM\t%.0f\t%.2f\t%.2f",
+	    hwm/MEGA, 
+	    maxrss/MEGA, 
+	    rssnow/MEGA, 
+	    stack/MEGA,
+	    paging,
+	    wall,
+	    cpu);
+  }
+  else {
+    sprintf(buf,"%.1fK\t%.1fK\t%.1fK\t%.1fK\t%.0f\t%.2f\t%.2f",
+	    hwm/KILO, 
+	    maxrss/KILO, 
+	    rssnow/KILO, 
+	    stack/KILO,
+	    paging,
+	    wall,
+	    cpu);
+  }
+
+  return buf;
+}
+
+PUBLIC void
+codb_trace_begin_()
+{
+  if (fp_trace) {
+    coml_set_lockid_(&PBAR_mylock);
+    {
+      const char *dtbuf = odb_datetime_(NULL, NULL); /* ptr to a static variable; do NOT free */
+      int myproc, tid, pid;
+      codb_procdata_(&myproc, NULL, &pid, &tid, NULL);
+      fprintf(fp_trace,"%s: ",dtbuf);
+      fprintf(fp_trace, "%s : Tracing started on PE#%d, pid=%d [thread#%d].\n", 
+	      trace_stat(0), myproc, pid, tid);
+    }
+    coml_unset_lockid_(&PBAR_mylock);
+  }
+}
+
+PUBLIC void
+codb_trace_end_()
+{
+  if (fp_trace) {
+    coml_set_lockid_(&PBAR_mylock);
+    {
+      const char *dtbuf = odb_datetime_(NULL, NULL); /* ptr to a static variable; do NOT free */
+      int myproc, tid, pid;
+      codb_procdata_(&myproc, NULL, &pid, &tid, NULL);
+      fprintf(fp_trace,"%s: ",dtbuf);
+      fprintf(fp_trace, "%s : Tracing finished on PE#%d, pid=%d [thread#%d].\n",
+	      trace_stat(1), myproc, pid, tid);
+      fflush(fp_trace);
+      if (fp_trace != stderr && fp_trace != stdout) fclose(fp_trace);
+      fp_trace = NULL;
+    }
+    coml_unset_lockid_(&PBAR_mylock);
+  }
+}
+
+
+PUBLIC void
+codb_trace_(const int  *handle,
+	    const int  *mode,
+	    const char *msg,
+	    const int   args[],
+	    const int  *numargs,
+	    /* Hidden arguments */
+	    int msg_len)
+{
+  if (fp_trace) {
+    coml_set_lockid_(&PBAR_mylock);
+    {
+      const char *dtbuf = odb_datetime_(NULL, NULL); /* ptr to a static variable; do NOT free */
+      int tid = get_thread_id_();
+      int Handle = *handle;
+      int Mode = *mode;
+      int j, Numargs = MIN(*numargs, MAXTRACEARGS);
+      unsigned char ch;
+      DECL_FTN_CHAR(msg);
+      
+      ALLOC_FTN_CHAR(msg);
+      
+      fprintf(fp_trace,"%s: [#%d] ",dtbuf, tid);
+      
+      ch = ':';
+      if (Mode == 1) ch = '>';
+      else if (Mode == 0) ch = '<';
+      
+      if (Handle >= 0) {
+	fprintf(fp_trace,
+		"%s %c %d %s", 
+		trace_stat(0), 
+		ch, Handle, p_msg);
+      }
+      else {
+	fprintf(fp_trace,
+		"%s %c %s", 
+		trace_stat(0), 
+		ch, p_msg);
+      }
+
+      for (j=0; j<Numargs; j++) fprintf(fp_trace," %d",args[j]);
+      
+      fprintf(fp_trace,"\n");
+
+      FREE_FTN_CHAR(msg);
+
+      if (trace_flush_freq > 0) {
+	static uint callno = 0;
+	callno++;
+	if (callno%trace_flush_freq == 0) fflush(fp_trace);
+      }
+    }
+    coml_unset_lockid_(&PBAR_mylock);
+  }
+}
+
+
+PUBLIC void
+codb_trace_init_(int *trace_on)
+{
+  boolean proceed = 0;
+  int myproc;
+  char *proc = getenv("ODB_TRACE_PROC");
+
+  codb_trace_end_();
+  if (trace_on) *trace_on = 0;
+
+  codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+
+  if (proc) {
+    trace_proc = atoi(proc);
+    proceed = (trace_proc == -1 || trace_proc == myproc);
+  }
+
+  if (proceed) {
+    char *p;
+    int rc, unit;
+    char *pfile = getenv("ODB_TRACE_FILE");
+    if (!pfile) pfile = "stdout"; /* std-output, not std-error to get line buffering */
+
+    if (strequ(pfile,"stderr") || strequ(pfile,"stdout")) {
+      fp_trace = strequ(pfile,"stderr") ? stderr : stdout;
+    }
+    else {
+      if (strchr(pfile,'%')) {
+	ALLOC(p,strlen(pfile) + 20);
+	sprintf(p,pfile,myproc);
+      }
+      else {
+	p = STRDUP(pfile);
+      }
+      cma_open_(&unit, p, "w", &rc, strlen(p), 1);
+      if (rc < 1) {
+	perror(p);
+	FREE(p);
+	return;
+      }
+      FREE(p);
+      
+      fp_trace = CMA_get_fp(&unit);
+    }
+    
+    if (fp_trace) {
+      codb_trace_begin_();
+      if (!trace_atexit_done) {
+	atexit(codb_trace_end_);
+	trace_atexit_done = 1;
+      }
+      if (trace_on) *trace_on = 1;
+      
+      {
+	char *x = getenv("ODB_TRACE_FLUSH_FREQ");
+	if (x) trace_flush_freq = atoi(x);
+      }
+    } /* if (fp_trace) */
+  } /* if (proceed) */
+}
+
+
+PUBLIC FILE *
+ODB_trace_fp()
+{
+  return fp_trace;
+}
+
+
+PUBLIC void
+ODB_debug_print_index(FILE *fp, const char *View, int poolno, int n, int ntbl, ...)
+{
+  static int rc = 0;
+  static int first_time = 1;
+
+  if (first_time) {
+    char *p = getenv("ODB_DEBUG_PRINT_INDEX");
+    if (p) rc = atoi(p);
+    first_time = 0;
+  }
+
+  if (!rc) 
+    return;
+  else if (fp && n > 0) {
+    int jtbl;
+    int myproc = 0;
+    int it = 0;
+    va_list ap;
+    va_start(ap, ntbl);
+    
+    codb_procdata_(&myproc, NULL, NULL, &it, NULL);
+    for (jtbl=0; jtbl<ntbl; jtbl++) {
+      const char *Table = va_arg(ap, const char *);
+      const int *Index_Table = va_arg(ap, const int *);
+      const void *Table_addr = va_arg(ap, const void *);
+      int Nrows = va_arg(ap, int);
+      int j, jnext, newline;
+      fprintf(fp,
+	      "\nDEBUG_PRINT :: myproc,it,poolno=<%d;%d;%d> ; View=%s ;"
+	      " Index_%s[0:n=%d) at %p ;"
+	      " Nrows(table %s at %p)=%d\n",
+	      myproc, it, poolno, View, 
+	      Table, n, Index_Table, 
+	      Table, Table_addr, Nrows);
+      fflush(fp);
+      for (j=0; j<n; j++) {
+	if (j%10 == 0) fprintf(fp,"<%d;%d;%d>", myproc, it, poolno);
+	jnext = j + 1;
+	newline = (jnext%10 == 0 || jnext == n) ? 1 : 0;
+	fprintf(fp,"%12d%s", Index_Table[j], newline ? "\n" : "");
+	if (newline) fflush(fp);
+      }
+      fflush(fp);
+    }
+    va_end(ap);
+  } /* if (rc && fp && n > 0) */
+}
+
+static int PBAR_iounit = 0;
+static int PBAR_maxpool = 0;
+static int PBAR_totalrows = 0;
+static double PBAR_totwtime = 0;
+
+PUBLIC void init_PBAR_lock()
+{
+  INIT_LOCKID_WITH_NAME(&PBAR_mylock,"tracing.c:PBAR_mylock");
+  PBAR_totwtime = util_walltime_(); /* Initialize wall clock timer */
+}
+
+
+PUBLIC void
+codb_set_progress_bar_(const char *param,
+		       const int *value
+		       /* Hidden arguments */
+		       , int param_len)
+{
+  /* Preset semi-permanent values for use by codb_progress_bar_() */
+  if (param && value) {
+    coml_set_lockid_(&PBAR_mylock);
+    if (strncaseequ(param,"iounit",param_len)) {
+      PBAR_iounit = *value;
+    }
+    else if (strncaseequ(param,"maxpool",param_len)) {
+      PBAR_maxpool = *value;
+    }
+    else if (strncaseequ(param,"totalrows",param_len)) {
+      PBAR_totalrows = *value;
+    }
+    coml_unset_lockid_(&PBAR_mylock);
+  }
+}
+
+PUBLIC void
+codb_get_progress_bar_(const char *param,
+		       int *value
+		       /* Hidden arguments */
+		       , int param_len)
+{
+  /* Get current semi-permanent values for use by codb_progress_bar_() */
+  if (param && value) {
+    coml_set_lockid_(&PBAR_mylock);
+    if (strncaseequ(param,"iounit",param_len)) {
+      *value = PBAR_iounit;
+    }
+    else if (strncaseequ(param,"maxpool",param_len)) {
+      *value = PBAR_maxpool;
+    }
+    else if (strncaseequ(param,"totalrows",param_len)) {
+      *value = PBAR_totalrows;
+    }
+    coml_unset_lockid_(&PBAR_mylock);
+  }
+}
+
+PUBLIC void
+codb_progress_nl_(const int *iounit)
+{
+  FILE *fp = stderr;
+  int Iounit = iounit ? *iounit : PBAR_iounit;
+  if (Iounit == 6) fp = stdout;
+  if (fp) {
+    fprintf(fp, "\n");
+    fflush(fp);
+  }
+}
+
+PUBLIC void
+codb_progress_bar_(const int *iounit,
+		   const char *dtname,
+		   const int *curpool,
+		   const int *maxpool,
+		   const int *currows,
+		   const int *totalrows,
+		   const double *wtime,
+		   const int *newline
+		   /* Hidden arguments */
+		   , int dtname_len)
+{
+  coml_set_lockid_(&PBAR_mylock);
+  {
+    int tid = get_thread_id_();
+    extern long long int gethwm_();
+    double hwm = gethwm_();
+    FILE *fp = stderr;
+    int Iounit = iounit ? *iounit : PBAR_iounit;
+    int Maxpool = maxpool ? *maxpool : PBAR_maxpool;
+    int Totalrows = totalrows ? *totalrows : PBAR_totalrows + (*currows);
+    static double maxhwm = 0;
+    double totwtime;
+    double pc = (*curpool > 0 && Maxpool > 0) ? (double)(*curpool)/(Maxpool) : 0;
+    int j, ipc;
+    static const int maxipc = 20;
+    static const char propel[4] = { '-', '\\', '|', '/' };
+    static int npropel = 0;
+    static int maxchar = 0;
+    int nchar = 0;
+    if (Iounit == 6) fp = stdout;
+    if (hwm > maxhwm) maxhwm = hwm;
+    /* if (tid != 1) fp = NULL; */
+    pc *= 100;
+    pc = MAX(0,pc);
+    pc = MIN(pc, 100);
+    ipc = maxipc * (pc/100);
+    if (newline && *newline) { ipc = maxipc; pc = 100; }
+    ipc = MIN(ipc,maxipc);
+    pc = MIN(pc,100);
+    if (fp) {
+      nchar += fprintf(fp,"%*.*s #%d: %d/%d rows, %d/%d pools : %c",
+		       dtname_len, dtname_len, dtname,
+		       tid,
+		       *currows, Totalrows, *curpool, Maxpool, 
+		       ((ipc == maxipc) || (newline && *newline)) ? '+'  : propel[npropel]);
+      if (++npropel >= 4) npropel = 0;
+      for (j=0; j<ipc; j++) nchar += fprintf(fp,"#");
+      for (j=ipc; j<maxipc; j++) nchar += fprintf(fp,".");
+    }
+    totwtime = util_walltime_() - PBAR_totwtime;
+    if (fp) {
+      double Tremains = (pc > 0) ? ((100 - pc) * totwtime / pc) : 0;
+      nchar += fprintf(fp,": %5.1f%% (%.3f/%.3f/%.3fs,%.0f/%.0fMB)",
+		       pc,*wtime,totwtime,Tremains,hwm/MEGA,maxhwm/MEGA);
+      if (maxchar > nchar) {
+	int nblanks = maxchar - nchar;
+	for (j=0; j<nblanks; j++) fprintf(fp," ");
+      }
+      else {
+	maxchar = nchar;
+      }
+      fprintf(fp,"%c",(newline && *newline) ? '\n' : '\r');
+      fflush(fp);
+    }
+    if (!totalrows) PBAR_totalrows = Totalrows;
+  }
+  coml_unset_lockid_(&PBAR_mylock);
+}
+
+
+#ifdef SGI
+  /* A few hacks for SGI, since getrusage() does not work ... sigh !! */
+
+PRIVATE int
+gethwm_()
+{
+  extern void *sbrk(int);
+  extern int _etext[];
+  int *p = sbrk(0);
+  int rc = (p - _etext)*sizeof(int);
+  return rc;
+}
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+
+PRIVATE void
+pr_infos(double *size, double *rssize)
+{
+  static int pid = -1;
+  static int fildes = -1;
+  static int pagesize = 1;
+  static prpsinfo_t psinfo;
+
+  if (size)   *size = 0;
+  if (rssize) *rssize = 0;
+
+  if (pid == -1) {
+    char procfile[40];
+    pid = getpid();
+    sprintf(procfile,"/proc/%10.10d",pid);
+    fildes = open(procfile, O_RDONLY);
+    pagesize = getpagesize();
+  }
+
+  if (fildes == -1) return;
+
+  if (ioctl(fildes, PIOCPSINFO, &psinfo) == -1) return;
+  
+  if (size  ) *size   = psinfo.pr_size * pagesize;
+  if (rssize) *rssize = psinfo.pr_rssize * pagesize;
+}
+
+#endif
diff --git a/odb/src/lib/twindow.c b/odb/src/lib/twindow.c
new file mode 100644
index 0000000..01e4f7f
--- /dev/null
+++ b/odb/src/lib/twindow.c
@@ -0,0 +1,433 @@
+
+/* twindow.c */
+
+
+#ifdef STANDALONE_TEST
+#include <stdio.h>
+#include <stdlib.h>
+#define boolean int
+#define PUBLIC
+#define PRIVATE static
+#define ABS(x) ( (x) >= 0 ? (x) : -(x) )
+extern int get_thread_id_();
+extern int get_max_threads_();
+#else
+#include "odb.h"
+#endif
+
+PRIVATE int allow_sec_error = 0; /* When non-zero, allows seconds to be > 59 ==> fixed to 59 */
+PRIVATE int allow_min_error = 0; /* When non-zero, allows minutes to be > 59 ==> fixed to 59 */
+PRIVATE int allow_hour_error= 0; /* When non-zero, allows hours to be > 23 ==> fixed to 23 */
+
+/* secdiff() from Y2K-compliant ECLIB */
+
+#if defined(_ABI64) || defined(__uxpch__) || defined(VPP5000) || defined(__64BIT__) || defined(NECSX)
+        typedef int _int32_t;
+#else
+        typedef long int _int32_t;
+#endif
+
+
+extern void
+secdiff(const _int32_t *const year1,
+	const _int32_t *const month1,
+	const _int32_t *const day1,
+	const _int32_t *const hour1,
+	const _int32_t *const min1,
+	const _int32_t *const sec1,
+	const _int32_t *const year2,
+	const _int32_t *const month2,
+	const _int32_t *const day2,
+	const _int32_t *const hour2,
+	const _int32_t *const min2,
+	const _int32_t *const sec2,
+	_int32_t *const seconds,
+	_int32_t *const ret);
+
+
+PRIVATE _int32_t *RC_tdiff = NULL; /* Used to be thread unsafe */
+
+PUBLIC void
+codb_init_twindow_()
+{
+  if (!RC_tdiff) {
+    int max_omp_threads = get_max_threads_();
+    RC_tdiff = (_int32_t *)calloc(max_omp_threads , sizeof(*RC_tdiff));
+  }
+}
+
+
+PUBLIC void
+codb_allow_time_error_(int *p_allow_errors) /* when set to HHMMSS , then allow errors
+					       in seconds, if SS > 0
+					       in minutes, if MM > 0
+					       in hours, if HH > 0
+					       So :
+					       if set to 1 --> tolerate errors only in seconds
+					       if set to 100 --> tolerate errors only in minutes
+					       if set to 10000 --> tolerate errors only in hours
+					       or if set to 10101 --> tolerate errors in HH,MM & SS
+					     */
+{
+  if (p_allow_errors) {
+    int x = ABS(*p_allow_errors);
+    int hh = x/10000;
+    int mm = (x%10000)/100;
+    int ss = x%100;
+    allow_sec_error = (ss > 0);
+    allow_min_error = (mm > 0);
+    allow_hour_error = (hh > 0);
+  }
+}
+
+PUBLIC double
+ODB_tdiff(double dtarget_date,  /* Date to be checked */   
+	  double dtarget_time,  /* Time to be checked */
+	  double danal_date,    /* Analysis date in format YYYYMMDD */
+	  double danal_time     /* Analysis time in format   HHMMSS */
+	  )
+     /* Calculates difference in seconds */
+{
+  _int32_t diff = 0;
+
+  int target_date = dtarget_date;
+  int target_time = dtarget_time;
+  int anal_date   = danal_date;
+  int anal_time   = danal_time;
+
+  _int32_t yyyy_target = target_date/10000;
+  _int32_t month_target = (target_date%10000)/100;
+  _int32_t day_target = target_date%100;
+  _int32_t hour_target = target_time/10000;
+  _int32_t min_target = (target_time%10000)/100;
+  _int32_t sec_target = target_time%100;
+  
+  _int32_t yyyy_anal = anal_date/10000;
+  _int32_t month_anal = (anal_date%10000)/100;
+  _int32_t day_anal = anal_date%100;
+  _int32_t hour_anal = anal_time/10000;
+  _int32_t min_anal = (anal_time%10000)/100;
+  _int32_t sec_anal = anal_time%100;
+
+  if (allow_hour_error) {
+    if (hour_target > 23) hour_target = 23; 
+    if (hour_anal > 23) hour_anal = 23;
+  }
+
+  if (allow_min_error) {
+    if (min_target > 59) min_target = 59; 
+    if (min_anal > 59) min_anal = 59;
+  }
+
+  if (allow_sec_error) {
+    if (sec_target > 59) sec_target = 59;
+    if (sec_anal > 59) sec_anal = 59;
+  }
+
+  {
+    int it = get_thread_id_();
+    if (!RC_tdiff) codb_init_twindow_();
+    secdiff(&yyyy_target, &month_target, &day_target, &hour_target, &min_target, &sec_target,
+	    &yyyy_anal, &month_anal, &day_anal, &hour_anal, &min_anal, &sec_anal,
+	    &diff,
+	    &RC_tdiff[--it]);
+  }
+
+  return (double)diff;
+}
+
+
+PUBLIC double
+ODB_twindow(double dtarget_date,  /* Date to be checked */   
+	    double dtarget_time,  /* Time to be checked */
+	    double danal_date,    /* Analysis date in format YYYYMMDD */
+	    double danal_time,    /* Analysis time in format   HHMMSS */
+	    double dleft_margin,  /* Left bdry; offset from analysis tstamp in +/-HHMMSS, HH can be > 23 */
+	    double dright_margin  /* Right bdry;  offset from analysis tstamp in +/-HHMMSS, HH can be > 23 */
+	    )
+{
+  /* twindow: Resolution in seconds */
+
+  int target_date = dtarget_date;
+  int target_time = dtarget_time;
+  int anal_date   = danal_date;
+  int anal_time   = danal_time;
+  int left_margin = dleft_margin;
+  int right_margin = dright_margin;
+
+  boolean inside = 0;
+  int rc = 0;
+  int leftsec = 0, rightsec = 0;
+  int diff = 0;
+  int sign, hour, min, sec;
+  
+  sign = (left_margin < 0) ? -1 : 1;
+  left_margin = ABS(left_margin);
+  hour = left_margin/10000;
+  min = (left_margin%10000)/100;
+  sec = left_margin%100;
+  left_margin *= sign;
+
+#if 0
+  if (hour > 23) {
+    if (allow_hour_error) hour = 23;
+    else rc++;
+  }
+#endif
+
+  if (min > 59) {
+    if (allow_min_error) min = 59;
+    else rc++;
+  }
+
+  if (sec > 59) {
+    if (allow_sec_error) sec = 59;
+    else rc++;
+  }
+
+  if (rc == 0) {
+    leftsec = hour * 3600 + min * 60 + sec;
+    leftsec *= sign;
+  }
+
+  sign = (right_margin < 0) ? -1 : 1;
+  right_margin = ABS(right_margin);
+  hour = right_margin/10000;
+  min = (right_margin%10000)/100;
+  sec = right_margin%100;
+  right_margin *= sign;
+
+#if 0
+  if (hour > 23) {
+    if (allow_hour_error) hour = 23;
+    else rc++;
+  }
+#endif
+
+  if (min > 59) {
+    if (allow_min_error) min = 59;
+    else rc++;
+  }
+
+  if (sec > 59) {
+    if (allow_sec_error) sec = 59;
+    else rc++;
+  }
+
+  if (rc == 0) {
+    rightsec = hour * 3600 + min * 60 + sec;
+    rightsec *= sign;
+  }
+
+  if (rc == 0) {
+    int it = get_thread_id_();
+    diff = ODB_tdiff(target_date, target_time, anal_date, anal_time);
+    rc = RC_tdiff[--it];
+  }
+  else {
+    fprintf(stderr,"ODB_twindow: Invalid left and/or right margins\n");
+    fprintf(stderr,"             Use +/-HHMMSS format (HH >= 0, MM <= 59, SS <= 59)\n");
+    fprintf(stderr,"              Left margin = %d\n", left_margin);
+    fprintf(stderr,"             Right margin = %d\n", right_margin);
+  }
+
+  if (rc != 0) {
+#ifdef STANDALONE_TEST
+    fprintf(stderr,"*** Error ***\n");
+    exit(1);
+#else
+    /* char p[] = "ODB_twindow"; */
+    fprintf(stderr,"ODB_twindow: Invalid date, time and/or margin(s)\n");
+    fprintf(stderr,"               Target (date,time) = (%8.8d, %6.6d)\n",
+	    target_date, target_time);
+    fprintf(stderr,"             Analysis (date,time) = (%8.8d, %6.6d)\n",
+	    anal_date, anal_time);
+    fprintf(stderr,"             Margins (left,right) = (%d, %d)\n",
+	    left_margin, right_margin);
+    /* codb_abort_func_(p, strlen(p)); */
+    inside = 0;
+#endif
+  }
+  else {
+    inside = (( rc == 0 ) && ( diff >= leftsec && diff <= rightsec ));
+  }
+
+#ifdef STANDALONE_TEST
+  printf("target: %8.8d %6.6d\n", target_date, target_time);
+  printf("  anal: %8.8d %6.6d\n",   anal_date,   anal_time);
+  printf("  diff: %d seconds with rc = %d\n", diff, rc);
+  printf("  left: %6d (%d sec)\n",  left_margin, leftsec);
+  printf(" right: %6d (%d sec)\n", right_margin, rightsec);
+  printf("inside: %d\n",inside);
+#endif
+
+  return (double)inside;
+}
+
+/* Fortran callable */
+
+PUBLIC void
+codb_twindow_(const int *target_date,
+	      const int *target_time,
+	      const int *anal_date,
+	      const int *anal_time,
+	      const int *left_margin,
+	      const int *right_margin,
+	      int *retcode)
+{
+  *retcode = ODB_twindow(*target_date,
+			 *target_time,
+			 *anal_date,
+			 *anal_time,
+			 *left_margin,
+			 *right_margin);
+}
+
+
+PUBLIC void
+codb_tdiff_(const int *target_date,
+	    const int *target_time,
+	    const int *anal_date,
+	    const int *anal_time,
+	    int *diff)
+{
+  *diff = ODB_tdiff(*target_date,
+		    *target_time,
+		    *anal_date,
+		    *anal_time);
+}
+
+
+PUBLIC double
+ODB_jd(double Date, double Time)
+{
+  /* Borrowed from http://www.macho.mcmaster.ca/JAVA/JD.html ; view source */
+  int Iyyyymmdd = Date;
+  int Ihhmmss = Time;
+  double y = Iyyyymmdd/10000;
+  double m = (Iyyyymmdd % 10000)/100;
+  double d = Iyyyymmdd % 100;
+  double uh = Ihhmmss/10000;
+  double um = (Ihhmmss % 10000)/100;
+  double us = Ihhmmss % 100;
+  double extra = 100.0*y + m - 190002.5;
+  double rjd = 367.0*y;
+  rjd -= floor(7.0*(y+floor((m+9.0)/12.0))/4.0);
+  rjd += floor(275.0*m/9.0);
+  rjd += d;
+  rjd += (uh + (um + us/60.0)/60.)/24.0;
+  rjd += 1721013.5;
+  rjd -= 0.5*extra/abs(extra);
+  rjd += 0.5;
+  return rjd;
+}
+
+PUBLIC void
+codb_jd_(const double *Date, const double *Time, double *Result)
+{
+  if (Date && Time && Result) *Result = ODB_jd(*Date, *Time);
+}
+
+PUBLIC double
+ODB_datenum(double Date) /* Assumed format YYYYMMDD */
+{ /* This is NOT EXACTLY correct interpreration of MATLAB datenum() function */
+  int dtnum = 0;
+  if (Date >= 0 && Date <= INT_MAX) {
+    int yyyymmdd = (int)Date;
+    int yyyy = yyyymmdd/10000;
+    int mm = (yyyymmdd/100)%100;
+    int dd = yyyymmdd%100;
+    int is_leap_year = ((yyyy%400 == 0) || ((yyyy%4 == 0) && (yyyy%100 != 0)));
+    static const int days_in_month[12] = {
+      31, 28, 31, 
+      30, 31, 30,
+      31, 31, 30, 
+      31, 30, 31 
+    };
+    static const int days_since_beginning_of_the_year[13] = {
+      0, 
+      31, 59, 90, 120, 151, 181,
+      212, 243, 273, 304, 334, 365
+    };
+    if (mm >= 1 && mm <= 12 && dd >= 1 && 
+	((mm != 2 && dd <= days_in_month[mm-1]) ||
+	 (mm == 2 && dd <= days_in_month[mm-1] + is_leap_year))) {
+      int j;
+      dtnum = dd;
+      if (mm > 2 && is_leap_year) dtnum++;
+      dtnum += days_since_beginning_of_the_year[--mm];
+    }
+  }
+  return (double)dtnum;
+}
+
+
+PUBLIC void /* Fortran callable */
+codb_datenum_(const double *Date, double *Result)
+{
+  if (Date && Result) *Result = ODB_datenum(*Date);
+}
+
+
+PUBLIC double
+ODB_hours_utc(double Time) /* Assumed format HHMMSS */
+{
+  double utc = 0;
+  if (Time >= 0 && Time <= INT_MAX) {
+    int rc = 0;
+    int hhmmss = (int)Time;
+    int hh = hhmmss/10000;
+    int mm = (hhmmss/100)%100;
+    int ss = hhmmss%100;
+#if 0
+    if (hh > 23) {
+      if (allow_hour_error) hh = 23;
+      else rc++;
+    }
+#endif
+    if (ss > 59) {
+      if (allow_min_error) ss = 59;
+      else rc++;
+    }
+    if (mm > 59) {
+      if (allow_min_error) mm = 59;
+      else rc++;
+    }
+    if (rc == 0) {
+      double totsec = mm * 60 + ss;
+      double frac = totsec / 3600;
+      utc = hh + frac;
+    }
+  }
+  return utc;
+}
+
+PUBLIC void /* Fortran callable */
+codb_hours_utc_(const double *Time, double *Result)
+{
+  if (Time && Result) *Result = ODB_hours_utc(*Time);
+}
+#ifdef STANDALONE_TEST
+main(int argc, char *argv[])
+{
+  if (--argc != 6) {
+    fprintf(stderr,"Usage: %s tgdate tgtime andate antime leftmargin rightmargin\n",argv[0]);
+    exit(1);
+  }
+  else {
+    int target_date  = atoi(argv[1]);  /* Date to be checked */   
+    int target_time  = atoi(argv[2]);  /* Time to be checked */
+    int anal_date    = atoi(argv[3]);  /* Analysis date in format YYYYMMDD */
+    int anal_time    = atoi(argv[4]);  /* Analysis time in format   HHMMSS */
+    int left_margin  = atoi(argv[5]);  /* Left bdry in format HHMMSS*/
+    int right_margin = atoi(argv[6]);  /* Right bdry in format HHMMSS*/
+
+    ODB_twindow(target_date,
+		target_time,
+		anal_date,
+		anal_time,
+		left_margin,
+		right_margin);
+  }
+}
+#endif
diff --git a/odb/src/lib/uniquenumdb.F90 b/odb/src/lib/uniquenumdb.F90
new file mode 100644
index 0000000..60255ea
--- /dev/null
+++ b/odb/src/lib/uniquenumdb.F90
@@ -0,0 +1,49 @@
+#ifdef RS6K
+ at PROCESS NOEXTCHK
+#endif
+SUBROUTINE uniquenumdb(p, kldim, kvals, klen, keff)
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: klen, kldim, kvals
+REAL(KIND=JPRB),    intent(in)  :: p(kldim, klen)
+INTEGER(KIND=JPIM), intent(out) :: keff
+INTEGER(KIND=JPIM), parameter :: UI_RATIO = 2 ! sizeof(real(8)) / sizeof(integer(4))
+INTEGER(KIND=JPIM) :: hash(klen)
+INTEGER(KIND=JPIM) :: i, itag, is_unique, ihash
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('UNIQUENUMDB',0,ZHOOK_HANDLE)
+keff = 0
+if (klen <= 1) then
+  keff = klen
+  IF (LHOOK) CALL DR_HOOK('UNIQUENUMDB',1,ZHOOK_HANDLE)
+  return
+endif
+
+CALL cODB_hash_set_lock()
+CALL cODB_hash_init()
+
+CALL cODB_vechash(&
+ & kvals * UI_RATIO, &
+ & kldim * UI_RATIO,&
+ & klen, &
+ & p(1,1), hash(1)) 
+
+keff = 0
+do i=1,klen
+  itag = i
+  CALL cODB_d_unique( &
+   & kvals, p(1,i), hash(i), &
+   & is_unique, itag, ihash) 
+  if (is_unique == 1) keff = keff + 1
+enddo
+
+CALL cODB_hash_init()
+CALL cODB_hash_unset_lock()
+
+IF (LHOOK) CALL DR_HOOK('UNIQUENUMDB',1,ZHOOK_HANDLE)
+
+END SUBROUTINE uniquenumdb
diff --git a/odb/src/lib/var.c b/odb/src/lib/var.c
new file mode 100644
index 0000000..21d9424
--- /dev/null
+++ b/odb/src/lib/var.c
@@ -0,0 +1,462 @@
+
+/* var.c */
+
+#include "odb.h"
+#include "cdrhook.h"
+
+/* Routines to maintain SET-variables via hashing */
+
+/*--- Defines functions: (per database, and (possibly) per view)
+
+  * Add/register variable
+  * Change the value of variable
+  * Get the current address of variable
+  * Get the current value of variable
+  * Delete variables
+  * Print variables (debug)
+  * Transfer list of variables back to calling program
+
+  ---*/
+
+#ifndef VAR_HASHSIZE
+#define VAR_HASHSIZE 1031U
+#endif
+
+PRIVATE o_lock_t VAR_mylock = 0; /* A specific OMP-lock; initialized only once in
+				    odb/lib/codb.c, routine codb_init_omp_locks_() */
+
+PRIVATE uint VAR_hashsize = 0;
+
+typedef struct _VAR_Hash_Table {
+  char *dbname;
+  char *symbol;
+  char *viewname;
+  double value;
+  struct _VAR_Hash_Table *collision;
+} VAR_Hash_Table;
+
+PRIVATE VAR_Hash_Table **VAR_hashtable = NULL;
+
+PRIVATE uint
+Hash(const char *dbname, 
+     const char *symbol, 
+     const char *viewname)
+{ 
+  uint hashval = 0;
+  for (; *dbname ; dbname++) {
+    hashval = (*dbname) + 31U * hashval;
+  }
+  for (; *symbol ; symbol++) {
+    hashval = (*symbol) + 31U * hashval;
+  }
+  if (viewname) {
+    for (; *viewname ; viewname++) {
+      hashval = (*viewname) + 31U * hashval;
+    }
+  }
+  hashval = hashval % VAR_hashsize;
+  return hashval;
+}
+
+
+PRIVATE void
+HashInit()
+{
+  if (!VAR_hashtable) {
+    coml_set_lockid_(&VAR_mylock);
+    if (!VAR_hashtable) {
+      VAR_Hash_Table **tmp_VAR_hashtable = NULL;
+      int inumt = get_max_threads_();
+      int it;
+      char *p = getenv("ODB_VAR_HASHSIZE");
+      if (p) {
+	VAR_hashsize = atoi(p);
+	if (VAR_hashsize <= 0) VAR_hashsize = VAR_HASHSIZE;
+      }
+      else
+	VAR_hashsize = VAR_HASHSIZE;
+      ALLOC(tmp_VAR_hashtable, inumt + 1); /* entries 0 for TABLEs, 1..inumt for VIEWs */
+      for (it = 0; it <= inumt ; it++) {
+	CALLOC(tmp_VAR_hashtable[it], VAR_hashsize);
+      }
+      VAR_hashtable = tmp_VAR_hashtable;
+    }
+    coml_unset_lockid_(&VAR_mylock);
+  }
+}
+
+PRIVATE VAR_Hash_Table *
+NewEntry(void)
+{
+  VAR_Hash_Table *p;
+  ALLOC(p, 1);
+  p->dbname = NULL;
+  p->symbol = NULL;
+  p->viewname = NULL;
+  p->value = 0;
+  p->collision = NULL;
+  return p;
+}
+
+PUBLIC void
+init_VAR_lock()
+{
+  INIT_LOCKID_WITH_NAME(&VAR_mylock,"var.c:VAR_mylock");
+  HashInit();
+}
+
+/*--- Add/register variable ---*/
+
+PUBLIC void
+ODB_add_var(const char *dbname, 
+            const char *symbol, 
+            const char *viewname,
+	    int it,
+            double value)
+{
+  int found = 0;
+  uint index;
+  VAR_Hash_Table *p;
+  DRHOOK_START(ODB_add_var);
+
+  if (!dbname || !symbol) goto finish;
+
+  if (!viewname) it = 0; /* make sure TABLEs are "non-threaded" */
+
+  index = Hash(dbname,symbol,viewname);
+  p = &VAR_hashtable[it][index];
+
+  found = 0;
+  while (p && p->symbol) {
+    if (strequ(p->symbol, symbol) && strequ(p->dbname, dbname) &&
+	(!viewname || strequ(p->viewname, viewname))) {
+      p->value = value;
+      ++found;
+      break;
+    }
+
+    if (p->collision) 
+      p = p->collision;
+    else {
+      p->collision = NewEntry();
+      p = p->collision;
+      break;
+    }
+  } /* while (p && p->symbol) */
+
+  if (!found && p) {
+    FILE *do_trace = ODB_trace_fp();
+    p->dbname = STRDUP(dbname);
+    p->symbol = STRDUP(symbol);
+    p->viewname = viewname ? STRDUP(viewname) : NULL;
+    p->value = value;
+    if (do_trace) {
+      ODB_Trace TracE;
+      TracE.handle = -1;
+      TracE.msglen = 512;
+      TracE.msg = NULL;
+      ALLOC(TracE.msg, TracE.msglen);
+      TracE.numargs = 0; 
+      TracE.mode = -1;
+      if (p->viewname) {
+	snprintf(TracE.msg, TracE.msglen,
+		"Added '%s', value=%.14g, db=%s, [%s], it=%d : hash#%d",
+		p->symbol, p->value,
+		p->dbname, p->viewname, it, index);
+      }
+      else {
+	snprintf(TracE.msg, TracE.msglen,
+		"Added '%s', value=%.14g, db=%s, it=%d : hash#%d",
+		p->symbol, p->value,
+		p->dbname, it, index);
+      }
+
+      codb_trace_(&TracE.handle, &TracE.mode,
+		  TracE.msg, TracE.args, 
+		  &TracE.numargs, TracE.msglen);
+      FREE(TracE.msg);
+    } /* if (do_trace) */
+  }
+
+ finish:
+  DRHOOK_END(0);
+}
+
+/*--- Change the value of variable ---*/
+
+PUBLIC double *
+ODB_alter_var(const char   *dbname, 
+	      const char   *symbol,
+	      const char   *viewname,
+	      int it,
+	      const double *newvalue,
+	      double       *oldvalue,
+	      int           recur)
+{
+  double *addr = NULL;
+  uint index;
+  VAR_Hash_Table *p;
+  FILE *do_trace = ODB_trace_fp();
+  ODB_Trace TracE;
+  DRHOOK_START(ODB_alter_var);
+
+  if (do_trace) {
+    TracE.handle = -1;
+    TracE.msglen = 512;
+    TracE.msg = NULL;
+    ALLOC(TracE.msg, TracE.msglen);
+    TracE.numargs = 0; 
+    TracE.mode = -1;
+  }
+
+  if (!dbname || !symbol) goto finish;
+
+  if (!viewname) it = 0; /* make sure TABLEs are "non-threaded" */
+
+  index = Hash(dbname,symbol,viewname);
+  p = &VAR_hashtable[it][index];
+
+  while (p && p->symbol) {
+    if (strequ(p->symbol, symbol) && strequ(p->dbname, dbname) &&
+	(!viewname || strequ(p->viewname, viewname))) {
+      if (oldvalue) *oldvalue = p->value;
+      if (newvalue) {
+	if (do_trace) {
+	  if (p->viewname) {
+	    snprintf(TracE.msg, TracE.msglen,
+		    "'%s', db=%s, (old,new)=(%.14g,%.14g) [%s] it=%d : hash#%d",
+		    p->symbol, p->dbname, 
+		    p->value, *newvalue,
+		    p->viewname, it, index);
+	  }
+	  else {
+	    snprintf(TracE.msg, TracE.msglen,
+		    "'%s', db=%s, (old,new)=(%.14g,%.14g) it=%d : hash#%d",
+		    p->symbol, p->dbname, 
+		    p->value, *newvalue,
+		    it, index);
+	  }
+	  codb_trace_(&TracE.handle, &TracE.mode,
+		      TracE.msg, TracE.args, 
+		      &TracE.numargs, TracE.msglen);
+	} /* if (do_trace) */
+	p->value = *newvalue;
+      }
+      if (!addr) {
+	if (!viewname) {
+	  addr = &p->value;
+	}
+	else if (strequ(p->viewname, viewname)) {
+	  addr = &p->value;
+	}
+	/* One appropriately found address is enough
+	   No coherence across views (with the same variable name) is needed */
+	if (addr) break;
+      }
+    } /* if (strequ(p->symbol, symbol) ... */
+    p = p->collision;
+  } /* while (p && p->symbol) */
+
+  if (!addr && *symbol == '$' && recur == 0) {
+    /* still no address ? perhaps a completely new variable ! */
+    /* note: new symbol will be added only for symbols starting with '$' */
+    coml_set_lockid_(&VAR_mylock);
+    if (viewname) {
+	   ODB_add_var(dbname, symbol, viewname, it, *newvalue);
+    }
+    else {
+      ODB_add_var(dbname, symbol, NULL, 0, *newvalue);
+    }
+    addr = ODB_alter_var(dbname, symbol, viewname, it, newvalue, oldvalue, ++recur);
+    coml_unset_lockid_(&VAR_mylock);
+  } /* if (!addr && *symbol == '$' && recur == 0) */
+
+ finish:
+  if (do_trace) FREE(TracE.msg);
+
+  DRHOOK_END(0);
+  return addr;
+}
+
+/*--- Get the current address of a variable ---*/
+
+PUBLIC double *
+ODB_getaddr_var(const char   *dbname, 
+		const char   *symbol,
+		const char   *viewname,
+		int it)
+{
+  double *addr = NULL;
+  uint index;
+  VAR_Hash_Table *p;
+  DRHOOK_START(ODB_getaddr_var);
+
+  if (!dbname || !symbol) goto finish;
+
+  if (!viewname) it = 0; /* make sure TABLEs are "non-threaded" */
+
+  index = Hash(dbname,symbol,viewname);
+  p = &VAR_hashtable[it][index];
+
+  while (p && p->symbol) {
+    if (strequ(p->symbol, symbol) && strequ(p->dbname, dbname) &&
+	(!viewname || strequ(p->viewname, viewname))) {
+      if (!addr) {
+	if (!viewname) {
+	  addr = &p->value;
+	}
+	else if (strequ(p->viewname, viewname)) {
+	  addr = &p->value;
+	}
+      }
+      /* One appropriately found address is enough. 
+         No coherence is needed across the views (over the same symbol name) */
+      if (addr) break;
+    }
+    p = p->collision;
+  } /* while (p && p->symbol) */
+
+ finish:
+  DRHOOK_END(0);
+  return addr;
+}
+
+/*--- Get the current value of variable ---*/
+
+PUBLIC double
+ODB_getval_var(const char   *dbname, 
+	       const char   *symbol,
+	       const char   *viewname,
+	       int it)
+{
+  double value = 0; /* Note: the default value is zero */
+  double *addr = ODB_getaddr_var(dbname, symbol, viewname, it);
+  if (addr) value = *addr;
+  return value;
+}
+
+
+/*--- Delete variables ---*/
+
+PUBLIC void
+ODB_del_vars(const char *dbname,
+	     const char *viewname,
+	     int it)
+{
+  if (!dbname) return;
+
+  if (VAR_hashtable) {
+    int j;
+    if (!viewname) it = 0; /* make sure TABLEs are "non-threaded" */
+    for (j=0; j<VAR_hashsize; j++) {
+      VAR_Hash_Table *p = &VAR_hashtable[it][j];
+      while (p && p->symbol) {
+	if (strequ(p->dbname, dbname) &&
+	    (!viewname || strequ(p->viewname, viewname))) {
+	  p->value = 0;
+	}
+	p = p->collision;
+      } /* while (p && p->symbol) */
+    } /* for (j=0; j<VAR_hashsize; j++) */
+  } /* if (VAR_hashtable) */
+}
+
+/*--- Print variables (debug) ---*/
+
+/* Can be called from Fortran, too */
+
+PUBLIC void
+codb_print_vars_(const int *enforce,
+		 const char *msg,
+		 /* Hidden arguments */
+		 int msg_len)
+{
+  DECL_FTN_CHAR(msg);
+  int print_it = *enforce;
+  int j;
+  int entries=0;
+  int hits=0;
+  char *env = getenv("ODB_VAR_DEBUG");
+  
+  if (env) {
+    int ienv = atoi(env);
+    ienv = MAX(0,MIN(1,ienv));
+    print_it |= ienv;
+  }
+
+  if (!print_it) return;
+
+  ALLOC_FTN_CHAR(msg);
+
+  if (msg_len > 0) fprintf(stderr,"codb_print_vars_: %s\n",p_msg);
+  fprintf(stderr,
+	  "codb_print_vars_: hashsize=%u, hashtable at %p\n",
+	  VAR_hashsize, VAR_hashtable);
+
+  if (VAR_hashtable) {
+    int inumt = get_max_threads_();
+    int it;
+    for (it = 0; it <= inumt ; it++) {
+      for (j=0; j<VAR_hashsize; j++) {
+	VAR_Hash_Table *p = &VAR_hashtable[it][j];
+	int k=1;
+	if (p->symbol) entries++;
+	while (p && p->symbol) {
+	  fprintf(stderr,
+		  "hash#%d [hit#%d] : db='%s', symbol='%s', view='%s', it=%d : value=%.14g (at %p)\n",
+		  j,k,
+		  p->dbname ? p->dbname : NIL, 
+		  p->symbol ? p->symbol : NIL, 
+		  p->viewname ? p->viewname : NIL,
+		  it,
+		  p->value,
+		  &p->value);
+	  p = p->collision;
+	  k++;
+	  hits++;
+	} /* while (p) */
+      } /* for (j=0; j<VAR_hashsize; j++) */
+    } /* for (it = 0; it <= inumt ; it++) */
+  } /* if (VAR_hashtable) */
+
+  fprintf(stderr,"codb_print_vars_: Total %d hits in %d hash-entries\n",hits,entries);
+
+  FREE_FTN_CHAR(msg);
+}
+
+/*--- Transfer variables and their values back to calling program ---*/
+
+PUBLIC int
+ODB_get_vars(const char *dbname,
+	     const char *viewname,
+	     int it,
+	     int nsetvar,
+	     ODB_Setvar setvar[])
+{
+  int count = 0;
+
+  if (VAR_hashtable) {
+    int j;
+    if (!viewname) it = 0; /* make sure TABLEs are "non-threaded" */
+    for (j=0; j<VAR_hashsize; j++) {
+      VAR_Hash_Table *p = &VAR_hashtable[it][j];
+      while (p && p->symbol) {
+	if ((!dbname || strequ(dbname,p->dbname)) &&
+	    (!viewname || strequ(viewname, p->viewname))) {
+	  /*
+	  fprintf(stderr,"ODB_get_vars(dbname='%s', nsetvar=%d): p->symbol='%s', value=%g\n",
+		  dbname, nsetvar, p->symbol, p->value);
+		  */
+	  if (setvar && count < nsetvar) {
+	    setvar[count].symbol = STRDUP(p->symbol);
+	    setvar[count].value = p->value;
+	  }
+	  count++;
+	}
+	p = p->collision;
+      } /* while (p) */
+    } /* for (j=0; j<VAR_hashsize; j++) */
+  } /* if (VAR_hashtable) */
+
+  return count;
+}
diff --git a/odb/src/lib/vecloops.c b/odb/src/lib/vecloops.c
new file mode 100644
index 0000000..fc5cf5f
--- /dev/null
+++ b/odb/src/lib/vecloops.c
@@ -0,0 +1,602 @@
+#ifdef RS6K
+#pragma options noextchk
+#endif
+
+#include "odb.h"
+
+
+PUBLIC void 
+codb_mask_control_word_(double vec[],
+			const int *k1, /* Note : C-indexing */
+			const int *k2, /* Note : C-indexing */
+			const int *doffset,
+			const int poolno[])
+{
+  ll_t *llvec = (ll_t *)vec;
+  int k;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  int kk = 0;
+  
+  for (k=K1; k<K2; k++) {
+    if (poolno[kk] < 0) {
+      llvec[Doffset + k] = 0x7fffffff7fffffffull; /* 0th & 32nd bit set to 0 */
+    }
+    kk++;
+  }
+}
+
+
+PUBLIC void 
+codb_put_control_word_(double vec[],
+		       const int *k1, /* Note : C-indexing */
+		       const int *k2, /* Note : C-indexing */
+		       const int *doffset,
+		       const int *poolno,
+		       const int *noffset)
+{
+  ll_t *llvec = (ll_t *)vec;
+  int k;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  ll_t Poolno = *poolno;
+  ll_t Noffset = *noffset;
+
+  for (k=K1; k<K2; k++) {
+    llvec[Doffset + k] = ((Poolno & 0x000000007fffffffull) << 32) + (k - K1) + Noffset;
+  }
+}
+
+PUBLIC double
+ODB_put_one_control_word(int k, int poolno)
+{
+  double ctrlw = 0;
+  int k1 = k;
+  int k2 = k+1;
+  int doffset = -k;
+  int noffset = k;
+  codb_put_control_word_(&ctrlw, &k1, &k2, &doffset, &poolno, &noffset);
+  return ctrlw;
+}
+
+
+PUBLIC void 
+codb_get_control_word_(const double vec[],
+		       const int *k1, /* Note : C-indexing */
+		       const int *k2, /* Note : C-indexing */
+		       const int *doffset,
+		       ll_t ctrlw[])
+{
+  const ll_t *llvec = (const ll_t *)vec;
+  int k;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  int kk = 0;
+
+  for (k=K1; k<K2; k++) {
+    ctrlw[kk++] = llvec[Doffset + k];
+  }
+}
+
+
+PUBLIC void
+codb_get_pool_count_(const double vec[],
+		     const int *k1, /* Note : C-indexing */
+		     const int *k2, /* Note : C-indexing */
+		     const int *doffset,
+		     const int *npools,
+		     const int poolno[],
+		     int *retcode)
+{
+  const ll_t *llvec = (const ll_t *)vec;
+  int k, jp;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  int Npools = *npools;
+  int count = 0;
+
+  for (jp=0; jp<Npools; jp++) {
+    ll_t ref_poolno = poolno[jp];
+    for (k=K1; k<K2; k++) {
+      ll_t this_poolno = ((llvec[Doffset+k] >> 32) & 0x000000007fffffffull);
+      if (this_poolno == ref_poolno) {
+	/* Count those which belong to this pool */
+	count++;
+      }
+    } /* for (k=K1; k<K2; k++) */
+  } /* for (jp=0; jp<Npools; jp++) */
+
+  *retcode = count;
+}
+
+
+PUBLIC void
+codb_get_poolnos_(const double vec[],
+		  const int *k1, /* Note : C-indexing */
+		  const int *k2, /* Note : C-indexing */
+		  const int *doffset,
+		  int poolno_out[])
+{
+  const ll_t *llvec = (const ll_t *)vec;
+  int k;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  int jp = 0;
+
+  for (k=K1; k<K2; k++) {
+    ll_t this_poolno = ((llvec[Doffset+k] >> 32) & 0x000000007fffffffull);
+    poolno_out[jp++] = this_poolno;
+  }
+}
+
+
+PUBLIC void
+codb_get_rownum_(const double vec[],
+		 const int *k1, /* Note : C-indexing */
+		 const int *k2, /* Note : C-indexing */
+		 const int *doffset,
+		 const int *noffset,
+		 int rownum[])
+{
+  const ll_t *llvec = (const ll_t *)vec;
+  int k;
+  int K1 = *k1;
+  int K2 = *k2;
+  int Doffset = *doffset;
+  ll_t Noffset = *noffset;
+  int jp = 0;
+
+  for (k=K1; k<K2; k++) {
+    ll_t this_rownum = (llvec[Doffset+k] & 0x000000007fffffffull);
+    rownum[jp++] = this_rownum - Noffset;
+  }
+}
+
+PUBLIC void 
+cmask32bits_(uint u[], const int *n, const int *nbits)
+{
+  int N = *n;
+  int Nbits = *nbits; /* if > 0 mask-out last Nbits, else < 0 mask-out -Nbits first bits */
+  int j;
+  if (Nbits > 0 && Nbits <= 32) {
+    for (j=0; j<N; j++) {
+      u[j] >>= Nbits;
+      u[j] <<= Nbits;
+    }
+  }
+  else if (Nbits >= -32 && Nbits < 0) {
+    Nbits = -Nbits;
+    for (j=0; j<N; j++) {
+      u[j] <<= Nbits;
+      u[j] >>= Nbits;
+    }
+  }
+}
+
+PUBLIC void 
+cmask64bits_(u_ll_t u[], const int *n, const int *nbits)
+{
+  int N = *n;
+  int Nbits = *nbits; /* if > 0 mask-out last Nbits, else < 0 mask-out -Nbits first bits */
+  int j;
+  if (Nbits > 0 && Nbits <= 64) {
+    for (j=0; j<N; j++) {
+      u[j] >>= Nbits;
+      u[j] <<= Nbits;
+    }
+  }
+  else if (Nbits >= -64 && Nbits < 0) {
+    Nbits = -Nbits;
+    for (j=0; j<N; j++) {
+      u[j] <<= Nbits;
+      u[j] >>= Nbits;
+    }
+  }
+}
+
+PUBLIC void
+ODB_Update_Hashmaxmin(int n, const uint h[])
+{
+  extern int ODB_hashmin, ODB_hashmax;
+  {
+    uint tmin = ODB_hashmin;
+    uint tmax = ODB_hashmax;
+    int i;
+    for (i=0; i<n; i++) {
+      if (tmin > h[i]) tmin = h[i];
+      if (tmax < h[i]) tmax = h[i];
+    }
+    ODB_hashmin = tmin;
+    ODB_hashmax = tmax;
+  }
+}
+
+PUBLIC void
+codb_vechash_(const int *nval,
+	      const int *nlda,      /* the leading dimension of u ; >= Nval */
+	      const int *nelem, 
+	      const uint u[], /* actual size : Nlda x  Nelem */
+	            uint h[])
+{ 
+  int i, j, k; 
+  int Nval = *nval;
+  int Nlda = *nlda;
+  int Nelem = *nelem;
+  uint Hashsize = ODB_Hashsize();
+
+  if (Nelem <= 0) return;
+
+  for (i=0; i<Nelem; i++) h[i] = 0;
+
+  for (j=0; j<Nval; j++) {
+    k = j;
+    for (i=0; i<Nelem; i++) {
+      h[i] = HASHFUNC(h[i], u[k], Hashsize);
+      k += Nlda;
+    }
+  }
+
+  for (i=0; i<Nelem; i++) h[i] %= Hashsize;
+
+  ODB_Update_Hashmaxmin(Nelem, h);
+}
+
+PUBLIC boolean
+ODB_uint_equal(const uint u1[], const uint u2[], int n)
+{
+  int j;
+#if defined(VPP) || defined(NECSX)
+  /* Vectorized */
+  int cnt=0;
+  for (j=0; j<n; j++) if (u1[j] != u2[j]) cnt++;
+  return (cnt == 0) ? 1 : 0;
+#else
+  for (j=0; j<n; j++) if (u1[j] != u2[j]) return 0;
+  return 1;
+#endif
+}
+
+
+PUBLIC boolean
+ODB_str_equal(const uchar u1[], const uchar u2[], int n)
+{
+  int j;
+  /* Will not vectorize; character (1-byte) data type */
+  for (j=0; j<n; j++) if (u1[j] != u2[j]) return 0;
+  return 1;
+}
+
+/* Generic packing stuff */
+
+#include "pcma_extern.h"
+
+#define DECL_Type2DBL(visibility, func, type, usecast) \
+visibility void func(double to[], const type from[], int n) \
+{ int j; for (j=0; j<n; j++) to[j] = (usecast)from[j]; }
+
+#define DECL_DBL2Type(visibility, func, type, usecast) \
+visibility void func(type to[], const double from[], int n) \
+{ int j; for (j=0; j<n; j++) to[j] = (usecast)from[j]; }
+
+DECL_Type2DBL(PUBLIC, ODB_dbl2dbl, double, double)
+DECL_Type2DBL(PUBLIC, ODB_uint2dbl, uint, double)
+DECL_Type2DBL(PUBLIC, ODB_float2dbl, float, double)
+
+DECL_Type2DBL(PRIVATE, dbl2dbl, double, double)
+
+DECL_Type2DBL(PRIVATE, int2dbl, int, double)
+DECL_DBL2Type(PRIVATE, dbl2int, int, int)
+
+DECL_Type2DBL(PRIVATE, uint2dbl, uint, double)
+DECL_DBL2Type(PRIVATE, dbl2uint, uint, int)
+
+void
+ODB_get_packing_consts(uint *magic, uint *hdrlen, uint *maxshift,
+		       double *nmdi, double*rmdi, int *new_version)
+{
+  if (magic)    *magic  = PCMA;
+  if (hdrlen)   *hdrlen = PCMA_HDRLEN;
+  if (maxshift) *maxshift = MAXSHIFT;
+  pcma_get_mdis_(nmdi, rmdi);
+  if (new_version) *new_version = 1;
+}
+
+
+double *
+ODB_unpack_DBL(const uint pd[],
+               const int  pdlen,
+	       int *dlen,
+	       int *method_used,
+	       uint  datatype)
+{
+  int rc = 0;
+  const uint *hdr  = pd;
+  double *cma = NULL;
+  double *d = NULL;
+  int method = 0;
+  int lenbytes = 0;
+  int lencma = 0;
+  int totalpkwords = 0;
+  const int b4 = sizeof(*hdr);
+  double nmdi, rmdi;
+  int new_version = 0;
+  int swp = 0;
+  uint dtnum = (datatype << 8);
+  int can_swp_data = EXTRACT_SWAPPABLE(dtnum);
+  const int idxlen = 0;
+  const int fill_zeroth_cma = 0;
+
+  *dlen = 0;
+
+  rc = upcma_hdr(NULL, &swp,
+		 (unsigned int *)hdr, 0, 
+		 &method, &lencma, &lenbytes,
+		 &nmdi, &rmdi,
+		 &new_version);
+
+  *method_used = method;
+
+  totalpkwords = rc + RNDUP(lenbytes,b4)/b4;
+
+  /*
+  fprintf(stderr,
+	  "ODB_unpack_DBL(HDRLEN=%d; rc=%d): method=%d, lencma=%d, lenbytes=%d, pdlen=%d, totalpkwords=%d\n",
+	  HDRLEN, rc, method, lencma, lenbytes, pdlen, totalpkwords);
+	  */
+
+  if ((!new_version && rc != HDRLEN) ||
+      ( new_version && rc != PCMA_HDRLEN)) {
+    rc = -1; /* Error */
+    goto finish;
+  }
+
+  if (rc != HDRLEN && !new_version) {
+    rc = -1; /* Error */
+    goto finish;
+  }
+
+  if (pdlen > 0 && totalpkwords != pdlen) {
+    rc = -2; /* Error */
+    goto finish;
+  }
+
+  if ((!new_version && pdlen > HDRLEN) ||
+      ( new_version && pdlen > PCMA_HDRLEN)) {
+    int count = 0;
+
+    ALLOC(cma, lencma);
+
+    pcma2cma_(&can_swp_data, pd, &pdlen, 
+	      NULL, &idxlen, &fill_zeroth_cma,
+	      cma, &lencma, &count, &rc);
+    if (rc != lencma) {
+      rc = -3; /* Error */
+      goto finish;
+    }
+
+    if (count != pdlen) {
+      rc = -4; /* Error */
+      goto finish;
+    }
+    *dlen = lencma - 1;
+  }
+  else
+    *dlen = 0;
+
+  if (*dlen > 0) {
+    /*
+    ALLOC(d, *dlen);
+    dbl2dbl(d, &cma[1], *dlen);
+    */
+    d = cma; /* due to fill_zeroth_cma == 0 */
+  }
+  else {
+    CALLOC(d, *dlen);
+  }
+
+ finish:
+  if (d != cma) FREE(cma);
+
+  if (!d || rc < 0) {
+    fprintf(stderr,
+	    "***Error in ODB_unpack_DBL[method=%d;%s:%d]: rc=%d, *dlen=%d, pdlen=%d, lencma=%d, totalpkwords=%d\n",
+	    method, __FILE__, __LINE__, rc, *dlen, pdlen, lencma, totalpkwords);
+    RAISE(SIGABRT); /* Abort */
+  }
+
+  if (rc < 0) FREE(d);
+  *dlen = (rc < 0) ? rc : *dlen;
+
+  return d;
+}
+
+
+uint *
+ODB_pack_DBL(const double d[],
+	     const int  dlen,
+	     int *method,
+	     int *pdlen,
+	     Bool avoid_copy)
+{
+  int rc = 0;
+  Packbuf pbuf;
+  int bytes_in, bytes_out;
+  int Method = *method;
+  double *cma = avoid_copy ? (double *)&d[-1] : NULL; /* A trique */
+  int lencma = dlen + 1;
+
+  if (dlen <= 0) { 
+    /* Empty column */
+    uint *oneword;
+    CALLOC(oneword, 1);
+    if (pdlen) *pdlen = 0;
+    if (method) *method = 0;
+    return oneword;
+  }
+
+  if (!avoid_copy) {
+    ALLOC(cma,lencma);
+    cma[0] = lencma;
+    dbl2dbl(&cma[1],d,dlen);
+  }
+
+  pbuf.counter = 0;
+  pbuf.maxalloc = 0;
+  pbuf.len = 0;
+  pbuf.p = NULL;
+  pbuf.allocatable = 1;
+
+  /*
+  fprintf(stderr,
+	  "ODB_pack_DBL(method=%d, dlen=%d, lencma=%d, addr=%p)\n",
+	  Method, dlen, lencma, cma);
+	  */
+
+  rc = pcma(NULL, NULL, Method, cma, lencma, &pbuf,
+	    &bytes_in, &bytes_out);
+
+  if (rc < 0) FREE(pbuf.p);
+
+  *pdlen = (rc < 0) ? rc : pbuf.len;
+
+  /*
+  fprintf(stderr,
+	  "ODB_pack_DBL(rc=%d): method=%d, lencma=%d, bytes_in=%d, bytes_out=%d, *pdlen=%d, p=%p\n",
+	  rc, method, lencma, bytes_in, bytes_out, *pdlen, pbuf.p);
+	  */
+
+  if (!avoid_copy) FREE(cma);
+
+  if (rc == 0) {
+    /* Extract true method from the packed stream */
+
+    const uint *hdr = pbuf.p;
+    int lenbytes;
+    double nmdi, rmdi;
+    int new_version;
+    int swp = 0;
+
+    /*
+    fprintf(stderr,"ODB_pack_DBL(rc=%d, lencma=%d): method in = %d ... ",rc,lencma,*method);
+    */
+
+    (void) upcma_hdr(NULL, &swp,
+		     (unsigned int *)hdr, 0, 
+		     method, &lencma, &lenbytes,
+		     &nmdi, &rmdi,
+		     &new_version);
+
+    /*
+    fprintf(stderr,"out = %d : lencma = %d, lenbytes = %d\n",*method,lencma,lenbytes);
+    */
+  }
+
+  return pbuf.p;
+}
+
+
+int *
+ODB_unpack_INT(const uint pd[],
+               const int  pdlen,
+                     int *dlen,
+	             int *method_used,
+	            uint  datatype)
+{
+  double *tmp = ODB_unpack_DBL(pd, pdlen, dlen, method_used, datatype);
+  int *p = NULL;
+  int len = *dlen;
+
+  ALLOC(p, len);
+  if (len > 0) dbl2int(p, tmp, len);
+
+  FREE(tmp);
+
+  return p;
+}
+
+
+uint *
+ODB_pack_INT(const int  d[],
+	     const int  dlen,
+                   int *method,
+	           int *pdlen,
+                   Bool avoid_copy)
+{
+  uint *p = NULL;
+
+  if (dlen <= 0) { 
+    /* An empty column */
+    CALLOC(p, 1);
+    if (pdlen) *pdlen = 0;
+    if (method) *method = 0;
+  }
+  else if (dlen > 0) {
+    double *tmp = NULL;
+    
+    ALLOC(tmp, dlen + 1);
+    tmp[0] = dlen + 1;
+    int2dbl(&tmp[1], d, dlen);
+    
+    p = ODB_pack_DBL(&tmp[1], dlen, method, pdlen, true);
+    
+    FREE(tmp);
+  }
+
+  return p;
+}
+
+
+uint *
+ODB_unpack_UINT(const uint pd[],
+                const int  pdlen,
+                      int *dlen,
+	              int *method_used,
+	             uint  datatype)
+{
+  double *tmp = ODB_unpack_DBL(pd, pdlen, dlen, method_used, datatype);
+  uint *p = NULL;
+  int len = *dlen;
+
+  ALLOC(p, len);
+  if (len > 0) dbl2uint(p, tmp, len);
+
+  FREE(tmp);
+
+  return p;
+}
+
+
+uint *
+ODB_pack_UINT(const uint  d[],
+	      const int   dlen,
+                    int  *method,
+                    int  *pdlen,
+	            Bool  avoid_copy)
+{
+  uint *p;
+
+  if (dlen <= 0) { 
+    /* Empty column */
+    CALLOC(p, 1);
+    if (pdlen) *pdlen = 0;
+    if (method) *method = 0;
+  }
+  else if (dlen > 0) {
+    double *tmp = NULL;
+
+    ALLOC(tmp, dlen + 1);
+    tmp[0] = dlen + 1;
+    uint2dbl(&tmp[1], d, dlen);
+    
+    p = ODB_pack_DBL(&tmp[1], dlen, method, pdlen, true);
+
+    FREE(tmp);
+  }
+
+  return p;
+}
diff --git a/odb/src/lib/version.c b/odb/src/lib/version.c
new file mode 100644
index 0000000..450d6af
--- /dev/null
+++ b/odb/src/lib/version.c
@@ -0,0 +1,94 @@
+
+/* version.c */
+
+/* Keeps track of ODB-version */
+
+#include "alloc.h"
+#include "magicwords.h"
+#include <ctype.h>
+
+#define VERSION_MAJOR 43     /* A positive integer; Number(s) after possible decimal point are ignored */
+#define VERSION_MINOR 0.000  /* Four digits precision/three decimal points (e.q. 2.068) here, please */
+			     /* Please make also sure the last digit is between 1 and 9 i.e. not 0 */
+
+const char *
+codb_versions_(double *major, double *minor, int *numeric, const int *check_IFS_CYCLE_env_first)
+{
+  const double Major = (int)VERSION_MAJOR;
+  const double Minor = VERSION_MINOR;
+  const int Numeric = ((int)VERSION_MAJOR) * 10000 + (int)(VERSION_MINOR * 1000);
+
+  static double ifs_cycle_Major = 0;
+  static double ifs_cycle_Minor = 0;
+  static int ifs_cycle_num = 0;
+
+  static char *ifs_cycle_str = NULL;
+  static char *cycle_str = NULL;
+
+  if (!cycle_str) { /* first time */
+    ALLOC(cycle_str, 20);
+    snprintf(cycle_str, 20, "CY%.0fR%.3f", Major, Minor);
+
+    ifs_cycle_str = getenv("IFS_CYCLE");
+    if (ifs_cycle_str) {
+      char *s = ifs_cycle_str;
+      int slen = STRLEN(s);
+      char *last = s + slen;
+      int numdigits = 0;
+
+      while (s < last) { /* pick up all the digits */
+	if (isdigit(*s)) {
+	  ++numdigits;
+	  ifs_cycle_num = 10*ifs_cycle_num + (*s - '0');
+	}
+	++s;
+      } /* while (s < last) */
+
+      switch (numdigits) {
+      case 2:
+	ifs_cycle_num = 10000 * ifs_cycle_num + 1; /* e.g. CY34 --> 340001 */
+	break;
+      case 3:
+	ifs_cycle_num = 1000 * ifs_cycle_num + 1; /* e.g. CY33R1 --> 331001 */
+	break;
+      case 4:
+	ifs_cycle_num *= 100; /* e.g. CY33R1.4 --> 331400 */
+	break;
+      case 5:
+	ifs_cycle_num *= 10; /* e.g. CY33R1.45 --> 331450 */
+	break;
+      case 6:
+	ifs_cycle_num *= 1; /* e.g. CY33R1.456 --> 331456 */
+	break;
+      default: /* Anything else --> use the value of the Numeric */
+	ifs_cycle_num = Numeric;
+	break;
+      } /* switch (numdigits) */
+    }
+    else {
+      ifs_cycle_num = Numeric;
+    }
+
+    if (ifs_cycle_num != Numeric) {
+      ifs_cycle_Major = (int)(ifs_cycle_num/10000);
+      ifs_cycle_Minor = (ifs_cycle_num%10000)/(double)1000;
+    }
+    else {
+      ifs_cycle_Major = Major;
+      ifs_cycle_Minor = Minor;
+    }
+  } /* if (!cycle_str) */
+
+  if (check_IFS_CYCLE_env_first && *check_IFS_CYCLE_env_first != 0) {
+    if (major) *major = ifs_cycle_Major;
+    if (minor) *minor = ifs_cycle_Minor;
+    if (numeric) *numeric = ifs_cycle_num;
+  }
+  else {
+    if (major) *major = Major;
+    if (minor) *minor = Minor;
+    if (numeric) *numeric = Numeric;
+  }
+
+  return (const char *)cycle_str;
+}
diff --git a/odb/src/lib/wildcard.c b/odb/src/lib/wildcard.c
new file mode 100644
index 0000000..b69060a
--- /dev/null
+++ b/odb/src/lib/wildcard.c
@@ -0,0 +1,213 @@
+#include "odb.h"
+#include "evaluate.h"
+#include "cdrhook.h"
+
+#if defined(LINUX) || defined(SUN4) || defined(RS6K) || defined(SV2)
+/* Watch for this; This GNU-thing may now be okay for other systems, too */
+#include <regex.h>
+#define REGEX_DEF(p)      regex_t p
+#define REGCMP(p,pattern) status = regcomp(&p,pattern,REG_EXTENDED | REG_NOSUB | REG_ICASE)
+#define REGEX(p,s)        status = regexec(&p,s,0,NULL,0)
+#define REGFREE(p)        regfree(&p)
+#else
+#ifdef ALPHA
+#define _XOPEN_SOURCE_EXTENDED 1
+#endif
+#include <libgen.h>
+#define REGEX_DEF(p)      char *p
+#define REGCMP(p,pattern) p = regcmp(pattern,NULL), status = (p ? 0 : 1)
+#define REGEX(p,s)        status = (regex(p,s) ? 0 : 1)
+#define REGFREE(p)
+#endif
+
+
+PUBLIC double
+ODBoffset(double colvar, double offset)
+{
+  return colvar;
+}
+
+
+PUBLIC int
+ODB_Common_StrEqual(const char *str,
+		    const char *cmpstr,
+		    int n, const double d[], 
+		    Boolean is_wildcard)
+{
+  int rc = 0; /* by default not-equal */
+  DRHOOK_START(ODB_Common_StrEqual);
+  if (cmpstr) {
+    n = 0;
+    if (str) {
+      /* A simple match ? */
+      if (strcaseequ(str, cmpstr) || 
+	  StrCaseStr(str, cmpstr, true)) /* from odb/lib/evaluate.c */
+	rc = 1;
+    }
+  }
+  if (rc == 0 && str && ((n > 0 && d) || cmpstr)) {
+    int status = 0;
+    REGEX_DEF(p);
+    char *ref_str = STRDUP(str);
+    char *pref = ref_str;
+    int ref_len = STRLEN(ref_str);
+    /* Skip over the initial blanks, unless the user supplied reference string
+       has explicit got blanks or we have wildcard comparison in concern */
+    Boolean skip_blanks_at_start = 
+      (is_wildcard || (ref_len > 0 && *ref_str == ' ')) ? false : true;
+    /* Ignore the trailing blanks, unless we are in wildcard comparison */
+    Boolean skip_blanks_at_end = 
+      is_wildcard ? false : true;
+    char *cmp_str = cmpstr ? STRDUP(cmpstr) : NULL;
+    
+    if (skip_blanks_at_start) {
+      while (*pref == ' ') ++pref;
+      ref_len = STRLEN(pref);
+    }
+    
+    if (skip_blanks_at_end) {
+      char *last = (ref_len > 0) ? pref + ref_len - 1 : NULL;
+      if (last && *last == ' ') {
+	do {
+	  *last-- = '\0';
+	} while (last >= pref && *last == ' ');
+      }
+    }
+
+    if (is_wildcard) {
+      char *rex = STRDUP(pref);
+      REGCMP(p,rex);
+      FREE(rex);
+      if (status != 0) {
+	rc = 0;
+	goto quick_exit;
+      }
+    }
+
+    if (!cmpstr) {
+      int j, len_cmp_str = n * sizeof(double) + 1;
+      ALLOC(cmp_str, len_cmp_str);
+      *cmp_str = '\0'; /* to allow strcat() */
+    
+      for (j=0; j<n; j++) {
+	S2D_Union u;
+	char *s = u.str;
+	u.dval = d[j];
+	u.str[sizeof(double)] = '\0';
+	if (j == 0 && !is_wildcard) {
+	  if (skip_blanks_at_start) {
+	    while (*s == ' ') ++s;
+	  }
+	  if (!strncaseequ(pref,s,1)) {
+	    /* Quick exit : when the first char doesn't match */
+	    rc = 0;
+	    goto quick_exit;
+	  }
+	}
+	strcat(cmp_str, s);
+      } /* for (j=0; j<n; j++) */
+    }
+
+    if (skip_blanks_at_end) {
+      int len = STRLEN(cmp_str);
+      char *last = (len > 0) ? cmp_str + len - 1 : NULL;
+      if (last && *last == ' ') {
+	do {
+	  *last-- = '\0';
+	} while (last >= cmp_str && *last == ' ');
+      }
+    }
+
+    /* The return value */
+    if (is_wildcard) {
+      REGEX(p, cmp_str);
+      rc = (status == 0) ? 1 : 0;
+    }
+    else {
+      rc = strcaseequ(pref, cmp_str);
+    }
+
+  quick_exit:
+    if (is_wildcard) REGFREE(p);
+    FREE(cmp_str);
+    FREE(ref_str);
+  }
+  DRHOOK_END(0);
+  return rc;
+}
+
+
+PUBLIC int
+ODB_StrEqual(int n, const char *str, ...)
+{
+  int rc = 0; /* by default not-equal */
+  if (--n > 0 && str) {
+    int j;
+    double *d = NULL;
+    va_list ap;
+    va_start(ap, str);
+    ALLOC(d,n);
+    for (j=0; j<n; j++) {
+      d[j] = va_arg(ap, double);
+    }
+    va_end(ap);
+    rc = ODB_Common_StrEqual(str, NULL, n, d, false);
+    FREE(d);
+  }
+  return rc;
+}
+
+
+PUBLIC int
+ODB_WildCard(int n, const char *str, ...)
+{
+  int rc = 0; /* by default not-equal */
+  if (--n > 0 && str) {
+    int j;
+    double *d = NULL;
+    va_list ap;
+    va_start(ap, str);
+    ALLOC(d,n);
+    for (j=0; j<n; j++) {
+      d[j] = va_arg(ap, double);
+    }
+    va_end(ap);
+    rc = ODB_Common_StrEqual(str, NULL, n, d, true);
+    FREE(d);
+  }
+  return rc;
+}
+
+
+PUBLIC double
+ODBstrequal(const int Nd, const double d[])
+{
+  double rc = 0; /* by default not-equal */
+  int n = Nd;
+  if (n-- > 1 && d) {
+    /* Note: d[0] (i.e. *d) is interpreted as an address to a character string (saddr) */
+    char *str = NULL;
+    S2D_Union u;
+    u.dval = *d++;
+    str = u.saddr;
+    rc = ODB_Common_StrEqual(str, NULL, n, d, false);
+  }
+  return rc;
+}
+
+
+PUBLIC double
+ODBwildcard(const int Nd, const double d[])
+{
+  double rc = 0; /* by default not-equal */
+  int n = Nd;
+  if (n-- > 1 && d) {
+    /* Note: d[0] (i.e. *d) is interpreted as an address to a character string (saddr) */
+    char *str = NULL;
+    S2D_Union u;
+    u.dval = *d++;
+    str = u.saddr;
+    rc = ODB_Common_StrEqual(str, NULL, n, d, true);
+  }
+  return rc;
+}
diff --git a/odb/src/lib/write_ddl.c b/odb/src/lib/write_ddl.c
new file mode 100644
index 0000000..99cff09
--- /dev/null
+++ b/odb/src/lib/write_ddl.c
@@ -0,0 +1,164 @@
+#include "odb.h"
+
+/* write_ddl.c */
+
+PUBLIC void
+write_ddl_(const int  *handle,
+	   const int  *iounit,
+	   int *retcode)
+{
+  int rc = 0;
+  int Handle = *handle;
+  FILE *fp = CMA_get_fp(iounit);
+  ODB_Pool *p;
+
+  if (!fp) { rc = -1; goto finish; }
+
+  FORPOOL {
+    if (p->inuse && p->handle == Handle) {
+      ODB_Funcs *pf;
+      char *dbname = p->dbname;
+      int id;
+      const char *dtbuf = odb_datetime_(NULL, NULL); /* ptr to a static variable; do NOT free */
+
+      fprintf(fp,"\n");
+      fprintf(fp,"// Schema for database '%s'\n",dbname);
+      fprintf(fp,"// File created on %s\n",dtbuf);
+      fprintf(fp,"\n");
+
+      /* SET-variables */
+
+      {
+	ODB_Setvar *setvar = NULL;
+	int nsetvar = ODB_get_vars(dbname, NULL, 0, 0, NULL);
+	if (nsetvar > 0) {
+	  ALLOC(setvar, nsetvar);
+	  rc = ODB_get_vars(dbname, NULL, 0, nsetvar, setvar);
+	  if (rc == nsetvar) {
+	    int j;
+	    for (j=0; j<nsetvar; j++) {
+	      fprintf(fp,"SET %s = %.14g;\n",setvar[j].symbol,setvar[j].value);
+	      FREE(setvar[j].symbol);
+	    }
+	  }
+	  else {
+	    rc = -2; 
+	  }
+	  FREE(setvar);
+	  if (rc < 0) goto finish; 
+	}
+      }
+
+      /* TYPE-definitions */
+
+      id = 0;
+      FORFUNC {
+	if (PFCOM->is_table) {
+	  int k;
+	  int ntag = PFCOM->ntag;
+	  char *table_name = PFCOM->name;
+	  const ODB_Tags *tags = PFCOM->tags;
+	  table_name++;
+	  for (k=0; k<ntag; k++) {
+	    int nmem = tags[k].nmem;
+	    if (nmem > 0) {
+	      char *m = tags[k].memb[nmem-1];
+	      if (strequ(m,UNUSED)) nmem--;
+	    }
+	    if (nmem > 0) {
+	      int i;
+	      int nbits = 0;
+	      char *memb_name = NULL;
+	      char *type_name = STRDUP(tags[k].name);
+	      char *c = strchr(type_name,':');
+	      if (c) *c = '\0';
+
+	      id++;
+	      fprintf(fp,
+		      "\nCREATE TYPE %s_%s_%d_t AS ( // ... with %d members\n",
+		      table_name, type_name, id, nmem); 
+	      FREE(type_name);
+
+	      for (i=0; i<nmem; i++) {
+		memb_name = STRDUP(tags[k].memb[i]);
+		c = strchr(memb_name,' ');
+		if (c) { /* Extract number of bits reserved for this member */
+		  *c = '\0';
+		  c++;
+		  nbits = atoi(c);
+		}
+		fprintf(fp,"  %s bit%d,\n", memb_name, nbits);
+		FREE(memb_name);
+	      }
+
+	      fprintf(fp,");\n");
+	    } /* if (nmem > 0) */
+	  } /* for (k=0; k<ntag; k++) */
+	}
+      } /* FORFUNC for TYPE-definitions */
+
+      /* TABLE-definitions */
+
+      id = 0;
+      FORFUNC {
+	if (PFCOM->is_table) {
+	  int k;
+	  int ntag = PFCOM->ntag;
+	  char *table_name = PFCOM->name;
+	  const ODB_Tags *tags = PFCOM->tags;
+	  table_name++;
+	  fprintf(fp,
+		  "\nCREATE TABLE %s AS (\n",
+		  table_name);
+	  for (k=0; k<ntag; k++) {
+	    int nmem = tags[k].nmem;
+	    char *name = STRDUP(tags[k].name);
+	    char *colon = strchr(name,':');
+	    char *atsign = strchr(name,'@');
+	    char *var_name, *type_name;
+
+	    if (nmem > 0) {
+	      char *m = tags[k].memb[nmem-1];
+	      if (strequ(m,UNUSED)) nmem--;
+	    }
+
+	    if (atsign) *atsign = '\0';
+	    if (colon)  *colon = '\0';
+
+	    type_name = name;
+	    var_name = colon ? colon + 1 : NIL;
+
+	    if (nmem > 0) {
+	      id++;
+	      fprintf(fp,"  %s %s_%s_%d_t,\n", var_name, table_name, type_name, id);
+	    }
+	    else if (strnequ(var_name, "LINKOFFSET(", 11)) {
+	      char *table_ref_name = &var_name[11];
+	      char *x = table_ref_name;
+	      while (*x != ')') {
+		if (*x == '\0') break;
+		x++;
+	      }
+	      *x = '\0';
+	      fprintf(fp,"  %s @LINK,\n", table_ref_name);
+	    }
+	    else if (strnequ(var_name, "LINKLEN(", 8)) {
+	      /* do nothing */
+	    }
+	    else {
+	      fprintf(fp,"  %s %s,\n",var_name, type_name);
+	    }
+
+	    FREE(name);
+	  } /* for (k=0; k<ntag; k++) */
+	  fprintf(fp,");\n");
+	}
+      } /* FORFUNC for TABLE-definitions */
+
+      break; /* The first occurence would do */
+    }
+  }
+
+ finish:
+  *retcode = rc;
+}
diff --git a/odb/src/module/.odb_module.F90.un~ b/odb/src/module/.odb_module.F90.un~
new file mode 100644
index 0000000..b45d588
Binary files /dev/null and b/odb/src/module/.odb_module.F90.un~ differ
diff --git a/odb/src/module/CMakeLists.txt b/odb/src/module/CMakeLists.txt
new file mode 100644
index 0000000..e818003
--- /dev/null
+++ b/odb/src/module/CMakeLists.txt
@@ -0,0 +1,21 @@
+list(APPEND module_files
+
+    module/odb.F90
+    module/odb_module.F90
+    module/odb_module8.F90
+    module/odbgetput.F90
+    module/odbio_msgpass.F90
+    module/odbiomap.F90
+    module/odbmap_reportype.F90
+    module/odbmp.F90
+    module/odbnetcdf.F90
+    module/odbprint.F90
+    module/odbshared.F90
+    module/odbsort.F90
+    module/odbstat.F90
+    module/odbutil.F90
+    module/stackdb.F90
+    module/str.F90
+)
+
+set(odb_module_files ${module_files} PARENT_SCOPE)
diff --git a/odb/src/module/odb.F90 b/odb/src/module/odb.F90
new file mode 100644
index 0000000..781c858
--- /dev/null
+++ b/odb/src/module/odb.F90
@@ -0,0 +1,2338 @@
+MODULE odb
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+USE MPL_MODULE, ONLY : MPL_GETARG
+USE OML_MOD    ,ONLY : OML_IN_PARALLEL, OML_NUM_THREADS
+
+#ifdef NAG
+use f90_unix_io,  only: flush
+#endif
+
+USE odbshared ! The shared (mainly internal) stuff
+USE odbmp ! The message passing module
+USE odbutil ! Misc utilities
+USE str, only : toupper, sadjustl, sadjustr
+USE odbsort, only : keysort
+USE odbiomap
+USE odbgetput, only : ODB_get, ODB_put, ODB_gethandle, ODB_getsize
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+#ifndef USE_CTRIM
+#define ctrim(x) x
+#define CTRIM(x) x
+#endif
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+#include "fodb_checkviewreg.h"
+#include "msgpass_loaddata.h"
+#include "msgpass_storedata.h"
+#include "msgpass_loadobs.h"
+#include "msgpass_storeobs.h"
+
+INTERFACE ODB_distribute
+MODULE PROCEDURE & 
+  & ODB_distribute_str  , ODB_distribute_vecstr, &
+  & ODB_distribute_int  , ODB_distribute_vecint, &
+  & ODB_distribute_real8, ODB_distribute_vecreal8
+END INTERFACE
+
+public :: ODB_open
+public :: ODB_load
+public :: ODB_store
+public :: ODB_select
+public :: ODB_cancel
+public :: ODB_close
+public :: ODB_swapout
+public :: ODB_init
+public :: ODB_end
+public :: ODB_distribute
+public :: ODB_pack
+public :: ODB_unpack
+public :: ODB_addpools
+public :: ODB_remove
+public :: ODB_release
+
+!-- Very dangerous routines; avoid using these two unless you know
+!   what you're doing; especially true with ODB_putindices !!
+public :: ODB_getindices
+public :: ODB_putindices
+
+CONTAINS
+
+SUBROUTINE ODB_getindices(handle, view, table, &
+      nrows, ncols, nstart_pos, &
+      poolno, indices, using)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+character(len=*), intent(in) :: view, table
+INTEGER(KIND=JPIM), intent(out) :: nrows, ncols
+INTEGER(KIND=JPIM), intent(in) :: nstart_pos
+INTEGER(KIND=JPIM), intent(in) :: poolno
+INTEGER(KIND=JPIM), intent(out), OPTIONAL :: indices(:,:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+INTEGER(KIND=JPIM) :: idxlen, ipoolno
+character(len=maxvarlen), allocatable :: tablez(:)
+logical :: is_table, all_tables
+INTEGER(KIND=JPIM) :: ntables, rc, jt, using_it
+INTEGER(KIND=JPIM) :: info(8)
+character(len=256) clinfo
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETINDICES',0,ZHOOK_HANDLE)
+
+nrows = 0
+ncols = 0
+
+if (odbHcheck(handle,'ODB_getindices')) then
+  is_table = .FALSE.
+  if (len(view) >= 1) is_table = (view(1:1) == '@')
+  if (is_table) goto 99999
+
+  ipoolno = get_poolno(handle, poolno)
+
+  if (ipoolno == -1 .or. .not. ODB_valid_poolno(ipoolno)) then
+    CALL ODB_abort('ODB_getindices',&
+      &'Specific pool number is missing for '//&
+      &'view="'//trim(view)//'", table="'//trim(table)//'"',&
+      &ipoolno)
+    rc = -1
+    goto 99999
+  endif
+
+  using_it = 0
+  if (present(using)) using_it = using
+
+  all_tables = .TRUE.
+  if (len(table) >= 1) all_tables = (table == '*')
+
+  if (all_tables) then
+    ntables = ODB_getnames(handle, view, 'table')
+  else
+    ntables = 1
+  endif
+
+!-- Get minimal dimensions for indices(:,:)-array : nrows x ncols
+
+  rc = ODB_getsize(handle, view, nrows, ncols, poolno=ipoolno, using=using)
+  ncols = ntables ! ncols re-set (has here a different meaning than usually)
+
+  if (nrows == 0 .or. .not.present(indices)) goto 99999
+
+  allocate(tablez(ntables))
+
+  if (all_tables) then
+    ntables = ODB_getnames(handle, view, 'table', tablez)
+    do jt=1,ntables
+      if (tablez(jt)(1:1) == '@') tablez(jt) = tablez(jt)(2:)
+    enddo
+  else
+    if (len(table) >= 2) then
+      if (table(1:1) == '@') then
+        tablez(1) = table(2:)
+      else
+        tablez(1) = table
+      endif
+    else
+      tablez(1) = table
+    endif
+   endif
+
+  idxlen = min(nrows,size(indices, dim=1)-nstart_pos+1)
+  ntables = min(ntables,size(indices, dim=2))
+
+  if (db_trace) then
+    info(1) = ipoolno
+    info(2) = nrows
+    info(3) = ncols
+    info(4) = nstart_pos
+    info(5) = idxlen
+    info(6) = ntables
+    info(7) = size(indices, dim=1)
+    info(8) = size(indices, dim=2)
+    clinfo = 'ODB_getindices:'//view
+    CALL cODB_trace(handle, -1, clinfo, info, size(info))
+  endif
+
+  do jt=1,ntables
+    CALL codb_getindex( &
+      handle, ipoolno, &
+      ctrim(view), ctrim(tablez(jt)), &
+      idxlen, indices(nstart_pos,jt), &
+      rc, using_it)
+    if (db_trace) then
+      info(1) = ipoolno
+      info(2) = nstart_pos
+      info(3) = idxlen
+      info(4) = rc
+      info(5) = jt
+      clinfo = 'ODB_getindices:'//trim(view)//'['//trim(tablez(jt))//']'
+      CALL cODB_trace(handle, -1, clinfo, info, 5)
+    endif
+    if (rc == -2) cycle
+    if (rc /= idxlen) then
+      CALL ODB_abort('ODB_getindices',&
+        &'codb_getindex failed for '//&
+        &'view="'//trim(view)//'", table="'//trim(tablez(jt))// &
+        &'"; poolno in message code.',&
+        &ipoolno)
+      goto 99999
+    endif
+  enddo
+
+  deallocate(tablez)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETINDICES',1,ZHOOK_HANDLE)
+END SUBROUTINE ODB_getindices
+
+
+SUBROUTINE ODB_putindices(handle, view, table, &
+      nrows, ncols, nstart_pos, &
+      poolno, indices, using)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+character(len=*), intent(in) :: view, table
+INTEGER(KIND=JPIM), intent(in) :: nrows, ncols, nstart_pos
+INTEGER(KIND=JPIM), intent(in) :: poolno
+INTEGER(KIND=JPIM), intent(in) :: indices(:,:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+INTEGER(KIND=JPIM) :: idxlen, ipoolno
+character(len=maxvarlen), allocatable :: tablez(:)
+logical :: is_table, all_tables
+INTEGER(KIND=JPIM) :: ntables, rc, jt, using_it
+INTEGER(KIND=JPIM) :: info(8)
+character(len=256) clinfo
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_PUTINDICES',0,ZHOOK_HANDLE)
+
+if (odbHcheck(handle,'ODB_putindices')) then
+  is_table = .FALSE.
+  if (len(view) >= 1) is_table = (view(1:1) == '@')
+  if (is_table) goto 99999
+
+  ipoolno = get_poolno(handle, poolno)
+
+  if (ipoolno == -1 .or. .not. ODB_valid_poolno(ipoolno)) then
+    CALL ODB_abort('ODB_putindices',&
+      &'Specific pool number is missing for '//&
+      &'view="'//trim(view)//'", table="'//trim(table)//'"',&
+      &ipoolno)
+    rc = -1
+    goto 99999
+  endif
+
+  using_it = 0
+  if (present(using)) using_it = using
+
+  all_tables = .TRUE.
+  if (len(table) >= 1) all_tables = (table == '*')
+
+  if (all_tables) then
+    ntables = ODB_getnames(handle, view, 'table')
+  else
+    ntables = 1
+  endif
+
+  allocate(tablez(ntables))
+
+  if (all_tables) then
+    ntables = ODB_getnames(handle, view, 'table', tablez)
+    do jt=1,ntables
+      if (tablez(jt)(1:1) == '@') tablez(jt) = tablez(jt)(2:)
+    enddo
+  else
+    if (len(table) >= 2) then
+      if (table(1:1) == '@') then
+        tablez(1) = table(2:)
+      else
+        tablez(1) = table
+      endif
+    else
+      tablez(1) = table
+    endif
+  endif
+
+  idxlen = min(nrows,size(indices, dim=1)-nstart_pos+1)
+  ntables = min(ncols,ntables,size(indices, dim=2))
+
+  if (db_trace) then
+    info(1) = ipoolno
+    info(2) = nrows
+    info(3) = ncols
+    info(4) = nstart_pos
+    info(5) = idxlen
+    info(6) = ntables
+    info(7) = size(indices, dim=1)
+    info(8) = size(indices, dim=2)
+    clinfo = 'ODB_putindices:'//view
+    CALL cODB_trace(handle, -1, clinfo, info, size(info))
+  endif
+
+  do jt=1,ntables
+    CALL codb_putindex( &
+      handle, ipoolno, &
+      ctrim(view), ctrim(tablez(jt)), &
+      idxlen, indices(nstart_pos,jt), &
+      rc, using_it)
+    if (db_trace) then
+      info(1) = ipoolno
+      info(2) = nstart_pos
+      info(3) = idxlen
+      info(4) = rc
+      info(5) = jt
+      clinfo = 'ODB_putindices:'//trim(view)//'['//trim(tablez(jt))//']'
+      CALL cODB_trace(handle, -1, clinfo, info, 5)
+    endif
+    if (rc == 0) cycle
+    if (rc /= idxlen) then
+      CALL ODB_abort('ODB_putindices',&
+        &'codb_putindex failed for '//&
+        &'view="'//trim(view)//'", table="'//trim(tablez(jt))//&
+        &'"; poolno in message code.',&
+        &ipoolno)
+      goto 99999
+    endif
+  enddo
+
+  deallocate(tablez)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_PUTINDICES',1,ZHOOK_HANDLE)
+END SUBROUTINE ODB_putindices
+
+
+FUNCTION ODB_init(myproc, nproc, pid, tid, ntid) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(out), optional :: myproc, nproc, pid
+INTEGER(KIND=JPIM), intent(out), optional :: tid, ntid
+INTEGER(KIND=JPIM), external :: get_max_threads, get_thread_id
+INTEGER(KIND=JPIM) :: rc
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_INIT',0,ZHOOK_HANDLE)
+rc = 0
+if (.not. db_initialized) CALL init_db()
+if (present(myproc)) myproc = ODBMP_myproc
+if (present(nproc)) nproc = ODBMP_nproc
+if (present(pid)) CALL cODB_getpid(pid)
+if (present(tid)) tid = get_thread_id()
+if (present(ntid)) ntid = get_max_threads()
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_INIT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_init
+
+
+
+FUNCTION ODB_end() RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM) :: rc
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_END',0,ZHOOK_HANDLE)
+rc = ODBMP_end()
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_END',1,ZHOOK_HANDLE)
+END FUNCTION ODB_end
+
+
+
+
+FUNCTION ODB_close(handle, save) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in)           :: handle
+logical, intent(in), optional :: save
+INTEGER(KIND=JPIM) :: rc
+INTEGER(KIND=JPIM) :: j, k, npoolidx
+INTEGER(KIND=JPIM) :: iounit, ntables, glbNpools, locNpools
+character(len=maxvarlen), allocatable :: ctable(:)
+INTEGER(KIND=JPIM) :: isave(1), tmp, jtbl, ichunk, iret, inumt
+INTEGER(KIND=JPIM) :: iprevious_numt
+INTEGER(KIND=JPIM), external :: get_max_threads
+INTEGER(KIND=JPIM) :: use_new_msgpass
+character(len=dbnamelen) dbname
+REAL(KIND=JPRB) ZHOOK_HANDLE, zwaltim(2), zsum_datavolume
+REAL(KIND=JPRB), allocatable :: zdv(:)
+character(len=maxvarlen), allocatable :: CLtables(:)
+INTEGER(KIND=JPIM), allocatable :: io_order(:)
+logical :: LLsave
+REAL(KIND=JPRB), external    :: util_walltime
+
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CLOSE',0,ZHOOK_HANDLE)
+
+rc = 0
+if (odbHcheck(handle, 'ODB_close')) then
+  isave = 0              ! By default: Do NOT save
+  if (present(save)) then
+    if (save) isave = 1
+  endif
+  if (db(handle)%readonly) isave = 0
+  LLsave = (isave(1) == 1)
+
+  dbname = db(handle)%name
+
+  CALL cODB_trace(handle, 1,'ODB_close:'//dbname, isave, 1)
+
+  if (LLsave) then
+    rc = ODB_store(handle)
+  endif
+
+!--   Database files altered on any PEs ?
+  if (db(handle)%readonly) then
+    db(handle)%altered = .FALSE.
+  else
+    tmp = 0
+    if (db(handle)%altered .or. db(handle)%newdb) tmp = 1
+    CALL ODBMP_global('MAX', tmp)
+    db(handle)%altered = (tmp == 1)
+  endif
+
+  if (db(handle)%altered .and. LLsave) then
+
+    if (ODBMP_myproc == 1) then
+!-- Remove possible .odbprune_done -file
+      call codb_remove_file('$ODB_SRCPATH_'//trim(db(handle)%name)//'/.odbprune_done',iret)
+    endif
+
+    glbNpools = db(handle)%glbNpools
+    ntables   = db(handle)%ntables
+
+!--   Message-pass obs. data back to I/O PEs and perform write, if applicable
+
+    if (db(handle)%io_method == 4) then
+      CALL util_igetenv('ODB_NEW_MSGPASS', 1, use_new_msgpass)
+      if (use_new_msgpass == 1)then
+        CALL msgpass_storeobs(handle, rc)
+      else
+        CALL msgpass_storedata(handle, rc)
+      endif
+    endif ! if (db(handle)%io_method == 4) then ...
+
+!-- Update I/O-map file(s)
+    if (db(handle)%naid > 0) then
+      CALL write_iomap(handle, rc)
+    endif
+
+!--   Update metadata (on PE#1)
+
+    if (ODBMP_myproc == 1) then
+!--   Open and write part#1
+      CALL cma_open(iounit, dbname, 'w', rc)
+      if (rc < 1) then
+        CALL ODB_abort('ODB_close',&
+         &'Cannot open metadata for DB="'//&
+         &trim(dbname)//'"',&
+         &rc)
+        rc = -1
+        goto 99999
+      endif
+
+      CALL cODB_write_metadata(&
+       &handle, iounit, glbNpools, &
+       &db(handle)%CreationDT, db(handle)%AnalysisDT,&
+       &db(handle)%Version_Major, db(handle)%Version_Minor,&
+       &db(handle)%io_method,&
+       &rc)
+      if (rc /= ntables) then
+        CALL ODB_abort('ODB_close',&
+         &'Unable to write metadata (part#1) for DB="'//&
+         &trim(dbname)//'"',&
+         &rc)
+        rc = -2
+        goto 99999
+      endif
+    endif
+
+!--   Gather TABLE filesizes (on every PE) and communicate
+!     the local contributions to PE#1
+    rc = ODB_getnames(handle, '*', 'table')
+    if (rc /= ntables) then
+      CALL ODB_abort('ODB_close',&
+       &'Invalid no. of tables found in DB="'//&
+       &trim(dbname)//'"',&
+       &rc)
+      rc = -3
+    endif
+
+    locNpools = db(handle)%locNpools
+
+    if (ODBMP_myproc == 1) then
+!--   Write part#2 
+      CALL cODB_write_metadata2(&
+       &handle, iounit, glbNpools, ntables,&
+       &rc)
+      if (rc /= ntables) then
+        CALL ODB_abort('ODB_close',&
+         &'Unable to write metadata (part#2) for DB="'//&
+         &trim(dbname)//'"',&
+         &rc)
+        rc = -4
+        goto 99999
+      endif
+!--   Write part#3 (set variables)
+      CALL cODB_write_metadata3(handle, iounit, rc)
+      if (rc < 0) then
+        CALL ODB_abort('ODB_close',&
+         &'Unable to write metadata (part#3) for DB="'//&
+         &trim(dbname)//'"',&
+         &rc)
+        rc = -5
+        goto 99999
+      endif
+!-- Close
+      CALL cma_close(iounit, rc)
+    endif ! if (ODBMP_myproc == 1)
+
+  endif                  ! if (db(handle)%altered .and. LLsave)
+
+  if (db(handle)%rewrite_flags .and. LLsave) then
+    call cODB_print_flags_file(dbname, ODBMP_myproc, rc)
+  endif
+
+  CALL cODB_close(handle, 0, rc)
+
+  if (rc < 0) then
+    CALL ODB_abort('ODB_close(cODB_close)',&
+     &'Unable to close DB="'//&
+     &trim(dbname)//'"',&
+     &rc)
+    goto 99999
+  endif
+
+  CALL newio_end32(handle, rc)
+  if (rc < 0) then
+    CALL ODB_abort('ODB_close(newio_end32)',&
+     &'Error in finishing DB-I/O="'//&
+     &trim(dbname)//'"',&
+     &rc)
+    goto 99999
+  endif
+
+  if (associated(db(handle)%poolidx)) then
+    deallocate(db(handle)%poolidx)
+    nullify(db(handle)%poolidx)
+  endif
+
+  if (associated(db(handle)%ctables)) then
+    deallocate(db(handle)%ctables)
+    nullify(db(handle)%ctables)
+  endif
+
+  if (associated(db(handle)%ioaid)) then
+    deallocate(db(handle)%ioaid)
+    nullify(db(handle)%ioaid)
+  endif
+
+  if (associated(db(handle)%ciomap)) then
+    deallocate(db(handle)%ciomap)
+    nullify(db(handle)%ciomap)
+  endif
+
+  if (associated(db(handle)%grpsize)) then
+    deallocate(db(handle)%grpsize)
+    nullify(db(handle)%grpsize)
+  endif
+
+  if (associated(db(handle)%io_volume)) then
+    deallocate(db(handle)%io_volume)
+    nullify(db(handle)%io_volume)
+  endif
+
+  if (associated(db(handle)%vpoolmap)) then
+    deallocate(db(handle)%vpoolmap)
+    nullify(db(handle)%vpoolmap)
+  endif
+
+  if (associated(db(handle)%vpoolmap_idx)) then
+    deallocate(db(handle)%vpoolmap_idx)
+    nullify(db(handle)%vpoolmap_idx)
+  endif
+
+  db(handle)%nvmap = 0
+
+  db(handle)%altered = .FALSE.
+  db(handle)%inuse = .FALSE.
+
+  CALL codb_end_poolmask(handle)
+
+  CALL cODB_trace(handle, 0,'ODB_close:'//dbname, isave, 1)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CLOSE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_close
+
+
+
+FUNCTION ODB_open(dbname, status, npools, old_npools, maxpoolno) RESULT(handle)
+implicit none
+character(len=*), intent(in)    :: dbname
+character(len=*), intent(in)    :: status
+INTEGER(KIND=JPIM), intent(inout)        :: npools
+! old_npools: Existing npools in the database before ODB_open
+INTEGER(KIND=JPIM), intent(out), OPTIONAL:: old_npools
+!  maxpoolno: The actual maximum poolno to be used 
+!             == "npools", if updatable database
+!     Can be  <= "npools", if read/only database
+INTEGER(KIND=JPIM), intent(out), OPTIONAL:: maxpoolno
+INTEGER(KIND=JPIM) :: rc, handle
+INTEGER(KIND=JPIM) :: iret, itmp
+character(len=len(status)) CL_status
+INTEGER(KIND=JPIM) :: j, iounit, prev_npools, max_poolno, io_method, io_method_env
+INTEGER(KIND=JPIM) :: shared_info(4) ! 1=newdb, 2=readonly, 3=io_method, 4=io_method_env
+logical newdb, okay
+logical readonly
+character(len=len(dbname) + 40) :: srcpath_dbname, datapath_dbname
+character(len=len(dbname) + 40) :: srcpath, datapath
+logical LLsrcpath_empty, LLdatapath_empty
+character(len=1024)             :: env_srcpath_dbname, env_datapath_dbname
+character(len=1024)             :: env_srcpath, env_datapath
+character(len=1024)             :: pwd, env_ioassign
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(2)
+character(len=2048) clinfo
+character(len=maxstrlen) a_out
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_OPEN',0,ZHOOK_HANDLE)
+
+handle = get_handle()
+okay = odbHcheck(handle, 'ODB_open')
+
+if (db_trace) then
+  clinfo = 'ODB_open:'//trim(dbname)//':'//trim(status)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+if (.not. okay) goto 99999
+
+!-- Moved here from open_db() to abort very early on
+call mpl_getarg(0, a_out)
+call cODB_static_init(ctrim(a_out), trim(dbname), ODBMP_myproc, rc)
+
+if (rc < 0) then
+  write(0,*)'***Error: Unrecognized ODB-database "'//trim(dbname)//'"'
+  write(0,*)'   Please check that you have linked the application'
+  write(0,*)'    with -l'//trim(dbname)//' and (the most recent) _odb_glue.o'
+  write(0,*)'   Before that you may have to run : create_odbglue '//trim(dbname)
+  CALL ODB_abort('open_db','Unrecognized database DB="'//trim(dbname)//'"',rc)
+  goto 99999
+endif
+
+!-- Get current directory 
+!   Please do not rely on $PWD, since on some system it is not 
+!   automatically updated, when 'cd' to another dir ;-(
+!--call util_cgetenv('PWD', '.', pwd, idummy)
+call codb_getcwd(pwd)
+
+if (db_trace) then
+  clinfo = 'ODB_open: PWD='//trim(pwd)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+!-- Check for ODB_SRCPATH
+srcpath = 'ODB_SRCPATH'
+call util_cgetenv(trim(srcpath), ' ', env_srcpath, idummy)
+LLsrcpath_empty = (env_srcpath == ' ')
+
+!-- Check for ODB_SRCPATH_<dbname>
+!     If not found, check for ODB_SRCPATH and 
+!       if found, then set ODB_SRCPATH_<dbname> to ODB_SRCPATH,
+!       else set ODB_SRCPATH_<dbname> to current directory
+!   If ODB_SRCPATH was not set, then set it to the just-updated ODB_SRCPATH_<dbname>
+     
+srcpath_dbname = 'ODB_SRCPATH_'//trim(dbname)
+call util_cgetenv(trim(srcpath_dbname), ' ', env_srcpath_dbname, idummy)
+
+if (env_srcpath_dbname  == ' ') then
+  if (LLsrcpath_empty) then
+    clinfo = trim(srcpath_dbname)//'='//trim(pwd)
+  else
+    clinfo = trim(srcpath_dbname)//'='//trim(env_srcpath)
+  endif
+  call codb_putenv(clinfo)
+  call util_cgetenv(trim(srcpath_dbname), ' ', env_srcpath_dbname, idummy)
+endif
+
+if (db_trace) then
+  clinfo = 'ODB_open: ODB_SRCPATH_'//trim(dbname)//'='//trim(env_srcpath_dbname)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+if (LLsrcpath_empty) then
+  clinfo = trim(srcpath)//'='//trim(env_srcpath_dbname)
+  call codb_putenv(clinfo)
+  call util_cgetenv(trim(srcpath), ' ', env_srcpath, idummy)
+endif
+
+if (db_trace) then
+  clinfo = 'ODB_open: ODB_SRCPATH'//'='//trim(env_srcpath)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+!-- Check for ODB_DATAPATH
+datapath = 'ODB_DATAPATH'
+call util_cgetenv(trim(datapath), ' ', env_datapath, idummy)
+LLdatapath_empty = (env_datapath == ' ')
+
+!-- Check for ODB_DATAPATH_<dbname>
+!     If not found, check for ODB_DATAPATH and 
+!       if found, then set ODB_DATAPATH_<dbname> to ODB_DATAPATH,
+!       else set ODB_DATAPATH_<dbname> to ODB_SRCPATH_<dbname>
+!   If ODB_DATAPATH was not set, then set it to the just-updated ODB_DATAPATH_<dbname>
+     
+datapath_dbname = 'ODB_DATAPATH_'//trim(dbname)
+call util_cgetenv(trim(datapath_dbname), ' ', env_datapath_dbname, idummy)
+
+if (env_datapath_dbname  == ' ') then
+  if (LLdatapath_empty) then
+    clinfo = trim(datapath_dbname)//'='//trim(env_srcpath)
+  else
+    clinfo = trim(datapath_dbname)//'='//trim(env_datapath)
+  endif
+  call codb_putenv(clinfo)
+  call util_cgetenv(trim(datapath_dbname), ' ', env_datapath_dbname, idummy)
+endif
+
+if (db_trace) then
+  clinfo = 'ODB_open: ODB_DATAPATH_'//trim(dbname)//'='//trim(env_datapath_dbname)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+if (LLdatapath_empty) then
+  clinfo = trim(datapath)//'='//trim(env_datapath_dbname)
+  call codb_putenv(clinfo)
+  call util_cgetenv(trim(datapath), ' ', env_datapath, idummy)
+endif
+
+if (db_trace) then
+  clinfo = 'ODB_open: ODB_DATAPATH'//'='//trim(env_datapath)
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 0)
+endif
+
+!-- Check for IOASSIGN
+call util_cgetenv('IOASSIGN',' ', env_ioassign, idummy)
+if (env_ioassign == ' ') then
+  call preferred_dbname_ioassign(trim(dbname))
+endif
+
+CL_status = trim(sadjustl(status))
+CALL toupper(CL_status)
+
+io_method = ODB_NMDI ! undefined
+readonly = .FALSE.
+rc = 1
+iounit = -1
+shared_info(:) = 0
+
+if (ODBMP_myproc == 1) then ! Only PE#1 does this
+
+CALL util_igetenv('ODB_IO_METHOD_'//trim(dbname), ODB_NMDI, io_method)
+if (db_trace) then
+  clinfo = 'ODB_open: ODB_IO_METHOD_'//trim(dbname)
+  idummy_arr(1) = io_method
+  CALL cODB_trace(handle, 1, clinfo, idummy_arr, 1)
+endif
+if (io_method == ODB_NMDI) then ! i.e. still undefined; try another env-variable
+  CALL util_igetenv('ODB_IO_METHOD', def_io_method, io_method)
+  if (db_trace) then
+    clinfo = 'ODB_open: ODB_IO_METHOD'
+    idummy_arr(1) = io_method
+    CALL cODB_trace(handle, 1, clinfo, idummy_arr, 1)
+  endif
+endif
+io_method_env = io_method
+if (io_method <= 0) io_method = def_io_method
+
+100 continue
+rc = 1
+iounit = -1
+
+select case (CL_status)
+
+case ('NEW', 'CREATE')
+  CALL cma_open(iounit, dbname, 'w', rc)
+  if (rc < 1) then
+    write(0,*)'***Error: Unable to open ODB-database "'//trim(dbname)//'"'
+    write(0,*)'   Please check that your ODB_SRCPATH_'//trim(dbname)//' is set'
+    write(0,*)'   Currently it is assumed to be "'//trim(env_srcpath_dbname)//'"'
+    CALL ODB_abort('ODB_open',&
+     &'Cannot create DB="'//&
+     &trim(dbname)//'"',&
+     &rc)
+    rc = -1
+    goto 9999
+  endif
+  newdb = .TRUE.
+
+case ('OLD', 'R/W', 'READ WRITE', 'READWRITE', 'READ/WRITE')
+  CALL cma_open(iounit, dbname, 'r', rc)
+  if (rc < 1) then
+    CALL cODB_remove_file(dbname, rc) ! remove zero-length file, typically points to /path/<dbname>.dd
+    write(0,*)'***Error: Unable to open ODB-database "'//trim(dbname)//'"'
+    write(0,*)'   Please check that your ODB_SRCPATH_'//trim(dbname)//' is set'
+    write(0,*)'   Currently it is assumed to be "'//trim(env_srcpath_dbname)//'"'
+    CALL ODB_abort('ODB_open',&
+     &'Cannot open DB="'//&
+     &trim(dbname)//'"',&
+     &rc)
+    rc = -2
+    goto 9999
+  endif
+  newdb = .FALSE.
+
+case ('R/O','READONLY','READ','READ ONLY','READ/ONLY','R')
+  readonly = .TRUE.
+  !-- Automatically set I/O-method to 5, if conditions are right i.e.
+  !   one of the directories { $ODB_SRCPATH_<dbname>/dca, $ODB_SRCPATH/dca, ./dca} exist
+  !-- Also, if I/O-method was set to 5 (via ODB_IO_METHOD_<dbname> or ODB_IO_METHOD)
+  !   and NONE of the aforementioned directories exist, the I/O-method is reverted
+  !   back to default (which is not 5)
+  if (db_trace) then
+    clinfo = 'ODB_open: Before detect_dcadir(): I/O-method, method_env ='
+    idummy_arr(1) = io_method
+    idummy_arr(2) = io_method_env
+    CALL cODB_trace(handle, 1, clinfo, idummy_arr, 2)
+  endif
+  itmp = io_method_env
+  CALL cODB_detect_dcadir(dbname, io_method_env)
+  if (io_method_env <= 0) io_method_env = def_io_method
+  if (itmp /= io_method_env) io_method = io_method_env
+  if (db_trace) then
+    clinfo = 'ODB_open:  After detect_dcadir(): I/O-method, method_env ='
+    idummy_arr(1) = io_method
+    idummy_arr(2) = io_method_env
+    CALL cODB_trace(handle, 1, clinfo, idummy_arr, 2)
+  endif
+  CL_status = 'OLD'
+  goto 100
+
+case ('*', 'UNKNOWN', 'UPDATE', 'APPEND', 'ADD', 'WRITE', 'W', 'A')
+  CALL cma_open(iounit, dbname, 'r', rc)
+  if (rc == -1) then
+    CL_status = 'NEW'
+    goto 100
+  else if (rc < 1) then
+    write(0,*)'***Error: Unable to open ODB-database "'//trim(dbname)//'"'
+    write(0,*)'   Please check that your ODB_SRCPATH_'//trim(dbname)//' is set'
+    write(0,*)'   Currently it is assumed to be "'//trim(env_srcpath_dbname)//'"'
+    CALL ODB_abort('ODB_open',&
+     &'Error in opening DB="'//&
+     &trim(dbname)//'"',&
+     &rc)
+    rc = -3
+    goto 9999
+  endif
+  newdb = .FALSE.
+
+case default
+  CALL ODB_abort(&
+        &'ODB_open',&
+        &'Unrecognized 2nd arg (status flag)="'//trim(status)//&
+        &'" for DB-name="'//&
+        &trim(dbname)//'"')
+  rc = -4
+  goto 9999
+end select
+
+if (newdb)    shared_info(1) = 1
+if (readonly) shared_info(2) = 1
+shared_info(3) = io_method
+shared_info(4) = io_method_env
+
+!!write(0,*)'Shared info#1: ', shared_info(:)
+
+endif ! if (ODBMP_myproc == 1) then ...
+
+CALL ODBMP_global('SUM', shared_info)
+!!write(0,*)'Shared info#2: ', shared_info(:)
+newdb         = (shared_info(1) == 1)
+readonly      = (shared_info(2) == 1)
+io_method     = shared_info(3)
+io_method_env = shared_info(4)
+
+iret = 0
+if (rc == 1) then
+  CALL open_db(handle, dbname, &
+               npools, prev_npools, max_poolno, &
+               iounit, newdb, readonly, io_method, io_method_env, rc)
+  if (rc > 0) then
+    if (present(old_npools)) old_npools = prev_npools
+    if (present(maxpoolno))  maxpoolno = max_poolno
+    if (ODBMP_myproc == 1) then
+      CALL cma_close(iounit, iret)
+      if (iret /= 0) then
+        CALL ODB_abort('ODB_open: cma_close', dbname, iret)
+        rc = -6
+        goto 9999
+      endif
+    endif
+  endif
+endif
+
+if (rc <= 0) then
+  CALL ODB_abort('ODB_open', dbname, rc)
+  rc = -5
+  goto 9999
+endif
+
+!--   Common exit path
+9999 continue
+
+if (rc <= 0) handle = rc
+
+if (db_trace) then
+  clinfo = 'ODB_open:'//trim(dbname)//':'//trim(status)
+  idummy_arr(1) = npools
+  CALL cODB_trace(handle, 0, clinfo, idummy_arr, 1)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_OPEN',1,ZHOOK_HANDLE)
+END FUNCTION ODB_open
+
+
+FUNCTION ODB_store(handle, poolno, sync) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: handle
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+logical,   intent(in), optional :: sync
+INTEGER(KIND=JPIM) :: rc, ipoolno, iret, rcsave
+INTEGER(KIND=JPIM) :: idummy_arr(2), io_method
+INTEGER(KIND=JPIM), parameter :: enforce = 0
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_STORE',0,ZHOOK_HANDLE)
+
+rc = 0
+if (odbHcheck(handle, 'ODB_store')) then
+  if (db(handle)%readonly) goto 99999
+  ipoolno = get_poolno(handle, poolno)
+  io_method = db(handle)%io_method
+  idummy_arr(1) = ipoolno
+  idummy_arr(2) = io_method
+  CALL cODB_trace(handle, 1, 'ODB_store', idummy_arr, 2)
+  CALL cODB_store(handle, ipoolno, io_method, rc)
+  rcsave = rc
+  ! puts ALL tables to disk, if not already (depends on actual io_method, though!)
+  CALL newio_flush32(handle, ipoolno, enforce, -1, '*', rc) !
+  idummy_arr = rc
+  CALL cODB_trace(handle, 0, 'ODB_store', idummy_arr, 1)
+  if (rc < 0) then
+    CALL ODB_abort('ODB_store',&
+     &'Cannot store DB="'//trim(db(handle)%name)//'"',&
+     &rc)
+    goto 99999
+  endif
+  db(handle)%altered = db(handle)%altered .or. (rcsave > 0)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_STORE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_store
+
+
+
+FUNCTION ODB_load(handle, poolno, sync) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: handle
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+logical,   intent(in), optional :: sync
+INTEGER(KIND=JPIM) :: rc, ipoolno, iret
+INTEGER(KIND=JPIM) :: idummy_arr(2), io_method
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_LOAD',0,ZHOOK_HANDLE)
+
+rc = 0
+if (odbHcheck(handle, 'ODB_load')) then
+  ipoolno = get_poolno(handle, poolno)
+  io_method = db(handle)%io_method
+  idummy_arr(1) = ipoolno
+  idummy_arr(2) = io_method
+  CALL cODB_trace(handle, 1, 'ODB_load', idummy_arr, 2)
+  CALL cODB_load(handle, ipoolno, io_method, rc)
+  idummy_arr = rc
+  CALL cODB_trace(handle, 0, 'ODB_load', idummy_arr, 1)
+  if (rc < 0) then
+    CALL ODB_abort('ODB_load',&
+    &'Cannot load DB="'//trim(db(handle)%name)//'"',&
+     &rc)
+    goto 99999
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_LOAD',1,ZHOOK_HANDLE)
+END FUNCTION ODB_load
+
+
+FUNCTION ODB_remove(handle, dtname, poolno) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+logical LLcheck, is_table
+INTEGER(KIND=JPIM) ipoolno, rc
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_REMOVE',0,ZHOOK_HANDLE)
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+rc = 0
+LLcheck = odbHcheck(handle, 'ODB_remove')
+if (LLcheck .and. is_table) then
+  if (.NOT.db(handle)%readonly) then
+    ipoolno = get_poolno(handle, poolno)
+    CALL cODB_remove(handle, ipoolno, ctrim(dtname), rc)
+    if (rc < 0) then
+      CALL ODB_abort('ODB_remove',&
+       &'Removal of TABLE="'//&
+       &trim(dtname)//'" has failed',&
+       &rc)
+      goto 99999
+    endif
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_REMOVE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_remove
+
+
+RECURSIVE &
+FUNCTION ODB_select(handle, dtname, nrows, ncols, nra,&
+     &poolno,&
+     &setvars, values,&
+     &PEvar, replicate_PE, sync, npes_override, recursion, inform_progress, &
+     &using) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+INTEGER(KIND=JPIM), intent(out)          :: nrows, ncols
+INTEGER(KIND=JPIM), intent(out), optional:: nra
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, replicate_PE, npes_override, using
+character(len=*), intent(in), optional :: PEvar
+character(len=*), intent(in), optional :: setvars(:)
+REAL(KIND=JPRB)            , intent(in), optional :: values(:)
+logical,   intent(in), optional :: sync, recursion, inform_progress
+logical has_PEvar, has_vars, is_table, LLcheck, is_replicate
+logical present_PEvar, present_replicate_PE
+logical has_aggrfuncs, LLrecursion, LLswapout, LLinform_progress, LLomp_okay
+INTEGER(KIND=JPIM) :: rc, ipoolno, npes, j, info(4), using_it, my_it
+INTEGER(KIND=JPIM), allocatable :: nrowvec(:)
+character(len=maxvarlen) CL_PEvar
+INTEGER(KIND=JPIM) :: nvars, ireplicate, vhandle, ipes, iaggrcols
+INTEGER(KIND=JPIM) :: ira, iphase_id, irows, icols, igrp
+INTEGER(KIND=JPIM) :: locNpools, npoolidx, ipoolno_save, iret, ngrp, irc
+REAL(KIND=JPRB) :: dummy
+REAL(KIND=JPRB), allocatable :: oldvalues(:)
+REAL(KIND=JPRB), allocatable :: dtmp(:,:)
+INTEGER(KIND=JPIM) :: glbNpools, i_inform_progress
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(0)
+character(len=256) clinfo
+INTEGER(KIND=JPIM), external :: get_thread_id
+REAL(KIND=JPRB) ZHOOK_HANDLE, ZHOOK_OMP
+
+LLrecursion = .FALSE.
+if (present(recursion)) LLrecursion = recursion
+
+IF (LHOOK .and. .not.LLrecursion) CALL DR_HOOK('ODB:ODB_SELECT',0,ZHOOK_HANDLE)
+
+is_table = .FALSE.
+if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+
+rc = 0
+nrows = 0
+ncols = 0
+ireplicate = 0
+is_replicate = .FALSE.
+
+present_PEvar = .FALSE.
+if (present(PEvar)) then
+  present_PEvar = (len_trim(PEvar) > 0)
+endif
+
+present_replicate_PE = .FALSE.
+if (present(replicate_PE)) then
+  present_replicate_PE = (replicate_PE == -1 .or. replicate_PE >= 1)
+endif
+
+ipes = 0
+if (present(npes_override)) then
+  if (npes_override /= ODB_NMDI .and. npes_override > 0) ipes = npes_override
+endif
+
+!--   Mutually exclusive, thus can't co-exist ...
+if (present_PEvar .and. present_replicate_PE) then
+  CALL ODB_abort('ODB_select',&
+   &'PEvar and replicate_PE mutually exclusive'//&
+   &' in VIEW/TABLE="'//trim(dtname)//'"')
+  goto 99999
+endif
+
+LLcheck = odbHcheck(handle, 'ODB_select')
+
+has_PEvar = .FALSE.
+if (present_PEvar .and. .not. is_table) then
+  glbNpools = db(handle)%glbNpools
+  npes = glbNpools
+  CL_PEvar = PEvar
+  has_PEvar = .TRUE.
+else if (present_replicate_PE) then
+  is_replicate = .TRUE.
+  CL_PEvar = 'dummy'
+  npes = 1
+  ireplicate = replicate_PE
+  if (ireplicate >= 1) then
+    ireplicate = min(ireplicate,ODBMP_nproc)
+  endif
+  has_PEvar = .TRUE.
+endif
+
+if (.not.has_PEvar) then
+  npes = 0
+  ireplicate = 0
+endif
+
+if (.not.has_PEvar .or. is_replicate) ipes = 0
+
+!-- The following mod allows shuffle-procedure to loop
+!   over input data more/less than glbNpools in the input database
+if (ipes > 0) npes = ipes
+
+using_it = 0
+if (present(using)) using_it = using
+my_it = get_thread_id()
+
+if (db_trace) then
+  if (has_PEvar) then
+    info(1) = npes
+    info(2) = ireplicate
+    info(3) = ODB_getval(handle, CL_PEvar, dtname)
+    info(4) = using_it
+    clinfo = 'ODB_select:'//trim(dtname)//'; npes, ireplicate, '//trim(CL_PEvar)//'='
+    CALL cODB_trace(handle, 1, clinfo, info, 4)
+  else
+    CALL cODB_trace(handle, 1,'ODB_select:'//dtname, idummy_arr, 0)
+  endif
+endif
+
+nvars = 0
+if (present(setvars) .and. present(values)) then
+  nvars = min(size(setvars), size(values))
+endif
+
+has_vars = (nvars > 0)
+
+LLinform_progress=.FALSE.
+if (present(inform_progress)) LLinform_progress=inform_progress
+if (ODBMP_nproc > 1) LLinform_progress=.FALSE. ! Otherwise messy output 
+
+if (LLcheck) then
+  ipoolno = get_poolno(handle, poolno)
+
+  if (has_vars) then
+    allocate(oldvalues(nvars))
+    do j=1,nvars
+      if (is_table) then
+        oldvalues(j) = ODB_setval(handle, setvars(j), values(j), using=using_it)
+      else
+        oldvalues(j) = ODB_setval(handle, setvars(j), values(j), viewname=dtname, using=using_it)
+      endif
+    enddo
+  endif
+
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle, using=using)
+
+  has_aggrfuncs = ODB_has_aggrfuncs(handle, dtname, ncols=iaggrcols, &
+       & phase_id=iphase_id, poolno=ipoolno, using=using)
+
+#if 0
+  write(0,'(1x,a,2L3,3i12)') &
+       & 'odb.F90: LLrecursion, has_aggrfuncs, iaggrcols, iphase_id, ipoolno = ',&
+       & LLrecursion, has_aggrfuncs, iaggrcols, iphase_id, ipoolno
+#endif
+
+  if (has_PEvar) then
+    allocate(nrowvec(npes))
+
+    vhandle = ODB_gethandle(handle, dtname, using=using)
+    CALL cODB_save_peinfo(vhandle, ireplicate, npes, using_it)
+
+    CALL cODB_mp_select(handle, ipoolno,&
+     &ctrim(dtname), nrowvec, ncols, rc,&
+     &ctrim(CL_PEvar), npes, ireplicate, using_it)
+
+    if (rc >= 0) then
+      if (is_replicate) then
+        CALL ODBMP_global('SUM', nrowvec)
+        nrows = sum(nrowvec(:))
+      else
+        CALL ODBMP_global('SUM', nrowvec)
+        nrows = 0
+        do j=1,npes
+          if (ODBMP_physproc(j) == ODBMP_myproc) then
+            nrows = nrows + nrowvec(j)
+          endif
+        enddo
+      endif
+    else
+      CALL ODB_abort('ODB_select',&
+       &'Multiprocessor SELECT failed in VIEW="'//&
+       &trim(dtname)//'"',&
+       &rc)
+      goto 99999
+    endif
+
+    deallocate(nrowvec)
+  else
+    if (has_aggrfuncs .and. iphase_id == 0 .and. ipoolno == -1 .and. .not.LLrecursion .and. my_it == 1) then
+      ipoolno_save = ipoolno
+      locNpools = db(handle)%locNpools
+      LLomp_okay = .not. OML_IN_PARALLEL() & ! Prevent nested OpenMP-parallelism
+                 & .AND. .not.present(using) ! and avoid already defined thread id
+      nrows = 0
+      irc = 0 ! Can't have "rc" in REDUCTION-clause, since it's already as the function RESULT
+!$OMP PARALLEL PRIVATE(npoolidx,ipoolno,iret,irows,icols,ZHOOK_OMP) &
+!$OMP&         REDUCTION(+:irc)                                        IF (LLomp_okay)
+      CALL DR_HOOK('ODB:ODB_SELECT>OMP-1',0,ZHOOK_OMP)
+!$OMP DO SCHEDULE(DYNAMIC)
+      do npoolidx=1,locNpools
+        ipoolno = db(handle)%poolidx(npoolidx)
+        iret = ODB_select(handle, dtname, irows, icols, poolno=ipoolno, &
+             &            recursion=.TRUE., inform_progress=LLinform_progress)
+        irc = irc + iret
+#if 0
+        write(0,'(1x,a,4i12)') &
+             & 'odb.F90[1]: ipoolno, iret, irows, icols = ',ipoolno, iret, irows, icols
+#endif
+      enddo
+!$OMP END DO
+      CALL DR_HOOK('ODB:ODB_SELECT>OMP-1',1,ZHOOK_OMP)
+!$OMP END PARALLEL
+      rc = irc
+      ipoolno = ipoolno_save
+      irc = ODB_getsize(handle, dtname, nrows, ncols, poolno=ipoolno) ! Get reliable "nrows" & "ncols"
+#if 0
+      write(0,'(1x,a,4i12)') &
+           & 'odb.F90> ipoolno,  rc , nrows, ncols = ',ipoolno,  rc , nrows, ncols
+#endif
+      iphase_id = -1 ! To avoid calling ODB_get/ODB_put below again
+    else ! i.e. .NOT. (has_aggrfuncs .and. iphase_id == 0 .and. ipoolno == -1 .and. .not.LLrecursion .and. my_it == 1)
+      i_inform_progress = 0
+      if (LLinform_progress) i_inform_progress = 1
+      CALL cODB_select(handle, ipoolno, ctrim(dtname), nrows, ncols, rc, i_inform_progress, using_it)
+    endif
+  endif
+
+  if (rc < 0) then
+    CALL ODB_abort('ODB_select',&
+     &'Cannot select VIEW/TABLE="'//trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+
+  if (has_aggrfuncs .and. nrows > 0 .and. ncols > 0) then
+
+    if (has_aggrfuncs .and. iphase_id == 0) then
+    ! Perform phase#0 processing of aggregate functions and save results into intermediate data structure
+    ! Cancel original data indices, but keep intermediate C-structures (pf->tmp) untouched
+    ! Perform pool-by-pool, if ipoolno = -1 (else-block)
+    ! Normally called recursively i.e. ipoolno is > 0
+
+      ngrp = 0 ! Total no. of rows AFTER aggregate phase#0
+      icols = ncols
+      locNpools = db(handle)%locNpools
+
+#if 0
+      write(0,'(1x,a,4i12)') &
+           & 'odb.F90[2]: nrows, ncols, ipoolno, locNpools = ',&
+           &           nrows, ncols, ipoolno, locNpools
+#endif
+
+      LLswapout = (db(handle)%io_method == 5)
+      if (ipoolno > 0) then
+        irows = nrows
+        ira = ODB_lda(irows)
+        allocate(dtmp(1:ira,0:icols))
+        igrp = ODB_get(handle, dtname, dtmp, irows, ncols=icols, poolno=ipoolno, &
+             & sorted=.FALSE., process_select_distinct=.FALSE.) ! Do aggr. phase#0
+#if 0
+        write(0,'(1x,a,5i12)') &
+             & 'odb.F90[2]: ipoolno, ira, igrp, irows, icols =',ipoolno, ira, igrp, irows, icols
+#endif
+        if (igrp > 0) then
+          ngrp = ngrp + igrp
+          rc = ODB_put(handle, dtname, dtmp, igrp, ncols=icols, poolno=ipoolno, &
+             & store_intermed=.TRUE.,using=1) ! Now tid#1 can access this again
+        endif
+        deallocate(dtmp)
+        if (LLswapout) then ! Saves plenty of memory in aggregate func calc
+          rc = ODB_swapout(handle, dtname, poolno=ipoolno, delete_intermed=.FALSE.)
+        else
+          rc = ODB_cancel(handle, dtname, poolno=ipoolno, delete_intermed=.FALSE.)
+        endif
+      else ! ipoolno = -1
+        ipoolno_save = ipoolno
+        LLomp_okay = .not. OML_IN_PARALLEL() & ! Prevent nested OpenMP-parallelism
+                   & .AND. .not.present(using) ! and avoid already defined thread id
+!$OMP PARALLEL PRIVATE(npoolidx,ipoolno,iret,irows,icols,dtmp,ira,igrp,ZHOOK_OMP) &
+!$OMP&         REDUCTION(+:ngrp)                                                     IF (LLomp_okay)
+      CALL DR_HOOK('ODB:ODB_SELECT>OMP-2',0,ZHOOK_OMP)
+!$OMP DO SCHEDULE(DYNAMIC)
+        do npoolidx=1,locNpools
+          ipoolno = db(handle)%poolidx(npoolidx)
+          irows = 0
+          iret = ODB_getsize(handle, dtname, irows, icols, nra=ira, poolno=ipoolno)
+          if (irows > 0) then
+#if 0
+            write(0,'(1x,a,5i12)') &
+                 & 'odb.F90:[1] ipoolno, ira, iret, irows, icols =',ipoolno, ira, iret, irows, icols
+#endif
+            allocate(dtmp(1:ira,0:icols))
+            igrp = ODB_get(handle, dtname, dtmp, irows, ncols=icols, poolno=ipoolno, &
+                 & sorted=.FALSE., process_select_distinct=.FALSE.) ! Do aggr. phase#0
+#if 0
+            write(0,'(1x,a,5i12)') &
+                 & 'odb.F90:[2] ipoolno, ira, igrp, irows, icols =',ipoolno, ira, igrp, irows, icols
+#endif
+            ngrp = ngrp + igrp
+            iret = ODB_put(handle, dtname, dtmp, igrp, ncols=icols, poolno=ipoolno, &
+                 & store_intermed=.TRUE.,using=1) ! Now tid#1 can access this again
+            deallocate(dtmp)
+          endif
+          if (LLswapout) then ! Saves plenty of memory in aggregate func calc
+            iret = ODB_swapout(handle, dtname, poolno=ipoolno, delete_intermed=.FALSE.)
+          else
+            iret = ODB_cancel(handle, dtname, poolno=ipoolno, delete_intermed=.FALSE.)
+          endif
+        enddo
+!$OMP END DO
+      CALL DR_HOOK('ODB:ODB_SELECT>OMP-2',1,ZHOOK_OMP)
+!$OMP END PARALLEL
+        ipoolno = ipoolno_save
+      endif
+
+      rc = ngrp
+      nrows = rc
+    endif
+  endif
+
+  if (has_vars) then
+    do j=1,nvars
+      if (is_table) then
+        dummy = ODB_setval(handle, setvars(j), oldvalues(j), using=using_it)
+      else
+        dummy = ODB_setval(handle, setvars(j), oldvalues(j), viewname=dtname, using=using_it)
+      endif
+    enddo
+    deallocate(oldvalues)
+  endif
+endif
+
+if (present(nra)) then
+  nra = ODB_lda(nrows)
+endif
+
+if (db_trace) then
+  info(1) = -nrows
+  if (present(nra)) info(1) = nra
+  info(2) = nrows
+  info(3) = ncols
+  CALL cODB_trace(handle, 0,'ODB_select:'//dtname, info, 3)
+endif
+99999 continue
+IF (LHOOK .and. .not.LLrecursion) CALL DR_HOOK('ODB:ODB_SELECT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_select
+
+
+
+FUNCTION ODB_cancel(handle, dtname, poolno, delete_intermed, using) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, using
+logical, intent(in), optional :: delete_intermed
+INTEGER(KIND=JPIM) :: rc, ipoolno, info(4), idel, using_it
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CANCEL',0,ZHOOK_HANDLE)
+
+rc = 0
+if (odbHcheck(handle, 'ODB_cancel')) then
+  ipoolno = get_poolno(handle, poolno)
+  idel = 1
+  if (present(delete_intermed)) then
+    if (.not.delete_intermed) idel = 0
+  endif
+  using_it = 0
+  if (present(using)) using_it = using
+  CALL cODB_cancel(handle, ipoolno, ctrim(dtname), rc, idel, using_it)
+  if (db_trace) then
+    info(1) = ipoolno
+    info(2) = rc
+    info(3) = idel
+    info(4) = using_it
+    CALL cODB_trace(handle, -1,'ODB_cancel:'//dtname, info, size(info))
+  endif
+  if (rc < 0) then
+    CALL ODB_abort('ODB_cancel',&
+     &'Cannot cancel request on VIEW/TABLE="'//&
+     &trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CANCEL',1,ZHOOK_HANDLE)
+END FUNCTION ODB_cancel
+
+
+
+FUNCTION ODB_swapout(handle, dtname, poolno, save, repack, delete_intermed, using) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, using
+logical, intent(in), optional :: save, repack, delete_intermed
+INTEGER(KIND=JPIM) :: rc, rctot, j, ntables
+INTEGER(KIND=JPIM) :: ipoolno, isave, info(3), idummy_arr(1), ilen, ilen_table, idel, using_it
+logical is_table, LLslow, LLrepack
+character(len=maxvarlen), allocatable :: cltable(:)
+character(len=maxvarlen) CLname
+character(len=maxstrlen) CL_str
+INTEGER(KIND=JPIM), parameter :: enforce = 0
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_SWAPOUT',0,ZHOOK_HANDLE)
+
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+
+rc = 0
+!if (.not. is_table) goto 99999
+
+if (odbHcheck(handle, 'ODB_swapout')) then
+  ipoolno = get_poolno(handle, poolno)
+  isave = 0              ! By default: Do NOT save
+  if (present(save)) then
+    if (save) isave = 1
+  endif
+  LLrepack = .FALSE.
+  if (present(repack)) then
+    LLrepack = repack .and. (isave == 1 .and. db(handle)%io_method == 4)
+  endif
+
+  idel = 1
+  if (present(delete_intermed)) then
+    if (.not.delete_intermed) idel = 0
+  endif
+
+  using_it = 0
+  if (present(using)) using_it = using
+
+  if (db(handle)%readonly) isave = 0 ! Prevent saving, but proceed with memory release
+  if (db_trace) then
+    info(1) = isave
+    info(2) = ipoolno
+    info(3) = idel
+    CALL cODB_trace(handle, 1, 'ODB_swapout:'//dtname,&
+     &info, size(info))
+  endif
+
+  rctot = 0
+  if (is_table) then
+    if (LLrepack) rc = ODB_pack(handle, ctrim(dtname), ipoolno)
+    CALL cODB_swapout(handle, ipoolno, ctrim(dtname), isave, rc, idel, using_it)
+    if (isave == 1) then
+      CALL newio_flush32(handle, ipoolno, enforce, 1, trim(dtname), rc) ! puts THIS table to disk, if not already
+    endif
+    rctot = rc
+  else if (dtname == '*') then ! Get ALL the tables
+    ntables = ODB_getnames(handle, '*', 'table')
+    allocate(cltable(ntables))
+    ntables = ODB_getnames(handle, '*', 'table', cltable)
+    do j=1,ntables
+      if (LLrepack) rc = ODB_pack(handle, ctrim(cltable(j)), ipoolno)
+      CALL cODB_swapout(handle, ipoolno, ctrim(cltable(j)), isave, rc, idel, using_it)
+      if (rc < 0) then
+        CLname = cltable(j)
+        goto 99
+      endif
+      rctot = rctot + rc
+    enddo
+    if (isave == 1) then
+      CALL newio_flush32(handle, ipoolno, enforce, -1, '*', rc) ! puts ALL tables to disk, if not already
+    endif
+  else ! Get all tables associated with this view
+    ntables = ODB_getnames(handle, dtname, 'table')
+    allocate(cltable(ntables))
+    ntables = ODB_getnames(handle, dtname, 'table', cltable)
+    CALL cODB_cancel(handle, ipoolno, ctrim(dtname), rc, idel, using_it)
+    do j=1,ntables
+      if (LLrepack) rc = ODB_pack(handle, ctrim(cltable(j)), ipoolno)
+      CALL cODB_swapout(handle, ipoolno, ctrim(cltable(j)), isave, rc, idel, using_it)
+      if (rc < 0) then
+        CLname = cltable(j)
+        goto 99
+      endif
+      rctot = rctot + rc
+    enddo
+    if (isave == 1) then
+      LLslow = .FALSE.
+!! overkill; we don't need this --> CALL codb_strblank(CL_str) ! faster initialization
+      CL_str(1:1) = '/'
+      ilen = 1
+      do j=1,ntables
+        ilen_table = len_trim(cltable(j))
+        if (ilen+ilen_table+1 > maxstrlen) then
+          LLslow = .TRUE.
+          exit
+        endif
+        CL_str(ilen+1:ilen+ilen_table+1) = cltable(j)(1:ilen_table)//'/'
+        ilen = ilen + ilen_table + 1
+      enddo
+      if (LLslow) then ! Adopt one-by-one method, since CL_str was too short
+        do j=1,ntables
+          CALL newio_flush32(handle, ipoolno, enforce, 1, trim(cltable(j)), rc) ! puts THIS table to disk, if not already
+        enddo
+      else
+        CALL newio_flush32(handle, ipoolno, enforce, ntables, CL_str(1:ilen), rc) ! puts THESE tables to disk, if not already
+      endif
+    endif ! if (isave == 1) then
+  endif
+99 continue
+  if (allocated(cltable)) deallocate(cltable)
+  if (rc < 0) then
+    idummy_arr = rc
+    CALL cODB_trace(handle, 0, 'ODB_swapout:'//dtname, idummy_arr, 1)
+    CALL ODB_abort('ODB_swapout',&
+     &'Unable to swapout TABLE="'//&
+     &trim(CLname)//'"',&
+     &rc)
+    goto 99999
+  else
+    idummy_arr = rctot
+    CALL cODB_trace(handle, 0, 'ODB_swapout:'//dtname, idummy_arr, 1)
+  endif
+  db(handle)%altered = db(handle)%altered .or. (isave == 1 .and. rctot > 0)
+  rc = rctot
+endif
+98 continue
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_SWAPOUT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_swapout
+
+
+FUNCTION ODB_distribute_vecreal8(s, target) RESULT(rc)
+REAL(KIND=JPRB), intent(inout) :: s(:)
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc, recip
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECREAL8',0,ZHOOK_HANDLE)
+if (.not. db_initialized) CALL init_db()
+if (present(target)) then
+!--   target == 0 : PE#1 distributes to all other PEs
+!             < 0 : I'll receive from abs(target)
+!             > 0 : I'll send to target
+  recip = target
+else
+!--   PE#1 distributes to all other PEs
+  recip = 0
+endif
+CALL ODBMP_distribute(s,size(s),recip,rc)
+if (rc /= size(s)) then
+  CALL ODB_abort('ODB_distribute_vecreal8','Data delivery failed',rc)
+  goto 99999
+endif
+rc = size(s)
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECREAL8',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_vecreal8
+
+FUNCTION ODB_distribute_real8(s, target) RESULT(rc)
+REAL(KIND=JPRB), intent(inout) :: s
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc
+REAL(KIND=JPRB) tmp(1)
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_REAL8',0,ZHOOK_HANDLE)
+tmp(1) = s
+rc = ODB_distribute(tmp, target)
+s = tmp(1)
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_REAL8',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_real8
+
+
+FUNCTION ODB_distribute_vecint(s, target) RESULT(rc)
+INTEGER(KIND=JPIM), intent(inout) :: s(:)
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc, recip
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECINT',0,ZHOOK_HANDLE)
+if (.not. db_initialized) CALL init_db()
+if (present(target)) then
+!--   target == 0 : PE#1 distributes to all other PEs
+!             < 0 : I'll receive from abs(target)
+!             > 0 : I'll send to target
+  recip = target
+else
+!--   PE#1 distributes to all other PEs
+  recip = 0
+endif
+CALL ODBMP_distribute(s,size(s),recip,rc)
+if (rc /= size(s)) then
+  CALL ODB_abort('ODB_distribute_vecint','Data delivery failed',rc)
+  goto 99999
+endif
+rc = size(s)
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECINT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_vecint
+
+
+FUNCTION ODB_distribute_int(s, target) RESULT(rc)
+INTEGER(KIND=JPIM), intent(inout) :: s
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc
+INTEGER(KIND=JPIM) itmp(1)
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_INT',0,ZHOOK_HANDLE)
+itmp(1) = s
+rc = ODB_distribute(itmp, target)
+s = itmp(1)
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_INT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_int
+
+FUNCTION ODB_distribute_str(s, target) RESULT(rc)
+character(len=*), intent(inout) :: s
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc, recip, lens
+external cODB_idistribute
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_STR',0,ZHOOK_HANDLE)
+if (.not. db_initialized) CALL init_db()
+if (present(target)) then
+!--   target == 0 : PE#1 distributes to all other PEs
+!             < 0 : I'll receive from abs(target)
+!             > 0 : I'll send to target
+  recip = target
+else
+!--   PE#1 distributes to all other PEs
+  recip = 0
+endif
+lens = len(s)
+CALL cODB_distribute_str(s,cODB_idistribute,recip,rc)
+if (rc /= lens) then
+  CALL ODB_abort('ODB_distribute_str','Data delivery failed',rc)
+  goto 99999
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_STR',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_str
+
+FUNCTION ODB_distribute_vecstr(s, target) RESULT(rc)
+character(len=*), intent(inout) :: s(:)
+INTEGER(KIND=JPIM), intent(in), optional :: target
+INTEGER(KIND=JPIM) :: rc, recip, lens
+external cODB_idistribute
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECSTR',0,ZHOOK_HANDLE)
+if (.not. db_initialized) CALL init_db()
+if (present(target)) then
+!--   target == 0 : PE#1 distributes to all other PEs
+!             < 0 : I'll receive from abs(target)
+!             > 0 : I'll send to target
+  recip = target
+else
+!--   PE#1 distributes to all other PEs
+  recip = 0
+endif
+lens = len(s) * size(s)
+if (lens > 0) then
+  CALL cODB_distribute_vecstr(s(1),cODB_idistribute,recip,size(s),rc)
+else
+  rc = 0
+endif
+if (rc /= lens) then
+  CALL ODB_abort('ODB_distribute_vecstr','Data delivery failed',rc)
+  goto 99999
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_DISTRIBUTE_VECSTR',1,ZHOOK_HANDLE)
+END FUNCTION ODB_distribute_vecstr
+
+!-- Private routines
+
+
+
+
+SUBROUTINE open_db(handle, dbname, &
+                 npools, old_npools, maxpoolno, &
+                 iounit, newdb, readonly, io_method, io_method_env, rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: handle, iounit, io_method, io_method_env
+logical, intent(in)  :: newdb, readonly
+INTEGER(KIND=JPIM), intent(inout) :: npools
+INTEGER(KIND=JPIM), intent(out) :: old_npools, maxpoolno
+character(len=*), intent(in) :: dbname
+INTEGER(KIND=JPIM), intent(out) :: rc
+INTEGER(KIND=JPIM) :: j, npoolidx, is_new, is_readonly, jtbl, iret
+INTEGER(KIND=JPIM) :: glbNpools, locNpools, ntables, naid, io_grpsize
+INTEGER(KIND=JPIM) :: tmp(2), ichunk, iadd_vars
+INTEGER(KIND=JPIM) :: pool_excess, io_method_updated
+INTEGER(KIND=JPIM) :: inumt, iprevious_numt
+INTEGER(KIND=JPIM) :: use_new_msgpass
+REAL(KIND=JPRB) ZHOOK_HANDLE, zwaltim(2), zsum_datavolume
+REAL(KIND=JPRB), allocatable :: zdv(:)
+INTEGER(KIND=JPIM), allocatable :: io_order(:)
+INTEGER(KIND=JPIM), allocatable :: iconsider(:)
+character(len=maxvarlen), allocatable :: CLtables(:)
+REAL(KIND=JPRB), external    :: util_walltime
+INTEGER(KIND=JPIM), external :: get_max_threads
+logical :: LLrewrite_flags
+INTEGER(KIND=JPIM) idummy
+character(len=256) CLsrcpath
+character(len=256) CLdatapath
+character(len=256) CLidxpath
+character(len=256) pwd
+IF (LHOOK) CALL DR_HOOK('ODB:OPEN_DB',0,ZHOOK_HANDLE)
+
+rc = 0
+LLrewrite_flags = .FALSE.
+
+call cODB_linkDB(dbname, rc)
+
+if (rc < 0) then
+  CALL ODB_abort('open_db','Unable to link DB="'//trim(dbname)//'"',rc)
+  goto 99999
+endif
+
+ntables = rc
+
+db(handle)%name = dbname
+db(handle)%ntables = ntables
+
+io_method_updated = io_method
+
+if (.not. newdb) then
+  if (ODBMP_myproc == 1) then
+    CALL cODB_read_metadata(&
+     &handle, iounit, glbNpools, &
+     &db(handle)%CreationDT, db(handle)%AnalysisDT,&
+     &db(handle)%Version_Major, db(handle)%Version_Minor,&
+     &io_method_updated,&
+     &rc)
+    write(0,*) 'There are rc = ', rc, ' and ntables = ', ntables
+    if (rc /= ntables) then
+      CALL ODB_abort('open_db',&
+       &'Inconsistent no. of tables (part#1), DB="'//&
+       &trim(dbname)//'"',&
+       &rc, really_abort=.FALSE.) ! bail out
+       if (.not. readonly) LLrewrite_flags = .TRUE.
+!      rc = -2
+!      goto 99999
+    endif
+    npools = glbNpools
+  endif
+else
+  CALL cODB_datetime(db(handle)%CreationDT(0), db(handle)%CreationDT(1))
+  CALL cODB_analysis_datetime(&
+   &db(handle)%AnalysisDT(0), db(handle)%AnalysisDT(1))
+  CALL cODB_versions(db(handle)%Version_Major, db(handle)%Version_Minor, idummy, 0)
+  if (ODBMP_myproc == 1) npools = max(npools, ODBMP_nproc) ! Make sure it is >= ODBMP_nproc at least
+endif
+
+if (ODBMP_myproc == 1) then
+  tmp(1) = npools
+  tmp(2) = io_method_updated
+else
+  tmp(:) = 0
+endif
+
+CALL ODBMP_global('SUM',tmp)
+npools = tmp(1)
+glbNpools = npools
+old_npools = 0
+if (.not. newdb) old_npools = npools
+io_method_updated = tmp(2)
+db(handle)%io_method = io_method_updated
+
+if (readonly .and. io_method_env == 5) db(handle)%io_method = 5 ! Via DCA; read/only access !
+
+npoolidx = 0
+do j=1,npools
+  if (ODBMP_physproc(j) == ODBMP_myproc) npoolidx = npoolidx + 1
+enddo
+
+locNpools = npoolidx
+allocate(db(handle)%poolidx(locNpools))
+db(handle)%glbNpools = glbNpools
+db(handle)%glbMaxpoolno = glbNpools
+db(handle)%locNpools = locNpools
+
+npoolidx = 0
+do j=1,glbNpools
+  if (ODBMP_physproc(j) == ODBMP_myproc) then
+    npoolidx = npoolidx + 1
+    db(handle)%poolidx(npoolidx) = j
+  endif
+enddo
+
+is_new = 0
+if (newdb) is_new = 1
+
+CALL codb_init_poolmask(handle, db(handle)%name, glbNpools)
+
+iadd_vars = 1
+do j=1,locNpools
+  npoolidx = db(handle)%poolidx(j)
+  if (readonly) then
+    CALL cODB_in_permanent_poolmask(handle, npoolidx, rc)
+  else
+    rc = 1
+  endif
+  if (rc == 1) then ! In R/O-mode initialize only those pools that are in permanent poolmask
+    CALL cODB_create_pool(handle, db(handle)%name, npoolidx, is_new, db(handle)%io_method, iadd_vars, rc)
+    if (rc /= npoolidx) then
+      rc = -(1000 + abs(npoolidx))
+      goto 99999
+    endif
+    iadd_vars = 0
+  endif
+enddo
+
+if (.not. newdb .and. .not. readonly) then
+  if (ODBMP_myproc == 1) then
+    CALL cODB_read_metadata2(&
+     &handle, iounit, glbNpools, ntables,&
+     &rc)
+    if (rc /= ntables) then
+      CALL ODB_abort('open_db',&
+       &'Inconsistent no. of tables (part#2), DB="'//&
+       &trim(dbname)//'"',&
+       &rc, really_abort=.FALSE.) ! bail out
+       LLrewrite_flags = .TRUE.
+!      rc = -4
+!      goto 99999
+    endif
+  endif
+endif
+
+db(handle)%inuse = .TRUE.
+db(handle)%newdb = newdb
+!*AF 07/02/10 not the best way to do it; we always rewrite IO/map file...
+!*AF To check and improve...
+!*AF db(handle)%altered = LLrewrite_flags
+db(handle)%altered = .TRUE.
+db(handle)%iounit = iounit
+db(handle)%readonly = readonly
+
+is_readonly = 0
+if (readonly) is_readonly = 1
+
+if ((newdb .or. LLrewrite_flags) .and. .not.readonly) then
+  db(handle)%rewrite_flags = .TRUE.
+else
+  db(handle)%rewrite_flags = .FALSE.
+endif
+
+if (ODBMP_myproc == 1) then
+  write(0,*) 'OPEN_DB: handle=',handle
+  write(0,*) 'DataBase-name="'//trim(db(handle)%name)//'"'
+  call codb_getcwd(pwd)
+  call util_cgetenv('ODB_SRCPATH_'//trim(db(handle)%name), &
+       & trim(pwd), CLsrcpath, idummy)
+  write(0,*) 'ODB_SRCPATH_'//trim(db(handle)%name)//'="'//CLsrcpath(1:idummy)//'"'
+  call util_cgetenv('ODB_DATAPATH_'//trim(db(handle)%name), &
+       & trim(CLsrcpath), CLdatapath, idummy)
+  write(0,*) 'ODB_DATAPATH_'//trim(db(handle)%name)//'="'//CLdatapath(1:idummy)//'"'
+  call util_cgetenv('ODB_IDXPATH_'//trim(db(handle)%name), &
+       & trim(CLsrcpath)//'/idx', CLidxpath, idummy)
+  write(0,*) 'ODB_IDXPATH_'//trim(db(handle)%name)//'="'//CLidxpath(1:idummy)//'"'
+  write(0,*) 'inuse ? ',db(handle)%inuse
+  write(0,*) 'newdb ? ',db(handle)%newdb
+  write(0,*) 'readonly ? ',db(handle)%readonly
+  write(0,*) 'rewrite_flags-file ? ',db(handle)%rewrite_flags
+  write(0,*) 'no. of global pools = ',db(handle)%glbNpools
+  write(0,*) 'global max poolno = ',db(handle)%glbMaxpoolno
+  write(0,*) 'no. of local pools = ',db(handle)%locNpools
+  write(0,*) 'max. no. of rows per pool = ',ODB_MAXROWS
+  write(0,*) 'I/O-method = ',db(handle)%io_method
+  write(0,*) 'iounit = ',iounit
+  write(0,*) 'ntables = ',ntables
+  write(0,*) 'no. of MPI-tasks = ',ODBMP_nproc
+  write(0,*) 'no. of OpenMP-threads = ',get_max_threads()
+!         do j=1,db(handle)%locNpools
+!            write(0,*) 'Local pool index#',j,' = ',db(handle)%poolidx(j)
+!         enddo
+endif
+
+CALL newio_start32(db(handle)%name, &
+                   handle, maxhandle, db(handle)%io_method, &
+                   db(handle)%ntables, is_new, is_readonly, &
+                   db(handle)%glbNpools, db(handle)%locNpools, db(handle)%poolidx, &
+                   rc)
+
+if (rc < 0) then
+  CALL ODB_abort('ODB_open(open_db(newio_start32))',&
+   &'Error in initializing DB-I/O structures="'//&
+   &trim(db(handle)%name)//'"',&
+   &rc)
+  goto 99999
+endif
+
+naid = 0
+if (db(handle)%io_method == 4) then
+  naid = IONAID
+  glbNpools = db(handle)%glbNpools
+  if (associated(db(handle)%ioaid)) deallocate(db(handle)%ioaid)
+  allocate(db(handle)%ioaid(glbNpools,ntables,naid))
+  db(handle)%ioaid(:,:,:) = 0
+  if (associated(db(handle)%ciomap)) deallocate(db(handle)%ciomap)
+  if (associated(db(handle)%grpsize)) deallocate(db(handle)%grpsize)
+  if (ODBMP_myproc == 1) then
+    allocate(db(handle)%ciomap(glbNpools))
+    db(handle)%ciomap(:) = ' '
+  endif
+  allocate(db(handle)%grpsize(glbNpools))
+  db(handle)%grpsize(:) = 0
+endif
+db(handle)%naid = naid
+db(handle)%nfileblocks = 0
+
+!-- If running with more processors than no. of pools, it used to fail
+!   Now (26/9/2001) we add some pools and update the db(handle)% -structure
+
+if (ODBMP_nproc > glbNpools) then
+  pool_excess = ODBMP_nproc - npools
+  npools = ODB_addpools(handle, pool_excess)
+endif
+
+maxpoolno = db(handle)%glbMaxpoolno
+
+CALL metaddl_write(handle, iounit)
+
+if (.NOT.db(handle)%newdb) then
+  if (db(handle)%naid > 0) then ! Fill in ioaid-array from iomap-file(s)
+    CALL read_iomap(handle, rc)
+  endif
+
+  if (db(handle)%io_method == 4) then
+!--   Read and message-pass obs. data to other processors
+    CALL util_igetenv('ODB_NEW_MSGPASS', 1, use_new_msgpass)
+    if (use_new_msgpass == 1)then
+      CALL msgpass_loadobs(handle, rc)
+    else
+      CALL msgpass_loaddata(handle, rc)
+    endif
+  endif ! if (db(handle)%io_method == 4) then ...
+endif
+
+if (db(handle)%naid > 0) then
+  if (db(handle)%newdb) then ! have to get started somehow ...
+    if (ODBMP_myproc == 1) then
+      db(handle)%ciomap(1) = trim(db(handle)%name)//'.iomap' ! The default IOMAP-file
+      db(handle)%nfileblocks = 1
+    endif
+    CALL util_igetenv('ODB_IO_GRPSIZE', 0, io_grpsize)
+    if (io_grpsize <= 0) then ! try $NPES_AN
+      CALL util_igetenv('NPES_AN', 0, io_grpsize)
+    endif
+    if (io_grpsize <= 0) io_grpsize = ODBMP_nproc
+    io_grpsize = min(io_grpsize, db(handle)%glbNpools)
+    db(handle)%grpsize(1) = io_grpsize
+    !-- Every PE does the following, since trivial ==> 
+    !   no need for message passing via routine comm_iomap()
+    do j=1,db(handle)%glbNpools
+      db(handle)%ioaid(j,:,IOAID_FBLOCK)  = 1
+      db(handle)%ioaid(j,:,IOAID_GRPSIZE) = io_grpsize
+      db(handle)%ioaid(j,:,IOAID_POOLNO)  = j
+      db(handle)%ioaid(j,:,IOAID_FILENO)  = 0
+      db(handle)%ioaid(j,:,IOAID_OFFSET)  = 0
+      db(handle)%ioaid(j,:,IOAID_LENGTH)  = 0
+      db(handle)%ioaid(j,:,IOAID_NROWS)   = 0
+      db(handle)%ioaid(j,:,IOAID_NCOLS)   = 0
+    enddo
+  endif
+endif
+
+if (ODBMP_myproc == 1) then
+  write(0,*)'END of OPEN_DB'
+endif
+
+rc = db(handle)%locNpools
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:OPEN_DB',1,ZHOOK_HANDLE)
+END SUBROUTINE open_db
+
+
+SUBROUTINE metaddl_write(handle, iounit)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle, iounit
+INTEGER(KIND=JPIM) :: ioddl, rc
+character(len=256) clinfo
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:METADDL_WRITE',0,ZHOOK_HANDLE)
+if (db(handle)%newdb .AND. ODBMP_myproc == 1) then
+  CALL cODB_write_metadata(&
+   &handle, iounit, &
+   &db(handle)%glbNpools,&
+   &db(handle)%CreationDT, db(handle)%AnalysisDT,&
+   &db(handle)%Version_Major, db(handle)%Version_Minor,&
+   &db(handle)%io_method,&
+   &rc)
+  if (rc /= db(handle)%ntables) then
+    CALL ODB_abort('open_db',&
+     &'Unable to write metadata (part#1) for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+    rc = -5
+    goto 99999
+  endif
+  CALL cODB_write_metadata2(&
+   &handle, iounit, &
+   &db(handle)%glbNpools,&
+   &db(handle)%ntables,&
+   &rc)
+  if (rc /= db(handle)%ntables) then
+    CALL ODB_abort('open_db',&
+     &'Unable to write metadata (part#2) for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+    rc = -6
+    goto 99999
+  endif
+  CALL cODB_write_metadata3(handle, iounit, rc)
+  if (rc < 0) then
+    CALL ODB_abort('open_db',&
+     &'Unable to write metadata (part#3) for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+     rc = -7
+     goto 99999
+  endif
+
+  clinfo = trim(db(handle)%name)//'.sch'
+  CALL cma_open(ioddl, clinfo, 'w', rc)
+  if (rc < 0) then
+    CALL ODB_abort('open_db',&
+      &'Unable to open SCHEMA/DDL-file '//trim(db(handle)%name)//'.sch for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+     rc = -8
+     goto 99999
+  endif
+  CALL write_ddl(handle, ioddl, rc)
+  if (rc < 0) then
+    CALL ODB_abort('open_db',&
+      &'Unable to write SCHEMA/DDL-file '//trim(db(handle)%name)//'.sch for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+     rc = -9
+     goto 99999
+  endif
+  CALL cma_close(ioddl, rc)
+  if (rc < 0) then
+    CALL ODB_abort('open_db',&
+      &'Unable to close SCHEMA/DDL-file '//trim(db(handle)%name)//'.sch for DB="'//&
+     &trim(db(handle)%name)//'"',&
+     &rc)
+     rc = -10
+     goto 99999
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:METADDL_WRITE',1,ZHOOK_HANDLE)
+END SUBROUTINE metaddl_write
+
+
+FUNCTION ODB_addpools(handle, pool_excess,old_npools,maxpoolno) RESULT(rc)
+!== Adds more pools on-the-fly
+!   Please make sure NO OUTSTANDING QUERIES are present
+!   i.e. no ODB_select() + ODB_get() processed and ODB_put() being waited
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle, pool_excess
+INTEGER(KIND=JPIM), intent(out), OPTIONAL :: old_npools,maxpoolno
+INTEGER(KIND=JPIM) :: npools, j, npoolidx, ntables, naid, rc
+INTEGER(KIND=JPIM) :: glbNpools, locNpools, excess, is_new, is_readonly
+INTEGER(KIND=JPIM) :: old_glbNpools, old_locNpools, io_grpsize
+INTEGER(KIND=JPIM) :: idim1, idim2, idim3
+INTEGER(KIND=JPIM) :: j1, j2, j3, istart, iadd_vars
+logical ldummy, LL_copied
+INTEGER(KIND=JPIM), allocatable :: tmp2(:,:)
+INTEGER(KIND=JPIM), allocatable :: ioaid(:,:,:)
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_ADDPOOLS',0,ZHOOK_HANDLE)
+
+ldummy = odbHcheck(handle, 'ODB_addpools')
+
+!-- Initialize
+rc = db(handle)%glbNpools
+if (present(old_npools)) old_npools = db(handle)%glbNpools
+if (present(maxpoolno))  maxpoolno = db(handle)%glbMaxpoolno
+
+!== PE#1 rules !!
+if (ODBMP_myproc == 1) then
+  excess = pool_excess
+else
+  excess = 0
+endif
+
+CALL ODBMP_global('SUM',excess) ! Every processor must participate 
+
+if (excess <= 0) goto 99999
+
+if (ODBMP_myproc == 1) then
+  write(0,*) 'ODB_addpools: (handle,dbname)=',handle,trim(db(handle)%name), &
+             ' : adding ',excess,' pools'
+  write(0,*) '              Old no. of global pools = ',db(handle)%glbNpools
+  write(0,*) '              Old global max. poolno = ',db(handle)%glbMaxpoolno
+  write(0,*) '              Old no. of local pools = ',db(handle)%locNpools
+endif
+
+old_glbNpools = db(handle)%glbNpools
+old_locNpools = db(handle)%locNpools
+
+npools = db(handle)%glbNpools + excess
+
+glbNpools = npools
+db(handle)%glbNpools = glbNpools
+if (.NOT.db(handle)%readonly) db(handle)%glbMaxpoolno = glbNpools
+
+npoolidx = 0
+do j=1,npools
+  if (ODBMP_physproc(j) == ODBMP_myproc) npoolidx = npoolidx + 1
+enddo
+
+locNpools = npoolidx
+db(handle)%locNpools = locNpools
+if (associated(db(handle)%poolidx)) deallocate(db(handle)%poolidx)
+allocate(db(handle)%poolidx(locNpools))
+db(handle)%glbNpools = glbNpools
+db(handle)%locNpools = locNpools
+
+npoolidx = 0
+do j=1,glbNpools ! re-create
+  if (ODBMP_physproc(j) == ODBMP_myproc) then
+    npoolidx = npoolidx + 1
+    db(handle)%poolidx(npoolidx) = j
+  endif
+enddo
+
+CALL codb_init_poolmask(handle, db(handle)%name, glbNpools)
+
+ntables = db(handle)%ntables
+
+if (ODBMP_myproc == 1) then
+  write(0,*) 'DataBase-name="'//trim(db(handle)%name)//'" : Situation after ODB_addpools()'
+  write(0,*) 'New no. of global pools = ',db(handle)%glbNpools
+  write(0,*) 'New global max poolno = ',db(handle)%glbMaxpoolno
+  write(0,*) 'New no. of local pools = ',db(handle)%locNpools
+  write(0,*) 'max. no. of rows per pool = ',ODB_MAXROWS
+endif
+
+if (present(maxpoolno))  maxpoolno = db(handle)%glbMaxpoolno
+
+is_readonly = 0
+if (db(handle)%readonly) is_readonly = 1
+
+iadd_vars = 1
+is_new = 1
+do j=old_locNpools+1,locNpools ! ... just for the NEW local pools
+  npoolidx = db(handle)%poolidx(j)
+  if (db(handle)%readonly) then
+    CALL cODB_in_permanent_poolmask(handle, npoolidx, rc)
+  else
+    rc = 1
+  endif
+  if (rc == 1) then ! In R/O-mode initialize only those pools that are in permanent poolmask
+    CALL cODB_create_pool(handle, db(handle)%name, npoolidx, is_new, db(handle)%io_method, iadd_vars, rc)
+    if (rc /= npoolidx) then
+      rc = -(1000 + abs(npoolidx))
+      goto 99999
+    endif
+    iadd_vars = 0
+  endif
+enddo
+
+is_new = 0
+if (db(handle)%newdb) is_new = 1
+
+!- Just update, or if initialization wasn't done before this call, then do it now
+CALL newio_start32(db(handle)%name, &
+                   handle, maxhandle, db(handle)%io_method, &
+                   db(handle)%ntables, is_new, is_readonly, &
+                   db(handle)%glbNpools, db(handle)%locNpools, db(handle)%poolidx, &
+                   rc)
+
+if (rc < 0) then
+  CALL ODB_abort('ODB_addpools(newio_start32)',&
+   &'Error in updating DB-I/O structures="'//&
+   &trim(db(handle)%name)//'"',&
+   &rc)
+  goto 99999
+endif
+
+LL_copied = .FALSE.
+naid = 0
+if (db(handle)%io_method == 4) then
+  naid = IONAID
+  glbNpools = db(handle)%glbNpools
+  LL_copied = associated(db(handle)%ioaid)
+  if (LL_copied) then ! copy
+    idim1 = size(db(handle)%ioaid, dim=1)
+    idim2 = size(db(handle)%ioaid, dim=2)
+    idim3 = size(db(handle)%ioaid, dim=3)
+    allocate(ioaid(idim1, idim2, idim3))
+    ioaid(:,:,:) = db(handle)%ioaid(:,:,:)
+    deallocate(db(handle)%ioaid)
+    allocate(db(handle)%ioaid(glbNpools,ntables,naid)) ! new allocation
+    db(handle)%ioaid(:,:,:) = 0
+    do j3=1,min(idim3,naid)
+      do j2=1,min(idim2,ntables)
+        do j1=1,min(idim1,glbNpools)
+          db(handle)%ioaid(j1,j2,j3) = ioaid(j1,j2,j3)
+        enddo
+      enddo
+    enddo
+    deallocate(ioaid)
+  else
+    allocate(db(handle)%ioaid(glbNpools,ntables,naid))
+    db(handle)%ioaid(:,:,:) = 0
+  endif
+  if (.not.LL_copied) then
+    if (associated(db(handle)%ciomap)) deallocate(db(handle)%ciomap)
+    if (associated(db(handle)%grpsize)) deallocate(db(handle)%grpsize)
+    if (ODBMP_myproc == 1) then
+      allocate(db(handle)%ciomap(glbNpools))
+      db(handle)%ciomap(:) = ' '
+    endif
+    allocate(db(handle)%grpsize(glbNpools))
+    db(handle)%grpsize(:) = 0
+  endif
+endif
+db(handle)%naid = naid
+if (.not.LL_copied) db(handle)%nfileblocks = 0
+
+if (db(handle)%naid > 0) then ! have to get started somehow ...
+  if (db(handle)%newdb) then
+    if (ODBMP_myproc == 1) then
+      db(handle)%ciomap(1) = trim(db(handle)%name)//'.iomap' ! The default IOMAP-file
+      db(handle)%nfileblocks = 1
+    endif
+    CALL util_igetenv('ODB_IO_GRPSIZE', 0, io_grpsize)
+    if (io_grpsize <= 0) then ! try $NPES_AN
+      CALL util_igetenv('NPES_AN', 0, io_grpsize)
+    endif
+    if (io_grpsize <= 0) io_grpsize = ODBMP_nproc
+    db(handle)%grpsize(1) = io_grpsize
+    io_grpsize = min(io_grpsize, db(handle)%glbNpools)
+  endif
+  !-- Every PE does the following, since trivial ==> 
+  !   no need for message passing via routine comm_iomap()
+  istart = 1
+  if (LL_copied .and. .not.db(handle)%newdb) istart = old_glbNpools+1
+  do j=istart,db(handle)%glbNpools
+    db(handle)%ioaid(j,:,IOAID_FBLOCK)  = 1
+    db(handle)%ioaid(j,:,IOAID_GRPSIZE) = io_grpsize
+    db(handle)%ioaid(j,:,IOAID_POOLNO)  = j
+    db(handle)%ioaid(j,:,IOAID_FILENO)  = 0
+    db(handle)%ioaid(j,:,IOAID_OFFSET)  = 0
+    db(handle)%ioaid(j,:,IOAID_LENGTH)  = 0
+    db(handle)%ioaid(j,:,IOAID_NROWS)   = 0
+    db(handle)%ioaid(j,:,IOAID_NCOLS)   = 0
+  enddo
+endif
+
+rc = npools
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_ADDPOOLS',1,ZHOOK_HANDLE)
+END FUNCTION ODB_addpools
+
+
+FUNCTION ODB_pack(handle, dtname, poolno) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+INTEGER(KIND=JPIM) :: rc, ipoolno, ipack
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_PACK',0,ZHOOK_HANDLE)
+rc = 0
+ipack = 1
+if (odbHcheck(handle, 'ODB_pack')) then
+  ipoolno = get_poolno(handle, poolno)
+  ipack = 1
+  CALL cODB_packer(handle, ipoolno, ctrim(dtname), ipack, rc)
+  if (rc < 0) then
+    CALL ODB_abort('ODB_packer',&
+     &'Cannot pack TABLE="'//trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_PACK',1,ZHOOK_HANDLE)
+END FUNCTION ODB_pack
+
+
+FUNCTION ODB_unpack(handle, dtname, poolno) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+INTEGER(KIND=JPIM) :: rc, ipoolno, ipack
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_UNPACK',0,ZHOOK_HANDLE)
+rc = 0
+if (odbHcheck(handle, 'ODB_unpack')) then
+  ipoolno = get_poolno(handle, poolno)
+  ipack = 0
+  CALL cODB_packer(handle, ipoolno, ctrim(dtname), ipack, rc)
+  if (rc < 0) then
+    CALL ODB_abort('ODB_packer',&
+     &'Cannot unpack TABLE="'//trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_UNPACK',1,ZHOOK_HANDLE)
+END FUNCTION ODB_unpack
+
+
+
+FUNCTION ODB_release(handle, poolno, delete_intermed) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+logical, intent(in), optional :: delete_intermed
+INTEGER(KIND=JPIM) :: rc, ipoolno, glbNpools, j
+INTEGER(KIND=JPIM) :: fast_physproc, xfast
+REAL(KIND=JPRB) ZHOOK_HANDLE
+fast_physproc(xfast) = mod(xfast-1,ODBMP_nproc)+1
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_RELEASE',0,ZHOOK_HANDLE)
+rc = 0
+if (odbHcheck(handle, 'ODB_release')) then
+  !-- play safe and allow this routine for READONLY databases only
+  if (db(handle)%readonly) then
+    ipoolno = get_poolno(handle, poolno)
+    rc = ODB_swapout(handle, '*', poolno=ipoolno, save=.FALSE., delete_intermed=delete_intermed)
+    if (ipoolno == -1) then
+      glbNpools = db(handle)%glbNpools
+      do j=1,glbNpools
+        if (fast_physproc(j) == ODBMP_myproc) then
+          ipoolno = j
+          CALL newio_release_pool32(handle, ipoolno, rc)
+        endif
+      enddo
+    else
+      CALL newio_release_pool32(handle, ipoolno, rc)
+    endif
+  endif ! if (db(handle)%readonly) ...
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_RELEASE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_release
+
+#ifndef USE_CTRIM
+#undef ctrim
+#undef CTRIM
+#endif
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odb
diff --git a/odb/src/module/odb_module.F90 b/odb/src/module/odb_module.F90
new file mode 100644
index 0000000..d06ab66
--- /dev/null
+++ b/odb/src/module/odb_module.F90
@@ -0,0 +1,22 @@
+MODULE odb_module
+
+USE PARKIND1  ,ONLY : JPIM, JPRB, JPRD
+
+!
+! Interface to ODB
+!
+! Author: Sami Saarinen, ECMWF, 27-Sep-2000
+! Last updated: 03-Jan-2008 by SS
+!
+
+USE ODB
+USE ODBGETPUT
+USE ODBUTIL
+USE ODBSHARED
+USE ODBMP
+USE ODBSORT
+USE ODBIOMAP
+USE ODBPRINT
+USE ODBSTAT
+
+END MODULE odb_module
diff --git a/odb/src/module/odb_module8.F90 b/odb/src/module/odb_module8.F90
new file mode 100644
index 0000000..8cfdddf
--- /dev/null
+++ b/odb/src/module/odb_module8.F90
@@ -0,0 +1,4484 @@
+!
+! Wrapper functions for 8-byte-word implementation
+! See original ODB_...() for inline documentation of arguments/variables
+!
+Module ODB_MODULE8
+#ifdef USE_8_BYTE_WORDS
+
+Use PARKIND1, Only : JPIM, JPRB, JPRM
+
+Implicit NONE
+
+Public
+
+INTERFACE ODB_map_vpools
+MODULE PROCEDURE &
+  & ODB_map_vpools_direct, &
+  & ODB_map_vpools_fromfile
+END INTERFACE
+
+INTERFACE ODB_distribute
+MODULE PROCEDURE &
+  & ODB_distribute_str, ODB_distribute_vecstr, &
+  & ODB_distribute_int, ODB_distribute_vecint, &
+  & ODB_distribute_real8, ODB_distribute_vecreal8
+END INTERFACE
+
+INTERFACE ODB_setval
+MODULE PROCEDURE &
+  & ODB_dsetval, ODB_isetval
+END INTERFACE
+
+INTERFACE ODB_duplchk
+MODULE PROCEDURE &
+  & ODB_iduplchk, ODB_dduplchk
+END INTERFACE
+
+INTERFACE ODB_groupify
+MODULE PROCEDURE &
+  & ODB_igroupify!, ODB_dgroupify
+END INTERFACE
+
+INTERFACE ODB_tolsearch
+MODULE PROCEDURE &
+  & ODB_itolsearch, ODB_dtolsearch
+END INTERFACE
+
+INTERFACE ODB_binsearch
+MODULE PROCEDURE &
+  & ODB_ibinsearch, ODB_dbinsearch
+END INTERFACE
+
+INTERFACE ODB_aggregate
+MODULE PROCEDURE &
+  & ODB_iaggregate, ODB_daggregate
+END INTERFACE
+
+INTERFACE ODB_control_word_info
+MODULE PROCEDURE &
+  & ODB_control_word_info_vector, ODB_control_word_info_matrix
+END INTERFACE
+
+!INTERFACE ODBMP_global
+!MODULE PROCEDURE &
+!     &ODBMP_iglobal!       , ODBMP_dglobal       , &
+!     &ODBMP_iglobal_2d    , ODBMP_dglobal_2d    , &
+!     &ODBMP_iglobal_3d    , ODBMP_dglobal_3d    , &
+!     &ODBMP_iglobal_scalar, ODBMP_dglobal_scalar
+!END INTERFACE
+
+!private ODBMP_iglobal
+!private ODBMP_dglobal
+!private ODBMP_iglobal_2d
+!private ODBMP_dglobal_2d
+!private ODBMP_iglobal_3d
+!private ODBMP_dglobal_3d
+!private ODBMP_iglobal_scalar
+!private ODBMP_dglobal_scalar
+
+private :: ODB_distribute_str
+private :: ODB_distribute_vecstr
+private :: ODB_distribute_int
+private :: ODB_distribute_vecint
+private :: ODB_distribute_real8
+private :: ODB_distribute_vecreal8
+private :: ODB_dsetval
+private :: ODB_isetval
+private :: ODB_iduplchk
+private :: ODB_dduplchk
+private :: ODB_igroupify
+private :: ODB_dgroupify
+private :: ODB_itolsearch
+private :: ODB_dtolsearch
+private :: ODB_ibinsearch
+private :: ODB_dbinsearch
+private :: ODB_iaggregate
+private :: ODB_daggregate
+private :: ODB_control_word_info_vector
+private :: ODB_control_word_info_matrix
+
+Contains
+
+!
+! ODB_open ============================================================
+!
+Integer(Kind=8) Function ODB_open(DBNAME, STATUS, NPOOLS, OLD_NPOOLS, &
+                                  MAXPOOLNO)
+
+  Use odb_module, only : ODB_open4 => ODB_open
+
+  Character(Len=*), Intent(IN) :: DBNAME, STATUS
+  Integer(Kind=8), Intent(INOUT) :: NPOOLS
+  Integer(Kind=8), Intent(OUT), Optional :: OLD_NPOOLS, MAXPOOLNO
+
+  Integer(Kind=JPIM) :: HANDLE4 = 0, NPOOLS4, OLD_NPOOLS4, MAXPOOLNO4
+
+  integer :: o=0,o1=0,o2=0
+
+  if (present(old_npools)) o1=1
+  if (present(maxpoolno)) o2=2
+  o=o1+o2
+
+  NPOOLS4 = NPOOLS
+
+  select case(o)
+  case(0)
+     HANDLE4=ODB_open4(dbname, status, npools4)
+  case(1)
+     HANDLE4=ODB_open4(dbname, status, npools4, old_npools=old_npools4)
+  case(2)
+     HANDLE4=ODB_open4(dbname, status, npools4, maxpoolno=maxpoolno4)
+  case(3)
+     HANDLE4=ODB_open4(dbname, status, npools4, old_npools=old_npools4, maxpoolno=maxpoolno4)
+  end select
+
+  NPOOLS = NPOOLS4
+  If (PRESENT(OLD_NPOOLS)) OLD_NPOOLS = OLD_NPOOLS4
+  If (PRESENT(MAXPOOLNO))  MAXPOOLNO  = MAXPOOLNO4
+  ODB_open = HANDLE4
+
+End Function ODB_open
+
+!
+! ODB_init ============================================================
+!
+Integer(Kind=8) Function ODB_init(myproc, nproc, pid, tid, ntid)
+
+  Use odb_module, only : ODB_init4 => ODB_init
+
+  Integer(Kind=8), Intent(OUT), Optional :: myproc, nproc, pid, tid, ntid
+
+  Integer(Kind=JPIM) :: myproc4 = -1, nproc4 = -1, pid4 = -1,          &
+                        tid4 = -1, ntid4 = -1, RC4 = 0
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0,o5=0
+
+  if (present(myproc)) o1=1
+  if (present(nproc)) o2=2
+  if (present(pid)) o3=4
+  if (present(tid)) o4=8
+  if (present(ntid)) o5=16
+  o=o1+o2+o3+o4+o5
+
+  select case(o)
+  case(0)
+     RC4=ODB_init4()
+  case(1)
+     RC4=ODB_init4(myproc=myproc4)
+  case(2)
+     RC4=ODB_init4(nproc=nproc4)
+  case(3)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4)
+  case(4)
+     RC4=ODB_init4(pid=pid4)
+  case(5)
+     RC4=ODB_init4(myproc=myproc4, pid=pid4)
+  case(6)
+     RC4=ODB_init4(nproc=nproc4, pid=pid4)
+  case(7)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, pid=pid4)
+  case(8)
+     RC4=ODB_init4(tid=tid4)
+  case(9)
+     RC4=ODB_init4(myproc=myproc4, tid=tid4)
+  case(10)
+     RC4=ODB_init4(nproc=nproc4, tid=tid4)
+  case(11)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, tid=tid4)
+  case(12)
+     RC4=ODB_init4(pid=pid4, tid=tid4)
+  case(13)
+     RC4=ODB_init4(myproc=myproc4, pid=pid4, tid=tid4)
+  case(14)
+     RC4=ODB_init4(nproc=nproc4, pid=pid4, tid=tid4)
+  case(15)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, pid=pid4, tid=tid4)
+  case(16)
+     RC4=ODB_init4(ntid=ntid4)
+  case(17)
+     RC4=ODB_init4(myproc=myproc4, ntid=ntid4)
+  case(18)
+     RC4=ODB_init4(nproc=nproc4, ntid=ntid4)
+  case(19)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, ntid=ntid4)
+  case(20)
+     RC4=ODB_init4(pid=pid4, ntid=ntid4)
+  case(21)
+     RC4=ODB_init4(myproc=myproc4, pid=pid4, ntid=ntid4)
+  case(22)
+     RC4=ODB_init4(nproc=nproc4, pid=pid4, ntid=ntid4)
+  case(23)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, pid=pid4, ntid=ntid4)
+  case(24)
+     RC4=ODB_init4(tid=tid4, ntid=ntid4)
+  case(25)
+     RC4=ODB_init4(myproc=myproc4, tid=tid4, ntid=ntid4)
+  case(26)
+     RC4=ODB_init4(nproc=nproc4, tid=tid4, ntid=ntid4)
+  case(27)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, tid=tid4, ntid=ntid4)
+  case(28)
+     RC4=ODB_init4(pid=pid4, tid=tid4, ntid=ntid4)
+  case(29)
+     RC4=ODB_init4(myproc=myproc4, pid=pid4, tid=tid4, ntid=ntid4)
+  case(30)
+     RC4=ODB_init4(nproc=nproc4, pid=pid4, tid=tid4, ntid=ntid4)
+  case(31)
+     RC4=ODB_init4(myproc=myproc4, nproc=nproc4, pid=pid4, tid=tid4, ntid=ntid4)
+  end select
+
+  If (PRESENT(myproc)) myproc = myproc4
+  If (PRESENT(nproc))  nproc  = nproc4
+  If (PRESENT(pid))    pid    = pid4
+  If (PRESENT(tid))    tid    = tid4
+  If (PRESENT(ntid))   ntid   = ntid4
+  ODB_init = RC4
+
+End Function ODB_init
+
+!
+! ODB_addview =========================================================
+!
+Integer(Kind=8) Function ODB_addview(HANDLE, DTNAME, VIEWFILE, SELECT, &
+                                     UNIQUEBY, FROM, WHERE, ORDERBY,   &
+                                     SORTBY, QUERY, SET, ABORT)
+
+  Use odb_module, only : ODB_addview4 => ODB_addview
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME
+  Character(Len=*), Intent(IN), Optional :: VIEWFILE, SELECT, UNIQUEBY,&
+                                            FROM, WHERE, ORDERBY,      &
+                                            SORTBY, QUERY
+  Character(Len=*), Dimension(:), Intent(IN), Optional :: SET
+  Logical(Kind=8), Intent(IN), Optional :: ABORT
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0
+  Logical(Kind=JPIM) :: ABORT4 = .FALSE.
+
+  integer :: o=0,o1=0
+
+  if (present(abort)) o1=1
+  o=o1
+
+  HANDLE4 = HANDLE
+  If (PRESENT(ABORT)) ABORT4 = ABORT
+
+  select case(o)
+  case(0)
+     RC4=ODB_addview4(handle4, dtname, viewfile, select, uniqueby, from, where, orderby, sortby, query, set)
+  case(1)
+     RC4=ODB_addview4(handle4, dtname, viewfile, select, uniqueby, from, where, orderby, sortby, query, set, &
+                      abort=abort4)
+  end select
+
+  ODB_addview = RC4
+
+End Function ODB_addview
+
+!
+! ODB_select ==========================================================
+!
+Integer(Kind=8) Function ODB_select(HANDLE, DTNAME, NROWS, NCOLS, NRA, &
+                                    POOLNO, SETVARS, VALUES, PEVAR,    &
+                                    REPLICATE_PE, SYNC, NPES_OVERRIDE)
+
+  Use odb_module, only : ODB_select4 => ODB_select
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME
+  Integer(Kind=8), Intent(OUT) :: NROWS, NCOLS
+  Integer(Kind=8), Intent(OUT), Optional :: NRA
+  Integer(Kind=8), Intent(IN), Optional :: POOLNO, REPLICATE_PE,       &
+                                           NPES_OVERRIDE
+  Character(Len=*), Dimension(:), Intent(IN), Optional :: SETVARS
+  Real(Kind=8), Dimension(:), Intent(IN), Optional :: VALUES
+  Character(Len=*), Intent(IN), Optional :: PEVAR
+  Logical(Kind=8), Intent(IN), Optional :: SYNC
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0, NROWS4, NCOLS4, NRA4,        &
+                        POOLNO4 = -1, REPLICATE_PE4 = -1,              &
+                        NPES_OVERRIDE4 = -1
+  Logical(Kind=JPIM) :: SYNC4 = .FALSE.
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0,o5=0
+
+  if (present(nra)) o1=1
+  if (present(poolno)) o2=2
+  if (present(replicate_pe)) o3=4
+  if (present(sync)) o4=8
+  if (present(npes_override)) o5=16
+  o=o1+o2+o3+o4+o5
+
+  HANDLE4 = HANDLE
+  If (PRESENT(POOLNO))        POOLNO4        = POOLNO
+  If (PRESENT(REPLICATE_PE))  REPLICATE_PE4  = REPLICATE_PE
+  If (PRESENT(NPES_OVERRIDE)) NPES_OVERRIDE4 = NPES_OVERRIDE
+  If (PRESENT(SYNC))          SYNC4          = SYNC
+
+  select case(o)
+  case(0)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar)
+  case(1)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4)
+  case(2)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4)
+  case(3)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4)
+  case(4)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     replicate_pe=replicate_pe4)
+  case(5)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, replicate_pe=replicate_pe4)
+  case(6)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, replicate_pe=replicate_pe4)
+  case(7)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, replicate_pe=replicate_pe4)
+  case(8)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     sync=sync4)
+  case(9)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, sync=sync4)
+  case(10)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, sync=sync4)
+  case(11)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, sync=sync4)
+  case(12)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     replicate_pe=replicate_pe4, sync=sync4)
+  case(13)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, replicate_pe=replicate_pe4, sync=sync4)
+  case(14)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, replicate_pe=replicate_pe4, sync=sync4)
+  case(15)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, replicate_pe=replicate_pe4, sync=sync4)
+  case(16)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     npes_override=npes_override4)
+  case(17)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, npes_override=npes_override4)
+  case(18)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, npes_override=npes_override4)
+  case(19)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, npes_override=npes_override4)
+  case(20)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     replicate_pe=replicate_pe4, npes_override=npes_override4)
+  case(21)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, replicate_pe=replicate_pe4, npes_override=npes_override4)
+  case(22)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, replicate_pe=replicate_pe4, npes_override=npes_override4)
+  case(23)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, replicate_pe=replicate_pe4, npes_override=npes_override4)
+  case(24)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     sync=sync4, npes_override=npes_override4)
+  case(25)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, sync=sync4, npes_override=npes_override4)
+  case(26)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, sync=sync4, npes_override=npes_override4)
+  case(27)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, sync=sync4, npes_override=npes_override4)
+  case(28)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     replicate_pe=replicate_pe4, sync=sync4, npes_override=npes_override4)
+  case(29)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, replicate_pe=replicate_pe4, sync=sync4, npes_override=npes_override4)
+  case(30)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     poolno=poolno4, replicate_pe=replicate_pe4, sync=sync4, npes_override=npes_override4)
+  case(31)
+     RC4=ODB_select4(handle4, dtname, nrows4, ncols4, setvars=setvars, values=values, pevar=pevar, &
+                     nra=nra4, poolno=poolno4, replicate_pe=replicate_pe4, sync=sync4, npes_override=npes_override4)
+  end select
+
+  NROWS = NROWS4
+  NCOLS = NCOLS4
+  IF (PRESENT(NRA)) NRA = NRA4
+  ODB_select = RC4
+
+End Function ODB_select
+
+!
+! ODB_release ==========================================================
+!
+Integer(Kind=8) Function ODB_release(HANDLE, POOLNO)
+
+  Use odb_module, only : ODB_release4 => ODB_release
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Integer(Kind=8), Intent(IN), Optional :: POOLNO
+
+  Integer(Kind=JPIM) :: HANDLE4 = 0, POOLNO4 = -1, RC4 = 0
+
+  integer :: o=0,o1=0
+
+  if (present(poolno)) o1=1
+  o=o1
+
+  HANDLE4 = HANDLE
+  If (PRESENT(POOLNO)) POOLNO4 = POOLNO
+
+  select case(o)
+  case(0)
+     RC4=ODB_release4(handle4)
+  case(1)
+     RC4=ODB_release4(handle4, poolno=poolno4)
+  end select
+
+  ODB_release = RC4
+
+End Function ODB_release
+
+Subroutine ODB_getindices(handle, view, table, nrows, ncols, nstart_pos, poolno, indices)
+
+  Use odb_module, only : ODB_getindices4 => ODB_getindices
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: view, table
+  INTEGER(KIND=8), intent(out)           :: nrows, ncols
+  INTEGER(KIND=8), intent(in)            :: nstart_pos
+  INTEGER(KIND=8), intent(in)            :: poolno
+  INTEGER(KIND=8), intent(out), OPTIONAL :: indices(:,:)
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM)              :: nrows4, ncols4
+  INTEGER(KIND=JPIM)              :: nstart_pos4
+  INTEGER(KIND=JPIM)              :: poolno4
+  INTEGER(KIND=JPIM) ,allocatable :: indices4(:,:)
+
+  integer :: o=0,o1=0
+
+  handle4 = handle4
+  nstart_pos4 = nstart_pos
+  poolno4 = poolno
+  if (present(indices)) allocate(indices4(size(indices,1),size(indices,2)))
+
+  if (present(indices)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     call ODB_getindices4(handle4, view, table, nrows4, ncols4, nstart_pos4, poolno4)
+  case(1)
+     call ODB_getindices4(handle4, view, table, nrows4, ncols4, nstart_pos4, poolno4, indices=indices4)
+  end select
+
+  nrows = nrows4
+  ncols = ncols4
+  if (present(indices)) then
+    indices = indices4
+    deallocate(indices4)
+  endif
+
+End Subroutine ODB_getindices
+
+Subroutine ODB_putindices(handle, view, table, nrows, ncols, nstart_pos, poolno, indices)
+
+  Use odb_module, only : ODB_putindices4 => ODB_putindices
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: view, table
+  INTEGER(KIND=8), intent(in)            :: nrows, ncols
+  INTEGER(KIND=8), intent(in)            :: nstart_pos
+  INTEGER(KIND=8), intent(in)            :: poolno
+  INTEGER(KIND=8), intent(in)            :: indices(:,:)
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM)              :: nrows4, ncols4
+  INTEGER(KIND=JPIM)              :: nstart_pos4
+  INTEGER(KIND=JPIM)              :: poolno4
+  INTEGER(KIND=JPIM) ,allocatable :: indices4(:,:)
+
+  handle4 = handle4
+  nrows4 = nrows
+  ncols4 = ncols4
+  nstart_pos4 = nstart_pos
+  poolno4 = poolno
+  allocate(indices4(size(indices,1),size(indices,2)))
+  indices4 = indices
+
+  call ODB_putindices4(handle4, view, table, nrows4, ncols4, nstart_pos4, poolno4, indices=indices4)
+
+  deallocate(indices4)
+
+End Subroutine ODB_putindices
+
+!
+! ODB_close ===========================================================
+!
+Integer(Kind=8) Function ODB_close(HANDLE, SAVE)
+
+  Use odb_module, only : ODB_close4 => ODB_close
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Logical(Kind=8), Intent(IN), Optional :: SAVE
+
+  Integer(Kind=JPIM) :: HANDLE4 = 0, RC4
+  Logical(Kind=JPIM) :: SAVE4
+
+  integer :: o=0,o1=0
+
+  if (present(save)) o1=1
+  o=o1
+
+  HANDLE4 = HANDLE
+  If (PRESENT(SAVE)) Then
+    SAVE4 = SAVE
+  Else
+    SAVE4 = .FALSE.
+  End If
+
+  select case(o)
+  case(0)
+     RC4=ODB_close4(handle4)
+  case(1)
+     RC4=ODB_close4(handle4, save=save4)
+  end select
+
+  ODB_close = RC4
+
+End Function ODB_close
+
+! =====================================================================
+! wrapper functions for odbgetput.F90
+! =====================================================================
+
+!
+! ODB_get =============================================================
+!
+Integer(Kind=8) Function ODB_get(HANDLE, DTNAME, D, NROWS, NCOLS,      &
+                                 POOLNO, COLGET, COLPACK, COLFREE,     &
+                                 INDEX, SORTED, OFFSET, START, LIMIT)
+
+  Use odb_module, only : ODB_get4 => ODB_get
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME
+  Real(Kind=8), Intent(OUT) :: D(:,0:)
+  Integer(Kind=8), Intent(INOUT) :: NROWS
+  Integer(Kind=8), Intent(INOUT), Optional :: NCOLS
+  Integer(Kind=8), Intent(IN), Optional :: POOLNO, OFFSET, START, LIMIT
+  Logical(Kind=8), Dimension(:), Intent(IN), Optional ::               &
+    COLGET, COLPACK, COLFREE
+  Integer(Kind=8), Dimension(:), Intent(OUT), Optional :: INDEX
+  Logical(Kind=8), Intent(IN), Optional :: SORTED
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0, NROWS4, NCOLS4 = -1,         &
+                        POOLNO4 = -1, OFFSET4 = -1, START4 = -1,       &
+                        LIMIT4 = -1
+  Logical(Kind=JPIM), Dimension(:), Allocatable ::                     &
+    COLGET4, COLPACK4, COLFREE4
+  Integer(Kind=JPIM), Dimension(:), Allocatable :: INDEX4
+  Logical(Kind=JPIM) :: SORTED4 = .FALSE.
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0,o5=0,o6=0,o7=0,o8=0,o9=0
+
+  if (present(poolno)) o1=1
+  if (present(colget)) o2=2
+  if (present(colpack)) o3=4
+  if (present(colfree)) o4=8
+  if (present(index)) o5=16
+  if (present(sorted)) o6=32
+  if (present(offset)) o7=64
+  if (present(start)) o8=128
+  if (present(limit)) o9=256
+  o=o1+o2+o3+o4+o5+o6+o7+o8+o9
+
+  HANDLE4 = HANDLE
+  NROWS4 = NROWS
+  If (PRESENT(NCOLS))  NCOLS4  = NCOLS
+  If (PRESENT(POOLNO)) POOLNO4 = POOLNO
+  If (PRESENT(OFFSET)) OFFSET4 = OFFSET
+  If (PRESENT(START))  START4  = START
+  If (PRESENT(LIMIT))  LIMIT4  = LIMIT
+  If (PRESENT(SORTED)) SORTED4 = SORTED
+  If (PRESENT(COLGET)) Then
+    Allocate(COLGET4(SIZE(COLGET)))
+    COLGET4 = COLGET
+  End If
+  If (PRESENT(COLPACK)) Then
+    Allocate(COLPACK4(SIZE(COLPACK)))
+    COLPACK4 = COLPACK
+  End If
+  If (PRESENT(COLFREE)) Then
+    Allocate(COLFREE4(SIZE(COLFREE)))
+    COLFREE4 = COLFREE
+  End If
+  If (PRESENT(INDEX)) Then
+    Allocate(INDEX4(SIZE(INDEX)))
+  End If
+
+  select case(o)
+  case(0)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4)
+  case(1)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4)
+  case(2)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4)
+  case(3)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4)
+  case(4)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4)
+  case(5)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4)
+  case(6)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4)
+  case(7)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4)
+  case(8)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4)
+  case(9)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4)
+  case(10)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4)
+  case(11)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4)
+  case(12)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4)
+  case(13)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4)
+  case(14)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4)
+  case(15)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4)
+  case(16)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4)
+  case(17)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4)
+  case(18)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4)
+  case(19)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4)
+  case(20)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4)
+  case(21)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4)
+  case(22)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4)
+  case(23)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4)
+  case(24)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4)
+  case(25)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4)
+  case(26)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4)
+  case(27)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4)
+  case(28)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4)
+  case(29)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4)
+  case(30)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4)
+  case(31)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4)
+  case(32)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4)
+  case(33)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4)
+  case(34)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4)
+  case(35)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4)
+  case(36)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4)
+  case(37)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4)
+  case(38)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4)
+  case(39)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4)
+  case(40)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4)
+  case(41)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4)
+  case(42)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4)
+  case(43)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4)
+  case(44)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4)
+  case(45)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, sorted=sorted4)
+  case(46)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, sorted=sorted4)
+  case(47)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, sorted=sorted4)
+  case(48)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4)
+  case(49)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4)
+  case(50)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4)
+  case(51)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4)
+  case(52)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4)
+  case(53)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4)
+  case(54)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4)
+  case(55)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  index=index4, sorted=sorted4)
+  case(56)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4)
+  case(57)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4)
+  case(58)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4)
+  case(59)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, &
+                  index=index4, sorted=sorted4)
+  case(60)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, sorted=sorted4)
+  case(61)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4)
+  case(62)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4)
+  case(63)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, sorted=sorted4)
+  case(64)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, offset=offset4)
+  case(65)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, offset=offset4)
+  case(66)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, offset=offset4)
+  case(67)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, offset=offset4)
+  case(68)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, offset=offset4)
+  case(69)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, offset=offset4)
+  case(70)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, offset=offset4)
+  case(71)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, offset=offset4)
+  case(72)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, offset=offset4)
+  case(73)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, offset=offset4)
+  case(74)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, offset=offset4)
+  case(75)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, offset=offset4)
+  case(76)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, offset=offset4)
+  case(77)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, offset=offset4)
+  case(78)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, offset=offset4)
+  case(79)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, offset=offset4)
+  case(80)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, offset=offset4)
+  case(81)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, offset=offset4)
+  case(82)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, offset=offset4)
+  case(83)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, offset=offset4)
+  case(84)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, offset=offset4)
+  case(85)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, offset=offset4)
+  case(86)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, offset=offset4)
+  case(87)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  index=index4, offset=offset4)
+  case(88)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, offset=offset4)
+  case(89)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, offset=offset4)
+  case(90)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, offset=offset4)
+  case(91)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, &
+                  index=index4, offset=offset4)
+  case(92)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, offset=offset4)
+  case(93)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4)
+  case(94)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4)
+  case(95)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, offset=offset4)
+  case(96)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, offset=offset4)
+  case(97)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, offset=offset4)
+  case(98)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, offset=offset4)
+  case(99)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, offset=offset4)
+  case(100)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(101)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(102)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(103)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  sorted=sorted4, offset=offset4)
+  case(104)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, offset=offset4)
+  case(105)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, offset=offset4)
+  case(106)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, offset=offset4)
+  case(107)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4)
+  case(108)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, offset=offset4)
+  case(109)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4)
+  case(110)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4)
+  case(111)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, sorted=sorted4, offset=offset4)
+  case(112)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, offset=offset4)
+  case(113)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, offset=offset4)
+  case(114)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, offset=offset4)
+  case(115)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  offset=offset4)
+  case(116)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, offset=offset4)
+  case(117)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4)
+  case(118)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4)
+  case(119)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, offset=offset4)
+  case(120)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, offset=offset4)
+  case(121)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4)
+  case(122)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4)
+  case(123)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4)
+  case(124)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4)
+  case(125)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4)
+  case(126)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4)
+  case(127)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, sorted=sorted4, offset=offset4)
+  case(128)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, start=start4)
+  case(129)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, start=start4)
+  case(130)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, start=start4)
+  case(131)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, start=start4)
+  case(132)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, start=start4)
+  case(133)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, start=start4)
+  case(134)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, start=start4)
+  case(135)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, start=start4)
+  case(136)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, start=start4)
+  case(137)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, start=start4)
+  case(138)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, start=start4)
+  case(139)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, start=start4)
+  case(140)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, start=start4)
+  case(141)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, start=start4)
+  case(142)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, start=start4)
+  case(143)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, start=start4)
+  case(144)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, start=start4)
+  case(145)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, start=start4)
+  case(146)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, start=start4)
+  case(147)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, start=start4)
+  case(148)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, start=start4)
+  case(149)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, start=start4)
+  case(150)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, start=start4)
+  case(151)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  start=start4)
+  case(152)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, start=start4)
+  case(153)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, start=start4)
+  case(154)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, start=start4)
+  case(155)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  start=start4)
+  case(156)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, start=start4)
+  case(157)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, start=start4)
+  case(158)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, start=start4)
+  case(159)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, start=start4)
+  case(160)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, start=start4)
+  case(161)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, start=start4)
+  case(162)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, start=start4)
+  case(163)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, start=start4)
+  case(164)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, start=start4)
+  case(165)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, start=start4)
+  case(166)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, start=start4)
+  case(167)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  sorted=sorted4, start=start4)
+  case(168)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, start=start4)
+  case(169)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, start=start4)
+  case(170)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, start=start4)
+  case(171)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, &
+                  sorted=sorted4, start=start4)
+  case(172)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, start=start4)
+  case(173)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, start=start4)
+  case(174)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, start=start4)
+  case(175)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, sorted=sorted4, start=start4)
+  case(176)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, start=start4)
+  case(177)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, start=start4)
+  case(178)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, start=start4)
+  case(179)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  start=start4)
+  case(180)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, start=start4)
+  case(181)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  start=start4)
+  case(182)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  start=start4)
+  case(183)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, start=start4)
+  case(184)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, start=start4)
+  case(185)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  start=start4)
+  case(186)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  start=start4)
+  case(187)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, start=start4)
+  case(188)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, start=start4)
+  case(189)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, start=start4)
+  case(190)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, start=start4)
+  case(191)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, sorted=sorted4, start=start4)
+  case(192)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, offset=offset4, start=start4)
+  case(193)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, offset=offset4, start=start4)
+  case(194)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, offset=offset4, start=start4)
+  case(195)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, offset=offset4, start=start4)
+  case(196)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, offset=offset4, start=start4)
+  case(197)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, offset=offset4, start=start4)
+  case(198)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, offset=offset4, start=start4)
+  case(199)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  offset=offset4, start=start4)
+  case(200)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, offset=offset4, start=start4)
+  case(201)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, offset=offset4, start=start4)
+  case(202)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, offset=offset4, start=start4)
+  case(203)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, &
+                  offset=offset4, start=start4)
+  case(204)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, offset=offset4, start=start4)
+  case(205)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  offset=offset4, start=start4)
+  case(206)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  offset=offset4, start=start4)
+  case(207)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, offset=offset4, start=start4)
+  case(208)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, offset=offset4, start=start4)
+  case(209)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, offset=offset4, start=start4)
+  case(210)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, offset=offset4, start=start4)
+  case(211)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, offset=offset4, &
+                  start=start4)
+  case(212)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, offset=offset4, start=start4)
+  case(213)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, offset=offset4, &
+                  start=start4)
+  case(214)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, offset=offset4, &
+                  start=start4)
+  case(215)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  offset=offset4, start=start4)
+  case(216)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, offset=offset4, start=start4)
+  case(217)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, offset=offset4, &
+                  start=start4)
+  case(218)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, offset=offset4, &
+                  start=start4)
+  case(219)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  offset=offset4, start=start4)
+  case(220)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  offset=offset4, start=start4)
+  case(221)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4, start=start4)
+  case(222)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4, start=start4)
+  case(223)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, offset=offset4, start=start4)
+  case(224)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, offset=offset4, start=start4)
+  case(225)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, offset=offset4, start=start4)
+  case(226)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, offset=offset4, start=start4)
+  case(227)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(228)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, offset=offset4, start=start4)
+  case(229)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(230)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(231)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(232)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, offset=offset4, start=start4)
+  case(233)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(234)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(235)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(236)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(237)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4, start=start4)
+  case(238)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4, start=start4)
+  case(239)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, sorted=sorted4, offset=offset4, start=start4)
+  case(240)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, offset=offset4, start=start4)
+  case(241)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(242)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(243)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(244)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(245)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(246)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(247)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4)
+  case(248)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4)
+  case(249)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(250)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4)
+  case(251)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4)
+  case(252)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4)
+  case(253)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4, start=start4)
+  case(254)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4, start=start4)
+  case(255)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+                  colfree=colfree4, index=index4, sorted=sorted4, offset=offset4, start=start4)
+  case(256)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, limit=limit4)
+  case(257)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, limit=limit4)
+  case(258)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, limit=limit4)
+  case(259)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, limit=limit4)
+  case(260)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, limit=limit4)
+  case(261)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, limit=limit4)
+  case(262)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, limit=limit4)
+  case(263)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, limit=limit4)
+  case(264)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, limit=limit4)
+  case(265)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, limit=limit4)
+  case(266)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, limit=limit4)
+  case(267)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, limit=limit4)
+  case(268)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, limit=limit4)
+  case(269)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, limit=limit4)
+  case(270)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, limit=limit4)
+  case(271)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, &
+             colfree=colfree4, limit=limit4)
+  case(272)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, limit=limit4)
+  case(273)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, limit=limit4)
+  case(274)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, limit=limit4)
+  case(275)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, limit=limit4)
+  case(276)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, limit=limit4)
+  case(277)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, limit=limit4)
+  case(278)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, limit=limit4)
+  case(279)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, limit=limit4)
+  case(280)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, limit=limit4)
+  case(281)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, limit=limit4)
+  case(282)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, limit=limit4)
+  case(283)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, limit=limit4)
+  case(284)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, limit=limit4)
+  case(285)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  limit=limit4)
+  case(286)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  limit=limit4)
+  case(287)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, limit=limit4)
+  case(288)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, limit=limit4)
+  case(289)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, limit=limit4)
+  case(290)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, limit=limit4)
+  case(291)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, limit=limit4)
+  case(292)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, limit=limit4)
+  case(293)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, limit=limit4)
+  case(294)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, limit=limit4)
+  case(295)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4, &
+                  limit=limit4)
+  case(296)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, limit=limit4)
+  case(297)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, limit=limit4)
+  case(298)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, limit=limit4)
+  case(299)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4, &
+                  limit=limit4)
+  case(300)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, limit=limit4)
+  case(301)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  limit=limit4)
+  case(302)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  limit=limit4)
+  case(303)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, limit=limit4)
+  case(304)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, limit=limit4)
+  case(305)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, limit=limit4)
+  case(306)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, limit=limit4)
+  case(307)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, limit=limit4)
+  case(308)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, limit=limit4)
+  case(309)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, limit=limit4)
+  case(310)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, limit=limit4)
+  case(311)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, limit=limit4)
+  case(312)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, limit=limit4)
+  case(313)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, limit=limit4)
+  case(314)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, limit=limit4)
+  case(315)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, limit=limit4)
+  case(316)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  limit=limit4)
+  case(317)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, limit=limit4)
+  case(318)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, limit=limit4)
+  case(319)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, limit=limit4)
+  case(320)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, offset=offset4, limit=limit4)
+  case(321)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, offset=offset4, limit=limit4)
+  case(322)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, offset=offset4, limit=limit4)
+  case(323)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, offset=offset4, limit=limit4)
+  case(324)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, offset=offset4, limit=limit4)
+  case(325)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, offset=offset4, limit=limit4)
+  case(326)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, offset=offset4, limit=limit4)
+  case(327)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, offset=offset4, &
+                  limit=limit4)
+  case(328)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, offset=offset4, limit=limit4)
+  case(329)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, offset=offset4, limit=limit4)
+  case(330)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, offset=offset4, limit=limit4)
+  case(331)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, offset=offset4, &
+                  limit=limit4)
+  case(332)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, offset=offset4, limit=limit4)
+  case(333)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, offset=offset4, &
+                  limit=limit4)
+  case(334)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, offset=offset4, &
+                  limit=limit4)
+  case(335)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  offset=offset4, limit=limit4)
+  case(336)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, offset=offset4, limit=limit4)
+  case(337)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, offset=offset4, limit=limit4)
+  case(338)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, offset=offset4, limit=limit4)
+  case(339)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, offset=offset4, limit=limit4)
+  case(340)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, offset=offset4, limit=limit4)
+  case(341)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, offset=offset4, limit=limit4)
+  case(342)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, offset=offset4, limit=limit4)
+  case(343)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  offset=offset4, limit=limit4)
+  case(344)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, offset=offset4, limit=limit4)
+  case(345)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, offset=offset4, limit=limit4)
+  case(346)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, offset=offset4, limit=limit4)
+  case(347)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  offset=offset4, limit=limit4)
+  case(348)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, offset=offset4, &
+                  limit=limit4)
+  case(349)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  offset=offset4, limit=limit4)
+  case(350)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  offset=offset4, limit=limit4)
+  case(351)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4, limit=limit4)
+  case(352)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(353)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(354)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(355)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(356)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(357)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(358)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(359)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(360)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(361)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(362)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(363)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(364)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(365)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(366)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(367)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4, limit=limit4)
+  case(368)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(369)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(370)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(371)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(372)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(373)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(374)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(375)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, offset=offset4, limit=limit4)
+  case(376)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, offset=offset4, &
+                  limit=limit4)
+  case(377)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(378)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(379)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, limit=limit4)
+  case(380)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, limit=limit4)
+  case(381)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, limit=limit4)
+  case(382)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, limit=limit4)
+  case(383)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4, limit=limit4)
+  case(384)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, start=start4, limit=limit4)
+  case(385)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, start=start4, limit=limit4)
+  case(386)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, start=start4, limit=limit4)
+  case(387)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, start=start4, limit=limit4)
+  case(388)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, start=start4, limit=limit4)
+  case(389)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, start=start4, limit=limit4)
+  case(390)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, start=start4, limit=limit4)
+  case(391)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, start=start4, limit=limit4)
+  case(392)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, start=start4, limit=limit4)
+  case(393)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, start=start4, limit=limit4)
+  case(394)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, start=start4, limit=limit4)
+  case(395)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, start=start4, limit=limit4)
+  case(396)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, start=start4, limit=limit4)
+  case(397)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, start=start4, &
+                  limit=limit4)
+  case(398)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, start=start4, &
+                  limit=limit4)
+  case(399)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  start=start4, limit=limit4)
+  case(400)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, start=start4, limit=limit4)
+  case(401)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, start=start4, limit=limit4)
+  case(402)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, start=start4, limit=limit4)
+  case(403)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, start=start4, limit=limit4)
+  case(404)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, start=start4, limit=limit4)
+  case(405)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, start=start4, limit=limit4)
+  case(406)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, start=start4, limit=limit4)
+  case(407)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  start=start4, limit=limit4)
+  case(408)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, start=start4, limit=limit4)
+  case(409)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, start=start4, limit=limit4)
+  case(410)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, start=start4, limit=limit4)
+  case(411)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  start=start4, limit=limit4)
+  case(412)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, start=start4, limit=limit4)
+  case(413)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  start=start4, limit=limit4)
+  case(414)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  start=start4, limit=limit4)
+  case(415)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, start=start4, limit=limit4)
+  case(416)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, start=start4, limit=limit4)
+  case(417)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, start=start4, limit=limit4)
+  case(418)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, start=start4, limit=limit4)
+  case(419)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, start=start4, limit=limit4)
+  case(420)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, start=start4, limit=limit4)
+  case(421)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, start=start4, limit=limit4)
+  case(422)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, start=start4, limit=limit4)
+  case(423)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(424)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, start=start4, limit=limit4)
+  case(425)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, start=start4, limit=limit4)
+  case(426)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, start=start4, limit=limit4)
+  case(427)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(428)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, start=start4, &
+                  limit=limit4)
+  case(429)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(430)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(431)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, start=start4, limit=limit4)
+  case(432)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(433)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(434)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(435)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(436)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(437)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(438)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(439)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, start=start4, limit=limit4)
+  case(440)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(441)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(442)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(443)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, start=start4, limit=limit4)
+  case(444)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  start=start4, limit=limit4)
+  case(445)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, start=start4, limit=limit4)
+  case(446)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, start=start4, limit=limit4)
+  case(447)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, start=start4, limit=limit4)
+  case(448)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, offset=offset4, start=start4, limit=limit4)
+  case(449)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, offset=offset4, start=start4, limit=limit4)
+  case(450)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, offset=offset4, start=start4, limit=limit4)
+  case(451)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, offset=offset4, start=start4, limit=limit4)
+  case(452)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, offset=offset4, start=start4, limit=limit4)
+  case(453)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, offset=offset4, start=start4, limit=limit4)
+  case(454)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, offset=offset4, start=start4, limit=limit4)
+  case(455)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(456)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, offset=offset4, start=start4, limit=limit4)
+  case(457)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, offset=offset4, start=start4, limit=limit4)
+  case(458)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, offset=offset4, start=start4, limit=limit4)
+  case(459)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(460)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, offset=offset4, start=start4, &
+                  limit=limit4)
+  case(461)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(462)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(463)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(464)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, offset=offset4, start=start4, limit=limit4)
+  case(465)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, offset=offset4, start=start4, limit=limit4)
+  case(466)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, offset=offset4, start=start4, limit=limit4)
+  case(467)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(468)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, offset=offset4, start=start4, limit=limit4)
+  case(469)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(470)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(471)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(472)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, offset=offset4, start=start4, limit=limit4)
+  case(473)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(474)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(475)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(476)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(477)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(478)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(479)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, offset=offset4, start=start4, limit=limit4)
+  case(480)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(481)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(482)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(483)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(484)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(485)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(486)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(487)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(488)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, sorted=sorted4, offset=offset4, start=start4, &
+                  limit=limit4)
+  case(489)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(490)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(491)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(492)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(493)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(494)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(495)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(496)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, index=index4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(497)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(498)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(499)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(500)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(501)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(502)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(503)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(504)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colfree=colfree4, index=index4, sorted=sorted4, offset=offset4, &
+                  start=start4, limit=limit4)
+  case(505)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(506)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(507)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(508)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, colfree=colfree4, index=index4, sorted=sorted4, &
+                  offset=offset4, start=start4, limit=limit4)
+  case(509)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(510)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, colget=colget4, colpack=colpack4, colfree=colfree4, index=index4, &
+                  sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  case(511)
+     RC4=ODB_get4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colget=colget4, colpack=colpack4, colfree=colfree4, &
+                  index=index4, sorted=sorted4, offset=offset4, start=start4, limit=limit4)
+  end select
+
+  NROWS = NROWS4
+  If (PRESENT(NCOLS)) NCOLS = NCOLS4
+  If (PRESENT(INDEX)) Then
+    INDEX = INDEX4
+    Deallocate(INDEX4)
+  End If
+  If (Allocated(COLGET4))  Deallocate(COLGET4)
+  If (Allocated(COLPACK4)) Deallocate(COLPACK4)
+  If (Allocated(COLFREE4)) Deallocate(COLFREE4)
+  ODB_get = RC4
+
+End Function ODB_get
+
+!
+! ODB_put =============================================================
+!
+Integer(Kind=8) Function ODB_put(HANDLE, DTNAME, D, NROWS, NCOLS,      &
+                                 POOLNO, COLPUT, COLPACK, SORTED,      &
+                                 OFFSET)
+
+  Use odb_module, only : ODB_put4 => ODB_put
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME
+  Real(Kind=8), Intent(INOUT) :: D(:,0:)
+  Integer(Kind=8), Intent(INOUT) :: NROWS
+  Integer(Kind=8), Intent(INOUT), Optional :: NCOLS
+  Integer(Kind=8), Intent(IN), Optional :: POOLNO, OFFSET
+  Logical(Kind=8), Dimension(:), Intent(IN), Optional :: COLPUT, COLPACK
+  Logical(Kind=8), Intent(IN), Optional :: SORTED
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0, NROWS4, NCOLS4 = -1,         &
+                        POOLNO4 = -1, OFFSET4 = -1
+  Logical(Kind=JPIM), Dimension(:), Allocatable :: COLPUT4, COLPACK4
+  Logical(Kind=JPIM) :: SORTED4 = .FALSE.
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0,o5=0
+
+  if (present(poolno)) o1=1
+  if (present(colput)) o2=2
+  if (present(colpack)) o3=4
+  if (present(sorted)) o4=8
+  if (present(offset)) o5=16
+  o=o1+o2+o3+o4+o5
+
+
+  HANDLE4 = HANDLE
+  NROWS4 = NROWS
+  If (PRESENT(NCOLS))  NCOLS4  = NCOLS
+  If (PRESENT(POOLNO)) POOLNO4 = POOLNO
+  If (PRESENT(OFFSET)) OFFSET4 = OFFSET
+  If (PRESENT(SORTED)) SORTED4 = SORTED
+  If (PRESENT(COLPUT)) Then
+    Allocate(COLPUT4(SIZE(COLPUT)))
+    COLPUT4 = COLPUT
+  End If
+  If (PRESENT(COLPACK)) Then
+    Allocate(COLPACK4(SIZE(COLPACK)))
+    COLPACK4 = COLPACK
+  End If
+
+  select case(o)
+  case(0)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4)
+  case(1)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4)
+  case(2)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4)
+  case(3)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4)
+  case(4)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4)
+  case(5)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4)
+  case(6)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, colpack=colpack4)
+  case(7)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, colpack=colpack4)
+  case(8)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4)
+  case(9)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4)
+  case(10)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, sorted=sorted4)
+  case(11)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, sorted=sorted4)
+  case(12)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4)
+  case(13)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4)
+  case(14)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, colpack=colpack4, sorted=sorted4)
+  case(15)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, colpack=colpack4, sorted=sorted4)
+  case(16)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, offset=offset4)
+  case(17)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, offset=offset4)
+  case(18)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, offset=offset4)
+  case(20)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, offset=offset4)
+  case(21)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, offset=offset4)
+  case(22)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, colpack=colpack4, offset=offset4)
+  case(23)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, colpack=colpack4, offset=offset4)
+  case(24)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, sorted=sorted4, offset=offset4)
+  case(25)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, sorted=sorted4, offset=offset4)
+  case(26)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, sorted=sorted4, offset=offset4)
+  case(27)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, sorted=sorted4, offset=offset4)
+  case(28)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(29)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(30)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, colput=colput4, colpack=colpack4, sorted=sorted4, offset=offset4)
+  case(31)
+     RC4=ODB_put4(handle4, dtname, d, nrows4, ncols4, poolno=poolno4, colput=colput4, colpack=colpack4, sorted=sorted4, &
+                  offset=offset4)
+  end select
+
+  NROWS = NROWS4
+  If (PRESENT(NCOLS)) NCOLS = NCOLS4
+  If (Allocated(COLPUT4))  Deallocate(COLPUT4)
+  If (Allocated(COLPACK4)) Deallocate(COLPACK4)
+  ODB_put = RC4
+
+End Function ODB_put
+
+! =====================================================================
+! wrapper functions for odbutil.F90
+! =====================================================================
+
+!
+! ODB_getnames ========================================================
+!
+Integer(Kind=8) Function ODB_getnames(HANDLE, DTNAME, MODE, OUTNAMES)
+
+  Use odb_module, only : ODB_getnames4 => ODB_getnames
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME, MODE
+  Character(Len=*), Dimension(:), Intent(OUT), Optional :: OUTNAMES
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0
+
+  HANDLE4 = HANDLE
+  RC4 = ODB_getnames4(HANDLE4, DTNAME, MODE, OUTNAMES)
+  ODB_getnames = RC4
+
+End Function ODB_getnames
+
+!
+! ODB_varindex ========================================================
+!
+Integer(Kind=8) Function ODB_varindex(HANDLE, DTNAME, NAMES, IDX)
+
+  Use odb_module, only : ODB_varindex4 => ODB_varindex
+
+  Integer(Kind=8), Intent(IN) :: HANDLE
+  Character(Len=*), Intent(IN) :: DTNAME
+  Character(Len=*), Dimension(:), Intent(IN) :: NAMES
+  Integer(Kind=8), Dimension(:), Intent(OUT) :: IDX
+
+  Integer(Kind=JPIM) :: HANDLE4, RC4 = 0
+  Integer(Kind=JPIM), Dimension(:), Allocatable :: IDX4
+
+  HANDLE4 = HANDLE
+  Allocate(IDX4(SIZE(IDX)))
+
+  RC4=ODB_varindex4(HANDLE4, DTNAME, NAMES, IDX4)
+
+  IDX = IDX4
+  ODB_varindex = RC4
+
+End Function ODB_varindex
+
+Integer(Kind=8) FUNCTION ODB_cancel(handle, dtname, poolno)
+
+  Use odb_module, only : ODB_cancel4 => ODB_cancel
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  character(len=*), intent(in)  :: dtname
+  INTEGER(KIND=8), intent(in), optional :: poolno
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  if (present(poolno)) o1=1
+  o=o1
+
+  HANDLE4 = handle
+  If (PRESENT(poolno)) poolno4 = poolno
+  
+
+  select case(o)
+  case(0)
+     RC4=ODB_cancel4(handle4, dtname)
+  case(1)
+     RC4=ODB_cancel4(handle4, dtname, poolno=poolno4)
+  end select
+
+  ODB_cancel = RC4
+
+End Function ODB_cancel
+
+Integer(Kind=8) FUNCTION ODB_end()
+
+  Use odb_module, only : ODB_end4 => ODB_end
+
+  implicit none
+  INTEGER(KIND=JPIM) :: RC4
+
+  RC4 = ODB_end4()
+
+  ODB_end = RC4
+
+End Function ODB_end
+
+Integer(Kind=8) Function ODB_load(handle, poolno, sync)
+
+  Use odb_module, only : ODB_load4 => ODB_load
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  INTEGER(KIND=8), intent(in), optional :: poolno
+  logical(KIND=8), intent(in), optional :: sync
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4, poolno4
+  logical(KIND=JPIM) :: sync4
+
+  integer :: o=0,o1=0,o2=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+  if (present(sync))   sync4 = sync
+
+  if (present(poolno)) o1=1
+  if (present(sync)) o2=2
+  o=o1+o2
+
+  select case(o)
+  case(0)
+     RC4=ODB_load4(handle4)
+  case(1)
+     RC4=ODB_load4(handle4, poolno=poolno4)
+  case(2)
+     RC4=ODB_load4(handle4, sync=sync4)
+  case(3)
+     RC4=ODB_load4(handle4, poolno=poolno4, sync=sync4)
+  end select
+
+  ODB_load = RC4
+
+End Function ODB_load
+
+Integer(Kind=8) Function ODB_store(handle, poolno, sync)
+
+  Use odb_module, only : ODB_store4 => ODB_store
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  INTEGER(KIND=8), intent(in), optional :: poolno
+  logical(KIND=8), intent(in), optional :: sync
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4, poolno4
+  logical(KIND=JPIM) :: sync4
+
+  integer :: o=0,o1=0,o2=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+  if (present(sync))   sync4 = sync
+
+  if (present(poolno)) o1=1
+  if (present(sync)) o2=2
+  o=o1+o2
+
+  select case(o)
+  case(0)
+     RC4=ODB_store4(handle4)
+  case(1)
+     RC4=ODB_store4(handle4, poolno=poolno4)
+  case(2)
+     RC4=ODB_store4(handle4, sync=sync4)
+  case(3)
+     RC4=ODB_store4(handle4, poolno=poolno4, sync=sync4)
+  end select
+
+  ODB_store = RC4
+
+End Function ODB_store
+
+Integer(Kind=8) Function ODB_getsize(handle, dtname, nrows, ncols, nra, poolno)
+
+  Use odb_module, only : ODB_getsize4 => ODB_getsize
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  INTEGER(KIND=8), intent(out)          :: nrows, ncols
+  character(len=*), intent(in)          :: dtname
+  INTEGER(KIND=8), intent(out), optional:: nra
+  INTEGER(KIND=8), intent(in), optional :: poolno
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: nrows4, ncols4
+  INTEGER(KIND=JPIM) :: nra4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+
+  if (present(nra)) o1=1
+  if (present(poolno)) o2=2
+  o=o1+o2
+
+  select case(o)
+  case(0)
+     RC4=ODB_getsize4(handle4,dtname,nrows4,ncols4)
+  case(1)
+     RC4=ODB_getsize4(handle4,dtname,nrows4,ncols4, nra=nra4)
+  case(2)
+     RC4=ODB_getsize4(handle4,dtname,nrows4,ncols4, poolno=poolno4)
+  case(3)
+     RC4=ODB_getsize4(handle4,dtname,nrows4,ncols4, nra=nra4, poolno=poolno4)
+  end select
+
+  nrows = nrows4
+  ncols = ncols4
+  if (present(nra)) nra = nra4
+
+  ODB_getsize = RC4
+
+End Function ODB_getsize
+
+Integer(Kind=8) Function ODB_swapout(handle, dtname, poolno, save, repack)
+
+  Use odb_module, only : ODB_swapout4 => ODB_swapout
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)           :: handle
+  character(len=*), intent(in)           :: dtname
+  INTEGER(KIND=8) , intent(in), optional :: poolno
+  logical(Kind=8) , intent(in), optional :: save, repack
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+  logical(Kind=JPIM) :: save4, repack4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+  if (present(save)) save4 = save
+  if (present(repack)) repack4 = repack
+
+  if (present(poolno)) o1=1
+  if (present(save)) o2=2
+  if (present(repack)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     RC4=ODB_swapout4(handle4,dtname)
+  case(1)
+     RC4=ODB_swapout4(handle4,dtname, poolno=poolno4)
+  case(2)
+     RC4=ODB_swapout4(handle4,dtname, save=save4)
+  case(3)
+     RC4=ODB_swapout4(handle4,dtname, poolno=poolno4, save=save4)
+  case(4)
+     RC4=ODB_swapout4(handle4,dtname, repack=repack4)
+  case(5)
+     RC4=ODB_swapout4(handle4,dtname, poolno=poolno4, repack=repack4)
+  case(6)
+     RC4=ODB_swapout4(handle4,dtname, save=save4, repack=repack4)
+  case(7)
+     RC4=ODB_swapout4(handle4,dtname, poolno=poolno4, save=save4, repack=repack4)
+  end select
+
+  ODB_swapout = RC4
+
+End Function ODB_swapout
+
+Integer(Kind=8) Function ODB_pack(handle, dtname, poolno)
+
+  Use odb_module, only : ODB_pack4 => ODB_pack
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  character(len=*), intent(in)    :: dtname
+  INTEGER(KIND=8), intent(in), optional :: poolno
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+
+  if (present(poolno)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_pack4(handle4, dtname)
+  case(1)
+     RC4=ODB_pack4(handle4, dtname, poolno=poolno4)
+  end select
+
+  ODB_pack = RC4
+
+End Function ODB_pack
+
+Integer(Kind=8) Function ODB_unpack(handle, dtname, poolno)
+
+  Use odb_module, only : ODB_unpack4 => ODB_unpack
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  character(len=*), intent(in)    :: dtname
+  INTEGER(KIND=8), intent(in), optional :: poolno
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+
+  if (present(poolno)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_unpack4(handle4, dtname)
+  case(1)
+     RC4=ODB_unpack4(handle4, dtname, poolno=poolno4)
+  end select
+
+  ODB_unpack = RC4
+
+End Function ODB_unpack
+
+Integer(Kind=8) Function ODB_gethandle(handle, dtname, addview)
+
+  Use odb_module, only : ODB_gethandle4 => ODB_gethandle
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)             :: handle
+  character(len=*), intent(in)             :: dtname
+  logical(Kind=8) , intent(in), optional   :: addview
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4
+  logical(Kind=4)    :: addview4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(addview)) addview4 = addview
+
+  if (present(addview)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_gethandle4(handle4, dtname)
+  case(1)
+     RC4=ODB_gethandle4(handle4, dtname, addview=addview4)
+  end select
+
+  ODB_gethandle = RC4
+
+End Function ODB_gethandle
+
+Integer(Kind=8) Function ODB_addpools(handle, pool_excess,old_npools,maxpoolno)
+
+  Use odb_module, only : ODB_addpools4 => ODB_addpools
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle, pool_excess
+  INTEGER(KIND=8), intent(out), OPTIONAL :: old_npools,maxpoolno
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4, pool_excess4
+  INTEGER(KIND=JPIM) :: old_npools4,maxpoolno4
+
+  integer :: o=0,o1=0,o2=0
+
+  handle4 = handle
+  pool_excess4 = pool_excess
+
+  if (present(old_npools)) o1=1
+  if (present(maxpoolno)) o2=2
+  o=o1+o2
+
+  select case(o)
+  case(0)
+     RC4=ODB_addpools4(handle4, pool_excess4)
+  case(1)
+     RC4=ODB_addpools4(handle4, pool_excess4, old_npools=old_npools4)
+  case(2)
+     RC4=ODB_addpools4(handle4, pool_excess4, maxpoolno=maxpoolno4)
+  case(3)
+     RC4=ODB_addpools4(handle4, pool_excess4, old_npools=old_npools4, maxpoolno=maxpoolno4)
+  end select
+
+  if (present(old_npools)) old_npools = old_npools4
+  if (present(maxpoolno))  maxpoolno  = maxpoolno4
+  ODB_addpools = RC4
+
+End Function ODB_addpools
+
+Integer(Kind=8) Function ODB_remove(handle, dtname, poolno)
+
+  use odb_module, only : ODB_remove4 => ODB_remove
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  character(len=*), intent(in)             :: dtname
+  INTEGER(KIND=8), intent(in), optional :: poolno
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+
+  if (present(poolno)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_remove4(handle4, dtname)
+  case(1)
+     RC4=ODB_remove4(handle4, dtname, poolno=poolno4)
+  end select
+
+  ODB_remove = RC4
+
+End Function ODB_remove
+
+Integer(Kind=4) Function ODB_getprecision(handle, dtname, maxbits, anyflp)
+
+  Use odb_module, only : ODB_getprecision4 => ODB_getprecision
+
+  Implicit none
+
+  INTEGER(KIND=8 ), intent(in)  :: handle
+  INTEGER(KIND=8) , intent(out) :: maxbits
+  logical(Kind=8) , intent(out) :: anyflp
+  character(len=*), intent(in)  :: dtname
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: maxbits4
+  logical(Kind=JPIM) :: anyflp4
+
+  handle4 = handle
+
+  RC4 = ODB_getprecision4(handle4, dtname, maxbits4, anyflp4)
+
+  maxbits = maxbits4
+  anyflp = anyflp4
+  ODB_getprecision = RC4
+
+End Function ODB_getprecision
+
+Integer(Kind=8) Function ODB_getval(handle, varname, viewname)
+
+  Use odb_module, only : ODB_getval4 => ODB_getval
+
+  implicit none
+
+  INTEGER(KIND=8)   , intent(in)           :: handle
+  character(len=*)  , intent(in)           :: varname
+  character(len=*)  , intent(in), optional :: viewname
+
+  INTEGER(KIND=JPIM) :: handle4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(viewname)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_getval4(handle4, varname)
+  case(1)
+     RC4=ODB_getval4(handle4, varname, viewname=viewname)
+  end select
+
+  ODB_getval = RC4
+
+End Function ODB_getval
+
+Logical(Kind=8) Function ODB_varexist(handle, varname, viewname)
+
+  Use odb_module, only : ODB_varexist4 => ODB_varexist
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)           :: handle
+  character(len=*), intent(in)           :: varname
+  character(len=*), intent(in), optional :: viewname
+
+  INTEGER(KIND=JPIM) :: handle4
+
+  logical(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(viewname)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_varexist4(handle4, varname)
+  case(1)
+     RC4=ODB_varexist4(handle4, varname, viewname=viewname)
+  end select
+
+  ODB_varexist = RC4
+
+End Function ODB_varexist
+
+Integer (Kind=8) Function ODB_poolinfo(handle, poolids, with_poolmask)
+
+  Use odb_module, only : ODB_poolinfo4 => ODB_poolinfo
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  INTEGER(KIND=8), intent(out), optional :: poolids(:)
+  logical(Kind=8), intent(in) , optional :: with_poolmask
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM), allocatable :: poolids4(:)
+  logical                         :: with_poolmask4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0
+
+  allocate(poolids4(size(poolids)))
+  handle4 = handle
+  if (present(with_poolmask)) with_poolmask4 = with_poolmask
+
+  if (present(poolids)) o1=1
+  if (present(with_poolmask)) o2=2
+  o=o1+o2
+
+  select case(o)
+  case(0)
+     RC4=ODB_poolinfo4(handle4)
+  case(1)
+     RC4=ODB_poolinfo4(handle4, poolids=poolids4)
+  case(2)
+     RC4=ODB_poolinfo4(handle4, with_poolmask=with_poolmask4)
+  case(3)
+     RC4=ODB_poolinfo4(handle4, poolids=poolids4, with_poolmask=with_poolmask4)
+  end select
+  
+  if (present(poolids)) poolids4 = poolids
+
+  deallocate(poolids4)
+  ODB_poolinfo = RC4
+
+End Function ODB_poolinfo
+
+Integer(Kind=8) FUNCTION ODB_twindow(target_date, target_time, analysis_date, analysis_time, left_margin, right_margin)
+
+  Use odb_module, only : ODB_twindow4 => ODB_twindow
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: target_date, target_time
+  INTEGER(KIND=8), intent(in) :: analysis_date, analysis_time
+  INTEGER(KIND=8), intent(in) :: left_margin, right_margin
+
+  INTEGER(KIND=JPIM) :: target_date4, target_time4
+  INTEGER(KIND=JPIM) :: analysis_date4, analysis_time4
+  INTEGER(KIND=JPIM) :: left_margin4, right_margin4
+  
+  INTEGER(KIND=JPIM) :: RC4
+
+  target_date4 = target_date
+  target_time4 = target_time
+  analysis_date4 = analysis_date
+  analysis_time4 = analysis_time
+  left_margin4 = left_margin
+  right_margin4 = right_margin
+
+  RC4 = ODB_twindow4(target_date4, target_time4, analysis_date4, analysis_time4, left_margin4, right_margin4)
+
+  ODB_twindow = RC4
+
+End Function ODB_twindow
+
+Integer(Kind=8) FUNCTION ODB_tdiff(target_date, target_time, analysis_date, analysis_time)
+
+  Use odb_module, only : ODB_tdiff4 => ODB_tdiff
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: target_date, target_time
+  INTEGER(KIND=8), intent(in) :: analysis_date, analysis_time
+
+  INTEGER(KIND=JPIM) :: target_date4, target_time4
+  INTEGER(KIND=JPIM) :: analysis_date4, analysis_time4
+  
+  INTEGER(KIND=JPIM) :: RC4
+
+  target_date4 = target_date
+  target_time4 = target_time
+  analysis_date4 = analysis_date
+  analysis_time4 = analysis_time
+
+  RC4 = ODB_tdiff4(target_date4, target_time4, analysis_date4, analysis_time4)
+
+  ODB_tdiff = RC4
+
+End Function ODB_tdiff
+
+SUBROUTINE ODB_analysis_datetime(handle, andate, antime)
+
+  use odb_module, only : ODB_analysis_datetime4 => ODB_analysis_datetime
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle, andate, antime
+
+  INTEGER(KIND=JPIM) :: handle4, andate4, antime4
+
+  handle4 = handle
+  andate4 = andate
+  antime4 = antime
+
+  call ODB_analysis_datetime4(handle4, andate4, antime4)
+
+End Subroutine ODB_analysis_datetime
+
+Integer(Kind=8) Function ODB_get_update_info(handle, dtname, colput)
+
+  Use odb_module, only : ODB_get_update_info4 => ODB_get_update_info
+
+  implicit none
+
+  INTEGER(KIND=8)  , intent(in)  :: handle
+  character(len=*) , intent(in)  :: dtname
+  logical(Kind=8)  , intent(out) :: colput(:)
+
+  INTEGER(KIND=JPIM)   :: handle4
+  logical, allocatable :: colput4(:)
+  
+  INTEGER(KIND=JPIM)   :: RC4
+
+  handle4 = handle
+  allocate(colput4(size(colput)))
+  colput4 = colput
+
+  RC4 = ODB_get_update_info4(handle4, dtname, colput4)
+
+  deallocate(colput4)
+
+  ODB_get_update_info = RC4
+
+End Function ODB_get_update_info
+
+Integer(Kind=8) Function ODB_sortkeys(handle, dtname, keys)
+
+  Use odb_module, only : ODB_sortkeys4 => ODB_sortkeys
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: dtname
+  INTEGER(KIND=8),intent(out) , optional :: keys(:)
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM), allocatable :: keys4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(keys)) allocate(keys4(size(keys)))
+
+  if (present(keys)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_sortkeys4(handle4, dtname)
+  case(1)
+     RC4=ODB_sortkeys4(handle4, dtname, keys=keys4)
+  end select
+
+  if (present(keys)) then
+     keys = keys4
+     deallocate(keys4)
+  endif
+
+  ODB_sortkeys = RC4
+
+End Function ODB_sortkeys
+
+Integer(Kind=8) Function ODB_io_method(handle)
+
+  Use odb_module, only : ODB_io_method4 => ODB_io_method
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)  :: handle
+
+  INTEGER(KIND=JPIM) :: handle4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  handle4 = handle
+
+  RC4 = ODB_io_method4(handle4)
+
+  ODB_io_method = RC4
+
+End Function ODB_io_method
+
+Logical(Kind=8) Function ODB_has_select_distinct(handle, dtname, ncols)
+
+  Use odb_module, only : ODB_has_select_distinct4 => ODB_has_select_distinct
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)            :: handle
+  character(len=*), intent(in)            :: dtname
+  INTEGER(KIND=8) , intent(out), optional :: ncols
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: ncols4
+
+  Logical :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(ncols)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_has_select_distinct4(handle4, dtname)
+  case(1)
+     RC4=ODB_has_select_distinct4(handle4, dtname, ncols=ncols4)
+  end select
+
+  if (present(ncols)) ncols4 = ncols
+
+  ODB_has_select_distinct = RC4
+
+End Function ODB_has_select_distinct
+
+Logical(Kind=8) Function ODB_has_uniqueby(handle, dtname, ncols)
+
+  Use odb_module, only : ODB_has_uniqueby4 => ODB_has_uniqueby
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)            :: handle
+  character(len=*), intent(in)            :: dtname
+  INTEGER(KIND=8) , intent(out), optional :: ncols
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: ncols4
+
+  Logical :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(ncols)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_has_uniqueby4(handle4, dtname)
+  case(1)
+     RC4=ODB_has_uniqueby4(handle4, dtname, ncols=ncols4)
+  end select
+
+  if (present(ncols)) ncols4 = ncols
+
+  ODB_has_uniqueby = RC4
+
+End Function ODB_has_uniqueby
+
+Logical(Kind=8) Function ODB_has_orderby(handle, dtname, ncols)
+
+  Use odb_module, only : ODB_has_orderby4 => ODB_has_orderby
+
+  implicit none
+
+  INTEGER(KIND=8) , intent(in)            :: handle
+  character(len=*), intent(in)            :: dtname
+  INTEGER(KIND=8) , intent(out), optional :: ncols
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: ncols4
+
+  Logical :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(ncols)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_has_orderby4(handle4, dtname)
+  case(1)
+     RC4=ODB_has_orderby4(handle4, dtname, ncols=ncols4)
+  end select
+
+  if (present(ncols)) ncols4 = ncols
+
+  ODB_has_orderby = RC4
+
+End Function ODB_has_orderby
+
+! odbshared
+
+Subroutine ODB_abort(routine, s, code, really_abort)
+
+  Use odb_module, only : ODB_abort4 => ODB_abort
+
+  implicit none
+
+  character(len=*), intent(in)           :: routine
+  character(len=*), intent(in), optional :: s
+  INTEGER(KIND=8) , intent(in), optional :: code
+  logical(Kind=8) , intent(in), optional :: really_abort
+
+  INTEGER(KIND=JPIM) :: code4
+  logical(Kind=JPIM) :: really_abort4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  if (present(code)) code4 = code
+  if (present(really_abort)) really_abort4 = really_abort
+
+  if (present(s)) o1=1
+  if (present(code)) o2=2
+  if (present(really_abort)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     call ODB_abort4(routine)
+  case(1)
+     call ODB_abort4(routine, s=s)
+  case(2)
+     call ODB_abort4(routine, code=code4)
+  case(3)
+     call ODB_abort4(routine, s=s, code=code4)
+  case(4)
+     call ODB_abort4(routine, really_abort=really_abort4)
+  case(5)
+     call ODB_abort4(routine, s=s, really_abort=really_abort4)
+  case(6)
+     call ODB_abort4(routine, code=code4, really_abort=really_abort4)
+  case(7)
+     call ODB_abort4(routine, s=s, code=code4, really_abort=really_abort4)
+  end select
+
+End Subroutine ODB_abort
+
+Integer(Kind=8) Function ODB_lda(n, method)
+
+  use odb_module, only : ODB_lda4 => ODB_lda
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: n
+  INTEGER(KIND=8), intent(in), OPTIONAL :: method
+
+  INTEGER(KIND=JPIM) :: n4
+  INTEGER(KIND=JPIM) :: method4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  n4 = n
+  if (present(method)) method4 = method
+
+  if (present(method)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_lda4(n4)
+  case(1)
+     RC4=ODB_lda4(n4, method=method4)
+  end select
+
+  ODB_lda = RC4
+
+End Function ODB_lda
+
+Integer(Kind=8) Function ODB_get_vpools(handle, poolnos)
+
+  Use odb_module, only : ODB_get_vpools4 => ODB_get_vpools
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle
+  INTEGER(KIND=8), intent(out), optional :: poolnos(:)
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM), allocatable :: poolnos4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(poolnos)) allocate(poolnos4(size(poolnos)))
+
+  if (present(poolnos)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_get_vpools4(handle4)
+  case(1)
+     RC4=ODB_get_vpools4(handle4, poolnos=poolnos4)
+  end select
+
+  if (present(poolnos)) poolnos = poolnos4
+  ODB_get_vpools = RC4
+
+End Function ODB_get_vpools
+
+Integer(Kind=8) Function ODB_unmap_vpools(handle)
+
+  Use odb_module, only : ODB_unmap_vpools4 => ODB_unmap_vpools
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle
+
+  INTEGER(KIND=JPIM) :: handle4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  handle4 = handle
+
+  RC4=ODB_unmap_vpools4(handle4)
+
+  ODB_unmap_vpools = RC4
+
+End Function ODB_unmap_vpools
+
+Integer(Kind=8) Function ODB_map_vpools_direct(handle, poolnos, verbose)
+
+  Use odb_module, only : ODB_map_vpools_direct4 => ODB_map_vpools_direct
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: handle
+  INTEGER(KIND=8), intent(in)           :: poolnos(:)
+  logical(Kind=8), intent(in), optional :: verbose
+
+  INTEGER(KIND=JPIM)              :: handle4
+  INTEGER(KIND=JPIM), allocatable :: poolnos4(:)
+  logical                         :: verbose4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  allocate(poolnos4(size(poolnos)))
+  poolnos4 = poolnos
+  if (present(verbose)) verbose4 = verbose
+
+  if (present(verbose)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_map_vpools_direct4(handle4, poolnos4)
+  case(1)
+     RC4=ODB_map_vpools_direct4(handle4, poolnos4, verbose=verbose4)
+  end select
+
+  ODB_map_vpools_direct = RC4
+
+End Function ODB_map_vpools_direct
+
+Integer(Kind=8) Function ODB_map_vpools_fromfile(handle, file, verbose)
+
+  Use odb_module, only : ODB_map_vpools_fromfile4 => ODB_map_vpools_fromfile
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: file
+  logical(Kind=8), intent(in), optional  :: verbose
+
+  INTEGER(KIND=JPIM) :: handle4
+  logical            :: verbose4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(verbose)) verbose4 =verbose
+
+  if (present(verbose)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_map_vpools_fromfile4(handle4, file)
+  case(1)
+     RC4=ODB_map_vpools_fromfile4(handle4, file, verbose=verbose4)
+  end select
+
+  ODB_map_vpools_fromfile = RC4
+
+End Function ODB_map_vpools_fromfile
+
+Integer(Kind=8) Function ODB_toggle_vpools(handle, toggle)
+ 
+  Use odb_module, only : ODB_toggle_vpools4 => ODB_toggle_vpools
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle
+  INTEGER(KIND=8), intent(in), optional :: toggle
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: toggle4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  if (present(toggle)) toggle4 = toggle
+
+  if (present(toggle)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_toggle_vpools4(handle4)
+  case(1)
+     RC4=ODB_toggle_vpools4(handle4, toggle=toggle4)
+  end select
+
+  ODB_toggle_vpools = RC4
+
+End Function ODB_toggle_vpools
+
+Integer(Kind=8) Function ODB_pool2vpool(handle, poolno)
+
+  Use odb_module, only : ODB_pool2vpool4 => ODB_pool2vpool
+  
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle
+  INTEGER(KIND=8), intent(in) :: poolno
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  handle4 = handle
+  poolno4 = poolno
+
+  RC4=ODB_pool2vpool4(handle4, poolno4)
+
+  ODB_pool2vpool=RC4
+
+End Function ODB_pool2vpool
+
+Integer(Kind=8) Function ODB_vpool2pool(handle, poolno)
+
+  Use odb_module, only : ODB_vpool2pool4 => ODB_vpool2pool
+  
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: handle
+  INTEGER(KIND=8), intent(in) :: poolno
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  handle4 = handle
+  poolno4 = poolno
+
+  RC4=ODB_vpool2pool4(handle4, poolno4)
+
+  ODB_vpool2pool=RC4
+
+End Function ODB_vpool2pool
+
+Logical(Kind=8) Function ODB_valid_poolno(poolno)
+
+  Use odb_module, only : ODB_valid_poolno4 => ODB_valid_poolno
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: poolno
+
+  INTEGER(KIND=JPIM) :: poolno4
+
+  Logical(KIND=JPIM) :: RC4
+
+  poolno4 = poolno
+
+  RC4=ODB_valid_poolno4(poolno4)
+
+  ODB_valid_poolno = RC4
+
+End Function ODB_valid_poolno
+
+! odbmp
+
+Subroutine ODBMP_abort(routine, s, code, really_abort)
+
+  Use odb_module, only : ODBMP_abort4 => ODBMP_abort
+
+  implicit none
+
+  character(len=*), intent(in)           :: routine
+  character(len=*), intent(in), optional :: s
+  INTEGER(KIND=8) , intent(in), optional :: code
+  logical(Kind=8) , intent(in), optional :: really_abort
+
+  INTEGER(KIND=JPIM) :: code4
+  logical            :: really_abort4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  if (present(code)) code4 = code
+  if (present(really_abort)) really_abort4 = really_abort
+
+  if (present(s)) o1=1
+  if (present(code)) o2=2
+  if (present(really_abort)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     call ODBMP_abort4(routine)
+  case(1)
+     call ODBMP_abort4(routine, s=s)
+  case(2)
+     call ODBMP_abort4(routine, code=code4)
+  case(3)
+     call ODBMP_abort4(routine, s=s, code=code4)
+  case(4)
+     call ODBMP_abort4(routine, really_abort=really_abort4)
+  case(5)
+     call ODBMP_abort4(routine, s=s, really_abort=really_abort4)
+  case(6)
+     call ODBMP_abort4(routine, code=code4, really_abort=really_abort4)
+  case(7)
+     call ODBMP_abort4(routine, s=s, code=code4, really_abort=really_abort4)
+  end select
+
+End Subroutine ODBMP_abort
+
+Subroutine ODBMP_init(LDsync)
+  
+  Use odb_module, only : ODBMP_init4 => ODBMP_init
+
+  implicit none
+
+  logical(Kind=8), intent(in), optional :: LDsync
+  logical :: LDsync4
+
+  integer :: o=0,o1=0
+
+  if (present(LDsync)) LDsync4 = LDsync
+
+  if (present(LDsync)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     call ODBMP_init4()
+  case(1)
+     call ODBMP_init4(LDsync=LDsync4)
+  end select
+
+End Subroutine ODBMP_init
+
+Integer(Kind=8) Function ODBMP_end()
+
+  Use odb_module, only : ODBMP_end4 => ODBMP_end
+
+  implicit none
+
+  Integer(Kind=JPIM) :: RC4
+
+  RC4 = ODBMP_end4()
+
+  ODBMP_end = RC4
+
+End Function ODBMP_end
+
+Subroutine ODBMP_sync(where)
+  
+  Use odb_module, only : ODBMP_sync4 => ODBMP_sync
+
+  implicit none
+
+  Integer(Kind=8), intent(in), optional :: where
+  Integer(Kind=JPIM) :: where4
+
+  integer :: o=0,o1=0
+
+  if (present(where)) where4 = where
+
+  if (present(where)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     call ODBMP_sync4()
+  case(1)
+     call ODBMP_sync4(where=where4)
+  end select
+
+End Subroutine ODBMP_sync
+
+Logical(Kind=8) Function ODBMP_testready(with)
+  
+  Use odb_module, only : ODBMP_testready4 => ODBMP_testready
+
+  implicit none
+
+  Integer(Kind=8), intent(in) :: with
+  Integer(Kind=JPIM) :: with4
+  Logical(Kind=JPIM) :: RC4
+
+  with4 = with
+
+  RC4=ODBMP_testready4(with4)
+
+  ODBMP_testready = RC4
+
+End Function ODBMP_testready
+
+Integer(Kind=8) Function ODBMP_locking(lockid, onoff)
+
+  Use odb_module, only : ODBMP_locking4 => ODBMP_locking
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in) :: lockid, onoff
+  INTEGER(KIND=JPIM) :: lockid4, onoff4
+  Integer(Kind=JPIM) :: RC4
+
+  lockid4 = lockid
+  onoff4 = onoff
+
+  RC4=ODBMP_locking4(lockid4, onoff4)
+
+  ODBMP_locking = RC4
+
+End Function ODBMP_locking
+
+Subroutine ODBMP_trace(trace_on)
+
+  Use odb_module, only : ODBMP_trace4 => ODBMP_trace
+
+  implicit none
+
+  logical(Kind=8), intent(in) :: trace_on
+  logical(Kind=JPIM) :: trace_on4
+
+  trace_on4 = trace_on
+
+  call ODBMP_trace4(trace_on4)
+
+End Subroutine ODBMP_trace
+
+Integer(Kind=8) Function ODBMP_physproc(x)
+
+  Use odb_module, only : ODBMP_physproc4 => ODBMP_physproc
+
+  implicit none
+
+  Integer(Kind=8), intent(in) :: x
+  Integer(Kind=JPIM) :: x4
+  Integer(Kind=JPIM) :: RC4
+
+  x4 = x
+
+  RC4=ODBMP_physproc4(x4)
+
+  ODBMP_physproc = RC4
+
+End Function ODBMP_physproc
+
+Integer(Kind=8) Function ODBMP_setup_exchange(opponent, start_proc)
+
+  Use odb_module, only : ODBMP_setup_exchange4 => ODBMP_setup_exchange
+
+  implicit none
+
+  INTEGER(KIND=8), intent(out) :: opponent(:)
+  INTEGER(KIND=8), intent(in), OPTIONAL :: start_proc
+
+  INTEGER(KIND=JPIM), allocatable :: opponent4(:)
+  INTEGER(KIND=JPIM) :: start_proc4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  allocate(opponent4(size(opponent)))
+  opponent4 = opponent
+  if (present(start_proc)) start_proc4 = start_proc
+
+  if (present(start_proc)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODBMP_setup_exchange4(opponent4)
+  case(1)
+     RC4=ODBMP_setup_exchange4(opponent4, start_proc=start_proc4)
+  end select
+
+  deallocate(opponent4)
+
+  ODBMP_setup_exchange = RC4
+
+End Function ODBMP_setup_exchange
+
+Integer(Kind=8) Function ODB_to_netcdf(handle, dtname, file, poolno, setvars, values, mdi)
+
+  Use odb_module, only : ODB_to_netcdf4 => ODB_to_netcdf
+
+  implicit none
+
+  INTEGER(KIND=8)   , intent(in)           :: handle
+  character(len=*)  , intent(in)           :: dtname
+  character(len=*)  , intent(in), optional :: file
+  INTEGER(KIND=8)   , intent(in), optional :: poolno
+  character(len=*)  , intent(in), optional :: setvars(:)
+  REAL(KIND=JPRB)   , intent(in), optional :: values(:)
+  REAL(KIND=JPRB)   , intent(in), optional :: mdi
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: poolno4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0,o5=0
+
+  handle4 = handle
+  if (present(poolno)) poolno4 = poolno
+
+  if (present(file)) o1=1
+  if (present(poolno)) o2=2
+  if (present(setvars)) o3=4
+  if (present(values)) o4=8
+  if (present(mdi)) o5=16
+  o=o1+o2+o3+o4+o5
+
+  select case(o)
+  case(0)
+     RC4=ODB_to_netcdf4(handle4, dtname)
+  case(1)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file)
+  case(2)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4)
+  case(3)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4)
+  case(4)
+     RC4=ODB_to_netcdf4(handle4, dtname, setvars=setvars)
+  case(5)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, setvars=setvars)
+  case(6)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, setvars=setvars)
+  case(7)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, setvars=setvars)
+  case(8)
+     RC4=ODB_to_netcdf4(handle4, dtname, values=values)
+  case(9)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, values=values)
+  case(10)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, values=values)
+  case(11)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, values=values)
+  case(12)
+     RC4=ODB_to_netcdf4(handle4, dtname, setvars=setvars, values=values)
+  case(13)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, setvars=setvars, values=values)
+  case(14)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, setvars=setvars, values=values)
+  case(15)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, setvars=setvars, values=values)
+  case(16)
+     RC4=ODB_to_netcdf4(handle4, dtname, mdi=mdi)
+  case(17)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, mdi=mdi)
+  case(18)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, mdi=mdi)
+  case(19)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, mdi=mdi)
+  case(20)
+     RC4=ODB_to_netcdf4(handle4, dtname, setvars=setvars, mdi=mdi)
+  case(21)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, setvars=setvars, mdi=mdi)
+  case(22)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, setvars=setvars, mdi=mdi)
+  case(23)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, setvars=setvars, mdi=mdi)
+  case(24)
+     RC4=ODB_to_netcdf4(handle4, dtname, values=values, mdi=mdi)
+  case(25)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, values=values, mdi=mdi)
+  case(26)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, values=values, mdi=mdi)
+  case(27)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, values=values, mdi=mdi)
+  case(28)
+     RC4=ODB_to_netcdf4(handle4, dtname, setvars=setvars, values=values, mdi=mdi)
+  case(29)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, setvars=setvars, values=values, mdi=mdi)
+  case(30)
+     RC4=ODB_to_netcdf4(handle4, dtname, poolno=poolno4, setvars=setvars, values=values, mdi=mdi)
+  case(31)
+     RC4=ODB_to_netcdf4(handle4, dtname, file=file, poolno=poolno4, setvars=setvars, values=values, mdi=mdi)
+  end select
+
+  ODB_to_netcdf = RC4
+
+End Function ODB_to_netcdf
+
+Integer(Kind=8) Function ODB_distribute_str(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  character(len=*), intent(inout)        :: s
+  INTEGER(KIND=8) , intent(in), optional :: target
+
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s)
+  case(1)
+     RC4=ODB_distribute4(s, target=target4)
+  end select
+
+  ODB_distribute_str = RC4
+
+End Function ODB_distribute_str
+  
+Integer(Kind=8) Function ODB_distribute_vecstr(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  character(len=*), intent(inout)        :: s(:)
+  INTEGER(KIND=8) , intent(in), optional :: target
+
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s)
+  case(1)
+     RC4=ODB_distribute4(s, target=target4)
+  end select
+
+  ODB_distribute_vecstr = RC4
+
+End Function ODB_distribute_vecstr
+  
+Integer(Kind=8) Function ODB_distribute_int(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  INTEGER(KIND=8), intent(inout)        :: s
+  INTEGER(KIND=8), intent(in), optional :: target
+
+  INTEGER(KIND=JPIM) :: s4
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  s4 = s
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s4)
+  case(1)
+     RC4=ODB_distribute4(s4, target=target4)
+  end select
+  
+  s = s4
+  ODB_distribute_int = RC4
+
+End Function ODB_distribute_int
+  
+Integer(Kind=8) Function ODB_distribute_vecint(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  INTEGER(KIND=8), intent(inout)        :: s(:)
+  INTEGER(KIND=8), intent(in), optional :: target
+
+  INTEGER(KIND=JPIM), allocatable :: s4(:)
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  allocate(s4(size(s)))
+  s4 = s
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s4)
+  case(1)
+     RC4=ODB_distribute4(s4, target=target4)
+  end select
+  
+  s = s4
+  deallocate(s4)
+  ODB_distribute_vecint = RC4
+
+End Function ODB_distribute_vecint
+  
+Integer(Kind=8) Function ODB_distribute_real8(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  REAL(KIND=JPRB), intent(inout)        :: s
+  INTEGER(KIND=8), intent(in), optional :: target
+
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s)
+  case(1)
+     RC4=ODB_distribute4(s, target=target4)
+  end select
+  
+  ODB_distribute_real8 = RC4
+
+End Function ODB_distribute_real8
+
+Integer(Kind=8) Function ODB_distribute_vecreal8(s, target)
+
+  Use odb_module, only : ODB_distribute4 => ODB_distribute
+
+  implicit none
+
+  REAL(KIND=JPRB), intent(inout)        :: s(:)
+  INTEGER(KIND=8), intent(in), optional :: target
+
+  INTEGER(KIND=JPIM) :: target4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  if (present(target)) target4 = target
+
+  if (present(target)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_distribute4(s)
+  case(1)
+     RC4=ODB_distribute4(s, target=target4)
+  end select
+  
+  ODB_distribute_vecreal8 = RC4
+
+End Function ODB_distribute_vecreal8
+
+Real(Kind=8) Function ODB_dsetval(handle, varname, newvalue, viewname)
+
+  Use odb_module, only : ODB_setval4 => ODB_setval
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: varname
+  REAL(KIND=JPRB), intent(in)            :: newvalue
+  character(len=*), intent(in), optional :: viewname 
+
+  INTEGER(KIND=JPIM) :: handle4
+  Real(KIND=JPRM)    :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+
+  if (present(viewname)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_setval4(handle4, varname, newvalue)
+  case(1)
+     RC4=ODB_setval4(handle4, varname, newvalue, viewname=viewname)
+  end select
+
+  ODB_dsetval = RC4
+
+End Function ODB_dsetval
+
+Integer(Kind=8) Function ODB_isetval(handle, varname, newvalue_in, viewname)
+
+  Use odb_module, only : ODB_setval4 => ODB_setval
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: handle
+  character(len=*), intent(in)           :: varname
+  INTEGER(KIND=8), intent(in)            :: newvalue_in
+  character(len=*), intent(in), optional :: viewname 
+
+  INTEGER(KIND=JPIM) :: handle4
+  INTEGER(KIND=JPIM) :: newvalue_in4
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  handle4 = handle
+  newvalue_in4 = newvalue_in
+
+  if (present(viewname)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_setval4(handle4, varname, newvalue_in4)
+  case(1)
+     RC4=ODB_setval4(handle4, varname, newvalue_in4, viewname=viewname)
+  end select
+
+  ODB_isetval = RC4
+
+End Function ODB_isetval
+
+Integer(Kind=8) Function ODB_control_word_info_vector(v,nrows,poolnos,rownums,noffset)
+
+  Use odb_module, only : ODB_control_word_info4 => ODB_control_word_info
+
+  implicit none
+
+  REAL(KIND=JPRB), intent(in)            :: v(:)
+  INTEGER(KIND=8), intent(in), optional  :: nrows, noffset
+  INTEGER(KIND=8), intent(out), optional :: poolnos(:), rownums(:)
+
+  INTEGER(KIND=JPIM)              :: nrows4, noffset4
+  INTEGER(KIND=JPIM), allocatable :: poolnos4(:), rownums4(:)
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  nrows4 = nrows
+  noffset4 = noffset
+  if (present(poolnos)) allocate(poolnos4(size(poolnos)))
+  if (present(rownums)) allocate(rownums4(size(rownums)))
+
+  if (present(nrows)) o1=1
+  if (present(poolnos)) o2=2
+  if (present(noffset)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     RC4=ODB_control_word_info4(v)
+  case(1)
+     RC4=ODB_control_word_info4(v, nrows=nrows4)
+  case(2)
+     RC4=ODB_control_word_info4(v, poolnos=poolnos4)
+  case(3)
+     RC4=ODB_control_word_info4(v, nrows=nrows4, poolnos=poolnos4)
+  case(4)
+     RC4=ODB_control_word_info4(v, noffset=noffset4)
+  case(5)
+     RC4=ODB_control_word_info4(v, nrows=nrows4, noffset=noffset4)
+  case(6)
+     RC4=ODB_control_word_info4(v, poolnos=poolnos4, noffset=noffset4)
+  case(7)
+     RC4=ODB_control_word_info4(v, nrows=nrows4, poolnos=poolnos4, noffset=noffset4)
+  end select
+  
+  poolnos = poolnos4
+  rownums = rownums4
+  if (present(poolnos)) deallocate(poolnos4)
+  if (present(rownums)) deallocate(rownums4)
+
+  ODB_control_word_info_vector = RC4
+
+End Function ODB_control_word_info_vector
+
+Integer(Kind=8) Function ODB_control_word_info_matrix(d,nrows,poolnos,rownums,noffset)
+
+  Use odb_module, only : ODB_control_word_info4 => ODB_control_word_info
+
+  implicit none
+
+  REAL(KIND=JPRB), intent(in)            :: d(:,0:)
+  INTEGER(KIND=8), intent(in), optional  :: nrows, noffset
+  INTEGER(KIND=8), intent(out), optional :: poolnos(:), rownums(:)
+
+  INTEGER(KIND=JPIM)              :: nrows4, noffset4
+  INTEGER(KIND=JPIM), allocatable :: poolnos4(:), rownums4(:)
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  nrows4 = nrows
+  noffset4 = noffset
+  if (present(poolnos)) allocate(poolnos4(size(poolnos)))
+  if (present(rownums)) allocate(rownums4(size(rownums)))
+
+  if (present(nrows)) o1=1
+  if (present(poolnos)) o2=2
+  if (present(noffset)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     RC4=ODB_control_word_info4(d)
+  case(1)
+     RC4=ODB_control_word_info4(d, nrows=nrows4)
+  case(2)
+     RC4=ODB_control_word_info4(d, poolnos=poolnos4)
+  case(3)
+     RC4=ODB_control_word_info4(d, nrows=nrows4, poolnos=poolnos4)
+  case(4)
+     RC4=ODB_control_word_info4(d, noffset=noffset4)
+  case(5)
+     RC4=ODB_control_word_info4(d, nrows=nrows4, noffset=noffset4)
+  case(6)
+     RC4=ODB_control_word_info4(d, poolnos=poolnos4, noffset=noffset4)
+  case(7)
+     RC4=ODB_control_word_info4(d, nrows=nrows4, poolnos=poolnos4, noffset=noffset4)
+  end select
+  
+  poolnos = poolnos4
+  rownums = rownums4
+  if (present(poolnos)) deallocate(poolnos4)
+  if (present(rownums)) deallocate(rownums4)
+
+  ODB_control_word_info_matrix = RC4
+
+End Function ODB_control_word_info_matrix
+
+Integer(Kind=8) Function ODB_iduplchk(a, nrows, ncols, npkcols, colidx, tol, dupl_with, idx)
+
+  Use odb_module, only : ODB_duplchk4 => ODB_duplchk
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)         :: nrows, ncols, npkcols
+  INTEGER(KIND=8), intent(out)        :: dupl_with(:)
+  INTEGER(KIND=8), intent(inout)      :: a(:,:)
+  INTEGER(KIND=8),  intent(in)        :: colidx(npkcols)
+  INTEGER(KIND=JPIM), intent(in)      :: tol(npkcols)
+  INTEGER(KIND=8),intent(in),optional :: idx(:)
+
+  INTEGER(KIND=JPIM) :: nrows4, ncols4, npkcols4
+  INTEGER(KIND=JPIM), allocatable :: dupl_with4(:)
+  INTEGER(KIND=JPIM), allocatable :: a4(:,:)
+  INTEGER(KIND=JPIM) :: colidx4(npkcols)
+  INTEGER(KIND=JPIM) :: tol4(npkcols)
+  INTEGER(KIND=JPIM), allocatable :: idx4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  nrows4 = nrows
+  ncols4 = ncols
+  npkcols4 = npkcols
+  a4 = a
+  colidx4 = colidx
+  tol4 = tol
+  idx4 = idx
+  allocate(dupl_with4(size(dupl_with)))
+  if (present(idx)) allocate(idx4(size(idx)))
+  allocate(a4(size(a,1),size(a,2)))
+
+  if (present(idx)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_duplchk4(a4, nrows4, ncols4, npkcols4, colidx4, tol4, dupl_with4)
+  case(1)
+     RC4=ODB_duplchk4(a4, nrows4, ncols4, npkcols4, colidx4, tol4, dupl_with4, idx=idx4)
+  end select
+
+  a = a4
+  dupl_with = dupl_with4
+
+  deallocate(dupl_with4)
+  if (present(idx)) deallocate(idx4)
+  deallocate(a4)
+
+  ODB_iduplchk = RC4
+
+End Function ODB_iduplchk
+
+Integer(Kind=8) Function ODB_dduplchk(a, nrows, ncols, npkcols, colidx, tol, dupl_with, idx)
+
+  Use odb_module, only : ODB_duplchk4 => ODB_duplchk
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)         :: nrows, ncols, npkcols
+  INTEGER(KIND=8), intent(out)        :: dupl_with(:)
+  REAL(KIND=JPRB), intent(inout)      :: a(:,:)
+  INTEGER(KIND=8),  intent(in)        :: colidx(npkcols)
+  REAL(KIND=JPRB), intent(in)      :: tol(npkcols)
+  INTEGER(KIND=8),intent(in),optional :: idx(:)
+
+  INTEGER(KIND=JPIM) :: nrows4, ncols4, npkcols4
+  INTEGER(KIND=JPIM), allocatable :: dupl_with4(:)
+  INTEGER(KIND=JPIM) :: colidx4(npkcols)
+  INTEGER(KIND=JPIM), allocatable :: idx4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  nrows4 = nrows
+  ncols4 = ncols
+  npkcols4 = npkcols
+  colidx4 = colidx
+  if (present(idx)) then
+    allocate(idx4(size(idx)))
+    idx4 = idx
+  endif
+  allocate(dupl_with4(size(dupl_with)))
+
+  if (present(idx)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_duplchk4(a, nrows4, ncols4, npkcols4, colidx4, tol, dupl_with4)
+  case(1)
+     RC4=ODB_duplchk4(a, nrows4, ncols4, npkcols4, colidx4, tol, dupl_with4, idx=idx4)
+  end select
+
+  if (present(idx)) deallocate(idx4)
+  deallocate(dupl_with4)
+
+  ODB_dduplchk = RC4
+
+End Function ODB_dduplchk
+
+Integer(Kind=8) Function ODB_igroupify(a, idx, off, cnt, grplist)
+
+  Use odb_module, only : ODB_groupify4 => ODB_groupify
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: a(:)
+  INTEGER(KIND=8), intent(in) , optional :: idx(:)
+  INTEGER(KIND=8), intent(out), optional :: off(:), cnt(:)
+  INTEGER(KIND=8), intent(out), optional :: grplist(:)
+
+  INTEGER(KIND=JPIM), allocatable :: a4(:)
+  INTEGER(KIND=JPIM), allocatable :: idx4(:)
+  INTEGER(KIND=JPIM), allocatable :: off4(:), cnt4(:)
+  INTEGER(KIND=JPIM), allocatable :: grplist4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0
+
+  allocate(a4(size(a)))
+  a4 = a
+  if (present(idx)) then
+    allocate(idx4(size(idx)))
+    idx4 = idx
+  endif
+  if (present(off)) allocate(off4(size(off)))
+  if (present(cnt)) allocate(cnt4(size(cnt)))
+  if (present(grplist)) allocate(grplist4(size(grplist)))
+  
+  if (present(idx)) o1=1
+  if (present(off)) o2=2
+  if (present(cnt)) o3=4
+  if (present(grplist)) o4=8
+  o=o1+o2+o3+o4
+
+  select case(o)
+  case(0)
+     RC4=ODB_groupify4(a4)
+  case(1)
+     RC4=ODB_groupify4(a4, idx=idx4)
+  case(2)
+     RC4=ODB_groupify4(a4, off=off4)
+  case(3)
+     RC4=ODB_groupify4(a4, idx=idx4, off=off4)
+  case(4)
+     RC4=ODB_groupify4(a4, cnt=cnt4)
+  case(5)
+     RC4=ODB_groupify4(a4, idx=idx4, cnt=cnt4)
+  case(6)
+     RC4=ODB_groupify4(a4, off=off4, cnt=cnt4)
+  case(7)
+     RC4=ODB_groupify4(a4, idx=idx4, off=off4, cnt=cnt4)
+  case(8)
+     RC4=ODB_groupify4(a4, grplist=grplist4)
+  case(9)
+     RC4=ODB_groupify4(a4, idx=idx4, grplist=grplist4)
+  case(10)
+     RC4=ODB_groupify4(a4, off=off4, grplist=grplist4)
+  case(11)
+     RC4=ODB_groupify4(a4, idx=idx4, off=off4, grplist=grplist4)
+  case(12)
+     RC4=ODB_groupify4(a4, cnt=cnt4, grplist=grplist4)
+  case(13)
+     RC4=ODB_groupify4(a4, idx=idx4, cnt=cnt4, grplist=grplist4)
+  case(14)
+     RC4=ODB_groupify4(a4, off=off4, cnt=cnt4, grplist=grplist4)
+  case(15)
+     RC4=ODB_groupify4(a4, idx=idx4, off=off4, cnt=cnt4, grplist=grplist4)
+  end select
+  
+  off = off4
+  cnt = cnt4
+  grplist = grplist4
+  deallocate(a4)
+  if (present(idx)) deallocate(idx4)
+  if (present(off)) deallocate(off4)
+  if (present(cnt)) deallocate(cnt4)
+  if (present(grplist)) deallocate(grplist4)
+
+  ODB_igroupify = RC4
+
+End Function ODB_igroupify
+  
+Integer(Kind=8) Function ODB_dgroupify(a, idx, off, cnt, grplist)
+
+  Use odb_module, only : ODB_groupify4 => ODB_groupify
+
+  implicit none
+
+  REAL(KIND=JPRB), intent(in)            :: a(:)
+  INTEGER(KIND=8), intent(in) , optional :: idx(:)
+  INTEGER(KIND=8), intent(out), optional :: off(:), cnt(:)
+  REAL(KIND=JPRB), intent(out), optional :: grplist(:)
+
+  INTEGER(KIND=JPIM), allocatable :: idx4(:)
+  INTEGER(KIND=JPIM), allocatable :: off4(:), cnt4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0
+
+  if (present(idx)) then
+    allocate(idx4(size(idx)))
+    idx4 = idx
+  endif
+  if (present(off)) allocate(off4(size(off)))
+  if (present(cnt)) allocate(cnt4(size(cnt)))
+  
+  if (present(idx)) o1=1
+  if (present(off)) o2=2
+  if (present(cnt)) o3=4
+  if (present(grplist)) o4=8
+  o=o1+o2+o3+o4
+
+  select case(o)
+  case(0)
+     RC4=ODB_groupify4(a)
+  case(1)
+     RC4=ODB_groupify4(a, idx=idx4)
+  case(2)
+     RC4=ODB_groupify4(a, off=off4)
+  case(3)
+     RC4=ODB_groupify4(a, idx=idx4, off=off4)
+  case(4)
+     RC4=ODB_groupify4(a, cnt=cnt4)
+  case(5)
+     RC4=ODB_groupify4(a, idx=idx4, cnt=cnt4)
+  case(6)
+     RC4=ODB_groupify4(a, off=off4, cnt=cnt4)
+  case(7)
+     RC4=ODB_groupify4(a, idx=idx4, off=off4, cnt=cnt4)
+  case(8)
+     RC4=ODB_groupify4(a, grplist=grplist)
+  case(9)
+     RC4=ODB_groupify4(a, idx=idx4, grplist=grplist)
+  case(10)
+     RC4=ODB_groupify4(a, off=off4, grplist=grplist)
+  case(11)
+     RC4=ODB_groupify4(a, idx=idx4, off=off4, grplist=grplist)
+  case(12)
+     RC4=ODB_groupify4(a, cnt=cnt4, grplist=grplist)
+  case(13)
+     RC4=ODB_groupify4(a, idx=idx4, cnt=cnt4, grplist=grplist)
+  case(14)
+     RC4=ODB_groupify4(a, off=off4, cnt=cnt4, grplist=grplist)
+  case(15)
+     RC4=ODB_groupify4(a, idx=idx4, off=off4, cnt=cnt4, grplist=grplist)
+  end select
+  
+  off = off4
+  cnt = cnt4
+  if (present(idx)) deallocate(idx4)
+  if (present(off)) deallocate(off4)
+  if (present(cnt)) deallocate(cnt4)
+
+  ODB_dgroupify = RC4
+
+End Function ODB_dgroupify
+
+Integer(Kind=8) Function ODB_itolsearch(tol, v, ksta, kend, index)
+
+  Use odb_module, only : ODB_tolsearch4 => ODB_tolsearch
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: ksta, kend
+  INTEGER(KIND=8), intent(in)           :: tol, v(:)
+  INTEGER(KIND=8), intent(in), OPTIONAL :: index(:)
+
+  INTEGER(KIND=JPIM)              :: ksta4, kend4, tol4
+  INTEGER(KIND=JPIM), allocatable :: v4(:)
+  INTEGER(KIND=JPIM), allocatable :: index4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  ksta4 = ksta
+  kend4 = kend
+  tol4 = tol
+  allocate(v4(size(v)))
+  v4 = v
+  if (present(index)) then
+    allocate(index4(size(index)))
+    index4 = index
+  endif
+
+  if (present(index)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_tolsearch4(tol4, v4, ksta4, kend4)
+  case(1)
+     RC4=ODB_tolsearch4(tol4, v4, ksta4, kend4, index=index4)
+  end select
+  
+  deallocate(v4)
+  if (present(index)) deallocate(index4)
+
+  ODB_itolsearch = RC4
+
+End Function ODB_itolsearch
+  
+Integer(Kind=8) Function ODB_dtolsearch(tol, v, ksta, kend, index)
+
+  Use odb_module, only : ODB_tolsearch4 => ODB_tolsearch
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)           :: ksta, kend
+  REAL(KIND=JPRB), intent(in)           :: tol, v(:)
+  INTEGER(KIND=8), intent(in), OPTIONAL :: index(:)
+
+  INTEGER(KIND=JPIM)              :: ksta4, kend4
+  INTEGER(KIND=JPIM), allocatable :: index4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0
+
+  ksta4 = ksta
+  kend4 = kend
+  if (present(index)) then
+    allocate(index4(size(index)))
+    index4 = index
+  endif
+
+  if (present(index)) o1=1
+  o=o1
+
+  select case(o)
+  case(0)
+     RC4=ODB_tolsearch4(tol, v, ksta4, kend4)
+  case(1)
+     RC4=ODB_tolsearch4(tol, v, ksta4, kend4, index=index4)
+  end select
+  
+  if (present(index)) deallocate(index4)
+
+  ODB_dtolsearch = RC4
+
+End Function ODB_dtolsearch
+
+Integer(Kind=8) Function ODB_ibinsearch(refval, v, ksta, kend, index, cluster_start, cluster_end)
+  
+  Use odb_module, only : ODB_binsearch4 => ODB_binsearch
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: ksta, kend
+  INTEGER(KIND=8), intent(in)            :: v(:), refval
+  INTEGER(KIND=8), intent(in) , OPTIONAL :: index(:)
+  INTEGER(KIND=8), intent(out), OPTIONAL :: cluster_start, cluster_end
+
+  INTEGER(KIND=JPIM)              :: ksta4, kend4, refval4
+  INTEGER(KIND=JPIM), allocatable :: v4(:)
+  INTEGER(KIND=JPIM), allocatable :: index4(:)
+  INTEGER(KIND=JPIM)              :: cluster_start4, cluster_end4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  ksta4 = ksta
+  kend4 = kend
+  allocate(v4(size(v)))
+  v4 = v
+  refval4 = refval
+  if (present(index)) then
+    allocate(index4(size(index)))
+    index4 = index
+  endif
+
+  if (present(index)) o1=1
+  if (present(cluster_start)) o2=2
+  if (present(cluster_end)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4)
+  case(1)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, index=index4)
+  case(2)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, cluster_start=cluster_start4)
+  case(3)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, index=index4, cluster_start=cluster_start4)
+  case(4)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, cluster_end=cluster_end4)
+  case(5)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, index=index4, cluster_end=cluster_end4)
+  case(6)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, cluster_start=cluster_start4, cluster_end=cluster_end4)
+  case(7)
+     RC4=ODB_binsearch4(refval4, v4, ksta4, kend4, index=index4, cluster_start=cluster_start4, cluster_end=cluster_end4)
+  end select
+
+  if (present(cluster_start)) cluster_start4 = cluster_start
+  if (present(cluster_end)) cluster_end4 = cluster_end
+  if (present(index)) deallocate(index4)
+
+  ODB_ibinsearch = RC4
+
+End Function ODB_ibinsearch
+
+Integer(Kind=8) Function ODB_dbinsearch(refval, v, ksta, kend, index, cluster_start, cluster_end)
+  
+  Use odb_module, only : ODB_binsearch4 => ODB_binsearch
+
+  implicit none
+
+  INTEGER(KIND=8), intent(in)            :: ksta, kend
+  REAL(KIND=JPRB), intent(in)            :: v(:), refval
+  INTEGER(KIND=8), intent(in) , OPTIONAL :: index(:)
+  INTEGER(KIND=8), intent(out), OPTIONAL :: cluster_start, cluster_end
+
+  INTEGER(KIND=JPIM)              :: ksta4, kend4
+  INTEGER(KIND=JPIM), allocatable :: index4(:)
+  INTEGER(KIND=JPIM)              :: cluster_start4, cluster_end4
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0
+
+  ksta4 = ksta
+  kend4 = kend
+  if (present(index)) then
+    allocate(index4(size(index)))
+    index4 = index
+  endif
+
+  if (present(index)) o1=1
+  if (present(cluster_start)) o2=2
+  if (present(cluster_end)) o3=4
+  o=o1+o2+o3
+
+  select case(o)
+  case(0)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4)
+  case(1)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, index=index4)
+  case(2)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, cluster_start=cluster_start4)
+  case(3)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, index=index4, cluster_start=cluster_start4)
+  case(4)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, cluster_end=cluster_end4)
+  case(5)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, index=index4, cluster_end=cluster_end4)
+  case(6)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, cluster_start=cluster_start4, cluster_end=cluster_end4)
+  case(7)
+     RC4=ODB_binsearch4(refval, v, ksta4, kend4, index=index4, cluster_start=cluster_start4, cluster_end=cluster_end4)
+  end select
+
+  if (present(cluster_start)) cluster_start4 = cluster_start
+  if (present(cluster_end)) cluster_end4 = cluster_end
+
+  ODB_dbinsearch = RC4
+
+End Function ODB_dbinsearch
+
+Integer(Kind=8) Function ODB_iaggregate(oper, a, nrows, target, idx, group_by, grplist, result)
+
+  Use odb_module, only : ODB_aggregate4 => ODB_aggregate
+
+  implicit none
+
+  CHARACTER(len=*), intent(in)            :: oper
+  INTEGER(KIND=8) , intent(in)            :: nrows, target
+  INTEGER(KIND=8) , intent(inout)         :: a(:,:)
+  INTEGER(KIND=8) , intent(in) , optional :: group_by(:), idx(:)
+  INTEGER(KIND=8) , intent(out), optional :: grplist(:,:)
+  REAL(KIND=JPRB) , intent(out), optional :: result(:)
+
+  INTEGER(KIND=JPIM)               :: nrows4, target4
+  INTEGER(KIND=JPIM), allocatable  :: a4(:,:)
+  INTEGER(KIND=JPIM), allocatable  :: group_by4(:), idx4(:)
+  INTEGER(KIND=JPIM), allocatable  :: grplist4(:,:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0
+
+  nrows4 = nrows
+  target4 = target
+  allocate(a4(size(a,1),size(a,2)))
+  a4 = a
+
+  if (present(group_by)) then
+    allocate(group_by4(size(group_by)))
+    group_by4 = group_by
+  endif
+  if (present(idx)) then
+    allocate(idx4(size(idx)))
+    idx4 = idx
+  endif
+  if (present(grplist)) then
+    allocate(grplist4(size(grplist,1),size(grplist,2)))
+  endif
+
+  if (present(idx)) o1=1
+  if (present(group_by)) o2=2
+  if (present(grplist)) o3=4
+  if (present(result)) o4=8
+  o=o1+o2+o3+o4
+
+  select case(o)
+  case(0)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4)
+  case(1)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4)
+  case(2)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, group_by=group_by4)
+  case(3)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, group_by=group_by4)
+  case(4)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, grplist=grplist4)
+  case(5)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, grplist=grplist4)
+  case(6)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, group_by=group_by4, grplist=grplist4)
+  case(7)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, group_by=group_by4, grplist=grplist4)
+  case(8)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, result=result)
+  case(9)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, result=result)
+  case(10)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, group_by=group_by4, result=result)
+  case(11)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, group_by=group_by4, result=result)
+  case(12)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, grplist=grplist4, result=result)
+  case(13)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, grplist=grplist4, result=result)
+  case(14)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, group_by=group_by4, grplist=grplist4, result=result)
+  case(15)
+     RC4=ODB_aggregate4(oper, a4, nrows4, target4, idx=idx4, group_by=group_by4, grplist=grplist4, result=result)
+  end select
+
+  a = a4
+  deallocate(a4)
+  deallocate(idx4)
+  deallocate(group_by4)
+  if (present(grplist)) then
+    grplist4 = grplist
+    deallocate(grplist4)
+  endif
+
+  ODB_iaggregate = RC4
+
+End Function ODB_iaggregate
+
+Integer(Kind=8) Function ODB_daggregate(oper, a, nrows, target, idx, group_by, grplist, result)
+
+  Use odb_module, only : ODB_aggregate4 => ODB_aggregate
+
+  implicit none
+
+  CHARACTER(len=*), intent(in)            :: oper
+  INTEGER(KIND=8) , intent(in)            :: nrows, target
+  REAL(KIND=JPRB) , intent(inout)         :: a(:,:)
+  INTEGER(KIND=8) , intent(in) , optional :: group_by(:), idx(:)
+  REAL(KIND=JPRB) , intent(out), optional :: grplist(:,:)
+  REAL(KIND=JPRB) , intent(out), optional :: result(:)
+
+  INTEGER(KIND=JPIM)               :: nrows4, target4
+  INTEGER(KIND=JPIM), allocatable  :: group_by4(:), idx4(:)
+
+  INTEGER(KIND=JPIM) :: RC4
+
+  integer :: o=0,o1=0,o2=0,o3=0,o4=0
+
+  nrows4 = nrows
+  target4 = target
+
+  if (present(group_by)) then
+    allocate(group_by4(size(group_by)))
+    group_by4 = group_by
+  endif
+  if (present(idx)) then
+    allocate(idx4(size(idx)))
+    idx4 = idx
+  endif
+
+  if (present(idx)) o1=1
+  if (present(group_by)) o2=2
+  if (present(grplist)) o3=4
+  if (present(result)) o4=8
+  o=o1+o2+o3+o4
+
+  select case(o)
+  case(0)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4)
+  case(1)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4)
+  case(2)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, group_by=group_by4)
+  case(3)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, group_by=group_by4)
+  case(4)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, grplist=grplist)
+  case(5)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, grplist=grplist)
+  case(6)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, group_by=group_by4, grplist=grplist)
+  case(7)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, group_by=group_by4, grplist=grplist)
+  case(8)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, result=result)
+  case(9)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, result=result)
+  case(10)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, group_by=group_by4, result=result)
+  case(11)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, group_by=group_by4, result=result)
+  case(12)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, grplist=grplist, result=result)
+  case(13)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, grplist=grplist, result=result)
+  case(14)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, group_by=group_by4, grplist=grplist, result=result)
+  case(15)
+     RC4=ODB_aggregate4(oper, a, nrows4, target4, idx=idx4, group_by=group_by4, grplist=grplist, result=result)
+  end select
+
+  deallocate(idx4)
+  deallocate(group_by4)
+
+  ODB_daggregate = RC4
+
+End Function ODB_daggregate
+
+#endif
+End Module ODB_MODULE8
diff --git a/odb/src/module/odbgetput.F90 b/odb/src/module/odbgetput.F90
new file mode 100644
index 0000000..b824422
--- /dev/null
+++ b/odb/src/module/odbgetput.F90
@@ -0,0 +1,345 @@
+MODULE odbgetput
+
+USE PARKIND1  ,ONLY : JPIM,JPIB,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+USE OML_MOD    ,ONLY : OML_IN_PARALLEL
+
+USE odbshared ! The shared (mainly internal) stuff
+USE odbmp ! The message passing module
+USE odbutil ! Misc utilities 
+USE str, only : toupper, sadjustl, sadjustr
+USE odbsort, only : keysort
+#ifdef NAG
+USE F90_UNIX_IO, ONLY: FLUSH
+#endif
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+#ifndef USE_CTRIM
+#define ctrim(x) x
+#define CTRIM(x) x
+#endif
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+#include "fodb_checkviewreg.h"
+
+INTERFACE ODB_put
+MODULE PROCEDURE &
+  & ODB_dput
+END INTERFACE
+
+INTERFACE ODB_get
+MODULE PROCEDURE &
+  & ODB_dget
+END INTERFACE
+
+INTERFACE ODB_ctrlw_sort
+MODULE PROCEDURE &
+  & ODB_dctrlw_sort
+END INTERFACE
+
+public :: ODB_gethandle
+public :: ODB_addview
+public :: ODB_get
+public :: ODB_put
+public :: ODB_ctrlw_sort
+public :: ODB_getsize
+
+CONTAINS
+
+FUNCTION ODB_getsize(handle, dtname, nrows, ncols, nra, poolno, using, &
+     & ncols_aux, colaux) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+INTEGER(KIND=JPIM), intent(out)          :: nrows, ncols
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(out), optional:: nra
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, using
+INTEGER(KIND=JPIM), intent(out), optional:: ncols_aux, colaux(:)
+INTEGER(KIND=JPIM) :: rc, ipoolno, info(6), irecur, using_it, idummy(0), icols_aux, iret, icols
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETSIZE',0,ZHOOK_HANDLE)
+
+rc = 0
+nrows = 0
+ncols = 0
+if (odbHcheck(handle, 'ODB_getsize')) then
+  ipoolno = get_poolno(handle, poolno)
+  CALL fODB_checkviewreg(handle, ctrim(dtname), rc, using=using)
+  using_it = 0
+  if (present(using)) using_it = using
+  irecur = 0
+  CALL cODB_getsize(handle, ipoolno, ctrim(dtname), nrows, icols, irecur, rc, using_it)
+  ncols = icols
+  if (db_trace) then
+    info(1) = ipoolno
+    info(2) = rc
+    info(3) = nrows
+    info(4) = ncols
+    info(5) = ODB_lda(nrows)
+    info(6) = using_it
+    CALL cODB_trace(handle, -1,'ODB_getsize:'//dtname, info, 5)
+  endif
+  if (rc < 0) then
+    CALL ODB_abort('ODB_getsize',&
+     &'Cannot get sizes of VIEW/TABLE="'//&
+     &trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+  iret = 0
+  if (present(colaux)) then
+    colaux(:) = 0
+    CALL cODB_getsize_aux(handle, ipoolno, ctrim(dtname), icols, icols_aux, colaux, size(colaux), iret, using_it)
+    if (present(ncols_aux)) ncols_aux = icols_aux
+  else if (present(ncols_aux)) then
+    CALL cODB_getsize_aux(handle, ipoolno, ctrim(dtname), icols, ncols_aux, idummy,            0, iret, using_it)
+  endif
+  if (iret < 0) then
+    CALL ODB_abort('ODB_getsize[aux-data]',&
+     &'Cannot obtain auxiliary sizeinfo for VIEW/TABLE="'//&
+     &trim(dtname)//'"',&
+     &iret)
+    goto 99999
+  endif
+endif
+if (present(nra)) then
+  nra = ODB_lda(nrows)
+endif
+99999 continue
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETSIZE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_getsize
+
+RECURSIVE FUNCTION ODB_gethandle(handle, dtname, addview, abort, using) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)    :: dtname
+logical, intent(in), optional   :: addview, abort
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+INTEGER(KIND=JPIM) :: rc, using_it
+logical LLaddview, LLabort
+!-- can't have Dr.Hook yet in (potentially) recursive routines
+!REAL(KIND=JPRB) ZHOOK_HANDLE
+!IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETHANDLE',0,ZHOOK_HANDLE)
+rc = 0
+if (odbHcheck(handle, 'ODB_gethandle')) then
+  LLaddview = .FALSE.
+  if (present(addview)) LLaddview = addview
+  LLabort = .TRUE.
+  if (present(abort)) LLabort = abort
+  using_it = 0
+  if (present(using)) using_it = using
+  CALL cODB_gethandle(handle, ctrim(dtname), rc, using_it)
+  if (LLaddview .and. rc <= 0) then
+    rc = ODB_addview(handle, dtname, abort=.FALSE.)
+    CALL cODB_gethandle(handle, ctrim(dtname), rc, using_it)
+  endif
+  if (rc <= 0 .and. LLabort) then
+    CALL ODB_abort('ODB_gethandle',&
+     &'Invalid VIEW/TABLE-handle for "'//trim(dtname)//'"',&
+     &rc)
+    goto 99999
+  endif
+endif
+99999 continue
+!-- can't have Dr.Hook yet in (potentially) recursive routines
+!IF (LHOOK) CALL DR_HOOK('ODB:ODB_GETHANDLE',1,ZHOOK_HANDLE)
+END FUNCTION ODB_gethandle
+
+RECURSIVE FUNCTION ODB_addview(handle, dtname,&
+     &viewfile,&
+     &select, uniqueby, from, where, orderby, sortby,&
+     &query, &
+     &set, abort) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)          :: handle
+character(len=*), intent(in) :: dtname
+character(len=*), intent(in),optional :: viewfile
+character(len=*), intent(in),optional :: select, uniqueby
+character(len=*), intent(in),optional :: from, where
+character(len=*), intent(in),optional :: orderby, sortby
+character(len=*), intent(in),optional :: query
+character(len=*), intent(in),optional :: set(:)
+logical, intent(in), optional :: abort
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(1)
+INTEGER(KIND=JPIM) :: rc, nset, j
+logical on_error, recreate, is_table, fromfile, LLabort
+character(len=maxstrlen) CL_where, CL_orderby
+character(len=maxstrlen) CL_uniqueby, CL_set
+character(len=maxstrlen) CL_query, CL_from
+character(len=maxvarlen) dbname
+!-- can't have Dr.Hook yet in (potentially) recursive routines
+!REAL(KIND=JPRB) ZHOOK_HANDLE
+!IF (LHOOK) CALL DR_HOOK('ODB:ODB_ADDVIEW',0,ZHOOK_HANDLE)
+
+rc = 0
+
+is_table = .FALSE.
+if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+
+if (is_table) goto 99999
+
+CALL cODB_trace(handle, 1,'ODB_addview:'//dtname, idummy_arr, 0)
+
+LLabort = .TRUE.
+if (present(abort)) LLabort = abort
+
+fromfile = present(viewfile)
+
+on_error = .not. odbHcheck(handle, 'ODB_addview', abort=.FALSE.)
+on_error = on_error .or.&
+     &(fromfile .and.&
+     &(present(select) .or. present(from) .or. present(where)))
+!!on_error = on_error .or. (present(select) .and. .not. present(from))
+on_error = on_error .or. (.not. present(select) .and. present(from))
+on_error = on_error .or.&
+     &(present(where) .and.&
+     &(.not. present(select) .and. .not. present(from)))
+on_error = on_error .or.(present(orderby) .and. present(sortby))
+on_error = on_error .or.(fromfile .and. present(query))
+on_error = on_error .or. &
+     &((present(select) .or. present(from) .or. present(where)).and.&
+     &present(query))
+
+if (on_error) then
+  CALL ODB_abort('ODB_addview',&
+   &'Conflicting and/or ambiguous arguments in VIEW="'//&
+   &trim(dtname)//'"')
+  rc = -2
+  goto 99999
+else
+  dbname = db(handle)%name
+  recreate = (present(select) .and. present(from))
+  recreate = recreate .or. present(query)
+  if (ODBMP_myproc == 1) then
+    if (recreate) then
+
+      if (present(uniqueby)) then
+        CL_uniqueby = trim(sadjustl(uniqueby))
+      else
+        CL_uniqueby = ' '
+      endif
+
+      if (present(from)) then
+        CL_from = trim(sadjustl(from))
+      else
+        CL_from = '*' 
+      endif
+
+      if (present(where)) then
+        CL_where = trim(sadjustl(where))
+      else
+        CL_where = ' '
+      endif
+
+      if (present(orderby)) then
+        CL_orderby = trim(sadjustl(orderby))
+      else if (present(sortby)) then
+        CL_orderby = trim(sadjustl(sortby))
+      else
+        CL_orderby = ' '
+      endif
+
+      nset = 0
+      if (present(set)) nset = size(set)
+      CL_set = ' '
+      do j=1,nset
+        CL_set = trim(CL_set)//'SET '//trimadjL(set(j))//';'//char(10)
+      enddo
+
+      if (present(query)) then
+        CL_query = trim(sadjustl(query))
+      else
+        CL_query = ' '
+      endif
+
+      CALL cODB_makeview(&
+       &handle,&
+       &dtname,&
+       &'',&
+       &trimadjL(select),&
+       &trim(CL_uniqueby),&
+       &trimadjL(CL_from),&
+       &trim(CL_where), &
+       &trim(CL_orderby), &
+       &trim(CL_set),&
+       &trim(CL_query),&
+       &rc)  
+
+      if (rc < 0 .and. LLabort) then
+        CALL ODB_abort('ODB_addview',&
+         &'Compilation failed for VIEW="'//&
+         &trim(dtname)//'", database="'//trim(dbname)//'"')
+      endif
+      if (rc < 0) goto 99999
+
+    else if (fromfile) then
+
+      CALL cODB_makeview(&
+       &handle, &
+       &dtname,&
+       &trimadjL(viewfile),&
+       &'',&
+       &'',&
+       &'',&
+       &'', &
+       &'', &
+       &'',&
+       &'',&
+       &rc)
+
+      if (rc < 0 .and. LLabort) then
+        CALL ODB_abort('ODB_addview',&
+         &'Compilation failed for VIEW="'//&
+         &trim(dtname)//'", viewfile="'//&
+         &trim(viewfile)//'", database="'//trim(dbname)//'"')
+      endif
+      if (rc < 0) goto 99999
+
+    endif
+  endif
+
+  if (recreate .or. fromfile) then
+    CALL ODBMP_sync()
+    rc = 0
+  else ! Check if already registered
+    rc = ODB_gethandle(handle, dtname, abort=.FALSE.)    
+  endif
+
+  ! Add only if not already added (or recreate/fromfile)
+  if (rc <= 0) CALL cODB_linkview(handle, dtname, rc)
+
+  if (rc < 0 .and. LLabort) then
+    CALL ODB_abort('ODB_addview',&
+     &'Linking failed for VIEW="'//&
+     &trim(dtname)//'", database="'//trim(dbname)//'"')
+  endif
+  if (rc < 0) goto 99999
+
+  rc = ODB_gethandle(handle, dtname)
+endif
+
+idummy_arr = rc
+CALL cODB_trace(handle, 0,'ODB_addview:'//dtname, idummy_arr, 1)
+
+99999 continue
+!-- can't have Dr.Hook yet in (potentially) recursive routines
+!IF (LHOOK) CALL DR_HOOK('ODB:ODB_ADDVIEW',1,ZHOOK_HANDLE)
+END FUNCTION ODB_addview
+
+#undef REAL_VERSION
+
+#define REAL_VERSION 8
+#include "fodb.h"
+#undef REAL_VERSION
+
+#ifndef USE_CTRIM
+#undef ctrim
+#undef CTRIM
+#endif
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odbgetput
diff --git a/odb/src/module/odbio_msgpass.F90 b/odb/src/module/odbio_msgpass.F90
new file mode 100644
index 0000000..5879b07
--- /dev/null
+++ b/odb/src/module/odbio_msgpass.F90
@@ -0,0 +1,1395 @@
+MODULE odbio_msgpass
+! A module used by both msgpass_loaddata and msgpass_storedata 
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+USE odb_module
+USE MPL_MODULE
+use oml_mod, only : oml_set_lock, oml_unset_lock, oml_my_thread
+
+IMPLICIT NONE
+
+SAVE
+PUBLIC
+INTEGER(KIND=JPIM), parameter   :: nstat = 4
+INTEGER(KIND=JPIM), parameter   :: ISTAT_NBYTES  = 1
+INTEGER(KIND=JPIM), parameter   :: ISTAT_NROWS   = 2
+INTEGER(KIND=JPIM), parameter   :: ISTAT_NCOLS   = 3
+INTEGER(KIND=JPIM), parameter   :: ISTAT_UPDATED = 4
+
+INTEGER(KIND=JPIM), parameter   :: sizeof_int = ODB_SIZEOF_INT
+
+CONTAINS
+
+
+
+
+SUBROUTINE io_error(cdmsg, krc, kexpected, kpoolno, filename, kdata)
+
+IMPLICIT NONE
+character(len=*), intent(in)            :: cdmsg
+INTEGER(KIND=JPIM), intent(in)          :: krc, kexpected, kpoolno
+INTEGER(KIND=JPIM), intent(in),optional :: kdata(:)
+INTEGER(KIND=JPIM)                      :: isize, ilen
+character(len=4096)                     :: filename
+REAL(KIND=JPRB)                         :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('IO_ERROR',0,ZHOOK_HANDLE)
+write(0,*) ODBMP_myproc,': '//cdmsg
+ilen = len_trim(filename)
+if (ilen > 0) write(0,*) ODBMP_myproc,': filename="'//filename(1:ilen)//'"'
+write(0,*) ODBMP_myproc,': krc, kexpected, kpoolno=',krc, kexpected, kpoolno
+if (present(kdata)) then
+  isize = size(kdata)
+  if (isize > 0) then
+    write(0,*) ODBMP_myproc,': kdata(1:',isize,')=',kdata(:)
+  endif
+endif
+CALL ODB_abort('ODBIO_MSGPASS(io_error)', cdmsg, krc)
+IF (LHOOK) CALL DR_HOOK('IO_ERROR',1,ZHOOK_HANDLE)
+END SUBROUTINE io_error
+
+
+
+
+
+SUBROUTINE allocate_incore(incore, kw, kretcode)
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(in)               :: kw
+INTEGER(KIND=JPIM), intent(out)              :: kretcode
+! Can't have INTENT on NEC for POINTER
+! INTEGER(KIND=JPIM), pointer, intent(out)   :: incore(:)
+INTEGER(KIND=JPIM), pointer                  :: incore(:)
+
+INTEGER(KIND=JPIM)                           :: isize
+REAL(KIND=JPRB)                              :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_INCORE',0,ZHOOK_HANDLE)
+isize = 0
+if (associated(incore)) isize = size(incore)
+if (isize == 0 .OR. isize < kw) then
+  if (associated(incore)) deallocate(incore)
+  allocate(incore(kw))
+  isize = size(incore)
+endif
+kretcode = isize
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_INCORE',1,ZHOOK_HANDLE)
+END SUBROUTINE allocate_incore
+
+
+
+
+
+!J---Start----
+SUBROUTINE allocate_jncore(jncore, kw, kretcode)
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(in)               :: kw
+INTEGER(KIND=JPIM), intent(out)              :: kretcode
+! Can't have INTENT on NEC for POINTER
+! INTEGER(KIND=JPIM), pointer, intent(out) :: jncore(:)
+INTEGER(KIND=JPIM), pointer :: jncore(:)
+
+INTEGER(KIND=JPIM)                           :: isize
+REAL(KIND=JPRB)                              :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_JNCORE',0,ZHOOK_HANDLE)
+isize = 0
+if (associated(jncore)) isize = size(jncore)
+if (isize == 0 .OR. isize < kw) then
+  if (associated(jncore)) deallocate(jncore)
+  allocate(jncore(kw))
+  isize = size(jncore)
+endif
+kretcode = isize
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_JNCORE',1,ZHOOK_HANDLE)
+END SUBROUTINE allocate_jncore
+!J---End----
+
+
+
+
+
+SUBROUTINE make_iopes(iope_map, kjtact, kfilesize, kgrpsize, knpools, &
+                      global_pool_offset, istat)
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(in) :: kfilesize  ! suggested max filesize ; in megabytes
+INTEGER(KIND=JPIM), intent(in) :: kgrpsize   ! max. no. of consecutive PEs' data, that
+                                             ! can be concatenated into one file
+INTEGER(KIND=JPIM), intent(in) :: knpools    ! no. of pools
+INTEGER(KIND=JPIM), intent(in) :: kjtact      
+INTEGER(KIND=JPIM), intent(out):: iope_map(:,:)
+INTEGER(KIND=JPIM), intent(in) :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), intent(in) :: global_pool_offset(:)
+INTEGER(KIND=JPIM)             :: pe, jm
+REAL(KIND=JPRB)                :: rfsize, rsum
+REAL(KIND=JPRB)                :: ZHOOK_HANDLE
+integer(kind=jpim), save       :: istart = 0
+!-- threshold filesize in bytes
+
+IF (LHOOK) CALL DR_HOOK('MAKE_IOPES',0,ZHOOK_HANDLE)
+rfsize = kfilesize
+rfsize = rfsize * (1024 * 1024)
+iope_map(:,1) = 0
+istart = mod(istart,kgrpsize)
+pe = 1+istart
+istart=istart+1
+rsum = 0.0_JPRB
+do jm=1,knpools
+  rsum = rsum + istat(ISTAT_NBYTES,jm,kjtact)
+  if (mod(jm-global_pool_offset(jm),kgrpsize) == 1 .OR.  &! groupsize limit exceeded
+     & rsum > rfsize) then         ! total filesize reached threshold 
+    pe = pe+1
+    rsum = istat(ISTAT_NBYTES,jm,kjtact)
+  endif
+  iope_map(jm,1) = pe  ! ... actually the poolno, where the I/O starts / switches over ;
+                       ! before use the iope_map(jm,1) is converted to iope via fastphysproc()
+enddo
+IF (LHOOK) CALL DR_HOOK('MAKE_IOPES',1,ZHOOK_HANDLE)
+END SUBROUTINE make_iopes
+
+
+
+
+
+SUBROUTINE makefilename(CD_dbname, CD_table, kpool, CD_filename)
+
+IMPLICIT NONE
+character(len=*), intent(in)  :: CD_dbname, CD_table
+INTEGER(KIND=JPIM), intent(in)         :: kpool
+character(len=*), intent(out) :: CD_filename
+character(len=20) ::  CLpool
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('MAKEFILENAME',0,ZHOOK_HANDLE)
+write(CLpool,*) kpool
+CD_filename = trim(CD_dbname)//'.'//trim(CD_table)//'.'//trim(adjustl(CLpool))
+IF (LHOOK) CALL DR_HOOK('MAKEFILENAME',1,ZHOOK_HANDLE)
+END SUBROUTINE makefilename
+
+
+
+
+
+SUBROUTINE true_dirname_and_basename(CD_filein, CD_dirname, CD_basename)
+
+IMPLICIT NONE
+character(len=*), intent(in)  :: CD_filein
+character(len=*), intent(out) :: CD_dirname, CD_basename
+character(len=len(CD_dirname) + len(CD_basename)) CLname
+INTEGER(KIND=JPIM) :: ipos, iretcode
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('TRUE_DIRNAME_AND_BASENAME',0,ZHOOK_HANDLE)
+CALL codb_truename(CD_filein, CLname, iretcode)
+ipos = SCAN(CLname(1:iretcode),'/',back=.TRUE.) ! Get the last '/' (if any)
+if (ipos <= 0) then
+  CD_dirname = '.'
+  CD_basename = CLname(1:iretcode)
+else
+  CD_dirname = CLname(1:ipos-1)
+  CD_basename = CLname(ipos+1:iretcode)
+endif
+IF (LHOOK) CALL DR_HOOK('TRUE_DIRNAME_AND_BASENAME',1,ZHOOK_HANDLE)
+END SUBROUTINE true_dirname_and_basename
+
+
+
+
+
+SUBROUTINE io_checkopen(CD_dbname, CD_filename, CLtbl, kio, kpool, kupdval, &
+                        kgrpsize, LDread, LLiotrace, hc32, global_pool_offset, &
+                        kfileno, kret)
+
+IMPLICIT NONE
+CHARACTER(len=*), intent(in)      :: CD_dbname, CLtbl
+CHARACTER(len=*), intent(out)     :: CD_filename
+INTEGER(KIND=JPIM), intent(inout) :: kio, kupdval
+INTEGER(KIND=JPIM), intent(out)   :: kfileno, kret
+INTEGER(KIND=JPIM), intent(in)    :: kpool, kgrpsize
+INTEGER(KIND=JPIM), intent(in)    :: global_pool_offset(:)
+LOGICAL, intent(in)               :: LDread, LLiotrace
+CHARACTER(len=maxvarlen)          :: CLpool
+INTEGER(KIND=JPIM)                :: icat
+INTEGER(KIND=JPIM), intent(in)    :: hc32(0:1)  ! "HC32" & its reverse/byteswap 
+
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('IO_CHECKOPEN',0,ZHOOK_HANDLE)
+
+if (kio == -1) then
+  CALL makefilename(CD_dbname, CLtbl, kpool, CD_filename)
+  
+  if (LDread) then
+    
+    if (LLiotrace) write(0,*) ODBMP_myproc,': Opening file="'//trim(CD_filename)//'" for reading'
+    if (LLiotrace) write(0,*) ODBMP_myproc,': kpool, kgrpsize=',kpool, kgrpsize
+    CALL cma_open(kio, trim(CD_filename), "r", kret)
+    kupdval = 0
+    if (kret /= 1) CALL io_error('Unable to open file for reading', kret, 1, kpool, CD_filename)
+    
+    CALL cma_readi(kio, icat, 1, kret) ! readI; prepare for be2le conversion
+    if (kret /= 1) CALL io_error('Unable to read file-format entry', kret, 1, kpool, CD_filename)
+    if (icat /= hc32(0) .and. icat /= hc32(1)) then
+      CALL io_error('Invalid file format', icat, hc32(0), kpool, CD_filename, hc32)
+    else if (icat == hc32(1)) then ! Apparently streams byteswapping need to be reversed
+      CALL cma_set_byteswap(kio, 1, kret)
+      kret = 1 
+    endif
+    kupdval = kupdval + kret * sizeof_int
+  else
+    
+    if (LLiotrace) write(0,*) ODBMP_myproc,': Opening file="'//trim(CD_filename)//'" for writing'
+    kfileno = mod(kpool-1-global_pool_offset(kpool), kgrpsize) + 1 ! Probably a bug here (fix asap)
+!-- The most likely version ?
+!   kfileno = mod(kpool-1-global_pool_offset(kpool), kgrpsize) + kpool ???
+    if (LLiotrace) write(0,'(i5,a,4i12)') &
+         & ODBMP_myproc,': kfileno, kpool, kgrpsize, global_pool_offset(kpool)=',&
+         &                 kfileno, kpool, kgrpsize, global_pool_offset(kpool)
+    CALL cma_open(kio, trim(CD_filename), "w", kret)
+    
+    kupdval = 0
+    CALL cma_writei(kio, hc32(0), 1, kret) ! writeI; prepare for be2le conversion
+    
+    if (kret /= 1) CALL io_error('Unable to write file-format entry', kret, 1, kpool, CD_filename)
+    kupdval = kupdval + kret * sizeof_int
+  endif
+  
+endif
+IF (LHOOK) CALL DR_HOOK('IO_CHECKOPEN',1,ZHOOK_HANDLE)
+END SUBROUTINE io_checkopen
+
+
+
+
+
+
+
+
+SUBROUTINE io_close(CD_filename, kio, kupdval, kpool, knfiles, datavolume, LLiotrace, kret)
+
+IMPLICIT NONE
+CHARACTER(len=*), intent(in)      :: CD_filename
+INTEGER(KIND=JPIM), intent(inout) :: kio, kupdval, knfiles
+INTEGER(KIND=JPIM), intent(out)   :: kret
+INTEGER(KIND=JPIM), intent(in)    :: kpool
+REAL(KIND=JPRB), intent(inout)    :: datavolume(0:ODBMP_nproc)
+LOGICAL, intent(in)               :: LLiotrace
+
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('IO_CLOSE',0,ZHOOK_HANDLE)
+if (kio /= -1) then
+  datavolume(ODBMP_myproc) = datavolume(ODBMP_myproc) + kupdval
+  knfiles = knfiles + 1
+  if (LLiotrace) then
+    write(0,'(i5,a,i12,a,i10)') &
+     & ODBMP_myproc,': Closing file="'//trim(CD_filename)//'" at position ',&
+     & kupdval,' bytes @ pool#',kpool 
+  endif
+  CALL cma_close(kio, kret)
+  kio = -1
+  kupdval = 0
+  CALL codb_strblank(CD_filename)
+endif
+IF (LHOOK) CALL DR_HOOK('IO_CLOSE',1,ZHOOK_HANDLE)
+END SUBROUTINE io_close
+      
+
+
+SUBROUTINE calculate_global_local_pool_offset(global_pool_offset,npools,ioaid,khandle)
+!***************************************************************
+! Calculate offset between
+! local pool numbers (within a fileblock) and global pool numbers
+! using IOAID db info
+!***************************************************************
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(inout)                  :: global_pool_offset(:)
+INTEGER(KIND=JPIM), intent(in)                     :: npools
+INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: khandle ! database handle
+
+INTEGER(KIND=JPIM)                                 :: ipoolno
+INTEGER(KIND=JPIM)                                 :: irefblk
+INTEGER(KIND=JPIM)                                 :: j, nfblk
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CALCULATE_GLOBAL_LOCAL_POOL_OFFSET',0,ZHOOK_HANDLE)
+
+global_pool_offset(:) = 0
+nfblk = db(khandle)%nfileblocks
+ipoolno = 0 
+irefblk = 0
+do j=1,npools
+  if (ioaid(j,1,IOAID_FBLOCK) /= irefblk) then
+    irefblk = ioaid(j,1,IOAID_FBLOCK)
+    ipoolno = j - 1
+  endif
+  global_pool_offset(j) = ipoolno
+enddo
+
+IF (LHOOK) CALL DR_HOOK('CALCULATE_GLOBAL_LOCAL_POOL_OFFSET',1,ZHOOK_HANDLE)
+
+END SUBROUTINE calculate_global_local_pool_offset
+
+
+SUBROUTINE construct_mask_of_considered_tables(khandle,dbname,ntables,cltable,LL_include_tbl,nactive_tables)
+!***************************************************************
+! Construct mask of considered tables
+!***************************************************************
+
+IMPLICIT NONE
+CHARACTER(len=maxvarlen), intent(in)               :: dbname
+INTEGER(KIND=JPIM), intent(in)                     :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(in)                     :: ntables
+CHARACTER(len=maxvarlen), intent(in), allocatable  :: cltable(:)
+LOGICAL, intent(inout), allocatable                :: LL_include_tbl(:)
+INTEGER(KIND=JPIM), intent(out)                    :: nactive_tables
+
+INTEGER(KIND=JPIM)                                 :: jt
+INTEGER(KIND=JPIM)                                 :: i_consider, icnt_not_active, iret
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CONSTRUCT_MASK_OF_CONSIDERED_TABLES',0,ZHOOK_HANDLE)
+
+!-- New approach (5-Sep-2006/SS)
+do jt=1,ntables
+  CALL cODB_table_is_considered(cltable(jt), i_consider)
+  LL_include_tbl(jt) = (i_consider == 1)
+enddo
+
+icnt_not_active = COUNT(.not.LL_include_tbl(:))
+nactive_tables = ntables - icnt_not_active
+
+!***************************************************************
+! Output diagnostics: Considered tables
+!***************************************************************
+if (ODBMP_myproc == 1) then
+  write(0,*)'***INFO: Considering the following ',&
+   & nactive_tables,' tables for database="'//trim(dbname)//'" :' 
+  if (icnt_not_active == 0) then
+    write(0,*)'***INFO: All tables considered'
+  endif
+endif
+
+!***************************************************************
+! Restore considered tables info... ?
+!***************************************************************
+do jt=1,ntables
+  i_consider = 1
+  if (.not.LL_include_tbl(jt)) i_consider = 0
+  CALL cODB_consider_table(khandle, trim(cltable(jt)), i_consider, iret)
+enddo
+
+IF (LHOOK) CALL DR_HOOK('CONSTRUCT_MASK_OF_CONSIDERED_TABLES',1,ZHOOK_HANDLE)
+
+END SUBROUTINE construct_mask_of_considered_tables
+
+
+SUBROUTINE construct_active_table_id_map(active_table_id,LL_include_tbl,ntables)
+IMPLICIT NONE
+LOGICAL, intent(in)                                :: LL_include_tbl(:)
+INTEGER(KIND=JPIM), intent(inout)                  :: active_table_id(:)
+INTEGER(KIND=JPIM), intent(in)                     :: ntables
+INTEGER(KIND=JPIM)                                 :: jt,jtact
+REAL(KIND=JPRB)                                   :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('CONSTRUCT_ACTIVE_TABLE_ID_MAP',0,ZHOOK_HANDLE)
+
+active_table_id(:)=-1
+jtact = 0
+do jt=1,ntables
+  if (LL_include_tbl(jt)) then
+    jtact = jtact + 1
+    active_table_id(jt) = jtact
+  endif
+enddo
+
+IF (LHOOK) CALL DR_HOOK('CONSTRUCT_ACTIVE_TABLE_ID_MAP',1,ZHOOK_HANDLE)
+
+END SUBROUTINE construct_active_table_id_map
+
+
+
+SUBROUTINE get_status_of_incore_data(istat,npools,ntables,active_table_id,cltable,khandle,LL_mypool,LL_include_tbl,LL_write_tbl)
+!***************************************************************
+! Get current status of incore items -> ISTAT
+!***************************************************************
+
+IMPLICIT NONE
+INTEGER(KIND=JPIM), intent(inout)                  :: istat(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: npools,ntables
+INTEGER(KIND=JPIM), intent(in)                     :: active_table_id(:)
+INTEGER(KIND=JPIM), intent(in)                     :: khandle ! database handle
+CHARACTER(len=maxvarlen), intent(in)               :: cltable(:)
+LOGICAL, intent(in)                                :: LL_mypool(:)
+LOGICAL, intent(in)                                :: LL_include_tbl(:)
+LOGICAL, intent(in), OPTIONAL                      :: LL_write_tbl(:)
+
+!Local
+INTEGER(KIND=JPIM)                                 :: j,jt,jtact
+CHARACTER(len=maxvarlen)                           :: CLtbl
+INTEGER(KIND=JPIM)                                 :: iret
+ REAL(KIND=JPRB)                                   :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('GET_STATUS_OF_INCORE_DATA',0,ZHOOK_HANDLE)
+
+istat(:,:,:) = 0
+jtact = 0
+STAT_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle STAT_LOOP 
+  if (present(LL_write_tbl)) then
+    if (.not.LL_write_tbl(jt)) cycle STAT_LOOP  ! do not proceed if the table is not writable (store only)
+  end if
+  jtact = active_table_id(jt)
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- Gather size information of incore items for memory allocations
+  do j=1,npools
+    if (LL_mypool(j)) then
+      CALL newio_status_incore32(khandle, j, istat(1,j,jtact), nstat, CLtbl, iret)
+!*AF      write(0,*) 'msgpass_loaddata table = ', trim(CLtbl), ' pool = ', j, ' nrows = ', istat(2,j,jtact), ' ncols = ', istat(3,j,jtact), &
+!*AF                 'updated = ', istat(4,j,jtact)
+    endif
+  enddo
+enddo STAT_LOOP
+
+IF (LHOOK) CALL DR_HOOK('GET_STATUS_OF_INCORE_DATA',1,ZHOOK_HANDLE)
+
+END SUBROUTINE get_status_of_incore_data
+
+
+
+
+SUBROUTINE output_db_diagnostics(waltim,CL_called_from,khandle,dbname,LLiotrace,CLmode,io_filesize,io_filesize_default,io_grpsize,hc32,LL_first_time,LL_backup)
+!***************************************************************
+! Output diagnostics: database info
+!***************************************************************
+IMPLICIT NONE
+REAL(KIND=JPRB), intent(inout)            :: waltim(2)
+CHARACTER(len=maxvarlen), intent(in)      :: dbname, CL_called_from
+CHARACTER(len=1),intent(in)               :: CLmode
+INTEGER(KIND=JPIM), intent(in)            :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(inout)         :: io_filesize
+INTEGER(KIND=JPIM), intent(in)            :: io_filesize_default
+
+INTEGER(KIND=JPIM), intent(inout)         :: io_grpsize
+LOGICAL, intent(inout)                    :: LLiotrace
+LOGICAL, intent(in), OPTIONAL             :: LL_backup
+LOGICAL, intent(inout)                    :: LL_first_time
+
+INTEGER(KIND=JPIM), intent(in)            :: hc32(0:1)
+
+LOGICAL                                   :: LLiomsgpasstrace
+LOGICAL, save                             :: LL_write_empty = .FALSE.
+
+INTEGER(KIND=JPIM), parameter             :: io_trace_default = 0
+INTEGER(KIND=JPIM), save                  :: io_trace = 0
+INTEGER(KIND=JPIM)                        :: io_msgpass_trace = 0
+INTEGER(KIND=JPIM), parameter             :: io_msgpass_trace_default = 0
+INTEGER(KIND=JPIM), save                  :: iwrite_empty = 0
+INTEGER(KIND=JPIM)                        :: itime(8)
+INTEGER(KIND=JPIM)                        :: imsgpass_time, imsgpass_date
+REAL(KIND=JPRB)                           :: ZHOOK_HANDLE
+INTEGER(KIND=JPIM), parameter             :: maxsize_mb = 1000 ! Maximum filesize in megabytes for HC32-file
+INTEGER(KIND=JPIM), save                  :: io_backup_enable = 0 ! By default do *NOT* enable back ups (thanks Bob C.!!)
+REAL(KIND=JPRB), external                 :: util_walltime  ! now [23/1/04] from ifsaux/support/drhook.c
+
+IF (LHOOK) CALL DR_HOOK('OUTPUT_DB_DIAGNOSTICS',0,ZHOOK_HANDLE)
+
+waltim(1) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  write(0,'(1x,a,i8.8,2x,i6.6)') &
+  '=== '//trim(CL_called_from)//' of db="'//trim(dbname)// &
+  '" for mode='//CLmode//' started on ',imsgpass_date,imsgpass_time
+endif
+
+if (ODBMP_myproc == 1) write(0,*)'=== '//trim(CL_called_from)//' ==='
+if (LL_first_time) then
+!$ CALL OML_SET_LOCK()
+!$OMP FLUSH(LL_first_time)
+ if (LL_first_time) then
+  !-- HC32-magic number
+  call get_magic_hc32(0, hc32(0))
+  !-- HC32-magic number byteswap i.e. reverse
+  call get_magic_hc32(1, hc32(1))
+  !-- I/O tracing
+  call util_igetenv('ODB_IO_TRACE', io_trace_default, io_trace)
+  LLiotrace = (io_trace /= 0)
+  !-- Message pass tracing
+  call util_igetenv('ODB_IO_MSGPASS_TRACE', io_msgpass_trace_default, io_msgpass_trace)
+  LLiomsgpasstrace = (io_msgpass_trace /= 0)
+  !-- Make sure these stay consistent with the ones obtained in ../aux/newio.c !
+  call util_igetenv('ODB_IO_FILESIZE', io_filesize_default, io_filesize) ! in megabytes
+  if (io_filesize <= 0) io_filesize = io_filesize_default
+  if (io_filesize > maxsize_mb) io_filesize = maxsize_mb ! never exceed this many megabytes
+  call util_igetenv('ODB_IO_GRPSIZE', 0, io_grpsize)
+  if (io_grpsize <= 0) then ! try $NPES_AN
+    call util_igetenv('NPES_AN', 0, io_grpsize)
+  endif
+  if (io_grpsize <= 0) io_grpsize = ODBMP_nproc
+  if(present(LL_backup)) call util_igetenv('ODB_IO_BACKUP_ENABLE', 0, io_backup_enable)
+  call util_igetenv('ODB_WRITE_EMPTY_FILES', 0, iwrite_empty)
+!*AF  LL_write_empty = (iwrite_empty /= 0)
+  LL_write_empty = (iwrite_empty == 1)
+  if (ODBMP_myproc == 1) then
+    write(0,*)'                 HC32=',hc32
+    write(0,*)'         ODB_IO_TRACE=',io_trace
+    write(0,*)' ODB_IO_MSGPASS_TRACE=',io_msgpass_trace
+    write(0,*)'      ODB_IO_FILESIZE=',io_filesize,' MBytes'
+    write(0,*)'       ODB_IO_GRPSIZE=',io_grpsize
+    write(0,*)'ODB_WRITE_EMPTY_FILES=',iwrite_empty, LL_write_empty
+    if(present(LL_backup)) write(0,*)' ODB_IO_BACKUP_ENABLE=',io_backup_enable
+  endif
+  LL_first_time = .FALSE.
+!$OMP FLUSH(LL_first_time)
+ endif
+!$ CALL OML_UNSET_LOCK()
+endif
+
+if (ODBMP_myproc == 1) then
+  write(0,*) ODBMP_myproc,&
+   & ': '//trim(CL_called_from)//'() khandle=',&
+   & khandle
+endif
+
+IF (LHOOK) CALL DR_HOOK('OUTPUT_DB_DIAGNOSTICS',1,ZHOOK_HANDLE)
+
+END SUBROUTINE output_db_diagnostics
+
+
+
+
+
+SUBROUTINE output_diagnostics_final(waltim,CL_called_from,datavolume,dbname,CLmode,it,nfiles)
+!***************************************************************
+! Output diagnostics: Final timings
+!***************************************************************
+
+IMPLICIT NONE
+REAL(KIND=JPRB), intent(in)               :: datavolume(0:ODBMP_nproc)
+REAL(KIND=JPRB), intent(inout)            :: waltim(2)
+INTEGER(KIND=JPIM), intent(in)            :: it
+INTEGER(KIND=JPIM), intent(in)            :: nfiles
+CHARACTER(len=maxvarlen), intent(in)      :: dbname, CL_called_from
+CHARACTER(len=1), intent(in)              :: CLmode
+INTEGER(KIND=JPIM)                        :: imsgpass_time,imsgpass_date
+REAL(KIND=JPRB)                           :: sum_datavolume
+INTEGER(KIND=JPIM)                        :: itime(8)
+REAL(KIND=JPRB)                           :: ZHOOK_HANDLE
+REAL(KIND=JPRB), external                 :: util_walltime  ! now [23/1/04] from ifsaux/support/drhook.c
+
+IF (LHOOK) CALL DR_HOOK('OUTPUT_DIAGNOSTICS_FINAL',0,ZHOOK_HANDLE)
+
+waltim(2) = util_walltime()
+
+if (ODBMP_myproc == 1) then
+  call date_and_time (values=itime)
+  imsgpass_time=itime(5)*10000+itime(6)*100+itime(7)
+  imsgpass_date=itime(1)*10000+itime(2)*100+itime(3)
+  sum_datavolume = sum(datavolume(1:ODBMP_nproc))/(1024 * 1024)
+
+  write(0,'(1x,a,i8.8,2x,i6.6,/, &
+   &        1x,a,f8.1,a,i5,a,f7.2,a,f8.1,a,i3,a)') &
+   & '=== '//trim(CL_called_from)//' of db="'//trim(dbname)// &
+   & '" for mode='//CLmode//' on all tables ended on ',imsgpass_date,imsgpass_time,&
+   & '=== '//trim(CL_called_from)//' : ',sum_datavolume,' MBytes (',&
+   & nfiles,' files) in ',waltim(2) - waltim(1),&
+   & ' secs (',sum_datavolume/(waltim(2) - waltim(1) + epsilon(waltim(1))),&
+   & ' MB/s) (it#',it ,')'
+endif
+
+IF (LHOOK) CALL DR_HOOK('OUTPUT_DIAGNOSTICS_FINAL',1,ZHOOK_HANDLE)
+
+END SUBROUTINE output_diagnostics_final
+
+
+
+
+
+FUNCTION same_file_as_previous(j,ioaid,istat,rsum,kjt,kjtact,kfilesize,kgrpsize,global_pool_offset,LL_data_in_file,LL_load,last_pool_containing_data) RESULT(LLis_same)
+
+ INTEGER(KIND=JPIM), intent(in)                     :: j
+ INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+ INTEGER(KIND=JPIM), intent(in)                     :: istat(:,:,:)
+ REAL(KIND=JPRB),    intent(inout)                  :: rsum
+ INTEGER(KIND=JPIM), intent(in)                     :: kjt, kjtact,last_pool_containing_data
+ INTEGER(KIND=JPIM), intent(in)                     :: kfilesize  ! suggested max filesize ; in megabytes
+ INTEGER(KIND=JPIM), intent(in)                     :: kgrpsize
+ INTEGER(KIND=JPIM), intent(in)                     :: global_pool_offset(:)
+ LOGICAL, intent(in)                                :: LL_load ! true if loaddata mode, false if storedata mode
+ LOGICAL, intent(out)                               :: LL_data_in_file
+ LOGICAL                                            :: LLis_same
+ INTEGER(KIND=JPIM)                                 :: rfsize
+ REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+ IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',0,ZHOOK_HANDLE)
+ LL_data_in_file = .FALSE.
+
+ if (j==1) then
+    LLis_same = .FALSE.    ! First pool so a new file.
+    rsum = rsum + istat(ISTAT_NBYTES,j,kjtact)  ! start accumulating file size with the first pool
+    if ((ioaid(j,kjt,IOAID_LENGTH) > 0).or.(istat(ISTAT_NBYTES,j,kjtact)>0)) LL_data_in_file = .TRUE.
+    IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+    return
+ else ! Not first pool
+    if (LL_load) then ! Load data mode
+    !if (ioaid(j,kjt,IOAID_FILENO) /= 0)then  ! IO file numbers already set so use them
+      if (ioaid(j,kjt,IOAID_LENGTH) == 0) then ! For cases where pools of data aren't contiguous but still in same file.
+        LLis_same = .TRUE.
+        IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+        return
+      endif
+      if (ioaid(j,kjt,IOAID_FILENO) /= ioaid(last_pool_containing_data,kjt,IOAID_FILENO))then    ! Current file number different from previous
+        LLis_same = .FALSE.
+        LL_data_in_file = .TRUE.
+        IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+        return
+      else
+        LLis_same = .TRUE.
+        IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+        return
+      endif
+    else    ! Store data mode
+      rfsize = kfilesize
+      rfsize = rfsize * (1024 * 1024)
+      rsum = rsum + istat(ISTAT_NBYTES,j,kjtact)
+      if (mod(j-global_pool_offset(j),kgrpsize) == 1 .OR.  &   ! groupsize limit exceeded
+        & rsum > rfsize) then                                  ! total filesize reached threshold 
+        rsum = istat(ISTAT_NBYTES,j,kjtact)
+        LLis_same = .FALSE.
+        LL_data_in_file = .TRUE.
+        IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+        return
+      else
+        LLis_same = .TRUE.
+        IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+        return
+      end if
+    endif
+ endif
+
+ IF (LHOOK) CALL DR_HOOK('SAME_FILE_AS_PREVIOUS',1,ZHOOK_HANDLE)
+END FUNCTION same_file_as_previous
+
+
+
+SUBROUTINE assign_iopes(iope_map, ioaid, istat, kfilesize, kgrpsize, knpools, &
+                      global_pool_offset, LL_include_tbl, kntables, active_table_id, LL_load)
+ !*********************************************************************
+ ! Designates which PEs are IOPEs for each pool for the given table
+ !
+ ! Input:
+ !
+ ! Output:
+ !    iope_map :  array specifying iopes for every pool and table
+ !
+ ! Peter Lean     November 2014
+ !*********************************************************************
+ INTEGER(KIND=JPIM), intent(inout)                  :: iope_map(:,:)
+ INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+ INTEGER(KIND=JPIM), intent(in)                     :: istat(:,:,:)
+ INTEGER(KIND=JPIM), intent(in)                     :: kntables
+ INTEGER(KIND=JPIM), intent(in)                     :: kfilesize  ! suggested max filesize ; in megabytes
+ INTEGER(KIND=JPIM), intent(in)                     :: kgrpsize
+ INTEGER(KIND=JPIM), intent(in)                     :: knpools
+ INTEGER(KIND=JPIM), intent(in)                     :: global_pool_offset(:)
+ INTEGER(KIND=JPIM), intent(in)                     :: active_table_id(:)
+ LOGICAL, intent(in)                                :: LL_include_tbl(:)
+ LOGICAL, intent(in)                                :: LL_load  ! true if LOADDATA, false if STOREDATA
+
+ LOGICAL                                            :: LL_data_in_file, LL_data_in_table
+ INTEGER(KIND=JPIM)                                 :: cur_iope, jm, jt, jtact, iope_inc, last_pool_containing_data
+ REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+ REAL(KIND=JPRB)                                    :: rsum
+
+ IF (LHOOK) CALL DR_HOOK('ASSIGN_IOPES',0,ZHOOK_HANDLE)
+ jtact = -1
+ cur_iope = 0
+ iope_inc = 1
+
+ LL_data_in_file = .FALSE.
+ do jt=1,kntables
+  if (LL_include_tbl(jt)) then
+    last_pool_containing_data = 1
+    jtact = active_table_id(jt)
+    if (LL_load) then
+      LL_data_in_table = (maxval(ioaid(1:knpools,jt,IOAID_LENGTH))>0)
+    else ! store
+      LL_data_in_table = (maxval(istat(ISTAT_NBYTES,1:knpools,jtact))>0)
+    endif
+    if (LL_data_in_table) then ! Only proceed if there is data in this table
+      cur_iope = cur_iope + iope_inc ! If there will be data in this table then assign a new iope for it
+      ! Loop over all pools
+      rsum = 0.0_JPRB
+      do jm=1,knpools
+          if (.NOT. same_file_as_previous(jm,ioaid,istat,rsum,jt,jtact,kfilesize,kgrpsize,global_pool_offset,LL_data_in_file, LL_load, last_pool_containing_data))then
+            if (LL_data_in_file) then 
+              cur_iope = cur_iope + iope_inc
+            endif
+          endif
+          iope_map(jm,jtact) = cur_iope        ! before use the iope_map(jm,1) is converted to iope via fastphysproc()
+          if (LL_load) then
+            if (ioaid(jm,jt,IOAID_LENGTH)>0) last_pool_containing_data = jm
+          else
+            last_pool_containing_data =jm
+          endif
+      enddo
+    else
+      iope_map(1:knpools,jtact) = cur_iope        ! before use the iope_map(jm,1) is converted to iope via fastphysproc()
+    endif
+  endif
+ enddo
+ IF (LHOOK) CALL DR_HOOK('ASSIGN_IOPES',1,ZHOOK_HANDLE)
+END SUBROUTINE assign_iopes
+
+
+
+
+SUBROUTINE calculate_table_sizes(dbname, cltable, ioaid, istat, data_bytes, npools, ntables, LL_include_tbl, LL_mypool, LLiotrace,LLiomsgpasstrace,maxbytes,active_table_id)
+
+IMPLICIT NONE
+
+CHARACTER(len=maxvarlen), intent(in)               :: dbname, cltable(:)
+INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: istat(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: npools, ntables, active_table_id(:)
+REAL(KIND=JPRB), intent(inout)                     :: data_bytes(:) ! nactive_tables
+LOGICAL, intent(in)                                :: LL_include_tbl(:)
+LOGICAL, intent(in)                                :: LL_mypool(:)
+LOGICAL, intent(in)                                :: LLiotrace
+LOGICAL, intent(in)                                :: LLiomsgpasstrace
+INTEGER(KIND=JPIM),intent(out)                     :: maxbytes
+INTEGER(KIND=JPIM)                                 :: jtact, jt, j, ipoolno, jmin, jmax, iexpect_len
+INTEGER(KIND=JPIM)                                 :: iret
+CHARACTER(len=maxvarlen)                           :: CLtbl
+LOGICAL                                            :: LL_check_len
+INTEGER(KIND=JPIM)                                 :: is_compressed
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+CHARACTER(len=4096)                                :: filename
+
+IF (LHOOK) CALL DR_HOOK('CALCULATE_TABLE_SIZES',0,ZHOOK_HANDLE)
+
+jtact = 0
+TABLE_LOOP: do jt=1,ntables
+  if (.not.LL_include_tbl(jt)) cycle TABLE_LOOP
+  jtact = active_table_id(jt)
+  data_bytes(jtact) = 0
+
+!-- If any bytes have been loaded, then prevent overwriting existing incore-structures from disk
+  maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+  if (maxbytes > 0) cycle TABLE_LOOP  ! already loaded --> skip
+
+!-- Strip off the leading '@'-character
+  CLtbl = cltable(jt)(2:)
+
+!-- Determine which pools have files present ==> pool owner-PEs become I/O-PEs
+  do j=1,npools
+    !-- ipoolno below is LOCAL (not global) poolno with respect to fileblock ioaid(j,jt,IOAID_FBLOCK) in concern
+    if (ioaid(j,jt,IOAID_GRPSIZE) > 0) then
+      ipoolno = mod(ioaid(j,jt,IOAID_POOLNO)-1,ioaid(j,jt,IOAID_GRPSIZE)) + 1 
+    else
+      ipoolno = 0
+    endif
+    if ( LL_mypool(j) .and. ipoolno > 0 .and. &
+       & ipoolno == ioaid(j,jt,IOAID_FILENO) ) then
+
+!-- The expected length in bytes can be calculated as follows :
+      jmin = max(j,1)
+      jmax = min(j+ioaid(j,jt,IOAID_GRPSIZE)-1,size(ioaid,dim=1))
+      iexpect_len = SUM(  ioaid(jmin:jmax,jt,IOAID_LENGTH), &
+                  & mask=(ioaid(jmin:jmax,jt,IOAID_FILENO) == ipoolno .and. &
+                  &       ioaid(jmin:jmax,jt,IOAID_FBLOCK) == ioaid(j,jt,IOAID_FBLOCK)))
+
+      LL_check_len = .TRUE.
+      if (iexpect_len > 0) then
+        iexpect_len = iexpect_len + sizeof_int   ! Plus length of the MAGIC-word (HC32)
+        call codb_tablesize(dbname, CLtbl, j, iret)
+        if (iret > 0 .and. iret /= iexpect_len) then
+           call makefilename(dbname, CLtbl, j, filename)
+           call cma_is_externally_compressed(trim(filename), 'r', is_compressed)
+           LL_check_len = (is_compressed == 0)
+        endif
+      else
+        iret = 0
+      endif
+
+      if (LLiotrace .or. LLiomsgpasstrace) then 
+        write(0,'(1x,i5,a,2i12,5i7)') &
+        & ODBMP_myproc,': tablesize for "'//trim(CLtbl)//'" & poolno=',&
+        & iret,ioaid(j,jt,IOAID_LENGTH),j,ioaid(j,jt,IOAID_POOLNO),&
+        & ioaid(j,jt,IOAID_FILENO),jtact,ipoolno
+      endif
+
+      if (iret == iexpect_len .or. .not.LL_check_len) then
+        if (iret > 0) then
+          data_bytes(jtact) = data_bytes(jtact) + iret
+        endif
+      else
+        write(0,*) ODBMP_myproc,': Expected length disagrees with the actual'
+        write(0,'(1x,i5,a,3i12)') ODBMP_myproc,': table, poolno, iret, iexpect_len : "'// &
+        &                                   trim(CLtbl)//'"', j, iret, iexpect_len
+        CALL ODB_abort('MSGPASS_LOADOBS', &
+                      &'Expected length disagrees with the actual', &
+                      & iret)
+      endif
+    endif
+  enddo
+enddo TABLE_LOOP
+
+IF (LHOOK) CALL DR_HOOK('CALCULATE_TABLE_SIZES',1,ZHOOK_HANDLE)
+
+END SUBROUTINE calculate_table_sizes
+
+
+
+
+
+SUBROUTINE send_message_to_pe(nw,incore,jncore,msgoff,destPE,itag,imp_type,jsendreq,LLiomsgpasstrace, CLtbl,nsent)
+
+INTEGER(KIND=JPIM), intent(in)                 :: nw
+INTEGER(KIND=JPIM), pointer, intent(in)        :: incore(:)
+INTEGER(KIND=JPIM), pointer, intent(inout)     :: jncore(:)
+INTEGER(KIND=JPIM), intent(inout)              :: msgoff
+INTEGER(KIND=JPIM), intent(in)                 :: destPE,itag
+INTEGER(KIND=JPIM), intent(in)                 :: imp_type
+INTEGER(KIND=JPIM), intent(inout)              :: jsendreq(:)
+LOGICAL, intent(in)                            :: LLiomsgpasstrace
+CHARACTER(len=maxvarlen), intent(in)           :: CLtbl
+INTEGER(KIND=JPIM), intent(inout)              :: nsent
+INTEGER(KIND=JPIM)                             :: iret
+REAL(KIND=JPRB)                                :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('SEND_MESSAGE_TO_PE',0,ZHOOK_HANDLE)
+
+if (LLiomsgpasstrace) &
+    & write(0,'(i5,a,i5,a,2i12)') &
+    & ODBMP_myproc,':LOAD: Sending to ',destPE,', tag,nw=',itag, nw
+
+!if(msgoff+nw > njmax) then
+!  if(nw .gt. njmax) then
+!    njmax=nw
+!    CALL allocate_jncore(jncore, njmax, iret)
+!  endif
+!  msgoff=0
+!endif
+jncore(msgoff+1:msgoff+nw)=incore(1:nw)
+nsent=nsent+1
+
+if (itag == -1) CALL ODB_abort('MSGPASS:', 'itag not set correctly for mpl_send ',iret) 
+
+CALL mpl_send(jncore(msgoff+1:msgoff+nw), KDEST=destPE, KTAG=itag, &
+    & KMP_TYPE=imp_type, KREQUEST=JSENDREQ(nsent), &
+    & CDSTRING='LOAD: Send data to data-owner PE; table=@'//trim(CLtbl))
+msgoff=msgoff+nw
+
+if (LLiomsgpasstrace) then
+  write(0,'(i5,a,i5,a,2i12)') &
+  & ODBMP_myproc,':LOAD: Sent to ',destPE,', tag',itag
+endif
+
+IF (LHOOK) CALL DR_HOOK('SEND_MESSAGE_TO_PE',1,ZHOOK_HANDLE)
+END SUBROUTINE send_message_to_pe
+
+
+
+
+
+SUBROUTINE receive_message_for_this_pool_table(pe,nw,itag,j,LLiomsgpasstrace,incore,filename,CLtbl,CL_called_from)
+INTEGER(KIND=JPIM), intent(inout)              :: pe, nw 
+INTEGER(KIND=JPIM), intent(in)                 :: itag, j
+LOGICAL, intent(in)                            :: LLiomsgpasstrace
+INTEGER(KIND=JPIM), pointer, intent(inout)     :: incore(:)
+CHARACTER(len=4096), intent(in)                :: filename
+CHARACTER(len=maxvarlen)                       :: CLtbl, CL_called_from
+
+INTEGER(KIND=JPIM)                             :: iret 
+REAL(KIND=JPRB)                                :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('RECEIVE_MESSAGE_FOR_THIS_POOL',0,ZHOOK_HANDLE)
+
+incore(:) = 0
+!CALL allocate_incore(incore, nw + 1, iret)
+
+if (LLiomsgpasstrace) &
+  & write(0,'(i5,a,i5,a,2i12)') &
+  & ODBMP_myproc,':LOAD: Receiving from ',pe,', tag,nw=',itag,nw
+if (pe == -1) then ! "ANY"-source : at present KSOURCE-parameter must be left out
+  if (itag == -1) CALL ODB_abort('MSGPASS_LOADOBS', 'itag not set correctly for mpl_recv ',iret)
+  CALL mpl_recv(incore, KTAG=itag, KOUNT=iret, &
+    & KFROM=pe,   &! Upon return the "pe" contains the actual "from-PE"
+    & CDSTRING='LOAD: Recv data from I/O-PE; table=@'//trim(CLtbl)) 
+else
+  if (itag == -1) CALL ODB_abort('MSGPASS_LOADOBS', 'itag not set correctly for mpl_recv ',iret)
+  CALL mpl_recv(incore, KSOURCE=pe, KTAG=itag, KOUNT=iret, &
+    & CDSTRING='Recv data from I/O-PE; table=@'//trim(CLtbl)) 
+endif
+if (LLiomsgpasstrace) &
+  & write(0,'(i5,a,i5,a,2i12)') &
+  & ODBMP_myproc,':LOAD: Received from ',pe,', tag,iret=',itag,iret
+
+
+if (iret /= nw) then
+  CALL io_error('***'//trim(CL_called_from)//'(io_error): Unable to receive correct amount of data from I/O-PE', &
+    & iret, nw, j,filename)
+endif
+
+IF (LHOOK) CALL DR_HOOK('RECEIVE_MESSAGE_FOR_THIS_POOL',1,ZHOOK_HANDLE)
+END SUBROUTINE receive_message_for_this_pool_table
+
+
+
+
+
+SUBROUTINE write_pool_to_hc32_file(incore,ioaid,iope_map,io,dbname,Cltbl,j,jt,jtact,NHDR,datavolume,nw,nwrite,nfiles,nfileno,cur_io_grpsize,LLiotrace,hc32,global_pool_offset)
+
+INTEGER(KIND=JPIM), pointer, intent(in)            :: incore(:)
+INTEGER(KIND=JPIM), intent(inout)                  :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: iope_map(:,:)
+INTEGER(KIND=JPIM), intent(inout)                  :: io
+CHARACTER(len=maxvarlen), intent(in)               :: dbname,CLtbl
+INTEGER(KIND=JPIM), intent(in)                     :: j,jt,jtact
+INTEGER(KIND=JPIM), intent(in)                     :: NHDR
+REAL(KIND=JPRB), intent(inout)                     :: datavolume(0:ODBMP_nproc)
+INTEGER(KIND=JPIM), intent(inout)                  :: nw
+INTEGER(KIND=JPIM), intent(inout)                  :: nwrite
+INTEGER(KIND=JPIM), intent(inout)                  :: nfiles,nfileno
+INTEGER(KIND=JPIM), intent(in)                     :: cur_io_grpsize
+LOGICAL, intent(in)                                :: LLiotrace
+INTEGER(KIND=JPIM), intent(in)                     :: hc32(0:1)
+INTEGER(KIND=JPIM), intent(in)                     :: global_pool_offset(:)
+
+CHARACTER(len=4096)                                :: filename
+INTEGER(KIND=JPIM)                                 :: iret, nrows, ncols
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+integer(kind=JPIM)                                 :: JWRITE=0
+
+IF (LHOOK) CALL DR_HOOK('WRITE_POOL_TO_HC32_FILE',0,ZHOOK_HANDLE)
+ call codb_strblank(filename)
+
+ call io_checkopen(dbname, filename, CLtbl, io, j, nwrite, cur_io_grpsize, LDread=.FALSE., &
+                        LLiotrace=LLiotrace, hc32=hc32, global_pool_offset=global_pool_offset, &
+                        kfileno=nfileno, kret=iret)
+ nrows = incore(4)
+ ncols = incore(5)
+
+ if(JWRITE>1) write(0,*) "JJJ write bytes,filename=",4*nw,trim(filename)
+
+ ! Write header
+ call cma_writei(io, incore(1), NHDR, iret) ! writeI; prepare for be2le conversion
+
+ if (iret /= NHDR) CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to write data header', iret, NHDR, j, &
+   & filename, kdata=incore(1:NHDR)) 
+ 
+ ! Write (packed) content
+ call cma_writeb(io, incore(NHDR+1), (nw - NHDR) * sizeof_int, iret) ! writeB; raw data xfer
+ if (iret /= (nw - NHDR) * sizeof_int) then
+   CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to write actual data', iret, &
+                (nw - NHDR) * sizeof_int, j, filename)
+ endif
+
+ ! Update ioaid metadata info
+ ioaid(j,jt,IOAID_FILENO) = nfileno
+ ioaid(j,jt,IOAID_OFFSET) = nwrite
+ ioaid(j,jt,IOAID_LENGTH) = nw * sizeof_int
+ ioaid(j,jt,IOAID_NROWS)  = nrows
+ ioaid(j,jt,IOAID_NCOLS)  = ncols
+
+ nwrite = nwrite + nw * sizeof_int
+
+ ! Close file if necessary
+ if (io /= -1 .AND. &
+   & (iope_map(j,jtact) /= iope_map(j+1,jtact) .OR. &
+   & mod(j-global_pool_offset(j), cur_io_grpsize) == 0)) then 
+     if(JWRITE>0) write(0,*) "JJJ close table,filename=",trim(CLtbl)," ",trim(filename)
+
+     call io_close(filename, io, nwrite, j, nfiles, datavolume, LLiotrace, iret)
+ endif
+
+IF (LHOOK) CALL DR_HOOK('WRITE_POOL_TO_HC32_FILE',1,ZHOOK_HANDLE)
+END SUBROUTINE write_pool_to_hc32_file
+
+
+
+
+
+
+
+
+
+SUBROUTINE read_next_pool_from_hc32_file(dbname, filename, CLtbl, incore,ioaid,global_pool_offset,npools,io,  &
+      &                                  hc32,NHDR,j,jt,ipoolno,igrpsize,nbytes,nrows,ncols,npad,nw, &
+      &                                  jsta,nread, nfiles, datavolume, LL_poolmask, LL_lastpool, LLiotrace, prev_fblk, prev_fileno)
+CHARACTER(len=maxvarlen), intent(in)               :: dbname,CLtbl
+CHARACTER(len=4096), intent(inout)                 :: filename
+INTEGER(KIND=JPIM), pointer, intent(inout)         :: incore(:)
+INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)                     :: global_pool_offset(:)
+INTEGER(KIND=JPIM), intent(in)                     :: hc32(0:1),j,jt,jsta
+INTEGER(KIND=JPIM), intent(in)                     :: NHDR,npools
+INTEGER(KIND=JPIM), intent(inout)                  :: nw, nread,nfiles,io
+REAL(KIND=JPRB), intent(inout)                     :: datavolume(0:ODBMP_nproc)
+INTEGER(KIND=JPIM), intent(out)                    :: ipoolno,igrpsize,nbytes,nrows,ncols,npad
+INTEGER(KIND=JPIM), intent(inout)                  :: prev_fileno, prev_fblk
+LOGICAL, intent(in)                                :: LL_poolmask(:), LL_lastpool(:), LLiotrace
+
+INTEGER(KIND=JPIM)                                 :: iret, cur_io_grpsize, nfileno
+INTEGER(KIND=JPIM)                                 :: ihdr(NHDR)
+
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('READ_NEXT_POOL_FROM_HC32_FILE',0,ZHOOK_HANDLE)
+
+  ! Close odb HC32 data file if required
+  if ((io /= -1).and. &
+    & ((j > npools).OR.LL_lastpool(j).OR. &
+    & (ioaid(j,jt,IOAID_FBLOCK) /= prev_fblk).OR. &
+    & (ioaid(j,jt,IOAID_FILENO) /= prev_fileno)))then
+    call io_close(filename, io, nread, j, nfiles, datavolume, LLiotrace, iret)
+    io = -1
+  endif
+
+  prev_fileno = ioaid(j,jt,IOAID_FILENO)
+  prev_fblk   = ioaid(j,jt,IOAID_FBLOCK)
+
+  cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+
+  CALL io_checkopen(dbname, filename, CLtbl, io, j, nread, cur_io_grpsize, LDread=.TRUE.,&
+                    LLiotrace=LLiotrace, hc32=hc32, global_pool_offset=global_pool_offset, &
+                    kfileno=nfileno, kret=iret)
+
+
+  ihdr(:) = 0
+  CALL cma_readi(io, ihdr(1), NHDR, iret) ! readI ==> prepare for be2le conversion
+  if (iret == -1) then ! Unexpected EOF encountered
+    CALL io_error('***MSGPASS_LOADOBS(io_error): Unexpected EOF encountered while reading file', &
+      & iret, NHDR, j, filename, kdata=ioaid(jsta:j,jt,IOAID_OFFSET)) 
+  endif          
+
+  if (iret /= NHDR) CALL io_error('***MSGPASS_LOADOBS(io_error): Unable to read header data', iret, NHDR, j, &
+    & filename, kdata=ihdr(1:NHDR)) 
+  
+  ipoolno = ihdr(1)
+  igrpsize = ihdr(2)
+  nbytes = ihdr(3)
+  nrows = ihdr(4)
+  ncols = ihdr(5)
+  npad = ihdr(6) ! ... not used for anything (else) yet ...
+  nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+
+  if (ioaid(j,jt,IOAID_LENGTH) /= nw * sizeof_int) then
+    CALL io_error('***MSGPASS_LOADOBS(io_error): Inconsistent no. of bytes', &
+      & nw * sizeof_int, ioaid(j,jt,IOAID_LENGTH), j, filename, &
+      & kdata=ioaid(jsta:j,jt,IOAID_LENGTH)) 
+  endif
+
+  if (ioaid(j,jt,IOAID_OFFSET) /= nread) then
+    CALL io_error('***MSGPASS_LOADOBS(io_error): Data expected from different byte-offset', &
+      & nread, ioaid(j,jt,IOAID_OFFSET), j, &
+      & filename, kdata=ioaid(jsta:j,jt,IOAID_OFFSET)) 
+  endif
+
+  nread = nread + iret * sizeof_int
+
+  if (LL_poolmask(j)) then
+    CALL allocate_incore(incore, nw + 1, iret)
+    incore(1:NHDR) = ihdr(1:NHDR)
+    CALL cma_readb(io, incore(NHDR+1), (nw - NHDR) * sizeof_int, iret) ! readB; raw data xfer
+    if (iret /= (nw - NHDR) * sizeof_int) then
+      CALL io_error('***MSGPASS_LOADOBS(io_error): Unable to read data', iret, &
+                    (nw - NHDR) * sizeof_int, j, filename)
+    endif
+  else ! just seek forward [=1] (should work for gzip'ped files, too; don't rewind though!)
+    CALL cma_seekb(io, (nw - NHDR) * sizeof_int, 1, iret)
+    if (iret /= 0) then
+      CALL io_error('***MSGPASS_LOADOBS(io_error): Unable to seek past data', iret, &
+                    (nw - NHDR) * sizeof_int, j, filename)
+    endif
+    iret = (nw - NHDR) * sizeof_int
+  endif
+  nread = nread + iret
+  
+IF (LHOOK) CALL DR_HOOK('READ_NEXT_POOL_FROM_HC32_FILE',1,ZHOOK_HANDLE)
+END SUBROUTINE read_next_pool_from_hc32_file
+
+
+
+
+
+SUBROUTINE get_incore_data_for_this_pool_table(khandle,ioaid,istat,NHDR,j,jt,jtact,CLtbl,this_io_grpsize,global_pool_offset,nw,maxbytes,incore)
+
+INTEGER(KIND=JPIM), intent(in)               :: khandle ! database handle
+INTEGER(KIND=JPIM), intent(in)               :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), intent(in)               :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)               :: j,jt, jtact, this_io_grpsize
+CHARACTER(len=maxvarlen), intent(in)         :: CLtbl
+INTEGER(KIND=JPIM), intent(in)               :: global_pool_offset(:)
+INTEGER(KIND=JPIM), intent(in)               :: NHDR
+INTEGER(KIND=JPIM), intent(out)              :: nw
+INTEGER(KIND=JPIM), intent(in)               :: maxbytes
+INTEGER(KIND=JPIM), pointer,intent(inout)    :: incore(:)
+
+CHARACTER(len=4096)                          :: filename
+INTEGER(KIND=JPIM), parameter                :: reset_updated_flag = 1
+INTEGER(KIND=JPIM)                           :: nrows,ncols,npad,nbytes
+INTEGER(KIND=JPIM)                           :: ipoolno,iret,cur_io_grpsize
+REAL(KIND=JPRB)                              :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('GET_INCORE_DATA_FOR_THIS_POOL_TABLE',0,ZHOOK_HANDLE)
+
+  call codb_strblank(filename)
+  cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+  if (cur_io_grpsize == 0) cur_io_grpsize = this_io_grpsize
+  nbytes = istat(ISTAT_NBYTES,j,jtact)
+  nrows  = istat(ISTAT_NROWS,j,jtact)
+  ncols  = istat(ISTAT_NCOLS,j,jtact)
+  npad   = 1
+  nw     = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+
+  if (mod(nbytes,sizeof_int) /= 0) incore(nw) = 0 ! make sure the last word is FULLY zeroed first
+  ipoolno = mod(j-1-global_pool_offset(j),cur_io_grpsize) + 1 ! Pool# relative to the beginning of this IO_GRP
+  incore(1) = ipoolno
+  incore(2) = cur_io_grpsize
+  incore(3) = nbytes
+  incore(4) = nrows
+  incore(5) = ncols
+  incore(6) = npad ! Data padded to the nearest INTEGER*4 word boundary
+  CALL newio_get_incore32(khandle, j, incore(NHDR + 1), maxbytes, &
+    & reset_updated_flag, CLtbl, iret) 
+  if (iret /= nbytes) then
+    CALL io_error('***MSGPASS_STOREDATA(io_error): Unable to get_incore() correct no. of bytes', iret, nbytes, j, &
+      & filename, kdata=incore(1:NHDR)) 
+  endif
+
+  nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+
+IF (LHOOK) CALL DR_HOOK('GET_INCORE_DATA_FOR_THIS_POOL_TABLE',1,ZHOOK_HANDLE)
+END SUBROUTINE get_incore_data_for_this_pool_table
+
+
+
+
+SUBROUTINE put_data_incore_for_this_pool_table(khandle,CLtbl,filename,j,incore,NHDR)
+
+INTEGER(KIND=JPIM), intent(in)               :: khandle ! database handle
+CHARACTER(len=maxvarlen), intent(in)         :: CLtbl
+CHARACTER(len=4096),intent(in)               :: filename
+INTEGER(KIND=JPIM), intent(in)               :: j,NHDR
+INTEGER(KIND=JPIM), pointer,intent(in)       :: incore(:)
+
+INTEGER(KIND=JPIM)                           :: iret,nbytes,nrows,ncols
+REAL(KIND=JPRB)                              :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('PUT_DATA_INCORE_FOR_THIS_POOL_TABLE',0,ZHOOK_HANDLE)
+
+
+  nbytes = incore(3)
+  nrows  = incore(4)
+  ncols  = incore(5)
+
+  CALL newio_put_incore32(khandle, j, incore(NHDR+1), nbytes, &
+                          nrows, ncols, CLtbl, iret)
+  if (iret /= nbytes) then
+    CALL io_error('***MSGPASS_LOADOBS(io_error): Unable to [1]put_incore() correct no. of bytes', &
+                  iret, nbytes, j, filename)
+  endif
+
+
+IF (LHOOK) CALL DR_HOOK('PUT_DATA_INCORE_FOR_THIS_POOL_TABLE',1,ZHOOK_HANDLE)
+END SUBROUTINE put_data_incore_for_this_pool_table
+
+
+
+
+SUBROUTINE define_filemask_for_this_table(LL_filemask, LL_lastpool, LL_poolmask, jt, npools, ioaid)
+
+LOGICAL, intent(inout)                             :: LL_filemask(:)
+LOGICAL, intent(inout)                             :: LL_lastpool(:)
+LOGICAL, intent(in)                                :: LL_poolmask(:)
+INTEGER(KIND=JPIM), intent(in)                     :: npools, jt
+INTEGER(KIND=JPIM), intent(in)                     :: ioaid(:,:,:)
+
+INTEGER(KIND=JPIM)                                 :: j,jj,iprev
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('DEFINE_FILEMASK_FOR_THIS_TABLE',0,ZHOOK_HANDLE)
+
+  LL_filemask(:) = .FALSE. ! .TRUE. only if file is to be processed at all
+  LL_lastpool(:) = .FALSE. ! .TRUE. only if pool is beyond the last to be processed in its file
+
+  j = 1
+  jj = 1
+  iprev = 0
+  FILEMASK_LOOP: do while (j <= npools)
+    if (LL_poolmask(j)) then
+      LL_filemask(jj) = .TRUE.
+      LL_filemask(j) = .TRUE.
+      iprev = j ! last pool so far which we care about for this file #jj
+    endif
+    if (j < npools) then
+      !-- detect the change of file: next chunk will be read from different file
+      if ( ioaid(j+1,jt,IOAID_FBLOCK) /= ioaid(j,jt,IOAID_FBLOCK) .OR. &
+          (ioaid(j+1,jt,IOAID_LENGTH)  > 0 .AND. &
+           ioaid(j+1,jt,IOAID_OFFSET) <= ioaid(j,jt,IOAID_OFFSET))) then
+        if (iprev > 0) LL_lastpool(iprev+1:j) = .TRUE. ! skip the reading these pools
+        iprev = 0
+        jj = j + 1
+      endif
+    endif
+    j = j + 1
+  enddo FILEMASK_LOOP
+
+IF (LHOOK) CALL DR_HOOK('DEFINE_FILEMASK_FOR_THIS_TABLE',1,ZHOOK_HANDLE)
+END SUBROUTINE define_filemask_for_this_table
+
+
+SUBROUTINE diagnostic_output_table(data_bytes,jtact,CLtbl,CL_called_from)
+REAL(KIND=JPRB), intent(in)                        :: data_bytes(:) ! nactive_tables
+INTEGER(KIND=JPIM), intent(in)                     :: jtact
+CHARACTER(len=maxvarlen), intent(in)               :: CLtbl
+CHARACTER(len=maxvarlen), intent(in)               :: CL_called_from
+
+INTEGER(KIND=JPIM)                                 :: jj
+character(len=maxvarlen)                           :: CLbytes
+character(len=maxvarlen)                           :: CLverb
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('DIAGNOSTIC_OUTPUT_TABLE',0,ZHOOK_HANDLE)
+
+  if (ODBMP_myproc == 1) then
+    write(CLbytes,'(f20.1)') data_bytes(jtact)
+    jj = index(CLbytes,'.')
+    if (jj > 0) CLbytes(jj:) = ' '
+    if (trim(CL_called_from)=='MSGPASS_STOREOBS') CLverb = 'STORE'
+    if (trim(CL_called_from)=='MSGPASS_LOADOBS') CLverb = 'LOAD'
+    write(0,'(1x,a)') trim(CLverb)//'ing table="'//trim(CLtbl)//'" total = '//&
+    & trim(CLbytes)//' bytes'
+  endif
+
+IF (LHOOK) CALL DR_HOOK('DIAGNOSTIC_OUTPUT_TABLE',1,ZHOOK_HANDLE)
+END SUBROUTINE diagnostic_output_table
+
+
+
+
+SUBROUTINE calculate_size_of_output_file(istat,ioaid,iope_map,this_io_grpsize,global_pool_offset,data_bytes,ntables,npools,NHDR,iwrite_empty, LL_write_empty, active_table_id)
+INTEGER(KIND=JPIM), intent(in)              :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), intent(in)              :: ioaid(:,:,:)
+INTEGER(KIND=JPIM), intent(in)              :: iope_map(:,:)
+INTEGER(KIND=JPIM), intent(in)              :: active_table_id(:)
+INTEGER(KIND=JPIM), intent(in)              :: this_io_grpsize
+INTEGER(KIND=JPIM), intent(in)              :: global_pool_offset(:)
+REAL(KIND=JPRB), intent(inout)              :: data_bytes(:) ! nactive_tables
+INTEGER(KIND=JPIM),intent(in)               :: ntables,npools,NHDR,iwrite_empty
+LOGICAL, intent(in)                         :: LL_write_empty
+
+INTEGER(KIND=JPIM)                          :: nw,j,jt,jtact,nbytes,cur_io_grpsize,nrows
+REAL(KIND=JPRB)                             :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('CALCULATE_SIZE_OF_OUTPUT_FILE',0,ZHOOK_HANDLE)
+
+do jt=1,ntables
+!-- Gather total no. of bytes information in advance
+  jtact = active_table_id(jt)
+  if (jtact /= -1)then
+    data_bytes(jtact) = 0
+    do j=1,npools
+      nw = 0
+      cur_io_grpsize = ioaid(j,jt,IOAID_GRPSIZE)
+      if (cur_io_grpsize == 0) cur_io_grpsize = this_io_grpsize
+      nbytes = istat(ISTAT_NBYTES,j,jtact)
+      nrows = istat(ISTAT_NROWS,j,jtact)
+!*AF  if ODB_WRITE_EMPTY_FILES=2 we do not really write...
+      if ((nbytes > 0 .and. (iwrite_empty /= 2 .or. nrows > 0)) .OR. (nbytes <= 0 .AND. LL_write_empty)) then
+        nw = NHDR + (nbytes + sizeof_int - 1)/sizeof_int
+      endif
+      if (iope_map(j,jtact) /= iope_map(j+1,jtact) .OR. &
+         & mod(j-global_pool_offset(j), cur_io_grpsize) == 0 .OR. &
+         & j == npools) then 
+        !-- Account for yet another file ending and allocate space for "HC32" 
+        !   i.e. 4 bytes which was so far unaccounted for when file was "opened"
+        nw = nw + 1
+      endif
+      data_bytes(jtact) = data_bytes(jtact) + nw * sizeof_int
+    enddo
+  endif
+enddo
+IF (LHOOK) CALL DR_HOOK('CALCULATE_SIZE_OF_OUTPUT_FILE',1,ZHOOK_HANDLE)
+
+END SUBROUTINE calculate_size_of_output_file
+
+
+SUBROUTINE allocate_incore_jncore(incore,jncore,istat,npools,jtact,NHDR,maxbytes)
+
+INTEGER(KIND=JPIM), pointer, intent(inout)     :: incore(:)
+INTEGER(KIND=JPIM), pointer, intent(inout)     :: jncore(:)
+INTEGER(KIND=JPIM), intent(in)                 :: istat(:,:,:) ! nstat x npools x nactive_tables
+INTEGER(KIND=JPIM), intent(in)                 :: npools,jtact,NHDR
+INTEGER(KIND=JPIM), intent(inout)              :: maxbytes
+
+INTEGER(KIND=JPIM)                             :: nwmax, iret
+REAL(KIND=JPRB)                                :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_INCORE_JNCORE',0,ZHOOK_HANDLE)
+
+  !-- Allocate data buffer
+    maxbytes = MAXVAL(istat(ISTAT_NBYTES,1:npools,jtact))
+    nwmax = NHDR + max(1,(maxbytes + sizeof_int - 1)/sizeof_int)
+    CALL allocate_incore(incore, nwmax, iret)
+  
+IF (LHOOK) CALL DR_HOOK('ALLOCATE_INCORE_JNCORE',1,ZHOOK_HANDLE)
+
+END SUBROUTINE allocate_incore_jncore
+
+
+
+
+
+SUBROUTINE make_temporary_backups_of_table_files(dbname,CLtbl,jt,npools,LL_mypool,LL_has_backup,ioaid,this_io_grpsize)
+
+CHARACTER(len=maxvarlen), intent(in)               :: dbname
+CHARACTER(len=maxvarlen), intent(in)               :: CLtbl
+INTEGER(KIND=JPIM), intent(in)                     :: jt, npools, this_io_grpsize
+LOGICAL, intent(in)                                :: LL_mypool(:)
+LOGICAL, intent(inout)                             :: LL_has_backup(:,:)
+INTEGER(KIND=JPIM), intent(inout)                  :: ioaid(:,:,:)
+
+INTEGER(KIND=JPIM), save                           :: io_backup_enable = 0 ! By default do *NOT* enable back ups (thanks Bob C.!!)
+INTEGER(KIND=JPIM)                                 :: j, iret
+CHARACTER(len=4096)                                :: filename, CLdirname, CLbasename
+REAL(KIND=JPRB)                                    :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('MAKE_TEMPORARY_BACKUPS_OF_TABLE_FILES',0,ZHOOK_HANDLE)
+
+!-- To start with : *rename* any existing table-files into backup file
+  do j=1,npools
+!! The following call to codb_remove_tablefile() has been removed since
+!! if job finished/aborted before updated version has been written to disk
+!! the whole database would be corrupt (SS/4-Jul-2003)
+!! Instead, backup files will be created and then removed at the very end
+!!      if (LL_mypool(j)) CALL codb_remove_tablefile(dbname, CLtbl, j, iret)
+    if (io_backup_enable /= 0) then
+      if (LL_mypool(j)) then ! More failsafe
+        call makefilename(dbname, CLtbl, j, filename)
+        call true_dirname_and_basename(trim(filename), CLdirname, CLbasename)
+        call codb_rename_file(trim(filename), trim(CLdirname)//'/'//trim(CLbasename)//'.BACKUP', iret)
+        LL_has_backup(j,jt) = (iret == 0)  ! True if a backup has been made
+      endif
+    endif
+    ! Reset ioaid for this pool,table
+    ioaid(j,jt,IOAID_FILENO) = 0
+    ioaid(j,jt,IOAID_OFFSET) = 0
+    ioaid(j,jt,IOAID_LENGTH) = 0
+    if (ioaid(j,jt,IOAID_GRPSIZE) == 0) ioaid(j,jt,IOAID_GRPSIZE) = this_io_grpsize
+    ioaid(j,jt,IOAID_NROWS)  = 0
+  enddo
+
+IF (LHOOK) CALL DR_HOOK('MAKE_TEMPORARY_BACKUPS_OF_TABLE_FILES',1,ZHOOK_HANDLE)
+
+END SUBROUTINE make_temporary_backups_of_table_files
+
+
+END MODULE odbio_msgpass
diff --git a/odb/src/module/odbiomap.F90 b/odb/src/module/odbiomap.F90
new file mode 100644
index 0000000..748cec1
--- /dev/null
+++ b/odb/src/module/odbiomap.F90
@@ -0,0 +1,106 @@
+MODULE odbiomap
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE odbshared
+USE odbmp
+USE odbutil
+
+implicit none
+
+SAVE
+PUBLIC
+
+!-- I/O-aid cases
+INTEGER(KIND=JPIM), parameter :: IOAID_FBLOCK  = 1
+INTEGER(KIND=JPIM), parameter :: IOAID_GRPSIZE = 2
+INTEGER(KIND=JPIM), parameter :: IOAID_POOLNO  = 3
+INTEGER(KIND=JPIM), parameter :: IOAID_FILENO  = 4
+INTEGER(KIND=JPIM), parameter :: IOAID_OFFSET  = 5
+INTEGER(KIND=JPIM), parameter :: IOAID_LENGTH  = 6
+INTEGER(KIND=JPIM), parameter :: IOAID_NROWS   = 7
+INTEGER(KIND=JPIM), parameter :: IOAID_NCOLS   = 8
+INTEGER(KIND=JPIM), parameter :: IONAID = 8 ! Always max. of IOAID_*'s
+
+#include "fwrite_iomap.h"
+
+CONTAINS
+
+SUBROUTINE comm_iomap(khandle, kcase, kret)
+implicit none
+INTEGER(KIND=JPIM), intent(in)  :: khandle, kcase
+INTEGER(KIND=JPIM), intent(out) :: kret
+
+INTEGER(KIND=JPIM) naid, j, jt
+character(len=1) CLenv
+INTEGER(KIND=JPIM), POINTER :: ioaid(:,:,:), grpsize(:) ! A shorthand notations
+
+kret = 0
+naid = db(khandle)%naid
+ioaid => db(khandle)%ioaid
+grpsize => db(khandle)%grpsize
+
+if (naid > 0) then
+  if (kcase == 0) then
+    CALL ODBMP_global('MAX', grpsize)
+  else if (kcase == 1) then ! First thing in msgpass_loaddata / msgpass_storedata
+    CALL ODBMP_global('MAX', ioaid)
+  else if (kcase == 2) then ! Last thing in msgpass_storedata (if STOREing)
+    CALL ODBMP_global('MAX', ioaid)
+  endif
+  if (ODBMP_myproc == 1 .and. (kcase == 1 .OR. kcase == 2)) then
+    CALL codb_getenv('ODB_PRINT_IOAID', CLenv)
+    if (CLenv == '1') then
+      write(0,*)'>>> COMM_IOMAP : kcase=',kcase,' <<<'
+      write(0,'(a4,1x,a5,1x,a5,1x,a5,1x,a12,1x,a12,1x,a12,1x,a5)') &
+        'FBLK','GRPSZ','POOL#', &
+        'FILE#','OFFSET','LENGTH', &
+        'NROWS', 'NCOLS'
+      do jt=1,size(ioaid,dim=2)
+        write(0,*)'==> Tblno#',jt
+        do j=1,size(ioaid,dim=1)
+          write(0,'(i4,1x,i5,1x,i5,1x,i5,1x,i12,1x,i12,1x,i12,1x,i5)') &
+          ioaid(j,jt,1:naid) ! assuming 8 entries
+        enddo
+      enddo
+      write(0,*)'>>> End of COMM_IOMAP print <<<'
+    endif
+  endif
+endif ! if (naid > 0) ...
+END SUBROUTINE comm_iomap
+
+
+
+SUBROUTINE read_iomap(khandle, kret)
+implicit none
+INTEGER(KIND=JPIM), intent(in)    :: khandle
+INTEGER(KIND=JPIM), intent(out)   :: kret
+
+INTEGER(KIND=JPIM) :: naid, ifblk, ipool_offset
+character(len=maxfilen) :: CLiomap_file
+
+kret = 0
+naid = db(khandle)%naid
+
+if (naid > 0) then
+  if (ODBMP_myproc == 1) then ! Metadata read by PE#1 only
+    CLiomap_file = trim(db(khandle)%name)//'.iomap'
+    ifblk = 0
+    ipool_offset = 0
+    CALL cread_iomap(khandle, trim(CLiomap_file), ifblk, &
+                     ipool_offset, kret)
+  endif
+  CALL comm_iomap(khandle, 0, kret)
+  kret = ifblk
+endif
+END SUBROUTINE read_iomap
+
+
+SUBROUTINE write_iomap(khandle, kret)
+implicit none
+INTEGER(KIND=JPIM), intent(in)    :: khandle
+INTEGER(KIND=JPIM), intent(out)   :: kret
+CALL fwrite_iomap(khandle, kret)
+END SUBROUTINE write_iomap
+
+END MODULE odbiomap
diff --git a/odb/src/module/odbmap_reportype.F90 b/odb/src/module/odbmap_reportype.F90
new file mode 100644
index 0000000..6b5517f
--- /dev/null
+++ b/odb/src/module/odbmap_reportype.F90
@@ -0,0 +1,458 @@
+module odbmap_reportype
+
+use yomhook, only : lhook, dr_hook
+
+integer(kind=4), parameter :: nvind = 2147483647
+
+! Describes a single mapping between different codes and a reportype
+type Mapping
+    integer(kind=4) :: groupid
+    integer(kind=4) :: satid
+    integer(kind=4) :: bufrtype
+    integer(kind=4) :: subtype
+    integer(kind=4) :: obstype
+    integer(kind=4) :: codetype
+    integer(kind=4) :: sensor
+    integer(kind=4) :: reportype
+    integer(kind=4) :: satinst
+    integer(kind=4) :: accumulation_length
+end type
+
+! Stores all code mappings from an input config file
+type AllMappings
+    Type(Mapping), pointer :: Entries(:)
+    integer :: mdi=-1
+end type
+
+Type(AllMappings), save :: CodeMappings
+
+contains
+
+
+subroutine load_config_if_required() 
+    implicit none
+
+    character(len=128) :: config_filename
+
+    ! Check if CodeMappings data structure has already been filled with data
+    ! if CodeMappings not yet filled, then load data from the config file
+    if (.not.associated(CodeMappings%Entries)) then
+        call get_environment_variable("ODB_CODE_MAPPINGS", config_filename)
+        call load_report_type_mappings_from_config(config_filename)
+    end if
+
+
+end subroutine load_config_if_required
+
+
+subroutine find_obstype_codetype(bufrtype, subtype, obstype, codetype, lallsky)
+    implicit none
+
+    integer(kind=4), intent(in)  :: bufrtype
+    integer(kind=4), intent(in)  :: subtype
+    integer(kind=4), intent(out) :: obstype
+    integer(kind=4), intent(out) :: codetype
+    integer(kind=4), parameter   :: allsky_obstype = 16
+    integer(kind=4)              :: i
+    integer(kind=4)              :: n_matches
+    integer(kind=4)              :: n_mappings
+    logical, intent(in)  :: lallsky
+    real(kind=8) :: hook_handle
+    character(len=128), parameter :: hook_label = &
+        & "odbmap_reportype:find_obstype_codetype"
+
+    if (lhook) call dr_hook(hook_label, 0, hook_handle)
+    
+    ! Load data from config file if not already in-memory
+    call load_config_if_required()
+
+    obstype = CodeMappings%mdi
+
+    ! Loop over all mappings, counting number of matches as it goes.
+    n_mappings = size(CodeMappings%Entries)
+    n_matches = 0
+
+    ! Main search for matching code combinations from config file mappings.
+    ! If multiple matches, then the last match is used.
+    MainLoop: do i = 1,n_mappings
+        if (lallsky) then
+            if ((CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                .and. (CodeMappings%Entries(i)%obstype == allsky_obstype)) then
+                
+                codetype = CodeMappings%Entries(i)%codetype
+                obstype = CodeMappings%Entries(i)%obstype
+
+                n_matches = n_matches + 1
+            end if
+        else
+            if ((CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                .and. (CodeMappings%Entries(i)%obstype /= allsky_obstype)) then
+                
+                codetype = CodeMappings%Entries(i)%codetype
+                obstype = CodeMappings%Entries(i)%obstype
+
+                n_matches = n_matches + 1
+            end if
+        end if
+    end do MainLoop
+
+    ! Special case for bit-comparability with old code: Wind profilers.
+    ! Explanation: Mappings from bufrtype,subtype to obstype,codetype are not unique
+    !       -old code contained repeated mappings for same bufrtype,subtype
+    !         -order of if statements determined which mapping was used
+    !       -new config file also contains multiple mappings for the same bufrtype,subtype
+    !         -order in config file is different to that in old code
+    !         -leads to differences in obs rejection (depends on codetype)
+    !       -for bit-comparability, special case inserted here to give same output as old code.
+    if ((bufrtype == 2) .and. (subtype == 96)) then  
+        obstype = 6
+        codetype = 134
+    end if
+
+    ! Exit with error if no matches, or if more than one match
+    if (n_matches == 0) then
+        write(0, "(2(a,i0),a,l1)") 'Error: No obstype/codetype mapping for bufrtype=', &
+            & bufrtype, ", subtype=", subtype, ", all-sky=", lallsky
+        call abor1("find_obstype_codetype")
+    end if 
+
+    if (lhook) call dr_hook(hook_label, 1, hook_handle)
+
+    return
+
+end subroutine find_obstype_codetype
+
+subroutine find_obskind(subtype, satemKind, satobKind, conventionalKind, accumulationKind)
+
+    implicit none
+
+    integer(kind=4), intent(in)   :: subtype
+    integer(kind=4)        :: n_mappings
+    integer(kind=4)        :: i
+    logical, intent(inout) :: satemKind
+    logical, intent(inout) :: satobKind
+    logical, intent(inout) :: conventionalKind
+    logical, intent(inout) :: accumulationKind
+    real(kind=8) :: hook_handle
+    character(len=128), parameter :: hook_label = &
+        & "odbmap_reportype:find_obskind"
+
+    if (lhook) call dr_hook(hook_label, 0, hook_handle)
+
+    call load_config_if_required()
+    n_mappings = size(CodeMappings%Entries)
+
+    MappingLoop: do i = 1,n_mappings
+        ! Find first entry with matching subtype
+        if (CodeMappings%Entries(i)%subtype == subtype)then
+
+            if ((CodeMappings%Entries(i)%sensor /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%satid /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%bufrtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%subtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%obstype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%codetype /= CodeMappings%mdi).and.&
+                (CodeMappings%Entries(i)%accumulation_length == CodeMappings%mdi)) then
+                  satemKind = .True.
+                  exit MappingLoop
+            end if
+            if ((CodeMappings%Entries(i)%sensor == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%satid /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%bufrtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%subtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%obstype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%codetype /= CodeMappings%mdi).and.&
+                (CodeMappings%Entries(i)%accumulation_length == CodeMappings%mdi)) then
+                  satobKind = .True.
+                  exit MappingLoop
+            end if
+            if ((CodeMappings%Entries(i)%sensor == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%satid == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%bufrtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%subtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%obstype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%codetype /= CodeMappings%mdi).and.&
+                (CodeMappings%Entries(i)%accumulation_length == CodeMappings%mdi)) then
+                  conventionalKind = .True.
+                  exit MappingLoop
+            end if
+            if ((CodeMappings%Entries(i)%sensor == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%satid == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%bufrtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%subtype /= CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%obstype == CodeMappings%mdi).and. &
+                (CodeMappings%Entries(i)%codetype == CodeMappings%mdi).and.&
+                (CodeMappings%Entries(i)%accumulation_length /= CodeMappings%mdi)) then
+                  accumulationKind = .True.
+                  exit MappingLoop
+            end if
+        end if
+    end do MappingLoop
+
+    ! Check that a kind has been selected
+    if ((satemKind .EQV. .false.).and.(satobKind .EQV. .false.).and.(conventionalKind .EQV. .false.).and.&
+       (accumulationKind .EQV. .false.)) then
+        write(0, "(a,i0)") 'Error : No Kind found for subtype: ',subtype
+        call abor1("find_obskind")
+    end if
+
+    if (lhook) call dr_hook(hook_label, 1, hook_handle)
+
+end subroutine find_obskind
+
+
+subroutine find_reportype(groupid, satid, bufrtype,subtype,obstype,&
+  & codetype, sensor, reportype, satinst, iproduct_type, iaccumulation_length)
+
+    implicit none
+
+    integer(kind=4), intent(out)   :: groupid
+    integer(kind=4), value   :: sensor, satid
+    integer(kind=4), value   :: bufrtype, subtype, obstype, codetype
+    integer(kind=4), intent(out)  :: reportype, satinst
+    integer(kind=4), intent(in), OPTIONAL  :: iproduct_type
+    integer(kind=4), intent(in), OPTIONAL  :: iaccumulation_length
+    integer(kind=4) :: n_mappings
+    integer(kind=4) :: i 
+    integer(kind=4) :: n_matches
+    integer(kind=4) :: product_type
+    integer(kind=4) :: accumulation_length
+    logical :: satemKind = .False.
+    logical :: satobKind = .False.
+    logical :: conventionalKind = .False.
+    logical :: accumulationKind = .False.
+    real(kind=8) :: hook_handle
+    character(len=128) :: reason
+    character(len=128), parameter :: hook_label = &
+        & "odbmap_reportype:find_reportype"
+
+    if (lhook) call dr_hook(hook_label, 0, hook_handle)
+
+    ! Set default values for incoming optional arguments
+    if (present(iproduct_type)) then
+        product_type = iproduct_type
+    else
+        product_type = CodeMappings%mdi
+    endif
+
+    if (present(iaccumulation_length)) then
+        accumulation_length = iaccumulation_length
+    else
+        accumulation_length = CodeMappings%mdi
+    endif
+
+    ! Initialize output variables
+    reportype = CodeMappings%mdi
+    satinst = CodeMappings%mdi
+    groupid = CodeMappings%mdi
+
+
+    ! Check incoming values are sensible
+    if (abs(sensor) == nvind) sensor = CodeMappings%mdi
+    if (abs(satid) == nvind) satid = CodeMappings%mdi
+    if (abs(bufrtype) == nvind) bufrtype = CodeMappings%mdi
+    if (abs(subtype) == nvind) subtype = CodeMappings%mdi
+    if (abs(obstype) == nvind) obstype = CodeMappings%mdi
+    if (abs(codetype) == nvind) codetype = CodeMappings%mdi
+    if (abs(product_type) == nvind) product_type = CodeMappings%mdi
+    if (abs(accumulation_length) == nvind) accumulation_length = CodeMappings%mdi
+
+    ! Load data from config file if not already in-memory
+    call load_config_if_required()
+
+    ! Loop over all mappings, counting number of matches as it goes.
+    n_mappings = size(CodeMappings%Entries)
+    n_matches = 0
+
+    ! ReportTypes come in several different Kinds: SatobKind, SatemKind, ConventionalKind, AccumulationKind.
+    ! Different codes are used in the mappings for each kind.
+    ! Here, the kind must first be determined from the subtype using the mappings in the config file.
+    ! Then, different checks and return values are set depending on the kind.
+    call find_obskind(subtype, satemKind, satobKind, conventionalKind, accumulationKind)
+
+    ! Special case. Reportype 7003 GRACE A GPSRO is of kind Satem, however when this routine is called it isn't passed sensor or satinst.
+    !               So, we need to treat it as a satob kind which doesn't have the sensor checks.
+    !               To deal with these situations more generally, we check if sensor is passed in or not.
+    if ((satemKind).and.(sensor == CodeMappings%mdi))then
+      satemKind = .false.
+      satobkind = .true.
+    end if
+
+    ! Main search for matching code combinations from config file mappings
+    EntryLoop: do i = 1,n_mappings
+        if (conventionalKind) then
+                if ((CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                    .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                    .and. (CodeMappings%Entries(i)%obstype == obstype) &
+                    .and. (CodeMappings%Entries(i)%codetype == codetype)) then
+
+                    groupid = CodeMappings%Entries(i)%groupid
+                    reportype = CodeMappings%Entries(i)%reportype
+
+                    n_matches = n_matches + 1
+                end if
+        else if (accumulationKind) then
+                if ((CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                    .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                    .and. (CodeMappings%Entries(i)%accumulation_length == accumulation_length)) then
+                    
+                    groupid = CodeMappings%Entries(i)%groupid
+                    reportype = CodeMappings%Entries(i)%reportype
+
+                    n_matches = n_matches + 1
+                end if
+        else if (satemKind) then
+            if ((CodeMappings%Entries(i)%sensor == sensor) &
+                .and. (CodeMappings%Entries(i)%satid == satid) &
+                .and. (CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                .and. (CodeMappings%Entries(i)%obstype == obstype) &
+                .and. (CodeMappings%Entries(i)%codetype == codetype)) then
+                
+                groupid = CodeMappings%Entries(i)%groupid
+                reportype = CodeMappings%Entries(i)%reportype
+                satinst = CodeMappings%Entries(i)%satinst
+
+                n_matches = n_matches + 1
+            end if
+       else if (satobKind) then
+            if ((CodeMappings%Entries(i)%satid == satid) &
+                .and. (CodeMappings%Entries(i)%bufrtype == bufrtype) &
+                .and. (CodeMappings%Entries(i)%subtype == subtype) &
+                .and. (CodeMappings%Entries(i)%obstype == obstype) &
+                .and. (CodeMappings%Entries(i)%codetype == codetype)) then
+                
+                groupid = CodeMappings%Entries(i)%groupid
+                reportype = CodeMappings%Entries(i)%reportype
+                satinst = CodeMappings%Entries(i)%satinst
+
+                n_matches = n_matches + 1
+            end if
+      end if
+    end do EntryLoop
+
+    ! Exit with error if no matches, or if more than one match
+    if (n_matches /= 1) then
+
+        if (n_matches == 0) then
+            write(reason, "(a)") 'Error: No reportype mapping: '
+        else if (n_matches > 1) then
+            write(reason ,"(a)") 'Error: Non-unique reportype mapping: '
+        end if
+
+        write(0, "(a,10(a,i0))") trim(reason), " reportype=", reportype, &
+            & ", groupid=", groupid, ", bufrtype=", bufrtype, ", subtype=", subtype, &
+            & ", obstype=", obstype, ", codetype=", codetype, ", sensor=", sensor, &
+            & ", satinst=", satinst, ", satid=", satid, ", accumulation_length=", &
+            & accumulation_length
+
+        call abor1("find_reportype")
+    end if 
+
+    if (lhook) call dr_hook(hook_label, 1, hook_handle)
+
+    return
+
+end subroutine find_reportype
+
+function count_lines_in_file(file_handle) result(n_lines)
+    ! Counts the number of lines in the file
+
+    implicit none
+
+    integer(kind=4), intent(in) :: file_handle
+    integer(kind=4) :: RetCode
+    integer(kind=4) :: n_lines
+
+    n_lines = 0
+    LineCount: do 
+        read(file_handle,*, iostat = RetCode)
+        if (RetCode < 0) exit
+        n_lines = n_lines + 1
+    end do LineCount
+
+    rewind(file_handle)
+
+end function count_lines_in_file
+
+subroutine load_report_type_mappings_from_config(config_filename)
+    ! Loads reportype mapping data from ODB-Gov config file
+    implicit none
+
+    character(len=*), intent(in) :: config_filename
+
+    integer(kind=4) :: i
+    integer(kind=4) :: file_handle
+    integer(kind=4) :: n_mappings
+    integer(kind=4) :: n_lines
+    integer(kind=4) :: sensor
+    integer(kind=4) :: satid
+    integer(kind=4) :: bufrtype
+    integer(kind=4) :: subtype
+    integer(kind=4) :: obstype
+    integer(kind=4) :: codetype
+    integer(kind=4) :: accumulation_length
+    integer(kind=4) :: groupid
+    integer(kind=4) :: reportype
+    integer(kind=4) :: satinst
+    integer(kind=4) :: RetCode
+    integer(kind=4) :: default_value
+    real(kind=8) :: hook_handle
+    character(len=128), parameter :: hook_label = &
+        & "odbmap_reportype:load_repor_type_mappings_from_config"
+
+    if (lhook) call dr_hook(hook_label, 0, hook_handle)
+
+    default_value = CodeMappings%mdi
+
+    file_handle = 10
+    open(unit=file_handle,file=config_filename,status='old',action='read',iostat=RetCode)
+    if (RetCode /= 0)then
+      write(0,*) 'Error opening ODB reportype mapping config file : filename, retcode ',trim(config_filename),RetCode
+      call abor1("Error opening ODB reportype mapping config file")
+    end if
+
+    i = 1
+
+    ! Count the number of lines in the file
+    n_lines = count_lines_in_file(file_handle)
+    n_mappings = n_lines - 1 ! First line in config file is header
+
+    allocate(CodeMappings%Entries(n_mappings))
+
+    ReadLoop: do i = 0,n_mappings
+        if (i==0) then
+            ! Ignore the first line - contains column headings, no data.
+            read(file_handle,*)
+        else
+
+            ! Read columns from file
+            read(file_handle,*,iostat=RetCode) reportype, groupid, bufrtype, subtype, obstype,&
+                     & codetype, sensor, satinst, satid, accumulation_length
+
+            if ( RetCode == -1) exit ReadLoop ! End of file
+
+            if ( RetCode == 0 ) then
+                CodeMappings%Entries(i)%sensor = sensor
+                CodeMappings%Entries(i)%satid = satid
+                CodeMappings%Entries(i)%bufrtype = bufrtype
+                CodeMappings%Entries(i)%subtype = subtype
+                CodeMappings%Entries(i)%obstype = obstype
+                CodeMappings%Entries(i)%codetype = codetype
+                CodeMappings%Entries(i)%accumulation_length = accumulation_length
+                CodeMappings%Entries(i)%groupid = groupid
+                CodeMappings%Entries(i)%reportype = reportype
+                CodeMappings%Entries(i)%satinst = satinst
+            end if
+        end if
+    end do ReadLoop
+  
+    close(file_handle)
+
+    if (lhook) call dr_hook(hook_label, 1, hook_handle)
+
+end subroutine load_report_type_mappings_from_config
+
+end module odbmap_reportype
diff --git a/odb/src/module/odbmp.F90 b/odb/src/module/odbmp.F90
new file mode 100644
index 0000000..65ec934
--- /dev/null
+++ b/odb/src/module/odbmp.F90
@@ -0,0 +1,380 @@
+#ifdef RS6K
+ at PROCESS NOCHECK
+#endif
+MODULE odbmp
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+USE str, only : sadjustl, sadjustr
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+#ifndef USE_CTRIM
+#define ctrim(x) x
+#define CTRIM(x) x
+#endif
+
+INTEGER(KIND=JPIM), parameter :: ntree = 2
+
+INTEGER(KIND=JPIM), parameter :: Success = 0
+
+INTEGER(KIND=JPIM), parameter :: rootPE = 1
+INTEGER(KIND=JPIM), parameter :: comm = 0
+INTEGER(KIND=JPIM), parameter :: sync = 0
+INTEGER(KIND=JPIM), parameter :: block = 0
+
+INTEGER(KIND=JPIM) :: ODBMP_nproc  = 0
+INTEGER(KIND=JPIM) :: ODBMP_myproc = 0
+logical :: mp_trace = .FALSE.
+logical :: mp_initialized_here = .FALSE.
+
+INTERFACE ODBMP_global
+MODULE PROCEDURE &
+     &ODBMP_iglobal       , ODBMP_dglobal       , &
+     &ODBMP_iglobal_2d    , ODBMP_dglobal_2d    , &
+     &ODBMP_iglobal_3d    , ODBMP_dglobal_3d    , &
+     &ODBMP_iglobal_scalar, ODBMP_dglobal_scalar
+END INTERFACE
+
+INTERFACE ODBMP_exchange1
+MODULE PROCEDURE & 
+  & ODBMP_iexchange1, ODBMP_dexchange1
+END INTERFACE
+
+INTERFACE ODBMP_exchange2
+MODULE PROCEDURE & 
+  & ODBMP_iexchange2, ODBMP_dexchange2
+END INTERFACE
+
+INTERFACE ODBMP_distribute
+MODULE PROCEDURE &
+  ODBMP_idistribute, ODBMP_ddistribute
+END INTERFACE
+
+PUBLIC :: ODBMP_nproc, ODBMP_myproc
+PUBLIC :: ODBMP_abort
+PUBLIC :: ODBMP_init
+PUBLIC :: ODBMP_end
+PUBLIC :: ODBMP_global
+PUBLIC :: ODBMP_sync
+PUBLIC :: ODBMP_exchange1
+PUBLIC :: ODBMP_exchange2
+PUBLIC :: ODBMP_distribute
+PUBLIC :: ODBMP_testready
+PUBLIC :: ODBMP_locking
+PUBLIC :: ODBMP_trace
+PUBLIC :: ODBMP_physproc
+PUBLIC :: ODBMP_setup_exchange
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+CONTAINS
+
+!---  Private routines ---
+
+!---  Public routines ---
+
+FUNCTION ODBMP_physproc(x) RESULT(physproc)
+INTEGER(KIND=JPIM), intent(in) :: x
+INTEGER(KIND=JPIM) :: physproc
+!physproc = min(max(1,mod(x-1,ODBMP_nproc)+1),ODBMP_nproc)
+physproc = mod(x-1,ODBMP_nproc)+1
+END FUNCTION ODBMP_physproc
+
+
+FUNCTION ODBMP_setup_exchange(opponent, start_proc) &
+         RESULT(n)
+!-- Setup tournament table approach in order to exchange
+!   messages with pairs of processors simultaneously
+USE MPL_MODULE
+implicit none
+INTEGER(KIND=JPIM), intent(out) :: opponent(:)
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: start_proc
+INTEGER(KIND=JPIM) :: k, n, istart_proc
+
+CALL MPL_TOUR_TABLE(opponent,KEVEN=n)
+
+if (present(start_proc)) then
+  istart_proc = start_proc
+else
+  istart_proc = 0
+endif
+
+do k=1,n
+  if (opponent(k) > 0 .and. opponent(k) <= ODBMP_nproc) then
+    opponent(k) = opponent(k) + istart_proc
+  else
+    opponent(k) = -1
+  endif
+enddo
+END FUNCTION ODBMP_setup_exchange
+
+
+SUBROUTINE ODBMP_trace(trace_on)
+implicit none
+logical, intent(in) :: trace_on
+mp_trace = trace_on
+END SUBROUTINE ODBMP_trace
+
+FUNCTION ODBMP_locking(lockid, onoff) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: lockid, onoff
+INTEGER(KIND=JPIM) rc, info(2), i
+INTEGER(KIND=JPIM), parameter :: maxlocks = 64
+logical, save :: locks(0:maxlocks) = (/(.FALSE., i=0,maxlocks)/)
+INTEGER(KIND=JPIM) id
+rc = 0
+if (onoff /= -1) then
+  id = lockid
+else
+  id = 13
+endif
+if (mp_trace) then
+  info(1) = id
+  info(2) = onoff
+  CALL cODB_trace(-1, 2,'ODBMP_locking', info, size(info))
+endif
+if (onoff == 1) then
+  if (id >= 0 .and. id <= maxlocks) then
+    if (.not.locks(id)) CALL mpe_lock(id, rc)
+  else
+    CALL mpe_lock(id, rc)
+  endif
+  if (id >= 0 .and. id <= maxlocks) locks(id) = .TRUE.
+else if (onoff == 0) then
+  if (id >= 0 .and. id <= maxlocks) then
+    if (locks(id)) CALL mpe_unlock(id, rc)
+  else
+    CALL mpe_unlock(id, rc)
+  endif  
+  if (id >= 0 .and. id <= maxlocks) locks(id) = .FALSE.
+else if (onoff == -1) then
+!-- A special case: enforce locking/unlocking using lock#13
+  if (locks(id)) then  ! Already locked ==> then unlock
+    CALL mpe_unlock(id, rc)
+    locks(id) = .FALSE.
+  else
+    CALL mpe_lock(id, rc)
+    locks(id) = .TRUE.
+  endif
+endif
+END FUNCTION ODBMP_locking
+
+
+SUBROUTINE ODBMP_abort(routine, s, code, really_abort)
+USE OML_MOD, ONLY : OML_MY_THREAD
+implicit none
+character(len=*), intent(in) :: routine
+character(len=*), intent(in), optional :: s
+INTEGER(KIND=JPIM),          intent(in), optional :: code
+logical,          intent(in), optional :: really_abort
+logical do_abort
+character(len=20) errwarn
+INTEGER(KIND=JPIM) :: idummy(1)
+
+errwarn = '*** Error'
+do_abort = .TRUE.
+
+if (present(really_abort)) then
+  if (.not. really_abort) errwarn = '*** Warning'
+  do_abort = really_abort
+endif
+
+write(0,'(1x,a,i3,a)')trim(errwarn)//' in routine "'//trimadjL(routine)//&
+          '" (thread#',OML_MY_THREAD(),')'
+
+if (present(s))    write(0,*) trimadjL(s)
+if (present(code)) write(0,*) 'Message code =',code
+
+if (do_abort) then
+  if (mp_trace) then
+    if (present(code)) then
+      CALL cODB_trace(-1, 2,'ODBMP_abort:'//routine, (/code/), 1)
+    else
+      CALL cODB_trace(-1, 2,'ODBMP_abort:'//routine, idummy, 0)
+    endif
+
+    CALL cODB_trace_end()
+  endif
+
+#ifdef RS6K
+  CALL XL__TRBK()
+#endif
+
+  if (present(s)) then
+    CALL cODB_abort_func(trim(routine)//' : '//trim(s)//char(0))
+  else
+    CALL cODB_abort_func(trim(routine)//' : '//char(0))
+  endif
+endif
+END SUBROUTINE ODBMP_abort
+
+
+
+SUBROUTINE ODBMP_init(LDsync)
+
+#ifdef USE_8_BYTE_WORDS
+  Use mpi4to8, Only : MPI_INITIALIZED => MPI_INITIALIZED8
+#endif
+USE MPL_MODULE
+implicit none
+logical, intent(in), optional :: LDsync
+INTEGER(KIND=JPIM) :: rc, mbxsize, ienforce, iverbose
+logical, save :: first_time = .TRUE.
+integer :: llinit
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_INIT',0,ZHOOK_HANDLE)
+if (first_time) then
+  if (MPL_NUMPROC == -1) then
+    !-- Thanks to Andreas Rhodin, DWD 27/08/2004
+    CALL MPI_INITIALIZED (llinit, rc) ! A direct call to MPI-routine, not via MPL ;-(
+    CALL MPL_INIT(LDINFO=.FALSE.) ! Regardless of LLinit, still need to get ECMWF MPL local variables in sync
+    mp_initialized_here = llinit == 0
+  endif
+  ODBMP_nproc = MPL_NPROC()
+  ODBMP_myproc = MPL_MYRANK()
+  first_time = .FALSE.
+  CALL cODB_init(ODBMP_myproc, ODBMP_nproc)
+!-- Not needed since MPL-library has already taken care of this shitoger
+!  if (ODBMP_nproc > 1) then
+!    ienforce = 0
+!    iverbose = 0
+!    CALL fODB_propagate_env(ienforce, iverbose)
+!  endif
+  if (present(LDsync)) then
+    if (LDsync) CALL ODBMP_sync()
+  else
+    CALL ODBMP_sync()
+  endif
+endif
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_INIT',1,ZHOOK_HANDLE)
+END SUBROUTINE ODBMP_init
+
+
+
+FUNCTION ODBMP_end() RESULT(rc)
+USE MPL_MODULE
+implicit none
+INTEGER(KIND=JPIM) :: rc
+INTEGER(KIND=JPIM), parameter :: iperform(1) = 1
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_END',0,ZHOOK_HANDLE)
+rc=0
+if (mp_trace) then
+  CALL cODB_trace(-1, 2,'ODBMP_end',iperform, 1)
+endif
+if (mp_initialized_here) CALL MPL_END(KERROR=rc)
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_END',1,ZHOOK_HANDLE)
+END FUNCTION ODBMP_end
+
+
+
+SUBROUTINE ODBMP_sync(where)
+USE MPL_MODULE
+implicit none
+INTEGER(KIND=JPIM), intent(in), optional :: where
+INTEGER(KIND=JPIM) :: rc, trace_data(2), trace_len
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_SYNC',0,ZHOOK_HANDLE)
+!      write(0,*)'ODBMP_sync: On PE#',ODBMP_myproc
+if (ODBMP_nproc > 1) then
+  if (mp_trace) then
+    trace_len = 0
+    trace_len = trace_len + 1
+    trace_data(trace_len) = ODBMP_nproc
+    if (present(where)) then
+      trace_len = trace_len + 1
+      trace_data(trace_len) = where
+    endif
+    CALL cODB_trace(-1, 2,'ODBMP_sync',trace_data,trace_len)
+  endif
+  CALL MPL_BARRIER
+endif
+IF (LHOOK) CALL DR_HOOK('ODBMP:ODBMP_SYNC',1,ZHOOK_HANDLE)
+END SUBROUTINE ODBMP_sync
+
+
+
+FUNCTION ODBMP_testready(with) RESULT(is_ready)
+USE MPL_MODULE
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: with
+INTEGER(KIND=JPIM) :: rc
+INTEGER(KIND=JPIM), parameter :: msgtag = 1996
+INTEGER(KIND=JPIM), parameter :: msglen = 1
+INTEGER(KIND=JPIM) :: target, msg, info(4)
+INTEGER(KIND=JPIM) :: recv_count, recv_from, recv_tag
+logical is_ready
+
+is_ready = .TRUE.
+target = max(1,min(abs(with),ODBMP_nproc))
+!      write(0,*)'ODBMP_testready: On PE#',ODBMP_myproc,
+!     $     ':',target,':',with
+if (target /= ODBMP_myproc) then
+  if (with > 0) then
+!--   I'll send() an acknowledgement that I'm ready now
+    msg = ODBMP_myproc
+    if (mp_trace) then
+      info(1) = target
+      info(2) = msglen
+      info(3) = msgtag
+      CALL cODB_trace(-1, 2,'ODBMP_testready:send',info,3)
+    endif
+    CALL MPL_SEND(msg,kdest=target,ktag=msgtag)
+  else if (with < 0) then
+!--   I'll wait in recv() until the recipient is ready
+    if (mp_trace) then
+      info(1) = target
+      info(2) = msglen
+      info(3) = msgtag
+      CALL cODB_trace(-1, 1,'ODBMP_testready:recv',info,3)
+    endif
+    CALL MPL_RECV(msg,ksource=target,ktag=msgtag,&
+     &kount=recv_count,kfrom=recv_from,krecvtag=recv_tag,kerror=rc)
+    if (mp_trace) then
+      info(1) = recv_from
+      info(2) = recv_count
+      info(3) = recv_tag
+      info(4) = rc
+      CALL cODB_trace(-1, 0,'ODBMP_testready:recv',info,4)
+    endif
+    if (rc == Success) rc = recv_count
+    is_ready = (&
+     &msg == target .and. &
+     &recv_from == target .and.&
+     &recv_tag == msgtag .and.&
+     &rc == 1)
+  endif
+endif
+END FUNCTION ODBMP_testready
+
+#undef INT_VERSION
+#undef REAL_VERSION
+
+#define INT_VERSION 4
+#include "fodbmp.h"
+#include "fodbmp1.h"
+#include "fodbmp2.h"
+#undef INT_VERSION
+
+#define REAL_VERSION 8
+#include "fodbmp.h"
+#include "fodbmp1.h"
+#include "fodbmp2.h"
+#undef REAL_VERSION
+
+#ifndef USE_CTRIM
+#undef ctrim
+#undef CTRIM
+#endif
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odbmp
diff --git a/odb/src/module/odbnetcdf.F90 b/odb/src/module/odbnetcdf.F90
new file mode 100644
index 0000000..fe938ec
--- /dev/null
+++ b/odb/src/module/odbnetcdf.F90
@@ -0,0 +1,500 @@
+MODULE odbnetcdf
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE odbshared
+USE odbmp
+USE odbutil
+USE odb
+USE odbgetput
+USE str, only : tolower, sadjustl
+
+!RJ #define trimadjL(x) trim(sadjustl(x))
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+INTERFACE ODB_to_netcdf
+MODULE PROCEDURE & 
+  & ODB_to_netcdf_dtname
+END INTERFACE
+
+INTEGER(KIND=JPIM) :: icdf_char    = -1
+INTEGER(KIND=JPIM) :: icdf_byte    = -1
+INTEGER(KIND=JPIM) :: icdf_short   = -1 
+INTEGER(KIND=JPIM) :: icdf_int     = -1
+INTEGER(KIND=JPIM) :: icdf_float   = -1
+INTEGER(KIND=JPIM) :: icdf_double  = -1
+INTEGER(KIND=JPIM) :: icdf_unknown = -1
+REAL(KIND=JPRB), parameter :: too_big4float = 1.7E+38_JPRB
+REAL(KIND=JPRB), parameter :: too_tiny = 1E-15_JPRB
+
+PUBLIC :: ODB_to_netcdf
+PUBLIC :: to_netcdf
+PUBLIC :: init_cdf
+
+CONTAINS
+
+SUBROUTINE init_cdf()
+implicit none
+logical, save :: LLfirst_time = .TRUE.
+if (LLfirst_time) then
+  CALL codb_gettype_netcdf('char', icdf_char)
+  CALL codb_gettype_netcdf('byte', icdf_byte)
+  CALL codb_gettype_netcdf('short', icdf_short)
+  CALL codb_gettype_netcdf('int', icdf_int)
+  CALL codb_gettype_netcdf('float', icdf_float)
+  CALL codb_gettype_netcdf('double', icdf_double)
+  CALL codb_gettype_netcdf('unknown', icdf_unknown)
+  LLfirst_time = .FALSE.
+endif
+END SUBROUTINE init_cdf
+
+
+SUBROUTINE modify_type(pd, mdi, itype, ipack, scale_factor, add_offset, pref_out, LDnopacking)
+implicit none
+REAL(KIND=JPRB), intent(in) :: pd(:)
+REAL(KIND=JPRB), intent(in) :: mdi
+INTEGER(KIND=JPIM), intent(inout) :: itype
+INTEGER(KIND=JPIM), intent(out) :: ipack
+REAL(KIND=JPRB), intent(out) :: scale_factor, add_offset, pref_out
+logical, intent(in) :: LDnopacking
+INTEGER(KIND=JPIM) j, nrows, count_mdis, count_zeros, count_thesame, count_ints, iref
+REAL(KIND=JPRB)    :: zmin, zmax, zref
+REAL(KIND=JPRB), parameter :: rmax_byte_dist  =   127_JPRB
+REAL(KIND=JPRB), parameter :: rmax_short_dist = 32767_JPRB
+ipack = 0
+scale_factor = 1
+add_offset = 0
+pref_out = abs(mdi)
+nrows = size(pd)
+if (nrows == 0) return
+if (LDnopacking) then
+  if (itype /= icdf_char) itype = icdf_double ! full precision preserved; and on strings by definition
+  return
+endif
+
+if (itype /= icdf_char) then
+  count_mdis = count(abs(pd(1:nrows)) == abs(mdi))
+  count_zeros = count(pd(1:nrows) == 0)
+
+  if (count_zeros + count_mdis == nrows) then
+    itype = icdf_byte
+  endif
+
+  if (itype == icdf_float) then
+    count_ints = 0
+    do j=1,nrows
+      if (abs(pd(j)) /= abs(mdi)) then
+        if (abs(pd(j)) > 2147483647) exit
+        iref = int(pd(j))
+        zref = iref
+        if (zref /= pd(j)) exit
+        count_ints = count_ints + 1
+      endif
+    enddo
+    if (count_ints == nrows - count_mdis) itype = icdf_int
+  endif
+
+  if (itype == icdf_int) then
+    if (count(abs(pd(1:nrows)) < 128 .AND. abs(pd(1:nrows)) /= abs(mdi)) == &
+        nrows - count_mdis) then
+      itype = icdf_byte
+    else if (count(abs(pd(1:nrows)) < 32768 .AND. abs(pd(1:nrows)) /= abs(mdi)) == &
+             nrows - count_mdis) then
+      itype = icdf_short
+    endif
+  else if (itype == icdf_float) then
+    if (count(abs(pd(1:nrows)) > too_big4float .AND. abs(pd(1:nrows)) /= abs(mdi)) > 0) &
+      itype = icdf_double
+  endif
+endif
+zref = pd(1)
+count_thesame = 1
+do j=2,nrows
+  if (pd(j) /= zref) exit
+  count_thesame = count_thesame + 1
+enddo
+count_thesame = -1 ! ncview doesn't appreciate these and no actual gain in filesize
+if (count_thesame == nrows) then ! all values the same as pd(1)
+  ipack = 1
+  pref_out = zref
+else if (count_mdis < nrows .AND. &
+  (itype == icdf_float .OR. itype == icdf_double .OR. itype == icdf_int)) then
+  zmin = minval(pd(1:nrows),MASK=abs(pd(1:nrows)) /= abs(mdi))
+  zmax = maxval(pd(1:nrows),MASK=abs(pd(1:nrows)) /= abs(mdi))
+  if (zmax == zmin) then
+    scale_factor = 1
+    add_offset = zmin
+    itype = icdf_byte
+    ipack = 3
+  else if (itype == icdf_int .AND. zmax - zmin < rmax_byte_dist) then
+    scale_factor = 1
+    add_offset = zmin
+    itype = icdf_byte
+    ipack = 3
+  else if (itype == icdf_int .AND. zmax - zmin < rmax_short_dist) then
+    scale_factor = 1
+    add_offset = zmin
+    itype = icdf_short
+    ipack = 2
+  else if (itype /= icdf_int) then
+    scale_factor = (zmax - zmin)/(rmax_short_dist - 1.0_JPRB)
+    add_offset = zmin
+    itype = icdf_short
+    ipack = 2
+  endif
+endif
+END SUBROUTINE modify_type
+
+SUBROUTINE to_netcdf(title, ncfile, namecfg, sql_query, &
+     & d, &
+     & itype, &
+     & odb_type, odb_name, odb_nickname, &
+     & mdi, ipoolno, LDnopacking, LDdebug_mode)
+implicit none
+character(len=*), intent(in) :: title, ncfile, namecfg, sql_query
+character(len=*), intent(in) :: odb_type(:), odb_name(:), odb_nickname(:)
+REAL(KIND=JPRB), intent(in) :: d(:,:)
+INTEGER(KIND=JPIM), intent(inout) :: itype(:)
+REAL(KIND=JPRB), intent(in) :: mdi
+INTEGER(KIND=JPIM), intent(in) :: ipoolno
+logical, intent(in) :: LDnopacking, LDdebug_mode
+INTEGER(KIND=JPIM) i, j, nrows, ncols, iret, ncid, icnt, ios, ii_cnt
+INTEGER(KIND=JPIM) icolid(size(itype)), ipack(size(itype)), idx(size(itype))
+REAL(KIND=JPRB) :: scale_factor(size(itype)), add_offset(size(itype))
+REAL(KIND=JPRB) :: mdi_out(size(itype)), itype_orig(size(itype))
+REAL(KIND=JPRB), allocatable :: zbuf(:)
+character(len=256), allocatable, save :: refname(:), mapname(:), long_name(:), units(:)
+REAL(KIND=JPRB), allocatable, save :: a(:), b(:)  ! for linear conversions : A * x + B
+character(len=4096) cline
+character(len=4096) CL_namecfg
+character(len=4096), save :: CL_namecfg_last = ' '
+
+nrows = size(d, dim=1)
+ncols = min(size(d, dim=2), size(itype), size(odb_type), size(odb_name), size(odb_nickname))
+
+icnt = 0
+
+CALL codb_truename(trim(namecfg), CL_namecfg, iret)
+if (CL_namecfg == CL_namecfg_last) then
+  if (allocated(refname)) icnt = size(refname)
+  goto 999
+endif
+
+if (LDdebug_mode) &
+  write(0,*) ODBMP_myproc,&
+             ': Opening name-configuration file "'//trim(CL_namecfg(1:iret))//'" (if available)'
+open(1,file=CL_namecfg(1:iret),status='old',err=888)
+CL_namecfg_last = CL_namecfg(1:iret)
+
+do
+  read(1,'(a)',err=98,end=98) cline
+  if (len_trim(cline) == 0) cycle
+  if (cline(1:1) == '!' .OR. cline(1:1) == '#') cycle
+  icnt = icnt + 1
+enddo
+ 98   continue
+
+if (icnt > 0) then
+  rewind(1)
+
+  if (allocated(refname))    deallocate(refname)
+  if (allocated(mapname))    deallocate(mapname)
+  if (allocated(long_name))  deallocate(long_name)
+  if (allocated(units))      deallocate(units)
+  if (allocated(a)) deallocate(a)
+  if (allocated(b)) deallocate(b)
+
+  allocate(refname(icnt))
+  allocate(mapname(0:icnt))    ; mapname(0)    = '-'
+  allocate(long_name(0:icnt))  ; long_name(0)  = '-'
+  allocate(units(0:icnt))      ; units(0)      = '-'
+  allocate(a(0:icnt)) ; a(0) = 1
+  allocate(b(0:icnt)) ; b(0) = 0
+
+  i = 0
+  do
+    read(1,'(a)',err=99,end=99) cline
+    if (len_trim(cline) == 0) cycle
+    cline = sadjustl(cline)
+    if (cline(1:1) == '!' .OR. cline(1:1) == '#') cycle
+    i = i + 1
+    refname(i) = ' '
+    mapname(i) = '-'
+    long_name(i) = '-'
+    units(i) = '-'
+    a(i) = 1
+    b(i) = 0
+    ios = 0
+!!    call tolower(cline)
+    read(cline,*,iostat=ios,err=97,end=97) refname(i),mapname(i),long_name(i),units(i),a(i),b(i)
+ 97 continue
+    if (mapname(i) /= '-' .AND. long_name(i) == '-') long_name(i) = mapname(i)
+    if (LDdebug_mode .AND. ODBMP_myproc == 1) then
+      write(0,*)'>> i,a(i),b(i) & names=',&
+             i, a(i), b(i), &
+             ',refname="'//trim(refname(i))//'"',&
+             ',mapname="'//trim(mapname(i))//'"',&
+             ',long_name="'//trim(long_name(i))//'"',&
+             ',units="'//trim(units(i))//'"'
+    endif
+  enddo
+ 99 continue
+endif
+close(1)
+goto 999
+ 888  continue
+ if (LDdebug_mode) &
+    write(0,*) ODBMP_myproc,': Name-configuration file could not be opened'
+ 999  continue
+
+if (icnt == 0) then
+  if (allocated(refname))    deallocate(refname)
+  if (allocated(mapname))    deallocate(mapname)
+  if (allocated(long_name))  deallocate(long_name)
+  if (allocated(units))      deallocate(units)
+  if (allocated(a)) deallocate(a)
+  if (allocated(b)) deallocate(b)
+
+  allocate(refname(icnt))
+  allocate(mapname(0:icnt))    ; mapname(0)    = '-'
+  allocate(long_name(0:icnt))  ; long_name(0)  = '-'
+  allocate(units(0:icnt))      ; units(0)      = '-'
+  allocate(a(0:icnt)) ; a(0) = 1
+  allocate(b(0:icnt)) ; b(0) = 0
+endif
+
+idx(:) = 0
+ii_cnt = 0
+LOOP_i: do i=icnt,1,-1
+  LOOP_j: do j=1,ncols
+    if (idx(j) == 0 .AND. odb_name(j) == refname(i)) then
+      idx(j) = i
+      ii_cnt = ii_cnt + 1
+      exit LOOP_j
+    endif
+  enddo LOOP_j
+  if (ii_cnt >= ncols) exit LOOP_i
+enddo LOOP_i
+
+write(0,'(a,i10,1x,i5)') '*** Writing to NetCDF-file "'//trim(ncfile)//'" : nrows, ncols =',nrows,ncols
+
+CALL codb_open_netcdf(ncid, trim(ncfile), 'w', iret)
+
+CALL codb_begindef_netcdf(ncid, trim(title), trim(sql_query), nrows, ncols, mdi, ipoolno, iret)
+
+allocate(zbuf(1:nrows))
+
+itype_orig(:) = itype(:)
+
+do j=1,ncols
+  zbuf(1:nrows) = d(1:nrows,j)
+
+  i = idx(j)
+
+  if (a(i) /= 1 .AND. b(i) /= 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = a(i) * zbuf(1:nrows) + b(i)
+  else if (a(i) /= 1 .AND. b(i) == 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = a(i) * zbuf(1:nrows)
+  else if (a(i) == 1 .AND. b(i) /= 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = zbuf(1:nrows) + b(i)
+  endif
+
+  if (itype_orig(j) == icdf_float) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi) .AND. abs(zbuf(1:nrows)) < too_tiny) zbuf(1:nrows) = 0
+  endif
+
+  CALL modify_type(zbuf(1:nrows), &
+                   mdi, itype(j), ipack(j), &
+                   scale_factor(j), add_offset(j), mdi_out(j), Ldnopacking)
+
+  CALL codb_putheader_netcdf(ncid, j, &
+                   odb_type(j), odb_name(j), odb_nickname(j), &
+                   mapname(i), long_name(i), units(i), &
+                   mdi_out(j), itype(j), ipack(j), &
+                   scale_factor(j), add_offset(j), iret)
+  icolid(j) = iret
+enddo
+
+CALL codb_enddef_netcdf(ncid, iret)
+
+do j=1,ncols
+  zbuf(1:nrows) = d(1:nrows,j)
+
+  i = idx(j)
+
+  if (a(i) /= 1 .AND. b(i) /= 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = a(i) * zbuf(1:nrows) + b(i)
+  else if (a(i) /= 1 .AND. b(i) == 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = a(i) * zbuf(1:nrows)
+  else if (a(i) == 1 .AND. b(i) /= 0) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi)) zbuf(1:nrows) = zbuf(1:nrows) + b(i)
+  endif
+
+  if (itype_orig(j) == icdf_float) then
+    WHERE (abs(zbuf(1:nrows)) /= abs(mdi) .AND. abs(zbuf(1:nrows)) < too_tiny) zbuf(1:nrows) = 0
+  endif
+
+  CALL codb_putdata_netcdf(ncid, icolid(j), ipack(j), zbuf(1), 1, nrows, iret)
+enddo
+
+deallocate(zbuf)
+
+CALL codb_close_netcdf(ncid, iret)
+
+END SUBROUTINE to_netcdf
+
+
+FUNCTION ODB_to_netcdf_dtname(handle, dtname,&
+                             &file, poolno,  &
+                             &setvars, values, mdi) RESULT(rc)
+implicit none
+
+! handle = database handle
+INTEGER(KIND=JPIM), intent(in)         :: handle
+! dtname = view or table name to be executed and converted into NETCDF format
+character(len=*), intent(in)  :: dtname
+! file = NETCDF output file
+!        if not given, defaults to trim(dtname)//'.nc.%d', where %d is turned into a poolno
+!        if poolno not given, then %d indicates my MPL-task id , i.e. one of 1..NPES
+character(len=*), intent(in), optional :: file
+! poolno = Pool number in concern (default = -1 i.e. all *local* pools)
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+! setvars = list of $-variables to be altered when SQL is executed
+character(len=*), intent(in), optional :: setvars(:)
+! values = changed values for each $-variable in setvars-list
+REAL(KIND=JPRB)            , intent(in), optional :: values(:)
+! mdi = missing data indicator
+!       if not supplied, abs(ODB_NMDI) becomes the default
+REAL(KIND=JPRB), intent(in), optional :: mdi
+! rc = return code; if  >= 0, then indicates no. of rows processed on this call
+INTEGER(KIND=JPIM) :: rc
+
+INTEGER(KIND=JPIM) :: nrows, ncols, nra
+INTEGER(KIND=JPIM) :: ipoolno, percent_d, iret, i, j
+REAL(KIND=JPRB), allocatable :: d(:,:)
+INTEGER(KIND=JPIM), allocatable :: itype(:)
+character(len=maxvarlen), allocatable :: names(:), types(:), ftntypes(:)
+character(len=4096)  CL_file, CL_title, CL_namecfg
+character(len=maxvarlen)  dbname, env
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(0), idx
+REAL(KIND=JPRB) mdi_out
+logical is_table
+logical LLnopacking, LLdebug_mode
+
+CALL codb_has_netcdf(rc)
+if (rc == 0) then
+  if (ODBMP_myproc == 1) write(0,*)'***Warning: Not compiled with -DHAS_NETCDF => no NetCDF support'
+  return ! no NetCDF support
+endif
+
+is_table = .FALSE.
+if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+
+CALL codb_getenv('ODB_NETCDF_NOPACKING', env) ! set ODB_NETCDF_NOPACKING=1 to see all in double or string
+LLnopacking = (env == '1')
+
+CALL codb_getenv('ODB_NETCDF_DEBUG', env)
+LLdebug_mode = (env == '1')
+
+CALL cODB_trace(handle, 1, 'ODB_to_netcdf:'//dtname,idummy_arr, 0)
+
+rc = 0
+
+if (odbHcheck(handle, 'ODB_to_netcdf')) then
+  ipoolno = get_poolno(handle, poolno)
+  if (ipoolno == -1) then
+    percent_d = ODBMP_myproc
+  else
+    percent_d = ipoolno
+  endif
+
+  if (present(file)) then
+    CL_file = file
+  else
+    CL_file = trim(dtname)//'.nc.%d'
+  endif
+
+  idx = index(CL_file, '%') 
+  if (idx > 0) CALL codb_pc_filter(trim(CL_file), CL_file, percent_d, iret)
+
+  iret = ODB_select(handle, dtname, nrows, ncols, &
+                   &poolno=ipoolno, nra=nra,   &
+                   &setvars=setvars, values=values)
+
+  if (LLdebug_mode) write(0,*) ODBMP_myproc, ': ODB_to_netcdf > dtname="'//trim(dtname)// &
+                               '", poolno,nrows,ncols=',ipoolno,nrows,ncols
+
+  if (nrows > 0) then
+    allocate(names(1:ncols))
+    iret = ODB_getnames(handle, dtname, 'name', names(1:ncols))
+
+    allocate(d(nra,0:ncols))
+    allocate(itype(1:ncols))
+    allocate(types(1:ncols))
+    allocate(ftntypes(1:ncols))
+
+    iret = ODB_getnames(handle, dtname,'type', types(1:ncols))
+    iret = ODB_getnames(handle, dtname,'ftntype', ftntypes(1:ncols))
+
+    CALL init_cdf()
+
+    iret = ODB_get(handle, dtname, d, nrows, ncols, poolno=ipoolno)
+
+    do j=1,ncols
+      if ( ftntypes(j)(1:7) == 'REAL(8)' .and.&
+         &    types(j)(1:7) == 'string ' ) then
+        itype(j) = icdf_char
+      else if ( ftntypes(j)(1:7) == 'CHAR(8)') then ! a future extension
+        itype(j) = icdf_char
+      else if (ftntypes(j)(1:5) == 'REAL(') then
+        itype(j) = icdf_float
+      else if (ftntypes(j)(1:8) == 'INTEGER(') then
+        itype(j) = icdf_int
+      else
+        itype(j) = icdf_unknown
+      endif
+    enddo
+
+    if (present(mdi)) then
+      mdi_out = mdi
+    else
+      mdi_out = ODB_getval(handle, '$mdi')
+      if (mdi_out == 0) mdi_out = abs(ODB_NMDI) ! i.e. $mdi was most likely not defined
+    endif
+
+    iret = ODB_cancel(handle, dtname, poolno=ipoolno)
+
+    dbname = db(handle)%name    
+    if (is_table) then
+      CL_title = 'Database '//trim(dbname)//', table '//trim(dtname(2:))//', pool#%d'
+    else
+      CL_title = 'Database '//trim(dbname)//', data query '//trim(dtname(1:))//', pool#%d'
+    endif
+    CALL codb_pc_filter(trim(CL_title), CL_title, ipoolno, iret)
+
+    CALL codb_getenv('ODB_NAMECFG_'//trim(dbname),CL_namecfg)
+    if (CL_namecfg == ' ') CALL codb_getenv('ODB_NAMECFG',CL_namecfg)
+    if (CL_namecfg == ' ') CL_namecfg = trim(dbname)//'.namecfg'
+
+    CALL to_netcdf(trim(CL_title), trim(CL_file), trim(CL_namecfg), 'N/A', &
+                  & d(1:nrows, 1:ncols), &
+                  & itype(1:ncols), &
+                  & types(1:ncols), names(1:ncols), names(1:ncols), &
+                  & mdi_out, ipoolno, LLnopacking, LLdebug_mode)
+
+    deallocate(d)
+    deallocate(itype)
+    deallocate(names)
+    deallocate(types)
+    deallocate(ftntypes)
+  endif ! if (nrows > 0) then
+
+  rc = nrows
+endif
+
+CALL cODB_trace(handle, 0, 'ODB_to_netcdf:'//dtname,idummy_arr, 0)
+END FUNCTION ODB_to_netcdf_dtname
+
+END MODULE odbnetcdf
diff --git a/odb/src/module/odbprint.F90 b/odb/src/module/odbprint.F90
new file mode 100644
index 0000000..5fae79a
--- /dev/null
+++ b/odb/src/module/odbprint.F90
@@ -0,0 +1,1014 @@
+#ifdef RS6K
+ at PROCESS NOOPTIMIZE NOEXTCHK
+#endif
+
+MODULE odbprint
+
+USE PARKIND1  ,ONLY : JPIM,JPIB,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+
+USE odbshared
+USE odbmp
+USE odbutil
+USE odb
+USE odbgetput
+USE odbstat
+
+#ifdef NAG
+use f90_unix_io, only: flush
+#endif
+
+implicit none
+
+SAVE
+PRIVATE
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+public :: ODB_print
+
+CONTAINS
+
+FUNCTION ODB_print(handle, dtname, &
+     &file, poolno, maxpoolno, &
+     &setvars, values,&
+     &PEvar, replicate_PE,&
+     &show_DB_index, inform_progress, &
+     &open_file, close_file, append_mode, &
+     &select_query, cancel_query, &
+     &latitude, longitude, color, llc_idx, &
+     &start, limit, got, print_title, print_timingstat, print_summary, stat) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: dtname
+character(len=*), intent(in), optional :: file
+character(len=*), intent(in), optional :: setvars(:)
+REAL(KIND=JPRB) , intent(in), optional :: values(:)
+REAL(KIND=JPRB) , intent(inout), optional :: stat(:,:) ! size= (>=6 x ncols) to be meaningful
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, replicate_PE, maxpoolno
+INTEGER(KIND=JPIM), intent(out), optional :: got
+logical, intent(in), optional :: show_DB_index, inform_progress
+logical, intent(in), optional :: open_file, close_file, append_mode
+logical, intent(in), optional :: select_query, cancel_query
+logical, intent(in), optional :: print_title, print_timingstat, print_summary
+REAL(KIND=JPRB), POINTER, optional :: latitude(:), longitude(:), color(:)
+INTEGER(KIND=JPIM), intent(in), optional :: llc_idx(:), start, limit
+character(len=*), intent(in), optional :: PEvar
+
+character(len=1), parameter :: cr = char(13)
+INTEGER(KIND=JPIM) :: nrows, ncols, nalloc, ilow, istart, ilimit, nn, jc
+INTEGER(KIND=JPIM), save :: ilen = 0
+INTEGER(KIND=JPIM) :: iret, j, pe, ipoolno, inc, icol
+INTEGER(KIND=JPIM) :: rc, pemin, pemax
+INTEGER(KIND=JPIM) :: nglb_rows(ODBMP_nproc)
+logical is_table, LLopen_file, LLclose_file, LLappend_mode, LLstdout
+logical LLselect, LLcancel, LLprthdr, LLprttimingstat, LLprtsummary, LLprtunderline
+logical LLinform_progress
+REAL(KIND=JPRB), allocatable :: d(:,:)
+INTEGER(KIND=JPIM), allocatable, save :: itype(:), inclen(:)
+character(len=maxvarlen), allocatable, save :: names(:)
+character(len=maxvarlen), allocatable :: types(:), ftntypes(:)
+character(len=maxstrlen)     CL_file
+INTEGER(KIND=JPIM) :: idummy, idummy_arr(0), nrows_global, imode, inilen, istatlen
+INTEGER(KIND=JPIM), save :: nrows_total
+character(len=80) :: clprtfmt, clprtfile
+INTEGER(KIND=JPIM) iprtfmt_len, iprtfmt, iat, iprtfile_len
+INTEGER(KIND=JPIM) :: icache, imaxpoolno
+INTEGER(KIND=JPIM), parameter :: allowed_cache_size_in_bytes = 262144 ! bytes
+REAL(KIND=JPRB) :: zwall(2)
+REAL(KIND=JPRB), external :: util_walltime  ! from ifsaux/support/drhook.c
+REAL(KIND=JPRB) :: RAD2DEG, x
+REAL(KIND=JPRB) :: RPI, RADIANS, RDEGREE
+RAD2DEG(x) = RDEGREE * x
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODBPRINT:ODB_PRINT',0,ZHOOK_HANDLE)
+
+!-- Consistent with obsproc/control/sunumc.F90
+RPI    =2.0_JPRB*ASIN(1.0_JPRB)
+RADIANS=RPI/180._JPRB
+RDEGREE=180._JPRB/RPI
+
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+
+CALL cODB_trace(handle, 1, 'ODB_print:'//dtname,idummy_arr, 0)
+
+if (showdbidx == 0) then
+  ilow = 1
+else
+  ilow = 0
+endif
+
+LLopen_file = .TRUE.
+if (present(open_file)) LLopen_file = open_file
+
+LLclose_file = .TRUE.
+if (present(close_file)) LLclose_file = close_file
+
+LLappend_mode = .FALSE.
+if (present(append_mode)) LLappend_mode = append_mode
+
+LLselect = .TRUE.
+if (present(select_query)) LLselect = select_query
+
+LLcancel = .TRUE.
+if (present(cancel_query)) LLcancel = cancel_query
+
+if (present(show_DB_index)) then
+  if (show_DB_index) then
+    ilow = 0
+  else
+    ilow = 1
+  endif
+endif
+
+if (present(got)) got = 0
+
+LLprthdr = .TRUE.
+if (present(print_title)) LLprthdr = print_title
+
+LLprttimingstat = .TRUE.
+if (present(print_timingstat)) LLprttimingstat = print_timingstat
+
+inilen = 0
+if (present(stat)) then
+  if (size(stat) > 0) inilen = odb_statcharlen
+endif
+
+LLprtunderline = .FALSE.
+LLprtsummary = .FALSE.
+if (present(print_summary)) LLprtsummary = print_summary
+if (LLprtsummary .and. inilen == 0) LLprtsummary = .FALSE.
+if (LLprtsummary) then
+  LLprthdr = .FALSE.
+  LLprttimingstat = .FALSE.
+  LLselect = .FALSE.
+  LLcancel = .FALSE.
+  istatlen = odb_statlen
+else
+  istatlen = 0
+endif
+
+LLinform_progress=.FALSE.
+
+rc = 0
+nrows_global = 0
+
+if (present(file)) then
+  CALL cODB_envtransf(trim(file), CL_file, iret)
+else
+  CL_file = trim(dtname)//'.rpt'
+endif
+
+LLstdout = .FALSE.
+CALL util_cgetenv('ODB_REPORTER', 'stdout', clprtfile, iprtfile_len)
+if (clprtfile == 'stdout' .or. clprtfile == 'stderr') then
+  LLstdout = .TRUE.
+  CL_file = clprtfile
+endif
+
+if (odbHcheck(handle, 'ODB_print')) then
+  ipoolno = get_poolno(handle, poolno)
+
+  if (LLopen_file) then
+    if (allocated(itype)) deallocate(itype)
+    if (allocated(inclen)) deallocate(inclen)
+    if (allocated(names)) deallocate(names)
+
+    nrows_total = 0
+    nrows_global = 0
+    zwall(:) = 0
+
+    if (ODBMP_myproc == 1.and.present(inform_progress)&
+     &   .and.present(maxpoolno)) then
+       if (inform_progress .and. .not.LLstdout) then
+          imaxpoolno = maxpoolno
+          if (imaxpoolno <= 0) imaxpoolno = db(handle)%glbNpools
+          call codb_set_progress_bar("iounit", 0)
+          call codb_set_progress_bar("maxpool", imaxpoolno)
+          call codb_set_progress_bar("totalrows", 0)
+          call codb_progress_bar(0, trim(dtname), &
+          & 0, imaxpoolno, nrows_global, nrows_total, &
+          & zwall(2) - zwall(1), 0)
+          LLinform_progress = .TRUE.
+       endif
+    endif
+  endif
+
+  zwall(1) = util_walltime()
+  if (LLselect) then
+    iret = ODB_select(handle, dtname, nrows, ncols,&
+         & poolno=ipoolno, nra=nalloc,&
+         & setvars=setvars, values=values,&
+         & PEvar=PEvar, replicate_PE=replicate_PE, inform_progress=LLinform_progress)
+  else
+    iret = ODB_getsize(handle, dtname, nrows, ncols,&
+         & poolno=ipoolno, nra=nalloc)
+  endif
+
+  if (LLprtsummary) then
+    if (size(stat,dim=2) >= ncols) then
+      nrows = odb_statlen
+    else
+      nrows = 0
+    endif
+  endif
+
+  rc = nrows
+
+  if (LLprtsummary .and. nrows > 0) then
+    nalloc = ODB_lda(nrows)
+    allocate(d(nalloc, 0:ncols))
+    d(:,0) = 0 ! dummy; not used; only here for consistency
+    call ODB_makestat(d(:,1:),nrows,ncols,stat)
+    LLprtunderline = .TRUE.
+  else if (nrows > 0) then
+    istart = 1
+    if (present(start)) istart = max(1,start)
+    ilimit = nrows
+    if (present(limit)) ilimit = max(0,min(nrows,limit))
+    nalloc = ODB_lda(ilimit)
+
+    allocate(d(nalloc, 0:ncols))
+    nrows = ilimit
+    rc = ODB_get(handle, dtname, d, nrows, ncols=ncols, &
+         &       poolno=ipoolno, start=istart, limit=ilimit, inform_progress=LLinform_progress)
+    if (present(got)) got = nrows
+    if (present(llc_idx)) then
+      if (size(llc_idx) >= 2) then
+        icol = abs(llc_idx(1))
+        if (icol >= 1 .and. icol <= ncols) then
+          if (llc_idx(1) == -icol) then ! convert radians to degrees
+            do j=1,nrows
+              d(j,icol) = rad2deg(d(j,icol))
+            enddo
+          endif
+          if (present(latitude)) then
+            if (associated(latitude)) deallocate(latitude)
+            allocate(latitude(nrows))
+            latitude(1:nrows) = d(1:nrows,icol)
+          endif
+        endif
+        icol = abs(llc_idx(2))
+        if (icol >= 1 .and. icol <= ncols) then
+          if (llc_idx(2) == -icol) then ! convert radians to degrees
+            do j=1,nrows
+              d(j,icol) = rad2deg(d(j,icol))
+            enddo
+          endif
+          if (present(longitude)) then
+            if (associated(longitude)) deallocate(longitude)
+            allocate(longitude(nrows))
+            longitude(1:nrows) = d(1:nrows,icol)
+          endif
+        endif
+      endif
+      if (size(llc_idx) >= 3 .and. present(color)) then
+        icol = llc_idx(3)
+        if (icol >= 1 .and. icol <= ncols) then
+          if (associated(color)) deallocate(color)
+          allocate(color(nrows))
+          color(1:nrows) = d(1:nrows,icol)
+        endif
+      endif
+    endif ! if (present(llc_idx)) then
+    call ODB_collectstat(handle,dtname,d(:,1:),nrows,ncols,stat)
+  endif
+
+  if (LLcancel) then
+    iret = ODB_cancel(handle, dtname, poolno=ipoolno)
+  endif
+
+  nglb_rows(:) = 0
+  nglb_rows(ODBMP_myproc) = nrows
+  CALL ODBMP_global('SUM',nglb_rows)
+  nrows_global = sum(nglb_rows)
+  nrows_total = nrows_total + nrows_global
+  rc = nrows_global
+  zwall(2) = util_walltime()
+
+  if (ODBMP_myproc == 1.and.present(inform_progress)&
+     &.and.present(maxpoolno)) then
+    if (inform_progress .and. .not.LLstdout) then
+      imaxpoolno = maxpoolno
+      if (imaxpoolno <= 0) imaxpoolno = db(handle)%glbNpools
+      call codb_progress_bar(0, trim(dtname), &
+         & ipoolno, imaxpoolno, nrows_global, nrows_total, &
+         & zwall(2) - zwall(1), 0)
+    endif
+  endif
+
+!         write(0,*)'ODB_print<select('//trim(dtname)//'): PE#',
+!     $        ODBMP_myproc,':',nrows,':',ncols
+
+  if (ODBMP_myproc == 1.and.LLopen_file) then
+    imode = 0
+    if (LLappend_mode) imode = 1
+    CALL cODB_openprt(trim(CL_file), imode, iret)
+  endif
+
+  if (nrows_global <= 0) goto 100
+
+  if (allocated(itype) .and. allocated(inclen) .and. allocated(names)) goto 110
+
+  if (allocated(itype))  deallocate(itype)
+  if (allocated(inclen)) deallocate(inclen)
+  if (allocated(names))  deallocate(names)
+
+  allocate(itype(ilow:ncols))
+  allocate(inclen(ilow:ncols))
+  allocate(names(ilow:ncols))
+
+  allocate(types(ilow:ncols))
+  allocate(ftntypes(ilow:ncols))
+
+  CALL util_cgetenv('ODB_PRINT_FORMAT', 'STD', clprtfmt, iprtfmt_len)
+  call toupper(clprtfmt)
+  if (clprtfmt == 'XL' .or. clprtfmt == 'EXCEL') then
+    iprtfmt = 1 ! Microsoft Excel
+  else if (clprtfmt == 'SIMUL' .or. clprtfmt == 'SIMULOBS') then
+    iprtfmt = 2 ! Ready for simulated obs
+  else
+    iprtfmt = 0
+  endif
+
+  if (ODBMP_myproc == 1.and.LLopen_file) then
+    if (.not.is_table .and. iprtfmt /= 2) then
+      CALL cODB_sqlprint(handle, dtname, iret)
+    endif
+  endif
+
+  ilen = 1 ! Space for initial blank (or colon)
+  ilen = ilen + inilen ! from existence of stat --> odb_statcharlen, if present(stat) & size(stat) > 0
+  ilen = ilen + ncols ! Space for "ncols"-newlines (just if wrapcol = 1)
+  if (ilow == 0) then
+    itype(ilow) = pdbidx%id
+    if (is_table) then
+      names(ilow) = 'DB-index at T='//trim(dtname(2:))
+    else
+      names(ilow) = 'DB-index at V='//trim(dtname(1:))
+    endif
+    types(ilow) = 'long long int'
+    ftntypes(ilow) = 'INTEGER(8)'
+    inc = pdbidx%len
+    inc = max(inc-1,len_trim('DB-index'))
+    if (is_table) then
+      inc = max(inc,len_trim('@T='//trim(dtname(2:))))
+    else
+      inc = max(inc,len_trim('@V='//trim(dtname(1:))))
+    endif
+    inclen(ilow) = inc+1 ! +1 for delimiter
+    ilen = ilen + inc+1
+  endif
+
+  iret = ODB_getnames(handle, dtname,'name', names(1:ncols))
+  iret = ODB_getnames(handle, dtname,'type', types(1:ncols))
+  iret = ODB_getnames(handle, dtname,'ftntype', ftntypes(1:ncols))
+
+  do j=1,ncols
+    iat = scan(names(j),'@',back=.TRUE.)
+    if (iat > 0) then
+      inclen(j) = max(iat-1,len_trim(names(j)(iat:)))
+    else
+      inclen(j) = len_trim(names(j))
+    endif
+    if (ftntypes(j)(1:8) == 'INTEGER(' .and.&
+     &types(j)(1:8) == 'Bitfield' ) then
+      if (index(names(j),'.') == 0 .and. iprtfmt == 0) then
+        itype(j) = pbitf%id
+        inc = pbitf%len
+      else
+        itype(j) = puint%id
+        inc = puint%len
+      endif
+    else if (types(j)(1:8) == 'Bitfield' ) then ! A result of nickname fugding : x as "Bitfield:x at table"
+      itype(j) = pbitf%id
+      inc = pbitf%len
+    else if ( ftntypes(j)(1:7) == 'REAL(8)' .and.&
+     &types(j)(1:7) == 'string ') then
+      itype(j) = pstring%id
+      inc = pstring%len
+    else if (ftntypes(j)(1:5) == 'REAL(') then
+      itype(j) = preal%id
+      inc = preal%len
+    else if (ftntypes(j)(1:8) == 'INTEGER(' .and.(&
+     &types(j)(1:3) == 'hex'&
+     &.or. types(j)(1:4) == 'bufr'&
+     &.or. types(j)(1:4) == 'grib'&
+     &)) then
+      itype(j) = phex%id
+      inc = phex%len
+    else if (ftntypes(j)(1:8) == 'INTEGER(' .and.&
+     &types(j)(1:8) == 'yyyymmdd') then
+      itype(j) = pyyyymmdd%id
+      inc = pyyyymmdd%len
+    else if (ftntypes(j)(1:8) == 'INTEGER(' .and.&
+     &types(j)(1:8) == 'hhmmss') then
+      itype(j) = phhmmss%id
+      inc = phhmmss%len
+    else if (ftntypes(j)(1:8) == 'INTEGER(') then
+      itype(j) = pint%id
+      inc = pint%len
+    else
+      itype(j) = punknown%id
+      inc = punknown%len
+    endif
+    if (LLprtsummary .and. nrows > 0) itype(j) = pvarprec%id
+!    write(0,*)'LLprtsummary, nrows, j, itype(j), ilen=',LLprtsummary, nrows, j, itype(j), ilen
+!    write(0,*) inclen(j),inc-1,iat,j,', names(j)="'//names(j)//'"'
+    inc = max(inc-1,inclen(j))
+    inclen(j) = inc+1 ! +1 for delimiter
+    ilen = ilen + inc
+  enddo
+
+  ilen = max(3*len_trim(dtname),132,ilen)
+  ilen = ilen + mod(ilen+1,2)
+
+  deallocate(types)
+  deallocate(ftntypes)
+
+ 110  continue
+
+! Cache size: (for sizing dtmp(:,:) in prtdata)
+! ==========
+!
+! (ncols - ilow + 1) * ODB_SIZEOF_REAL8 * icache  < allowed_cache_size_in_bytes
+!
+! --> icache = max(1,allowed_cache_size_in_bytes/((ncols - ilow + 1) * ODB_SIZEOF_REAL8))
+!
+
+  icache = max(1,allowed_cache_size_in_bytes/((ncols - ilow + 1) * ODB_SIZEOF_REAL8))
+
+  if (ODBMP_myproc == 1) then
+    if (.not.present(replicate_PE)) then
+      pemin = 1
+      pemax = ODBMP_nproc
+    else
+      if (replicate_PE == -1) then
+        pemin = 1
+      else
+        pemin = replicate_PE
+      endif
+      pemax = pemin
+    endif
+    do pe=pemin,pemax
+      CALL prtdata(&
+       &handle, ipoolno, &
+       &dtname, pe, &
+       &trim(CL_file), itype, inclen, names, d, &
+       &ilow, nglb_rows(pe), ncols, ilen, inilen, &
+       &nglb_rows, zwall(2) - zwall(1),&
+       &iprtfmt, LLprthdr, LLprttimingstat, &
+       &LLprtsummary, LLprtunderline, istatlen, icache)
+    enddo
+  else
+    pe = 0
+    if (.not.present(replicate_PE)) then
+      pe = ODBMP_myproc
+    else
+      if (replicate_PE == ODBMP_myproc) then
+        pe = ODBMP_myproc
+      endif
+    endif
+    if (pe > 0) then
+      CALL prtdata(&
+       &handle, ipoolno, &
+       &dtname, pe,&
+       &trim(CL_file), itype, inclen, names, d, &
+       &ilow, nglb_rows(pe), ncols, ilen, inilen, &
+       &nglb_rows, zwall(2) - zwall(1),&
+       &iprtfmt, LLprthdr, LLprttimingstat, &
+       &LLprtsummary, LLprtunderline, istatlen, icache)
+    endif
+  endif
+
+ 100  continue
+  if (allocated(d)) deallocate(d)
+
+  if (LLclose_file) then
+    if (allocated(itype)) deallocate(itype)
+    if (allocated(inclen)) deallocate(inclen)
+    if (allocated(names)) deallocate(names)
+    ilen = 0
+  endif
+
+  if (ODBMP_myproc == 1) then
+    if (LLclose_file) then
+      CALL cODB_closeprt(iret)
+    else
+      CALL cODB_flushprt(iret)
+    endif
+  endif
+
+  if (.not.LLstdout .and. ODBMP_myproc == 1.and. .not.present(file)) then
+    call flush(0)
+    call flush(6)
+    call codb_system('cat '//trim(CL_file))
+    call util_remove_file(trim(CL_file), iret)
+  endif
+
+  CALL ODBMP_sync()
+endif
+
+CALL cODB_trace(handle, 0, 'ODB_print:'//dtname,idummy_arr, 0)
+IF (LHOOK) CALL DR_HOOK('ODBPRINT:ODB_PRINT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_print
+
+
+SUBROUTINE prtdata(&
+     &handle, poolno, &
+     &dtname, target,&
+     &filename, itype, kinc, names, d, &
+     &ilow, nrows, ncols, ilen, inilen, &
+     &nglb_rows, deltaw, iprtfmt, print_title, print_timingstat, &
+     &print_summary, print_underline, istatlen, ncache)
+implicit none
+INTEGER(KIND=JPIM), intent(in)          :: handle, nrows, ncols, ilow, inilen
+INTEGER(KIND=JPIM), intent(in)          :: ilen, poolno, iprtfmt, ncache
+INTEGER(KIND=JPIM), intent(in)          :: itype(ilow:), kinc(ilow:), target
+character(len=*), intent(in) :: dtname, filename, names(ilow:)
+REAL(KIND=JPRB), intent(in)             :: d(:,0:), deltaw
+INTEGER(KIND=JPIM), intent(in)          :: nglb_rows(:), istatlen
+logical, intent(in)                     :: print_title, print_timingstat, print_summary, print_underline
+
+character(len=maxvarlen) buf
+REAL(KIND=JPRB) :: dtmp(ilow:ncols, ncache), dd
+INTEGER(KIND=JPIM), parameter :: idata_col_def = 7 ! Bits == 111
+INTEGER(KIND=JPIM) :: idata_col
+INTEGER(KIND=JPIM), parameter :: rootPE = 1
+INTEGER(KIND=JPIM) :: i, j, jj, idot, iret, iexp, ipar, iat, itmp
+INTEGER(KIND=JPIM) :: jc, jsta, jend, recip
+INTEGER(KIND=JPIM) :: k, ib, ich, iline, j1, j2
+INTEGER(KIND=JPIM) :: idate, itime
+logical is_table, has_members, ok
+logical LLsend, LLrecv, LLfill, LLio
+character(len= 2) cdelim
+character(len= 6) cmyproc
+character(len= 8) cdate
+character(len=10) ctime
+character(len= 5) clabel
+character(len=20) crows, ccols, ctmp
+character(len=maxstrlen) cinfo
+character(len=*), parameter :: hash    = '#'
+character(len=*), parameter :: colon   = ':'
+character(len=*), parameter :: space   = ' '
+character(len=*), parameter :: comma   = ','
+character(len=*), parameter :: null    = char(0)
+character(len=*), parameter :: tab     = char(9)
+character(len=*), parameter :: newline = char(10)
+character(len=1) colon_char
+INTEGER(KIND=JPIM) :: icolon_len
+INTEGER(KIND=JPIM), parameter :: jpfirst = 6
+#if __GNUC__ == 5
+character(len=ilen) cline(jpfirst+nrows+1) ! workaround for regression in GNU 5.x (see ODB-231)
+#else
+character(len=ilen), allocatable :: cline(:)
+#endif
+INTEGER(KIND=JPIM) :: nlines, trace_info(6), len_statbuf, size_statbuf
+logical, allocatable :: LLskip_this(:)
+INTEGER(KIND=JPIM), parameter :: iprint_mdi_def = 1 ! print NULL=1 (def), print the value itself=0
+INTEGER(KIND=JPIM), parameter :: iprint_pdt_def = 0 ! pretty date/time=1, the usual=0 (def)
+INTEGER(KIND=JPIM) iprint_mdi, iprint_pdt, iprtimm, imod, ilim
+INTEGER(KIND=JPIM), allocatable :: poolnos(:), rownums(:)
+logical LLprint_mdi, LLprint_pdt, LLprint_imm
+REAL(KIND=JPRB) ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ODBPRINT:PRTDATA',0,ZHOOK_HANDLE)
+
+!--   (a) Only PE#1 does I/O
+!     (b) All other PEs send data to PE#1
+
+!      write(0,*)'prtdata('//trim(dtname)//') : PE#',
+!     $     ODBMP_myproc,':',target
+
+if (LHOOK .and. ODBMP_myproc /= rootPE .and. ODBMP_myproc /= target) &
+      & CALL DR_HOOK('ODBPRINT:PRTDATA',1,ZHOOK_HANDLE)
+if (            ODBMP_myproc /= rootPE .and. ODBMP_myproc /= target) return
+
+if (db_trace) then
+  trace_info(:) = (/target, ilow, nrows, ncols, ilen, 0/)
+  CALL cODB_trace(handle, 1,'prtdata:'//filename, &
+                  trace_info, size(trace_info))
+endif
+
+LLio = (ODBMP_myproc == rootPE)
+
+if (target == rootPE .and. LLio) then
+  LLsend = .FALSE.
+  LLrecv = .FALSE.
+  LLfill = .TRUE.
+else if (target == ODBMP_myproc) then
+  LLsend = .TRUE.
+  LLrecv = .FALSE.
+  LLfill = .TRUE.
+else
+  LLsend = .FALSE.
+  LLrecv = .TRUE.
+  LLfill = .FALSE.
+endif
+
+if (LLio) then
+  recip = target
+else
+  recip = -rootPE
+endif
+
+iprtimm = 0
+if (ODBMP_nproc == 1) iprtimm = 1
+LLprint_imm = (iprtimm == 1)
+
+#if __GNUC__ != 5
+if (LLprint_imm) then
+  allocate(cline(jpfirst+1))
+else
+  allocate(cline(jpfirst+nrows+1))
+endif
+#endif
+
+if (.not. LLfill) goto 9999
+
+len_statbuf = 0
+size_statbuf = istatlen
+if (size_statbuf > 0) len_statbuf = min(inilen,odb_statcharlen)
+if (len_statbuf <= 0) size_statbuf = 0 ! disabled again
+!  write(0,*)'statbuf: size_statbuf, len_statbuf=',size_statbuf, len_statbuf
+!  write(0,*)'odb_statbuf(:)='
+!  do i=1,size_statbuf
+!    write(0,*) i, '"'//odb_statbuf(i)//'"'
+!  enddo
+
+!write(cmyproc,'(i6)') ODBMP_myproc
+write(cmyproc,'(i6)') poolno
+cmyproc = trim(sadjustl(cmyproc))
+!CALL DATE_AND_TIME(cdate, ctime)
+CALL cODB_datetime(idate, itime)
+cdate= ' '
+write(cdate(1:8),'(i8.8)') idate
+ctime=' '
+write(ctime(1:6),'(i6.6)') itime
+
+is_table = (dtname(1:1) == '@')
+clabel = 'VIEW'
+if (is_table) clabel = 'TABLE'
+
+write(crows,'(i20)') nrows
+write(ccols,'(i20)') ncols
+
+CALL util_cgetenv('ODB_PRINT_COLON', colon, colon_char, icolon_len)
+
+if (iprtfmt == 2) then ! simulated obs
+  iline=1
+  write(cline(iline),'(a)') &
+      & '#'//trimadjL(dtname)//newline//&
+      & '#/nrows='//trimadjL(crows)//newline//&
+      & '#/ncols='//trimadjL(ccols)
+  iline=2
+  write(ctmp,'(i20)') ilen
+  write(cline(iline),'(a)') &
+      & '#/poolno='//trimadjL(cmyproc)//newline//&
+      & '#/width='//trimadjL(ctmp)//newline//&
+      & '#/end'
+else
+  iline = 1
+  write(cline(iline),'(a)')&
+       &colon_char//space//trim(clabel)//'="'//&
+       &trimadjL(dtname)//&
+       &'" on '//trim(cdate)//' at '//trim(ctime(1:6))
+
+  iline = 2
+  write(cline(iline),'(a)')&
+       &colon_char//' Pool#'//trim(cmyproc)//': no. of rows x cols = '//&
+       &trimadjL(crows)//&
+       &' x '//&
+       &trimadjL(ccols)
+endif
+
+has_members = .FALSE.
+
+if (ilow == 0) then
+  jsta = 1
+  jend = ncols + 1
+  if (nrows > 0) then
+    allocate(poolnos(nrows))
+    iret = odb_control_word_info(d(:,0),poolnos=poolnos) ! testing the vector-version
+    allocate(rownums(nrows))
+    iret = odb_control_word_info(d,rownums=rownums) ! this is the matrix-version
+  endif
+else
+  jsta = 1
+  jend = ncols
+endif
+
+CALL util_igetenv('ODB_PRINT_DATA_COL', idata_col_def, idata_col)
+allocate(LLskip_this(jsta:jend))
+LLskip_this(jsta:jend) = .FALSE.
+
+CALL util_igetenv('ODB_PRINT_MDI', iprint_mdi_def , iprint_mdi)
+LLprint_mdi = (iprint_mdi /= 0)
+
+CALL util_igetenv('ODB_PRINT_PRETTY_DATE_TIME', iprint_pdt_def , iprint_pdt)
+LLprint_pdt = (iprint_pdt /= 0)
+
+!--   Print variable names (w/o member names, though)
+iline = 3
+if (iprtfmt == 2) then ! simulated obs
+  cline(iline) = space
+else
+  cline(iline) = colon_char
+endif
+k = 1 + inilen
+do jc=jsta,jend
+  j = jc
+  if (jc > ncols) j = ilow
+  if (itype(j) == pbitf%id) then
+    if (IAND(idata_col,8) /= 8) then ! Check for 4th bit = 1 ?
+      LLskip_this(jc) = .TRUE.
+      cycle
+    endif
+  endif
+  buf = trimadjL(names(j))
+  iat = scan(buf,'@',back=.TRUE.)
+  if (iat > 0) buf(iat:) = space
+  if (buf(1:11) == 'LINKOFFSET(') then
+    if (IAND(idata_col,4) /= 4) then ! Check for 3rd bit = 1 ?
+      LLskip_this(jc) = .TRUE.
+      cycle
+    endif
+    buf(1:11) = space
+    ipar = index(buf,')')
+    if (ipar > 0) buf(ipar:) = space
+    buf = trimadjL(buf)//'.offset'
+  else if (buf(1:8) == 'LINKLEN(') then
+    if (IAND(idata_col,2) /= 2) then ! Check for 2nd bit = 1 ?
+      LLskip_this(jc) = .TRUE.
+      cycle
+    endif
+    buf(1:8) = space
+    ipar = index(buf,')')
+    if (ipar > 0) buf(ipar:) = space
+    buf = trimadjL(buf)//'.len'
+  endif
+  if (IAND(idata_col,1) /= 1) then ! Check for 1st bit = 1 ?
+    LLskip_this(jc) = .TRUE.
+    cycle
+  endif
+  cline(iline)(k+1:k+kinc(j)) = space//trim(buf)
+  cline(iline)(k+1:k+kinc(j)) = sadjustr(cline(iline)(k+1:k+kinc(j)))
+  k = k + kinc(j)
+enddo
+
+iline = 4
+if (has_members) then
+!--   Bitfield members present ==> print member names
+  cline(iline) = colon_char
+  k = 1 + inilen
+  do jc=jsta,jend
+    if (LLskip_this(jc)) cycle
+    j = jc
+    if (jc > ncols) j = ilow
+    if (itype(j) == puint%id) then
+      buf = trimadjL(names(j))
+      idot = index(buf,'.')
+      if (idot > 0) then
+        buf(:idot) = space
+        buf = '.'//trimadjL(buf)
+        iat = scan(buf,'@',back=.TRUE.)
+        if (iat > 0) buf(iat:) = space
+      else
+        buf = space
+      endif
+    else
+      buf = space
+    endif
+    cline(iline)(k+1:k+kinc(j)) = space//trim(buf)
+    cline(iline)(k+1:k+kinc(j)) = sadjustr(cline(iline)(k+1:k+kinc(j)))
+    k = k + kinc(j)
+  enddo
+else
+  cline(iline) = null ! ==> This line will not be printed at all
+endif
+
+!--   Print TABLE names the variables belong to
+iline = 5
+cline(iline) = colon_char
+k = 1 + inilen
+do jc=jsta,jend
+  if (LLskip_this(jc)) cycle
+  j = jc
+  if (jc > ncols) j = ilow
+  buf = trimadjL(names(j))
+  iat = scan(buf,'@',back=.TRUE.)
+  if (iat > 0) then
+    buf(:iat) = space
+    buf = '@'//trimadjL(buf)
+  endif
+  cline(iline)(k+1:k+kinc(j)) = space//trim(buf)
+  cline(iline)(k+1:k+kinc(j)) = sadjustr(cline(iline)(k+1:k+kinc(j)))
+  k = k + kinc(j)
+enddo
+
+if (iprtfmt == 2) then ! simulated obs
+  cline(iline) = null ! ==> This line will not be printed at all
+endif
+
+!--   Handle underline
+iline = 6
+cline(iline) = cline(iline-1)
+do j=2,ilen
+  if (cline(iline)(j:j) /= space) cline(iline)(j:j) = '='
+enddo
+
+if (LLio .and. (print_title .or. print_underline)) then
+  if (print_title) then
+    if (target == rootPE .and. iprtfmt == 0) then
+      write(ccols,'(i20)') count(.not.LLskip_this(:))
+      write(ctmp,'(i20)') size(nglb_rows)
+      cinfo = colon_char//space//trimadjL(ccols)//space//trimadjL(ctmp)
+      do j=1,size(nglb_rows)
+        write(ctmp,'(i20)') nglb_rows(j)
+        cinfo = trimadjL(cinfo)//space//trimadjL(ctmp)
+      enddo
+      CALL cODB_lineprt(trim(cinfo)//newline, iret)
+    endif
+    j1 = 1
+    j2 = jpfirst
+  else if (print_underline) then
+    j1 = jpfirst
+    j2 = j1
+  endif
+  nlines = 0
+  do iline=j1,j2
+    if (cline(iline)(1:1) /= null) then
+      CALL cODB_lineprt(trim(cline(iline))//newline, iret)
+      nlines = nlines + 1
+    endif
+  enddo
+endif
+
+do i=1,nrows
+  imod = mod(i-1,ncache) + 1
+  if (imod == 1) then
+     ilim = min(ncache,nrows-i+1)
+     do j=ilow,ncols
+        do k=1,ilim
+           dtmp(j,k) = d(i+k-1,j)
+        enddo
+     enddo
+  endif
+
+  if (LLprint_imm) then
+    iline = jpfirst + 1
+  else
+    iline = jpfirst + i
+  endif
+
+  k = 1 + inilen
+  cline(iline)(1:k) = space
+  if (size_statbuf > 0 .and. i <= size_statbuf) then
+    cline(iline)(1:k) = colon_char//odb_statbuf(i)(1:len_statbuf)
+!    write(0,*) i,iline,k,'"'//cline(iline)(1:k)//'"'
+  endif
+  if (LLprint_imm) CALL cODB_lineprt(cline(iline)(1:k), iret)
+
+!  if (iprtfmt == 0) then
+!    cdelim = space//null
+!  else
+    cdelim = null
+!  endif
+  do jc=jsta,jend
+    if (LLskip_this(jc)) cycle
+    j = jc
+    if (jc > ncols) j = ilow
+    dd = dtmp(j,imod)
+    if (itype(j) == pdbidx%id) then
+      CALL cODB_fill_ctrlw(iprtimm,cdelim,pdbidx%cfmt,poolnos(i),rownums(i),cline(iline)(k+1:k+kinc(j)),iret)
+    else if (itype(j) == pint%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+        CALL cODB_fill_NULL(iprtimm,cdelim,pint%len,cline(iline)(k+1:k+kinc(j)),iret)
+      else
+        CALL cODB_fill_longlongint(iprtimm,cdelim,pint%cfmt,dd,cline(iline)(k+1:k+kinc(j)),iret)
+      endif
+    else if (itype(j) == puint%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+        CALL cODB_fill_NULL(iprtimm,cdelim,puint%len,cline(iline)(k+1:k+kinc(j)),iret)
+      else
+        CALL cODB_fill_ulonglongint(iprtimm,cdelim,puint%cfmt,dd,cline(iline)(k+1:k+kinc(j)),iret)
+      endif
+    else if (itype(j) == preal%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+        CALL cODB_fill_NULL(iprtimm,cdelim,preal%len,cline(iline)(k+1:k+kinc(j)),iret)
+      else
+        CALL cODB_fill_dble(iprtimm,cdelim,preal%cfmt,dd,cline(iline)(k+1:k+kinc(j)),iret)
+      endif
+    else if (itype(j) == pvarprec%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+        CALL cODB_fill_NULL(iprtimm,cdelim,kinc(j),cline(iline)(k+1:k+kinc(j)),iret)
+      else
+        CALL cODB_fill_varprec(iprtimm,cdelim,pvarprec%cfmt,dd,cline(iline)(k+1:k+kinc(j)),iret)
+      endif
+    else if (itype(j) == pstring%id) then
+      CALL cODB_fill_string(iprtimm,cdelim,pstring%cfmt,dd,cline(iline)(k+1:k+kinc(j)),iret)
+    else if (itype(j) == pbitf%id) then
+      CALL cODB_d2u(dd, itmp)
+      CALL cODB_fill_bitfield(iprtimm,cdelim,pbitf%len,itmp,cline(iline)(k+1:k+kinc(j)),iret)
+    else if (itype(j) == phex%id) then
+      CALL cODB_d2u(dd, itmp)
+      CALL cODB_fill_truehex(iprtimm,cdelim,phex%cfmt,itmp,cline(iline)(k+1:k+kinc(j)),iret)
+    else if (itype(j) == pyyyymmdd%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+         CALL cODB_fill_NULL(iprtimm,cdelim,pyyyymmdd%len,cline(iline)(k+1:k+kinc(j)),iret)
+      else
+         itmp = int(dd)
+         if (LLprint_pdt) then
+           CALL cODB_fill_yyyymmdd(iprtimm,cdelim,pyyyymmdd_pdt%cfmt,itmp,&
+                & cline(iline)(k+1:k+kinc(j)),iret)
+         else
+           CALL cODB_fill_trueint(iprtimm,cdelim,pyyyymmdd%cfmt,itmp,cline(iline)(k+1:k+kinc(j)),iret)
+         endif
+      endif
+    else if (itype(j) == phhmmss%id) then
+      if (LLprint_mdi .and. abs(dd) == ODB_NMDI) then
+         CALL cODB_fill_NULL(iprtimm,cdelim,phhmmss%len,cline(iline)(k+1:k+kinc(j)),iret)
+      else
+         itmp = int(dd)
+         if (LLprint_pdt) then
+           CALL cODB_fill_hhmmss(iprtimm,cdelim,phhmmss_pdt%cfmt,itmp,&
+                & cline(iline)(k+1:k+kinc(j)),iret)
+         else
+           CALL cODB_fill_trueint(iprtimm,cdelim,phhmmss%cfmt,itmp,cline(iline)(k+1:k+kinc(j)),iret)
+         endif
+      endif
+    else
+       CALL cODB_fill_UNKNOWN(iprtimm,cdelim,punknown%len,cline(iline)(k+1:k+kinc(j)),iret)
+    endif
+
+    k = k + kinc(j)
+    if (jc < jend .and. mod(jc,wrapcol) == 0) then
+      if (LLprint_imm) then
+         CALL cODB_lineprt(newline, iret)
+      else
+         cline(iline)(k+1:k+1) = newline
+      endif
+      k = k + 1
+    endif
+    if (iprtfmt == 1) then ! Microsoft Excel
+      cdelim = tab//null
+    endif
+  enddo ! do jc=jsta,jend
+  if (LLprint_imm) CALL cODB_lineprt(newline, iret)
+enddo ! do i=1,nrows
+
+if (print_timingstat) then
+!-- The last line
+  iline = size(cline)
+  if (iprtfmt == 2) then
+    cline(iline) = space
+  else
+    write(cline(iline),'(a,i12,a,f7.3,a)')&
+       &colon_char//space//trim(clabel)//'="'//&
+       &trimadjL(dtname)//&
+       &'" : ',nrows,' row(s) in ',deltaw,' secs (pool#'//trim(cmyproc)//')'
+  endif
+  if (LLprint_imm) CALL cODB_lineprt(trim(cline(iline))//newline, iret)
+endif
+
+9999 continue
+
+if (ODBMP_testready(recip)) then
+  if (LLsend) then
+    iret = ODB_distribute(cline, rootPE)
+  else if (LLrecv) then
+    iret = ODB_distribute(cline, -target)
+  endif
+endif
+
+if (LLio .and. .not.LLprint_imm) then
+  do iline=jpfirst+1,size(cline)
+    if (cline(iline)(1:1) /= null) then
+      CALL cODB_lineprt(trim(cline(iline))//newline, iret)
+      nlines = nlines + 1
+    endif
+  enddo
+endif
+
+if (allocated(LLskip_this)) deallocate(LLskip_this)
+#if __GNUC__ != 5
+if (allocated(cline)) deallocate(cline)
+#endif
+if (allocated(poolnos)) deallocate(poolnos)
+if (allocated(rownums)) deallocate(rownums)
+
+if (db_trace) then
+  trace_info(:) = (/target, ilow, nrows, ncols, ilen, nlines/)
+  CALL cODB_trace(handle, 0,'prtdata:'//filename, &
+                  trace_info, size(trace_info))
+endif
+IF (LHOOK) CALL DR_HOOK('ODBPRINT:PRTDATA',1,ZHOOK_HANDLE)
+END SUBROUTINE prtdata
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odbprint
diff --git a/odb/src/module/odbshared.F90 b/odb/src/module/odbshared.F90
new file mode 100644
index 0000000..4c8d018
--- /dev/null
+++ b/odb/src/module/odbshared.F90
@@ -0,0 +1,678 @@
+MODULE odbshared
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE odbmp ! The message passing module
+USE str, only : toupper, tolower, sadjustl, sadjustr
+USE odbsort, only : keysort
+
+IMPLICIT NONE
+SAVE
+PUBLIC
+
+INTERFACE ODB_map_vpools
+MODULE PROCEDURE & 
+  & ODB_map_vpools_direct, &
+  & ODB_map_vpools_fromfile
+END INTERFACE
+
+#ifndef USE_CTRIM
+#define ctrim(x) x
+#define CTRIM(x) x
+#endif
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+TYPE prt_t
+SEQUENCE
+INTEGER(KIND=JPIM) :: id
+INTEGER(KIND=JPIM) :: len
+character(len=40) :: fmt
+character(len=40) :: cfmt
+END TYPE prt_t
+
+INTEGER(KIND=JPIM), parameter :: ODB_MAXBITS = 32
+INTEGER(KIND=JPIM), parameter :: ODB_MAXROWS = 2147483647
+INTEGER(KIND=JPIM), parameter :: ODB_SIZEOF_INT   = 4
+INTEGER(KIND=JPIM), parameter :: ODB_SIZEOF_REAL4 = 4
+INTEGER(KIND=JPIM), parameter :: ODB_SIZEOF_REAL8 = 8
+
+TYPE(prt_t)&
+     &pint, puint, preal, pstring, &
+     &pbitf, &! (ODB_MAXBITS), 
+     &punknown, phex,&
+     &pyyyymmdd, phhmmss, &
+     &pyyyymmdd_pdt, phhmmss_pdt, &
+     &pdbidx, &
+     &plinkoffset_t, plinklen_t, pvarprec
+
+INTEGER(KIND=JPIM), parameter :: flag_update = 1
+INTEGER(KIND=JPIM), parameter :: flag_pack   = 2
+INTEGER(KIND=JPIM), parameter :: flag_get    = flag_update
+INTEGER(KIND=JPIM), parameter :: flag_put    = flag_update
+INTEGER(KIND=JPIM), parameter :: def_flag    = flag_update ! i.e. GET all, PUT all cols
+INTEGER(KIND=JPIM), parameter :: flag_free   = 4
+
+!-- Maximum number of characters in a Fortran90 string (i.e. character(len=maxstrlen))
+INTEGER(KIND=JPIM), parameter :: maxstrlen = 32767 ! 65536
+
+INTEGER(KIND=JPIM), parameter :: maxvarlen = 512
+INTEGER(KIND=JPIM), parameter :: maxfilen  = 512
+INTEGER(KIND=JPIM), parameter :: dbnamelen = 80
+REAL(KIND=JPRB),    parameter :: rmaxint = 2147483647.0_JPRB
+
+!-- Note: UNDEFDB brought over from /cc/rd/ifs/module/yomdb.F90 on 20-Mar-2002 by SS
+#ifdef RS6K
+!-- in the following if 0x7FF7FFFF is used as 4-byte initialization string, would enable better
+!   error detection for automatic arrays
+!   Use also -qinitauto=7FF7FFFF (Fortran)
+INTEGER(KIND=JPIM), parameter :: UNDEFDB =  2146959359 ! "ODB_UNDEF" ; the same as 0x7FF7FFFF
+#else
+!-- in the following if 0x8B8B8B8B used as an index value on FUJITSU, it triggers SIGBUS error
+INTEGER(KIND=JPIM), parameter :: UNDEFDB = -1953789045 ! "ODB_UNDEF" ; the same as 0x8B8B8B8B
+#endif
+INTEGER(KIND=JPIM) :: UNDEFDB_actual = UNDEFDB
+
+INTEGER(KIND=JPIM), parameter :: ODB_NMDI =  2147483647
+REAL(KIND=JPRB),    parameter :: ODB_RMDI = -2147483647.0_JPRB
+
+INTEGER(KIND=JPIM), parameter :: ODB_HDR_ALIGNED = 1
+INTEGER(KIND=JPIM), parameter :: ODB_BODY_ALIGNED = 2
+
+!--   Newline after certain no. of columns (in prtdata)
+INTEGER(KIND=JPIM), parameter :: def_wrapcol = 2147483647
+INTEGER(KIND=JPIM)            ::     wrapcol = def_wrapcol
+
+!--   Show database index
+INTEGER(KIND=JPIM), parameter :: def_showdbidx = 0
+INTEGER(KIND=JPIM)            ::     showdbidx = 0
+
+!--   I/O locking
+INTEGER(KIND=JPIM), parameter :: def_haveiolock = 0
+INTEGER(KIND=JPIM)            ::     haveiolock = 0
+
+!--   Max no. of simultaneously open DBs
+INTEGER(KIND=JPIM), parameter :: def_maxhandle = 10
+INTEGER(KIND=JPIM)            :: maxhandle = 0
+
+!--   Determine the leading dimension calculation method
+#if defined(VPP) || defined(NECSX)
+!-- Vector machines
+INTEGER(KIND=JPIM), parameter :: def_lda_method = 0 ! i.e. ld = n + mod(n+1,2)
+#else
+!-- Scalar machines (most/all of them aren't keen to have power-of-two leading dimension)
+INTEGER(KIND=JPIM), parameter :: def_lda_method = 2 ! i.e. ld = n, but not power of 2 (which case n+1)
+#endif
+!INTEGER(KIND=JPIM)            :: lda_method = def_lda_method 
+INTEGER(KIND=JPIM)            :: lda_method = 1 ! By default do *not* add +1 (SS/26-Feb-2014)
+
+!-- Used in odb_*array_dump()-routines
+INTEGER(KIND=JPIM)            :: max_dump_count = 100 ! Redefine via env. ODB_ARRAY_MAX_DUMP_COUNT
+INTEGER(KIND=JPIM)            ::     dump_count = 0
+
+!-- Default I/O-method
+INTEGER(KIND=JPIM)            :: def_io_method = 1
+
+!-- Default OpenMP I/O choice (0=off, 1=on)
+INTEGER(KIND=JPIM)            :: def_io_openmp = 0
+
+TYPE db_t
+logical :: inuse
+logical :: newdb
+logical :: altered
+logical :: readonly
+logical :: rewrite_flags
+INTEGER(KIND=JPIM) :: io_method
+INTEGER(KIND=JPIM) :: glbNpools
+! glbMaxpoolno: if NOT readonly, then == glbNpools
+!               otherwise up to glbNpools before (the first) ODB_addpools()
+INTEGER(KIND=JPIM) :: glbMaxpoolno
+INTEGER(KIND=JPIM) :: locNpools
+INTEGER(KIND=JPIM) :: iounit
+INTEGER(KIND=JPIM) :: ntables
+INTEGER(KIND=JPIM) :: naid  ! 0 or 5 for io_method=4
+INTEGER(KIND=JPIM) :: nfileblocks ! ... of nested iomap-files
+INTEGER(KIND=JPIM) :: CreationDT(0:1)
+INTEGER(KIND=JPIM) :: AnalysisDT(0:1)
+REAL(KIND=JPRB) :: Version_Major, Version_Minor
+character(len=dbnamelen) :: name
+INTEGER(KIND=JPIM), pointer :: poolidx(:)
+INTEGER(KIND=JPIM), pointer :: ioaid(:,:,:) ! glbNpools x ntables x naid
+INTEGER(KIND=JPIM), pointer :: grpsize(:)   ! IO_GRPSIZE per each ciomap-file ; maxsize <= glbNpools
+character(len=maxvarlen), pointer :: ctables(:) ! cached tablenames; size=ntables
+character(len=maxfilen) , pointer :: ciomap(:) ! Aux. FBLOCK I/O-map files; maxsize <= glbNpools
+REAL(KIND=JPRB), pointer :: io_volume(:)  ! used with IO_OPENMP=1 upon write; size=ntables
+INTEGER(KIND=JPIM) :: nvmap ! 0 = no mapping, >0 : mapping active, <0 : mapping [temporarely] passive
+INTEGER(KIND=JPIM), pointer :: vpoolmap(:) ! Virtual pool map vpoolmap(poolno) --> virtual poolno
+INTEGER(KIND=JPIM), pointer :: vpoolmap_idx(:) ! Indexing to make ODB_vpool2pool() fast
+END TYPE db_t
+
+TYPE(db_t), allocatable :: db(:)
+logical :: db_initialized = .FALSE.
+logical :: db_trace = .FALSE.
+
+CONTAINS
+
+
+#ifdef USE_CTRIM
+FUNCTION ctrim(c) result(s)
+character(len=*), intent(in) :: c
+character(len=len_trim(c)+1) s
+s = c(1:len(s)-1)//char(0)
+END FUNCTION ctrim
+#endif
+
+
+FUNCTION ODB_lda(n, method) RESULT(lda)
+!-- Leading dimension
+INTEGER(KIND=JPIM), intent(in) :: n
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: method
+INTEGER(KIND=JPIM) :: lda, m, use_method, iarg
+logical :: isPowerOfTwo
+isPowerOfTwo(iarg) = (IAND(iarg,-iarg) == iarg)
+
+m = max(1,n) ! make sure at least one row gets allo-gated
+
+if (present(method)) then
+  use_method = method
+else
+  use_method = lda_method
+endif
+
+if (use_method == 0) then
+  lda = m + mod(m+1,2)
+else if (use_method == 1) then
+  lda = m
+else if (use_method == 2) then
+!-- the same as #1, but also checks that m is not a power of 2 
+!   i.e. 2**int_x, int_x = [1..31] ; otherwise bad on some RISC-machines
+!  if (ANY(m == (/2,4,8,16,32,64,128,256,512,&
+!          &1024,2048,4096,8192,16384,32768,65536,131072,262144,&
+!          &524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,&
+!          &134217728,268435456,536870912,1073741824/))) m = m + 1
+!-- Hey, the following is much better (09/03/2005 by SS) !!
+  if (isPowerOfTwo(m)) m = m + 1
+  lda = m
+else
+  lda = m
+endif
+END FUNCTION ODB_lda
+
+
+SUBROUTINE ODB_abort(routine, s, code, really_abort)
+implicit none
+character(len=*), intent(in) :: routine
+character(len=*), intent(in), optional :: s
+INTEGER(KIND=JPIM),        intent(in), optional :: code
+logical,          intent(in), optional :: really_abort
+CALL ODBMP_abort(routine, s, code, really_abort)
+END SUBROUTINE ODB_abort
+
+
+SUBROUTINE dummy_load(func, cond)
+implicit none
+external func
+logical, optional :: cond
+if (present(cond)) then
+  if (cond) call func()
+endif
+END SUBROUTINE dummy_load
+
+
+FUNCTION free_iounit() RESULT(kunit)
+implicit none
+INTEGER(KIND=JPIM) :: j, kunit
+logical LLopened
+kunit = -1
+do j=99, 0, -1
+  INQUIRE(unit=j, opened=LLopened)
+  if (.not.LLopened) then
+    kunit = j
+    return
+  endif
+enddo
+END FUNCTION free_iounit
+
+
+FUNCTION odbHcheck(handle, routine, abort) RESULT(okay)
+implicit none
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: routine
+logical, intent(in), optional :: abort
+logical okay
+okay = (handle > 0 .and. handle <= maxhandle)
+if (.not.okay) then
+  CALL ODB_abort(routine,&
+       & 'Invalid handle. Hint: Increase max. no. of open handles via export ODB_MAXHANDLE=value',&
+       & handle,abort)
+endif
+END FUNCTION odbHcheck
+
+
+FUNCTION ODB_get_vpools(handle, poolnos) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM), intent(out), optional :: poolnos(:)
+INTEGER(KIND=JPIM) :: rc, n, npools
+rc = 0
+if (odbHcheck(handle,'ODB_get_vpools')) then
+  npools = db(handle)%glbNpools ! Can't be larger than this
+  n = abs(db(handle)%nvmap)
+  rc = -n
+  if (n > 0 .and. associated(db(handle)%vpoolmap)) then
+     if (present(poolnos)) then
+        if (size(poolnos) >= npools) then
+           poolnos(1:npools) = db(handle)%vpoolmap(1:npools)
+           rc = npools
+        endif
+     endif
+  endif
+endif
+END FUNCTION ODB_get_vpools
+
+
+FUNCTION ODB_unmap_vpools(handle) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM) :: rc
+rc = 0
+if (odbHcheck(handle,'ODB_unmap_vpools')) then
+  if (associated(db(handle)%vpoolmap)) then
+    deallocate(db(handle)%vpoolmap)
+    nullify(db(handle)%vpoolmap)
+  endif
+  if (associated(db(handle)%vpoolmap_idx)) then
+    deallocate(db(handle)%vpoolmap_idx)
+    nullify(db(handle)%vpoolmap_idx)
+  endif
+  db(handle)%nvmap = 0
+endif
+END FUNCTION ODB_unmap_vpools
+
+
+FUNCTION ODB_map_vpools_direct(handle, poolnos, verbose) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM), intent(in) :: poolnos(:)
+logical, intent(in), optional :: verbose
+logical :: LLverbose
+INTEGER(KIND=JPIM) :: j, rc, npools, iret
+LLverbose = .FALSE.
+if (present(verbose)) LLverbose = verbose
+rc = 0
+if (odbHcheck(handle,'ODB_map_vpools_direct')) then
+  rc = ODB_unmap_vpools(handle)
+  rc = size(poolnos)
+  npools = db(handle)%glbNpools
+  if (rc >= npools) then
+    allocate(db(handle)%vpoolmap(npools))
+    db(handle)%vpoolmap(1:npools) = poolnos(1:npools)
+    if (LLverbose) then
+      write(0,'(1x,a,i10)') 'ODB_map_vpools: Poolno ==> Virtual pool mapping : npools = ',npools
+      do j=1,npools
+        write(0,'(1x,i12," ==> ",i12)') j,db(handle)%vpoolmap(j)
+      enddo
+    endif
+    allocate(db(handle)%vpoolmap_idx(npools))
+    CALL keysort(iret, db(handle)%vpoolmap, npools, &
+         & descending=.TRUE., index=db(handle)%vpoolmap_idx, init=.TRUE.)
+    db(handle)%nvmap = npools
+    rc = npools
+  else
+    rc = -npools
+  endif
+endif
+END FUNCTION ODB_map_vpools_direct
+
+
+FUNCTION ODB_map_vpools_fromfile(handle, file, verbose) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+character(len=*), intent(in)   :: file
+logical, intent(in), optional  :: verbose
+logical :: LLverbose
+INTEGER(KIND=JPIM) :: rc, npools, j, poolno, vpoolno, k
+INTEGER(KIND=JPIM), allocatable :: poolnos(:)
+INTEGER(KIND=JPIM), parameter :: iu = 45
+rc = 0
+LLverbose = .FALSE.
+if (present(verbose)) LLverbose = verbose
+if (odbHcheck(handle,'ODB_map_fromfile')) then
+  rc = ODB_unmap_vpools(handle)
+  rc = 0
+  open(unit=iu,file=file,status='old',err=99)
+  npools = db(handle)%glbNpools ! Can't be larger than this
+  allocate(poolnos(npools))
+  poolnos(:) = -abs(ODB_NMDI)
+  k = 0
+  do j=1,npools
+    read(iu,*,end=98,err=98) poolno, vpoolno
+    if (poolno >= 1 .and. poolno <= npools) then
+      poolnos(poolno) = vpoolno
+      k = k + 1
+    endif
+  enddo
+98 continue
+  close(iu)
+  if (k > 0) then
+    rc = ODB_map_vpools_direct(handle, poolnos, verbose=verbose)
+  endif
+  if (allocated(poolnos)) deallocate(poolnos)
+99 continue
+endif
+END FUNCTION ODB_map_vpools_fromfile
+
+
+FUNCTION ODB_toggle_vpools(handle, toggle) RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM), intent(in), optional :: toggle
+INTEGER(KIND=JPIM) :: rc, itoggle
+rc = 0
+if (odbHcheck(handle,'ODB_toggle_vpools')) then
+  rc = db(handle)%nvmap ! save the old value
+  if (present(toggle)) then
+    itoggle = toggle
+  else ! reverse the previous on/off status to off/on (unless nvmap == 0)
+    if (rc > 0) then
+      itoggle = -1 ! switch from ON to OFF 
+    else
+      itoggle = +1 ! switch from OFF to ON
+    endif
+  endif
+  if (itoggle > 0) then ! turn ON
+    db(handle)%nvmap = +abs(db(handle)%nvmap)
+  else                  ! turn OFF
+    db(handle)%nvmap = -abs(db(handle)%nvmap)
+  endif  
+endif
+END FUNCTION ODB_toggle_vpools
+
+
+FUNCTION ODB_pool2vpool(handle, poolno) RESULT(rc)
+! Given true pool number [1..npools], returns virtual i.e. user/mapped pool number
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM), intent(in) :: poolno ! true pool number
+INTEGER(KIND=JPIM) :: rc, n, npools
+rc = poolno ! The ultimate default : i.e. no mapping
+if (odbHcheck(handle,'ODB_pool2vpool')) then
+  n = db(handle)%nvmap
+  if (n > 0 .and. associated(db(handle)%vpoolmap)) then ! I.e. mapping exists
+    if (poolno >= 1 .and. poolno <= npools) then
+       rc = db(handle)%vpoolmap(poolno) ! The user/mapped pool numbe
+    else
+       ! By default: Mapping exists, but poolno not mapped (usually due to user error)
+       rc = -abs(ODB_NMDI)
+    endif
+  endif
+endif
+END FUNCTION ODB_pool2vpool
+
+
+FUNCTION ODB_vpool2pool(handle, vpoolno) RESULT(rc)
+! Given virtual i.e. user/mapped pool number, returns true pool number [1..npools]
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle
+INTEGER(KIND=JPIM), intent(in) :: vpoolno ! virtual i.e. user/mapped pool number
+INTEGER(KIND=JPIM) :: rc, n, npools, j, k
+rc = vpoolno ! By default : no mapping i.e. assume vpoolno == poolno
+if (odbHcheck(handle,'ODB_vpool2pool')) then
+  n = db(handle)%nvmap
+  if (n > 0 .and. associated(db(handle)%vpoolmap) &
+          & .and. associated(db(handle)%vpoolmap_idx)) then ! I.e. mapping exists
+    do k=1,npools
+       j = db(handle)%vpoolmap_idx(k) ! Descending order i.e. largest first
+       if (db(handle)%vpoolmap(j) == vpoolno) then
+          rc = j
+          exit
+       else if (db(handle)%vpoolmap(j) < vpoolno) then
+          rc = -abs(ODB_NMDI)
+          exit ! Cannot be found
+       endif
+    enddo
+  endif
+endif
+END FUNCTION ODB_vpool2pool
+
+
+FUNCTION get_poolno(handle, poolno) RESULT(ipoolno)
+implicit none
+INTEGER(KIND=JPIM), intent(in)           :: handle
+INTEGER(KIND=JPIM), intent(in), optional :: poolno
+INTEGER(KIND=JPIM) :: ipoolno, j, locNpools
+logical valid
+
+ipoolno = -1 ! By default: Any pool that "ODBMP_myproc" is responsible for
+
+if (present(poolno)) then
+  ipoolno = ODB_vpool2pool(handle,poolno)
+  if (ipoolno > 0) then
+    if (ODBMP_physproc(ipoolno) /= ODBMP_myproc) then
+      ipoolno = 0  ! It is not my pool
+    endif
+  endif
+  if (ipoolno > db(handle)%glbMaxpoolno) ipoolno = 0
+endif
+
+if (handle > 0 .and. handle <= maxhandle) then
+  locNpools = db(handle)%locNpools
+  if (ipoolno > 0) then ! Check validity
+    valid = .FALSE.
+    LOOP: do j=1,locNpools
+      if (ipoolno == db(handle)%poolidx(j)) then
+        valid = .TRUE.
+        exit LOOP
+      endif
+    enddo LOOP
+    if (.not. valid) ipoolno = -2
+  else if (ipoolno == -1) then ! If "-1", check if only one pool for this PE
+    if (locNpools == 1) ipoolno = db(handle)%poolidx(1) ! Set exactly to this poolno for performance
+  endif
+endif
+
+END FUNCTION get_poolno
+
+
+
+FUNCTION ODB_valid_poolno(poolno) RESULT(valid)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: poolno
+logical valid
+valid = (poolno == -1 .or. (poolno >= 1 .and. poolno <= 2147483647))
+END FUNCTION ODB_valid_poolno
+
+
+
+SUBROUTINE no_abort()
+implicit none
+return
+END SUBROUTINE no_abort
+
+
+
+FUNCTION get_handle() RESULT(rc)
+implicit none
+INTEGER(KIND=JPIM) :: j, rc
+if (.not. db_initialized) CALL init_db()
+rc = -1
+do j=1,maxhandle
+  if (.not.db(j)%inuse) then
+    rc = j
+    return
+  endif
+enddo
+END FUNCTION get_handle
+
+
+
+SUBROUTINE init_db()
+implicit none
+INTEGER(KIND=JPIM) :: j, trace_on, rc, idummy(1), ilen, ibytes
+INTEGER(KIND=JPIM), allocatable :: ioassign(:)
+external odb_debug_print
+external cma_open, cma_close, cma_readb, cma_writeb
+external codb_twindow, codb_tdiff
+external codb_trace, codb_filesize, codb_datetime
+external codb_abort_func
+external cmpl_abort
+external codb_putenv, codb_pause, codb_system, codb_getpid
+external codb_getenv, codb_set_entrypoint, codb_wait, codb_subshell
+!      external abort
+
+if (db_initialized) return
+
+CALL cODB_register_abort_func('cmpl_abort')
+!      CALL cODB_register_abort_func('abort')
+
+CALL ODBMP_init()
+
+if (ODBMP_myproc < 1 .or. ODBMP_nproc < 1) then
+  CALL ODB_abort('init_db','Invalid myproc and/or nproc')
+  return
+endif
+
+
+CALL codb_putenv('IOASSIGN_INCORE=0')
+if (ODBMP_nproc > 1) then
+!-- Make sure that only one MPI-task reads the IOASSIGN
+!   and then replicates the contents to other tasks
+  CALL ODBMP_trace(.FALSE.)
+  if (ODBMP_myproc == 1) then
+    CALL get_incore_ioassign(idummy,0,rc) ! rc = # of bytes in IOASSIGN-file
+  else
+    rc = 0
+  endif
+  CALL ODBMP_global('MAX',rc)
+  ibytes = rc
+  ilen = (ibytes + ODB_SIZEOF_INT - 1) / ODB_SIZEOF_INT
+  if (ilen > 0) then
+    allocate(ioassign(ilen))
+    ioassign(:) = 0
+    if (ODBMP_myproc == 1) then
+      CALL get_incore_ioassign(ioassign,ibytes,rc)
+    endif
+    CALL ODBMP_distribute(ioassign,ilen,0,rc)
+    CALL put_incore_ioassign(ioassign,ibytes,rc)
+    deallocate(ioassign)
+    CALL codb_putenv('IOASSIGN_INCORE=1')
+  endif
+endif
+
+CALL cODB_init_omp_locks()
+
+trace_on = 0
+CALL cODB_trace_init(trace_on)
+db_trace = (trace_on > 0)
+
+CALL ODBMP_trace(db_trace)
+
+CALL cODB_set_signals()
+
+CALL util_igetenv('ODB_WRAPCOL', def_wrapcol, wrapcol)
+if (wrapcol <= 0) wrapcol = def_wrapcol
+
+CALL util_igetenv('ODB_SHOWDBIDX', def_showdbidx, showdbidx)
+if (showdbidx > 0) then
+  showdbidx = 1
+else
+  showdbidx = 0
+endif
+
+CALL util_igetenv('ODB_IO_LOCK', def_haveiolock, haveiolock)
+if (showdbidx <= 0) haveiolock = 0
+
+CALL util_igetenv('ODB_LDA_METHOD', def_lda_method, lda_method)
+
+CALL util_igetenv('ODB_MAXHANDLE', def_maxhandle, maxhandle)
+if (maxhandle <= 0) maxhandle = def_maxhandle
+CALL cODB_alloc_poolmask(maxhandle)
+
+allocate(db(maxhandle))
+
+do j=1,maxhandle
+  db(j)%inuse = .FALSE.
+  db(j)%newdb = .TRUE.
+  db(j)%altered = .FALSE.
+  db(j)%readonly = .FALSE.
+  db(j)%io_method = 1
+  db(j)%glbNpools = 0
+  db(j)%locNpools = 0
+  db(j)%iounit = -1
+  db(j)%ntables = 0
+  db(j)%naid = 0
+  db(j)%nfileblocks = 0
+  db(j)%CreationDT(:) = 0
+  db(j)%AnalysisDT(:) = 0
+  db(j)%name = '(not defined)'
+  nullify(db(j)%poolidx)
+  nullify(db(j)%ioaid)
+  nullify(db(j)%grpsize)
+  nullify(db(j)%ctables)
+  nullify(db(j)%ciomap)
+  nullify(db(j)%io_volume)
+  nullify(db(j)%vpoolmap)
+  nullify(db(j)%vpoolmap_idx)
+  db(j)%nvmap = 0
+enddo
+
+pint          = prt_t( 1, 13, '(1x,a12)', "%s%*lld"//char(0))
+puint         = prt_t( 2, 13, '(1x,a12)', "%s%*llu"//char(0))
+preal         = prt_t( 3, 22, '(1x,1p,g21.14)', "%s%*.14g"//char(0))
+pstring       = prt_t( 4, 12, "(2x,'''',a8,'''')", "%s%*s'%8s'"//char(0))
+pbitf         = prt_t( 5, 34, '(2x,b32.32)', 'N/A')
+phex          = prt_t( 6, 12, '(2x,"0x",z8.8)', "%s%*s0x%8.8llx"//char(0))
+pyyyymmdd     = prt_t( 7, 14, '(6x,i8.8)', "%s%*.8lld"//char(0))
+! But when ODB_PRINT_PRETTY_DATE_TIME=1, then use the following format below DD-mon-YYYY
+pyyyymmdd_pdt = prt_t(17, 14, '(3x,i2.2,"-",a3,"-",i4.4)', "%s%s"//char(0))
+phhmmss       = prt_t( 8, 12, '(6x,i6.6)', "%s%*.6lld"//char(0))
+! But when ODB_PRINT_PRETTY_DATE_TIME=1, the use the following format below HH:MM:SS
+phhmmss_pdt   = prt_t(18, 12, '(4x,i2.2,":",i2.2,":",i2.2)', "%s%s"//char(0))
+pdbidx        = prt_t( 9, 20, '(i10,i10.10)', "%s%10u%10.10u"//char(0))
+pvarprec      = prt_t(10, 22, '(1x,1p,g21.14)', "%s%*.*g"//char(0))
+plinkoffset_t = prt_t( 1, 13, '(1x,a12)', "%s%*lld"//char(0))
+plinklen_t    = prt_t( 1, 13, '(1x,a12)', "%s%*lld"//char(0))
+punknown      = prt_t(-1, 12, '(6x,"<what>")','N/A')
+
+#ifdef DYNAMIC_LINKING
+!-- Enforce some routines into executable even if they
+!   were not directly called.
+!   They may be used by the dynamically linked objects.
+!   These externals will in turn bring more code in.
+
+CALL dummy_load(odb_debug_print)
+CALL dummy_load(cma_open)
+CALL dummy_load(cma_close)
+CALL dummy_load(cma_readb)
+CALL dummy_load(cma_writeb)
+CALL dummy_load(codb_twindow)
+CALL dummy_load(codb_tdiff)
+CALL dummy_load(codb_trace)
+CALL dummy_load(codb_filesize)
+CALL dummy_load(codb_datetime)
+CALL dummy_load(codb_abort_func)
+CALL dummy_load(codb_putenv)
+CALL dummy_load(codb_getenv)
+CALL dummy_load(codb_pause)
+CALL dummy_load(codb_system)
+CALL dummy_load(codb_getpid)
+CALL dummy_load(codb_set_entrypoint)
+CALL dummy_load(codb_wait)
+CALL dummy_load(codb_subshell)
+
+CALL cdummy_load()
+#endif
+
+db_initialized = .TRUE.
+END SUBROUTINE init_db
+
+#ifndef USE_CTRIM
+#undef ctrim
+#undef CTRIM
+#endif
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odbshared
diff --git a/odb/src/module/odbsort.F90 b/odb/src/module/odbsort.F90
new file mode 100644
index 0000000..8df3273
--- /dev/null
+++ b/odb/src/module/odbsort.F90
@@ -0,0 +1,4 @@
+MODULE ODBSORT
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE ecsort_mix ! From IFSAUX
+END MODULE ODBSORT
diff --git a/odb/src/module/odbstat.F90 b/odb/src/module/odbstat.F90
new file mode 100644
index 0000000..d02fb5a
--- /dev/null
+++ b/odb/src/module/odbstat.F90
@@ -0,0 +1,127 @@
+module odbstat
+USE PARKIND1  ,ONLY : JPIM,JPIB,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+USE odbutil, only : odb_getnames
+USE odbshared, only : ODB_NMDI
+
+implicit none
+
+private
+
+INTEGER(KIND=JPIM), parameter :: odb_statlen = 7
+INTEGER(KIND=JPIM), parameter :: odb_statcharlen = 8
+
+character(len=odb_statcharlen), parameter :: odb_statbuf(odb_statlen) = (/ &
+     & '  Count ', &
+     & 'Ignored ', &
+     & '    Min ', &
+     & '    Max ', &
+     & 'Average ', &
+     & ' St.Dev ', &
+     & '    RMS '/)
+     
+
+public :: odb_statlen, odb_statcharlen
+public :: odb_statbuf
+public :: odb_collectstat
+public :: odb_makestat
+
+contains
+
+subroutine odb_collectstat(handle, dtname, d, nrows, ncols, stat)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: handle, nrows, ncols
+character(len=*), intent(in)   :: dtname
+REAL(KIND=JPRB), intent(in)    :: d(:,:)
+REAL(KIND=JPRB), intent(inout), optional :: stat(:,:)
+INTEGER(KIND=JPIM) ndtypes, j
+character(len=64) CLdtypes(ncols)
+logical LLmask
+INTEGER(KIND=JPIM) jc, nrows_out, ncols_out
+REAL(KIND=JPRB) ZHOOK_HANDLE
+if (.not.present(stat)) return
+if (size(stat) == 0) return
+IF (LHOOK) CALL DR_HOOK('ODBSTAT:ODB_COLLECTSTAT',0,ZHOOK_HANDLE)
+nrows_out = min(nrows, size(d,dim=1))
+ndtypes = ODB_getnames(handle, dtname, 'datatype', CLdtypes)
+ncols_out = min(ndtypes, ncols, size(d,dim=2), size(stat,dim=2))
+if (size(stat, dim=1) >= odb_statlen .and. nrows_out > 0 .and. ncols_out > 0) then
+  do jc=1,ncols_out
+    !-- check first if initialization is required
+    if (stat(1,jc) == 0) then
+      stat(:,jc) = 0
+      stat(3,jc) =  ODB_NMDI ! Min
+      stat(4,jc) = -ODB_NMDI ! Max
+    endif
+
+    stat(1,jc) = stat(1,jc) + nrows_out ! total count so far (valid + non-valid data)
+
+    if (CLdtypes(jc) == 'string') then
+      stat(2,jc) = 0 ! Non-valid data for statistics calculation throughout
+    else
+      do j=1,nrows_out
+        LLmask = (abs(d(j,jc)) /= ODB_NMDI) ! Take only those which aren't missing data
+        if (LLmask) then
+          stat(2,jc) = stat(2,jc) + 1                ! No. of valid data
+          stat(3,jc) = min(stat(3,jc), d(j,jc))      ! Min
+          stat(4,jc) = max(stat(4,jc), d(j,jc))      ! Max
+          stat(5,jc) = stat(5,jc) + d(j,jc)          ! Sum(d)
+          stat(6,jc) = stat(6,jc) + d(j,jc)*d(j,jc)  ! Sum(d^2)
+        endif
+      enddo ! do j=1,nrows_out
+    endif
+  enddo ! do jc=1,ncols_out
+endif
+IF (LHOOK) CALL DR_HOOK('ODBSTAT:ODB_COLLECTSTAT',1,ZHOOK_HANDLE)
+end subroutine odb_collectstat
+
+
+subroutine odb_makestat(final_stat, nrows, ncols, stat)
+implicit none
+INTEGER(KIND=JPIM), intent(in) :: nrows, ncols
+REAL(KIND=JPRB), intent(out)   :: final_stat(:,:)
+REAL(KIND=JPRB), intent(in)    :: stat(:,:)
+REAL(KIND=JPRB) rnn, avg
+INTEGER(KIND=JPIM) jc, nrows_out, ncols_out
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODBSTAT:ODB_MAKESTAT',0,ZHOOK_HANDLE)
+nrows_out = min(nrows, size(final_stat,dim=1), size(stat,dim=1))
+ncols_out = min(ncols, size(final_stat,dim=2), size(stat,dim=2))
+if (nrows_out >= odb_statlen .and. ncols_out > 0) then
+  do jc=1,ncols_out
+    rnn = stat(2,jc) ! No. of valid data
+    final_stat(1,jc) = rnn ! No. of valid data
+    final_stat(2,jc) = stat(1,jc) - rnn ! No. of missing/ignored/string data
+    final_stat(3,jc) = stat(3,jc)
+    final_stat(4,jc) = stat(4,jc)
+    if (rnn > 0) then
+      avg = stat(5,jc)/rnn ! Average
+    else
+      avg = 0
+    endif
+    final_stat(5,jc) = avg
+    if (rnn > 1) then ! Standard deviation
+      final_stat(6,jc) = (stat(6,jc) - rnn * (avg**2))/(rnn - 1)
+      if (final_stat(6,jc) > 0) then ! some security due to round of errors
+        final_stat(6,jc) = sqrt(final_stat(6,jc))
+      else
+        final_stat(6,jc) = 0
+      endif
+    else
+      final_stat(6,jc) = 0
+    endif
+    if (rnn > 0) then ! RMS
+      if (stat(6,jc) > 0) then
+        final_stat(7,jc) = sqrt(stat(6,jc)/rnn)
+      else
+        final_stat(7,jc) = 0
+      endif
+    else
+      final_stat(7,jc) = 0
+    endif
+  enddo
+endif
+IF (LHOOK) CALL DR_HOOK('ODBSTAT:ODB_MAKESTAT',1,ZHOOK_HANDLE)
+end subroutine odb_makestat
+
+end module odbstat
diff --git a/odb/src/module/odbutil.F90 b/odb/src/module/odbutil.F90
new file mode 100644
index 0000000..2e71c53
--- /dev/null
+++ b/odb/src/module/odbutil.F90
@@ -0,0 +1,842 @@
+#ifdef RS6K
+ at PROCESS NOEXTCHK
+#endif
+MODULE odbutil
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+
+USE odbshared ! The shared (internal) stuff
+USE odbmp ! The message passing module
+USE str, only : toupper, tolower, sadjustl, sadjustr
+USE odbsort, only : keysort
+
+IMPLICIT NONE
+SAVE
+PRIVATE
+
+#ifndef USE_CTRIM
+#define ctrim(x) x
+#define CTRIM(x) x
+#endif
+
+#define trimadjL(x) trim(sadjustl(x))
+#define trimadjR(x) trim(sadjustr(x))
+
+#include "fodb_checkviewreg.h"
+
+INTERFACE ODB_setval
+MODULE PROCEDURE & 
+  & ODB_dsetval, ODB_isetval
+END INTERFACE
+
+INTERFACE ODB_duplchk
+MODULE PROCEDURE & 
+  & ODB_iduplchk, ODB_dduplchk
+END INTERFACE
+
+INTERFACE duplchk0
+MODULE PROCEDURE & 
+  & iduplchk0, dduplchk0
+END INTERFACE
+
+INTERFACE ODB_groupify
+MODULE PROCEDURE & 
+  & ODB_igroupify, ODB_dgroupify
+END INTERFACE
+
+INTERFACE ODB_tolsearch
+MODULE PROCEDURE & 
+  & ODB_itolsearch, ODB_dtolsearch
+END INTERFACE
+
+INTERFACE ODB_binsearch
+MODULE PROCEDURE & 
+  & ODB_ibinsearch, ODB_dbinsearch
+END INTERFACE
+
+INTERFACE ODB_aggregate
+MODULE PROCEDURE & 
+  & ODB_iaggregate, ODB_daggregate
+END INTERFACE
+
+INTERFACE ODB_control_word_info
+MODULE PROCEDURE &
+  & ODB_control_word_info_vector, ODB_control_word_info_matrix
+END INTERFACE
+
+public :: ODB_getnames
+public :: ODB_varindex
+public :: ODB_getprecision
+public :: ODB_setval
+public :: ODB_getval
+public :: ODB_varexist
+public :: ODB_poolinfo
+public :: ODB_duplchk
+public :: ODB_groupify
+public :: ODB_tolsearch
+public :: ODB_binsearch
+public :: ODB_aggregate
+public :: ODB_twindow
+public :: ODB_tdiff
+public :: ODB_analysis_datetime
+public :: ODB_get_update_info
+public :: ODB_get_aggr_info
+public :: ODB_sortkeys
+public :: ODB_io_method
+public :: ODB_has_select_distinct
+public :: ODB_has_uniqueby
+public :: ODB_has_orderby
+public :: ODB_has_aggrfuncs
+public :: ODB_control_word_info
+
+CONTAINS
+
+FUNCTION ODB_poolinfo(handle, poolids, with_poolmask) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)            :: handle
+INTEGER(KIND=JPIM), intent(out), optional :: poolids(:)
+logical, intent(in), optional :: with_poolmask
+INTEGER(KIND=JPIM) :: rc, j, jj, jlocal, npools, poolmask_set
+INTEGER(KIND=JPIM), allocatable :: ids(:), pool_list(:)
+logical LL_with_poolmask
+logical, allocatable :: LL_poolmask(:)
+rc = 0
+if (odbHcheck(handle, 'ODB_poolinfo')) then
+  npools = db(handle)%glbNpools ! Global no. of pools
+
+  if (present(poolids)) then
+    allocate(LL_poolmask(npools))
+    LL_with_poolmask = .FALSE.
+    if (present(with_poolmask)) LL_with_poolmask = with_poolmask
+
+    if (LL_with_poolmask) then
+      allocate(pool_list(npools))
+      pool_list(:) = 0
+      !-- Note: The current poolmask only reliable/applicable for local pools !!
+      CALL cODB_get_poolmask(handle, npools, pool_list, poolmask_set, rc)
+      if (rc == 0 .or. poolmask_set == 0) then
+        !-- poolmask empty or not set at all --> process all pools
+        LL_poolmask(:) = .TRUE.
+      else
+        do j=1,npools
+          if (pool_list(j) == 1) then
+            LL_poolmask(j) = .TRUE.
+          else
+            LL_poolmask(j) = .FALSE.
+          endif
+        enddo
+      endif
+      deallocate(pool_list)
+    else ! disregard poolmask i.e. consider all pools included
+      LL_poolmask(:) = .TRUE.
+    endif
+
+    allocate(ids(npools))
+    ids(:) = 0 ! Initialize to non-existent pool number <= 0
+    jj = 0
+    do j=1,npools
+      if (ODBMP_physproc(j) == ODBMP_myproc) then ! locally owned pools
+        if (LL_poolmask(j)) then ! poolmask is guaranteed been set for local pools only
+          jj = jj + 1
+          ids(jj) = j
+        endif
+      endif
+    enddo
+    jlocal = jj
+    do j=1,npools
+      if (ODBMP_physproc(j) /= ODBMP_myproc) then ! non-local pools
+      ! we do not test for
+        jj = jj + 1
+        ids(jj) = j
+      endif
+    enddo
+
+    do j=1,min(npools,size(poolids))
+      poolids(j) = ids(j)
+    enddo
+    deallocate(ids)
+    deallocate(LL_poolmask)
+
+!---  Note: Return code is now local no. of pools, i.e. the first entries put into poolids(:)
+    rc = jlocal   ! i.e. db(handle)%locNpools if no poolmasking taken into account
+  else
+!---  Note: Return code without presence of poolids(:) arg is global no. of pools
+!           (poolmask was not taken into account)
+    rc = npools
+  endif
+endif
+END FUNCTION ODB_poolinfo
+
+
+
+FUNCTION ODB_twindow(&
+     &target_date,&
+     &target_time,&
+     &analysis_date,&
+     &analysis_time,&
+     &left_margin,&
+     &right_margin)&
+     &RESULT(rc)
+INTEGER(KIND=JPIM), intent(in) :: target_date, target_time
+INTEGER(KIND=JPIM), intent(in) :: analysis_date, analysis_time
+INTEGER(KIND=JPIM), intent(in) :: left_margin, right_margin
+INTEGER(KIND=JPIM) :: rc
+CALL cODB_twindow(&
+     &target_date, target_time,&
+     &analysis_date, analysis_time,&
+     &left_margin, right_margin,&
+     &rc)
+END FUNCTION ODB_twindow
+
+
+
+FUNCTION ODB_tdiff(&
+     &target_date,&
+     &target_time,&
+     &analysis_date,&
+     &analysis_time)&
+     &RESULT(rc)
+INTEGER(KIND=JPIM), intent(in) :: target_date, target_time
+INTEGER(KIND=JPIM), intent(in) :: analysis_date, analysis_time
+INTEGER(KIND=JPIM) :: rc
+CALL cODB_tdiff(target_date, target_time,analysis_date, analysis_time,rc)
+END FUNCTION ODB_tdiff
+
+
+
+SUBROUTINE ODB_analysis_datetime(handle, andate, antime)
+INTEGER(KIND=JPIM), intent(in) :: handle, andate, antime
+INTEGER(KIND=JPIM) :: rc
+if (odbHcheck(handle, 'ODB_analysis_datetime')) then
+  rc = ODB_twindow(andate, antime, andate, antime, 0, 0)
+  if (rc /= 1) then
+    write(0,*)'*** Warning: Attempt to change analysis date/time failed'
+    write(0,*) 'Wrong analysis date: ',andate,' and/or time ',antime
+  else
+    db(handle)%analysisDT(0) = andate
+    db(handle)%analysisDT(1) = antime
+  endif
+endif
+END SUBROUTINE ODB_analysis_datetime
+
+
+
+FUNCTION ODB_getnames(handle, dtname, mode, outnames) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: dtname, mode
+character(len=*), intent(out), optional :: outnames(:)
+INTEGER(KIND=JPIM) :: rc
+character(len=maxstrlen) CL_str
+character(len=1) ODB_tag_delim
+INTEGER(KIND=JPIM) :: what, j, istart, iend, ilen
+logical LL_alltables, LL_cached
+rc = 0
+if ( mode == 'type'      .or. &
+     mode == 'ctype'     .or. &
+     mode == 'datatype' ) then
+  what = 1
+else if (mode == 'name' .or. mode == 'varname' .or.  mode == 'colname') then
+  what = 2
+else if (mode == 'table' .or. mode == 'tablename') then
+  what = 3
+else if (mode == 'view' .or. mode == 'viewname') then
+  what = 4
+else if (mode == 'sql' .or. mode == 'sqlname') then
+  what = 4
+else if (mode == 'query' .or. mode == 'queryname') then
+  what = 4
+else if (mode == 'ftntype' .or. mode == 'ftndatatype') then
+  what = 11
+else if (mode == 'exttype'      .or. &
+         mode == 'extctype'     .or. &
+         mode == 'extdatatype' ) then
+  what = 101
+else if (mode == 'extname' .or. mode == 'extvarname' .or. mode == 'colvarname') then
+  what = 102
+else if (mode == 'extftntype' .or. mode == 'extftndatatype') then
+  what = 111
+else
+  what = 0
+endif
+
+if (odbHcheck(handle, 'ODB_getnames')) then
+  LL_alltables = .FALSE.
+  LL_cached = .FALSE.
+  if (len(dtname) >= 1) then
+    LL_alltables = (dtname(1:1) == '*' .AND. what == 3)
+    LL_cached = LL_alltables .AND. associated(db(handle)%ctables)
+  endif
+  if (present(outnames)) then
+!    CL_str = ' '
+    if (LL_cached) then
+      rc = db(handle)%ntables
+    else
+      CALL codb_strblank(CL_str) ! faster initialization
+      CALL fODB_checkviewreg(handle, ctrim(dtname), rc)
+      CALL cODB_getnames(handle, ctrim(dtname), what, CL_str, ilen, rc)
+    endif
+    if (rc < 0) then
+      CALL ODB_abort('ODB_getnames',&
+       &'Internal error: Cannot fit names(mode='//&
+       &trim(mode)//&
+       &') of VIEW/TABLE="'//trim(dtname)//&
+       &'" into the array',&
+       &rc)
+      return
+    endif
+    if (rc > size(outnames)) then
+      CALL ODB_abort('ODB_getnames',&
+       &'Require more space for output names(mode='//&
+       &trim(mode)//&
+       &') of VIEW/TABLE="'//trim(dtname)//'"',&
+       &rc)
+      return
+    endif
+  else ! Just get the dimension/size
+    if (LL_cached) then
+      rc = db(handle)%ntables
+    else
+      CALL fODB_checkviewreg(handle, ctrim(dtname), rc)
+      CALL cODB_getnames(handle, ctrim(dtname), what, '', ilen, rc)
+    endif
+    if (rc < 0) then
+      CALL ODB_abort('ODB_getnames',&
+       &'Internal error: with mode='//&
+       &trim(mode)//&
+       &') of VIEW/TABLE="'//trim(dtname)//&
+       &'"',&
+       &rc)
+      return
+    endif
+!--   Yes, this is indeed correct: 
+!     -- Just return the no. elems needed for outnames(:)
+    return
+  endif
+  if (LL_cached) then
+    do j=1,min(rc,size(outnames))
+      outnames(j) = db(handle)%ctables(j)
+    enddo
+  else
+    call cODB_tag_delim(ODB_tag_delim)
+    iend = 1
+    do j=1,min(rc,size(outnames))
+      istart = iend + 1
+      iend = iend + index(CL_str(istart:),ODB_tag_delim)
+      outnames(j) = CL_str(istart:iend-1)
+    enddo
+    if (LL_alltables .AND. rc == db(handle)%ntables) then
+      allocate(db(handle)%ctables(rc))
+      iend = 1
+      do j=1,rc
+        istart = iend + 1
+        iend = iend + index(CL_str(istart:),ODB_tag_delim)
+        db(handle)%ctables(j) = CL_str(istart:iend-1)
+      enddo
+    endif
+  endif
+endif
+END FUNCTION ODB_getnames
+
+
+
+FUNCTION ODB_varindex(handle, dtname, names, idx) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: dtname
+character(len=*), intent(in)  :: names(:)
+INTEGER(KIND=JPIM), intent(out)        :: idx(:)
+INTEGER(KIND=JPIM), parameter :: what = 2
+INTEGER(KIND=JPIM) :: rc
+character(len=len(names)) CL_names
+character(len=maxstrlen) CL_str
+character(len=1) ODB_tag_delim
+character(len=30) CL_tmp
+INTEGER(KIND=JPIM) :: i, j, ncols, ncols_idx
+INTEGER(KIND=JPIM) :: i1
+INTEGER(KIND=JPIM) :: jleft, jright, number, ilen
+INTEGER(KIND=JPIM), allocatable :: istart(:), iend(:)
+logical is_table, is_formula, takethis
+
+is_table = .FALSE.
+if (len(dtname) >= 1) then
+  is_table = (dtname(1:1) == '@')
+endif
+
+rc = 0
+if (odbHcheck(handle, 'ODB_varindex')) then
+!  CL_str = ' '
+  CALL codb_strblank(CL_str) ! faster initialization
+  CALL fODB_checkviewreg(handle, ctrim(dtname), rc)
+  CALL cODB_getnames(handle, ctrim(dtname), what, CL_str, ilen, rc)
+  if (rc <= 0) then
+    CALL ODB_abort('ODB_varindex',&
+     &'Internal error: Cannot fit names'//&
+     &' of VIEW/TABLE="'//trim(dtname)//&
+     &'" into the array',&
+     &rc)
+    return
+  endif
+  ncols = rc
+  allocate(istart(ncols))
+  allocate(iend(0:ncols))
+  iend(0) = 0
+  call cODB_tag_delim(ODB_tag_delim)
+  do j=1,ncols
+    istart(j) = iend(j-1) + 2
+    iend(j) = istart(j) + index(CL_str(istart(j):),ODB_tag_delim) - 2
+  enddo
+
+  idx(:) = 0
+  ncols_idx = min(size(names), size(idx))
+  rc = 0
+
+  do i=1,ncols_idx
+    CL_names = trimadjL(names(i))
+
+! detect whether te current CL_names is in fact a formula or nickname 
+    if (is_table) then
+      is_formula = .FALSE.
+    else
+      i1 = scan(trim(CL_names), '@Formula', back=.TRUE.)
+      is_formula = (i1 > 0) ! Formula
+      if (.not.is_formula) then
+        i1 = index(trim(CL_names), '@')
+        if (i1 <= 0) then
+          is_formula = .TRUE.
+          CL_names = trim(CL_names)//'@Formula'
+        endif
+      endif
+      if (is_formula) goto 988
+    endif
+
+! check for '[<number>]' and convert it to '_<number>'
+    jleft = index(CL_names,'[')
+    if (jleft > 1) then
+       jright = index(CL_names,']', back=.TRUE.)
+       if (jright > jleft + 1) then
+          read(CL_names(jleft+1:jright-1),*,err=987,end=987) number
+       else if (jright == jleft + 1) then
+          number = 0
+       else
+          goto 987
+       endif
+       if (number < 0) then
+          write(CL_tmp,*) -number
+          CL_names = CL_names(1:jleft-1)//'__'//&
+            trimadjL(CL_tmp) &
+            //CL_names(jright+1:)
+       else
+          write(CL_tmp,*) number
+         CL_names = CL_names(1:jleft-1)//'_'//&
+            trimadjL(CL_tmp) &
+            //CL_names(jright+1:)
+       endif
+    endif
+
+987 continue
+    i1 = index(CL_names,'(')
+    if (i1 == 0) then
+      i1 = 1
+    else
+      CALL toupper(CL_names(1:i1-1))
+    endif
+    CALL tolower(CL_names(i1:))
+
+988 continue
+
+    LOOP: do j=1,ncols
+      takethis = .FALSE.
+      if (is_table) then
+        if (trim(CL_names)//'@'//trim(dtname(2:)) == CL_str(istart(j):iend(j))) takethis = .TRUE.
+      else
+        if (CL_names == CL_str(istart(j):iend(j))) takethis = .TRUE.
+      endif
+      if (takethis) then
+        rc = rc + 1
+        idx(i) = j
+        exit LOOP
+      endif
+    enddo LOOP
+  enddo
+
+  deallocate(istart)
+  deallocate(iend)
+endif
+END FUNCTION ODB_varindex
+
+
+
+FUNCTION ODB_getprecision(handle, dtname, maxbits, anyflp)RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+INTEGER(KIND=JPIM), intent(out)        :: maxbits
+logical, intent(out)          :: anyflp
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM) :: rc, ianyflp
+rc = 0
+anyflp = .FALSE.
+maxbits = 0
+if (odbHcheck(handle, 'ODB_getprecision')) then
+  CALL cODB_getprecision(handle, ctrim(dtname), maxbits, ianyflp, rc)
+  if (rc <= 0) then
+    CALL ODB_abort('ODB_getprecision',&
+     &'Internal error: Cannot get precision'//&
+     &' of VIEW/TABLE="'//trim(dtname)//&
+     &'" into the array',&
+     &rc)
+    return
+  endif
+  anyflp = (ianyflp > 0)
+endif
+END FUNCTION ODB_getprecision
+
+
+
+FUNCTION ODB_dsetval(handle, varname, newvalue, viewname, using)RESULT(oldvalue)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: varname
+REAL(KIND=JPRB), intent(in)              :: newvalue
+character(len=*), intent(in), optional :: viewname
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+REAL(KIND=JPRB) :: oldvalue
+INTEGER(KIND=JPIM) :: rc, using_it
+oldvalue = 0
+if (odbHcheck(handle, 'ODB_dsetval')) then
+  using_it = 0
+  if (present(using)) using_it = using
+  if (present(viewname)) then
+    CALL fODB_checkviewreg(handle, ctrim(viewname), rc)
+    CALL cODB_setval(&
+     &ctrim(db(handle)%name), ctrim(varname), ctrim(viewname),&
+     &newvalue, oldvalue, using_it)
+  else
+    CALL cODB_setval(&
+     &ctrim(db(handle)%name), ctrim(varname), ctrim(''),&
+     &newvalue, oldvalue, using_it)
+  endif
+endif
+END FUNCTION ODB_dsetval
+
+
+
+FUNCTION ODB_isetval(handle, varname, newvalue_in, viewname, using)RESULT(oldvalue)
+INTEGER(KIND=JPIM), intent(in)            :: handle
+character(len=*), intent(in)     :: varname
+INTEGER(KIND=JPIM), intent(in)            :: newvalue_in
+character(len=*), intent(in), optional :: viewname
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+REAL(KIND=JPRB) :: newvalue
+INTEGER(KIND=JPIM) :: oldvalue
+oldvalue = 0
+if (odbHcheck(handle, 'ODB_isetval')) then
+  newvalue = newvalue_in
+  oldvalue = ODB_setval(handle, varname, newvalue, viewname, using)
+endif
+END FUNCTION ODB_isetval
+
+
+
+FUNCTION ODB_getval(handle, varname, viewname, using) RESULT(value)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: varname
+character(len=*), intent(in), optional :: viewname
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: using
+REAL(KIND=JPRB) :: value
+INTEGER(KIND=JPIM) :: rc, using_it
+value = 0
+if (odbHcheck(handle, 'ODB_getval')) then
+  using_it = 0
+  if (present(using)) using_it = using
+  if (present(viewname)) then
+    CALL fODB_checkviewreg(handle, ctrim(viewname), rc)
+    CALL cODB_getval(ctrim(db(handle)%name), ctrim(varname), ctrim(viewname),value, using_it)
+  else
+    CALL cODB_getval(ctrim(db(handle)%name), ctrim(varname), ctrim('')      ,value, using_it)
+  endif
+endif
+END FUNCTION ODB_getval
+
+
+
+FUNCTION ODB_varexist(handle, varname, viewname) RESULT(exist)
+INTEGER(KIND=JPIM), intent(in)           :: handle
+character(len=*), intent(in)  :: varname
+character(len=*), intent(in), optional :: viewname
+REAL(KIND=JPRB) :: oldvalue, tmpvalue, testvalue
+logical exist
+exist = .FALSE.
+if (odbHcheck(handle, 'ODB_varexist')) then
+  tmpvalue = 1998
+  oldvalue = ODB_setval(handle, varname, tmpvalue, viewname)
+  testvalue = ODB_getval(handle, varname, viewname)
+  exist = (tmpvalue == testvalue)
+  tmpvalue = ODB_setval(handle, varname, oldvalue, viewname)
+endif
+END FUNCTION ODB_varexist
+
+
+
+FUNCTION ODB_get_update_info(handle, dtname, colput) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: dtname
+logical, intent(out)          :: colput(:)
+INTEGER(KIND=JPIM) :: can_update(size(colput))
+INTEGER(KIND=JPIM) :: rc, ncols
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GET_UPDATE_INFO',0,ZHOOK_HANDLE)
+rc = 0
+colput(:) = .FALSE. ! be conservative on this
+if (odbHcheck(handle, 'ODB_get_update_info')) then
+  ncols = size(colput)
+  can_update(:) = 0
+  CALL cODB_update_info(handle, ctrim(dtname), ncols, can_update, rc)
+  if (ncols >=1 .and. ncols <= size(colput)) then
+    colput(1:ncols) = (can_update(1:ncols) == 1)
+  endif
+endif
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GET_UPDATE_INFO',1,ZHOOK_HANDLE)
+END FUNCTION ODB_get_update_info
+
+
+FUNCTION ODB_get_aggr_info(handle, dtname, aggr_func_flag, phase_id, poolno, using) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)         :: handle
+character(len=*), intent(in)  :: dtname
+INTEGER(KIND=JPIM), intent(out) :: aggr_func_flag(:), phase_id
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, using
+INTEGER(KIND=JPIM) :: rc, ncols, ipoolno, using_it
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GET_AGGR_INFO',0,ZHOOK_HANDLE)
+rc = 0
+aggr_func_flag(:) = 0
+if (odbHcheck(handle, 'ODB_get_aggr_info')) then
+  ncols = size(aggr_func_flag)
+  ipoolno = -1
+  if (present(poolno)) ipoolno = poolno
+  using_it = 0
+  if (present(using)) using_it = using
+#if 0
+  write(0,*) 'ODB_get_aggr_info< ipoolno, ncols, using_it=',ipoolno, ncols, using_it
+#endif
+  CALL cODB_aggr_info(handle, ipoolno, ctrim(dtname), ncols, aggr_func_flag, phase_id, using_it, rc)
+#if 0
+  write(0,*) 'ODB_get_aggr_info> rc, phase_id=',rc,phase_id
+  write(0,*) 'ODB_get_aggr_info> aggr_func_flag(:)=',aggr_func_flag
+#endif
+  if (ODBMP_nproc > 1) phase_id = -1 ! Effectively disables the use of pf->tmp in codb.c/aggr.c
+#if 0
+  write(0,*) 'ODB_get_aggr_info>> ODBMP_nproc, phase_id=',ODBMP_nproc, phase_id
+#endif
+endif
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_GET_AGGR_INFO',1,ZHOOK_HANDLE)
+END FUNCTION ODB_get_aggr_info
+
+
+FUNCTION ODB_sortkeys(handle, dtname, keys) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM),intent(out) , optional :: keys(:)
+INTEGER(KIND=JPIM) rc, idummy_arr(0), vhandle
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_SORTKEYS',0,ZHOOK_HANDLE)
+rc = 0
+if (odbHcheck(handle, 'ODB_sortkeys',abort=.FALSE.)) then
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle)
+  if (present(keys)) then
+    if (size(keys) > 0) then
+      CALL cODB_sortkeys(handle, dtname, size(keys), keys(1), rc)
+    endif
+  else
+    CALL cODB_sortkeys(handle, dtname, 0, idummy_arr, rc)
+  endif
+endif
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_SORTKEYS',1,ZHOOK_HANDLE)
+END FUNCTION ODB_sortkeys
+
+
+FUNCTION ODB_io_method(handle) RESULT(rc)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+INTEGER(KIND=JPIM) rc
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_IO_METHOD',0,ZHOOK_HANDLE)
+rc = 1
+if (odbHcheck(handle, 'ODB_io_method',abort=.FALSE.)) then
+  rc = db(handle)%io_method
+endif
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_IO_METHOD',1,ZHOOK_HANDLE)
+END FUNCTION ODB_io_method
+
+
+FUNCTION ODB_has_select_distinct(handle, dtname, ncols) RESULT(has_select_distinct)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(out), optional :: ncols
+logical has_select_distinct, is_table
+INTEGER(KIND=JPIM) view_info(1), nview_info, vhandle, icols
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_SELECT_DISTINCT',0,ZHOOK_HANDLE)
+has_select_distinct = .FALSE.
+icols = 0
+if (odbHcheck(handle, 'ODB_has_select_distinct',abort=.FALSE.)) then
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle)
+  is_table = .FALSE.
+  if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+  if (is_table) then
+    has_select_distinct = .FALSE.
+  else
+    nview_info = 0
+    view_info(:) = 0
+    CALL cODB_get_view_info(handle, ctrim(dtname), view_info(1), size(view_info), nview_info)
+    ! A negative view_info(1) should contain ABS() of no. of columns in SELECT DISTINCT
+    has_select_distinct = (nview_info >= 1 .AND. view_info(1) < 0)
+    icols = abs(view_info(1))
+  endif
+endif
+if (present(ncols)) ncols = icols
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_SELECT_DISTINCT',1,ZHOOK_HANDLE)
+END FUNCTION ODB_has_select_distinct
+
+
+FUNCTION ODB_has_uniqueby(handle, dtname, ncols) RESULT(has_uniqueby)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(out), optional :: ncols
+logical has_uniqueby, is_table
+INTEGER(KIND=JPIM) view_info(1), nview_info, vhandle, icols
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_UNIQUEBY',0,ZHOOK_HANDLE)
+has_uniqueby = .FALSE.
+icols = 0
+if (odbHcheck(handle, 'ODB_has_uniqueby',abort=.FALSE.)) then
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle)
+  is_table = .FALSE.
+  if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+  if (is_table) then
+    has_uniqueby = .FALSE.
+  else
+    nview_info = 0
+    view_info(:) = 0
+    CALL cODB_get_view_info(handle, ctrim(dtname), view_info(1), size(view_info), nview_info)
+    ! A positive view_info(1) should contain no. of columns in UNIQUEBY-clause
+    has_uniqueby = (nview_info >= 1 .AND. view_info(1) > 0)
+    icols = abs(view_info(1))
+  endif
+endif
+if (present(ncols)) ncols = icols
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_UNIQUEBY',1,ZHOOK_HANDLE)
+END FUNCTION ODB_has_uniqueby
+
+
+FUNCTION ODB_has_orderby(handle, dtname, ncols) RESULT(has_orderby)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(out), optional :: ncols
+logical has_orderby, is_table
+INTEGER(KIND=JPIM) nkeys, vhandle, icols
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_ORDERBY',0,ZHOOK_HANDLE)
+has_orderby = .FALSE.
+icols = 0
+if (odbHcheck(handle, 'ODB_has_orderby',abort=.FALSE.)) then
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle)
+  is_table = .FALSE.
+  if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+  if (is_table) then
+    has_orderby = .FALSE.
+  else
+    nkeys = ODB_sortkeys(handle, dtname)
+    has_orderby = (nkeys > 0)
+    icols = nkeys
+  endif
+endif
+if (present(ncols)) ncols = icols
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_ORDERBY',1,ZHOOK_HANDLE)
+END FUNCTION ODB_has_orderby
+
+
+FUNCTION ODB_has_aggrfuncs(handle, dtname, ncols, phase_id, poolno, using) RESULT(has_aggrfuncs)
+INTEGER(KIND=JPIM), intent(in)  :: handle
+character(len=*), intent(in)    :: dtname
+INTEGER(KIND=JPIM), intent(out), optional :: ncols ! No. of cols having aggregate funcs
+INTEGER(KIND=JPIM), intent(out), optional :: phase_id
+INTEGER(KIND=JPIM), intent(in), optional :: poolno, using
+logical has_aggrfuncs, is_table
+INTEGER(KIND=JPIM) vhandle, icols, idummy(0), iphase_id
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_AGGRFUNCS',0,ZHOOK_HANDLE)
+has_aggrfuncs = .FALSE.
+icols = 0
+iphase_id = -1
+if (odbHcheck(handle, 'ODB_has_aggrfuncs',abort=.FALSE.)) then
+  CALL fODB_checkviewreg(handle, ctrim(dtname), vhandle)
+  is_table = .FALSE.
+  if (len(dtname) >= 1) is_table = (dtname(1:1) == '@')
+  if (is_table) then
+    has_aggrfuncs = .FALSE.
+  else
+    icols = ODB_get_aggr_info(handle, dtname, idummy, iphase_id, poolno=poolno, using=using)
+    has_aggrfuncs = (icols > 0)
+  endif
+endif
+if (present(ncols)) ncols = icols
+if (present(phase_id)) phase_id = iphase_id
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_HAS_AGGRFUNCS',1,ZHOOK_HANDLE)
+END FUNCTION ODB_has_aggrfuncs
+
+
+FUNCTION ODB_control_word_info_vector(v,nrows,poolnos,rownums,noffset) RESULT(rc)
+REAL(KIND=JPRB), intent(in)               :: v(:)
+INTEGER(KIND=JPIM), intent(in), optional  :: nrows, noffset
+INTEGER(KIND=JPIM), intent(out), optional :: poolnos(:), rownums(:)
+INTEGER(KIND=JPIM) rc, nrows_out, j, noffset_out
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CONTROL_WORD_INFO_VECTOR',0,ZHOOK_HANDLE)
+nrows_out = size(v)
+if (present(nrows))   nrows_out = min(nrows_out, nrows)
+if (present(poolnos)) nrows_out = min(nrows_out, size(poolnos))
+if (present(rownums)) nrows_out = min(nrows_out, size(rownums))
+if (.not.present(poolnos) .and. .not.present(rownums)) nrows_out = 0
+if (nrows_out > 0) then
+  if (present(poolnos)) then
+    CALL cODB_get_poolnos(v(1), 0, nrows_out, 0, poolnos(1))
+  endif
+  if (present(rownums)) then
+     noffset_out = 0
+    if (present(noffset)) noffset_out = noffset
+    CALL cODB_get_rownum(v(1), 0, nrows_out, 0, noffset_out, rownums(1))
+  endif
+endif ! if (nrows_out > 0)
+rc = nrows_out
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CONTROL_WORD_INFO_VECTOR',1,ZHOOK_HANDLE)
+END FUNCTION ODB_control_word_info_vector
+
+
+FUNCTION ODB_control_word_info_matrix(d,nrows,poolnos,rownums,noffset) RESULT(rc)
+REAL(KIND=JPRB), intent(in)               :: d(:,0:)
+INTEGER(KIND=JPIM), intent(in), optional  :: nrows, noffset
+INTEGER(KIND=JPIM), intent(out), optional :: poolnos(:), rownums(:)
+INTEGER(KIND=JPIM) rc
+REAL(KIND=JPRB) ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CONTROL_WORD_INFO_MATRIX',0,ZHOOK_HANDLE)
+rc = ODB_control_word_info_vector(d(:,0),nrows,poolnos,rownums,noffset)
+IF (LHOOK) CALL DR_HOOK('ODB:ODB_CONTROL_WORD_INFO_MATRIX',1,ZHOOK_HANDLE)
+END FUNCTION ODB_control_word_info_matrix
+
+
+#undef INT_VERSION
+#undef REAL_VERSION
+
+#define INT_VERSION 4
+#include "fodbutil.h"
+#undef INT_VERSION
+
+#define REAL_VERSION 8
+#include "fodbutil.h"
+#undef REAL_VERSION
+
+#ifndef USE_CTRIM
+#undef ctrim
+#undef CTRIM
+#endif
+
+#undef trimadjL
+#undef trimadjR
+
+END MODULE odbutil
diff --git a/odb/src/module/stackdb.F90 b/odb/src/module/stackdb.F90
new file mode 100644
index 0000000..73be00b
--- /dev/null
+++ b/odb/src/module/stackdb.F90
@@ -0,0 +1,119 @@
+MODULE stackdb
+
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+
+USE odbshared, only : maxvarlen
+
+implicit none
+
+SAVE
+PRIVATE
+
+PUBLIC :: init_stack
+PUBLIC :: size_stack
+PUBLIC :: push_stack
+PUBLIC :: vecpush_stack
+PUBLIC :: pop_stack
+
+INTEGER(KIND=JPIM) :: stack_size = 0
+
+TYPE stackdb_t
+  character(len=maxvarlen) name
+  TYPE(stackdb_t), POINTER :: prev
+  TYPE(stackdb_t), POINTER :: next
+END TYPE stackdb_t
+
+TYPE(stackdb_t), POINTER :: head
+TYPE(stackdb_t), POINTER :: tail
+
+CONTAINS
+
+FUNCTION size_stack() RESULT(isize)
+implicit none
+INTEGER(KIND=JPIM) :: isize
+isize = stack_size
+END FUNCTION size_stack
+
+
+SUBROUTINE init_stack()
+implicit none
+TYPE(stackdb_t), POINTER :: this, next
+if (stack_size > 0) then
+  this => head
+  do while (associated(this))
+    next => this%next
+    deallocate(this)
+    this => next
+  enddo
+endif
+nullify(head)
+nullify(tail)
+stack_size = 0
+END SUBROUTINE init_stack
+
+
+SUBROUTINE push_stack(name)
+implicit none
+character(len=*), intent(in) :: name
+TYPE(stackdb_t), POINTER :: this
+nullify(this)
+if (.not.associated(head)) then
+  allocate(head)
+  tail => head
+  stack_size = 1
+else
+  this => tail
+  allocate(this%next)
+  tail => this%next
+  stack_size = stack_size + 1
+endif
+tail%name = name
+tail%prev => this
+nullify(tail%next)
+END SUBROUTINE push_stack
+
+
+SUBROUTINE vecpush_stack(name, table, k1, k2)
+implicit none
+character(len=*), intent(in) :: name, table
+INTEGER(KIND=JPIM), intent(in) :: k1
+INTEGER(KIND=JPIM), intent(in), OPTIONAL :: k2
+INTEGER(KIND=JPIM) :: i1, i2
+character(len=len(name)+len(table)+20) tmp
+INTEGER(KIND=JPIM) j
+i1 = k1
+if (present(k2)) then
+  i2 = k2
+else
+  i2 = i1
+endif
+do j=i1,i2
+  if (j >= 0 .and. j <= 9) then
+    write(tmp,'(a,"_",i1,a)') name, j, table
+  else if (j >= 10 .and. j <= 99) then
+    write(tmp,'(a,"_",i2,a)') name, j, table
+  else
+    tmp = '<undefined>'
+  endif
+  CALL push_stack(tmp)
+enddo
+END SUBROUTINE vecpush_stack
+
+
+FUNCTION pop_stack() RESULT(c)
+implicit none
+character(len=maxvarlen) :: c
+TYPE(stackdb_t), POINTER :: this
+this => tail
+if (associated(this) .and. stack_size > 0) then
+  c = this%name
+  this => tail%prev
+  deallocate(tail)
+  tail => this
+  stack_size = stack_size - 1
+else
+  c = ' '
+endif
+END FUNCTION pop_stack
+
+END MODULE stackdb
diff --git a/odb/src/module/str.F90 b/odb/src/module/str.F90
new file mode 100644
index 0000000..bb04be6
--- /dev/null
+++ b/odb/src/module/str.F90
@@ -0,0 +1,4 @@
+MODULE str
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+USE strhandler_mod  ! From IFSAUX
+END MODULE str
diff --git a/odb/src/p4sync b/odb/src/p4sync
new file mode 100755
index 0000000..e480e51
--- /dev/null
+++ b/odb/src/p4sync
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+
+""" Script to sync sources between Git and P4 repositories.
+
+To use this script you will first need to create a .p4config file in the directory that
+you want to keep in sync with P4.
+
+Here is an example of .p4config file for ODB project:
+
+P4CLIENT=client_datk_CY41R2_odb_develop
+P4PORT=p4rd:14000
+P4PROJECT=odb
+
+"""
+
+import os
+import re
+import sys
+import optparse
+import logging
+import difflib
+import filecmp
+
+from P4 import P4, P4Exception
+
+def gather(source_dir):
+    """ Walk through all sub-directories of source_dir and return a flat list of all files.
+    """
+    source_files = []
+    for path, dirs, files in os.walk(source_dir):
+        for file in files:
+            file = os.path.join(path, file)
+            source_files.append(os.path.relpath(file, source_dir))
+    return source_files
+
+def match(local_files, remote_files, repository):
+    matched_files = []
+    for file in (local_files & remote_files):
+        remote = os.path.join(repository, file)
+        pair = (file, remote)
+        matched_files.append(pair)
+    return matched_files
+
+def copy(source, target):
+    """ Copies content of the source file into the target
+    """
+    with open(source) as s, open(target, "w") as t:
+        t.write(s.read())
+
+def newer(this, that):
+    """ Returns true if this is newer than that
+    """
+    mtime = lambda x: os.path.getmtime(x)
+    if mtime(this) > mtime(that): 
+        with open(this) as a, open(that) as b:
+            if a.read() != b.read():
+                return True
+    return False
+
+def fetch(matched_files):
+    """ Fetch remote changes from P4 client (but do not commit).
+    """
+    count = 0
+    for local, remote in matched_files:
+        if filecmp.cmp(remote, local, shallow=False) or os.path.islink(remote):
+            continue
+        copy(remote, local)
+        sys.stdout.write("fetch: %s => %s\n" % (remote, local))
+        count += 1
+    return count
+
+def diff(matched_files):
+    count = 0
+    for this, that in matched_files:
+        with open(this) as a, open(that) as b:
+            if a.read() != b.read():
+                a.seek(0)
+                b.seek(0)
+                changes = difflib.unified_diff(a.readlines(), b.readlines(),
+                    fromfile=this, tofile=that)
+                sys.stdout.write("".join(changes))
+                count += 1
+    return count
+
+def push(p4, matches):
+    """ Push local changes to P4 client (but do not submit).
+    """
+    count = 0
+    for local, remote in matches:
+        if filecmp.cmp(local, remote, shallow=False) or os.path.islink(local):
+            continue
+        p4.run("edit", os.path.relpath(remote, p4.cwd))
+        copy(local, remote)
+        sys.stdout.write("push: %s => %s\n" % (local, remote))
+        count += 1
+    return count
+
+def p4_config():
+    """ Return path to .p4config file if found, otherwise returns None.
+    """
+    head = tail = os.path.abspath(".")
+    while tail:
+        file = os.path.join(head, ".p4config")
+        if os.path.exists(file):
+            return file
+        head, tail = os.path.split(head)
+    return None
+
+def main():
+
+    parser = optparse.OptionParser()
+    parser.usage = "%prog fetch|push|ls-files|diff"
+    parser.add_option("-c", "--client", help="use specific P4 client", metavar="P4CLIENT")
+    parser.add_option("-v", "--verbose", action="store_true", default=False, help="be verbose")
+    opts, args = parser.parse_args()
+
+    if len(args) < 1:
+        parser.error("Invalid number of arguments\n\n")
+
+    command = args.pop(0)
+
+    if not command in ("fetch", "push", "ls-files", "diff"):
+        parser.error("Invalid command: %s\n" % command)
+
+    level = logging.WARNING
+    if opts.verbose:
+        level = logging.INFO
+    logging.basicConfig(level=level, format="%(message)s")
+
+    config = p4_config()
+
+    if config is None:
+        sys.stderr.write("Could not find .p4config file.\n")
+        sys.stderr.write("You will need to create this file in a directory that you want to sync with P4.\n")
+        sys.exit(1)
+
+    p4 = P4()
+    p4.user = os.getenv("USER")
+    p4_project = None
+
+    with open(config) as file:
+        logging.info("Reading P4 config file: %s" % config)
+        for line in file:
+            key, value = line.strip().split("=")
+            if key == "P4CLIENT":
+                p4.client = value
+            elif key == "P4PORT":
+                p4.port = value
+            elif key == "P4PROJECT":
+                p4_project = value
+
+    # Override the P4 client if required
+    if opts.client:
+        p4.client = opts.client
+
+    logging.info("Connecting to P4 client %s at port %s" % (p4.client, p4.port))
+    p4.connect()
+    info = p4.run("info")
+    p4.cwd = info[0]["clientRoot"]
+    logging.info("P4 client root: %s" % p4.cwd)
+
+    p4_project_dir = os.path.join(p4.cwd, p4_project)
+    if not os.path.exists(p4_project_dir):
+        sys.stderr.write("Please add %s project to your P4 branch %s\n" % (p4_project, p4.client))
+        sys.exit(1)
+
+    # Generate a list of all local Git files and remote P4 files and match them up.
+
+    local_dir, _ = os.path.split(config)
+    local_files = set(gather(local_dir))
+    remote_files = set(gather(p4_project_dir))
+    matched_files = match(local_files, remote_files, p4_project_dir)
+
+    if command == "ls-files":
+        for pair in matched_files:
+            sys.stdout.write(" %s <=> %s\n" % pair)
+
+    elif command == "diff":
+        if len(args) != 0:
+            matched_files = filter(lambda x: x[0] in args, matched_files)
+        if diff(matched_files) == 0:
+            sys.stdout.write("No differencies, all files up to date.\n")
+
+    elif command == "fetch":
+        if len(args) != 0:
+            function = lambda x: os.path.basename(x[1]) in args
+            matched_files = filter(function, matched_files)
+        if fetch(matched_files) == 0:
+            sys.stdout.write("Nothing to fetch, all files up to date.\n")
+
+    elif command == "push":
+        if len(args) != 0:
+            matched_files = filter(lambda x: x[0] in args, matched_files)
+        if push(p4, matched_files) == 0:
+            sys.stdout.write("Nothing to push, all files up to date.\n")
+
+if __name__ == "__main__": main()
+
diff --git a/odb/src/scripts/.odb_deprecated.sh b/odb/src/scripts/.odb_deprecated.sh
new file mode 100755
index 0000000..73584ba
--- /dev/null
+++ b/odb/src/scripts/.odb_deprecated.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+set -ue
+
+script=${0//*\//}
+tool=$(echo $script | sed 's/\(odb_\|odb\)//')
+
+case $tool in
+    to_request)
+        usage="odb oda2request $@"
+        ;;
+    dump)
+        usage="odb sql \* -i $@"
+        ;;
+    count|header|set|split)
+        usage="odb $tool $@"
+        ;;
+    *)
+        usage="odb$tool $@"
+        ;;
+esac
+
+echo "error: Wrapper script '$script' has been deprecated. Please use the following command: $usage" 1>&2
+exit 1
+
diff --git a/odb/src/scripts/.odb_serial_wrapper.sh.in b/odb/src/scripts/.odb_serial_wrapper.sh.in
new file mode 100755
index 0000000..158e069
--- /dev/null
+++ b/odb/src/scripts/.odb_serial_wrapper.sh.in
@@ -0,0 +1,19 @@
+#!/usr/bin/env ksh
+
+# Wrapper script allowing to run MPI executables as serial programs
+
+set -e
+
+if echo $0 | grep -q ".x$"; then
+  mpi_prog=${0%.*}mp.x
+else
+  mpi_prog=${0}mp
+fi
+
+sanitized_args=$(echo $@ | sed 's/\$/\\$/g')
+
+if [[ -n $ENV_RUN_PARALLEL || -n $OMPI_COMMAND ]]; then
+  eval $mpi_prog $sanitized_args
+else
+  eval @MPIEXEC@ -n 1 $mpi_prog $sanitized_args
+fi
diff --git a/odb/src/scripts/CMakeLists.txt b/odb/src/scripts/CMakeLists.txt
new file mode 100644
index 0000000..b93707e
--- /dev/null
+++ b/odb/src/scripts/CMakeLists.txt
@@ -0,0 +1,88 @@
+configure_file(use_odb.csh.in ${CMAKE_BINARY_DIR}/bin/use_odb.csh @ONLY)
+configure_file(use_odb.sh.in ${CMAKE_BINARY_DIR}/bin/use_odb.sh @ONLY)
+
+install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/use_odb.csh DESTINATION bin)
+install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/use_odb.sh DESTINATION bin)
+
+if(HAVE_ODB_MPI AND HAVE_ODB_MPI_SERIAL_WRAPPERS)
+  if(NOT MPIEXEC) # FIXME: MPIEXEC is not set on Cray, assuming mpiexec for now
+    set(MPIEXEC mpiexec)
+  endif()
+  configure_file(.odb_serial_wrapper.sh.in ${CMAKE_BINARY_DIR}/bin/.odb_serial_wrapper.sh @ONLY)
+  install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/.odb_serial_wrapper.sh DESTINATION bin)
+endif()
+
+list(APPEND _odb_scripts
+
+    check_links
+    create_index
+    create_ioassign
+    create_odbglue
+    create_static_stubb
+    dcafix
+    dcagen
+    dcaquick
+    latlon_rad
+    latlonrad
+    makegp.ksh
+    newodb
+    odb1to4
+    odb4to1
+    odb_1to4
+    odb_4to1
+    odb_cat
+    odb_compress
+    odb_diff
+    odb_dup
+    odb_gnuplot
+    odb_less
+    odb_merge
+    odb_more
+    odb_prune
+    odbc++
+    odbcat
+    odbcc
+    odbclean
+    odbcomp
+    odbcompress
+    odbdiff
+    odbdup
+    odbf90
+    odbf90mp
+    odbgnuplot
+    odbless
+    odbmerge
+    odbmore
+    odbprune
+    odbsql
+    test_arch
+
+    # DEPRECATED: wrapper scripts for odb-api tools
+
+    .odb_deprecated.sh
+    odb_count
+    odb_dump
+    odb_header
+    odb_set
+    odb_split
+    odb_to_request
+    odbcount
+    odbdump
+    odbheader
+    odbset
+)
+
+if(ODB_SERVER_CLIENT)
+  list(APPEND _odb_scripts
+    askodb
+    odbi_proxy
+    odbi_show_server
+    odbi_start_server
+    odbi_stop_server)
+endif()
+
+install(PROGRAMS ${_odb_scripts} DESTINATION bin)
+
+foreach(script ${_odb_scripts})
+    configure_file(${script} ${CMAKE_BINARY_DIR}/bin COPYONLY)
+endforeach()
diff --git a/odb/src/scripts/DEPRECATED b/odb/src/scripts/DEPRECATED
new file mode 100644
index 0000000..b66122e
--- /dev/null
+++ b/odb/src/scripts/DEPRECATED
@@ -0,0 +1,14 @@
+create_ioassign => odb_create_ioassign NOTE: used, differs from IFS scripts, which one is up to date?
+create_odbglue => odb_create_glue NOTE: used, differs from IFS scripts, which one is up to date?
+create_static_stubb      NOTE: used, differs from IFS scripts version
+mpif.h
+mpif.h.necsx.BoM
+mpif.h.necsx5.CSCS
+shp2txt.pl
+test_arch          NOTE: used by many tools: odbsql, odbf90, odbviewer, etc.
+where_fiddle.pl    NOTE: used by odbdiff tool
+
+client/server functionality
+---------------------------
+odb/tools/odbversion.c is only used to set environment variables: ODB_VERSION_ID, ODB_MAJORVN, ODB_MINORVN
+and those are only used in the script askodb
diff --git a/odb/src/scripts/askodb b/odb/src/scripts/askodb
new file mode 100755
index 0000000..3245ce4
--- /dev/null
+++ b/odb/src/scripts/askodb
@@ -0,0 +1,938 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 123' 1 2 3 15
+# Save current fd#1 (stdout) to #3
+exec 3>&1
+# Save current fd#2 (stderr) to #4
+exec 4>&2
+# Redirect globally stdout (#1) to stderr (#2)
+exec 1>&2
+#begin
+#
+# askodb -- A utility to launch ODB data queries away from database directory, 
+#           so that multiple users can share the same database. Database
+#           can reside on a remote machine, but then server-process will be created (if not already running)
+#
+# Options:				Description and defaults
+# --------				------------------------
+#
+#	-F				Do *not* use the new & fast 'odbsql' (the default is to use 'odbsql')
+#	-C				Use this when askodb is invoked from c/s software, not directly
+#	-b format			The actual data is returned in binary mode (the default is text-mode)
+#                                       The default format is "inary" or "binary" or "normal", obtained via:
+#                                       -binary or -b binary or -b normal
+#                                       Format NetCDF f.ex. can be returned via -b netcdf
+#       -O output_file_name             Output file name (default: /dev/null)
+#	-B bufsize			Buffer size for retrieval, in double's (default=max(ncols,1000))
+#	-c				Automatic (re-)compilation & cleaning, if necessary
+#	-D				Return data only (i.e. as from ODBI_fetch_row_array())
+#	-f sqlfile[.sql|.so] 		SQL-query file; by default=myview (use .so-sfx to avoid recompilation)
+#	-h				Help! Displays this output
+# 	-H {host[:port]|[host]:port}	Reserved for client/server. Denotes server hostname & port
+#	-i database_dir		        Database directory. No defaults
+# 	-i [host:]database_dir		Database directory on the target (host) machine
+#	-k				Keep all temporary stuff in workdir (default: do NOT keep)
+#	-l [start_row,]maxrows		Limit option. Returns only maxrows, starting from output row start_row
+#	-m				Return database level (tables, set-vars, etc.) metadata only, no data
+#	-N                              In text-mode do not print NULL's, but the value of missing data
+#	-o working_directory		Working directory. Determined from database_dir
+#	-p poolmask			Which pools to scan (by default all pools included)
+#	-P port				Port number for client/server
+#	-r                              Re-execute the program without any recompilations
+#	-q 'sql_query_string'		Data query string (default: <empty> and -f sqlfile takes precedence)
+#	-t [@]table_name                Data query string will be 'SELECT * FROM table_name'. You can omit the '@'.
+#	-s 			        Run in silent mode i.e. suppress all irrelevant output
+#	-S			        Show row numbers in text-mode output
+#	-T timeout			Timeout value for C/S communications to avoid hanging (default:3600 sec)
+#	-U use_application		Runs 'use applic'; can be supplied many times; say -U pgf90 for 'use pgf90'
+# 	-u username			Changes the default username
+#	-v 				Be just a little more verbose while running the askodb-script
+#	-V '$var1=1.5; var2=2.3'	Overrides $-variable defaults; The '$' can be omitted.
+#	-x specific_executable_name	Use specific executable (found & already created under $workdir)
+#	-5				Abandon fast ODB data access (i.e. do NOT use I/O-method 5 => high memory usage)
+#	-n numeric_odb_version		Clients 'odb_version -numeric'
+#	-# ncpus[.nchunk]		Parallelism (and pool-chunking) for server process (default: ncpus=1)
+#	-g debugger			Run under debugger
+#	--				The query will be read from standard input
+#       [dbname]			ODB-database name (usually figured out from the '-i' option)
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, Sep/Oct-2004
+#
+# Modifications:
+#  Sami Saarinen, ECMWF, 25-Apr-2007 : dbname figured out from datapath for client/server -runs, too
+#  Sami Saarinen, ECMWF, 05-Dec-2007 : datapath can contain wildcards [given in quotes], since odbmerge is performed
+#  Sami Saarinen, ECMWF, 13-Dec-2007 : datapath can contain odb://hostname[:port]/path
+# 
+
+set +xv
+set -eu
+
+devnull=/dev/null
+
+thisdir=$(\cd .; echo $(pwd))
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+export DR_HOOK=0
+export DR_HOOK_SHOW_PROCESS_OPTIONS=${DR_HOOK_SHOW_PROCESS_OPTIONS:=0}
+export DR_HOOK_SILENT=${DR_HOOK_SILENT:=1}
+export EC_SORTING_INFO=0
+
+export ARCH=${ARCH:=unknown}
+
+test_arch=$(test_arch 2>$devnull || echo "$ARCH")
+
+export USER=${USER:=$(id -un)}
+
+export TMPDIR=${TMPDIR:=/tmp}
+
+FLAGS="#:b:B:cCDf:Fg:hH:i:kl:mn:No:O:p:P:rq:sSt:T:u:U:vV:x:5-"
+
+prog=odbi_direct_main
+
+objs="$prog.o"
+
+fast=1                  # fast=0 when -F is given
+fastopt=""
+fastquery=""
+numeric_odb_version=0   # Override with -n `odbversion -numeric`
+binary=0
+format=normal
+binmode=""		# -binary
+bufsize="-B 1000"	# -B bufsize
+compile=0		# -c
+clean_too=0		# (cleaning takes place only if -c is supplied explicitly)
+data_only=""		# -D
+data_only_given=0	# (a flag to see whether -D was given; to disable possible -m)
+viewname=myview		# -f viewname[.so]
+relink=0		# (need for re-linking decided on-the-fly)
+abort=no		# -h (help option => activated by setting abort=yes)
+hostport=""		# -H host[:port] or -H [host]:port or -P port)
+cliserv=0		# (flag whether -H option was used or -i host:/data/path was given)
+datapath="."		# -i datapath (the default current dir)
+dbname=""		# (figured out from .dd-file in datapath or from the last parameter)
+keep=0			# -k
+limit=""		# -l 100 alias -l 1,100 (or -l 200,10)
+metadata=""		# -m
+request_metadata=0	# (set to 1, if -m given)
+nulls=""		# -N
+workdir=""		# -o workdir
+poolmask=""		# -p 1-10 -p 12,13 -p "15-17,20"
+#defport=11998		# -P default_port
+defport=$(id -u | awk '{print $1%10000 + 10000}') # -P default_port=mod(uid,10000)+10000
+query=""		# -q 'select x,y from t1,t2 where $x > 2'
+query_given=0		# (to record whether -q option was given)
+reexec=0		# -r
+silent=0		# -s
+showrows=""		# -S
+timeout=3600		# -T 100
+user=$USER		# -u username
+use_appl=""		# -U pgf90
+is_verbose=0		# -v
+varvalue=""		# -V '$var = value'
+varargs=""		# (filled at the end based on $varvalue(s))
+my_a_out=""		# -x executable_file
+my_a_out_given=0	# (stems from the previous)
+io_method=5		# -5  (to turn *off* the fast I/O-method 5)
+stdin=0			# --
+debugger=""		# -g debugger
+ncpus=1                 # -# ncpus[.nchunk]
+outfil=$devnull         # -O output_file
+csopt=""                # -C
+
+while getopts ${FLAGS} i
+do
+  case $i in
+	b)	format="$OPTARG"; binmode="-b $format"; binary=1 ;;
+	B)	bufsize="-B $OPTARG";;
+	c)	compile=1; clean_too=1;;
+	C)	csopt="-C";;
+	D)	data_only="-D"; data_only_given=1;;
+	f)	viewname="$OPTARG";;
+	F)	fast=0; fastopt="-F";;
+	g)	debugger="$OPTARG";;
+	h)	abort=yes;;
+	H)	hostport="$OPTARG"; cliserv=1;;
+	i)	datapath="$OPTARG";;
+	k)	keep=1;;
+	l)	limit="$OPTARG";;
+	m)	metadata="-m"; request_metadata=1;;
+	n)	numeric_odb_version="$OPTARG";;
+	N)	nulls="-N";;
+	o)	workdir="$OPTARG";;
+	O)	outfil="$OPTARG";;
+	p)	poolmask="$poolmask $OPTARG";;
+	P)	defport="$OPTARG";;
+	q)	query="$OPTARG"; query_given=1;;
+	r)	reexec=1;;
+	s)	silent=1;;
+	S)	showrows="-S";;
+	T)	timeout="$OPTARG";;
+	t)	typeset tbl=$(echo "$OPTARG" | perl -pe 's/^\s*(\@)?//'); query="SELECT * FROM $tbl"; query_given=1;;
+	u)	user="$OPTARG";;
+	U)	use_appl="$use_appl $OPTARG";;
+	v)	is_verbose=1;;
+	V)	varvalue="$OPTARG ; $varvalue";;
+	x)	my_a_out="$OPTARG";;
+	5)	io_method=-1;; # Setting this to a <=0 value will ensure I/O-method 5 will NOT be used
+                               # If > 0, there is an automatic test for READ/ONLY databases, whether ./dca
+                               # directory exists. But keeping I/O-method <= 0 bypasses this testing
+	-)	stdin=1;;
+	\#)	ncpus="$OPTARG";;
+	\?)	abort=yes; break;;
+  esac
+done
+
+#set -x
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  dbname=$1
+  shift
+fi
+
+if [[ $stdin -eq 1 ]] ; then
+  query="$(\cat);"
+  query_given=1
+fi
+
+if [[ $silent -eq 1 ]] ; then
+# You asked for silence, you've got it!
+# Closing stdout & stderr
+  exec 1>$devnull
+  exec 2>$devnull
+  zailenz="-s"
+else
+  zailenz=""
+fi
+
+if [[ $# -gt 0 ]] ; then
+  echo "***Error: Too many args. The not understood were : $*" >&4
+  abort=yes
+fi
+
+if [[ "$datapath" = "" ]] ; then
+  echo "***Error: Database path not given. Use -i option" >&4
+  abort=yes
+fi
+
+#-- Handle $-variables
+
+if [[ "$varvalue" != "" ]] ; then
+  varargs=$(echo "$varvalue" | \
+            perl -pe 's/\s+//g; s/\$//g; s/^/;/; s/;(\w+=\w+)/ -V $1\n/g; s/\n//g; s/;/ /g; s/\s+/ /g')
+fi
+
+#-- Check limit
+
+if [[ "$limit" != "" ]] ; then
+  limit=$(echo "$limit" | perl -pe 's/^(,|\d+\s*$)/1 $1/; s/,/ /g; s/^\s+//; s/\s+$//; s/\s+/,/')
+  limit="-L $limit"
+fi
+
+#-- Check the mutually exclusive requests
+
+if [[ $request_metadata -eq 1 && $data_only_given -eq 1 ]] ; then
+  request_metadata=0
+  metadata=""
+fi
+
+# Detect if client/server from datapath (unless -H already given)
+
+# Prune datapath & hostport if contains odb://host[:port]/path
+odbslsl=$(echo "$datapath" | cut -c1-6)
+if [[ "$odbslsl" = "odb://" ]] ; then
+  datapath=$(echo "$datapath" | perl -pe 's|^odb://||')
+  # overwrite $hostport, since it takes now precedence
+  hostport=$(echo "$datapath" | awk -F/ '{print $1}')
+  datapath=$(echo "$datapath" | perl -pe 's|^.*?/|/|')
+  cliserv=1
+fi
+
+# Create host & port
+host=""
+port=$defport
+
+nargs=$(echo "$datapath" | awk -F: '{print NF}')
+if [[ $cliserv -eq 0 ]] ; then
+  if [[ $nargs -eq 2 ]] ; then
+    cliserv=1
+    host=$(echo "$datapath" | awk -F: '{print $1}')
+    datapath=$(echo "$datapath" | sed 's/^.*://')
+  fi
+else
+  if [[ $nargs -eq 2 ]] ; then
+    host=$(echo "$datapath" | awk -F: '{print $1}')
+    datapath=$(echo "$datapath" | sed 's/^.*://')
+  fi
+  ahost=$(echo "$hostport" | awk -F: '{print $1}')
+  aport=$(echo "$hostport" | awk -F: '{print $2}')
+  if [[ "$ahost" != "" ]] ; then
+    host=$ahost # takes precedence
+  fi
+  if [[ "$aport" != "" ]] ; then
+    port=$aport
+  fi
+fi
+
+if [[ $cliserv -eq 1 && "$host" = "" ]] ; then
+  host="localhost"
+fi
+
+if [[ $cliserv -eq 1 ]] ; then
+  #-- check if the "$host" and `hostname` are in fact the same ;-)
+  host_ip_addr=$($ODB_FEBINPATH/odbi_host.x "$host" || echo "$host")
+  hostname=$(hostname) 
+  hostname_ip_addr=$($ODB_FEBINPATH/odbi_host.x "$hostname" || echo "$hostname")
+  if [[ $host_ip_addr = $hostname_ip_addr ]] ; then
+    cliserv=0 # switch off the client/server-approach and use local dadabaaz-approach (faster)
+  fi
+fi
+
+if [[ $abort = no && $cliserv -eq 1 ]] ; then 
+#
+# resolve host IP-address for convenience (obsolete; resolve done by the client):
+#  is_ipv4=$(echo "$host" | awk -F. '{print NF}')
+#  if [[ "$host" = localhost ]] || [[ "$host" = "$(hostname)" ]] ; then
+#    host="127.0.0.1"
+#  elif [[ "$is_ipv4" != "4" ]] ; then
+#    nonexist=$(nslookup -timeout=1 $host < $devnull 2>&1 | grep "Non-existent" | sed 's/^.*\(Non-existent\).*$/\1/')
+#    if [[ "$nonexist" = "" ]] ; then
+#      host=$(nslookup -timeout=1 $host < $devnull |\
+#             egrep "^Address:" | perl -pe 's/^\s*\n//; s/^[>].*$//' | tail -1 | awk '{print $2}')
+#    else
+#      echo "***Error: IP-address for host '$host' does not exist. Check your -H or -i option(s)" >&4
+#      abort=yes
+#    fi
+#  fi
+#
+  if [[ "$dbname" = "" && "$datapath" != "" ]] ; then
+    dbname=$(basename "$datapath" | perl -pe 's/\..*//; tr/a-z/A-Z/')
+  fi
+
+  if [[ "$dbname" = "" ]] ; then
+    echo "***Error: Database name must be given explicitly in client/server-runs" >&4
+    abort=yes
+  fi
+fi
+
+#-- Prune poolmask
+
+if [[ $abort = no ]] ; then
+  if [[ "$poolmask" != "" ]] ; then
+    poolmask=$(echo "$poolmask" | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  else
+    poolmask=$(echo "$poolmask" | perl -pe 's/^\s*,//')
+  fi
+fi
+
+#----------------------------------------------------------------------------#
+# Branch off to the client/server-world and never return back to this script #
+#----------------------------------------------------------------------------#
+
+if [[ $abort = no && $cliserv -eq 1 ]] ; then
+  prog=$ODB_FEBINPATH/odbi_client.x
+# the following works too; even if -i & -H not given
+  cmd="$prog -l $dbname -H $host -P $port -T $timeout -Oclihost=$(hostname)"
+  cmd="$cmd $binmode -f $outfil $data_only $bufsize"
+  cmd="$cmd $nulls $limit $showrows $varargs $metadata"
+  [[ "$poolmask" = ""  ]] || cmd="$cmd -p $poolmask"
+  [[ $is_verbose -eq 0 ]] || cmd="$cmd -Overbose"
+  [[ $clean_too  -eq 0 ]] || cmd="$cmd -Oclean"
+  [[ $keep       -eq 0 ]] || cmd="$cmd -Okeep"
+  [[ $fast       -eq 1 ]] || cmd="$cmd -Onoodbsql"
+  [[ $ncpus      -le 1 ]] || cmd="$cmd -# $ncpus"
+  if [[ $silent -eq 1 ]] ; then
+    cmd="$cmd -Osilent"
+  else
+    cmd="$cmd -Onosilent"
+  fi
+  [[  $io_method -eq  5  ]] || cmd="$cmd -Oio_method=$io_method"
+  cmd="$cmd -Ouser=$user"
+  [[ "$my_a_out" = "" ]] || cmd="$cmd -Oexe=$my_a_out"
+  [[ "$workdir"  = "" ]] || cmd="$cmd -Oworkdir=$workdir"
+  if [[ $request_metadata -eq 1 ]] ; then
+    viewname="@" # A dummy table
+    cmd="$cmd -v $viewname"
+  else
+    sqldir=$(dirname $viewname)
+    sfx=$(basename $viewname | perl -ne 'print $1 if (/.*(\.\w+)/);')
+    viewname=$(basename $viewname | perl -pe 's/\..*//; tr/A-Z/a-z/')
+    is_table=$(echo $viewname | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+    if [[ $is_table -eq 1 ]] ; then
+      cmd="$cmd -v $viewname"
+      query_given=0
+    elif [[ "$sfx" = ".so" ]] ; then
+      cmd="$cmd -v $viewname.so"
+      query_given=0
+    else
+      sqlfile=$viewname.sql
+      sqldir=$(\cd $thisdir; \cd $sqldir; pwd)
+      if [[ $query_given -eq 0 && -r $sqldir/$sqlfile ]] ; then
+        query="$(cat $sqldir/$sqlfile);"
+        query_given=1
+      fi
+      if [[ $query_given -eq 1 ]] ; then
+        cmd="$cmd -v $viewname"
+      fi
+    fi
+  fi
+  if [[ $query_given -eq 1 ]] ; then
+    thecmd="$cmd -q '$query' -i '$datapath'"
+  else
+    thecmd="$cmd -i '$datapath'"
+  fi
+  [[ $is_verbose -eq 0 ]] || echo "$thecmd" | perl -pe 's/\s+/ /g; s/$/\n/;' >&4
+
+  #-- Redirect stdout back to its original state (#1) and close the temporary fd#3
+  #   (stderr still flows as usual to #2, unless silenced with -s)
+  exec 1>&3
+  exec 3>$devnull
+
+  #-- Run the extraction 
+  # (output comes to stdout; errors still go to stderr, unless silenced with -s)
+
+  if [[ $silent -eq 1 ]] ; then
+    exec 2>&4
+  fi
+  
+  rc=0
+  if [[ $query_given -eq 1 ]] ; then
+  #-- have to do this way for now, since the shell eats -q '$query' if embedded in the $cmd ;-(
+    exec $cmd -q "$query" -i "$datapath" || rc=$?
+  else
+    exec $cmd -i "$datapath" || rc=$?
+  fi
+
+  #-- Should never endup hier ...
+
+  if [[ $rc -ne 0 ]] ; then
+    echo "***Error(s) were encountered in your client/server-run (rc=$rc):" >&4
+    echo "$thecmd" >&4
+    exit $rc
+  fi
+  exit 0
+fi
+
+#----------------------------------------------------------------------------#
+
+#-- Create composite database by using odbmerge (odbdup)
+if [[ "$dbname" = "" ]] ; then
+  #-- Firstly; extract dbname, if not given :
+  dbname=$(basename "$datapath" | perl -pe 's/\..*//; tr/a-z/A-Z/')
+fi
+
+#-- The "mtimecnt" tries to trace whether input database(s) crucial metadata has changed,
+#   indicating potential changes in the data itself;
+#   We could have 'ls -C1sR' through the datapath(s) to calculate the sum of file sizes;
+#   this could however be potentially very, very time consuming for large amount of files;
+#   Even now the count of dca-files could be big
+
+mtimecnt="0.0"
+new_datapath=""
+
+for d in $datapath
+do
+  if [[ ! -d $d ]] ; then
+    typeset f
+    for f in $d $d.dd $d.sch
+    do
+      if [[ -f $f ]] ; then
+        d=$(dirname $f)
+        break
+      fi
+    done
+  fi
+  if [[ -d $d ]] ; then
+    new_datapath="${new_datapath}$d "
+    mtimecnt=$(echo "$mtimecnt" | $ODB_FEBINPATH/odbfiletime.x $d/*.dd $d/*.iomap $d/dca $d/dca/*.dca 2>$devnull || echo "$mtimecnt")
+  fi
+done
+
+datapath=$(echo "$new_datapath" | perl -pe 's/\s+$//')
+
+if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+  # Prefer to use RAM-disk (/dev/shm) when available
+  dupdir=/dev/shm
+elif [[ -d "$TMPDIR" ]] ; then
+  dupdir=$TMPDIR
+else
+  dupdir=/tmp
+fi
+
+#-- New (or existing -- for multiple runs) datapath
+
+ddtag=$($ODB_FEBINPATH/odbmd5sum -D"$datapath")
+
+dbpath=${dupdir}/askodb.$USER/$dbname.$ddtag.$mtimecnt
+
+if [[ $clean_too -eq 1 && -d $dbpath ]] ; then
+  rm -rf $dbpath    
+fi
+
+if [[ ! -d "$dbpath" ]] ; then
+  if [[ "$mtimecnt" = "0.0" ]] ; then
+    echo "***Error: Input datapath '$datapath' contains no ODB metadata" >&4
+    abort=yes
+  else
+    odbmerge -i "$datapath" -o $dbpath -l $dbname $zailenz >&4 || {
+      echo "***Error: Cannot 'odbmerge' '$datapath' into '$dbpath' ; dbname='$dbname'" >&4
+      abort=yes
+    } 
+  fi
+  if [[ $abort = no ]] ; then
+    echo "$datapath" > $dbpath/.datapath
+  fi
+fi
+
+if [[ $abort = no ]] ; then
+  datapath="$dbpath"
+fi
+
+if [[ "$datapath" != "" && ! -d "$datapath" ]] ; then
+  datapath=$(dirname "$datapath" || :)
+  if [[ ! -d "$datapath" ]] ; then
+    echo "***Error: Invalid database path '$datapath'. Check your -i option" >&4
+    abort=yes
+  fi
+fi
+
+if [[ "$dbname" = "" && -d "$datapath" ]] ; then
+  cd "$datapath"
+  rc=0
+  \ls -C1 *.dd >$devnull 2>&1 || rc=$?
+  if [[ $rc -eq 0 ]] ; then
+    dbname=$(\ls -C1 *.dd 2>$devnull | head -1)
+    dbname=$(basename $dbname .dd)
+  else
+    echo "***Error: Cannot locate any metadata files '*.dd' under $datapath" >&4
+    abort=yes
+  fi
+  cd $thisdir
+  datapath=$(\cd "$datapath"; pwd)
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Invalid database '$dbname'. Check -i option and existence of <dbname>.dd file" >&4
+  abort=yes
+fi
+
+#-- Abort, if necessary
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&4
+  exit 1
+fi
+
+#-- Set poolmask related env. variable
+
+if [[ "$poolmask" != "" ]] ; then
+  export ODB_PERMANENT_POOLMASK_$dbname="$poolmask"
+fi
+
+#-- Run use-commands (check, whether your environment has 'use'-command at all!)
+
+if [[ "$use_appl" != "" ]] ; then
+  set +eu
+  for u in $use_appl
+  do
+    use $u >$devnull 2>&1
+  done
+  set -eu
+fi
+
+#*** Check if the fast option will be used --> revert to odbsql
+
+if [[ $fast -eq 1 ]] ; then
+
+  a_out="$ODB_FEBINPATH/odbi_direct.x"  
+
+  if [[ $request_metadata -eq 1 ]] ; then
+    viewname="@" # A dummy table
+    cmd="$cmd -v $viewname"
+  else
+    sqldir=$(dirname $viewname)
+    sfx=$(basename $viewname | perl -ne 'print $1 if (/.*(\.\w+)/);')
+    viewname=$(basename $viewname | perl -pe 's/\..*//; tr/A-Z/a-z/')
+    is_table=$(echo $viewname | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+    if [[ $is_table -eq 1 ]] ; then
+      query_given=0
+    else
+      sqlfile=$viewname.sql
+      sqldir=$(\cd $thisdir; \cd $sqldir; pwd)
+      if [[ $query_given -eq 0 && -r $sqldir/$sqlfile ]] ; then
+        query="$sqldir/$sqlfile"
+        query_given=2
+      fi
+    fi
+  fi
+
+  if [[ $query_given -ge 1 ]] ; then
+    fastquery="$query"
+  else
+    fastquery=""
+  fi
+
+  export ODB_SRCPATH_$dbname=$datapath
+  export ODB_DATAPATH_$dbname=$datapath
+  export ODB_IDXPATH_$dbname=$datapath/idx
+  export ODB_IO_METHOD=5
+
+  #-- Make sure dca-indices are ok
+  if [[ -d $datapath/dca ]] ; then
+    if [[ ! -f $datapath/dca/.dcafixed ]] ; then
+      dcafix -q -i $datapath >&4
+    fi
+  else
+    dcagen -q -z -n -i $datapath >&4
+  fi
+
+else
+
+  fastopt="-F"
+
+  #-- In to the business
+
+  slash2dot="askodb.$user.CY${ODB_MAJORVN}R${ODB_MINORVN}.$test_arch$(echo $datapath | sed 's%/%\.%g')"
+  if [[ "$workdir" = "" ]] ; then
+    defscr=$TMPDIR
+    if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+      # check available capacity of the local Linux Ramdisk
+      capakb=$(df -kl /dev/shm 2>$devnull | tail -1 | awk '{print $4}')
+      if [[ $capakb -gt 40960 ]] ; then # more than 40MBytes
+        defscr=/dev/shm
+      fi
+    fi
+    workdir=$defscr
+  fi
+  workdir=$workdir/$slash2dot
+
+  if [[ $clean_too -eq 1 && -d $workdir ]] ; then
+    [[ $is_verbose -eq 0 ]] || echo "Cleaning $workdir" >&4
+    rm -rf $workdir
+  fi
+  
+  if [[ ! -d $workdir ]] ; then
+    [[ $is_verbose -eq 0 ]] || echo "Creating $workdir" >&4
+    mkdir -p $workdir
+    compile=1
+  fi
+  [[ $is_verbose -eq 0 ]] || echo "cd $workdir" >&4
+  cd $workdir
+  
+  export ODB_SRCPATH_$dbname=$workdir
+  export ODB_DATAPATH_$dbname=$datapath
+  export ODB_IDXPATH_$dbname=$workdir/idx
+  
+  # but *not* IOASSIGN 
+  for sfx in dd sch flags iomap
+  do
+    if [[ -f $datapath/$dbname.$sfx ]] ; then 
+      if [[ ! -f $dbname.$sfx ]] || \
+         [[ $datapath/$dbname.$sfx -nt $dbname.$sfx ]] ; then
+        cp $datapath/$dbname.$sfx .
+        chmod u+w $dbname.$sfx
+      fi
+    fi
+  done
+  
+  ddfile=$dbname.dd
+  
+  if [[ ! -f $ddfile ]] ; then
+    echo "***Error: The main metadata file '$ddfile' not found" >&4
+    exit 1
+  fi
+  
+  #-- Create fresh IOASSIGN
+  
+  if [[ ! -f $dbname.IOASSIGN ]] ; then
+    create_ioassign -l $dbname -q
+    export IOASSIGN=$dbname.IOASSIGN
+  fi
+  
+  #-- Determine need for recompilation of data layout
+  
+  if [[ $compile -eq 0 ]] ; then
+    if [[ ! -f lib$dbname.a ]] || \
+       [[ ! -f $dbname.ddl_ ]] || \
+       [[ ! -f $dbname.h    ]] || \
+       [[ -f $dbname.sch && $dbname.sch -nt $dbname.ddl_ ]] || \
+       [[ -f $dbname.ddl && $dbname.ddl -nt $dbname.ddl_ ]] || \
+       [[ $ODB_FEBINPATH/odb98.x -nt $dbname.ddl_ ]] || \
+       [[ -f lib$dbname.a && $ODB_FEBINPATH/odb98.x -nt lib$dbname.a ]]; then
+      compile=1
+    fi
+  fi
+  
+  #-- Recompile data layout
+  
+  if [[ $request_metadata -eq 1 ]] ; then
+    viewname="@" # A dummy table
+  fi
+  
+  sqldir=$(dirname $viewname)
+  sfx=$(basename $viewname | perl -ne 'print $1 if (/.*(\.\w+)/);')
+  viewname=$(basename $viewname | perl -pe 's/\..*//; tr/A-Z/a-z/')
+  a_out=./$viewname.x
+  if [[ "$my_a_out" != "" ]] ; then
+    my_a_out=./$(basename $my_a_out)
+    if [[ -x $my_a_out ]] ; then
+      [[ $is_verbose -eq 0 ]] || echo "Using user supplied executable '$my_a_out'" >&4
+      a_out=$my_a_out
+      my_a_out_given=1
+    fi
+  fi
+  a_out_table=./@.x
+  cachefile=$viewname.cache # saves pairs of (poolno,nrows) [not implemented yet]
+  lastquery=Last_Query
+  
+  if [[ ! -x $a_out ]] ; then
+    reexec=0
+  fi
+  
+  if [[ $compile -eq 1 ]] ; then
+    reexec=0
+  fi
+  
+  if [[ $compile -eq 1 ]] ; then
+    odbclean -f -c
+    if [[ ! -f $dbname.sch ]] ; then
+      [[ $is_verbose -eq 0 ]] || echo "Creating data layout $dbname.sch from metadata $dbname.dd ..." >&4
+      dd2ddl $dbname
+    fi
+    [[ $is_verbose -eq 0 ]] || echo "Compiling data layout $dbname.sch ..." >&4
+    odbcomp $dbname.sch # Note: The following can NOT have -z option, since data files are not moved into $workdir
+    if [[ $keep -eq 0 ]] ; then # remove "clutter"
+      rm -f ${dbname}.o ${dbname}_T_*.o
+      rm -f ${dbname}.c ${dbname}_T_*.c
+    fi
+    rm -f $cachefile $lastquery
+  fi
+  
+  #-- Fiddle with the I/O-method and dca
+  
+  if [[ -s $ddfile ]] ; then
+    iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+  else
+    iom=1
+  fi
+  export ODB_IO_METHOD=$io_method
+  if [[ $io_method -eq 5 && ! -d dca ]] ; then
+    # Try copying first
+    if [[ -d $datapath/dca ]] ; then
+      cp -r $datapath/dca .
+      chmod -R u+rw dca
+      dcafix -q -i $datapath
+    else # Generate (but using non-update [-n] option; ca. 100 x quicker than -u(pdate) option)
+      dcagen -q -z -n -i $datapath
+    fi
+    if [[ ! -d dca ]] ; then # Switch back to database specific I/O-method
+      ODB_IO_METHOD=$iom
+    fi
+  elif [[ -d dca ]] ; then
+    dcafix -q -i $datapath
+  fi
+  
+  #-- Enable access to cache/ directory, if present
+  if [[ -d $datapath/cache ]] ; then
+    rm -rf cache
+    ln -s $datapath/cache .
+  fi
+  
+  #-- Check the need for (lat,lon) radians->degrees conversion
+  export ODB_LATLON_RAD=$(\cd $datapath; $ODB_FEBINPATH/latlon_rad 2>$devnull || echo "-1")
+  
+  #-- Compile SQL
+  
+  is_table=$(echo $viewname | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+  if [[ $is_table -eq 1 ]] ; then
+    sqlfile=$devnull
+    sqldir=""
+  else
+    sqlfile=$viewname.sql
+    sqldir=$(\cd $thisdir; \cd $sqldir; pwd)
+  fi
+  
+  if [[ $is_table       -eq 0 && \
+        $reexec         -eq 0 && \
+        $query_given    -eq 0 && \
+        $my_a_out_given -eq 0 && \
+        "$sfx" != ".so" ]] ; then
+    if [[ ! -f $sqldir/$sqlfile ]] ; then
+      echo "***Error: Cannot locate input SQL-file '$sqldir/$sqlfile'" >&4
+      exit 1
+    fi
+  fi
+  
+  if [[ $is_table -eq 0 && \
+        $my_a_out_given -eq 0 && \
+        "$sfx" != ".so" ]] ; then
+    if [[ $query_given -eq 1 ]] ; then
+      echo "$query" > $sqlfile.new
+    else
+      cp $sqldir/$sqlfile $sqlfile.new
+    fi
+    chmod u+w $sqlfile.new
+    #-- check the last query first
+    lq=$(cat $lastquery 2>$devnull || echo "")
+    if [[ "$lq" = "$viewname" && -f $sqlfile ]] ; then
+      rc=0
+      cmp -s $sqlfile $sqlfile.new || rc=$?
+      if [[ $rc -eq 0 ]] ; then # SQL has not changed
+        rm -f $sqlfile.new
+        sfx=".so"
+      else
+        mv $sqlfile.new $sqlfile
+      fi
+    else
+      mv $sqlfile.new $sqlfile
+    fi
+  fi
+  
+  was_so=1
+  if [[ $is_table -eq 0 && \
+        $my_a_out_given -eq 0 ]] ; then
+    if [[ $compile -eq 1  ]] || \
+       [[ "$sfx" != ".so" ]] || \
+       [[ ! -f ${dbname}_$viewname.o ]] || \
+       [[ $sqlfile -nt ${dbname}_$viewname.o ]] ; then
+      was_so=0
+    fi
+  fi
+  
+  if [[ $reexec -eq 0 && \
+        $is_table -eq 0 && \
+        $was_so -eq 0 ]] ; then
+    export ODB_READONLY=1
+    [[ $is_verbose -eq 0 ]] || echo "Compiling data query $sqlfile for database $dbname ..." >&4
+    odbcomp -w -l $dbname $sqlfile
+    if [[ $keep -eq 0 ]] ; then # remove "clutter" (postponement)
+      keep=2
+    fi
+    rm -f $cachefile $lastquery
+  fi
+  
+  if [[ $is_table -eq 1 ]] ; then
+    export ODB_CONSIDER_TABLES=$(echo $viewname | perl -pe 's#\@(\w+)#/\L$1/#')
+  elif [[ -f ${dbname}_$viewname.c ]] ; then
+    # the following hassle defines you the ODB_CONSIDER_TABLES
+    eval `fgrep '#define ODB_CONSIDER_TABLES' ${dbname}_$viewname.c | awk '{print "export",$2"="$3}'`
+  else
+    export ODB_CONSIDER_TABLES='*'
+  fi
+  export ODB_CONSIDER_TABLES=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 'tr/A-Z/a-z/')
+  
+  if [[ $keep -eq 2 ]] ; then # remove "clutter" ... now
+    rm -f ${dbname}_$viewname.c
+  fi
+  
+  if [[ $compile -eq 1 ]] || \
+     [[ ! -x $a_out    ]] || \
+     [[ lib$dbname.a -nt $a_out ]] ; then
+    relink=1
+  fi
+  
+  #-- Re-link (if necessary)
+  if [[ ! -f $prog.o ]] || \
+     [[ $ODB_LIBPATH/libodbmain.a -nt $prog.o ]] ; then
+    ar xv $ODB_LIBPATH/libodbmain.a $objs
+    relink=1
+  fi
+  
+  if [[ $is_table -eq 1 ]] ; then
+    if [[ ! -x $a_out_table ]] || \
+       [[ $prog.o -nt $a_out_table ]] || \
+       [[ $ODB_LIBPATH/libodb.a -nt $a_out_table ]] || \
+       [[ lib$dbname.a -nt $a_out_table ]] ; then
+      [[ $is_verbose -eq 0 ]] || echo "Creating the executable for direct table accesses $a_out_table ..." >&4
+      odbcc $objs -o $a_out_table -l$dbname
+    fi
+    a_out=$a_out_table
+    relink=0
+  else
+    if [[ ! -x $a_out ]] || \
+       [[ $prog.o -nt $a_out ]] || \
+       [[ $ODB_LIBPATH/libodb.a -nt $a_out ]] ; then
+      relink=1
+    fi
+  fi
+  
+  if [[ $relink -eq 1 ]] ; then
+    [[ $is_verbose -eq 0 ]] || echo "Re-linking the executable $a_out ..." >&4
+    odbcc $objs -o $a_out -l$dbname
+  else
+    [[ $is_verbose -eq 0 ]] || echo "Using pre-linked executable $a_out ..." >&4
+    reexec=1
+  fi
+  
+  #-- Remove cache-file, unless reexec
+  
+  if [[ $reexec -eq 0 ]] ; then
+    rm -f $cachefile $lastquery
+  fi
+  
+  #-- Record the last query
+  
+  if [[ $is_table -eq 0 ]] ; then
+    echo "$viewname" > $lastquery
+  fi
+  
+fi # if [[ $fast -eq 1 ]] ; ... else ...
+  
+#-- The command-line will now be:
+cmd_1="$fastopt $csopt -l $dbname -v $viewname -n $numeric_odb_version -# $ncpus"
+cmd_2="$binmode -f $outfil $data_only $bufsize $nulls $limit $showrows $varargs $metadata"
+
+if [[ "$fastquery" != "" ]] ; then
+  if [[ $query_given -eq 1 ]] ; then
+    cmd="$cmd_1 -q '$fastquery ;' $cmd_2"
+  else
+    cmd="$cmd_1 -Q $fastquery $cmd_2"
+  fi
+else
+  cmd="$cmd_1 $cmd_2"
+fi
+
+[[ $is_verbose -eq 0 ]] || echo "$a_out $cmd" >&4
+
+#-- Redirect stdout back to its original state (#1) and close the temporary fd#3
+#   (stderr still flows as usual to #2, unless silenced with -s)
+exec 1>&3
+exec 3>$devnull
+
+#-- Run data extraction 
+# (output comes to stdout; errors still go to stderr, unless silenced with -s)
+
+if [[ $silent -eq 1 ]] ; then
+  exec 2>$devnull
+fi
+
+if [[ "$debugger" != "" ]] ; then
+  echo "Run the debugger '$debugger' with the following arguments:"
+  echo "$cmd" >&2
+  exec $debugger $a_out
+  rc=1
+else
+  rc=0
+  if [[ "$fastquery" != "" ]] ; then
+    if [[ $query_given -eq 1 ]] ; then
+      exec $a_out $cmd_1 -q "$fastquery ;" $cmd_2 || rc=$?
+    else
+      exec $a_out $cmd_1 -Q $fastquery $cmd_2 || rc=$?
+    fi
+  else
+    exec $a_out $cmd || rc=$?
+  fi
+fi
+
+#-- Should never endup hier ...
+
+if [[ $rc -ne 0 ]] ; then
+  rc=$?
+  echo "***Error(s) were encountered while executing command (rc=$rc) :" >&4
+  echo "$a_out $cmd" >&4
+  exit $rc
+fi
+
+exit 0
diff --git a/odb/src/scripts/check_links b/odb/src/scripts/check_links
new file mode 100755
index 0000000..2f825bd
--- /dev/null
+++ b/odb/src/scripts/check_links
@@ -0,0 +1,84 @@
+#!/bin/ksh
+#
+#begin
+#
+#  check_links [/path/][dbname.dd]
+#
+#  A rudimentary tool to check @LINK consistency
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 25-Nov-2006
+#
+
+set -eu
+
+thisdir=$(pwd)
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+abort=no
+
+dbpath=$thisdir
+dbname=""
+
+if [[ $# -ge 1 ]] ; then
+  dbpath=$1
+  if [[ -f $dbpath ]] ; then
+    dbpath=$(dirname $dbpath)
+  fi
+fi
+
+if [[ -d "$dbpath" ]] ; then
+  \cd $dbpath
+  dbpath=$(pwd)
+  dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    echo "***Error: Unable to locate the main metadata file (.dd) from directory '$dbpath'" >&2
+    dbname=""
+    abort=yes
+  fi
+  \cd $thisdir
+fi
+
+ddfile=$dbpath/$dbname.dd
+if [[ "$abort" = "no" && ! -f "$ddfile" ]] ; then
+  echo "***Error: The main metadata file '$ddfile' not found" >&2
+  abort=yes
+fi
+
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+tables=$(egrep "^@" $ddfile | awk '{print $1}' | perl -pe 's#\@# #g;')
+npools=$(head -5 $ddfile | tail -1)
+
+for t in $tables
+do
+  subtables=$(set +e; \
+              egrep ":LINKOFFSET" $ddfile 2>/dev/null | egrep "\@$t" |\
+              awk '{print $1}'| perl -pe 's/^.*LINKOFFSET\(//' |\
+              awk -F\) '{print $1}')
+  for st in $subtables
+  do
+    echo "Processing parent-table '$t' against child-table '$st':"
+
+    sql_1="select \$#,count(*) as 'no_of_rows_in_$st' from $st"
+
+    sql_2="select \$#,min(LINKOFFSET($st)),min(LINKLEN($st)),"
+    sql_2="$sql_2  minloc(LINKOFFSET($st),#$t),minloc(LINKLEN($st),#$t) from $t"
+
+    sql_3="select \$#,max(LINKOFFSET($st)),max(LINKLEN($st)),"
+    sql_3="$sql_3  maxloc(LINKOFFSET($st),#$t),maxloc(LINKLEN($st),#$t) from $t"
+
+    offlen="$st.offset + min(0,$st.len)"
+    sql_4="select \$#,min($offlen),minloc($offlen,#$t) from $t"
+
+    offlen="$st.offset + $st.len"
+    sql_5="select \$#,max($offlen),maxloc($offlen,#$t) from $t"
+
+    sql="$sql_1; $sql_2; $sql_3; $sql_4; $sql_5;"
+    $ODB_BINPATH/odbsql -q "$sql" -i $dbpath -N 
+  done
+done
diff --git a/odb/src/scripts/create_index b/odb/src/scripts/create_index
new file mode 100755
index 0000000..273fd36
--- /dev/null
+++ b/odb/src/scripts/create_index
@@ -0,0 +1,141 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+set -eu
+#=======================================================================
+#begin
+#
+# create_index [-u|-b]  [-n idxname] -t table -c colname(s) [-p poolno(s)] [-l dbname] [-r ratio]
+#
+# A (development) tool to create ODB row-indices
+#
+# CREATE [UNIQUE|BITMAP] INDEX idxname ON tblname (colname(s)) PARTITION poolno
+#
+# Options:
+#
+#  -u           : unique index (the default)
+#  -b           : bitmap index
+#  -n idxname   : index name, by default table-name + timestamp (for now)
+#  -t table     : table name in concern (must be supplied)
+#  -c col(s)    : comma or blank separated list of column (must be supplied)
+#  -p poolno(s) : pool number(s) (could be a range: 1-5 or a comma separated: 1,2,3,10,11 or both)
+#  -l dbname    : database name in concern (the default figured out from existing .dd-file)
+#  -r ratio     : cardinality over no. of rows -limit percentage above which index creation is abandoned (default=10)
+#
+# Author: Sami Saarinen, ECMWF, 16-Jan-2006
+#
+#end
+#=======================================================================
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+idxtype=1 # 1=unique index, 2=bitmap index
+idxtypename=UNIQUE
+idxname=""
+table=""
+cols=""
+poolmask=""
+dbname=""
+dbdir=. # for now
+ratio=10
+
+FLAGS=bc:l:n:p:r:t:u
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  b) idxtype=2; idxtypename=BITMAP;;
+  c) cols="$cols $OPTARG";;
+  l) dbname="$OPTARG";;
+  n) idxname="$OPTARG";;
+  p) poolmask="$poolmask $OPTARG";;
+  r) ratio="$OPTARG";;
+  t) table="$OPTARG";;
+  u) idxtype=1; idxtypename=UNIQUE;;
+  \?) abort=yes; break;;
+  esac
+done
+
+# for now : no 'cd':ing
+#cd $dbdir || exit 1
+
+ddfile=/dev/null
+if [[ "$dbname" = "" ]] ; then
+  dbname=$(basename $(ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    dbname=""
+  fi
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Cannot determine database name" >&2
+  abort=yes
+else
+  ddfile=$dbname.dd
+fi
+
+if [[ "$table" = "" ]] ; then
+  echo "***Error: Table name not given" >&2
+  abort=yes
+else
+  rc=0
+  egrep "^@$table" $ddfile >/dev/null 2>&1 || rc=$?
+  if [[ $rc -ne 0 ]] ; then
+    echo "***Error: Table '$table' is not part of database schema '$dbname'" >&2
+    abort=yes
+  fi
+fi
+
+# sort columns in alphabetical order, remove commas, use blank as a separator and remove trailing space
+# so for example: "col1  col3, col2,,col4" becomes "col1 col2 col3 col4"
+cols=$(echo "$cols" | perl -pe 's/^\s*//; s/\s*$//; s/,/ /g; s/\s+/\n/g;' |\
+       sort -u | perl -pe 's/\s+/ /g' | perl -pe 's/\s+$//')
+if [[ "$cols" = "" ]] ; then
+  echo "***Error: No column name(s) specified" >&2
+  abort=yes
+fi
+
+#=======================================================================
+#   Report errors and exit
+#=======================================================================
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+#=======================================================================
+#   So far all ok
+#=======================================================================
+
+#-- Show columns
+echo "==> Using columns $cols"
+
+#-- Generate index name
+if [[ "$idxname" = "" ]] ; then
+  idxname=${table}_$(echo "$cols" | cksum | awk '{print $1}')
+fi
+echo "==> Using index name '$idxname' for CREATE $idxtypename INDEX"
+
+#-- Poolmask
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK="$poolmask"
+  echo "==> Using only pools : $ODB_PERMANENT_POOLMASK"
+fi
+
+#=======================================================================
+#   Get going (assume lib$dbname.a is already there .. for now)
+#=======================================================================
+
+obj=$($ODB_AR t $ODB_LIBPATH/libodbmain.a | grep Create_index)
+$ODB_AR xv $ODB_LIBPATH/libodbmain.a $obj
+
+odbf90 $obj -l$dbname -o create_index.x
+
+# Usage for now
+cmd="./create_index.x $dbname $idxtype $idxname $table $ratio $cols"
+echo "$cmd"
+      $cmd
+
+rm -f $obj create_index.x
diff --git a/odb/src/scripts/create_ioassign b/odb/src/scripts/create_ioassign
new file mode 100755
index 0000000..d00fb96
--- /dev/null
+++ b/odb/src/scripts/create_ioassign
@@ -0,0 +1,351 @@
+#!/bin/ksh
+#create_ioassign      version:  20130305
+
+set -eu
+#=======================================================================
+#
+#     Script create_ioassign     
+#     ----------------------
+#                         
+#     Purpose     : To create IOASSIGN file for the given ODB database
+#                               
+#     Usage       :  create_ioassign
+#     -----                -l dbname   ; database name
+#                          [-d dirname ; location of ioassign_file]
+#                          [-n npools]
+#                          [-x] ; expand ioassign_file to get rid of percent-d's
+#                          [-t task] ; component databases; use with -x
+#                          [-s]      ; use this if surface analysis
+#                          [-e]      ; use this if ensemble data assimilation
+#                          [-q]      ; be quiet (except for fatal errors)
+#                                            
+#     Parameters  : dbname    - database name, like ECMA or CCMA; must be supplied
+#     ----------    dirname   - directory where the IOASSIGN will be placed ;
+#                               the default: $PWD
+#                   npools    - number of pools (default: from $dbname/ECMA.dd)
+#                   task      - component database(s); like -t amsua for ECMA.amsua
+#
+#=======================================================================
+
+ARGS="$0 $*"
+USAGE1="$0 -l dbname [-d dirname] [-n npools]"
+USAGE2="   [-x (to expand ioassign) [-s (if surface analysis)] -t task1 [-t task2] ...]"
+USAGE3="   [-q (quiet)] [-b iobufsize]"
+
+dbname=none
+dir=.
+npools=0
+expand=0
+alltasks=""
+surf=0
+ensemble=0
+silence=0
+
+errflg=0
+
+FLAGS="d:l:n:sqt:xe"
+
+while getopts $FLAGS option
+do
+  case $option in
+    l) dbname=$OPTARG;;
+    d) dir="$OPTARG";;
+    n) npools=$OPTARG;;
+    s) surf=1;;
+    e) ensemble=1;;
+    q) silence=1;;
+    t) alltasks="$alltasks $OPTARG";;
+    x) expand=1;;
+   \?) errflg=1;;
+  esac
+done
+
+if [[ $silence -eq 0 ]] ; then
+  echo "$ARGS" >&2
+fi
+
+#=======================================================================
+#   Check parameters
+#=======================================================================
+
+if [[ $dbname = none ]] ; then
+  echo "$0: An invalid dbname=$dbname was supplied via -l option" >&2
+  errflg=1
+fi
+
+[[ -d $dir ]] || mkdir -p $dir || errflg=1
+
+if [[ ! -d $dir ]] ; then
+  echo "$0: Database dir '$dir' not found" >&2
+  errflg=1
+fi
+
+if [[ $expand -eq 1 && "$alltasks" = "" ]] ; then
+  alltasks=$(cd $dir/.. ; \ls -C1pd $dbname.* | \
+             awk -F/ '{print $1}' | sed "s/^$dbname\.//g" | sort -u)
+fi
+
+if [[ $errflg -ne 0 ]] ; then
+  echo "$ARGS" >&2
+  echo $USAGE1 >&2
+  echo $USAGE2 >&2
+  echo $USAGE3 >&2
+  exit 1
+fi
+
+ddfile=$dir/$dbname.dd
+
+if [[ $npools -le 0 ]] ; then # try to find out correct no. of pools
+  if [[ -s $ddfile ]] ; then
+    npools=$(head -5 $ddfile | tail -1)
+  else
+    npools=${ODB_IOASSIGN_MAXPROC:=0} # If == 0, can be usually a bad thing ;-(
+  fi
+  if  [[ $silence -eq 0 ]] ; then
+  echo "$0: Total no. of pools was detected automatically from file '$ddfile' ;" >&2
+  echo "    Using value for npools='$npools'" >&2
+  fi
+fi
+
+io_method=${ODB_IO_METHOD:=4}
+if [[ -s $ddfile ]] ; then
+  iom=$(head -1 $ddfile | awk 'BEGIN {n=0;} {if (NF >= 3) n=$3;} END {print n;}')
+  [[ $iom -ne 0 ]] || io_method=$iom
+fi
+
+#-- More I/O-buffering when either less pools or I/O-method found to be horizontal concatenation
+if [[ $npools -lt 32 ]] || [[ $io_method -eq 4 ]] ; then
+  iodef="-r 8m -w 8m -p 8m -e 8m"
+else
+  iodef="-r 1m -w 1m -p 1m -e 1m"
+fi
+
+#-- Get list of tables either from existing $ddfile or using latest known tables
+
+if [[ -s $ddfile ]] ; then
+  tables=$(egrep "^@" $ddfile | awk '{print $1}' | perl -pe 's#\@# #g;')
+else
+#-- Known tables in alphabetical order
+
+  tables="aeolus_auxmet aeolus_hdr aeolus_l2c"
+  tables="$tables body bufr bufr_tables bufr_tables_desc"
+  tables="$tables ddrs desc errstat hdr index poolmask resat"
+  tables="$tables rtovs rtovs_body rtovs_mlev rtovs_pred rtovs_slev"
+  tables="$tables sat satem satob scatt scatt_body smos ralt"
+  tables="$tables ssmi ssmi_body ssmi_mlev ssmi_slev"
+  tables="$tables timeslot_index update limb resat_averaging_kernel"
+  tables="$tables radar radar_body radar_station"
+  tables="$tables surfbody_feedback modsurf radiance allsky co2_sink cloud_sink collocated_imager_information"
+  tables="$tables auxiliary auxiliary_body radiance_body allsky_body fcdiagnostic"
+  tables="$tables gbrad gbrad_body gnssro gnssro_body"
+  tables="$tables ensemble conv conv_body raingg raingg_body"
+
+  #-- Include only minimal amount of update tables
+  #   Note: can't use MXUP_TRAJ, since $NMXUPD in data layout may have a larger value
+
+  jpmxup=10 # from source code of IFS ; see ifs/module/parcma.F90
+
+  uptraj=0
+  while [[ $uptraj -lt $jpmxup ]]
+  do
+    ((uptraj += 1))
+    tables="$tables update_$uptraj"
+  done
+
+  jpmxenkf=120 # from source code of IFS ; see ifs/module/parcma.F90
+  enkf_count=0
+  while [[ $enkf_count -lt $jpmxenkf ]]
+  do
+    ((enkf_count += 1))
+    tables="$tables enkf_$enkf_count"
+  done
+
+  jpmxenda=100 # from source code of IFS ; see ifs/module/parcma.F90
+  enda_count=0
+  while [[ $enda_count -lt $jpmxenda ]]
+  do
+    ((enda_count += 1))
+    tables="$tables enda_$enda_count"
+  done
+  enda_count=0
+  while [[ $enda_count -lt $jpmxenda ]]
+  do
+    ((enda_count += 1))
+    tables="$tables surfbody_feedback_$enda_count"
+  done
+
+  jpmxfcdiag=20 #from source code of IFS ; see ifs/module/parcma.F90
+  fcdiag_count=0
+  while [[ $fcdiag_count -lt $jpmxfcdiag ]]
+  do
+    ((fcdiag_count += 1))
+    tables="$tables fcdiagnostic_body_$fcdiag_count"
+  done
+fi
+
+#-- Start creating IOASSIGN-file (in the fastest possible way ?)
+#   ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname/%d/$cmd $dbname..%d
+
+unset IOASSIGN  || :
+tmpfile=__ioassign__.$$
+cat /dev/null > $tmpfile
+
+ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.dd $dbname           >> $tmpfile
+ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.sch $dbname.sch      >> $tmpfile
+ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.flags $dbname.flags  >> $tmpfile
+ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.iomap $dbname.iomap  >> $tmpfile
+
+#-- dca : direct column access -files (globally one file per table)
+#         only applicable for self-contained databases i.e. $expand == 0
+dcadir=dca
+if [[ $expand -eq 0 ]] && [[ $alltasks == "" ]] ; then
+    echo "tables=$tables"
+    awk \
+    '(NR==1) { dca=$0; };(NR >= 2) { \
+            for (i=1; i<=NF; i++) { x=dca; gsub("TABLENAME",$i,x); print x; }}' >> $tmpfile \
+    <<EOF
+$(ioassign -s -a \$ODB_SRCPATH_$dbname/$dcadir/TABLENAME.dca $dbname.TABLENAME.dca)
+$tables
+EOF
+fi
+
+if [[ $expand -eq 0 ]] ; then # Retain percent-d's
+  #-- Sense whether gzipped already ?
+  hdrgz=$(find [0-9]* -type f -name 'hdr.gz' -print 2>/dev/null | head -1)
+  if [[ "$hdrgz" != "" ]] ; then
+    cmd=".gz -c #gzip"
+  else
+    cmd=""
+  fi
+
+  if [[ $ensemble -eq 1 ]] ; then
+    dots="/../../"
+  else
+    dots="/"
+  fi
+
+  #-- No gzipping of QTARFILE ($ODB_IO_METHOD = 3)
+  ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname/%d/QTARFILE $dbname.QTARFILE.%d >> $tmpfile
+
+  if [[ $alltasks != "" ]];then #e.g. multiple tasks - ECMA.conv, ECMA.amsua etc
+    if [[ $surf -eq 1 ]] ; then
+      dots="/../../"
+    else
+      dots="/../"
+    fi
+
+    p=0
+    for task in $alltasks
+    do
+      # read npools in this xCMA.x from the .dd file
+      d=$dir$dots$dbname.$task
+      ddfile=$d/$dbname.dd
+      np=$(head -5 $ddfile | tail -1)
+      # Calculate global pool number range for this ECMA.x
+      ((psta = p + 1))
+      ((pend = p + np))
+      p=$pend
+      ioassign -S $psta -s -n $np $iodef -a \$ODB_DATAPATH_$dbname$dots$dbname.$task/%d/%s$cmd $dbname.%s.%d >> $tmpfile
+    done
+  else # e.g. single CCMA
+    ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname$dots%d/%s$cmd $dbname.%s.%d >> $tmpfile
+  fi
+
+else # Expand
+
+  #-- Create template file for table=_xxx_ for subsequent filtering
+  tbl=_xxx_
+  template=__template__.$$
+  cat /dev/null > $template
+  p=0
+  if [[ $surf -eq 1 ]] ; then
+    dots="../.."
+  else
+    dots=".."
+  fi
+  for task in $alltasks
+  do
+    d=$dir/$dots/$dbname.$task
+    ddfile=$d/$dbname.dd
+    if [[ $silence -eq 0 ]] ; then
+    echo "$0: Processing $ddfile ; p=$p" >&2
+    fi
+    if [[ -s $ddfile ]] ; then
+      #-- Sense whether gzipped already ?
+      hdrgz=$(find [0-9]* -type f -name 'hdr.gz' -print 2>/dev/null | head -1)
+      if [[ "$hdrgz" != "" ]] ; then
+        cmd=".gz -c #gzip"
+      else
+        cmd=""
+      fi
+      np=$(head -5 $ddfile | tail -1)
+      ((psta = p + 1))
+      ((pend = p + np))
+      #-- In the following the %d after "-a" option i.e. physical filename 
+      #   expands (-x) between range [1 .. $np], but the logical filename's %d
+      #   expands between range [$psta .. $pend] i.e [$psta .. $psta + $np - 1] (due to -S)
+      ioassign -s -x -n $np -S $psta $iodef \
+               -a \$ODB_DATAPATH_$dbname/$dots/$dbname.$task/%d/$tbl$cmd \
+               $dbname.$tbl.%d >> $template
+      p=$pend
+    fi # if [[ -s $ddfile ]]
+  done
+
+  if [[ $p -ne $npools ]] ; then
+    if [[ $silence -eq 0 ]] ; then
+    echo "$0: ***Warning: Inconsistent no. of pools found=$p ; expected=$npools" >&2
+  fi
+  fi
+
+  #-- Now filter "_xxx_" across all tables using Perl to create final IOASSIGN-file
+#  for tbl in $tables
+#  do
+#    perl -pe "s/_xxx_/$tbl/g" < $template >> $tmpfile
+#  done
+cat << \EOF > create_ioassign_perl.pl
+
+use strict;
+use warnings;
+
+my $tables = $ENV{'tables'};
+my @tables=split(/\s+/,$tables);
+my $templ_file=$ENV{'template'};
+my $tmpfile=$ENV{'tmpfile'};
+
+my(@lines);
+
+if(!open(INFIL,$templ_file)) {
+   print STDERR "Can't open $templ_file for reading\n";
+   die("Can't open $templ_file for reading\n");
+}
+open(OUT,">>$tmpfile");
+ at lines=<INFIL>;
+close INFIL;
+
+my $line;
+for (@tables) {
+  my $tbl=$_;
+  for (@lines) {
+    $line=$_;
+    $line=~s/_xxx_/$tbl/g;
+    print OUT $line;
+  }
+}
+
+EOF
+
+  export tables template tmpfile
+  perl create_ioassign_perl.pl
+  rm -f $template
+fi
+
+rm -f $dir/*IOASSIGN* || true
+cp $tmpfile $dir/$dbname.IOASSIGN
+
+rm -f $tmpfile
+
+# for compatibility & convenience
+(cd $dir ; \rm -f IOASSIGN.$dbname ; \ln -s $dbname.IOASSIGN IOASSIGN.$dbname)
+(cd $dir ; \rm -f IOASSIGN         ; \ln -s $dbname.IOASSIGN IOASSIGN)
+
+exit 0
diff --git a/odb/src/scripts/create_odbglue b/odb/src/scripts/create_odbglue
new file mode 100755
index 0000000..9011029
--- /dev/null
+++ b/odb/src/scripts/create_odbglue
@@ -0,0 +1,92 @@
+#!/bin/ksh
+#
+# Usage: create_odbglue [dbname(s)]
+#
+# Creates glue-file "_odb_glue.c" and compiles it, if
+# environment variable "ODB_CC" has been defined
+#
+# Author: Sami Saarinen, ECMWF, 13-Feb-2004
+#                               11-Apr-2006 : No more known/predefined databases
+#
+#
+
+set -eu
+
+if [[ $# -lt 1 ]] ; then
+  echo "Usage: create_odbglue [dbname(s)]" >&2
+  exit 1
+fi
+
+odbglue=_odb_glue.c
+
+cat > $odbglue << 'EOF'
+#include <stdio.h>
+#include <string.h>
+
+extern void
+codb_procdata_(int *myproc,
+               int *nproc,
+               int *pid,
+               int *it,
+               int *inumt);
+
+extern void 
+ODB_add2funclist(const char *dbname,
+		 void (*func)(),
+                 int funcno);
+
+#define Static_Init(db) \
+if (strncmp(dbname, #db, dbname_len) == 0) { \
+  extern void db##_static_init(); \
+  ODB_add2funclist(#db, db##_static_init, 0); \
+} \
+else { /* fprintf(stderr,"***Warning: Not initializing '%s'\n",#db); */ }  
+
+void
+codb_set_entrypoint_(const char *dbname
+	             /* Hidden arguments */
+	             , int dbname_len)
+{
+  int myproc = 0;
+  codb_procdata_(&myproc, NULL, NULL, NULL, NULL);
+  if (myproc == 1) {
+    fprintf(stderr,
+            "codb_set_entrypoint_(dbname='%*s', dbname_len=%d)\n",
+            dbname_len, dbname, dbname_len);
+  }
+EOF
+
+#known_dbs="CCMA ECMA ECMASCR PREODB"
+known_dbs=""
+
+newarg="$known_dbs "
+for arg in $*
+do
+  db=$(basename $arg | perl -pe 's/\s+//g; s/\..*$//; s/[_-]//g; tr/a-z/A-Z/')
+  newarg="$newarg$db "
+done
+
+# Ensure uniqueness (strictly speaking not a requirement, but cleaner)
+newarg=$(echo "$newarg" | perl -pe 's/(\S+)\s*/$1\n/g' | sort -u)
+
+# Lets rock'n'roll now ...
+for db in $newarg
+do
+  echo "  Static_Init($db);" >> $odbglue
+done
+
+cat >> $odbglue << 'EOF'
+}
+EOF
+
+#ls -l $odbglue
+
+export ODB_CC=${ODB_CC:=""}
+
+rc=0
+if [[ "$ODB_CC" != "" ]] ; then
+  echo "$ODB_CC -c $odbglue" >&2
+        $ODB_CC -c $odbglue  >&2 || rc=$?
+fi
+
+exit $rc
diff --git a/odb/src/scripts/create_static_stubb b/odb/src/scripts/create_static_stubb
new file mode 100755
index 0000000..6f67c7f
--- /dev/null
+++ b/odb/src/scripts/create_static_stubb
@@ -0,0 +1,165 @@
+#!/bin/ksh
+#
+# Generates database specific static stubb file from
+# the given SQL filenames
+#
+# Usage: create_static_stubb [-c|-v] database_name [sql_files]
+#
+# Output file is called : <database_name>_Sstatic.c
+#
+# If -c option is used (MUST BE the first arg), 
+#    then the created C-code will be compiled with $ODB_CC (if ODB_CC is defined)
+#    If compilation successful, then the object will be put into lib<dbname>.a (if available)
+# If -v option is used (MUST BE the first arg),
+#    then the viewnames associated (found) in the given SQL-file are written to stdout
+#
+
+set -eu
+
+usage="Usage: $0 [-c|-v] database_name [sql_files]"
+
+if [[ $# -lt 1 ]] ; then
+  echo "$usage" >&2
+  exit 1
+fi
+
+compile=0
+vn=0
+
+if [[ "$1" = "-c" ]] ; then
+  compile=1
+  shift
+elif [[ "$1" = "-v" ]] ; then
+  vn=1
+  shift
+fi
+
+if [[ $# -lt 1 ]] ; then
+  echo "$usage" >&2
+  exit 2
+fi
+
+db=$1
+shift
+
+if [[ $# -ge 1 ]] ; then
+  sql_files=$*
+else
+  sql_files=$(\ls [a-z]*.sql 2>/dev/null || :)
+fi
+
+if [[ $compile -eq 1 ]] ; then
+  stubb_file=${db}_Sstatic.c
+else
+  stubb_file=${db}_Sstatic.c.new
+fi
+stubb_obj=${db}_Sstatic.o
+stubb_tmp=${db}_Sstatic.c.tmp
+
+cat > $stubb_file <<EOF
+#define ODB_GENCODE 0
+#include "${db}.h"
+
+PUBLIC void ${db}_static_init() {
+ODB_ANCHOR(${db});
+EOF
+
+export ODB_AR=${ODB_AR:="ar"}
+
+libname=lib$db.a
+testvar=ODB_SRCPATH_${db}
+set +u
+testvalue=$(eval echo \$$testvar 2>/dev/null || :)
+if [[ "$testvalue" != "" && -d "$testvalue" ]] ; then
+  libname=$testvalue/lib$db.a
+else
+  testvalue=""
+fi
+set -u
+
+#-- Preserve pre-existing views from previous compilation(s) (except if -v given)
+cat /dev/null > $stubb_tmp
+if [[ $vn -eq 0 && -r $libname ]] ; then
+  $ODB_AR t $libname | perl -pe "s/^${db}_//; s/[.]o//;" |\
+                       egrep -v "^(T_|Sstatic|${db})" > $stubb_tmp
+fi
+
+set +u
+for sql in $sql_files
+do
+  if [[ -r "$sql" && "$sql" != "/dev/null" ]] ; then
+#    s=$(basename $sql .sql)
+#    set -A v $(\cat $sql | perl -ne 'print "\L$1 " if (/CREATE\s+VIEW\s+(\w+)/i);')
+    set -A v $(perl -ne 'print "\L$1\n" if(/^\s*CREATE\s*VIEW\s+(\S+)/i);' $sql |\
+               perl -pe 's/(\w+)\s*\[\s*(-?\d+)\s*\].*/$1_$2/; s/-/_/g;')
+#    echo "v=${v[*]}"
+#    echo "no. of v=${#v[*]}"
+    if [[ ${#v[*]} -gt 0 ]] ; then
+      for s in ${v[*]}
+      do
+        echo "$s" >> $stubb_tmp
+      done
+    else # Probably a direct select ... from ... ?
+      s=$(basename $sql .sql | perl -pe 'tr/A-Z/a-z/')
+      echo "ODB_ANCHOR_VIEW(${db}, $s );" >> $stubb_file
+      # count number of selects. if more than 1, make also views _tmp_1, _tmp_2, etc.
+      n=$(\cat $sql | perl -ne 'BEGIN {$n=0} $n++ if (m/^.*\bselect\b.*/i); END {print $n}')
+      if [[ $n -gt 1 ]] ; then
+        j=1;
+        while [[ $j -lt $n ]] # < $n, since first view is already per .sql-file basename
+        do
+          echo "_tmp_$j" >> $stubb_tmp
+          ((j += 1))
+        done
+      fi
+    fi
+  fi
+done
+set -u
+
+for s in $(sort -u $stubb_tmp)
+do
+  echo "ODB_ANCHOR_VIEW(${db}, $s );" >> $stubb_file
+done
+\rm -f $stubb_tmp
+
+echo '}' >> $stubb_file
+
+rc=0
+
+if [[ $compile -eq 1 ]] ; then
+  export ODB_CC=${ODB_CC:=""}
+  libname=lib$db.a
+  if [[ "$ODB_CC" != "" ]] ; then
+    if [[ "$testvalue" != "" ]] ; then
+      export ODB_CC="${ODB_CC:=cc} -I$testvalue"
+    fi
+    echo "$ODB_CC -c $stubb_file" >&2
+          $ODB_CC -c $stubb_file  >&2 || rc=$?
+    if [[ $rc -eq 0 && -f $stubb_obj && -f $libname ]] ; then
+      $ODB_AR r $libname $stubb_obj || rc=$?
+    fi
+  fi
+elif [[ $vn -eq 1 ]] ; then
+  egrep ODB_ANCHOR_VIEW $stubb_file >/dev/null 2>&1 || rc=$?
+  egrep ODB_ANCHOR_VIEW $stubb_file 2>/dev/null | awk '{print $2}'
+  \rm -f $stubb_file  
+else # Create the final stubb-file only if it
+     # (1) does not exist already or
+     # (2) new differs from the existing one
+  rename=0
+  true_stubb_file=${db}_Sstatic.c
+  if [[ -f $true_stubb_file ]] ; then
+    diff -q $true_stubb_file $stubb_file >/dev/null 2>&1 || rename=1
+  else
+    rename=1
+  fi
+  if [[ $rename -eq 1 ]] ; then
+    \rm -f $true_stubb_file
+    \mv $stubb_file $true_stubb_file
+  else
+    \rm -f $stubb_file
+  fi
+fi
+
+exit $rc
diff --git a/odb/src/scripts/dcafix b/odb/src/scripts/dcafix
new file mode 100755
index 0000000..9886a71
--- /dev/null
+++ b/odb/src/scripts/dcafix
@@ -0,0 +1,78 @@
+#!/bin/ksh
+# 
+# Usage: dcafix [-i datapath] [-v] [-q] [dca/hdr.dca [dca/body.dca] ... ]
+#
+
+set -eu
+
+datapath="."
+datapath_opt=""
+verbose=0
+verbose_opt=""
+quiet_opt=""
+
+while getopts i:qv  option
+do
+  case $option in
+    i) datapath="$OPTARG";;
+    v) quiet_opt=""  ; verbose=1; verbose_opt="-v";;
+    q) quiet_opt="-q"; verbose=0; verbose_opt=""  ;;
+  esac
+done
+
+if [[ -f $datapath/dca/.dcafixed ]] ; then
+#-- Already dcafix'ed --> do nothing
+  exit 0
+fi
+
+datapath_opt="-i $datapath $verbose_opt $quiet_opt"
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  args=$*
+  all=0
+else
+  args="dca/*.dca"
+  all=1
+fi
+
+\cd $datapath || exit 1
+
+for f in $args
+do
+  if [[ -f $f ]] ; then
+    begin_hash=$(dd bs=1 if=$f count=1 2>/dev/null || :)
+    if [[ "$begin_hash" = '#' ]] ; then
+      line=$(egrep '^#DCA:' $f 2>/dev/null | head -1)
+    else
+      line="" # the file is presumably a binary DCA-file --> no need for dcafix'ing
+    fi
+    if [[ ! -z "$line" ]] ; then
+      [[ $verbose -eq 0 ]] || echo "Fixing DCA for file $f ..."
+      check=$(echo "$line" | sed 's/^.*\(is_little\).*/\1/') # a further check; a 28R1-bug
+      [[ $verbose -eq 0 ]] || echo "line='$line'"
+      [[ $verbose -eq 0 ]] || echo "check='$check'"
+      if [[ "$check" = "is_little" ]] ; then
+        env DATAPATH=$datapath perl -w $ODB_BINPATH/dcafix.pl < $f > $f.new
+        mv $f $f.old
+        mv $f.new $f
+      elif [[ $all -eq 1 ]] ; then
+        all=2
+        break # for f in $args
+      else # Re-generate quickly ...
+        table=$(basename $f | sed 's/\..*//')
+        dcagen -z -F -n -t $table $datapath_opt 
+      fi
+    fi
+  fi
+done
+
+if [[ $all -ge 1 ]] ; then
+  if [[ $all -eq 2 ]] ; then
+    #-- Uses multiple processes 
+    dcagen -z -F -n $datapath_opt
+  fi
+  cat /dev/null > dca/.dcafixed
+fi
+
diff --git a/odb/src/scripts/dcafix.pl b/odb/src/scripts/dcafix.pl
new file mode 100644
index 0000000..56f04a1
--- /dev/null
+++ b/odb/src/scripts/dcafix.pl
@@ -0,0 +1,96 @@
+#
+# dcafix.pl
+#
+
+use strict;
+
+# Read environment variables
+my $datapath = $ENV{'DATAPATH'} || ".";
+
+my @in = <>;
+my @out = ();
+
+my $dcaline = "";
+for (@in) {
+  chomp;
+  if (m/^\d+/) {
+    push(@out,$_);
+  }
+  elsif (m/^\#DCA:/) {
+    $dcaline = $_;
+  }
+}
+
+if ($dcaline =~ m/^\#DCA:/) {
+  my $is_hcat = 0;
+  my $file_tested = 0;
+  my $maxfilelen = 0;
+
+  for (@out) {
+    my ($col, $colname, $dtname, $dtnum, $file, $poolno, $offset, $length,
+	$pmethod, $pmethod_actual, $nrows, $nmdis, 
+	$avg, $min, $max, $res1, $res2, $is_little) = split(/\s+/);
+    my $len = length($file);
+    $maxfilelen = $len if ($len > $maxfilelen);
+    if (!$file_tested) {
+      $file = "$datapath/$file" if (! -f $file);
+      if (-f $file) { # quick'n'dirty
+	my $word = `od -cv $file|head -1`;
+	$word =~ s/^\s*\S+\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+.*$/$1$2$3$4/;
+	chomp($word);
+	$is_hcat = ($word eq "HC32" || $word eq "23CH");
+      }
+      $file_tested = 1;
+    }
+    last if (!$is_hcat);
+  }
+
+  if ($is_hcat) {
+    my $key;
+    my %keyval = ();
+    for (@out) {
+      my ($col, $colname, $dtname, $dtnum, $file, $poolno, $offset, $length,
+	  $pmethod, $pmethod_actual, $nrows, $nmdis, 
+	  $avg, $min, $max, $res1, $res2, $is_little) = split(/\s+/);
+      $key = sprintf "%6.6d %*s %12.12d",$poolno,$maxfilelen,$file,$offset;
+      $keyval{$key} = $offset;
+    }
+
+    my $prevpoolno=0;
+    my $prevfile="";
+    my $fix = 0;
+    for $key (sort keys %keyval) {
+      my ($poolno,$thisfile,$thisoffset) = split(/\s+/,$key);
+      if ($thisfile ne $prevfile) {
+	$fix = 0;
+	$prevfile = $thisfile;
+      }
+      $fix -= 20 if ($prevpoolno != $poolno);
+      my $offset = $keyval{$key};
+      $offset += $fix;
+#      print STDERR "$key:$keyval{$key} => $offset ($fix)\n";
+      $keyval{$key} = $offset;
+      $prevpoolno = $poolno;
+    }
+
+    for (@out) {
+      my ($col, $colname, $dtname, $dtnum, $file, $poolno, $offset, $length,
+	  $pmethod, $pmethod_actual, $nrows, $nmdis, 
+	  $avg, $min, $max, $res1, $res2, $is_little) = split(/\s+/);
+      $key = sprintf "%6.6d %*s %12.12d",$poolno,$maxfilelen,$file,$offset;
+      $offset = $keyval{$key};
+      $_ = join(' ',
+		($col, $colname, $dtname, $dtnum, $file, $poolno, $offset, $length,
+		 $pmethod, $pmethod_actual, $nrows, $nmdis, 
+		 $avg, $min, $max, $res1, $res2, $is_little));
+    }
+  }
+}
+
+$dcaline =~ s/^(\#DCA):/${1}2:/;
+print "$dcaline\n";
+for (@out) {
+  print "$_\n";
+}
+
+
diff --git a/odb/src/scripts/dcagen b/odb/src/scripts/dcagen
new file mode 100755
index 0000000..ec147a4
--- /dev/null
+++ b/odb/src/scripts/dcagen
@@ -0,0 +1,453 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..." >&2; wait; exit 1' 1 2 3 15
+
+set -eu
+#begin
+#=======================================================================
+#
+#     Script dcagen  
+#     -------------    
+#                         
+#     Purpose     : Creates Direct Column Access-files for given ODB
+#                   to improve post-processing & direct column access
+#                   from ODB tables
+#                               
+#     Usage       : dcagen [-l dbname] [-t table] [-f] [-d] [-n] [-u] [-i dbdir] [-v] [-N cpus]
+#                          [-F] [-b] [-B bufsiz] [-z] [-g] [-c colname at table] [-C colname at table]
+#                          [-x] [-Q] [-m] [-o output_file_prefix] [-D cache_disk] [-a] [-A] [-I] [-P]
+#                          [-e errlog] [-E errlog]
+#                                            
+#     Parameters  : -l dbname - database name (default: from *.dd file name)
+#     ----------    -t table  - table name (can be supplied multiple times)
+#                   -f        - force to continue despite fatal errors
+#                   -F        - force to create despite already exists
+#                   -d        - turn debugging on
+#                   -n        - do NOT update i.e. DO NOT use -u option for dcagen.x (the default)
+#                   -u        - use option -u for dcagen.x
+#                   -i dbdir  - Database directory (default: "." i.e. current dir)
+#                   -v        - Produce verbose output
+#                   -N        - How many CPUs to use to parallelize dcagen over multiple tables (default=3)
+#                   -b        - Create binary DCA-file instead of text
+#                   -B bufsiz - Override the ODB_CACHE_LIMIT used with -c/-C (in MBytes) (default=128)
+#                   -z        - Remove zero-length DCA-files (by default NOT removed)
+#                   -g        - DCA-files (binary or text) will be gzip'ped, if possible (by default: not)
+#                   -c c at t    - Create cache of column 'c at t' values to file cache/c at t.<#>
+#                   -C c at t    - Create unpacked cache of column 'c at t' values to file cache/c at t.<#>
+#                   -q        - Quiet option : Do not print dots (....) in show progress in non-verbose mode
+#                   -x        - Extract poolno,nrows,nmdis,cardinality,min,max of column(s) given by -c/-C
+#                   -m        - Same as -x, but prints only column name followed by aggregate min & max
+#                   -Q        - Quickmode: same as -x, but quits after the first input file has been processed
+#                   -o prefix - *ALL* cacheable files will be written to file(s) cache/prefix.cache.%d. Implies -N 1
+#                                If set to %s, then prefix will be based on prevailing tablename
+#                   -D cachedisk - root-path for cache-disk i.e. ODB_CACHE_DISK (default=cache)
+#                   -a        - cache all encountered columns. Do NOT unpack them (-C colname and -A override)
+#                   -A        - cache all encountered columns. Unpack them before caching
+#                   -I        - Do *NOT* (re-)create $dbname.IOASSIGN-file (even if it did not exist)
+#                   -P        - Prevent from running odbprune recursively (f.ex. when dcagen is called from odbprune)
+#                   -e errlog - Enforce stderr output to file errlog
+#                   -E errlog - Enforce stderr output to file errlog; as -e, but append to the existing errlog
+#
+#=======================================================================
+#end
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+thisdir=$(pwd)
+
+if [[ $# -gt 0 ]] ; then
+  ARGS="${cmd} $*"
+else
+  ARGS="${cmd}"
+fi
+
+USAGE="Usage: $0 [-l dbname] [-t table] [-f] [-F] [-d] [-u] [-n]"
+USAGE="$USAGE [-i dbdir] [-v] [-N cpus] [-b] [-B bufsiz] [-z] [-g]"
+USAGE="$USAGE [-c col at table] [-C col at table] [-q] [-x] [-m] [-Q] [-o output_file_prefix]"
+USAGE="$USAGE [-D cache_disk] [-a] [-A] [-I] [-P] [-e errlog] [-E errlog]"
+
+dbname=""
+tables=""
+force2continue=0
+force2create=0
+errflg=0
+debug=""
+update="-n" # -u (update) can be 100 times slower than if -n option was used ;-(
+dbdir=.
+verbose=0
+export ODB_PARAL=${ODB_PARAL:=4}
+paral=${ODB_PARAL}
+bufsiz=""
+binary=""
+bin=0
+rmzero=0
+dogzip=0
+cachec=""
+cacheC=""
+cacheit=0
+quiet=0
+extract=0
+extract_arg=""
+quick=0
+minmax=0
+oprefix=""
+oprefix_given=0
+export ODB_CACHE_DISK=${ODB_CACHE_DISK:="cache"} # could be f.ex. "/fast/disk"
+cachedisk=${ODB_CACHE_DISK}
+allcached=""
+ALLcached=""
+create_Ioassign=1 # ... but only when $dbname.IOASSIGN was not found
+prune=1
+errlog_given=0
+errlog="/dev/null"
+
+while getopts aAbB:c:C:dD:e:E:fFgi:Il:mnN:o:PqQt:uvxz  option
+do
+  case $option in
+    a) allcached="-a"; cacheit=1;;
+    A) ALLcached="-A"; cacheit=1;;
+    b) binary="-b"; bin=1;;
+    B) bufsiz="-i $OPTARG";;
+    c) cachec="$cachec $OPTARG"; cacheit=1;;
+    C) cacheC="$cacheC $OPTARG"; cacheit=1;;
+    d) debug="-d";;
+    D) cachedisk="$OPTARG";;
+    e) errlog_given=1; errlog="$OPTARG";;
+    E) errlog_given=2; errlog="$OPTARG";;
+    f) force2continue=1;;
+    F) force2create=1;;
+    g) dogzip=1;;
+    i) dbdir=$OPTARG;;
+    I) create_Ioassign=0;;
+    l) dbname=$OPTARG;;
+    m) minmax=1; extract=1;;
+    n) update="-n";;
+    N) paral=$OPTARG;;
+    o) oprefix="-o $(basename $OPTARG)"; oprefix_given=1;;
+    P) prune=0;;
+    q) quiet=1;;
+    Q) extract=1; quick=1;;
+    t) tables="$tables$OPTARG ";;
+    u) update="-u";;
+    v) verbose=1;;
+    x) extract=1; quick=0;;
+    z) rmzero=1;;
+    *) errflg=1;;
+  esac
+done
+
+if [[ $extract -eq 1 ]] ; then
+  extract_arg="-x"
+  quiet=1
+  update="-n"
+  binary=""
+  bin=0
+  dogzip=0
+  paral=1
+  verbose=0
+  force2create=1
+  errlog_given=1; errlog="/dev/null"
+fi
+
+if [[ $errlog_given -ge 1 ]] ; then
+  if [[ $errlog_given -eq 1 ]] ; then # -e
+    exec 2>$errlog
+  else # -E
+    exec 2>>$errlog
+  fi
+fi
+
+if [[ $quiet -eq 0 ]] ; then
+  echo "$ARGS" >&2
+fi
+
+if [[ $cacheit -eq 1 && $oprefix_given -eq 1 ]] ; then
+  paral=1
+fi
+
+if [[ ! -d $dbdir ]] ; then
+  echo "***Error: Given database directory does not exist. Check your '-i dbdir'" >&2
+  errflg=2
+else
+  dbdir=$(\cd $dbdir>/dev/null 2>&1; pwd)
+  if [[ "$dbname" = "" ]] ; then
+    dbname=$(\cd $dbdir>/dev/null 2>&1; \ls -C1 *.dd 2>/dev/null | head -1)
+    dbname=$(basename $dbname .dd)
+  fi
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Unable to determine the database name. Check your '-l dbname'" >&2
+  errflg=3
+fi
+
+dbname=$(echo "$dbname" | perl -pe 's/\..*//')
+ddfile=$dbdir/$dbname.dd
+npools=0
+if [[ ! -f $ddfile ]] ; then
+  echo "***Error: Unable to locate the main metadata file (ddfile '$ddfile')" >&2
+  errflg=4
+else
+  npools=$(head -5 $ddfile | tail -1)
+fi
+
+#=======================================================================
+#   Report errors and exit
+#=======================================================================
+
+if [[ $errflg -ne 0 ]] ; then
+  echo "***Error(s) were detected" >&2
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+#=======================================================================
+# Begin processing ...
+#=======================================================================
+
+if [[ $prune -eq 1 ]] ; then
+  prunecmd="odbprune -i $dbdir"
+  if [[ $quiet -eq 1 ]] ; then
+    prunecmd="$prunecmd -q"
+  fi
+  $prunecmd || {
+    rc=$?
+    echo "***Error in $0: '$prunecmd' has failed" >&2
+    exit $rc
+  }
+fi
+
+dcadir_in=$dbdir/dca
+dcadir_out=$dbdir/dca
+
+if [[ $create_Ioassign -eq 1 && ! -f $dbdir/$dbname.IOASSIGN ]] ; then
+  #-- Make sure $dbdir/$dbname.IOASSIGN exists
+  \cd $dbdir
+  if [[ $quiet -eq 1 ]] ; then
+    create_ioassign -l $dbname -q >&2
+  else
+    create_ioassign -l $dbname >&2
+  fi
+  \cd $thisdir
+fi
+
+if [[ "$(echo "$cachedisk" | cut -c1)" != "/" ]] ; then
+  cachedisk=./$cachedisk
+fi
+export ODB_CACHE_DISK="$cachedisk"
+
+cacheall=""
+cachearg=""
+if [[ $cacheit -eq 1 ]] ; then
+  if [[ $extract -eq 0 ]] ; then
+    [[ -d $cachedisk ]] || mkdir -p $cachedisk
+  fi
+  if [[ "$cachec" != "" ]] ; then
+    cacheallc=$(echo "$cachec" | perl -pe 's/,/ /g; s/\s+/ /g;')
+    cachec=$(echo "$cachec" | perl -pe 's/,/ /g; s/\s+/ /g; s/(\S+)/-c $1/g')
+  else
+    cacheallc=""
+  fi
+  if [[ "$cacheC" != "" ]] ; then
+    cacheallC=$(echo "$cacheC" | perl -pe 's/,/ /g; s/\s+/ /g;')
+    cacheC=$(echo "$cacheC" | perl -pe 's/,/ /g; s/\s+/ /g; s/(\S+)/-C $1/g')
+  else
+    cacheallC=""
+  fi
+  cacheall="$cacheallc $cacheallC"
+  cachearg="$oprefix $ALLcached $allcached $cachec $cacheC" # Note: oprefix (-o flag) MUST BE prior to -c/-C flags
+fi
+
+if [[ "$tables" = "" ]] ; then
+  tables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+
+# reorder tables for optimal parallel dcagen: largest tables first
+# for this we need the actual cumulative filesizes for each table
+
+  TMPDIR=${TMPDIR:=/tmp}
+  sizes=$TMPDIR/sizes.pl.$$
+  cat > $sizes <<'EOF'
+use strict; my %cnt = (); my $size; my $key;
+for (<>) { next if (m/^\s*$/); s/^\s+//; s|\s+\d+/| |; ($size,$key) = split/\s+/; $cnt{$key} += $size; }
+foreach $key (keys(%cnt)) { $size = $cnt{$key}; print "$size $key\n"; }
+EOF
+
+  #-- AIX doesn't seem to support 'xargs -r', but its 'xargs' by default implies -r ...
+  xargs_r=$(echo "" | xargs -r 2>/dev/null && echo "xargs -r" || echo "xargs")
+
+  tables=$(\cd $dbdir >/dev/null 2>&1; \
+          (echo "$tables" | perl -pe 's/\s*(\w+)/0 $1\n/g;' ; \
+           find [0-9]* -type f -follow 2>/dev/null | $xargs_r ls -C1s) | \
+           perl -w $sizes | sort -nr -k1,1 | awk '{print $NF}' | perl -pe 's/\n/ /g;')
+
+  rm -f $sizes
+else
+  tables=$(echo "$tables" | perl -pe 's/,/ /g; s/\s+/ /g;')
+fi
+
+[[ $verbose -eq 0 ]] || set +xv
+
+[[ $verbose -eq 0 ]] || echo "dcagen: $(pwd) ..."
+[[ -d $dcadir_out ]] || mkdir $dcadir_out
+
+in_error=$thisdir/in_error
+rm -f $in_error
+
+function dcagen_parallel {
+  set -eu
+  typeset t=$1
+  if [[ $cacheit -eq 1 ]] ; then
+    typeset ca
+    for ca in $cacheall
+    do
+      typeset col=$(echo "$ca" | perl -pe 's/\@.*//')
+      if [[ $extract -eq 0 ]] ; then
+        rm -f $cachedisk/${col}@$t.cache.*
+      fi
+    done
+  fi
+  typeset cnt=0
+  typeset dcafile_out
+  if [[ $extract -eq 0 ]] ; then
+    dcafile_out=$dcadir_out/$t.dca
+  else
+    dcafile_out=$dcadir_out/$t.extract
+  fi
+  typeset rc=0
+  typeset nohdr=""
+  typeset gzip=""
+  [[ $dogzip -eq 0 ]] || gzip=$(whence gzip 2>/dev/null || echo "")
+  typeset v=""
+  [[ $verbose -eq 0 ]] || v="v"
+  if [[ $bin -eq 0 ]] ; then
+    typeset dcafile_in=$dcadir_in/$t.dca
+    egrep '^#DCA' $dcafile_in 2>/dev/null | egrep 'is_little$' >/dev/null 2>&1 || rc=$?
+  fi
+  if [[ $rc -ne 0 ]] || [[ $force2create -eq 1 ]] ; then
+    [[ $verbose -eq 0 ]] || echo "Creating DCA-information for table $t ..."
+    cat /dev/null > $dcafile_out
+#    for f in $(\cd $dbdir >/dev/null 2>&1; \
+#               find [0-9]* -type f -follow -name $t -print 2>/dev/null | sort -n)
+    typeset f
+    typeset poolno=0
+    while [[ $poolno -lt $npools ]]
+    do
+     ((poolno += 1))
+     f=$poolno/$t
+     if [[ -r $dbdir/$f ]] ; then
+      typeset cmd
+      cmd=$(echo "$ODB_FEBINPATH/dcagen.x $debug $update -f $ddfile -l $dbname \
+            -t $t $cachearg -p $poolno $binary $bufsiz $nohdr $extract_arg $f")
+      cmd=$(echo "$cmd" | perl -pe 's/\s+/ /g')
+
+      [[ $verbose -eq 0 ]] || echo "cd $dbdir; $cmd"
+      (\cd $dbdir >/dev/null 2>&1; $cmd) >> $dcafile_out || {
+        echo "***Error in '$cmd'" >&2
+        [[ $force2continue -eq 1 ]] || {
+           echo "***Error in '$cmd'" >> $in_error
+           exit 1
+        }
+      }
+      if [[ $extract -eq 0 && $verbose -eq 0 && $quiet -eq 0 ]] ; then # ...... printout (per every 10th)
+        ((cnt += 1))
+        typeset tst=$((cnt%10))
+        if [[ $tst -eq 1 ]] ; then
+          (echo "." | perl -pe 's/\n//' >&2)  # echo -n not available on all Junikses
+        fi
+      fi
+      nohdr="-h"
+      if [[ $quick -eq 1 ]] ; then # get out now
+        poolno=$npools
+      fi
+     fi # if [[ -r $f ]] ; then ...
+    done
+
+    if [[ $extract -eq 0 && $verbose -eq 0 && $quiet -eq 0 ]] ; then # last ..... printout
+      (echo "." | perl -pe 's/\n//' >&2)  # echo -n not available on all Junikses
+    fi
+
+    if [[ $extract -eq 1 ]] ; then
+      if [[ $minmax -eq 1 ]] ; then 
+        typeset cols=$(awk '{print $1}' < $dcafile_out | sort -u)
+        typeset ca
+        for ca in $cols
+        do
+          egrep "^$ca " $dcafile_out |\
+            awk 'BEGIN { name=""; min=1e+100; max=-1e+100;}  { \
+                 name=$1; \
+                 if ($NF > max) { max=$NF; } \
+                 if ($(NF-1) < min) { min=$(NF-1);}          } \
+                 END {print name,min,max;}'
+        done
+      else
+        cat $dcafile_out
+      fi
+      rm -f $dcafile_out
+    else
+      if [[ $bin -eq 0 ]] ; then  
+        egrep '^#DCA' $dcafile_out | head -1 > $dcafile_out.$$
+        egrep -v '^#' $dcafile_out | sort -n -k1,1 -k6,6 >> $dcafile_out.$$
+        mv $dcafile_out.$$ $dcafile_out
+      fi
+
+      if [[ -s $dcafile_out ]] ; then
+        if [[ "$gzip" != "" && -x "$gzip" ]] ; then
+          rm -f $dcafile_out.gz
+          $gzip -1$v $dcafile_out
+          if [[ -f $dcafile_out.gz ]] ; then
+            mv $dcafile_out.gz $dcafile_out
+          fi
+        fi
+      elif [[ $rmzero -eq 1 ]] ; then
+        rm -f $dcafile_out
+      fi
+    fi # if [[ $extract -eq 1 ]] ; then ... else ...
+  fi
+}
+
+subproc="&"
+if [[ $paral -le 1 ]] ; then
+  subproc=""
+  paral=1
+fi
+
+setx="";
+[[ $verbose -eq 0 ]] || setx="set -x;"
+
+[[ $verbose -eq 0 ]] || date
+n=0
+for t in $tables
+do
+  eval "($setx dcagen_parallel $t) $subproc"
+  ((n+=1))
+  if [[ -f $in_error && $force2continue -eq 0 ]] ; then
+    break
+  fi
+  [[ $((n%$paral)) -eq 0 ]] && wait
+  if [[ -f $in_error && $force2continue -eq 0 ]] ; then
+    break
+  fi
+done
+wait
+
+if [[ $extract -eq 0 ]] ; then
+  if [[ $quiet -eq 0 ]] ; then
+    [[ $verbose -eq 1 ]] || echo " "
+    [[ $verbose -eq 0 ]] || date
+  fi
+fi
+
+if [[ -f $in_error ]] ; then
+  echo "***Error: There were error(s) encountered during dcagen run(s)" >&2
+  cat $in_error >&2
+  rm -f $in_error
+  exit 1
+elif [[ $verbose -eq 1 ]] ; then
+  pwd
+  ls -Lltr $dcadir_out/*.dca 2>/dev/null || :
+  if [[ $cacheit -eq 1 && $extract -eq 0 ]] ; then
+    ls -Lltr $cachedisk 2>/dev/null || :
+  fi
+fi
+
+exit 0
+
+
diff --git a/odb/src/scripts/dcaquick b/odb/src/scripts/dcaquick
new file mode 100755
index 0000000..9630789
--- /dev/null
+++ b/odb/src/scripts/dcaquick
@@ -0,0 +1,160 @@
+#!/bin/ksh
+#begin
+#
+# Usage: dcaquick
+#
+# Creates dca/-dir from multiple database w/o reading the actual
+# data, but figuring out it from the existing databases.
+#
+# Currently the existing dca-files must be in text (not binary) format
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 13-Nov-2006
+#
+
+set -eu
+
+thisdir=$(pwd)
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+perl=$(whence perl 2>/dev/null || echo "perl")
+awk=$(whence awk 2>/dev/null || echo "awk")
+mysort=$ODB_FEBINPATH/mysort
+
+if [[ X"${ARCH:-}" = X ]] ; then
+  export ARCH=unknown
+fi
+test_arch=$(test_arch 2>/dev/null || echo "$ARCH")
+
+export ODB_PARAL=${ODB_PARAL:=3}
+paral=$ODB_PARAL
+
+abort=no
+
+#-- Determine database name (assuming you're in the (virtual) database dir right now)
+dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+if [[ "$dbname" = ".dd" ]] ; then
+  echo "***Error: Unable to locate the main metadata file (.dd)"  >&2
+  dbname=""
+  abort=yes
+fi
+
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+#-- More general case: Many dca-dirs
+
+#dirs=$(exec 2>/dev/null; \ls -ld [0-9]* | egrep "^l" | $awk '{print $NF}' | xargs -n1 dirname | sort -u || :)
+dirs=$(exec 2>/dev/null; \ls -ld [0-9]* | egrep "^l" |\
+       $awk '{print $NF}' |\
+       $perl -pe 's#/\w+[/]?$#/#;s#(\S+)/$#\1#;s#^\w+$#.#' | $mysort -u |\
+       $perl -pe 's/\s+/ /g' || :)
+
+# If any input database dirs hasn't got the dca/ directory, then
+# create global dca/ over all the given databases into the current dir and exit
+
+create_dca=0
+for dbdir in $dirs
+do
+  if [[ -d $dbdir && ! -d $dbdir/dca ]] ; then
+    create_dca=1
+    break
+  fi
+done
+
+if [[ $create_dca -eq 1 ]] ; then
+  dcagen -q -P -F -n -z
+  exit 0
+fi
+
+# Temporary dca-dir
+export TMPDIR=${TMPDIR:=/tmp}
+
+if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+  # Prefer to use RAM-disk (/dev/shm) when available
+  tmpdir=/dev/shm
+elif [[ -d "$TMPDIR" ]] ; then
+  tmpdir=$TMPDIR
+else
+  tmpdir=/tmp
+fi
+
+dcatmp=$tmpdir/dcatmp.$$
+\rm -rf $dcatmp
+mkdir -p $dcatmp
+
+# Obtain "true_pooldir;virtual_pooldir;" -pairs from "dada"
+# Assuming ls -ld gives links as follows:
+# lrwxrwxrwx  1 mps rd 47 Aug 24  2006 993 -> /hugetmp/mps/era_interim/1111/1988121612/CCMA/1
+# ==> "true_pooldir;virtual_pooldir;" becomes :
+# /hugetmp/mps/era_interim/1111/1988121612/CCMA/1;993;
+
+mapfile=$dcatmp/map.$$
+\ls -ld [0-9]* 2>/dev/null | egrep "^l" | $awk '{print $NF";"$(NF-2)";"}' > $mapfile || : &
+
+#-- create dca/-dir
+(\rm -rf dca ; mkdir dca) &
+
+# Tables (ordered; most often [thus normally the biggest] table occurring first)
+ddfile=$dbname.dd
+#tables=$(egrep "^@" $ddfile | $awk '{print $1}' | $perl -pe 's#\@# #g;')
+tables=$(\ls -C1m [0-9]* |\
+         $perl -pe 's/^\s*$//; s/:\n/ /; s/,\s*/ /g; s/^\d+\s+//; s/\s+/\n/g' |\
+         $mysort | uniq -c | $mysort -nr | $awk '{print $2}')
+
+procfile=$dcatmp/procfile.$$
+cat > $procfile <<EOF
+#!/bin/ksh
+set -eu
+t=\$1 # table name
+has_captured=0
+dcafile_out=$dcatmp/\$t.dca
+#-- To hold the capture of the 1st dca-line
+capture=$dcatmp/LINE1.\$t
+cat /dev/null > \$dcafile_out
+#-- dbdir = the original database directory in concern (e.g. /hugetmp/mps/era_interim/1111/1988121612/CCMA/)
+for dbdir in $dirs  
+do
+  dcafile_in=\$dbdir/dca/\$t.dca
+  if [[ -s \$dcafile_in ]] ; then
+    if [[ \$has_captured -eq 0 ]] ; then
+      head -1 \$dcafile_in > \$capture
+      has_captured=1
+    fi
+    #-- tpd = true_pooldir
+    for tpd in \$($awk '{if (NR > 1) print \$5}' \$dcafile_in | $mysort -u | $awk -F/ '{print \$1}')
+    do
+      #-- vpd = virtual_pooldir
+      vpd=\$($perl -ne 's/^.*;(\d+);/\$1/, print if (m#'"^\${dbdir}/\${tpd};"'#)' < $mapfile)
+      $perl -ne 's#(^.*)\s+'\$tpd/\$t'\s+(\d+)\s+(.*)#sprintf("%s %d/%s %d %s",\$1,'\$vpd,'"'\$t'",\$2+'\$vpd-\$tpd',\$3)#e, print if (m#'" \$tpd/\$t "'#)' < \$dcafile_in >> \$dcafile_out || :  
+    done
+  fi
+done
+#-- sort (as in dcagen)
+if [[ \$has_captured -eq 1 ]] ; then
+  cat \$capture > dca/\$t.dca
+  $perl -pe 's/ 2147483647 -2147483647 / 1 -1 /' < \$dcafile_out | $mysort -n +0 +5 >> dca/\$t.dca
+fi
+EOF
+
+chmod u+rx $procfile
+
+cmdfile=$dcatmp/cmdfile.$$
+cat /dev/null > $cmdfile
+
+for t in $tables
+do
+  echo "$procfile $t" >> $cmdfile
+done
+
+wait
+
+nmaxcmd=$(wc -l $cmdfile)
+env ODB_PARAL=$paral $ODB_FEBINPATH/fscheduler.x $nmaxcmd >/dev/null 2>/dev/null
+
+\rm -rf $dcatmp
+
+exit 0
diff --git a/odb/src/scripts/dd2ddl b/odb/src/scripts/dd2ddl
new file mode 100755
index 0000000..2c0a6d6
--- /dev/null
+++ b/odb/src/scripts/dd2ddl
@@ -0,0 +1,70 @@
+#!/bin/ksh
+#
+# A script to re-create DDL-file from data
+#
+# Usage: dd2ddl database_name
+#
+# For example: dd2ddl ECMA
+#
+# Author: Sami Saarinen, ECMWF, 16-Oct-2000
+#
+
+#
+# Check for SET-variable presence
+#
+# A bug prior to CY23R3/4: $-variables did not
+# enter into the DD-file at all; have to be gotten
+# from $ODB_SYSPATH/<database>.ddl_ (if exists)
+#
+
+if [[ $# -ne 1 ]] ; then
+  echo "***Error: Invalid number of arguments"
+  echo "Usage: dd2ddl database_name"
+  exit 1
+fi
+
+db=$(basename $1 | perl -pe 's/^(.*)\..*/\U$1/')
+ddl_dir=$(dirname $1)
+ddfile=$ddl_dir/$db.dd
+ddl_file=$db.sch
+
+if [[ ! -f $ddfile ]] ; then
+  echo "***Error: DD-file '$ddfile' not found"
+  exit 2
+fi
+
+egrep '^\$' $ddfile > /dev/null 2>&1
+
+if [[ $? -eq 1 ]] ; then
+  usd_found=0
+else
+  usd_found=1
+fi
+
+repeat=0
+while [[ $repeat -le 1 ]]
+do
+# Grab the default (if any) SET-variables
+  if [[ $usd_found -eq 0 && -f $ODB_SYSPATH/$db.ddl_ ]] ; then
+    egrep ^SET $ODB_SYSPATH/$db.ddl_ > $ddl_file
+  else
+    cat /dev/null > $ddl_file
+  fi
+
+# Translate : .dd -> .ddl (or .sch, rather)
+  echo "Creating '$ddl_file' ..."
+  $ODB_FEBINPATH/dd2ddl.x < $ddfile >> $ddl_file
+
+# Check if any SET-variables present; if not, then redo once
+# with usd_found=0
+
+  egrep ^SET $ddl_file >/dev/null 2>&1
+  if [[ $? -eq 0 ]] ; then
+    repeat=2
+  else
+    repeat=$((repeat + 1))
+    usd_found=0
+  fi
+done
+
+exit 0
diff --git a/odb/src/scripts/ddl2flags.pl b/odb/src/scripts/ddl2flags.pl
new file mode 100644
index 0000000..72761c8
--- /dev/null
+++ b/odb/src/scripts/ddl2flags.pl
@@ -0,0 +1,90 @@
+use strict;
+
+#my @in=<DATA>;
+
+my %var=();
+
+#for (@in) {
+for (<>) {
+    chomp;
+    s/^\s*//;
+    next if (m/^$/  ||
+	     m#^//# ||
+	     m/RESET/i);
+    if (m/^SET\s+(\S+)\s*=\s*(\d+)\b\s*/i) {
+	my $tmp = lc($1);
+	$var{$tmp} = $2;
+	next;
+    }
+    s/\s+//g;
+    s/^(.*)/\L$1/;
+    if (m/^(align|onelooper)\((.*)\)/) {
+      my $kind = ($1 eq "align") ? "A" : "1";
+      $_ = $2;
+      my @v = split(/,/);
+      my $first = shift @v;
+      print "-$kind$first=";
+      my @tmp = ();
+      for (@v) {
+	if (m/\[/) {
+	  if (m/(\w+)\[(\S+):(\S+)\]/) {
+	    my $name = $1;
+	    my $a = &getval($2);
+	    my $b = &getval($3);
+	    if ($a <= $b) {
+	      for ($a .. $b) {
+		my $abs = ($_ >= 0) ? $_ : -$_;
+		push(@tmp,($_ >= 0) ? "${name}_$abs" : "${name}__$abs");
+	      }
+	    }
+	  }
+	  elsif (m/(\w+)\[(\S+)\]/) {
+	    my $name = $1;
+	    $_ = &getval($2);
+	    my $abs = ($_ >= 0) ? $_ : -$_;
+	    push(@tmp,($_ >= 0) ? "${name}_$abs" : "${name}__$abs");
+	  }
+	}
+	else {
+	  push(@tmp,$_);
+	}
+      }
+      @v = @tmp;
+      my $separ = ($#v == 0) ? "" : "(";
+      for (@v) {
+	print "$separ$_";
+	$separ = ",";
+      }
+      print ")" if ($#v > 0);
+      print "\n";
+    }
+}
+
+sub getval {
+  my ($x) = @_;
+  if ($x =~ m/^[-+]?\d+$/) {
+    return $x; # is an integer
+  }
+  elsif (defined($var{$x})) {
+    return $var{$x};
+  }
+  else {
+    return -2147483647;
+  }
+}
+
+__DATA__
+
+//SET $NMXUPD=3;
+
+// Aligned tables (contain the same no. of rows when requested over the @LINK)
+RESET ALIGN;
+ALIGN(body,errstat,update[1:$NMXUPD],scatt_body,ssmi_body);
+ALIGN(atovs,atovs_pred);
+
+// @LINKs with maximum jump of one ("one-loopers")
+// Rows in these tables have one-to-one correspondence over the @LINK
+RESET ONELOOPER;
+ONELOOPER(index,hdr);
+ONELOOPER(hdr,sat);
+ONELOOPER(sat,atovs,ssmi,scatt[-2:$nmxupd],satob,reo3[$nmxupd]);
diff --git a/odb/src/scripts/latlon_rad b/odb/src/scripts/latlon_rad
new file mode 100755
index 0000000..e189483
--- /dev/null
+++ b/odb/src/scripts/latlon_rad
@@ -0,0 +1,47 @@
+#!/bin/ksh
+#
+# latlon_rad [-s]
+#
+# Quickly establishes whether (lat,lon) are in radians or degrees
+#
+# Returns 1, if in radians, 0 if not and -1 if could not be determined
+#
+# Use -s (s for slow) to scan all pool files.
+# By default uses quick mode and checks the very first pool only
+#
+# (lat,lon) are assumed to be lat at hdr and lon at hdr
+# Override via ODB_LAT and ODBLON, respectively
+#
+
+set -eu
+
+mode="-mxQ"
+if [[ $# -ge 1 ]] ; then
+  if [[ $1 -eq '-s' ]] ; then
+    mode="-mx"
+  else
+    echo "Usage: latlon_rad [-s]" >&2
+    exit 1
+  fi
+fi
+
+export ODB_LAT=${ODB_LAT:="lat at hdr"}
+export ODB_LON=${ODB_LON:="lon at hdr"}
+
+tables=$(echo "${ODB_LAT} ${ODB_LON}" |\
+         perl -pe 's/\w+\@(\w+)\b/$1/g; s/[,:\s]+/\n/g' | sort -u)
+
+# pi
+pi=$(echo "4*a(1)" | bc -l)
+eps=0.01  # Added to pi to just accept abs(values) < pi + eps
+#eps=$pi  # treat abs(lat,lon-values) < 2*pi as radians
+
+(echo "$pi $eps"; 
+ dcagen $mode -t "$tables" -c "${ODB_LAT}" -c "${ODB_LON}" 2>/dev/null) |\
+awk 'BEGIN { res=0; nrec=0; } { \
+     if (NR==1) { pi=$1; eps=$2; gaagaa=pi+eps; } else { nrec++;\
+        if ($2 > -gaagaa && $3 < gaagaa) { res++; } } } \
+     END { if (nrec==0) { res=-1; } else { res/=nrec; } \
+           printf("%d\n",res); }'
+
+
diff --git a/odb/src/scripts/latlonrad b/odb/src/scripts/latlonrad
new file mode 120000
index 0000000..e18dc52
--- /dev/null
+++ b/odb/src/scripts/latlonrad
@@ -0,0 +1 @@
+latlon_rad
\ No newline at end of file
diff --git a/odb/src/scripts/makegp.ksh b/odb/src/scripts/makegp.ksh
new file mode 100755
index 0000000..47cd23c
--- /dev/null
+++ b/odb/src/scripts/makegp.ksh
@@ -0,0 +1,259 @@
+#!/bin/ksh
+
+set -eu
+
+bname=$(basename $0)
+
+: ${terminal:=}
+: ${title:=}
+: ${size:=}
+: ${origin:=}
+: ${rotate_x:=60}
+: ${rotate_z:=30}
+: ${scale_x:=1}
+: ${scale_z:=1}
+: ${xdata:=}
+: ${ydata:=}
+: ${zdata:=}
+: ${timefmt:=}
+: ${xlabel:=}
+: ${formatx:=}
+: ${minx:=}
+: ${maxx:=}
+: ${ylabel:=}
+: ${formaty:=}
+: ${miny:=}
+: ${maxy:=}
+: ${zlabel:=}
+: ${formatz:=}
+: ${minz:=}
+: ${maxz:=}
+: ${key:=}
+: ${plotting:=plot}
+: ${usings:=}
+: ${items:=}
+: ${styles:=}
+: ${lw:=}
+: ${boxwidth:=}
+: ${regexp:='\(.*\)'}
+: ${postload:=}
+
+function Usage
+{
+cat 1>&2 <<EOF
+Usage: $(basename $0) files
+       [--title=TITLE]
+       [--size=SIZE]
+       [--origin=ORIGIN]
+       [--rotate_x=ROTATE_X]
+       [--rotate_z=ROTATE_Z]
+       [--scale_x=SCALE_X]
+       [--scale_z=SCALE_Z]
+       [--xdata=XDATA]
+       [--ydata=YDATA]
+       [--timefmt=TIMEFMT]
+       [--xlabel=X LABEL]
+       [--formatx=FORMAT OF X]
+       [--minx=MINIMUM OF X]
+       [--maxx=MAXIMUM OF X]
+       [--ylabel=Y LABEL]
+       [--formaty=FORMAT OF Y]
+       [--miny=MINIMUM OF Y]
+       [--maxy=MAXIMUM OF Y]
+       [--zlabel=Z LABEL]
+       [--formatz=FORMAT OF Z]
+       [--minz=MINIMUM OF Z]
+       [--maxz=MAXIMUM OF Z]
+       [--key=KEY]
+       [--plotting=PLOTTING (defalut ${plotting})]
+       [--usings=USINGS]
+       [--items=ITEMS]
+       [--styles=STYLES]
+       [--lw=LINESWIDTH]
+       [--boxwidth=BOXWIDTH]
+       [--regexp=REGEXP (default ${regexp})]
+EOF
+
+exit 1
+}
+
+while [ $# -gt 0 ]
+do
+    case $1 in
+        --vname=*) vname="${vname:+${vname} }$(echo "$1" | sed -e's/--vname=//')" ;;
+        --boxwidth=* | --formatx=* | --formaty=* | --formatz=* | --key=* | --maxx=* | --maxy=* | --maxz=* | --minx=* | --miny=* | --minz=* | --origin=* | --plotting=* | --regexp=* | --rotate_x=* | --rotate_z=* | --scale_x=* | --scale_z=* | --size=* | --terminal=* | --timefmt=* | --title=* | --xdata=* | --xlabel=* | --ydata=* | --ylabel=* | --zdata=* | --zlabel=*)
+            vname=$(echo "$1" | sed -e's/^--//' -e's/=.*$//')
+            eval ${vname}=\"$(echo "$1" | sed -e"s/^--${vname}=//" | awk '{printf("%s",$0)}')\"
+            ;;
+        --lw=* | --postload=* | --styles=* | --usings=*)
+            vname=$(echo "$1" | sed -e's/^--//' -e's/=.*$//')
+            eval ${vname}=\"\${${vname}:+\${${vname}} }$(echo "$1" | sed -e"s/^--${vname}=//" | awk '{printf("%s",$0)}')\"
+            ;;
+        --items=*)
+            vname=$(echo "$1" | sed -e's/^--//' -e's/=.*$//')
+            eval ${vname}=\"\${${vname}:+\${${vname}},}$(echo "$1" | sed -e"s/^--${vname}=//" | awk '{printf("%s",$0)}')\"
+            ;;
+        --*)
+            echo ${bname}: illegal option $1 1>&2
+            Usage
+            ;;
+	*)  break ;;
+    esac
+
+    shift
+done
+
+: ${*:?}
+
+if [ -z "${usings}" ]; then
+    if [ "${plotting}" = splot ]; then
+        usings=1:2:3
+    else
+        case ${styles} in
+            xyerrorbars) usings=1:2:3:4:5:6 ;;
+            yerrorbars) usings=1:2:3:4 ;;
+            errorbars) usings=1:2:3 ;;
+            *)  usings=1:2 ;;
+        esac
+    fi
+fi
+
+cbuf=${styles}
+styles=
+field=1
+for using in ${usings}
+do
+    style=$(echo ${cbuf} | awk -v field=${field} '{print $field}')
+    if [ -n "${style}" ];then
+        styles="${styles:+${styles} }${style}"
+    else
+        if [ "${plotting}" = splot ];then
+            styles="${styles:+${styles} }linespoints"
+        else
+            case $(echo "${using}" | awk -F: '{print NF}') in
+                6) styles="${styles:+${styles} }xyerrorbars" ;;
+                4) styles="${styles:+${styles} }yerrorbars" ;;
+                3) styles="${styles:+${styles} }errorbars" ;;
+                *) styles="${styles:+${styles} }points" ;;
+            esac
+        fi
+    fi
+    ((field+=1))
+done
+
+if [ -n "${terminal}" ]; then
+    case ${terminal} in
+        *) echo set terminal ${terminal} ;;
+    esac
+fi
+
+for vname in boxwidth origin size xdata ydata zdata
+do
+    if [ -n "`eval echo \\${${vname}}`" ]; then
+        eval echo set ${vname} \${${vname}}
+    fi
+done
+
+for vname in output timefmt title xlabel ylabel zlabel
+do
+    if [ -n "`eval echo \\${${vname}}`" ]; then
+        eval echo set ${vname} '\"'\${${vname}}'\"'
+    fi
+done
+
+test -n "${formatx}" && echo set format x \"${formatx}\"
+test -n "${formaty}" && echo set format y \"${formaty}\"
+test -n "${formatz}" && echo set format z \"${formatz}\"
+
+if [ "${plotting}" = splot ]; then
+    cat <<EOF
+rotate_x=${rotate_x}
+rotate_z=${rotate_z}
+scale_x=${scale_x}
+scale_z=${scale_z}
+set view rotate_x, rotate_z, scale_x, scale_z
+EOF
+fi
+
+if [ "${key}" = nokey ];then
+    echo set ${key}
+elif [ -n "${key}" ];then
+    echo set key ${key}
+fi    
+
+if [ "${xdata}" = time ]; then
+    test -n "${minx}" && minx=\"${minx}\"
+    test -n "${maxx}" && maxx=\"${maxx}\"
+fi
+
+if [ "${ydata}" = time ]; then
+    test -n "${miny}" && miny=\"${miny}\"
+    test -n "${maxy}" && maxy=\"${maxy}\"
+fi
+
+if [ "${zdata}" = time ]; then
+    test -n "${minz}" && minz=\"${minz}\"
+    test -n "${maxz}" && maxz=\"${maxz}\"
+fi
+
+nusing=$(echo ${usings} | awk '{print NF}')
+
+if [ "${plotting}" = splot ];then
+    echo ${plotting} [ ${minx} : ${maxx} ] [ ${miny} : ${maxy} ] [ ${minz} : ${maxz} ] \\
+else
+    echo ${plotting} [ ${minx} : ${maxx} ] [ ${miny} : ${maxy} ] \\
+fi
+
+i=1
+while [ $# -gt 0 ]
+do
+    fname=$1
+
+    if [ ${nusing} -gt 1 ];then
+        group=
+    else
+        case ${regexp} in
+            [0-9]*) 
+                group=$(echo ${fname} | awk -v field=${regexp} '{print $field}')
+                ;;
+            *)  group=$(expr "${fname}" : ${regexp}) || true ;;
+        esac
+    fi
+
+    field=1
+    for using in ${usings}
+    do
+        if [ ${nusing} -le 1 ];then
+            item=
+        else
+            item=$(echo ${items} | awk -F , -v field=${field} '{print $field}')
+        fi
+        item="${group}${item:+ ${item}}"
+
+        style=$(echo ${styles} | awk -v field=${field} '{print $field}')
+        with="${style:+${style}}${lw:+ lw ${lw}}"
+
+        if [ ${i} -eq 1 ] && [ ${field} -eq 1 ];then
+            :
+        else
+            echo ',\'
+        fi
+
+        echo " \"${fname}\" ${using:+using ${using}} ${item:+title \"${item}\"} ${with:+with ${with}}" | awk '{printf("%s",$0)}'
+
+	((field+=1))
+    done
+
+    ((i+=1))
+
+    shift
+done
+
+echo
+
+for fname in ${postload}
+do
+    echo load \"${fname}\"
+done
+
+exit 0
diff --git a/odb/src/scripts/newodb b/odb/src/scripts/newodb
new file mode 100755
index 0000000..82ff361
--- /dev/null
+++ b/odb/src/scripts/newodb
@@ -0,0 +1,53 @@
+#!/bin/ksh
+#
+# Introduces new database(s) and creates static linking "glue" for use by 
+#
+# Usage: newodb [-z] [dbname1] [dbname2] ... [dbnameN] 
+#
+# Author: Sami Saarinen, ECMWF, 2003-2006
+#
+#
+
+echo "Running: $0 $*"
+
+if [[ $# -lt 1 ]] ; then
+  head -6 $0 | tail -5
+  exit 1
+fi
+
+set -eu
+
+empty_tables=""
+
+if [[ "$1" = "-z" ]] ; then
+  empty_tables="-z"
+  shift
+fi
+
+errflg=0
+for arg in $*
+do
+  db=$(basename $arg | perl -pe 's/\s+//g; s/\..*$//; s/[_-]//g; tr/a-z/A-Z/')
+  if [[ ! -f $db.ddl && ! -f $db.sch ]] ; then
+    echo "***Error: Unable to locate data layout or schema file ($db.ddl/$db.sch) for db=$db"
+    errflg=1
+  elif [[ -f $db.ddl ]] ; then
+    odbcomp $empty_tables -l $db $db.ddl
+  elif [[ -f $db.sch ]] ; then
+    odbcomp $empty_tables -l $db $db.sch
+  fi
+done
+
+if [[ $errflg -eq 1 ]] ; then
+  exit 3
+fi
+
+create_odbglue $*
+
+odbglue=_odb_glue.c
+odbglue_o=_odb_glue.o
+
+if [[ ! -f $odbglue_o ]] || [[ $odbglue -nt $odbglue_o ]] ; then
+  echo odbcc -c $odbglue
+  exec odbcc -c $odbglue
+fi
diff --git a/odb/src/scripts/odb1to4 b/odb/src/scripts/odb1to4
new file mode 100755
index 0000000..13d6686
--- /dev/null
+++ b/odb/src/scripts/odb1to4
@@ -0,0 +1,170 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+
+#begin
+#
+# odb4to1 : converts database's I/O-method#1 to #4
+#           using hcat-utility
+#
+# Usage : odb1to4 [dbdir]
+#
+#
+#end
+
+set -eu
+
+if [[ $# -eq 1 ]] ; then
+  dbdir=$1
+  shift
+  if [[ ! -d $dbdir ]] ; then
+    echo "***Error: Unable to locate database directory '$dbdir'"
+    exit 1
+  else
+    \cd $dbdir
+  fi
+fi
+
+mysort=$ODB_FEBINPATH/mysort
+
+dbname=$(basename "$(\ls -C1 *.dd 2>/dev/null | head -1)" .dd)
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Unable to determine database name"
+  exit 2
+fi
+
+ddfile=$dbname.dd
+
+iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+if [[ $iom -ne 1 ]] ; then
+  echo "***Error: Database '$dbname' I/O-method is not #1"
+  exit 3
+fi
+
+npools=$(head -5 $ddfile | tail -1)
+ntables=$(head -6 $ddfile | tail -1)
+tables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+orig_tables=$tables
+
+\rm -rf _
+mkdir _
+
+export TMPDIR=${TMPDIR:=/tmp}
+
+cmdfile=$TMPDIR/cmdfile.$$
+cat /dev/null > $cmdfile
+
+export ODB_PARAL=${ODB_PARAL:=3}
+paral=$ODB_PARAL
+
+if [[ $paral -eq 1 ]] ; then
+  echo '#!/bin/ksh' >> $cmdfile
+  echo 'set -eu'    >> $cmdfile
+  chmod u+rx $cmdfile
+fi
+
+in_error=$TMPDIR/in_error.$$
+\rm -f $in_error
+
+# reorder tables for optimal parallel dcagen: largest tables first
+# for this we need the actual cumulative filesizes for each table
+
+sizes=$TMPDIR/sizes.pl.$$
+cat > $sizes <<'EOF'
+use strict; my %cnt = (); my $size; my $key;
+for (<>) { next if (m/^\s*$/); s/^\s+//; s|\s+\d+/| |; 
+($size,$key) = split/\s+/; $cnt{$key} += $size; }
+foreach $key (keys(%cnt)) { $size = $cnt{$key}; print "$size $key\n"; }
+EOF
+
+#-- AIX doesn't seem to support 'xargs -r', but its 'xargs' by default implies -r ...
+xargs_r=$(echo "" | xargs -r 2>/dev/null && echo "xargs -r" || echo "xargs")
+
+tables=$(\
+    (echo "$tables" | perl -pe 's/\s*(\w+)/0 $1\n/g;' ; \
+    find [0-9]* -type f -follow | $xargs_r ls -C1s) | \
+    perl -w $sizes | $mysort -nr +0 | awk '{print $NF}' | perl -pe 's/\n/ /g;')
+
+\rm -f $sizes
+
+export ODB_IO_GRPSIZE=${ODB_IO_GRPSIZE:=$npools}
+export ODB_IO_FILESIZE=${ODB_IO_FILESIZE:=128}    # in MBytes
+
+grpsize=${ODB_IO_GRPSIZE}
+filesize=${ODB_IO_FILESIZE}
+
+for t in $tables
+do
+  echo "$ODB_FEBINPATH/hcat -14 -l $dbname -t $t -n $npools -L $filesize -G $grpsize > iomap.$t || touch $in_error" >> $cmdfile
+done
+
+export ODB_DATAPATH_$dbname=.
+export ODB_SRCPATH_$dbname=.
+export IOASSIGN=$dbname.IOASSIGN
+
+if [[ $paral -eq 1 ]] ; then
+  $cmdfile
+else
+  nmaxcmd=$(wc -l $cmdfile)
+  env ODB_PARAL=$paral $ODB_FEBINPATH/fscheduler.x $nmaxcmd
+fi
+\rm -f $cmdfile
+
+if [[ -f $in_error ]] ; then
+  echo "***Error: There were error(s) in 1-to-4 creation"
+  \rm -f $in_error
+  exit 4
+fi
+
+#-- Alter .dd-file
+awk '{ if (NR == 1) { print $1,$2,4; } else { print; }}' < $ddfile > $ddfile.tmp
+\mv $ddfile.tmp $ddfile
+
+#-- Create I/O-map (see also odb/lib/fwrite_iomap.F90)
+cat > $dbname.iomap <<EOF
+              1
+$dbname.iomap
+EOF
+
+echo "$ntables $npools $grpsize" | awk '{printf("%15d%15d%15d\n",$1,$2,$3);}' >> $dbname.iomap
+
+npad=0 # note : no padding; see concat_file routine in odb/tools/hcat.c
+iom=4
+lenmult=1
+echo "$npad $iom $lenmult" | awk '{printf("%15d%15d%15d\n",$1,$2,$3);}' >> $dbname.iomap
+
+eor=1
+jt=0
+for t in $orig_tables
+do
+  ((jt+=1))
+  if [[ -s iomap.$t ]] ; then # file exists and its size is > 0 bytes
+    ncols=$(head -1 iomap.$t) 
+    echo "$jt $ncols @$t" | awk '{printf("%15d%15d %s\n",$1,$2,$3);}' >> $dbname.iomap
+    awk '{if (NR > 1) printf("%15d%15d%15d%15d%15d\n",$1,$2,$3,$4,$5);}' < iomap.$t >> $dbname.iomap
+  else # an empty file/or does not exist at all
+    ncols=-1 # legal according to odb/lib/fwrite_iomap.F90
+    echo "$jt $ncols @$t" | awk '{printf("%15d%15d %s\n",$1,$2,$3);}' >> $dbname.iomap
+  fi
+  echo "$eor" | awk '{printf("%15d%15d%15d%15d%15d\n",-$1,-$1,-$1,-$1,-$1);}' >> $dbname.iomap
+  \rm -f iomap.$t
+done
+
+echo "$eor" | awk '{printf("%15d%15d EOF\n",-$1,-$1);}' >> $dbname.iomap
+
+#-- Remove existing data dirs
+\rm -rf [0-9]*
+
+#-- Bring the re-generated data dirs one level up
+\mv _/[0-9]* .
+\rm -rf _
+
+#-- Re-generate DCAs
+\rm -rf dca
+dcagen -z -F -n -q 2>/dev/null || :
+dcafix -q
+
+#-- Clean-up
+odbclean -f
+
+
+
diff --git a/odb/src/scripts/odb2netcdf b/odb/src/scripts/odb2netcdf
new file mode 100755
index 0000000..6723b7a
--- /dev/null
+++ b/odb/src/scripts/odb2netcdf
@@ -0,0 +1,302 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15 
+#begin
+#
+# odb2netcdf : ODB interface to NetCDF
+#
+# Usage: odb2netcdf [-l dbname] [-v sqlfile1 ... [-v sqlfileN]]
+#                   [-q 'select_data_query']  : Supply your data query straight here!
+#                   [-t table_name]  : Supply a table name -- with or w/o '@'
+#                   [-p poolno]      : pool number to be processed ; can be supplied multiple times
+#                   [-n NPES]        : number of MPI-tasks (limited to 8)
+#                   [-N NPES]        : number of MPI-tasks ("unlimited")
+#                   [-j jobid]       : job identification ; if not supplied -> process id [non-odbsql only]
+#                   [-c name_configuration_file] : supply your own mods to std name configuration file
+#                   [-C]             : bypass name configuration processing altogether
+#                   [-r]             : re-use executable from previous call -> no compilations
+#                   [-P]             : for switching NetCDF packing OFF (by default is ON)
+#                   [-d]             : for debug mode
+#                   [-5]             : do NOT use fast I/O-method#5
+#                   [-m]             : merge results (of each view) into single file (valid for NPES=1 only)
+#                                      Please note that with odbsql-interface we always merge;
+#                                      If you want pool-by-pool results with odbsql, run this against
+#                                      each pool via -p <each_pool_in_turn>
+#                   [-F]             : do NOT use the fast odbsql interface
+#                   [-b]             : show progress bar (odbsql-approach only)
+#
+#     You have supply at least one SQL (or a table-name) via -v option
+#     or supply a data query directly via -q option, in which case query goes to file "myview.sql"
+#
+#end
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+namecfg=""
+no_namecfg=0
+debug=0
+nopacking=0
+dbname=""
+sqlfiles=""
+poolmask=""
+npes=1
+maxpes=8
+jobid=$$
+reuse=0
+errflg=0
+io_method=5
+query=""
+query_given=0
+merge=""
+fast=1
+progress_bar="-B"
+
+FLAGS=CdPrc:l:v:p:n:N:j:5q:mFbt:
+
+while getopts $FLAGS option
+do
+  case $option in
+    C) no_namecfg=1;;
+    d) debug=1;;
+    P) nopacking=1;;
+    r) reuse=1;;
+    c) namecfg=$OPTARG;;
+    l) dbname=$OPTARG;;
+    v) sqlfiles="$sqlfiles $OPTARG";;
+    t) sqlfiles="$sqlfiles @$OPTARG";;
+    p) poolmask="$poolmask $OPTARG";;
+    j) jobid=$OPTARG;;
+    n) npes=$OPTARG;;
+    N) npes=$OPTARG; maxpes=99999;;
+    5) io_method=0;;
+    q) query_given=1; query="$OPTARG"; sqlfiles="$sqlfiles myview.sql";;
+    m) merge="-m";;
+    F) fast=0;;
+    b) progress_bar="-b";;
+   \?) errflg=1;;
+  esac
+done
+
+if [[ "$dbname" = "" ]] ; then
+  dbname=$(basename "$(\ls -C1 *.dd 2>/dev/null | head -1)" .dd)
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Database name (-l dbname) must be given"
+  errflg=1
+fi
+
+if [[ "$sqlfiles" = "" ]] ; then
+  echo "***Error: At least one sqlfile or table name must be given"
+  errflg=1
+fi
+
+if [[ $errflg -eq 1 ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+if [[ $query_given -eq 1 ]] ; then
+  echo "$query" > myview.sql
+fi
+
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g; s/[,]+/,/g')
+fi
+
+if [[ $nopacking -eq 1 ]] ; then
+  export ODB_NETCDF_NOPACKING=1
+else
+  export ODB_NETCDF_NOPACKING=0
+fi
+
+# check number of PEs and limit up to maxpes PEs
+if [[ $npes -lt 1 ]] ; then
+  npes=1
+fi
+if [[ $npes -gt $maxpes ]] ; then
+  npes=$maxpes
+fi
+
+if [[ $fast -eq 1 ]] ; then
+  #-- Do use odbsql -f netcdf -approach [the default]
+  rc=0
+  for sql in $sqlfiles
+  do
+    prefix=$(basename $sql | sed 's/\..*//')
+    sql=$(dirname $sql)/${prefix}.sql
+    cmd="odbsql -k -f netcdf $progress_bar"
+    if [[ "$poolmask" != "" ]] ; then
+      cmd="$cmd -p $poolmask"
+    fi
+    if [[ -f $sql ]] ; then
+      cmd="$cmd -v $sql"
+    else
+      tbl=$(echo "$prefix" | sed 's/@//g')
+      cmd="$cmd -v @$tbl"
+    fi
+    if [[ $npes -gt 1 ]] ; then
+      cmd="$cmd -n $npes"
+    fi
+    $cmd || rc=$?
+    [[ $rc -eq 0 ]] || break
+  done
+  exit $rc
+fi
+
+#--- Proceed with old-fashioned way (compilations etc. krap !) ...
+
+export NPES=$npes
+echo "Using NPES MPI-tasks: NPES=$NPES"
+
+Exe=./odb2netcdf.x
+if [[ ! -x $Exe ]] ; then
+  reuse=0
+fi
+
+if [[ ! -f lib$dbname.a ]] || \
+   [[ ! -f $dbname.ddl_ ]] || \
+   [[ ! -f ${dbname}.h  ]] || \
+   [[ $ODB_FEBINPATH/odb98.x -nt $dbname.ddl_ ]] || \
+   [[ $dbname.ddl -nt $dbname.ddl_ ]] ; then
+  newodb -z $dbname
+  reuse=0
+fi
+
+views=""
+consider=""
+
+for sql in $sqlfiles
+do
+  prefix=$(basename $sql | sed 's/\..*//')
+  sql=$(dirname $sql)/${prefix}.sql
+  if [[ -f $sql ]] ; then
+    views="$views -v $prefix"
+    if [[ -f $Exe && $sql -nt $Exe ]] ; then
+      reuse=0
+    fi
+  else
+    tbl=$(echo "$prefix" | sed 's/@//g')
+    consider="$consider $tbl"
+    views="$views -v @$tbl"
+  fi
+done
+
+if [[ $reuse -eq 0 ]] ; then
+  viewfiles=""
+  for sql in $sqlfiles
+  do
+    prefix=$(basename $sql | sed 's/\..*//')
+    sql=$(dirname $sql)/${prefix}.sql
+    if [[ -f $sql ]] ; then
+      viewfiles="$viewfiles $sql"
+    fi
+  done
+  if [[ "$viewfiles" != "" ]] ; then
+    odbcomp -w -l $dbname $viewfiles
+  fi
+fi
+
+if [[ "$consider" = "" ]] ; then
+  # the following hassle defines you the ODB_CONSIDER_TABLES (part#1)
+  export ODB_CONSIDER_TABLES=""
+  for cf in $(\ls -C1 ${dbname}_[a-z]*.c 2>/dev/null || :)
+  do
+    eval `fgrep '#define ODB_CONSIDER_TABLES' $cf | awk '{print "export",$2"="$3}'`
+    ODB_CONSIDER_TABLES=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 'tr/A-Z/a-z/; s|/| |g;')
+    consider="$consider $ODB_CONSIDER_TABLES"
+  done
+  unset ODB_CONSIDER_TABLES
+fi
+
+if [[ "$consider" != "" ]] ; then
+  star=$(echo "$consider" | perl -pe 's/^.*\*.*/*/')
+  if [[ "$star" = '*' ]] ; then
+    export ODB_CONSIDER_TABLES='*'
+  else
+    # the following hassle defines you the ODB_CONSIDER_TABLES (part#2)
+    export ODB_CONSIDER_TABLES=$(echo "$consider" | perl -pe 's/\s*(\w+)\b/$1\n/g;' |\
+                                 sort -u | perl -pe 's/\n//g; s#\s*(\w+)\b#/$1#g; END {print "/";}')
+  fi
+else
+  export ODB_CONSIDER_TABLES='*'
+fi
+
+echo "==> ODB_CONSIDER_TABLES=$ODB_CONSIDER_TABLES"
+
+if [[ "$poolmask" != "" ]] ; then
+  export ODB_PERMANENT_POOLMASK="$poolmask"
+  echo "==> ODB_PERMANENT_POOLMASK=$ODB_PERMANENT_POOLMASK"
+fi
+
+rm_namecfg=0
+if [[ $no_namecfg -eq 1 ]] ; then
+  export ODB_NAMECFG_$dbname=/dev/null
+  echo "==> Name configuration processing bypassed"
+elif [[ -r "$namecfg" ]] ; then
+  tmp=$(eval echo \$ODB_NAMECFG_$dbname 2>/dev/null || :)
+  if [[ "$tmp" = "" ]] ; then
+    tmp=$(echo $ODB_NAMECFG 2>/dev/null || :)
+  fi
+  if [[ -r "$tmp" ]] ; then
+    tmp_namecfg=tmp_namecfg.$$
+    cat $tmp $namecfg > $tmp_namecfg || :
+    rm_namecfg=1
+  else
+    tmp_namecfg=$namecfg
+  fi
+  export ODB_NAMECFG_$dbname="$tmp_namecfg"
+  echo "==> ODB_NAMECFG_$dbname=$tmp_namecfg"
+fi
+
+if [[ $debug -eq 1 ]] ; then
+  export ODB_NETCDF_DEBUG=1
+  export ODB_IO_TRACE=1
+else
+  export ODB_NETCDF_DEBUG=0
+fi
+echo "==> ODB_NETCDF_DEBUG=$ODB_NETCDF_DEBUG"
+
+echo "==> ODB_NETCDF_NOPACKING=$ODB_NETCDF_NOPACKING"
+
+if [[ -f $Exe && $ODB_LIBPATH/libodbmain.a -nt $Exe ]] ; then
+  reuse=0
+fi
+
+if [[ $reuse -eq 0 ]] ; then
+  obj=Odb2netcdf.o
+  if [[ ! -f $obj ]] || [[ $ODB_LIBPATH/libodbmain.a -nt $obj ]] ; then
+    ar x $ODB_LIBPATH/libodbmain.a $obj
+  fi
+
+  odbf90mp -o $Exe $obj -L. -l$dbname
+fi
+
+if [[ $io_method -eq 5 ]] ; then
+  if [[ "$ODB_CONSIDER_TABLES" = '*' ]] ; then
+    tables=""
+  else
+    tables=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 's#/(\w+)# -t $1#g; s#/##g;')
+  fi
+  dbdir=.
+  if [[ ! -d $dbdir/dca ]] ; then
+    mkdir $dbdir/dca
+  else
+    dcafix $dbdir/dca/*.dca 2>/dev/null
+  fi
+  dcagen -l $dbname $tables -n
+  export ODB_IO_METHOD=5
+#  unset ODB_CONSIDER_TABLES
+fi
+
+#export ODB_CATCH_SIGNALS=1
+#export ODB_ERRTRA=1
+echo  "mpirun.ibm -np $NPES $Exe -l $dbname $views $merge -j $jobid"
+       mpirun.ibm -np $NPES $Exe -l $dbname $views $merge -j $jobid
+
+if [[ $rm_namecfg -eq 1 ]] ; then
+  rm -f $tmp_namecfg
+fi
+
+exit 0
diff --git a/odb/src/scripts/odb4to1 b/odb/src/scripts/odb4to1
new file mode 100755
index 0000000..22d379b
--- /dev/null
+++ b/odb/src/scripts/odb4to1
@@ -0,0 +1,127 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+
+#begin
+#
+# odb4to1 : converts database's I/O-method#4 to #1
+#           using hcat-utility
+#
+# Usage : odb4to1
+#
+#end
+
+set -eu
+
+mysort=$ODB_FEBINPATH/mysort
+
+dbname=$(basename "$(\ls -C1 *.dd 2>/dev/null | head -1)" .dd)
+if [[ "$dbname" = "" ]] ; then
+  echo "***Error: Unable to determine database name"
+  exit 1
+fi
+
+if [[ ! -f $dbname.iomap ]] ; then
+  echo "***Error: Database '$dbname' has no I/O-map file"
+  exit 2
+fi
+
+ddfile=$dbname.dd
+
+iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+if [[ $iom -ne 4 ]] ; then
+  echo "***Error: Database '$dbname' I/O-method is not #4"
+  exit 3
+fi
+
+npools=$(head -5 $ddfile | tail -1)
+
+tables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+
+\rm -rf _
+mkdir _
+
+export TMPDIR=${TMPDIR:=/tmp}
+
+cmdfile=$TMPDIR/cmdfile.$$
+cat /dev/null > $cmdfile
+
+export ODB_PARAL=${ODB_PARAL:=3}
+paral=$ODB_PARAL
+
+if [[ $paral -eq  1 ]] ; then
+  echo '#!/bin/ksh' >> $cmdfile
+  echo 'set -eu'    >> $cmdfile
+  chmod u+rx $cmdfile
+fi
+
+in_error=$TMPDIR/in_error.$$
+\rm -f $in_error
+
+# reorder tables for optimal parallel dcagen: largest tables first
+# for this we need the actual cumulative filesizes for each table
+
+sizes=$TMPDIR/sizes.pl.$$
+cat > $sizes <<'EOF'
+use strict; my %cnt = (); my $size; my $key;
+for (<>) { next if (m/^\s*$/); s/^\s+//; s|\s+\d+/| |; 
+($size,$key) = split/\s+/; $cnt{$key} += $size; }
+foreach $key (keys(%cnt)) { $size = $cnt{$key}; print "$size $key\n"; }
+EOF
+
+#-- AIX doesn't seem to support 'xargs -r', but its 'xargs' by default implies -r ...
+xargs_r=$(echo "" | xargs -r 2>/dev/null && echo "xargs -r" || echo "xargs")
+
+tables=$(\
+    (echo "$tables" | perl -pe 's/\s*(\w+)/0 $1\n/g;' ; \
+    find [0-9]* -type f -follow | $xargs_r ls -C1s) | \
+    perl -w $sizes | $mysort -nr +0 | awk '{print $NF}' | perl -pe 's/\n/ /g;')
+
+\rm -f $sizes
+
+for t in $tables
+do
+  echo "$ODB_FEBINPATH/hcat -41 -l $dbname -t $t -n $npools || touch $in_error" >> $cmdfile
+done
+
+export ODB_DATAPATH_$dbname=.
+export ODB_SRCPATH_$dbname=.
+export IOASSIGN=$dbname.IOASSIGN
+
+if [[ $paral -eq 1 ]] ; then
+  $cmdfile
+else
+  nmaxcmd=$(wc -l $cmdfile)
+  env ODB_PARAL=$paral $ODB_FEBINPATH/fscheduler.x $nmaxcmd
+fi
+\rm -f $cmdfile
+
+if [[ -f $in_error ]] ; then
+  echo "***Error: There were error(s) in 4-to-1 creation"
+  \rm -f $in_error
+  exit 4
+fi
+
+#-- Alter .dd-file
+awk '{ if (NR == 1) { print $1,$2,1; } else { print; }}' < $ddfile > $ddfile.tmp
+\mv $ddfile.tmp $ddfile
+
+#-- Remove the I/O-map file
+\rm -f $dbname.iomap
+
+#-- Remove existing data dirs
+\rm -rf [0-9]*
+
+#-- Bring the re-generated data dirs one level up
+\mv _/[0-9]* .
+\rm -rf _
+
+#-- Re-generate DCAs
+\rm -rf dca
+dcagen -z -F -n -q 2>/dev/null || :
+dcafix -q
+
+#-- Clean-up
+odbclean -f
+
+
+
diff --git a/odb/src/scripts/odb_1to4 b/odb/src/scripts/odb_1to4
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_1to4
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_4to1 b/odb/src/scripts/odb_4to1
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_4to1
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_cat b/odb/src/scripts/odb_cat
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_cat
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_compress b/odb/src/scripts/odb_compress
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_compress
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_count b/odb/src/scripts/odb_count
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_count
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_diff b/odb/src/scripts/odb_diff
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_diff
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_dump b/odb/src/scripts/odb_dump
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_dump
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_dup b/odb/src/scripts/odb_dup
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_dup
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_gnuplot b/odb/src/scripts/odb_gnuplot
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_gnuplot
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_header b/odb/src/scripts/odb_header
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_header
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_less b/odb/src/scripts/odb_less
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_less
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_ls b/odb/src/scripts/odb_ls
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_ls
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_merge b/odb/src/scripts/odb_merge
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_merge
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_more b/odb/src/scripts/odb_more
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_more
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_prune b/odb/src/scripts/odb_prune
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_prune
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_qsub b/odb/src/scripts/odb_qsub
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_qsub
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_set b/odb/src/scripts/odb_set
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_set
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_split b/odb/src/scripts/odb_split
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_split
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_tar b/odb/src/scripts/odb_tar
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_tar
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_to_request b/odb/src/scripts/odb_to_request
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_to_request
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_viewer b/odb/src/scripts/odb_viewer
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_viewer
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odb_xyplot b/odb/src/scripts/odb_xyplot
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odb_xyplot
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odbc++ b/odb/src/scripts/odbc++
new file mode 120000
index 0000000..6435024
--- /dev/null
+++ b/odb/src/scripts/odbc++
@@ -0,0 +1 @@
+odbcc
\ No newline at end of file
diff --git a/odb/src/scripts/odbcat b/odb/src/scripts/odbcat
new file mode 120000
index 0000000..618b4c5
--- /dev/null
+++ b/odb/src/scripts/odbcat
@@ -0,0 +1 @@
+odbless
\ No newline at end of file
diff --git a/odb/src/scripts/odbcc b/odb/src/scripts/odbcc
new file mode 100755
index 0000000..2912893
--- /dev/null
+++ b/odb/src/scripts/odbcc
@@ -0,0 +1,166 @@
+#!/bin/ksh
+#
+# A script to invoke C/C++-compilation with correct ODB-include path.
+#
+# Usage: odbcc [flags] c-file(s) [object(s)]
+#        odbc++ [flags] c++-file(s) [object(s)]
+#
+#       (can't have odbCC, since Windows/CYGWIN maps it to odbcc)
+#
+# Author: Sami Saarinen, ECMWF, 2003-2004, 2006, 2008
+#
+# Now also for linking C/C++-programs
+#
+
+if [[ $# -lt 1 ]] ; then
+  head -13 $0 | tail -12
+  exit 1
+fi
+
+#-- Is this script odbcc or odbc++ (or even obsolescent odbCC on non-cygwin) ?
+is_cxx=$(basename $0 | sed 's/.*\(CC|c++\)$/CC/')
+
+#-- gprof style profiling on ? Set this externally to "-pg" to enable gprof
+ODB_GPROF=${ODB_GPROF:=""}
+
+ODB_ARCH=${ODB_ARCH:="$ARCH"}
+test_arch=$(test_arch 2>/dev/null || echo "unknown")
+
+#MPICH_ROOT=${MPICH_ROOT:=/vol/rdx_dir/mpi/suse90/mpich-1.2.7} # for CPU_TYPE=amd64
+MPICH_ROOT=${MPICH_ROOT:=/not/available}
+
+#-- See also use_odb/use_odb.sh -scripts whether $LIBNETCDF was already set there
+if [[ "$ODB_ARCH" = @(ibm_power*) ]] ; then
+  LIBNETCDF=${LIBNETCDF:=/usr/local/lib/netcdf/current/lib/libnetcdf.a}
+  netcdfinc="/usr/local/lib/netcdf/current/include/netcdf.h"
+else
+  LIBNETCDF=${LIBNETCDF:=/usr/local/apps/netCDF/current/lib/libnetcdf.a}
+  netcdfinc="/usr/local/apps/netCDF/current/include/netcdf.h"
+fi
+
+if [[ -f "$LIBNETCDF" ]] ; then
+  typeset cxxtoo=""
+  if [[ "$is_cxx" = CC ]] ; then # in case of odbc++
+    typeset cxxfile="$(dirname $LIBNETCDF)/libnetcdf_c++.a"
+    if [[ -f $cxxfile ]] ; then
+      cxxtoo=" -l$(basename $cxxfile | perl -pe 's/^lib//; s/\..*//;')"
+    fi
+  fi
+  netcdflib="-L$(dirname $LIBNETCDF)$cxxtoo -l$(basename $LIBNETCDF | perl -pe 's/^lib//; s/\..*//;')"
+else
+  netcdflib=""
+fi
+
+if [[ -f "$netcdfinc" ]] ; then
+  netcdfinc="-I$(dirname $netcdfinc)"
+else
+  netcdfinc="-I${ODB_SYSPATH}"
+fi
+
+odbglue="_odb_glue.o"
+[[ -f $odbglue ]] || odbglue=""
+
+compile_only=0
+for arg in $*
+do
+  if [[ "$arg" = "-c" ]] ; then
+    odbglue=""
+    compile_only=1
+    break
+  fi
+done
+
+addargs=""
+if [[ $compile_only -eq 0 ]] ; then
+  #-- create automatically odb-glue from (possible) -lDBNAME information
+  #-- first: merge possible "-l<space>XXX" into "-lXXX"
+  newargs=$(echo "$*" | perl -pe 's/-l\s+/-l/g');
+  dbnames=""
+  for arg in $newargs
+  do
+    if [[ "$(echo $arg | cut -c1-2)" = "-l" ]] ; then
+      db=$(echo $arg | cut -c3-)
+      DB=$(echo $db | perl -pe 's/\s+//g; s/\..*$//; s/[_-]//g; tr/a-z/A-Z/')
+      if [[ "$db" = "$DB" ]] ; then
+        dbnames="$dbnames $db"
+        # A big thanks to ttl 27/04/2006 for the idea of including -L$ODB_SRCPATH_<dbname> !!
+        typeset testvar=ODB_SRCPATH_${db}
+        typeset testvalue=$(eval echo \$$testvar 2>/dev/null || :)
+        if [[ "$testvalue" != "" && -d "$testvalue" ]] ; then
+          addargs="$addargs-L$testvalue "
+        fi
+      fi
+    fi
+  done
+  if [[ "$dbnames" != "" ]] ; then
+    create_odbglue $dbnames
+    odbglue="_odb_glue.o"
+  fi
+fi
+
+if [[ "$is_cxx" = CC ]] ; then
+  export ODB_CPLUSPLUS=${ODB_CPLUSPLUS:=c++}
+  cmd=${ODB_CPLUSPLUS}
+else
+  cmd=${ODB_CC}
+fi
+
+rc=0
+args=""
+for arg in $*
+do 
+  if [[ "$arg" = "-glue" ]] ; then
+    args="$args$odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | cut -c1-2)" = "-l" ]] ; then # insert -L's in-front of the first -l
+    args="$args$addargs$arg "
+    addargs=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(a|so|o)\b$/$1/')" = @(a|so|o) ]] ; then
+    args="$args$arg $odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(c)\b$/$1/')" = @(c) ]] ; then
+    if [[ "$is_cxx" = CC ]] ; then
+      odbcc -c $arg || rc=1
+      arg=$(echo $arg | sed 's/\.c/.o/')
+    fi
+    args="$args$arg $odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(cc)\b$/$1/')" = @(cc) ]] ; then
+    if [[ "$is_cxx" != CC ]] ; then
+      odbc++ -c $arg || rc=1
+      arg=$(echo $arg | sed 's/\.cc/.o/')
+    fi
+    args="$args$arg $odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(F|F90|f|f90)\b$/$1/')" = @(F|F90|f|f90) ]] ; then
+    odbf90 -c $arg || rc=1
+    arg=$(echo $arg | perl -pe 's/\.(F|F90|f|f90)/.o/g')
+    args="$args$arg $odbglue "
+    odbglue=""
+  else
+    args="$args$arg "
+  fi
+done
+
+if [[ $rc -ne 0 ]] ; then
+  echo "***Error: There were problem(s) in compiling C/C++ files" >&2
+  exit $rc
+fi
+
+cmd="$cmd $ODB_GPROF"
+
+if [[ $compile_only -eq 1 ]] ; then
+  echo $cmd $netcdfinc $args >&2
+  exec $cmd $netcdfinc $args >&2
+else
+  if [[ "${ODB_FCLIBS:-}" = "" ]] ; then
+    if [[ -r $ODB_SYSPATH/ODB_FCLIBS ]] ; then
+      export ODB_FCLIBS=$(head -1 $ODB_SYSPATH/ODB_FCLIBS 2>/dev/null || echo "")
+    fi
+  fi
+  echo $cmd $netcdfinc -L. $args $odbglue $ODB_LIB $ODB_FCLIBS >&2
+  exec $cmd $netcdfinc -L. $args $odbglue $ODB_LIB $ODB_FCLIBS >&2
+fi
+
+#-- should never end up here
+exit 1
diff --git a/odb/src/scripts/odbclean b/odb/src/scripts/odbclean
new file mode 100755
index 0000000..586bac3
--- /dev/null
+++ b/odb/src/scripts/odbclean
@@ -0,0 +1,69 @@
+#!/bin/ksh
+#begin
+#
+# odbclean removes all non-associated files from database directory
+#
+# odbclean [-f]   : force to clean objects, .c, .h-files etc., but retain .sql
+#          [-F]   ; the same as -f
+#          [-i]   : ask before removing anything (the default)
+#          [-c]   : retain other files like .c, .h, .jpg, .rpt, .ddl_, .info etc. (by default: also removed)
+#          [file(s)]
+#
+# Author: Sami Saarinen, ECMWF, 03-Jan-2006 : Initial version
+#
+#end
+#-----------------------------------------------------------------------
+
+set +xv
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+FLAGS=cfFi
+
+enforce=0
+retain=0
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  c)	retain=1;;
+  f|F)	enforce=1;;
+  i)	enforce=0;;
+  *)	abort=yes; break;;
+  esac
+done
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  files=$*
+else
+  files=""
+fi
+
+if [[ $enforce -eq 1 ]] ; then
+  alias rmfile='\rm -f'
+else
+  alias rmfile='\rm -i'
+fi
+
+for f in $(ls -C1 *.o *.a *.so *.x *.lst fort.0 *~ core core.* */core */core.* $files 2>/dev/null || :)
+do
+  rmfile $f 2>/dev/null </dev/null || :
+done
+
+if [[ $retain -eq 0 ]] ; then
+  for f in $(ls -C1 *.h *.c *.rpt *.jpg *.png *.obs *.obs.gz *.ps *.ddl_ *.info 2>/dev/null || :)
+  do
+    rmfile $f 2>/dev/null </dev/null || :
+  done
+fi
+
+
diff --git a/odb/src/scripts/odbcomp b/odb/src/scripts/odbcomp
new file mode 100755
index 0000000..4f834f7
--- /dev/null
+++ b/odb/src/scripts/odbcomp
@@ -0,0 +1,326 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..." >&2; wait; exit 1' 1 2 3 15 
+#
+# A script to compile DDL-file(s)
+#
+# Usage: odbcomp [flags]                 LAYOUT.ddl    # SQL of data layout itself
+#        odbcomp [flags] -c              LAYOUT.ddl    # No shareable object creation
+#        odbcomp [flags] -w    -l LAYOUT viewfile.sql  # SQL of view(s)
+#        odbcomp [flags] -w -c -l LAYOUT viewfile.sql  # No shareable object creation
+#        odbcomp [flags] -z -c           LAYOUT.ddl    # Compile and provide dummy objects for empty tables
+#
+# Author: Sami Saarinen, ECMWF, 1998-2006
+#
+
+usage="head -10 $0 | tail -9"
+TMPDIR=${TMPDIR:=/tmp}
+
+if [[ $# -lt 1 ]] ; then
+  eval $usage >&2
+  exit 1
+fi
+
+#-- gprof style profiling on ? Set this externally to "-pg" to enable gprof
+export ODB_GPROF=${ODB_GPROF:=""}
+
+export ODB_CREATE_IOASSIGN=${ODB_CREATE_IOASSIGN:=1}
+
+export ODB_PARAL=${ODB_PARAL:=4}
+paral=${ODB_PARAL}
+
+cc_compile_error=$TMPDIR/cc_compile_error.$$
+
+function cc_compile {
+  [[ $# -lt 1 ]] && return
+  typeset f
+  for f in $*
+  do
+    if [[ -s $f ]] ; then
+      cmd="$ODB_CC $ODB_GPROF -c $f"
+      echo $cmd >&2
+           $cmd >&2 || (echo "***Error in compiling $f" >> $cc_compile_error)
+    fi
+  done
+}
+
+set +u
+
+if [[ "$ODB_SYSPATH" = "" ]] ; then
+  echo "***Error: ODB_SYSPATH is not defined; Please enter 'use odb'" >&2
+  exit 1
+fi
+
+views=$(echo "$*" | perl -pe 's/^.*\s*-w\b.*/1/')
+#echo "**views=$views" >&2
+
+[[ "$views" = "1" ]] || views=0
+dbname=$(echo "$*" | perl -ne 'print $1 if (/.*-l\s*(\w+).*/);')
+
+args=$*
+argsnew=""
+
+# for now ...
+nsql=0
+sqlfiles=""
+thefile=""
+for x in $args
+do
+  if [[ -f "$x" ]] ; then
+    suffix=$(echo "$x"| perl -pe 's/\w+\.(\w+)/$1/')
+    if [[ "$suffix" = sql ]] ; then
+      ((nsql+=1))
+      sqlfiles="$sqlfiles $x"
+      thefile=$x
+      if [[ $views -ne 1 ]] ; then
+        views=1
+        argsnew="$argsnew -w"
+      fi
+    else
+      argsnew="$argsnew $x"
+    fi
+  else
+    argsnew="$argsnew $x"
+  fi
+done
+
+if [[ $nsql -le 1 ]] ; then
+  file=$(echo "$0 $*"| perl -pe 's/.*\s+(\S+)\s*$/$1/')
+  args="$argsnew $thefile"
+else
+  file=tmp$$.sql
+  args="$argsnew $file"
+  cat /dev/null > $file
+  for x in $sqlfiles 
+  do
+    (cat $x ; echo ';') >> $file
+  done
+  echo "***Supplied SQL-files ($sqlfiles) placed temporarely in $file"
+  # cat $file
+fi
+pref=$(echo "$file"| perl -pe 's/(\w+)\.\w+/$1/')
+sufx=$(echo "$file"| perl -pe 's/\w+\.(\w+)/$1/')
+
+addargs=""
+
+setup_file="/dev/null"
+
+if [[ "$dbname" = "" ]] ; then
+  dbname=$(basename $(ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    dbname=""
+  fi
+fi
+
+if [[ "$IOASSIGN" = "" ]] ; then
+  export IOASSIGN=IOASSIGN
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  if [[ -s "$IOASSIGN" ]] ; then
+    dbname=$(egrep -v '^_' $IOASSIGN | head -1 | perl -pe 's/^(\w+).*/$1/;')
+  fi
+fi
+
+if [[ "$dbname" = "" ]] ; then
+  dbname=$(basename $file | perl -pe 's/(\w+)\..*/uc($1)/e;')
+fi
+
+# A big thanks to ttl 24/04/2006 added for the idea of including -I$ODB_SRCPATH_<dbname> !!
+testvar=ODB_SRCPATH_${dbname}
+testvalue=$(eval echo \$$testvar 2>/dev/null || :)
+if [[ "$testvalue" != "" && -d "$testvalue" ]] ; then
+  export ODB_CC="${ODB_CC:=cc} -I$testvalue"
+  addargs="$addargs -I$testvalue"
+  libname=$testvalue/lib$dbname.a
+else
+  libname=lib$dbname.a
+fi
+
+if [[ ! -s "$IOASSIGN" ]] ; then
+  rm -f *IOASSIGN*
+  create_ioassign -l $dbname
+  export IOASSIGN=$dbname.IOASSIGN
+fi
+
+addargs="$addargs -l $dbname"
+
+#if [[ -f "$dbname.dd" ]] ; then
+#  nf=$(head -1 $dbname.dd | awk '{print NF}')
+#  if [[ $nf -gt 2 ]] ; then
+#    awk '{if (NR==1) print $1,$2; else print }' $dbname.dd > $dbname.dd.$$
+#    \cp $dbname.dd $dbname.dd.bck
+#    \mv $dbname.dd.$$ $dbname.dd
+#  fi
+#fi
+
+viewnames=""
+
+if [[ -f "$file" ]] ; then
+  viewnames=$(perl -ne 'print "\L$1 " if (/CREATE\s+VIEW\s+(\w+)/i);' < $file)
+  if [[ "$viewnames" != "" ]] ; then
+    addargs="$addargs -w"
+    views=1 
+  fi
+#  echo ">>viewnames=$viewnames" >&2
+#  echo ">>views=$views" >&2
+#  echo ">>addargs=$addargs" >&2
+  if [[ $views -eq 0 ]] ; then
+    setup_file=$dbname.setup
+  fi
+  export ODB_SETUP_FILE="$setup_file"
+fi
+
+if [[ "$ODB_LIBS_KEEP" = "" ]] ; then
+  unset ODB_LIBS
+else
+  if [[ $ODB_LIBS_KEEP -ne 1 ]] ; then
+    unset ODB_LIBS
+  fi
+fi
+
+[[ "$sufx" = @(ddl|sql) ]] || {
+  if [[ $views -eq 0 ]] ; then
+    ln -s $file $pref.ddl 2>/dev/null || :
+    args=$(echo $args | perl -pe "s/\.(\w+)\$/.ddl/")
+  fi
+}
+
+if [[ "$ODB_STATIC_LINKING" -eq 1 ]] ; then
+  addargs="$addargs -s -S -C"
+fi
+
+# Prefer back-end compilation over front-end ?
+export RUN_FE_DIRECT=${RUN_FE_DIRECT:=0}
+if [[ $RUN_FE_DIRECT -eq 1 && -x $ODB_BINPATH/odb98be.x ]] ; then
+  ODB_COMPILER=$(echo "${ODB_COMPILER}" | perl -pe 's/\bodb98\b/odb98be/')
+  echo "***Note: Using back-end ODB/SQL-compiler" >&2
+fi
+
+cmd="${ODB_COMPILER} -I $ODB_SYSPATH $addargs $args"
+
+if [[ -r ${dbname}.flags ]] ; then
+  export ODB_COMPILER_FLAGS=${dbname}.flags
+fi
+
+if [[ $views -eq 0 ]] ; then
+  rm -f ${dbname}.c ${dbname}.h ${dbname}_T_*.c
+fi
+
+echo "$cmd" >&2
+      $cmd  >$file.list 2>&1 || {
+   set -x
+   cat $file.list >&2
+   exit 1
+ }
+egrep -v 'was already set ; previous value retained' $file.list
+rm -f $file.list
+
+if [[ -f "$setup_file" ]] && [[ "$setup_file" != "/dev/null" ]] ; then
+  chmod u+rx "$setup_file"
+fi
+
+if [[ ! -f "$IOASSIGN" ]] && [[ "$setup_file" != "/dev/null" ]] ; then
+  if [[ -f "$setup_file" ]] ; then
+    echo "*** Running IOASSIGN-setup file '$setup_file' ..." >&2
+    $setup_file >/dev/null 2>&1
+  fi
+fi
+
+if [[ "$ODB_STATIC_LINKING" -eq 1 ]] ; then
+  if [[ $views -eq 0 ]] ; then
+    create_odbglue $dbname
+    create_ioassign -l $dbname
+    create_static_stubb $dbname /dev/null
+    rm -f $libname # a fresh library will be created
+    filelist=$(\ls ${dbname}.c ${dbname}_T_*.c ${dbname}_Sstatic.c 2>/dev/null || :)
+  else
+    create_static_stubb $dbname $file
+    if [[ -s ${dbname}_Sstatic.c ]] ; then
+      filelist=${dbname}_Sstatic.c
+    else
+      filelist=""
+    fi
+    # viewnames=$(egrep ODB_ANCHOR_VIEW ${dbname}_Sstatic.c | perl -pe 's/.*,\s*(\w+)\b.*/$1/')
+    viewnames=$($ODB_BINPATH/create_static_stubb -v $dbname $file)
+    for f in $viewnames
+    do
+      if [[ -s ${dbname}_$f.c ]] ; then
+        filelist="$filelist ${dbname}_$f.c"
+      fi
+    done
+  fi
+
+  # Order filelist by size of the file, largest file first
+  mysort=$ODB_FEBINPATH/mysort
+  filelist=$(\ls -lg $filelist 2>/dev/null | $mysort -nr +3 | awk '{print $NF}')
+
+  rm -f $cc_compile_error
+#  subproc="&"
+#  [[ $paral -gt 1 ]] || subproc=""
+#  n=0
+#  for f in $filelist
+#  do
+#    eval "(cc_compile $f) $subproc"
+#    ((n+=1))
+#    [[ $((n%$paral)) -eq 0 ]] && wait
+#  done
+
+#  wait
+
+  cmdfile=$TMPDIR/cmdfile.$$
+  cat /dev/null > $cmdfile
+  cat /dev/null > $cc_compile_error
+  for f in $filelist
+  do
+    echo "$ODB_CC $ODB_GPROF -c $f || (echo '***Error in compiling '$f >> $cc_compile_error)" >> $cmdfile
+  done
+  objlist=$(echo $filelist | sed 's/\.c/.o/g')
+  rm -f $objlist
+
+  if [[ $paral -gt 1 ]] ; then
+    #-- The following command compiles C-files in a parallel loop
+    nmaxcmd=$(wc -l $cmdfile)
+    env ODB_PARAL=$paral $ODB_FEBINPATH/fscheduler.x $nmaxcmd >&2
+  else
+    (set -ex; $ODB_CC $ODB_GPROF -c $filelist || (echo '***Error(s) in compilation' >> $cc_compile_error))
+  fi
+  rm -f $cmdfile
+
+  if [[ -s $cc_compile_error ]] ; then
+    echo "***Error: C-compilation has failed" >&2
+    cat $cc_compile_error >&2
+    rm -f $cc_compile_error
+    exit 1
+  fi
+  rm -f $cc_compile_error
+
+  if [[ ! -f $libname ]] ; then
+    $ODB_AR q $libname $objlist || exit 3
+  else
+    $ODB_AR r $libname $objlist || exit 3
+  fi
+  if [[ -f $ODB_SYSPATH/SHLIB && "$ODB_LD_SHARED" != none ]] ; then
+  # Create shared lib
+    libso=lib$dbname$ODB_LD_SHARED_SFX
+    rm -f $libso
+    $ODB_LD_SHARED -o $libso `$ODB_AR t $libname` || {
+      mkdir _tmpdir.$$
+      cd _tmpdir.$$
+      $ODB_AR x ../$libname
+      $ODB_LD_SHARED -o ../$libso `$ODB_AR t ../$libname` || {
+        echo "***Error: Unable to create shareable library '$libso'" >&2
+        echo "          Retry with 'export ODB_LD_SHARED=none' in Korn-shell or" >&2
+        echo "                     'setenv ODB_LD_SHARED none' in C-shell" >&2
+        cd .. ; rm -rf _tmpdir.$$
+        exit 2
+      }
+      cd .. ; rm -rf _tmpdir.$$
+    }
+  fi
+fi
+
+if [[ $nsql -ge 2 ]] ; then
+  rm -f $file
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbcompress b/odb/src/scripts/odbcompress
new file mode 100755
index 0000000..4ba6caa
--- /dev/null
+++ b/odb/src/scripts/odbcompress
@@ -0,0 +1,317 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15 
+#begin
+#
+# odbcompress   -i input_database_path         : location of source database (dbname figured out from .dd-file)
+#               -o output_database_path        : location of destination database
+#              [-a]                            : to append to the existing database (output_db)
+#              [-l output_db_data_layout_file] : must be provided, unless -a option is used
+#              [-f flags_file]                 : additional input for layout (same as .flags-file)
+#              [-p specific_pool_number(s)]    : select only from these *input* database pools for output database
+#              [-1]                            : use I/O-method#1 for output database (the default)
+#              [-4]                            : use I/O-method#4 for output database
+#              [-n]                            : create dca-indices with fast -n option (the default)
+#              [-u]                            : create dca-indices with (sometimes) timeconsuming -u option
+#              [-c]                            : enforce clean build (odbcomp)
+#              [-k]                            : konvert $ODB_LAT (def=lat at hdr) & $ODB_LON (def=lon at hdr) to degrees
+#              [-g odb_table_name]             : Apply odbgzip'ping for selected table(s)
+#              [-G]                            : Apply odbgzip'ping ALL available tables
+#              [-v]                            : Be more verbose when running ODB-compress
+#              [-T]                            : set ODB tracing on
+#              [-m membytes]                   : Max. mem. in bytes for ODB_get() (default=67108864 bytes or 1/10 of avail.mem.)
+#              [-H dr_hook_opt]                : Enable Dr.Hook profiler and export DR_HOOK_OPT with dr_hook_opt
+#              [-h]                            : Print this usage
+#
+#end
+#
+
+set -eu
+
+thisdir=$(pwd)
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+FLAGS=acf:g:GhH:i:kl:m:no:p:Tuv14
+
+append=0
+flagfile=""
+input_db=""
+layout=""
+output_db=""
+poolmask=""
+io_method=1
+update="-n"
+clean_build=0
+konvert=""
+gztables=""
+gzip=0
+gzall=0
+drhookopt=""
+trace=0
+verbose=""
+membytes=67108864 # 64 Mbytes
+
+hinv=$(whence hinv 2>/dev/null || echo "")
+if [[ "$hinv" != "" && -x "$hinv" ]] ; then
+  rc=0
+  $hinv 2>/dev/null | grep " Mbytes" || rc=$?
+  if [[ $rc -eq 0 ]] ; then
+    membytes=$($hinv 2>/dev/null | grep " Mbytes" | awk '{printf("%.0f\n", ($(NF-1) * 1024 * 1024)/10); }')
+  fi
+fi
+
+export ODB_LAT=${ODB_LAT:="lat at hdr"}
+export ODB_LON=${ODB_LON:="lon at hdr"}
+export ODB_LATLON_RAD=${ODB_LATLON_RAD:="latlon_rad at desc"}
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  a)  append=1;;
+  c)  clean_build=1;;
+  f)  flagfile="$OPTARG";;
+  g)  gztables="$gztables $OPTARG"; gzip=1;;
+  G)  gzip=1; gzall=1;;
+  H)  drhookopt="$OPTARG";;
+  h)  abort=yes; break;;
+  i)  input_db="$OPTARG";;
+  k)  konvert="-k";;
+  l)  layout="$OPTARG";;
+  m)  membytes="$OPTARG";;
+  n)  update="-n";;
+  o)  output_db="$OPTARG";;
+  p)  poolmask="$poolmask $OPTARG";;
+  u)  update="-u";;
+  T)  trace=1;;
+  v)  verbose="-v";;
+  1)  io_method=1;;
+  4)  io_method=4;;
+  *)  abort=yes; break;;
+  esac
+done
+
+if [[ "$input_db" = "" ]] ; then
+  echo "***Error: Input database not given"
+  abort=yes
+fi
+
+if [[ "$output_db" = "" ]] ; then
+  echo "***Error: Output database not given"
+  abort=yes
+fi
+
+input_db_dir="$input_db"
+
+grpsize=1
+if [[ -d "$input_db_dir" ]] ; then
+  input_db_dir=$(\cd $input_db_dir 2>/dev/null; pwd)
+  input_db=$(\cd $input_db_dir 2>/dev/null; basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$input_db" = ".dd" ]] ; then
+    echo "***Error: Unable to locate principal metadata file from input database dir '$input_db_dir'"
+    abort=yes
+  else
+    if [[ -s $input_db_dir/$input_db.dd ]] ; then
+      grpsize=$(head -5 $input_db_dir/$input_db.dd | tail -1)
+      yyyymmddhh=$(head -4 $input_db_dir/$input_db.dd | tail -1 | awk '{printf("%8.8d%2.2d\n",$1,$2/10000);}')
+      export ODB_ANALYSIS_DATE=$(echo $yyyymmddhh | cut -c1-8)
+      export ODB_ANALYSIS_TIME="$(echo $yyyymmddhh | cut -c9-10)0000"
+    fi
+    [[ $clean_build -eq 0 ]] || \rm -f  $input_db_dir/lib$input_db.a
+    if [[ ! -f $input_db_dir/lib$input_db.a ]] ; then
+      cd $input_db_dir
+      pwd
+      odbcomp -z $input_db.sch
+      cd $thisdir
+    fi
+    if [[ ! -d $input_db_dir/dca ]] ; then
+      cd $input_db_dir
+      pwd
+      dcagen -z -F -n
+      cd $thisdir
+    fi
+  fi
+else
+  if [[ $abort = no ]] ; then
+    echo "***Warning: Unable to locate input database directory '$input_db_dir'"
+    echo "----------> ODB-compression will NOT be performed for this database"
+    exit 0
+  else
+    echo "***Error: Unable to locate input database directory '$input_db_dir'"
+    abort=yes
+  fi
+fi
+
+if [[ $append -eq 0 && "$layout" != "" && ! -f "$layout" ]] ; then
+  echo "***Error: Unable to locate given data layout file '$layout'"
+  abort=yes
+fi
+
+if [[ $append -eq 0 && "$flagfile" != "" && ! -f "$flagfile" ]] ; then
+  echo "***Error: Unable to locate given flags-file '$flagfile'"
+  abort=yes
+fi
+
+if [[ $append -eq 0 && "$layout" = "" ]] ; then
+  echo "***Error: Data layout file for the *NEW* output database must be given (unless -a is also used)"
+  abort=yes
+fi
+
+[[ $abort = no ]] || {
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+}
+
+[[ $abort = no ]] || {
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 2
+}
+
+output_db_dir="$output_db"
+
+if [[ $append -eq 0 && -d "$output_db_dir" ]] ; then
+  \rm -rf $output_db_dir
+fi
+
+if [[ ! -d "$output_db_dir" ]] ; then
+  mkdir -p $output_db_dir
+  append=0
+fi
+
+if [[ $append -eq 0 ]] || [[ $clean_build -eq 1 ]] ; then
+  if [[ "$layout" != "" && -f "$layout" ]] ; then
+    output_db=$(echo "$layout" | perl -pe 's#^.*/##; s/\..*//')
+    \cp $layout $output_db_dir/$output_db.ddl
+    [[ ! -f $flagfile ]] || \cp $flagfile $output_db_dir/$output_db.flags
+    cd $output_db_dir
+    pwd
+    env ODB_CREATE_IOASSIGN=0 odbcomp $(basename $layout)
+    # re-create IOASSIGN-files, since they probably got wrong/or not created
+    if [[ -f $output_db.setup ]] ; then
+      rm -f *IOASSIGN* || :
+      chmod u+x $output_db.setup
+      ./$output_db.setup > $output_db.IOASSIGN
+      ln -s $output_db.IOASSIGN IOASSIGN.$output_db
+      ln -s $output_db.IOASSIGN IOASSIGN
+    fi
+    cd $thisdir
+  else
+    echo "***Error: Data layout file for *NEW* output database must be given"
+    abort=yes
+  fi
+fi
+
+[[ $abort = no ]] || {
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 3
+}
+
+if [[ -d "$output_db_dir" ]] ; then
+  output_db_dir=$(\cd $output_db_dir 2>/dev/null; pwd)
+  output_db=$(echo "$output_db" | perl -pe 's#^.*/##; s/\..*//')
+  if [[ $append -eq 0 ]] ; then
+    (\cd $output_db_dir 2>/dev/null; \rm -rf [0-9]*)
+  fi
+else
+  echo "***Error: Unable to locate output database directory '$output_db_dir'"
+  abort=yes
+fi
+
+[[ $abort = no ]] || {
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 4
+}
+
+#-- Poolmask
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo "$poolmask" | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK_${input_db}="$poolmask"
+  echo "==> Using only pools these input pools : $poolmask"
+fi
+
+#-- Append arg
+
+if [[ $append -eq 0 ]] ; then
+  append_arg=""
+else
+  append_arg="-a"
+fi
+
+#-- create executable --
+
+obj=$($ODB_AR t $ODB_LIBPATH/libodbmain.a | grep Odbcompress)
+$ODB_AR x $ODB_LIBPATH/libodbmain.a $obj
+
+create_odbglue ${input_db} ${output_db}
+
+odbf90 $obj -o $thisdir/odbcompress.x \
+       -L${input_db_dir} -l${input_db} \
+       -L${output_db_dir} -l${output_db}
+
+rm -f $obj
+
+#-- setup environment --
+
+export IOASSIGN=$thisdir/tmp.IOASSIGN.$$
+cat $input_db_dir/$input_db.IOASSIGN $output_db_dir/$output_db.IOASSIGN > $IOASSIGN
+
+export ODB_IO_METHOD_${input_db}=5
+export ODB_SRCPATH_${input_db}=$input_db_dir
+export ODB_DATAPATH_${input_db}=$input_db_dir
+
+export ODB_IO_METHOD_${output_db}=$io_method
+#export ODB_IO_METHOD=$io_method   # this not required as the initialization bug in newio.c was fixed
+export ODB_IO_GRPSIZE=$grpsize
+export ODB_SRCPATH_${output_db}=$output_db_dir
+export ODB_DATAPATH_${output_db}=$output_db_dir
+
+#-- run --
+
+if [[ "$drhookopt" != "" ]] ; then
+  export DR_HOOK=true
+  export DR_HOOK_OPT="$drhookopt"
+fi
+
+if [[ $trace -eq 1 ]] ; then # turn ODB-tracing on
+  export ODB_TRACE_PROC=-1
+  export ODB_TRACE_FILE=$thisdir/trace.%d
+  export ODB_TRACE_FLUSH_FREQ=1
+fi
+
+cmd="$thisdir/odbcompress.x -i ${input_db} -o ${output_db} -m $membytes $konvert $append_arg $verbose"
+
+if [[ "$ODB_ARCH" = "nectx" ]] ; then
+  echo "$cmd" | odbqsub -N odbcmprs$$ || exit $?
+else
+  echo "$cmd"
+        $cmd || exit $?
+fi
+
+echo "Creating direct column access indices (with $update) ..."
+cd $output_db_dir
+pwd
+dcagen -z -F $update
+
+if [[ $gzip -eq 1 ]] ; then
+  cd $output_db_dir
+  ddfile=${output_db}.dd
+  npools=$(head -5 $ddfile | tail -1)
+  if [[ $gzall -eq 1 ]] ; then
+    gztables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+  fi
+
+  #-- AIX doesn't seem to support 'xargs -r', but its 'xargs' by default implies -r ...
+  xargs_r=$(echo "" | xargs -r 2>/dev/null && echo "xargs -r" || echo "xargs")
+
+  echo "odbgzip'ping table(s) $gztables ..."
+  pwd
+  for t in $gztables
+  do
+    find . -name "$t" -type f -print 2>/dev/null | $xargs_r -n$npools odbgzip -v
+  done
+fi
+
+echo "=== Size comparison: input vs. output in kilobytes:"
+du -sk $input_db_dir
+du -sk $output_db_dir
+
+\rm -f $IOASSIGN $thisdir/odbcompress.x
diff --git a/odb/src/scripts/odbcount b/odb/src/scripts/odbcount
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odbcount
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odbdiff b/odb/src/scripts/odbdiff
new file mode 100755
index 0000000..aa47410
--- /dev/null
+++ b/odb/src/scripts/odbdiff
@@ -0,0 +1,339 @@
+#!/bin/ksh
+set +xv
+#begin
+#
+# odbdiff -c                # Enforce recompilations
+#         -v sqlfile        # SQL-file (with or w/o prefix .sql) or a table, if starts with '@'
+#                             If SQL-file, an editor will be opened (unless -e pipe or -e batch)
+#         -e editor_name    # Preferred editor name (use pipe or batch, if no editor)
+#                             As in odbviewer, the default being $ODB_EDITOR
+#         -q 'query_string' # Data query itself : no editor will be opened
+#         -n maxdiffs       # Max. number of diffs allowed before bailing out (default=2147483647)
+#         -g                # Do *NOT* generate diff.database REFCMP i.e.
+#                             input files for simulobs2odb & create database REFCMP & run odbviewer
+#         -C _color         # Name of the "color" column for diff database (default=_color)
+#         -l label          # Label for this job to separate multiple diff DBs (default=default)
+#         -1                # Enforce (lat,lon)-conversion to degrees for reference database (DB#1)
+#         -2                # Enforce (lat,lon)-conversion to degrees for comparison database (DB#2)
+#         -b nbits          # How many last bits to ignore after (lat,lon)-conversion (default=0 i.e. none)
+#         -p poolmask       # List of pools to search. Can appear multiple times. As in odbviewer
+#         -s                # Right-adjust string-datatype before comparison (by default NOT adjusted)
+#         -R                # Do NOT convert (lat,lon) into degrees in odbviewer
+#         -r                # Convert (lat,lon) into degrees in odbviewer only in the plot, but not in textual report
+#         -k                # Convert (lat,lon) into degrees in odbviewer for both plot & report (the default)
+#         -m                # Use less memory by reading reference database pool-by-pool (default uses more memory)
+#         -i                # Latitude band increment (default=180)
+#         reference_database_dir compare_database_dir
+#
+# Author: Sami Saarinen, ECMWF, 27-Jun-2005 .. 11-Jul-2005
+#
+#end
+#
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+thisdir=$(pwd)
+cd $thisdir
+export WDIR=${WDIR:=$thisdir}
+
+maxdiffs=2147483647
+recomp=0
+query=""
+query_given=0
+defview=myview
+viewname=$defview
+hassql=1
+simulobs=1
+color="_color"
+label=default
+rad2deg_1=0
+rad2deg_2=0
+rad2deg_flag="-k" # for odbviewer : convert (lat,lon) radians to degrees in plot & textual report
+nbits=0
+poolmask=""
+adjustr=0
+editor=${ODB_EDITOR:=emacs}
+memopt=0
+rlatinc=180
+rlatinc_given=0
+
+abort=no
+FLAGS=b:cC:e:gi:kl:mn:p:q:Rrsv:12
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  b)	nbits="$OPTARG";;
+  c)	recomp=1;;
+  C)	color="$OPTARG";;
+  e)	editor="$OPTARG";;
+  g)	simulobs=0;;
+  i)	rlatinc="$OPTARG" ; rlatinc_given=1;;
+  k)	rad2deg_flag="-k" ;;
+  l)	label="$OPTARG";;
+  m)	memopt=1;;
+  n)	maxdiffs="$OPTARG";;
+  p)	poolmask="$poolmask $OPTARG";;
+  q)	query_given=1; query="$OPTARG";;
+  r)	rad2deg_flag="-r" ;;
+  R)	rad2deg_flag="-R" ;;
+  s)	adjustr=1;;
+  v)	viewname="$OPTARG";;
+  1)	rad2deg_1=1 ; rad2deg_flag="-R" ;; # -R for odbviewer : (lat,lon) assumed in degrees at REFCMP-database
+  2)	rad2deg_2=1 ; rad2deg_flag="-R" ;; # -R for odbviewer : (lat,lon) assumed in degrees at REFCMP-database
+  \?)   abort=yes; break;;
+  esac
+done
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -ne 2 || "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+refpath=$1
+cmppath=$2
+
+is_table=$(echo "$viewname" | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+
+if [[ $is_table -eq 1 && $query_given -eq 0 ]] ; then
+  hassql=0
+  sqlfile=/dev/null
+elif [[ $query_given -eq 1 ]] ; then
+  viewname=$(echo "$viewname" | perl -pe 's/\..*//')
+  sqlfile=$viewname.sql
+  echo "$query" > $sqlfile
+elif [[ -f $viewname ]] ; then
+  sqlfile=$viewname
+  query_given=2
+else
+  sqlfile=$viewname
+  suffix=$(echo "$viewname" | perl -ne 'print $1 if (/.*(\.\w+)/);')
+  if [[ "$suffix" = ".so" && $recomp -eq 0 && $rlatinc_given -eq 0 ]] ; then
+    hassql=0
+    query_given=1
+  else
+    query_given=2
+  fi
+  viewname=$(echo "$viewname" | perl -pe 's/\..*//')
+  sqlfile=$viewname.sql
+fi
+
+sqldir=$(dirname $sqlfile)
+sqlfile=$(basename $sqlfile)
+sqldir=$(\cd $sqldir >/dev/null 2>&1 ; pwd)
+
+if [[ $query_given -eq 2 ]] ; then
+  if [[ "$editor" != pipe && "$editor" != batch ]] ; then
+    $editor $sqldir/$sqlfile &
+  fi
+fi
+
+refpath=$(\cd $refpath >/dev/null 2>&1 ; pwd)
+cmppath=$(\cd $cmppath >/dev/null 2>&1 ; pwd)
+
+REF=$thisdir/REF.$label
+CMP=$thisdir/CMP.$label
+REFCMP=REFCMP.$label
+
+cd $thisdir
+out=out$$
+
+if [[ $recomp -eq 1 ]] || \
+   [[ ! -d $REF ]] || [[ ! -d $CMP ]] ; then # Recompile layout AND SQL
+  cd $thisdir
+  odbdup -i $refpath -o $REF -l REF -F -D
+  cd $REF
+  if [[ ! -d dca ]] ; then
+    dcagen -F -n -z >$thisdir/1.$out 2>&1 &
+  fi
+  newodb -z REF >$thisdir/2.$out 2>&1 &
+
+  cd $thisdir
+  odbdup -i $cmppath -o $CMP -l CMP -F -D
+  cd $CMP
+  if [[ ! -d dca ]] ; then
+    dcagen -F -n -z >$thisdir/3.$out 2>&1 &
+  fi
+  newodb -z CMP >$thisdir/4.$out 2>&1 &
+  echo "*** Waiting for subprocesses to finish ..."
+  wait
+  for n in 1 2 3 4
+  do
+    if [[ -f $thisdir/$n.$out ]] ; then
+      cat $thisdir/$n.$out
+      rm -f $thisdir/$n.$out
+    fi
+  done
+fi
+
+wait
+
+if [[ $hassql -eq 1 ]] ; then # Recompile SQL
+  if [[ $rlatinc_given -eq 1 ]] ; then
+    where_fiddle=1
+    egrep -i '(lat|hdr)' $sqldir/$sqlfile >/dev/null 2>&1 || where_fiddle=0
+  else
+    where_fiddle=0
+  fi
+
+  cd $REF
+  if [[ $where_fiddle -eq 1 ]] ; then
+    if [[ $rad2deg_1 -eq 1 ]] ; then # Latitude already assumed in degrees
+       env ODB_WHERE_FIDDLE='$lat1 < lat <= $lat2' \
+           perl -w $ODB_BINPATH/where_fiddle.pl < $sqldir/$sqlfile > $sqlfile
+    else
+       env ODB_WHERE_FIDDLE='$lat1 < degrees(lat) <= $lat2' \
+           perl -w $ODB_BINPATH/where_fiddle.pl < $sqldir/$sqlfile > $sqlfile
+    fi
+  else
+    cat < $sqldir/$sqlfile > $sqlfile
+  fi
+  echo "*** The following SQL is in concern (database=REF at $(pwd)):"
+  cat $sqlfile
+  echo " "
+  odbcomp -z -lREF $sqlfile
+
+  cd $CMP
+  if [[ $where_fiddle -eq 1 ]] ; then
+    if [[ $rad2deg_2 -eq 1 ]] ; then # Latitude already assumed in degrees
+       env ODB_WHERE_FIDDLE='$lat1 < lat <= $lat2' \
+           perl -w $ODB_BINPATH/where_fiddle.pl < $sqldir/$sqlfile > $sqlfile
+    else
+       env ODB_WHERE_FIDDLE='$lat1 < degrees(lat) <= $lat2' \
+           perl -w $ODB_BINPATH/where_fiddle.pl < $sqldir/$sqlfile > $sqlfile
+    fi
+  else
+    cat < $sqldir/$sqlfile > $sqlfile
+  fi
+  echo "*** The following SQL is in concern (database=CMP at $(pwd)):"
+  cat $sqlfile
+  echo " "
+  odbcomp -z -lCMP $sqlfile
+else
+  echo "*** The following TABLE is in concern: $viewname"
+fi
+
+cd $thisdir
+create_odbglue REF CMP
+
+export ODB_DATAPATH_REF=$REF
+export ODB_SRCPATH_REF=$ODB_DATAPATH_REF
+export ODB_DATAPATH_CMP=$CMP
+export ODB_SRCPATH_CMP=$ODB_DATAPATH_CMP
+
+export IOASSIGN=$thisdir/IOASSIGN_$label
+cat $ODB_SRCPATH_REF/REF.IOASSIGN $ODB_SRCPATH_CMP/CMP.IOASSIGN > $IOASSIGN
+
+export ODB_READONLY=1
+export ODB_IO_METHOD=5
+
+obj=$($ODB_AR t $ODB_LIBPATH/libodbmain.a | grep Odbdiff)
+$ODB_AR x $ODB_LIBPATH/libodbmain.a $obj
+
+odbf90 $obj -o odbdiff.x -L$ODB_DATAPATH_REF -lREF -L$ODB_DATAPATH_CMP -lCMP
+
+if [[ $simulobs -eq 1 ]] ; then
+  simulobs_file2="only_in_cmp.txt.$label"
+  simulobs_file1="only_in_ref.txt.$label"
+  cat > $simulobs_file1 <<'EOF'
+#refcmp
+#/poolno=1
+#/end
+# These data rows were only found from REFERENCE database and/or are different from COMPARISON database
+EOF
+  cat > $simulobs_file2 <<'EOF'
+#refcmp
+#/poolno=2
+#/end
+# These data rows were only found from COMPARISON database and/or are different from REFERENCE database
+EOF
+else
+  simulobs_file1="/dev/null"
+  simulobs_file2="/dev/null"
+fi
+
+if [[ $hassql -eq 1 ]] ; then
+  view=$(echo "$sqlfile" | perl -pe 's/\..*//')
+else
+  view=$viewname
+fi
+
+#-- Poolmask
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK_REF="$poolmask"
+  export ODB_PERMANENT_POOLMASK_CMP="$poolmask"
+  echo "==> Scanning only pools : $poolmask"
+fi
+
+#-- Remove gprof output (if any)
+rm -f gmon.out*
+
+./odbdiff.x CMP REF $view $maxdiffs $simulobs_file1 $color 1 $rad2deg_2 $rad2deg_1 $nbits $adjustr $memopt $rlatinc
+if [[ -f gmon.out ]] ; then
+  mv gmon.out gmon.out.CMPvsREF
+fi
+./odbdiff.x REF CMP $view $maxdiffs $simulobs_file2 $color 2 $rad2deg_1 $rad2deg_2 $nbits $adjustr $memopt $rlatinc
+if [[ -f gmon.out ]] ; then
+  mv gmon.out gmon.out.REFvsCMP
+fi
+
+#-- Disable gprof'fing (if it was on)
+export ODB_GPROF=""
+
+if [[ $simulobs -eq 1 ]] ; then
+  # Pool#1 contains REF vs. CMP database diffs
+  # Pool#2 contains CMP vs. REF database diffs
+  # "color" is set to 1 in pool#1 and 2 in pool#2
+  ndiffs1=$(tail -1 $simulobs_file1 | awk '{print $NF}')
+  ndiffs2=$(tail -1 $simulobs_file2 | awk '{print $NF}')
+  if [[ $ndiffs1 -gt 0 ]] || [[ $ndiffs2 -gt 0 ]] ; then
+    export ODB_IO_METHOD=1 # Better than 4 in case of low memory system, and since cannot be 5
+    cd $thisdir
+    simulobs2odb -l $REFCMP -i $simulobs_file1 -i $simulobs_file2 -n 2 -c
+    montage=$(whence montage 2>/dev/null || echo "")
+    xdiff=$(whence xdiff 2>/dev/null || echo "")
+    cd $REFCMP
+    export ODB_REPORTER="head -10" # Just to avoid opening b4.x-window ;-)
+    has_lat=$(grep ' lat_hdr ' REFCMP.sch >/dev/null 2>&1 || echo "no")
+    has_lon=$(grep ' lon_hdr ' REFCMP.sch >/dev/null 2>&1 || echo "no")
+    if [[ "$has_lat" = no ]] || [[ "$has_lon" = no ]] ; then
+      export ODB_PLOTTER=0 # Plotting off; no (lat,lon)-coordinates
+    else
+      export ODB_VIEWER_LAT="lat_hdr at refcmp"
+      export ODB_VIEWER_LON="lon_hdr at refcmp"
+      export ODB_VIEWER_TEXT_3="Only in DB = $refpath"
+    fi
+    odbviewer -F $rad2deg_flag -v data_only_in_ref_db \
+              -p 1 -q "select '!/:${color}@/' from refcmp orderby *" -e batch -I < /dev/null
+    export ODB_VIEWER_TEXT_3="Only in DB = $cmppath"
+    odbviewer -F $rad2deg_flag -v data_only_in_cmp_db \
+              -p 2 -q "select '!/:${color}@/' from refcmp orderby *" -e batch -I < /dev/null
+    ls -ltr data_only_in_ref_db.rpt data_only_in_ref_db.jpg || :
+    ls -ltr data_only_in_cmp_db.rpt data_only_in_cmp_db.jpg || :
+    if [[ -x "$montage" && -f data_only_in_ref_db.jpg && -f data_only_in_cmp_db.jpg ]] ; then
+      $montage -tile 2x1 -geometry 600x600 data_only_in_ref_db.jpg data_only_in_cmp_db.jpg montage.jpg
+      xv montage.jpg &
+    fi
+    if [[ -x "$xdiff" && -f data_only_in_ref_db.rpt && -f data_only_in_cmp_db.rpt ]] ; then
+      $xdiff data_only_in_ref_db.rpt data_only_in_cmp_db.rpt &
+    fi
+    echo ">>> Databases differ against the given query/table"
+    echo ">>> There are $ndiffs1 rows which are ONLY found in reference database ($refpath)"
+    echo ">>> There are $ndiffs2 rows which are ONLY found in comparison database ($cmppath)"
+    echo ">>> Difference database is found under $thisdir/$REFCMP"
+    echo ">>> Data in pool#1 denotes the rows found only in reference database"
+    echo ">>> Data in pool#2 denotes the rows found only in comparison database"
+  else
+    echo ">>> Databases are considered similar against the given query/table"
+    rm -rf $REFCMP
+  fi
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbdump b/odb/src/scripts/odbdump
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odbdump
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odbdump.ksh b/odb/src/scripts/odbdump.ksh
new file mode 100755
index 0000000..0ac7dc8
--- /dev/null
+++ b/odb/src/scripts/odbdump.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh
+#
+# A utility to create statistics on odbdump-creation.
+# Can be modified later on to create the actual dump(s)
+#
+# 26-Jun-2008 by Sami Saarinen, ECMWF
+#
+
+set -eu
+
+set +v
+
+pools=""
+#pools="-p 1-2"
+
+dbname=ECMA
+odbdump=$ODB_FEBINPATH/odbdump.x
+
+for f in ${dbname}.*.tar
+do
+  dir=$(basename $f .tar)
+
+  echo "/database=$dir"
+
+  dir=$(pwd)/$dir
+
+  echo " "
+  echo "    $(hostname):$dir"
+  echo " "
+
+  #-- Get analysis date & time, experiment name/version & 
+  #   run date/time, actual no. of updates, no. of pools, no. of tables
+  q0="select expver, andate, antime, creadate, creatime"
+  q0="${q0}, mxup_traj, \$npools# as npools, \$ntables# as ntables from desc"
+  $odbdump -i $dir -q "$q0" $pools -N -m1 | tee $dir.q0
+
+  #-- Can this be a satellite at all ? 
+  qsat="select max(sat.len) from hdr"
+  $odbdump -i $dir -q "$qsat" $pools -N | tee $dir.qsat
+  echo " "
+
+  sat=$(egrep -v '^#' $dir.qsat | perl -pe 's/\s+//g;')
+  if [[ $sat -gt 0 ]] ; then # This is a satellite
+    grp="obstype,codetype,sensor"
+
+    #-- Provide list of different satellite id's with description
+
+    qid="select distinct $grp,satid,statid,satname[1:4] from hdr,sat"
+    $odbdump -i $dir -q "$qid" $pools | tee $dir.qid
+    echo " "
+
+  else # conventional obs
+    grp="obstype,codetype"
+
+    #-- Provide list of different station id's/ident binned per obstype
+
+    qid="select distinct $grp,satid,statid from hdr"
+    $odbdump -i $dir -q "$qid" $pools | tee $dir.qid
+    echo " "
+  fi
+
+  #-- Different groups: either per (obstype,codetype)-pair or (obstype,codetype,sensor)-triplet
+  q1="select distinct $grp from hdr"
+  $odbdump -i $dir -q "$q1" $pools -N -D, | tee $dir.q1
+  echo " "
+
+  #-- Count of hdr-entries binned by the group
+  q2="select $grp,count(*) from hdr"
+  $odbdump -i $dir -q "$q2" $pools -N | tee $dir.q2
+  echo " "
+
+  #-- Count of body-entries binned by the group AND variable number
+  q3="select $grp,varno,count(*) from hdr,body"
+  $odbdump -i $dir -q "$q3" $pools -N | tee $dir.q3
+  echo " "
+
+  #-- Get data volume statistics binned per group
+  for w in $(egrep -v '^#' $dir.q1)
+  do
+    if [[ $sat -eq 1 ]] ; then
+      where=$(echo "$w" | perl -pe 's/^\s*(\d+)/obstype=$1/;s/,(\d+)/ and codetype=$1/;s/,(\d+)/ and sensor=$1/;')
+    else
+      where=$(echo "$w" | perl -pe 's/^\s*(\d+)/obstype=$1/;s/,(\d+)/ and codetype=$1/;')
+    fi    
+
+    #-- Which tables present for this WHERE-statement ?
+
+    tables="hdr,body,errstat"
+
+    if [[ $sat -eq 1 ]] ; then
+      for tbl in $(grep LINKLEN $dir/$dbname.dd | grep '@sat ' | perl -pe 's/^.*\(([^)].*)\).*/\1/')
+      do
+        query="select max(${tbl}.len) from hdr,sat where $where"
+        cnt=$(set +e; $odbdump -i $dir -q "$query" $pools -T | perl -pe 's/\s+//g;')
+        if [[ $cnt -gt 0 ]] ; then
+          tables="${tables},$tbl"
+          if [[ "$tbl" = "atovs" ]] ; then # automatically include atovs_pred
+            tables="${tables},atovs_pred"
+          fi
+          #-- search for possible ${tbl}_body -tables
+          tbl_body="${tbl}_body"
+          query="select max(${tbl_body}.len) from hdr,sat,$tbl where $where"
+          cnt=$(set +e; $odbdump -i $dir -q "$query" $pools -T | perl -pe 's/\s+//g;')
+          if [[ $cnt -gt 0 ]] ; then
+            tables="${tables},$tbl_body"
+          fi
+        fi
+      done
+    fi
+
+    qstat_suffix=$(echo "$w" | perl -pe 's/^\s*/group=/; s/\s+/_/g; s/\s+/_/g; s/_$//;')
+
+    cols='lldegrees(lat at hdr) as lat at hdr, lldegrees(lon at hdr) as lon at hdr, "~/(LINK|:lat at hdr|:lon at hdr)/"'
+
+    hash_tables=$(echo "$tables" | perl -pe 's/(\w+)/#$1/g; s/,\s*$//')
+    qstat="select \$pool#, $hash_tables , $cols from $tables where $where"
+    $odbdump -i $dir -q "$qstat" $pools -s | tee $dir.qstat.$qstat_suffix
+    echo " "
+  done # for w in $(egrep -v '^#' $dir.q1)
+
+  echo "/end"
+done
diff --git a/odb/src/scripts/odbdup b/odb/src/scripts/odbdup
new file mode 100755
index 0000000..d9cd47e
--- /dev/null
+++ b/odb/src/scripts/odbdup
@@ -0,0 +1,431 @@
+#!/bin/ksh
+trap 'echo "odbdup: Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#begin
+#
+# Usage: odbdup [-c] [-F] -i input_db_dir -o output_db_dir [-l output_dbname] [-D] [-L] [-r] [-Q] [-s]
+#
+# Purpose: Duplicates existing database with a different name
+#          The duplicate is a copy only if "-c" option used, otherwise
+#          actual data (i.e. not metadata) is symbolically linked to the
+#          originating database.
+#          The use of this facility enables (say) a concurrent access two databases
+#          which originally had the same name, since now two ODB_open()'s are
+#          applied to different database names -- thus bypassing one of the ODB
+#          limitations not being able to concurrently ODB_open() two databases of
+#          a similar name.
+#
+# Notes: 1) Any recompilations must take place outside this script
+#        2) If the copy-option is used, then the resulting database is self-contained
+#           and can be tar'red up or modified without consequences to the originating
+#           database
+#        3) Output database name is guessed from output database directory name,
+#           but can be bypassed by use of -l option
+#        4) Input database name is determined from the .dd-file name residing in
+#           the input (originating) database directory
+#
+# -i input_db_dir  : Input database directory ; name derived from its .dd-file prefix
+#                    Can be supplied multiple times to enable composite database
+#                    Caveat: Multiple -i's disable existing cache/ dirs and dca/ dirs
+#                            Multiple -i's also imply creation of dca/ dir regardless if -D option was used or not
+# -o output_db_dir : Database to be created either copying or symbolically linking the data
+# -c : Copy existing database from input_db_dir to output_db_dir
+#      By default only metadata from the existing database is copied (and renamed), and
+#      data is symbolically linked (this saves potentially lots of space)
+# -F : Enforces to create output_db_dir, even if it already exists, in which case
+#      the existing one is removed first
+# -l output_dbname : Name of the output database, unless can be derived from the output_db_dir
+# -D : Do not run dcagen
+# -L : Apart from metadata, copy & rename also the database library from the input_db_dir
+#      (this option has not been implemented yet due to problems with different symbol names)
+# -r : Retains metadata, but removes data (-links) from output_db_dir. This option
+#      will ignore -c options and symbolic links for data
+# -m : Allow mismatch in database names
+# -Q : Do *NOT* use greatly speeded up dcagen (=dcaquick) maybe because
+#      input dca-files are binary, gzipped or otherwise invalid for dcaquick
+# -P : Do *NOT* run odbprune
+# -s : Run silently
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 15-Mar-2005 : Initial version
+#                               27-May-2005 : Added doc about options
+#                               27-May-2005 : -D option prevents running the dcagen
+#                               27-May-2005 : -r option retains metadata, but removes data
+#                               27-May-2005 : -L options copies & renames the lib$input_db.a (N/W)
+#                               22-Feb-2006 : Bring over the possible cache/ directory, too
+#                               13-Mar-2006 : Allow multiple -i options to enable composite databases
+#                               03-Apr-2006 : Option -m added
+#                               13-Nov-2006 : Option -Q added
+#                               13-Feb-2006 : Option -P added
+#                               21-Dec-2006 : Option -s added
+#
+#-----------------------------------------------------------------------
+
+set +xv
+set -eu
+
+thisdir=$(pwd)
+
+cmd=$0
+thiscmd=$(basename $0)
+
+if [[ $# -gt 0 ]] ; then
+  ARGS="${thiscmd} $*"
+else
+  ARGS="${thiscmd}"
+fi
+
+#-----------------------------------------------------------------------
+
+FLAGS=cDFi:l:L:mo:PQrs
+
+copy=0
+dcagen=1
+enforce=0
+indb=""
+inputdirs=""
+libtoo=0
+output=""
+outdb=""
+remdata=0
+mismatch=0
+dcaquick=1
+prune=1
+silent=0
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  c)    copy=1;;
+  D)    dcagen=0;;
+  F)    enforce=1;;
+  i)    inputdirs="$inputdirs $OPTARG";;
+  l)    outdb="$OPTARG";;
+  L)    libtoo=1;;
+  m)    mismatch=1;;
+  o)    output="$OPTARG";;
+  P)    prune=0;;
+  Q)    dcaquick=0;;
+  r)    remdata=1;;
+  s)    silent=1;;
+  *)	abort=yes; break;;
+  esac
+done
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  abort=yes
+fi
+
+if [[ $silent -eq 0 ]] ; then
+  echo "$ARGS" >&2
+fi
+
+#-----------------------------------------------------------------------
+# Check obvious error(s)
+#-----------------------------------------------------------------------
+
+if [[ "$outdb" = "" ]] ; then
+  outdb=$(basename "$output")
+fi
+outdb=$(echo "$outdb" | perl -pe 's/\s+//g; s/\..*//; tr/[a-z]/[A-Z]/; s/[_-]//g')
+
+if [[ "$output" = "" ]] ; then
+  echo "***Error: Output database directory must be given" >&2
+  abort=yes
+elif [[ -d $output && $enforce -eq 0 ]] ; then
+  echo "***Error: Output database directory already exists. Use -F flag to enforce overwrite" >&2
+  abort=yes
+fi
+
+if [[ $abort = no ]] ; then
+#- Output database dirs basename cannot contain '-' --> filter them out & reconstruct
+  apath=$(dirname $output)
+  adir=$(basename $output | perl -pe 's/-//g')
+  output="$apath/$adir"
+fi
+
+ninp=0  # Number of input dirs
+indb="" # Input database name
+glbnpools=0
+
+if [[ $abort = no && "$inputdirs" != "" ]] ; then
+  typeset tmp=""
+  typeset d
+  for d in $(exec 2>/dev/null; /bin/csh -c "/bin/ls -dC1 $inputdirs || :")
+  do
+    if [[ -d $d ]] ; then
+      tmp="${tmp}$d "
+      if [[ $prune -eq 1 ]] ; then
+        # a hack; for now ... before odbprune -E & dcagen work together
+        if [[ ! -f $d/.odbprune_done ]] ; then
+          odbprune -i $d >/dev/null 2>&1 || : &
+        fi
+      fi
+    fi
+  done
+  inputdirs=$tmp
+fi
+
+refset=0
+refdb=""
+refiom=0
+
+if [[ $abort = no && "$inputdirs" = "" ]] ; then
+  echo "***Error: Input database directory/-ies must be given" >&2
+  abort=yes
+elif [[ $abort = no ]] ; then
+  typeset input
+  for input in $inputdirs
+  do
+#    if [[ $silent -eq 0 ]] ; then
+#      echo "Processing ddfile in $input" >&2
+#    fi
+    typeset ddfile
+    if [[ -d $input ]] ; then
+      ddfile=$(set +e ; \cd $input >/dev/null 2>&1 ; \ls -C1 *.dd 2>/dev/null | head -1)
+    else
+      ddfile="$(basename "$input" |  perl -pe 's/\s+//g; s/\..*//; tr/[a-z]/[A-Z]/; s/[_-]//g').dd"
+    fi
+    indb=$(basename "$ddfile" .dd | perl -pe 's/\s+//g; s/\..*//; tr/[a-z]/[A-Z]/; s/[_-]//g')
+    ddfile="$indb.dd"
+
+    typeset iom=0
+    typeset npools=0
+
+    if [[ ! -d $input ]] ; then
+      echo "***Error: Input database directory '$input' does not exist" >&2
+      abort=yes
+    elif [[ ! -f $input/$ddfile ]] ; then
+      echo "***Error: The main metadata input file '$input/$ddfile' not found" >&2
+      abort=yes
+    else
+      iom=$(head -1 $input/$ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+      npools=$(head -5 $input/$ddfile | tail -1)
+    fi
+
+    if [[ "$input" = "$output" ]] ; then
+      echo "***Error: Input and output directories must differ" >&2
+      abort=yes
+    fi
+
+    if [[ $abort = no ]] ; then
+      if [[ $refset -eq 0 ]] ; then # set reference database (based on the 1st database in list)
+        refdb=$indb
+	refiom=$iom
+        refset=1
+      fi
+      if [[ $iom -ne $refiom ]] ; then
+        echo "***Error: Reference database (at $input) mismatch in I/O-method: Was $iom, expecting $refiom" >&2
+        abort=yes
+      fi
+
+      if [[ "$indb" != "$refdb" ]] ; then
+        if [[ $mismatch -eq 0 ]] ; then
+          echo "***Error: Reference database name mismatch (at $input): Was '$indb', expecting '$refdb'" >&2
+          abort=yes
+        else
+          echo "***Warning: Reference database name mismatch (at $input): Was '$indb', expecting '$refdb'" >&2
+        fi
+      fi
+    fi
+
+    if [[ $abort = no ]] ; then
+      ((glbnpools+=npools))
+      ((ninp+=1))
+#      if [[ $silent -eq 0 ]] ; then
+#        echo "Processing of $ddfile in $input done." >&2
+#      fi
+    fi
+  done
+fi
+
+if [[ $abort = no && $glbnpools -eq 0 ]] ; then
+  echo "***Error: Global number of input pools cannot be zero" >&2
+  abort=yes
+fi
+
+if [[ $abort = no ]] ; then
+  if [[ -d $output ]] ; then
+    \mv $output $output.$$
+    rm -rf $output.$$ &
+  fi
+
+  mkdir -p $output || {
+    echo "***Error: Cannot create output database directory" >&2
+    abort=yes
+  }
+fi
+
+#-----------------------------------------------------------------------
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  wait
+  exit 1
+fi
+
+#-----------------------------------------------------------------------
+
+if [[ $silent -eq 0 ]] ; then
+  echo "Copy option (on=1/off=0) : $copy"     >&2
+  echo "Enforce-option           : $enforce"  >&2
+  echo "dcagen-option (-D)       : $dcagen"   >&2
+  echo "dcaquick-option (-Q)     : $dcaquick" >&2
+  echo "Library-option           : $libtoo"   >&2
+  echo "Retain/remove-option     : $remdata"  >&2
+  echo "Allow DB-name mismatches : $mismatch" >&2
+fi
+
+#-----------------------------------------------------------------------
+
+output=$(\cd $output >/dev/null 2>&1 ; echo $(pwd))
+if [[ $silent -eq 0 ]] ; then
+  echo "Output database=$outdb at '$output'" >&2
+  echo "Number of input databases = $ninp" >&2
+fi
+
+#-----------------------------------------------------------------------
+
+wait
+
+meta="dd sch flags iomap"
+
+if [[ $refiom -eq 4 ]] ; then
+  echo "2" > $output/$outdb.iomap # use I/O-map file format#2
+  sub="&"
+  wait=wait
+else
+  sub=""
+  wait=""
+fi
+
+typeset ndbs=0
+typeset nglb=1
+typeset input
+for input in $inputdirs
+do
+  cd $thisdir
+  input=$(\cd $input >/dev/null 2>&1 ; echo $(pwd)) # becomes absolute path
+
+  typeset ddfile
+  cd $input
+  ddfile=$(\ls -C1 *.dd 2>/dev/null | head -1)
+  indb=$(basename "$ddfile" .dd)
+  indb=$(echo "$indb" | perl -pe 's/\s+//g; s/\..*//; tr/[a-z]/[A-Z]/; s/[_-]//g')
+
+  cd $thisdir
+
+  ((ndbs+=1))
+  if [[ $silent -eq 0 ]] ; then
+    echo " Input database #$ndbs = $indb at '$input'" >&2
+  fi
+
+  if [[ "$meta" != "" ]] ; then
+    cd $thisdir
+    cd $input
+    for sfx in $meta
+    do
+      filein=$indb.$sfx
+      fileout=$outdb.$sfx
+      if [[ -f $filein ]] ; then
+        if [[ $sfx = iomap && $refiom -eq 4 ]] ; then
+          echo "$input/$filein" >> $output/$outdb.iomap
+        else
+          cp $filein $output/$fileout
+          chmod u+w $output/$fileout
+        fi
+      fi
+    done
+  fi # if [[ "$meta" != "" ]] ; then
+
+  if [[ $remdata -eq 0 ]] ; then
+    cd $thisdir
+    cd $input
+    typeset npools=$(head -5 $indb.dd | tail -1)
+    if [[ $copy -eq 1 ]] ; then # copying
+      if [[ $ninp -eq 1 && -d cache ]] ; then
+        eval "cp -r cache $output $sub"
+      fi
+      typeset d=1
+      while [[ $d -le $npools ]]
+      do
+        if [[ -d $d ]] ; then
+          eval "cp -r $d $output/$nglb $sub"
+        fi
+        ((d+=1))
+        ((nglb+=1))
+      done
+      $wait
+      find $output -print | xargs chmod u+w
+    else # symbolic links (the default)
+      if [[ $ninp -eq 1 && -d cache ]] ; then
+        thedir=$(\cd cache >/dev/null 2>&1; /bin/pwd 2>/dev/null || pwd)
+        ln -s $thedir $output
+      fi
+      typeset curdir=$(pwd)
+      typeset d=1
+      while [[ $d -le $npools ]]
+      do
+        if [[ -d $d ]] ; then
+          eval "ln -s $curdir/$d $output/$nglb $sub"
+        fi
+        ((d+=1))
+        ((nglb+=1))
+      done
+      $wait
+    fi
+  else
+    if [[ $silent -eq 0 ]] ; then
+      echo "***Warning: -r option given ==> only metadata will be available for output db, not the actual data" >&2
+    fi
+  fi # if [[ $remdata -eq 0 ]] ; then ... else
+
+  if [[ $refiom -eq 4 ]] ; then
+    meta="iomap"
+  else
+    meta=""
+  fi
+done # for input in $inputdirs
+
+if [[ $ninp -gt 1 ]] ; then
+# Fiddle with number of pools
+  cd $thisdir
+  cd $output
+  awk '{ if (NR == 5) { print '"$glbnpools"'; } else { print; }}' < $outdb.dd > $outdb.dd.tmp
+  \mv $outdb.dd.tmp $outdb.dd
+else
+# Copy existing dca/ dir to output dir
+  cd $thisdir
+  cd $input
+  if [[ -d dca ]] ; then
+    rm -rf $output/dca 2>/dev/null || :
+    cp -r dca $output
+    cd $thisdir
+    cd $output
+    find dca -print | xargs chmod u+w
+    dcafix -q >&2
+  fi
+fi
+
+cd $thisdir
+cd $output
+
+if [[ $dcagen -eq 1 && ! -d dca ]] ; then
+  if [[ $dcaquick -eq 0 ]] ; then 
+    if [[ $silent -eq 0 ]] ; then
+      echo "Generating direct column access -indices. This may take a while ..." >&2
+    fi
+    dcagen -F -n -z -q >&2
+  else
+    if [[ $silent -eq 0 ]] ; then
+      echo "Generating direct column access -indices using existing DCA-indices (quick)" >&2
+    fi
+    dcaquick >&2
+  fi
+fi
+create_ioassign -l $outdb -q >&2
+
+exit 0
diff --git a/odb/src/scripts/odbf90 b/odb/src/scripts/odbf90
new file mode 100755
index 0000000..521ff37
--- /dev/null
+++ b/odb/src/scripts/odbf90
@@ -0,0 +1,124 @@
+#!/bin/ksh
+#
+# A script to invoke F90-compilation with correct (module) include path.
+#
+# Usage: odbf90 [flags] Fortran90-file(s) [object(s)] [-glue] [libraries]
+#
+# Author: Sami Saarinen, ECMWF, 1998-2004
+#
+#
+
+if [[ $# -lt 1 ]] ; then
+  head -6 $0 | tail -5
+  exit 1
+fi
+
+#-- gprof style profiling on ? Set this externally to "-pg" to enable gprof
+ODB_GPROF=${ODB_GPROF:=""}
+
+ODB_ARCH=${ODB_ARCH:="$ARCH"}
+test_arch=$(test_arch 2>/dev/null || echo "unknown")
+
+#MPICH_ROOT=${MPICH_ROOT:=/vol/rdx_dir/mpi/suse90/mpich-1.2.7} # for CPU_TYPE=amd64
+MPICH_ROOT=${MPICH_ROOT:=/not/available}
+
+#-- See also use_odb/use_odb.sh -scripts whether $LIBNETCDF was already set there
+if [[ "$ODB_ARCH" = @(ibm_power*) ]] ; then
+  LIBNETCDF=${LIBNETCDF:=/usr/local/lib/netcdf/current/lib/libnetcdf.a}
+else
+  LIBNETCDF=${LIBNETCDF:=/usr/local/apps/netCDF/current/lib/libnetcdf.a}
+fi
+
+if [[ -f "$LIBNETCDF" ]] ; then
+  netcdflib="-L$(dirname $LIBNETCDF) -l$(basename $LIBNETCDF | perl -pe 's/^lib//; s/\..*//;')"
+else
+  netcdflib=""
+fi
+
+odbglue="_odb_glue.o"
+[[ -f $odbglue ]] || odbglue=""
+
+compile_only=0
+for arg in $*
+do
+  if [[ "$arg" = "-c" ]] ; then
+    odbglue=""
+    compile_only=1
+    break
+  fi
+done
+
+addargs=""
+if [[ $compile_only -eq 0 ]] ; then
+  #-- create automatically odb-glue from (possible) -lDBNAME information
+  #-- first: merge possible "-l<space>XXX" into "-lXXX"
+  newargs=$(echo "$*" | perl -pe 's/-l\s+/-l/g');
+  dbnames=""
+  for arg in $newargs
+  do
+    if [[ "$(echo $arg | cut -c1-2)" = "-l" ]] ; then
+      db=$(echo $arg | cut -c3-)
+      DB=$(echo $db | perl -pe 's/\s+//g; s/\..*$//; s/[_-]//g; tr/a-z/A-Z/')
+      if [[ "$db" = "$DB" && "$db" != @(X11*) ]] ; then
+        dbnames="$dbnames $db"
+        # A big thanks to ttl 27/04/2006 for the idea of including -L$ODB_SRCPATH_<dbname> !!
+        typeset testvar=ODB_SRCPATH_${db}
+        typeset testvalue=$(eval echo \$$testvar 2>/dev/null || :)
+        if [[ "$testvalue" != "" && -d "$testvalue" ]] ; then
+          addargs="$addargs-L$testvalue "
+        fi
+      fi
+    fi
+  done
+  if [[ "$dbnames" != "" ]] ; then
+    create_odbglue $dbnames
+    odbglue="_odb_glue.o"
+  fi
+fi
+
+rc=0
+args=""
+for arg in $*
+do 
+  if [[ "$arg" = "-glue" ]] ; then
+    args="$args$odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | cut -c1-2)" = "-l" ]] ; then # insert -L's in-front of the first -l
+    args="$args$addargs$arg "
+    addargs=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(a|so|o|F|F90|f|f90)\b$/$1/')" = @(a|so|o|F90|F|f|f90) ]] ; then
+    args="$args$arg $odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(c)\b$/$1/')" = @(c) ]] ; then
+    odbcc -c $arg || rc=1
+    arg=$(echo $arg | sed 's/\.c/.o/')
+    args="$args$arg $odbglue "
+    odbglue=""
+  elif [[ "$(echo $arg | perl -pe 's/^.*\.(cc)\b$/$1/')" = @(cc) ]] ; then
+    odbc++ -c $arg || rc=1
+    arg=$(echo $arg | sed 's/\.cc/.o/')
+    args="$args$arg $odbglue "
+    odbglue=""
+  else
+    args="$args$arg "
+  fi
+done
+
+if [[ $rc -ne 0 ]] ; then
+  echo "***Error: There were problem(s) in compiling C/C++ files" >&2
+  exit $rc
+fi
+
+ODB_LD=${ODB_LD:=$ODB_F90}
+
+if [[ $compile_only -eq 1 ]] ; then
+  echo ${ODB_F90} ${ODB_GPROF} $args >&2
+  exec ${ODB_F90} ${ODB_GPROF} $args >&2
+else
+  echo ${ODB_LD} ${ODB_GPROF} -L. $args $odbglue $ODB_LIB >&2
+  exec ${ODB_LD} ${ODB_GPROF} -L. $args $odbglue $ODB_LIB >&2
+fi
+
+#-- should never end up here
+exit 1
+
diff --git a/odb/src/scripts/odbf90mp b/odb/src/scripts/odbf90mp
new file mode 120000
index 0000000..9ca9bad
--- /dev/null
+++ b/odb/src/scripts/odbf90mp
@@ -0,0 +1 @@
+odbf90
\ No newline at end of file
diff --git a/odb/src/scripts/odbgnuplot b/odb/src/scripts/odbgnuplot
new file mode 100755
index 0000000..d146e01
--- /dev/null
+++ b/odb/src/scripts/odbgnuplot
@@ -0,0 +1,354 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15 
+#begin
+#
+#Usage: odbgnuplot [OPTION]... [SQLfile]...
+#                  -l dbname                        : by default automatically detected
+#                  -v viewname_or_tablename         : default=myview ; could be a table name, say: @hdr
+#                  -q 'select statement'            : supply ODB/SQL query directly (by default implies -v myview)
+#                  -s starting_row                  : default=1 (counting starts from the first active pool)
+#                  -n max_number_of_rows_to_display : default=-1 ; if -1 --> unlimited)
+#                  -a                               : display all rows (same as -n -1)
+#                  -b row_buffer_size               : default=1000 ; if -1 --> no. of rows in each pool)
+#                  -E                               : Use the same -s & -n & -b option for Every pool separately
+#                  -p poolmask(s)                   : default=-1 i.e. all pools included; f.ex.: -p 1 -p1-4 -p1,3,6
+#                  -k                               : konvert (lat,lon) to degrees
+#                  -c                               : force re-creation of lib<dbname>.a
+#                  -d "options"                     : run also dcagen with these options
+#                  -5                               : do NOT use fast I/O-method=5, even if desirable
+#                  -f output_file                   : Save displayed data on file output_file, too
+#                  -T                               : set ODB tracing on
+#                  -g                               : Enable debugging output go to stderr.out
+#                  -D debugger                      : Run tool under debugger (default=none)
+#                  -0                               : (zero) ignore stderr (by default written to stderr.out)
+#                  -H dr_hook_opt                   : Enable Dr.Hook profiler and export DR_HOOK_OPT with dr_hook_opt
+#                  -h                               : Print help/usage and abort
+#
+#                  -x xlabel                        : x-label (if empty --> 1st SELECT-column of the SQL)
+#                  -y ylabel                        : y-label (if empty --> 2nd SELECT-column of the SQL)
+#                  -z zlabel                        : z-label (if empty --> 3rd SELECT-column of the SQL; implies "splot")
+#                  -w 'from table where ...'        : from|from+where|from+where+orderby|from+orderby|where|where+orderby|orderby
+#                  -t                               : set x-label to date/time
+#
+# (... under development ...)
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 09-May-2006 ; based on odbless-script
+#
+
+set -eu
+
+export SHELL=/bin/ksh
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+basecmd=$(basename $cmd)
+
+thisdir=$(pwd)
+cd $thisdir
+
+: ${dbname:=}
+: ${dbdir:=${thisdir}}
+: ${views:=}
+: ${viewname_given:=0}
+: ${start:=1}
+: ${limit:=-1}
+: ${rowbuf:=100000}
+: ${poolmask:=}
+: ${stderr:=stderr.out}
+: ${query:=}
+: ${query_given:=0}
+: ${dcagen_opt:=}
+: ${io_method:=5}
+: ${recompile:=0}
+: ${konvert:=0}
+: ${output:=}
+: ${trace:=0}
+: ${debug:=0}
+: ${debugger:=}
+: ${drhookopt:=}
+: ${every:=0}
+: ${where:=}
+: ${plotting:=plot}
+: ${minx:=}
+: ${maxx:=}
+: ${miny:=}
+: ${maxy:=}
+: ${minz:=}
+: ${maxz:=}
+: ${rotate_x:=}
+: ${rotate_z:=}
+: ${timefmt:=}
+: ${title:=}
+: ${terminal:=}
+: ${styles:=points}
+: ${xdata:=}
+: ${xlabel:=}
+: ${ylabel:=}
+: ${zlabel:=}
+: ${EXE:=./odbgnuplot.x}
+: ${FILTER:=}
+
+: ${ODB_BINPATH:=}
+: ${ODB_LIBPATH:=}
+
+: ${ftime:=$ODB_BINPATH/time.awk}
+: ${anime:=}
+
+: ${GNUPLOT:="gnuplot -persist"}
+: ${MAKEGP:=$ODB_BINPATH/makegp.ksh}
+
+FLAGS=ab:cd:ED:f:ghH:kl:n:p:q:s:Ttv:05x:y:z:w:
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  a) limit="-1";;
+  b) rowbuf="$OPTARG";;
+  c) recompile=1;;
+  d) dcagen_opt="$OPTARG";;
+  D) debugger="$OPTARG";;
+  E) every=1;;
+  f) output="$OPTARG";;
+  g) debug=1;;
+  h) abort=yes; break;;
+  H) drhookopt="$OPTARG";;
+  k) konvert=1;;
+  l) dbname="$OPTARG";;
+  n) limit="$OPTARG";; 
+  p) poolmask="$poolmask $OPTARG";;
+  q) query_given=1; query="$OPTARG";;
+  s) start="$OPTARG";;
+  T) trace=1;;
+  t) xlabel="date/time";;
+  v) views="${views:+${views} }${OPTARG}"; viewname_given=1;;
+  0) stderr="/dev/null";;
+  5) io_method=-1;; # Setting this to a <=0 value will ensure I/O-method 5 will NOT be used
+                    # If > 0, there is an automatic test for READ/ONLY databases, whether ./dca
+                    # directory exists. But keeping I/O-method <= 0 bypasses this testing
+  x) xlabel="$OPTARG";;
+  y) ylabel="$OPTARG";;
+  z) zlabel="$OPTARG"; plotting=splot;;
+  w) where="$OPTARG";;
+  *) abort=yes; break;;
+  esac
+done
+
+shift `expr ${OPTIND} - 1`
+
+files=${*:-}
+: ${views:=myview}
+
+if [ -z "${output}" ]; then
+    case ${terminal} in
+        postscript*) output=./`echo ${views} | sed -e 's/ /_/g'`.ps ;;
+    esac
+fi
+
+case $(echo "${xlabel}" | perl -pe 'tr/A-Z/a-z/') in
+    date | date at hdr)
+        timefmt="%Y%m%d"
+        xdata=time
+        ;;
+    time | time at hdr)
+        timefmt="%H%M%S"
+        xdata=time
+        ;;
+    date/time)
+        FILTER="awk -f ${ftime}"
+        timefmt="%Y%m%d/%H%M%S"
+        xdata=time
+        ;;
+esac
+
+if [[ "$abort" = "no" && "$dbname" = "" ]] ; then
+  dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    dbname=""
+    abort=yes
+  fi
+fi
+
+if [[ "$abort" = "no" && "$debugger" != "" ]] ; then
+  typeset test=$(whence "$debugger" 2>/dev/null || echo "")
+  if [[ "$test" = "" ]] ; then
+    echo "***Error: Unable to locate debugger '$debugger'"
+    abort=yes
+  else
+    debugger=$test
+  fi
+fi
+
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+if [[ -d "$dbname" ]] ; then
+  dbdir=$(\cd $dbname 2>/dev/null ; pwd)
+  dbname=$(basename "$dbname" | perl -pe 's/\..*//; tr/a-z/A-Z/')
+fi
+
+is_table=$(echo "$views" | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+test $is_table -eq 1 && files=/dev/null
+
+cd $dbdir
+
+if [[ $is_table -eq 0 ]] ; then # Is not a table
+  if [[ $query_given -eq 0 && $viewname_given -eq 0 && -z "${files}" && \
+        "$xlabel" != "" && "$ylabel" != "" ]] ; then
+
+    case $(echo "${xlabel}" | perl -pe 'tr/A-Z/a-z/') in
+        date/time) query="SELECT date at hdr, time at hdr, ${ylabel}" ;;
+        *)  query="SELECT $xlabel, $ylabel" ;;
+    esac
+
+    [[ "$zlabel" = "" ]] || query="$query, $zlabel";
+    [[ "$where"  = "" ]] || query="$query  $where";
+    query="$query;"
+    query_given=1
+  fi
+  if [[ $query_given -eq 1 ]] ; then
+    files=./${views}.sql
+    echo "$query" > ${files}
+  fi
+fi
+
+#if [[ ! -f "${EXE}" ]]; then
+    if [[ ! -f lib$dbname.a ]] || \
+       [[ ! -f $dbname.ddl_ ]] || \
+       [[ ! -f ${dbname}.h  ]] || \
+       [[ $ODB_FEBINPATH/odb98.x -nt $dbname.ddl_ ]] || \
+       [[ $dbname.ddl -nt $dbname.ddl_ ]] ; then
+      recompile=1
+    fi
+#fi
+
+if [[ $recompile -eq 1 ]] ; then
+  odbcomp -z $dbname.sch
+fi
+
+if [[ "$dcagen_opt" != "" ]] ; then
+  dcagen -F $dcagen_opt
+fi
+
+if [[ $is_table -eq 0 && "${files}" != "/dev/null" && -n "${files}" ]] ; then
+  odbcomp -l$dbname -w ${files}
+fi
+
+#echo "views=$views" 1>&2
+if [[ $is_table -eq 1 ]] ; then
+  export ODB_CONSIDER_TABLES=$(echo $views | perl -pe 's#\@(\w+)#/\L$1/#')
+elif [[ -f ${dbname}_$views.c ]] ; then
+  # the following hassle defines you the ODB_CONSIDER_TABLES
+  eval `fgrep '#define ODB_CONSIDER_TABLES' ${dbname}_$views.c | awk '{print "export",$2"="$3}'`
+else
+  export ODB_CONSIDER_TABLES='*'
+fi
+ODB_CONSIDER_TABLES=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 'tr/A-Z/a-z/')
+#echo "==> ODB_CONSIDER_TABLES=$ODB_CONSIDER_TABLES" 1>&2
+
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK="$poolmask"
+  #echo "==> ODB_PERMANENT_POOLMASK=$ODB_PERMANENT_POOLMASK" 1>&2
+fi
+
+if [[ -f Odbgnuplot.F90 ]] ; then
+  if [[ ! -f Odbgnuplot.o ]] || [[ Odbgnuplot.F90 -nt Odbgnuplot.o ]] ; then
+    odbf90 -c Odbgnuplot.F90
+  fi
+fi
+
+if [[ $recompile -eq 1 ]] || \
+   [[ ! -f ${EXE} ]] || \
+   [[ lib$dbname.a -nt ${EXE} ]] || \
+   [[ $ODB_LIBPATH/libodbmain.a -nt ${EXE} ]] ; then
+  obj=$($ODB_AR t $ODB_LIBPATH/libodbmain.a | grep Odbgnuplot)
+  $ODB_AR x $ODB_LIBPATH/libodbmain.a $obj
+  odbf90 $obj -l$dbname -o ${EXE}
+  rm -f $obj
+fi
+
+export ODB_LAT=${ODB_LAT:="lat at hdr"}
+export ODB_LON=${ODB_LON:="lon at hdr"}
+export ODB_LATLON_RAD=$($ODB_FEBINPATH/latlon_rad 2>/dev/null || echo "-1")
+
+#-- I/O-method
+ddfile=$dbdir/$dbname.dd
+if [[ -s $ddfile ]] ; then
+  iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+else
+  iom=1
+fi
+
+#-- remove possible file (not dir) $dbdir/dca, and if not successful then possible *empty* $dbdir/dca dir
+\rm $dbdir/dca 2>/dev/null || rmdir $dbdir/dca 2>/dev/null || :
+
+export ODB_IO_METHOD=${ODB_IO_METHOD:=$io_method}
+if [[ $io_method -eq 5 && ! -d $dbdir/dca ]] ; then
+#  ODB_IO_METHOD=$iom
+  ODB_IO_METHOD=0 # for now
+fi
+
+export ODB_REPORTER=stdout
+export ODB_PRINT_COLON="#"
+
+args=
+for view in ${views}
+do
+    args="${args:+${args} }\"< ${EXE} 0 $dbname ${view} $start $limit $rowbuf $konvert $every $debug 2>>$stderr ${FILTER:+| ${FILTER}}\""
+done
+
+if [[ "$debugger" = "" ]] ; then
+  if [[ $trace -eq 1 ]] ; then # turn ODB-tracing on
+    export ODB_TRACE_PROC=-1
+    export ODB_TRACE_FILE=trace.%d
+    export ODB_TRACE_FLUSH_FREQ=1
+  fi
+
+  if [[ "$drhookopt" != "" ]] ; then
+    export DR_HOOK=true
+    export DR_HOOK_OPT="$drhookopt"
+  fi
+
+  eval \
+  minx=${minx} \
+  maxx=${maxx} \
+  miny=${miny} \
+  maxy=${maxy} \
+  minz=${minz} \
+  maxz=${maxz} \
+  output=${output} \
+  plotting=${plotting} \
+  postload=${anime} \
+  regexp=\'5\' \
+  rotate_x=${rotate_x} \
+  rotate_z=${rotate_z} \
+  styles=\"${styles}\" \
+  terminal=\"${terminal}\" \
+  title=\"${title}\" \
+  timefmt=\"${timefmt}\" \
+  xdata=${xdata} \
+  xlabel=\"${xlabel}\" \
+  ylabel=\"${ylabel}\" \
+  zlabel=\"${zlabel}\" \
+  ${MAKEGP} ${args} | eval ${GNUPLOT}
+
+  # Wanna run it ? Remove the '#' below
+  # eval  $cmd2
+
+else # Run under $debugger
+
+  cmdargs="1 $dbname $views $start $limit $rowbuf $konvert $every $debug"
+
+  echo "Using debugger '$debugger'"
+  echo "Use the following arguments: $cmdargs"
+  
+  $debugger ${EXE}
+
+  exit 1
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbgunzip b/odb/src/scripts/odbgunzip
new file mode 120000
index 0000000..3a86bfb
--- /dev/null
+++ b/odb/src/scripts/odbgunzip
@@ -0,0 +1 @@
+odbgzip
\ No newline at end of file
diff --git a/odb/src/scripts/odbgzip b/odb/src/scripts/odbgzip
new file mode 100755
index 0000000..62b6e9d
--- /dev/null
+++ b/odb/src/scripts/odbgzip
@@ -0,0 +1,119 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#
+# odbgzip/odbgunzip
+#
+#begingzip
+#
+# odbgzip : gzip's ODB data file(s) and preserve their file suffix
+#           check if already gzip'ped --> ignored 
+#           (note: not having the suffix .gz is not a guarantee for that!)
+#
+# odbgzip [-fv123456789] [-B bufsize] [-t] file(s)
+#
+# The default: odbgzip -1f -B 1M 
+#
+#endgzip
+#
+#begingunzip
+#
+# odbgunzip : gunzip's ODB data file(s), but only they were gzip'ped in the first place
+#             (note: not having the suffix .gz is not a guarantee for that!)
+#
+# odbgunzip [-v] [-B bufsize] [-t] file(s)
+#
+# The default: odbgunzip -B 1M 
+#
+#endgunzip
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+#=======================================================================
+
+pack=1
+echo "$(basename $0)" | grep gzip >/dev/null 2>&1 || pack=0
+
+#=======================================================================
+
+bufsize=1M
+verbose=0
+
+if [[ $pack -eq 1 ]] ; then
+  opt="-1f"
+  flags="B:ftv123456789"
+else
+  opt=""
+  flags="B:tv"
+fi
+tables=0
+
+abort=no
+while getopts $flags option
+do
+  case $option in
+    B) bufsize="$OPTARG";;
+    f) opt="${opt} -f";;
+    t) tables=1;;
+    v) opt="${opt} -v"; verbose=1;;
+    1) opt="${opt} -1";;
+    2) opt="${opt} -2";;
+    3) opt="${opt} -3";;
+    4) opt="${opt} -4";;
+    5) opt="${opt} -5";;
+    6) opt="${opt} -6";;
+    7) opt="${opt} -7";;
+    8) opt="${opt} -8";;
+    9) opt="${opt} -9";;
+    *) abort=yes;;
+  esac
+done
+
+shift $(expr $OPTIND - 1)
+
+if [[ "$abort" = "yes" ]] ; then
+  if [[ $pack -eq 1 ]] ; then
+    awk '/#begingzip/,/#endgzip/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  else
+    awk '/#begingunzip/,/#endgunzip/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  fi
+  exit 1
+fi
+
+if [[ $# -lt 1 ]] ; then # No files supplied
+  files=""
+else
+  files="$*"
+fi
+
+if [[ $tables -eq 1 ]] ; then
+  files="$files [0-9]*/*"
+fi
+
+#=======================================================================
+
+magic="037213"
+old_magic="037236"
+
+for f in $files
+do
+  if [[ -s $f ]] ; then
+    check=$(od -cv $f | head -1 | awk '{print $2$3}')
+    if [[ $pack -eq 1 ]] ; then
+      if [[ "$check" != "$magic" && "$check" != "$old_magic" ]] ; then
+        # until gzip calls setbuf() ...
+        [[ $verbose -eq 0 ]] || (echo "gzip'ing $f ... " | perl -pe 's/\n//;')
+        dd bs=$bufsize if=$f 2>/dev/null | $ODB_GZIP $opt -c | dd bs=$bufsize of=$f.gz 2>/dev/null
+        mv $f.gz $f
+      fi
+    else
+      if [[ "$check" = "$magic" ]] || [[ "$check" = "$old_magic" ]] ; then
+        # until gunzip calls setbuf() ...
+        [[ $verbose -eq 0 ]] || (echo "gunzip'ing $f ... ")
+        dd bs=$bufsize if=$f 2>/dev/null | $ODB_GUNZIP $opt -c | dd bs=$bufsize of=$f.ugz 2>/dev/null
+        mv $f.ugz $f
+      fi
+    fi
+  fi
+done
diff --git a/odb/src/scripts/odbheader b/odb/src/scripts/odbheader
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odbheader
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odbi_proxy b/odb/src/scripts/odbi_proxy
new file mode 100755
index 0000000..0bfed9a
--- /dev/null
+++ b/odb/src/scripts/odbi_proxy
@@ -0,0 +1,108 @@
+#!/bin/ksh
+#
+# Usage: env [env-args] odbi_proxy [odbi_server.x-args]
+#
+# See [env-args] from source code at function odb/a*x/odbcs_wrappers.c:StartServer()
+#                                         and odb/a*x/odbcs_conf.c
+#
+
+set +eu
+
+args=${*:-}
+
+verbose=0
+for a in $args
+do
+  if [[ "$a" = "-v" ]] ; then
+    verbose=1
+    break;
+  fi
+done
+
+host=$(hostname)
+
+export ARCH=${ARCH:=$_ARCH}
+export CPU_TYPE=${CPU_TYPE:=$_CPU_TYPE}
+export OBJECT_MODE=${OBJECT_MODE:=$_OBJECT_MODE}
+export ODB_VERSION=${ODB_VERSION:=$_ODB_VERSION}
+export ODB_ARCH=${ODB_ARCH:=$_ODB_ARCH}
+
+initscr=$_ODB_ROOT/bin/use_odb.sh
+if [[ -r $initscr ]] ; then
+  export ODB_DIR=${ODB_DIR:=$_ODB_DIR}
+  export ODB_ROOT=${ODB_ROOT:=$_ODB_ROOT}
+else # ECMWF ;-(
+  initscr=${ECMWFHOME:=/usr/local/share/ecmwf}/use/sh.odb
+fi
+
+#-- ECMWF's special rumba ... hmmm ... ;-(
+
+if [[ X"${PGI:-}" = X ]] ; then # PGI-compiler root maybe missing ...
+  initscr_pgi=${ECMWFHOME:=/usr/local/share/ecmwf}/use/sh.pgi
+  if [[ -r $initscr_pgi ]] ; then
+    . $initscr_pgi >/dev/null 2>&1
+  fi
+fi
+
+hpc=$(echo "$host" | cut -c1-3)
+system=$(uname -s | cut -c1-3)
+
+if [[ "$hpc" = hpc && "$system" = "AIX" ]] ; then
+  hpcx=$(echo "$host" | cut -c1-4)
+  gid=$(id -gn)
+  uid=$(id -un)
+  export TMPDIR=/$hpcx/tmp/$gid/$uid   # ~ $TEMP on HPCs
+else
+  uid=$(id -un)
+  export TMPDIR=/tmp/tmpdir/$uid    # ~ $TRUE_TMPDIR
+fi
+
+if [[ -r $initscr ]] ; then
+  . $initscr >/dev/null 2>&1
+else
+  echo "***Error in odbi_proxy: Unable to run the initialization script '$initscr' on $host" >&2
+  exit 1
+fi
+
+set -e
+
+if [[ ! -d $TMPDIR ]] ; then
+  mkdir -p $TMPDIR 2>/dev/null || :
+  if [[ ! -d $TMPDIR ]] ; then
+    uid=$(id -un)
+    export TMPDIR=/tmp/$uid
+    mkdir -p $TMPDIR 2>/dev/null || :
+  fi
+  if [[ ! -d $TMPDIR ]] ; then
+    export TMPDIR=/tmp
+  fi
+fi
+
+\cd $TMPDIR >/dev/null 2>&1 || :
+
+ulimit -c 0  # no core dumps
+ulimit -s unlimited 2>/dev/null >&2 || :
+
+if [[ $verbose -eq 1 ]] ; then
+  ulimit -a >&2 || :
+fi
+
+# Avoid possible gdb/dbx hangs ... ;-(
+export GNUDEBUGGER=0
+export DBXDEBUGGER=0
+
+export DR_HOOK=0
+export EC_SORTING_INFO=0
+
+if [[ -x $ODB_BINPATH/odbi_server.x ]] ; then
+  if [[ $verbose -eq 1 ]] ; then
+    exec $ODB_BINPATH/odbi_server.x $args >&2 &
+  else
+    exec $ODB_BINPATH/odbi_server.x $args >/dev/null 2>&1 &
+  fi
+else
+  echo "***Error in odbi_proxy: Unable to start the ODB-server '$ODB_BINPATH/odbi_server.x' on $host" >&2
+  exit 2
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbi_show_server b/odb/src/scripts/odbi_show_server
new file mode 100755
index 0000000..46a9bed
--- /dev/null
+++ b/odb/src/scripts/odbi_show_server
@@ -0,0 +1,82 @@
+#!/bin/ksh
+#begin
+#
+# Show running odbi_server.x's started by the username and/or by others
+#
+# Usage: odbi_show_server [-u username] [-x server_exe] [-h hostname]
+#
+# Note:  -h hostname can be supplied multiple times to monitor many hosts e.g.:
+#
+#        -h hpce -h bee04 -h ecgate
+# 
+# If -h hostname are given as the last argument(s), then -h's can be left out :
+#        
+#           hpce    bee04    ecgate
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 06-Dec-2007
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+user=""
+exe=odbi_server.x
+host=""
+
+FLAGS=x:u:h:
+
+abort=no
+
+while getopts ${FLAGS} i
+do
+  case $i in
+	x)	exe="$OPTARG";;
+	u)	user="$OPTARG";;
+	h)	host="$host$OPTARG ";;
+	*) 	abort=yes; break;;
+	\?)     abort=yes; break;;
+  esac
+done
+
+#-- Abort, if necessary
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  host="$host$*"
+fi
+
+if [[ "$host" = "" ]] ; then
+  host="localhost"
+fi
+
+set +e
+exec 2>/dev/null
+
+for h in $host
+do
+  ip_addr=$($ODB_FEBINPATH/odbi_host.x "$h" || echo '0')
+  if [[ "$ip_addr" != "0" ]] ; then
+    if [[ "$h" = "localhost" ]] ; then
+      prefix=""
+    else
+      prefix="/usr/bin/rsh $h"
+    fi
+    if [[ "$user" != "" ]] ; then
+      cmd="$prefix ps -fu $user"
+    else
+      cmd="$prefix ps -fe"
+    fi
+    $cmd | fgrep "$exe" | fgrep -v grep | perl -pe 's/^(\s*)/'"$h\($ip_addr\)"': /; s/\s+/ /g; s/$/\n/;'
+  fi
+done
+
+exit 0
diff --git a/odb/src/scripts/odbi_start_server b/odb/src/scripts/odbi_start_server
new file mode 100755
index 0000000..e4927f8
--- /dev/null
+++ b/odb/src/scripts/odbi_start_server
@@ -0,0 +1,89 @@
+#!/bin/ksh
+#
+# Starts ODBI server(s) on one or more hosts
+#
+# Usage: odbi_start_server [-i] [-n backlog] [-p port] [-t timeout] [-v] [-b binpath] [-h hostname] [-T server_self_timeout] [hostname(s)]
+#
+# Keep args consistent with the source code odb/tools/odbi_server_main.c
+#
+# except that:
+#
+# -h hostname can be supplied multiple times
+# the arguments after optional args are interpreted as hostnames 
+#
+# Author: Sami Saarinen, ECMWF, 14-Oct-2004
+#         Sami Saarinen, ECMWF, 10-Dec-2007 : Totally revised
+#
+
+set -eu
+
+if [[ -x $ODB_BINPATH/odbi_server.x && -x $ODB_BINPATH/odbi_client.x ]] ; then
+  ulimit -c 0  # no core dumps
+  [[ ! -f core ]] || chmod u+w core
+  rm -f core
+  cat /dev/null > core
+  chmod 000 core
+
+  export ODBCS_TIMEOUT=${ODBCS_TIMEOUT:=3600}
+
+  FLAGS=h:in:p:t:vb:T:
+
+  host=""
+  ignore_child=""
+  backlog=""
+  port=$(id -u | awk '{print $1%10000 + 10000}') # default port mod(uid,10000)+10000
+  timeout=${ODBCS_TIMEOUT}
+  self_timeout=""
+  verbose=""
+  binpath=""
+
+  while getopts ${FLAGS} i
+  do
+    case $i in
+    h) host="$host$OPTARG ";;
+    i) ignore_child="-i";;
+    n) backlog="-n $OPTARG";;
+    p) port="$OPTARG";;
+    t) timeout="$OPTARG";;
+    T) self_timeout="-T $OPTARG";;
+    v) verbose="-v";;
+    b) binpath="-b $OPTARG";;
+    esac
+  done
+
+  shift $(expr $OPTIND - 1)
+
+  if [[ $# -gt 0 ]] ; then
+    host="$host$*"
+  fi
+
+  if [[ "$host" = "" ]] ; then
+    host="localhost"
+  fi
+
+  # Avoid possible gdb/dbx hangs ... ;-(
+  export GNUDEBUGGER=0
+  export DBXDEBUGGER=0
+
+  export DR_HOOK=0
+  export EC_SORTING_INFO=0
+
+  for h in $host
+  do
+    logfile=$(pwd)/log.$h.$(date +%Y%d%m_%H%M%S)
+    echo "*** Obtain ODB-server stats with ' xterm -e tail -f $logfile & '" >&2
+
+    if [[ "$h" = "localhost" ]] ; then
+      h_arg=""
+    else
+      h_arg="-h $h"
+    fi
+
+    exec $ODB_BINPATH/odbi_server.x \
+       $h_arg -p $port -t $timeout $binpath \
+       $verbose $ignore_child $backlog $self_timeout >$logfile 2>&1 &
+  done
+else
+  echo "***Error: Unable to execute ODBI-server : client/server computing maybe disabled" >&2
+  exit 1
+fi
diff --git a/odb/src/scripts/odbi_stop_server b/odb/src/scripts/odbi_stop_server
new file mode 100755
index 0000000..146737b
--- /dev/null
+++ b/odb/src/scripts/odbi_stop_server
@@ -0,0 +1,104 @@
+#!/bin/ksh
+#begin
+#
+# Stop odbi_server.x's started by the username
+#
+# Usage: odbi_stop_server [-9] [-u username] [-x server_exe] [-p process_id] [-h hostname] [hostname(s)]
+#
+# Note:  -p process_id can be supplied multiple times AND applies to ALL hosts given
+#
+# Note:  -h hostname can be supplied multiple times to kill servers on many hosts e.g.:
+#
+#        -h hpce -h bee04 -h ecgate
+#
+#        or as last args :
+#
+#        hpce bee04 ecgate
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 02-May-2007
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+export USER=${USER:=$(id -un)}
+user=$USER
+exe=odbi_server.x
+pids=""
+nine=""
+host=""
+
+FLAGS=p:x:u:9h:
+
+abort=no
+
+while getopts ${FLAGS} i
+do
+  case $i in
+	p)	pids="$pids$OPTARG ";;
+	x)	exe="$OPTARG";;
+	u)	user="$OPTARG";;
+	9)	nine="-9";;
+	h)	host="$host$OPTARG ";;
+	*) 	abort=yes; break;;
+	\?)     abort=yes; break;;
+  esac
+done
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 0 ]] ; then
+  host="$host$*"
+fi
+
+#-- Abort, if necessary
+
+if [[ $abort = yes ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+if [[ "$host" = "" ]] ; then
+  host="localhost"
+fi
+
+for h in $host
+do
+  if [[ "$h" = "localhost" ]] ; then
+    prefix=""
+  else
+    prefix="/usr/bin/rsh $h"
+  fi
+
+  if [[ "$pids" = "" ]] ; then
+    all=1
+  else
+    all=0
+  fi
+
+  pid_list=$($prefix ps -fu $user | fgrep "$exe" | fgrep -v grep | awk '{print $2}')
+
+  if [[ "$pid_list" != "" ]] ; then
+    if [[ $all -eq 1 ]] ; then
+      kill_list=$pid_list
+    else
+      kill_list=""
+      for p in $pids
+      do
+        for tp in $pid_list
+        do
+          [[ $tp -ne $p ]] || kill_list="$kill_list$p "
+        done
+      done
+    fi
+
+    if [[ "$kill_list" != "" ]] ; then
+      $prefix kill $nine $kill_list 2>/dev/null || :
+    fi
+  fi
+done
+
+exit 0
diff --git a/odb/src/scripts/odbless b/odb/src/scripts/odbless
new file mode 100755
index 0000000..e0f7162
--- /dev/null
+++ b/odb/src/scripts/odbless
@@ -0,0 +1,321 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15 
+#begin
+#
+#   Usage: odbless -l dbname                        : by default automatically detected
+#                  -v viewname_or_sqlfile           : default=myview ; could be a table name, say: @hdr
+#                  -q 'select statement'            : supply ODB/SQL query directly (by default implies -v myview)
+#                  -s starting_row                  : default=1 (counting starts from the first active pool)
+#                  -n max_number_of_rows_to_display : default=100 ; if -1 --> unlimited)
+#                  -a                               : display all rows (same as -n -1)
+#                  -b row_buffer_size               : default=1000 ; if -1 --> no. of rows in each pool)
+#                  -E                               : Use the same -s & -n & -b option for Every pool separately
+#                  -x your_less_command             : default="less -nISX"
+#                  -p poolmask(s)                   : default=-1 i.e. all pools included; f.ex.: -p 1 -p1-4 -p1,3,6
+#                  -k                               : konvert (lat,lon) to degrees
+#                  -c                               : force re-creation of lib<dbname>.a
+#                  -d "options"                     : run also dcagen with these options
+#                  -5                               : do NOT use fast I/O-method=5, even if desirable
+#                  -S                               : display ONLY summary data
+#                  -I                               : Ignore summary data
+#                  -f output_file                   : Save displayed data on file output_file, too
+#                  -X                               : View output also by opening an X-window
+#                  -T                               : set ODB tracing on
+#                  -g                               : Enable debugging output go to stderr.out
+#                  -D debugger                      : Run tool under debugger (default=none)
+#                  -0                               : (zero) ignore stderr (by default written to stderr.out)
+#                  -i                               : Show also database index (as a last column) i.e. export ODB_SHOWDBIDX=1
+#                  -e                               : Show output in editable file (implies -X) [odbedit not implemented yet]
+#                  -H dr_hook_opt                   : Enable Dr.Hook profiler and export DR_HOOK_OPT with dr_hook_opt
+#                  -h                               : Print help/usage and abort
+#
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 26-Jan-2006 .. 03-Feb-2006
+#
+
+set -eu
+
+export SHELL=/bin/ksh
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+basecmd=$(basename $cmd)
+baseless=$(echo "$basecmd" | perl -pe 's/odb[_]?//')
+
+thisdir=$(pwd)
+cd $thisdir
+
+dbname=""
+dbdir=$thisdir
+viewname=myview
+start=1
+limit=100
+rowbuf=1000
+if [[ "$baseless" = "less" ]] ; then
+  less="less -nISX"
+elif [[ "$baseless" = "more" ]] ; then
+  less=more
+elif [[ "$baseless" = "cat" ]] ; then
+  less=cat
+else
+  less=cat
+fi
+poolmask=""
+stderr=stderr.out
+query=""
+query_given=0
+dcagen_opt=""
+io_method=5
+recompile=0
+konvert=0
+summary=1
+output=/dev/null
+trace=0
+xwin=0
+debug=0
+debugger=""
+export ODB_SHOWDBIDX=${ODB_SHOWDBIDX:=0}
+odbedit=0 # not implemented yet
+drhookopt=""
+every=0
+
+FLAGS=ab:cd:eED:f:ghH:iIkl:n:p:q:s:STv:x:X05
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  a) limit="-1";;
+  b) rowbuf="$OPTARG";;
+  c) recompile=1;;
+  d) dcagen_opt="$OPTARG";;
+  D) debugger="$OPTARG";;
+  e) odbedit=1; xwin=1;;
+  E) every=1;;
+  f) output="$OPTARG";;
+  g) debug=1;;
+  h) abort=yes; break;;
+  H) drhookopt="$OPTARG";;
+  i) ODB_SHOWDBIDX=1;;
+  I) summary=0;;
+  k) konvert=1;;
+  l) dbname="$OPTARG";;
+  n) limit="$OPTARG";; 
+  p) poolmask="$poolmask $OPTARG";;
+  q) query_given=1; query="$OPTARG";;
+  s) start="$OPTARG";;
+  S) summary=2;;
+  T) trace=1;;
+  v) viewname="$OPTARG";;
+  x) less="$OPTARG";;
+  X) xwin=1;;
+  0) stderr="/dev/null";;
+  5) io_method=-1;; # Setting this to a <=0 value will ensure I/O-method 5 will NOT be used
+                    # If > 0, there is an automatic test for READ/ONLY databases, whether ./dca
+                    # directory exists. But keeping I/O-method <= 0 bypasses this testing
+  *) abort=yes; break;;
+  esac
+done
+
+export ODB_READONLY=${ODB_READONLY:=1}
+
+if [[ "$abort" = "no" && "$dbname" = "" ]] ; then
+  dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    dbname=""
+    abort=yes
+  fi
+fi
+
+if [[ "$abort" = "no" && "$debugger" != "" ]] ; then
+  typeset test=$(whence "$debugger" 2>/dev/null || echo "")
+  if [[ "$test" = "" ]] ; then
+    echo "***Error: Unable to locate debugger '$debugger'"
+    abort=yes
+  else
+    debugger=$test
+  fi
+fi
+
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' | sed "s/odbless /$basecmd /"
+  exit 1
+fi
+
+if [[ -d "$dbname" ]] ; then
+  dbdir=$(\cd $dbname 2>/dev/null ; pwd)
+  dbname=$(basename "$dbname" | perl -pe 's/\..*//; tr/a-z/A-Z/')
+fi
+
+is_table=$(echo "$viewname" | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+so=$(basename "$viewname" | perl -pe 's/^.*\.so$/so/')
+
+if [[ "$so" = so ]] ; then
+  is_so=1
+else
+  is_so=0
+fi
+
+if [[ $is_table -eq 1 ]] ; then
+  sqlfile=/dev/null
+else
+  if [[ $is_so -eq 1 ]] ; then
+    viewname=$(basename "$viewname" .so)
+    sqlfile=$viewname.sql
+  elif [[ -f $viewname ]] ; then
+    sqlfile=$viewname
+  else
+    sqlfile=$viewname.sql
+  fi
+fi
+
+cd $dbdir
+
+if [[ $is_table -eq 0 && $query_given -eq 1 ]] ; then
+  echo "$query" > $sqlfile
+fi
+
+if [[ ! -f lib$dbname.a ]] || \
+   [[ ! -f $dbname.ddl_ ]] || \
+   [[ ! -f ${dbname}.h  ]] || \
+   [[ $ODB_FEBINPATH/odb98.x -nt $dbname.ddl_ ]] || \
+   [[ $dbname.ddl -nt $dbname.ddl_ ]] ; then
+  recompile=1
+fi
+
+if [[ $recompile -eq 1 ]] ; then
+  odbcomp $dbname.sch
+fi
+
+if [[ "$dcagen_opt" != "" ]] ; then
+  dcagen -F $dcagen_opt
+fi
+
+if [[  $is_table -eq 0 && $is_so -eq 0 && \
+       "$sqlfile" != "/dev/null" && -f $sqlfile ]] ; then
+  odbcomp -l$dbname -w $sqlfile
+fi
+
+if [[ $is_table -eq 1 ]] ; then
+  export ODB_CONSIDER_TABLES=$(echo $viewname | perl -pe 's#\@(\w+)#/\L$1/#')
+elif [[ -f ${dbname}_$viewname.c ]] ; then
+  # the following hassle defines you the ODB_CONSIDER_TABLES
+  eval `fgrep '#define ODB_CONSIDER_TABLES' ${dbname}_$viewname.c | awk '{print "export",$2"="$3}'`
+else
+  export ODB_CONSIDER_TABLES='*'
+fi
+ODB_CONSIDER_TABLES=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 'tr/A-Z/a-z/')
+echo "==> ODB_CONSIDER_TABLES=$ODB_CONSIDER_TABLES"
+
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK="$poolmask"
+  echo "==> ODB_PERMANENT_POOLMASK=$ODB_PERMANENT_POOLMASK"
+fi
+
+exe=./odbless.x
+if [[ $recompile -eq 1 ]] || \
+   [[ $is_so -eq 0 ]] || \
+   [[ ! -f $exe ]] || \
+   [[ lib$dbname.a -nt $exe ]] || \
+   [[ $ODB_LIBPATH/libodbmain.a -nt $exe ]] ; then
+  obj=$($ODB_AR t $ODB_LIBPATH/libodbmain.a | grep Odbless)
+  $ODB_AR x $ODB_LIBPATH/libodbmain.a $obj
+  odbf90 $obj -l$dbname -o $exe
+  rm -f $obj
+fi
+
+export ODB_LAT=${ODB_LAT:="lat at hdr"}
+export ODB_LON=${ODB_LON:="lon at hdr"}
+export ODB_LATLON_RAD=$($ODB_FEBINPATH/latlon_rad 2>/dev/null || echo "-1")
+
+#-- I/O-method
+ddfile=$dbdir/$dbname.dd
+if [[ -s $ddfile ]] ; then
+  iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+else
+  iom=1
+fi
+
+#-- remove possible file (not dir) $dbdir/dca, and if not successful then possible *empty* $dbdir/dca dir
+\rm $dbdir/dca 2>/dev/null || rmdir $dbdir/dca 2>/dev/null || :
+
+export ODB_IO_METHOD=${ODB_IO_METHOD:=$io_method}
+if [[ $io_method -eq 5 && ! -d $dbdir/dca ]] ; then
+#  ODB_IO_METHOD=$iom
+  ODB_IO_METHOD=0 # for now
+fi
+
+export ODB_REPORTER=stdout
+if [[ $summary -ge 1 ]] ; then
+  export DR_HOOK=true
+  export DR_HOOK_IGNORE_SIGNALS=8 # Can't afford SIGFPE's caused by the summary print-out
+fi
+
+if [[ "$debugger" = "" ]] ; then
+  cmd="$exe $dbname $viewname $start $limit $rowbuf $konvert $summary $debug $every 2>$stderr"
+  cmd="$cmd | awk '{ if (NR <= 3 || NR > 6) print; }'"
+
+  if [[ $summary -eq 2 ]] ; then
+    cmd="$cmd | awk '/^:/' | uniq"
+  fi
+
+  export DISPLAY=${DISPLAY:-no}
+  if [[ "$DISPLAY" = no ]] ; then
+    xwin=0 # X-windows output turned off, since DISPLAY was not set
+  fi
+
+  if [[ $xwin -eq 1 && "$output" = "/dev/null" ]] ; then
+    output="$viewname.rpt"
+  fi
+
+  if [[ $summary -eq 2 && "$output" = "/dev/null" ]] ; then
+    output="$viewname.rpt"
+  fi
+
+  if [[ "$output" != "/dev/null" ]] ; then
+    cmd="$cmd | tee $output"
+    rm -f $output
+  fi
+
+  if [[ "$(basename $less)" != less ]] ; then
+    eval `resize`
+    cmd="$cmd | cut -c1-$COLUMNS"  # Note: Only this many columns will be output; file (if any) contains all
+  fi
+
+  cmd="$cmd | $less"
+
+  if [[ $trace -eq 1 ]] ; then # turn ODB-tracing on
+    export ODB_TRACE_PROC=-1
+    export ODB_TRACE_FILE=trace.%d
+    export ODB_TRACE_FLUSH_FREQ=1
+  fi
+
+  if [[ "$drhookopt" != "" ]] ; then
+    export DR_HOOK=true
+    export DR_HOOK_OPT="$drhookopt"
+  fi
+
+  eval $cmd
+
+  if [[ $xwin -eq 1 && -s "$output" ]] ; then
+    $ODB_REPORTER $output &
+  fi
+
+else # Run under $debugger
+
+  cmdargs="$dbname $viewname $start $limit $rowbuf $konvert $summary $debug"
+
+  echo "Using debugger '$debugger'"
+  echo "Use the following arguments: $cmdargs"
+  
+  $debugger $exe
+
+fi
+
+exit 0
+
+
+
+
diff --git a/odb/src/scripts/odblink b/odb/src/scripts/odblink
new file mode 100755
index 0000000..a03a15e
--- /dev/null
+++ b/odb/src/scripts/odblink
@@ -0,0 +1,74 @@
+#!/bin/csh -f
+#
+# A script to re-generate shareable object for a given layout.
+#
+# Assumes that ODB_LIBPATH is already defined.
+#
+# Objects are created into the current directory.
+#
+# Usage: odblink DATABASE_NAME
+#
+# Author: Sami Saarinen, ECMWF, 1998-99
+#
+
+if ( $#argv != 1 ) then
+  echo "Usage: odblink DATABASE_NAME"
+  exit 1
+endif
+
+set dbname=$1
+
+set rc=0
+if ( $?ODB_LIBPATH == 0) then
+  echo "*** Error: ODB_LIBPATH must be defined"
+  @ rc++
+endif
+
+if ( ! -f $ODB_LIBPATH/lib${dbname}.a ) then
+  echo "*** Error: No such library file '$ODB_LIBPATH/lib${dbname}.a'"
+  @ rc++
+endif
+
+if ( $rc > 0 ) exit $rc
+
+set this=`pwd`
+
+if ( $?SCRATCHDIR != 0 ) then
+  set tmpdir=$SCRATCHDIR
+else if ( $?SCRATCH != 0 ) then
+  set tmpdir=$SCRATCH
+else if ( $?TMPDIR != 0 ) then
+  set tmpdir=$TMPDIR
+else
+  set tmpdir=/tmp
+endif
+
+set tmpdir=$tmpdir/tmp.$$
+mkdir -p $tmpdir || exit 3
+cd $tmpdir
+
+echo Extracting TABLE-specific object files from \$ODB_LIBPATH/lib${dbname}.a ...
+ar  x $ODB_LIBPATH/lib${dbname}.a
+#rm -f ${dbname}_*.o
+cp $this/${dbname}.o     || :
+cp $this/${dbname}_T_*.o || :
+set sofile=$this/${dbname}.so
+
+rm -f $sofile
+
+set rc=0
+echo ${ODB_LD} ${dbname}.o ${dbname}_T_*.o ${ODB_LIBS} -o $sofile
+     ${ODB_LD} ${dbname}.o ${dbname}_T_*.o ${ODB_LIBS} -o $sofile || set rc=$status
+
+cd $this
+rm -rf $tmpdir
+
+if ( $rc != 0 ) then
+  rm -f $sofile
+  echo "*** Error: Shareable object '$sofile' creation failed"
+else
+  set sofile=`basename $sofile`
+  ls -l $sofile    
+endif
+
+exit $rc
diff --git a/odb/src/scripts/odbls b/odb/src/scripts/odbls
new file mode 100755
index 0000000..428b252
--- /dev/null
+++ b/odb/src/scripts/odbls
@@ -0,0 +1,322 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#begin
+#
+#   odbls [other_options] [-l] database_directory
+#
+#      If -l is included, then a wide listing will be produced
+#      If -l is omitted, then just the list of ODB-tables will be output
+#
+#   In the alternative form the -l *must* be given and be followed by the database directory
+#
+#   odbls [other_options] -l database_directory other_options
+#
+# other_options:
+#   -a            : Print a complete summary listing
+#   -p poolnos    : default=-1 i.e. all pools included; f.ex.: -p 1 -p1-4 -p1,3,6
+#   -s            : Sort w.r.t. number of rows, smallest first
+#   -r            : Sort w.r.t. number of rows, biggest first
+#   -T            : Do *not* display the title columns
+#   -w where_cond : Supply a simple, table specific WHERE-condition for filtering
+#   -z            : Do *not* show zero length tables (tables w/o any rows)
+#   -t            : Do *not* print the total size information at the end. Also,
+#                   omit the "Total <count>"-record, when -l has *not* been used
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 01-Jun-2007
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+abort=no
+
+function do_abort {
+  typeset kmd=$1
+  typeset rest=$2
+  awk '/#begin/,/#end/' $kmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  echo "*** Error in command : $(basename $kmd) $rest" >&2
+  exit 1
+}
+
+nargs=$#
+args=${*:-}
+
+mysort=$ODB_FEBINPATH/mysort
+
+all=0
+poolmask=""
+sort=0
+title=1
+where="1"
+widelst=0
+dbdir="."
+zero=1
+total=1
+
+if [[ $nargs -gt 0 ]] ; then
+  last=""
+  for a in $args
+  do
+    last=$a
+  done
+  if [[ "$last" != "" ]] ; then
+    first=$(echo "X$last" | cut -c2-2)
+    if [[ "$first" = "-" ]] ; then
+      has_el=$(echo "X$last" | egrep 'l$' >/dev/null 2>&1 && echo "1" || echo "0")
+      if [[ $has_el -eq 1 ]] ; then
+        exec $0 $args .
+        exit 1
+      fi
+    fi
+  fi
+fi
+
+if [[ $nargs -eq 0 ]] ; then
+  title=0
+elif [[ $nargs -eq 1 && "$args" = "-l" ]] ; then
+  widelst=1
+else
+  FLAGS=ap:srTw:l:zt
+  while getopts $FLAGS option
+  do
+    case $option in
+    a) all=1;;
+    p) poolmask="$poolmask $OPTARG";;
+    s) sort=1;;
+    r) sort=-1;;
+    T) title=0;;
+    w) where="$OPTARG";;
+    l) widelst=1; dbdir="$OPTARG";;
+    z) zero=0;;
+    t) total=0;;
+    *) echo "***Error: Unrecognized option : $option" >&2; abort=yes; break;;
+    esac
+  done
+  shift $(expr $OPTIND - 1) || :
+  if [[ $# -eq 0 ]] ; then
+    :
+  elif [[ $# -eq 1 && $widelst -eq 0 ]] ; then
+    dbdir=$1
+    title=0
+  else
+    echo "***Error: Unrecognized arguments : $*" >&2
+    abort=yes
+  fi
+fi
+
+#-- Some sanity checks ...
+
+if [[ $abort = no ]] ; then
+  if [[ ! -d "$dbdir" ]] ; then
+    echo "***Error: Database directory '$dbdir' not found" >&2
+    abort=yes
+  else
+    dbdir=$(\cd $dbdir>/dev/null 2>&1; pwd)
+  fi
+
+  dbname=$(\cd $dbdir>/dev/null 2>&1; \ls -C1 *.dd 2>/dev/null | head -1)
+  dbname=$(basename "$dbname" .dd)
+
+  if [[ "$dbname" = "" ]] ; then
+    echo "***Error: Database name could not be determined. No .dd-file under $dbdir ?" >&2
+    abort=yes
+  fi
+fi
+
+if [[ $abort = no ]] ; then
+  ddfile=$dbdir/$dbname.dd
+  if [[ ! -f "$ddfile" ]] ; then
+    echo "***Error: Database main metadata-file '$ddfile' not found" >&2
+    abort=yes
+  fi
+fi
+
+#-- Abort ?
+
+if [[ $abort = yes ]] ; then
+  do_abort $cmd "$args"
+fi
+
+#-- Get going ...
+
+tty=$(tty -s 2>/dev/null && echo "0" || echo "$?")
+
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+else
+  poolmask="-1"
+fi
+
+#-- AIX doesn't seem to support 'xargs -r', but its 'xargs' by default implies -r ...
+xargs_r=$(echo "" | xargs 2>/dev/null && echo "xargs -r" || echo "xargs")
+
+tables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+npools=$(head -5 $ddfile| tail -1)
+ntables=$(head -6 $ddfile| tail -1)
+
+#--- Output ---
+
+if [[ $all -eq 1 ]] ; then
+  iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+  cycle=$(head -1 $ddfile | awk '{printf("%s",$1);}')
+  release=$(head -1 $ddfile | awk '{printf("%s",$2);}')
+  creation_tstamp=$(head -2 $ddfile | tail -1)
+  last_updated_tstamp=$(head -3 $ddfile | tail -1)
+  analysis_tstamp=$(head -4 $ddfile | tail -1)
+  echo "ODB database           = $dbname"
+  host=$(hostname)
+  echo "Datatase host          = $host"
+  echo "Database directory     = $dbdir"
+  echo "Number of tables       = $ntables"
+  echo "Number of data pools   = $npools"
+  echo "Data pools used        = $poolmask"
+  ntsl=0
+  for t in $tables
+  do
+    if [[ $t = "timeslot_index" ]] || [[ $t = "index" ]] ; then
+      poolno=$(\ls -C1 [0-9]*/$t 2>/dev/null | awk -F/ '{print $(NF-1)}' | sort -n | head -1)
+      if [[ "$poolno" != "" ]] ; then
+        if [[ $t = "timeslot_index" ]] ; then
+          entry="timeslot"
+        else
+          entry="tslot"
+        fi
+        ntsl=$(odbsql -BT -i $dbdir -q "select count(distinct $entry) from $t" -p$poolno 2>/dev/null || echo "-1")
+        break
+      fi
+    fi
+  done
+  echo "Number of time-slots   = $ntsl"
+  echo "Database I/O-method    = $iom"
+  echo "Created with revision  = CY${cycle}R${release}"
+  echo "Creation timestamp     = $creation_tstamp"
+  echo "Last updated timestamp = $last_updated_tstamp"
+  echo "Analysis timestamp     = $analysis_tstamp"
+  echo "Current timestamp      = $(date '+%Y%m%d %H%M%S')"
+  if [[ "$where" != "1" ]] ; then
+    echo "WHERE-statement = $where"
+  fi
+fi
+
+if [[ "X$poolmask" = "X-1" && "X$where" = "X1" ]] ; then
+  simple=2
+  reftbl=""
+elif [[ "X$poolmask" != "X-1"  && "X$where" = "X1" ]] ; then
+  simple=1
+  reftbl=""
+else
+  simple=0
+  reftbl=$(echo "$where" | perl -pe 's/^.*?[@#](\w+)\b.*/$1/')
+  tables="$reftbl"
+  sort=0
+  ntables=1
+  total=0
+fi
+
+if [[ $title -eq 1 && $widelst -eq 1 ]] ; then
+  if [[ "$where" = "1" ]] ; then
+    echo "Id# Table_Name Data_Size(Bytes) #_of_Cols #_of_Rows" |\
+      awk '{printf("%3s %20s %20s %12s  %s\n",$1,$2,$3,$4,$5);}'
+    echo "--- ---------- ---------------- --------- ---------" |\
+      awk '{printf("%3s %20s %20s %12s  %s\n",$1,$2,$3,$4,$5);}'
+  else
+    echo "Id# Table_Name Data_Size(Bytes) #_of_Cols #_of_Rows ,WHERE" |\
+      awk '{printf("%3s %20s %20s %12s  %s %s",$1,$2,$3,$4,$5,$6);}'
+    echo " ${where}"
+    len=$(echo "${where}" | perl -ne 'print length($_)')
+    echo "--- ---------- ---------------- --------- --------- ------ $len" |\
+      awk '{printf("%3s %20s %20s %12s  %s-%s",$1,$2,$3,$4,$5,$6); for(i=1;i<=$7;i++) printf("-");}'
+    echo ""
+  fi
+elif [[ $total -eq 1 ]] ; then
+  echo "Total $ntables"
+fi
+
+if [[ $widelst -eq 0 ]] ; then
+  for t in $tables
+  do
+    echo "$t"
+  done
+elif [[ $ntables -gt 0 ]] ; then
+  export TMPDIR=${TMPDIR:=/tmp}
+  tmpfile=$TMPDIR/odbls.$$
+  if [[ $sort -ne 0 ]] ; then
+    cat /dev/null > $tmpfile
+    [[ $tty -ne 0 ]] || echo "Gathering information for sorting ..." | perl -pe 's/\n/\r/' >&2
+  fi
+  id=0
+  tot=0
+  totbytes=0
+  totcols=0
+  totrows=0
+  for t in $tables
+  do
+    ((id+=1))
+    ncols=$(egrep "^@$t " $ddfile | cut -f2 -d' ')
+    bytes=$(find $dbdir -type f -name "$t" -follow | $xargs_r ls -l | awk '{s += $5} END { printf("%d\n",s) }')
+    if [[ $simple -eq 2 ]] ; then
+      if [[ $bytes -gt 0 ]] ; then
+        #-- Much faster way (!!) than 'odbsql' currently : fgrep the DCA-file $table.dca directly
+        entry=$(find $dbdir -type f -name "$t.dca" -follow | $xargs_r head -2 | tail -1 | awk '{print $2}')
+        nrows=$(find $dbdir -type f -name "$t.dca" -follow | $xargs_r egrep " $entry " |\
+                awk '{s += $11} END { printf("%d\n",s) }')
+        if [[ $nrows -le 0 ]] ; then
+          #-- Slow (despite well optimized!) way to get the nrows
+          nrows=$(odbsql -BT -i $dbdir -q "select count(*) from $t" 2>/dev/null || echo "-1")
+          [[ "$nrows" != "" ]] || nrows=0
+        fi
+      else
+        nrows=0
+      fi
+    elif [[ $simple -eq 1 ]] ; then
+      nrows=$(odbsql -BT -i $dbdir -q "select count(*) from $t" -p$poolmask 2>/dev/null || echo "-1")
+      [[ "$nrows" != "" ]] || nrows=0
+    elif [[ "$reftbl" = "$t" ]] ; then
+      query="select count(*) from $t where $where"
+      run_query="Running query '$query' ..."
+      [[ $tty -ne 0 ]] || echo "$run_query" | perl -pe 's/\n/\r/' >&2
+      nrows=$(odbsql -BT -i $dbdir -q "$query" -p$poolmask 2>/dev/null || echo "-1")
+      [[ "$nrows" != "" ]] || nrows=0
+      if [[ $tty -eq 0 ]] ; then
+        len=$(echo "${run_query}" | perl -ne 'print length($_)')
+        echo "$len" | awk '{for(i=1;i<=$1;i++) printf(" "); printf("\n")}' | perl -pe 's/\n/\r/' >&2
+      fi
+    else
+      nrows=0
+    fi
+    if [[ $nrows -gt 0 ]] || [[ $zero -eq 1 && $nrows -le 0 ]] ; then
+      ((tot+=1))
+      if [[ $sort -ne 0 ]] ; then
+        echo "$id $t $bytes $ncols $nrows" | awk '{printf("%3d %20s %20d %12d  %s\n",$1,$2,$3,$4,$5);}' >> $tmpfile
+      else
+        echo "$id $t $bytes $ncols $nrows" | awk '{printf("%3d %20s %20d %12d  %s\n",$1,$2,$3,$4,$5);}'
+      fi
+      if [[ $total -eq 1 && $bytes -gt 0 && $nrows -ge 0 ]] ; then
+        ((totbytes+=$bytes))
+        ((totcols+=$ncols))
+        ((totrows+=$nrows))
+      fi
+    fi
+  done
+  if [[ $sort -ne 0 ]] ; then
+    num=4
+    if [[ $sort -gt 0 ]] ; then
+      $mysort -n  +${num} $tmpfile
+    else
+      $mysort -nr +${num} $tmpfile
+    fi   
+    \rm -f $tmpfile
+  fi
+  if [[ $total -eq 1 ]] ; then
+    echo "--- ---------- ---------------- --------- ---------" | awk '{printf("%3s %20s %20s %12s  %s\n",$1,$2,$3,$4,$5);}'
+    echo "$tot ********** $totbytes $totcols $totrows" | awk '{printf("%3d %20s %20d %12d  %s\n",$1,$2,$3,$4,$5);}'
+  fi
+fi
+
+exit 0
+
+
+
diff --git a/odb/src/scripts/odbmerge b/odb/src/scripts/odbmerge
new file mode 120000
index 0000000..ecfbb28
--- /dev/null
+++ b/odb/src/scripts/odbmerge
@@ -0,0 +1 @@
+odbdup
\ No newline at end of file
diff --git a/odb/src/scripts/odbmore b/odb/src/scripts/odbmore
new file mode 120000
index 0000000..618b4c5
--- /dev/null
+++ b/odb/src/scripts/odbmore
@@ -0,0 +1 @@
+odbless
\ No newline at end of file
diff --git a/odb/src/scripts/odbprune b/odb/src/scripts/odbprune
new file mode 100755
index 0000000..4348702
--- /dev/null
+++ b/odb/src/scripts/odbprune
@@ -0,0 +1,181 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#begin
+#
+# Usage: odbprune [-i database_directory] [-r] [-u] [-n] [-C] [-E]
+#        -i dbdir  : the default is "." and will look for ECMA.dd
+#        -r        : do not remove, but just rename the datafiles
+#        -u        : create dca-indices with -u(npack) option
+#        -n        : create dca-indices with -n(o-unpack) option
+#        -C        : Cold-run: do not remove/rename anything, just show what would have happened
+#        -E        : similar to Coldrun, but rather than doing something Echoes expected_files, if any
+#        -q        : Quiet option i.e. do not print any messages, except for fatal errors. 
+#                    -q is ignored if used with -C or -E
+#
+# By default the dca-indices are NOT created (i.e. dcagen is not run).
+#
+# The purpose is to remove such ODB data files (under [0-9]*/ dirs) that according to 
+# the metadata-file <dbname>.iomap are actually not part of the database, but are
+# left there due to much improved parallel I/O-scheme introduced in cycle 31R2+.
+#
+# ***Note: Only applicable to databases with I/O-method#4.
+#
+# The script assumes that you have write-access to the database and that
+# all datafiles reside on a shared disk.
+#
+# It will also remove all empty directories after the rename/remove.
+#
+#end
+#  
+# Author: Sami Saarinen, ECMWF, 13-Feb-2007
+#
+#
+
+set -eu
+
+thisdir=$(pwd)
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+
+abort=no
+dcagen=""
+dbpath=$thisdir
+remove=1
+coldrun=0
+silence=0
+
+FLAGS=i:runCEq
+while getopts ${FLAGS} i
+do
+  case $i in
+  i) dbpath="$OPTARG";;
+  r) remove=0;;
+  u) dcagen="-u";;
+  n) dcagen="-n";;
+  C) coldrun=1;;
+  E) coldrun=2;;
+  q) silence=1;;
+  *) abort=yes; break;;
+  esac
+done
+
+if [[ $coldrun -gt 0 ]] ; then
+  silence=0
+fi
+
+dbname=""
+
+if [[ -d "$dbpath" ]] ; then
+  \cd $dbpath
+  dbpath=$(pwd)
+  dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+  if [[ "$dbname" = ".dd" ]] ; then
+    echo "***Error: Unable to locate the main metadata file (.dd) from directory '$dbpath'" >&2
+    dbname=""
+    abort=yes
+  else
+    ddfile=$dbname.dd
+  fi
+else
+  echo "***Error: No such database directory/schema file '$dbpath'" >&2
+  dbname=""
+  abort=yes
+fi
+
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+if [[ $iom -ne 4 ]] ; then
+#  echo "***Warning: Database '$dbname' I/O-method is not #4. Exiting gracefully ..." >&2
+  cat /dev/null > .odbprune_done 2>/dev/null || :
+  exit 0
+fi
+
+iomap=$dbname.iomap
+if [[ ! -f $iomap ]] ; then
+  echo "***Error: Database '$dbname' I/O-method is 4, but its metadata-file '$iomap' is not found" >&2
+  exit 2
+fi
+
+iomtype=$(head -1 $iomap | perl -pe 's/^\s+//')
+if [[ "$iomtype" != "1" ]] ; then
+#  echo "***Warning: Database '$dbname' I/O-map file's type is not equal to 1. Exiting gracefully ..." >&2
+  cat /dev/null > .odbprune_done 2>/dev/null || :
+  exit 0
+fi
+
+#tables=$(egrep ^@ $ddfile | perl -ne 'print "$1\n" if (m/^\@(\S+)\s+\d+/)' | perl -pe 's/\n/ /g;')
+
+expfil=expected_files.$$
+curfil=current_files.$$
+
+awk '{if (NR > 4 && NF == 3) print $3; else if (NF == 5 && $1 > 0) print $2;}' < $iomap |\
+    uniq | egrep -v ^EOF | awk -F\@ '{if (NF == 2) x=$2; else printf("%s %d\n",x,$1);}' |\
+    sort > $expfil &
+
+\ls -C1 [0-9]*/[a-z0-9_]* | egrep -v '([.]|[A-Z])' | awk -F/ '{print $2,$1}' |\
+    sort > $curfil &
+
+wait
+
+files_to_be_removed=$(diff $curfil $expfil | egrep '^< ' | awk '{printf("%d/%s ",$3,$2);}')
+
+if [[ $silence -eq 0 ]] ; then
+  [[ $coldrun -eq 2 ]] || pwd >&2
+fi
+if [[ "$files_to_be_removed" != "" ]] ; then
+  if [[ $remove = 1 ]] ; then
+    if [[ $coldrun -eq 0 ]] ; then
+      set -x
+      \rm -f $files_to_be_removed
+      set +x
+    elif [[ $coldrun -eq 1 ]] ; then
+      echo "rm -f $files_to_be_removed" >&2
+    fi
+  else
+    for f in $files_to_be_removed
+    do
+      if [[ $coldrun -eq 0 ]] ; then
+        set -x
+        \mv $f $f.REMOVED
+        set +x
+      elif [[ $coldrun -eq 1 ]] ; then
+        echo "mv $f $f.REMOVED" >&2
+      fi
+    done
+  fi
+elif [[ $coldrun -ne 2 ]] ; then
+  if [[ $silence -eq 0 ]] ; then
+    echo "*** No ODB data files need to be removed/renamed" >&2
+  fi
+fi
+
+if [[ $coldrun -eq 0 ]] ; then
+  \rmdir [0-9]* 2>/dev/null || :
+  cat $expfil > .odbprune_done || :
+elif [[ $coldrun -eq 1 ]] ; then
+  echo "rmdir [0-9]* 2>/dev/null || :"
+  echo "cat $expfil > .odbprune_done || :"
+elif [[ $coldrun -ne 2 ]] ; then
+  if [[ $silence -eq 0 ]] ; then
+    cat $expfil 2>/dev/null || :
+  fi
+fi
+
+\rm -f $curfil $expfil
+
+if [[ "$dcagen" != "" ]] ; then
+  if [[ $silence -eq 1 ]] ; then
+    dcagen="$dcagen -q"
+  fi
+  if [[ $coldrun -eq 0 ]] ; then
+    dcagen -P -F -z $dcagen
+  else
+    echo "dcagen -P -F -z $dcagen"
+  fi
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbqsub b/odb/src/scripts/odbqsub
new file mode 100755
index 0000000..3a4236d
--- /dev/null
+++ b/odb/src/scripts/odbqsub
@@ -0,0 +1,142 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#begin
+#
+# echo "command(s)-to-be-executed" | odbqsub [qsub-options]
+#  or
+# cat file | odbqsub [qsub-options]
+#
+# Please note that commands to be executed are always read from stdin i.e. also
+# a multiline here-document would be acceptable.
+#
+# NOTE: This utility is for ODB_ARCH=nectx only in order to submit jobs in batch queue for NEC SX (ODB_ARCH=necsx)
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 12-Feb-2007
+#
+#
+
+set -eu
+
+thisdir=$(pwd)
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+test_arch=$(test_arch 2>/dev/null || echo "unknown")
+
+if [[ "$test_arch" != "nectx" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+qsub_opts=${*:-}
+
+jobname=odb
+queue=vector
+
+FLAGS=N:q:
+while getopts ${FLAGS} i
+do
+  case $i in
+  N) jobname=$(echo "$OPTARG" | cut -c1-15);;
+  q) queue="$OPTARG";;
+  esac
+done
+
+successful_completion="Successful completion"
+
+jobfile=$jobname.job
+
+necsx_arch=$(echo "$ARCH" | sed 's/nectx/necsx/')
+necsx_odb_dir=$(echo "$ODB_ROOT" | perl -pe 's|(^.*ODBDIR)/.*|$1|')
+necsx_odb_version=$(odbversion)
+necsx_odb_root=$(echo "$ODB_ROOT" | sed 's/nectx/necsx/')
+
+cat > $jobfile <<EOF
+#PBS -N $jobname
+#PBS -q $queue
+#PBS -S /bin/ksh
+#PBS -l elapstim_req=00:10:00
+#PBS -l cpunum_job=1
+#PBS -l memsz_job=2gb
+#PBS -b 1
+#PBS -j o
+set -eu
+rc=0
+ulimit -c 0 2>/dev/null || :
+set -a
+ARCH=$necsx_arch
+ODB_DIR=$necsx_odb_dir
+ODB_VERSION=$necsx_odb_version
+ODB_ROOT=$necsx_odb_root
+set +a
+use_odb=\$ODB_ROOT/bin/use_odb.sh
+[[ -r \$use_odb ]] || {
+  echo "***Error: Unable to locate the ODB initialization file \$use_odb"    >&2
+  echo "          Check also the existence of ODB_ROOT directory \$ODB_ROOT" >&2
+  exit 1
+}
+. \$use_odb
+set -a
+$(printenv | egrep "^ODB_(READONLY|IO_METHOD|SRCPATH|DATAPATH|PERMANENT|LATLON|TRACE|PRINT|)" || :)
+$(printenv | egrep "^ODB_(VIEWER|EDITOR|PACKING|PLOTTER|REPORTER)" || :)
+$(printenv | egrep "^(IOASSIGN|EC_|DR_HOOK|RUN_FE|F_|C_)" || :)
+$(printenv | egrep "^(GDB|DBX)DEBUGGER" || :)
+set +a
+cd $thisdir
+$(cat)
+set +xv
+[[ \$rc -eq 0 ]] || exit \$rc
+wait
+echo "$successful_completion"
+EOF
+
+#-- Submit & monitor the job
+
+submit=$(qsub $qsub_opts $jobfile)
+echo "$submit" >&2
+date >&2
+
+reqid=$(echo "$submit" | awk '{print $2}' | perl -pe 's/^(\d+).*/$1/')
+qstat -r $reqid | head -2 >&2
+
+tty=$(tty -s 2>/dev/null && echo "0" || echo "$?")
+
+count=0
+rc=$reqid
+qstat=""
+last=""
+while [[ "$rc" = "$reqid" ]]
+do
+  ((count+=1))
+  [[ $count -eq 1 ]] || sleep 1
+  qstat=$(qstat -r $reqid | awk '{if (NR > 2) print;}')
+  if [[ "$last" != "$qstat" ]] || [[ $((count%10)) -eq 0 ]] ; then
+    if [[ $tty -eq 0 ]] ; then
+      echo "$qstat" | perl -pe 's/\n/\r/' >/dev/tty
+    else
+      echo "$qstat" >&2
+    fi
+    last="$qstat"
+  fi
+  rc=$(echo "$qstat" | perl -pe 's/^(\d+).*/$1/')
+done
+
+echo "$qstat" >&2
+date >&2
+
+joboutput=$jobname.o$reqid
+
+if [[ -f $joboutput ]] ; then
+  cat $joboutput
+  last_line=$(tail -1 $joboutput)
+  [[ "$last_line" = "$successful_completion" ]] || {
+    echo "***Error: The batch job ($reqid) did not complete successfully"
+    exit 2
+  }
+else
+  echo "***Error: Unable to find the output-file '$joboutput'"
+  echo "          Please check you jobfile '$jobname.job'"
+  exit 1
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbset b/odb/src/scripts/odbset
new file mode 120000
index 0000000..357ca12
--- /dev/null
+++ b/odb/src/scripts/odbset
@@ -0,0 +1 @@
+.odb_deprecated.sh
\ No newline at end of file
diff --git a/odb/src/scripts/odbsql b/odb/src/scripts/odbsql
new file mode 100755
index 0000000..d46681c
--- /dev/null
+++ b/odb/src/scripts/odbsql
@@ -0,0 +1,972 @@
+#!/bin/ksh
+
+thisdir=$(pwd)
+
+export TMPDIR=${TMPDIR:=/tmp}
+[ "${ODB_API_VERSION}" != "" ] || export ODB_API_VERSION=$ODB2_VERSION
+
+tmpquery=$TMPDIR/myview_$$.sql
+cmdfile=$TMPDIR/cmdfile.odbsqlmp.$$
+stderr=$TMPDIR/stderr.$$
+errtrg=$TMPDIR/errtrg.$$
+odb98_info=$TMPDIR/odb98.info.$$
+action_dir=$thisdir/dir.$$
+
+trap 'echo "Received signal, aborting ..."; \
+      cat $stderr >&2 || :; \
+      \rm -f $stderr 2>/dev/null < /dev/null || :; \
+      \rm -f $cmdfile 2>/dev/null < /dev/null || :; \
+      \rm -f $tmpquery  2>/dev/null < /dev/null || :; \
+      \rm -f $errtrg  2>/dev/null < /dev/null || :; \
+      \rm -f $odb98_info  2>/dev/null < /dev/null || :; \
+      \rm -rf $action_dir 2>/dev/null < /dev/null || :; \
+      sleep 1; exit 1' \
+      1 2 3 6 15
+
+#begin
+#
+# Usage: odbsql  -q 'data query'      # ODB/SQL data query statement (either this or -v sqlfile must be given)
+#                -v sql_file          # Data query supplied via file
+#               [-h]                  # print this usage and exit
+#               [-F]                  # Force to (re-)create the dca/ -dir
+#               [-I]                  # Display only INFO-data of the data query
+#               [-g]                  # Debugging output on (goes to stderr)
+#               [-k]                  # Convert the sole columns $ODB_LAT & $ODB_LON degrees, if present/applicable
+#               [-K]                  # Do *not* convert the sole columns $ODB_LAT & $ODB_LON degrees (the default)
+#               [-o file[.gz]]        # SQL-output goes to a file (also gzip'ped, if suffix is ".gz")
+#               [-f output_format]    # case insensitive output_format can be "odbtk", "odb" or "default"
+#               [-% fmt_string]       # Alternate format for real-numbers which will override the default; f.ex. -%15.7g
+#                                       For the moment applicable only to '-f default' or '-f odbtk'
+#               [-p pool(s)]          # Use these pools i.e. provide poolmask (as in other ODB-tools)
+#               [-m [start,]maxcount] # Max no. of rows over all pools. If "start" not given, assumed == 1
+#               [-M maxcount]         # Max no. of rows *per pool* to print (triggers auto-use of ODBTk's $__maxcount__!)
+#               [-t table_name]       # Get data from table "directly" ; same as -q 'SELECT * FROM table'
+#               [-D debugger]         # Run program odbsql.x under the "debugger"
+#               [-c]                  # Disable use of curses (also using -q or -v options will disable curses)
+#               [-T]                  # Do *NOT* write column title at all
+#               [-N]                  # Do *NOT* write NULLs, but proper missing data values (same as ODB_PRINT_MDI=0)
+#               [-X]                  # View end result in a separate window
+#               [-b]                  # Show progress bar
+#               [-B]                  # Do *NOT* show progress bar (now the default)
+#               [-U]                  # Do *NOT* attempt to use predefined indices (the same as ODB_USE_INDICES=0)
+#               [-H dr_hook_opt]      # Enable Dr.Hook profiler and export DR_HOOK_OPT with dr_hook_opt
+#               [-C color_map[.cmap]  # Supply color-map file (suffix .cmap or no-suffix); The file is searched from
+#                                       file's directory (if not current_dir), then current_dir, and finally from $ODB_SYSPATH
+#               [-d]                  # Use DUMMY-database from $ODB_SYSDBPATH
+#               [-e error_out_file]   # By default stderr.<process_id>; For some cases maybe useful : -e /dev/null
+#               [-w]                  # Activate wind-arrow plotting : same as -f wplotobs 
+#               [-j]                  # Join consecutive character string columns into name[1:10]@table (-f default only)
+#               [-A plot_area]        # Plotting area; default = -90,-180,90,180[,50e6]  # The 50e6 is Magics map scaling factor
+#               [-P projection]       # Projection ; default = CYLINDRICAL (other: AITOFF, POLAR[_STEREOGRAPHIC], MERCATOR, LAMBERT)
+#               [-i /data/base/dir/DB.sch] # Location of schema file :if not given, try to find from the current dir;
+#                                            if still not found, revert to use DUMMY-database in $ODB_SYSDBPATH
+#                                       New: If you give -i option multiple times -- or the argument for -i contains
+#                                            wildcards [in quotes] (i.e. possibly multiple databases), then the
+#                                            odbdup/odbmerge will be called and the SQL is executed against the odbdup'ped directory
+#               [-n ncpus[.nchunk]]   # If ncpus > 1, tries to run the SQL in several chunks using ncpus and then concatenate results.
+#                                     # Restrictions apply: certain global operations (like stdev), or SELECT DISTINCT, or ORDERBY
+#                                     # may initially be preventing from parallelization.
+#                                     # Since parallelization chunk is a pool-chunk, defining poolmask also will prevent parallelism.
+#                                     # The optional "nchunk" signifies how many pools is given for each parallel subprocess
+#               [-V '$var1=1.5; var2=2.3']  # Overrides $-variable defaults found in SQL; The '$' can be omitted.
+#               [-x executable_name]  # Supply alternative filepath for odbsql.x (for flexible testing purposes only)
+#  
+# Note: Since "curses"-interface is not yet implemented, then using -c option has no effect.
+#
+# However, if you don't supply -o option, but use -f odbtool, then all *binary* ODB-tool output 
+# will go to the default ODB-tool file "temp.000001". The ASCII ODB-tool still goes to
+# "temp_ascii.000001" (and there is currently no way to change this)
+# 
+# The file name in -o option can be parameterized by supplying '%s' and/or '%d' as part of the file name.
+# The '%s' will be replaced by viewname (for each SQL) and '%d' with a pool number in concern.
+# Finally, if .gz suffix is supplied, then output file(s) will be "gzip'ped".
+#
+# When "output_format" is
+#
+#  - "newodb", then create a new odb with format ODB-2.0 (single ODB file); recommended: use also -o file and -i database/path
+#  - "odbtk", then field delimiters become "!,!" and unique column ids ($uniq#)
+#     will be printed as "zero-th" column
+#  - "odb", then "odbviewer"/"odbless" .rpt-file format is emulated (default with -X option)
+#  - "default" (the default), then field delimiter is space (" "), and output is rather compressed
+#  - "binary", then a binary format will be used for output (recommended: use also -o file)
+#  - "plotobs", then $ODB_PLOTTER compatible binary file for Magics will be created
+#  - "wplotobs", then $ODB_PLOTTER compatible binary file for Magics will be created (wind-arrows)
+#  - "odbtool", then input(s) for IDL/odbtool (by Phil Watts while at ECMWF, now in Eumetsat) will be created
+#  For Metview GEO-points : Please make sure your SQL conforms with the -f geo[:xxx] label !
+#  - "geo", then (standard) Metview GEO-points file with "lat long level  date time value"
+#  - "geo:xyv", then also GEO-points file with "x/long y/lat value"
+#  - "geo:xy_vector", then also GEO-points file with "lat lon height date time u v"
+#  - "geo:polar_vector", then also GEO-points file with "lat lon height date time speed direction"
+#  For NetCDF (*new*) :
+#  - "netcdf", then create NetCDF-file with ODB Conventions
+#  - "unetcdf", "unpacked" netcdf : as "netcdf" above, but create without packing
+#    Both NetCDF-options also imply -k i.e. lat/lon are in degrees
+#  Text dump:
+#  - "dump", then similar to "default", but delimiter is comma ","
+#    dump-option also imply -k i.e. lat/lon are in degrees (unless -K had been explicitly given)
+#  Binary dump:
+#  - "bindump", similar to "binary", but all data will be printed row_wise + metadat & title-structure always embedded
+#    Similar to dump-option, it implies  -k i.e. lat/lon are in degrees (unless -K had been explicitly given)
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 06-Nov-2006
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+alias cd='\cd'
+
+export ODB_SYSDBPATH=${ODB_SYSDBPATH:=$ODB_SYSPATH/../sysdb}
+export OMP_NUM_THREADS=1
+
+export ODB_NETCDF_NOPACKING=${ODB_NETCDF_NOPACKING:=0}
+
+odbsql2_inputfile=""
+option_odbsql2=""
+odbsql2=-1
+query=""
+query_given=0
+debug=0
+debugverb=""
+create_dca=0
+outfile="/dev/null"
+info_only=0
+poolmask=""
+#dbpath=$thisdir
+dbpath=""
+dbpath_count=0
+schema_file=""
+sqlfile="/dev/null"
+viewname="myview"
+use_curses=1
+start=1
+maxcount=-1
+global_row_count=1
+table=""
+table_given=0
+debugger=""
+format="default"
+format_given=0
+konvert=0
+write_title=1
+export ODB_PRINT_MDI=${ODB_PRINT_MDI:=1} # 1 = print NULLs, 0 = print the actual MDI values
+tty=$(tty -s 2>/dev/null && echo "0" || echo "$?")
+# progress_bar=1 # old default
+progress_bar=0 # new default
+if [[ "${ODB_ARCH:-unknown}" = "nectx" ]] ; then
+  progress_bar=0
+else
+  [[ $tty -eq 0 ]] || progress_bar=0
+fi
+progress_bar_given=0
+b4x=0
+cmap=""
+cmap_given=0
+fmt_string="-"
+export ODB_USE_INDICES=${ODB_USE_INDICES:=1} # 1=use predefined indices, 0=do NOT use them
+drhookopt=""
+dummydb=0
+warrow=""
+joinstr=0
+plot_area=""
+plot_proj=""
+ncpus=1
+varvalue=""
+minusK=0
+altexe="/dev/null"
+exe_given=0
+
+FLAGS=A:bBcC:dD:e:f:FghH:i:IjkKm:M:n:No:p:P:q:t:TUv:V:wx:X%:
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  A) plot_area="$OPTARG";;
+  b) progress_bar_given=1; progress_bar=1;;
+  B) progress_bar_given=1; progress_bar=0;;
+  c) use_curses=0;;
+  C) cmap_given=1; cmap="$OPTARG";;
+  d) dummydb=1;;
+  D) debugger="$OPTARG";;
+  f) format_given=1; format="$OPTARG";;
+  F) create_dca=1;;
+  e) stderr="$OPTARG";;
+  g) debug=1; debugverb="-v -d";;
+  h) abort=yes; break;;
+  H) drhookopt="$OPTARG";;
+  k) konvert=1;;
+  K) konvert=0; minusK=1;;
+  i) ((dbpath_count+=1)); dbpath="$dbpath$OPTARG ";;
+  I) info_only=1;;
+  j) joinstr=1;;
+  m) maxcount="$OPTARG"; global_row_count=1;;
+  M) maxcount="$OPTARG"; global_row_count=0;;
+  n) ncpus="$OPTARG";;
+  N) export ODB_PRINT_MDI=0; option_odbsql2=" -N ";;
+  o) outfile="$OPTARG";;
+  p) poolmask="$poolmask $OPTARG";;
+  P) plot_proj="$OPTARG";;
+  q) use_curses=0; query_given=1; query="$OPTARG";; 
+  t) table_given=1; table=$(echo "$OPTARG"| perl -pe 's#^\@##');;
+  T) write_title=0;;
+  U) export ODB_USE_INDICES=0;;
+  v) use_curses=0; sqlfile="$OPTARG"; viewname=$(basename "$sqlfile" | perl -pe 's/\..*//');;
+  V) varvalue="$varvalue ; $OPTARG";;
+  w) warrow="w"; format_given=1; format="wplotobs";;
+  x) altexe="$OPTARG"; exe_given=1;;
+  X) b4x=1;;
+  %) fmt_string="%$OPTARG";;
+  *) abort=yes; break;;
+  esac
+done
+
+function _with_odb_api {
+  # Attempts to load odb_api module if odb|odb_migrator|odb2netcdf.x tool is not in user's PATH.
+  command -v $1 >/dev/null 2>&1 && return 0
+  command -v module >/dev/null 2>&1 && module --silent load odb_api
+  command -v $1 >/dev/null 2>&1 || {
+    echo "***Error: ODB-API tool '$1' not in your PATH" >&2
+    return 1
+  }
+}
+
+if [[ "$abort" = "no" ]] ; then
+  if [[ "$varvalue" = "" ]] ; then
+    varvalue="-"
+  else
+    varvalue=$(echo "$varvalue" | perl -pe 's/\s*=\s*/=/g; s/\s*[;]+\s*/\n/g; s/^\s+//g; s/[\$]+//g; s/\n/,/g; s/[,]+/,/g;')
+  fi
+
+  if [[ X"${USER:-}" = X ]] ; then
+    export USER=${USER:=$(id -un)}
+  fi
+
+  if [[ X"${ARCH:-}" = X ]] ; then
+    export ARCH=unknown
+  fi
+  test_arch=$(test_arch 2>/dev/null || echo "$ARCH")
+  if [[ "$dbpath" != "" ]] ; then
+# remove leading white spaces
+     dbpath=${dbpath## }
+# remove trailing white spaces
+     dbpath=${dbpath%% }
+     if [[ -f $dbpath ]]; then
+        ascii=$(file $dbpath | grep -i ascii || echo 1)
+        if [[ "$ascii" = "1" ]] ; then
+         odbsql2=1
+         odbsql2_inputfile=$dbpath
+        if [[ $write_title -eq 0 ]] ; then
+         option_odbsql2=" $option_odbsql2 -T "
+        fi
+        if [[ "$format" = "newodb" ]] ; then
+          format=odb
+        fi 
+        fi
+     fi
+  fi
+  if [[ $dbpath_count -eq 0 ]] ; then
+    dbpath=$thisdir
+  else
+    #dbpath=$(echo "$dbpath" | perl -pe 's/\s+$//')
+    #-- Check how many dirs actually ...
+    inpdirs=""
+    dbname=""
+    hasdca=0
+    dbpath_count=0
+    #-- Handle possible wildcard expansions here
+    for db in $(exec 2>/dev/null; /bin/csh -c "/bin/ls -dC1 $dbpath || :")
+    do
+      if [[ -f $db ]] ; then
+        db=$(dirname $db)
+      fi
+      dbn=$(\cd $db >/dev/null 2>&1 && basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+      if [[ -f "$db/$dbn.dd" ]] ; then
+        ((dbpath_count+=1))
+        dbname=$dbn
+        inpdirs="${inpdirs}$db "
+        if [[ -d $db/dca ]] ; then
+          ((hasdca+=1))
+        fi
+      fi
+    done
+
+    if [[ $dbpath_count -eq 1 ]] ; then
+      dbpath=$(echo "${inpdirs}" | perl -pe 's/\s+$//')
+    else # This for both $dbpath_count -eq 0 (i.e. $dbname = "") and $dbpath_count -gt 1 
+
+      #-- Use odbdup and create new database dir on the temp disk
+
+      if [[ "$dbname" != "" ]] ; then
+        #-- The "mtimecnt" tries to trace whether input database(s) crucial metadata has changed,
+        #   indicating potential changes in the data itself;
+        #   We could have 'ls -C1sR' through the datapath(s) to calculate the sum of file sizes;
+        #   this could however be potentially very, very time consuming for large amount of files;
+        #   Even now the count of dca-files could be big
+
+        mtimecnt="0.0"
+        for d in ${inpdirs}
+        do
+          if [[ -d $d ]] ; then
+            mtimecnt=$(echo "$mtimecnt" | $ODB_FEBINPATH/odbfiletime.x $d/*.dd $d/*.iomap $d/dca $d/dca/*.dca 2>/dev/null || echo "$mtimecnt")
+          fi
+        done
+
+        ddtag=$($ODB_FEBINPATH/odbmd5sum -D"${inpdirs}")
+
+        if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+          # Prefer to use RAM-disk (/dev/shm) when available
+          dupdir=/dev/shm
+        elif [[ -d "$TMPDIR" ]] ; then
+          dupdir=$TMPDIR
+        else
+          dupdir=/tmp
+        fi
+        dbpath=${dupdir}/odbsql.${USER}/$dbname.$ddtag.$mtimecnt
+
+        #-- Note: If odbdup'ped database dir already exist, do NOT rerun odbdup
+        #         unless -F option was used, too (re-create dca)
+        if [[ ! -d "$dbpath" ]] || [[ $create_dca -gt 0 ]] ; then
+          opt="-s -F -l $dbname -o $dbpath "
+          if [[ $hasdca -ne $dbpath_count ]] ; then
+            opt="${opt}-Q " # do NOT run dcaquick, since one or more dca/-dirs are missing
+          fi
+          for db in ${inpdirs}
+          do
+            opt="${opt}-i $db "
+          done
+          $ODB_BINPATH/odbdup $opt >&2      
+        fi
+        dbpath_count=1
+        create_dca=0
+      else
+        if [[ $odbsql2 -eq -1 ]] ; then
+          echo "***Error: One or more invalid directories/schema files in '$dbpath'" >&2
+          abort=yes
+          dbpath_count=0
+          dbpath=/dev/null
+        fi
+      fi
+    fi
+  fi # if [[ $dbpath_count -eq 0 ]] ; then
+
+  
+  if [[ $dbpath_count -eq 1 ]] ; then
+    if [[ -f $dbpath ]] ; then
+      schema_file=$dbpath
+      dbpath=$(dirname $dbpath)
+    fi
+  fi
+
+  if [[ -d "$dbpath" ]] ; then
+    \cd $dbpath
+    dbpath=$(pwd)
+    dbname=$(basename $(\ls -C1 *.dd 2>/dev/null | head -1) .dd || echo "")
+    if [[ "$dbname" = ".dd" ]] ; then
+    #  echo "***Error: Unable to locate the main metadata file (.dd) from directory '$dbpath'" >&2
+    #  dbname=""
+    #  abort=yes
+      dummydb=1
+    fi
+    \cd $thisdir
+  else
+    if [[ $odbsql2 -eq -1 ]] ; then
+      echo "***Error: No such database directory/schema file '$dbpath'" >&2
+      dbname=""
+      abort=yes
+    fi
+  fi
+
+  if [[ $dummydb -eq 1 ]] ; then
+    dbname=DUMMY
+    dbpath=$ODB_SYSDBPATH/$dbname
+    schema_file=$dbpath/$dbname.sch
+  fi
+
+  if [[ "$schema_file" = "" ]] ; then
+    schema_file=$dbpath/$dbname.sch
+  fi
+
+  if [[ "$schema_file" -ef "$ODB_SYSDBPATH/DUMMY/DUMMY.sch" ]] ; then
+    dummydb=1
+    dbname=DUMMY
+    dbpath=$ODB_SYSDBPATH/$dbname
+    schema_file=$dbpath/$dbname.sch
+  else
+    dummydb=0
+  fi
+
+  if [[ $table_given -eq 1 ]] ; then
+    if [[ $odbsql2 -eq 1 ]] ; then
+      query="select *"
+    else
+      query='SELECT * FROM '"$table" 
+    fi
+    query_given=1
+  elif [[ "$sqlfile" != "/dev/null" && -r "$sqlfile" ]] ; then
+    query=$(perl -pe 's#(//|--\s+).*##' < $sqlfile) # get rid of the messages after the comment '//' or '-- '
+    query_given=1
+  fi
+
+  if [[ $query_given -eq 0  && $odbsql2 -ne 1 ]] ; then
+    echo "***Error: ODB/SQL data query MUST be given (see use of -q or -v option)" >&2
+    abort=yes
+  else
+    query=$(echo "$query" | perl -pe 's/\n/ /g')
+  fi
+fi
+
+if [[ $odbsql2 -eq 1 ]] ; then
+
+ if [[ $query_given -eq 0 ]] ; then
+   query='select \* from '\\\"$odbsql2_inputfile\\\"';' 
+   query="select *" 
+   query_given=1
+   table_given=1
+   echo "$query" > $TMPDIR/.tmp.sql
+   sqlfile=$TMPDIR/.tmp.sql
+ else
+ 
+ if [[ "$sqlfile" = "/dev/null" ]] ; then
+   echo "$query ;" > $tmpquery
+   sqlfile=$tmpquery
+ fi
+ query_with_input_file=$(grep  $odbsql2_inputfile  $sqlfile || echo "")
+ has_dblequote=$(grep  \"$odbsql2_inputfile\"  $sqlfile || echo "")
+ if [[ "$has_dblequote" = "" ]] ; then
+   sql_request=$(sed 's#'`echo $odbsql2_inputfile`'#"'$odbsql2_inputfile'"#' $sqlfile)
+   echo $sql_request >$sqlfile
+ else
+  odbsql2_ofile=$(basename $odbsql2_inputfile)
+  has_dblequote=$(grep  \"$odbsql2_ofile\"  $sqlfile || echo "" )
+  if [[ "$has_dblequote" = "" ]] ; then
+     sql_request=$(sed 's#'`echo $odbsql2_ofile`'#"'$odbsql2_ofile'"#' $sqlfile)
+     echo $sql_request >$sqlfile
+  fi
+ fi
+
+ fi
+ if [[ "$outfile" = "/dev/null" ]] ; then
+    cat $sqlfile | sed 's/\\\*/\*/g' > ${tmpquery}.new
+    sqlfile=${tmpquery}.new
+    _with_odb_api odb && { odb sql $sqlfile -i $odbsql2_inputfile $option_odbsql2; } || exit 1
+ else
+   if [[  $format_given -eq 1 && "$format" = "odb" ]] ; then
+    cat $sqlfile | sed 's/\\\*/\*/g' > ${tmpquery}.new
+    sqlfile=${tmpquery}.new
+    _with_odb_api odb && { odb sql $sqlfile  -i $odbsql2_inputfile  -f odb -o $outfile $option_odbsql2; } || exit 1
+   elif [[  $format_given -eq 1 && "$format" = "netcdf" ]] ; then
+    cat $sqlfile | sed 's/\\\*/\*/g' > ${tmpquery}.new
+    sqlfile=${tmpquery}.new
+    _with_odb_api odb && { odb sql $sqlfile  -i $odbsql2_inputfile  -f odb -o $TMPDIR/.tmp.odb $option_odbsql2; } || exit 1
+    _with_odb_api odb2netcdf.x && { odb2netcdf.x -i $TMPDIR/.tmp.odb -o $outfile; } || exit 1
+   else
+    cat $sqlfile | sed 's/\\\*/\*/g' > ${tmpquery}.new
+    sqlfile=${tmpquery}.new
+    _with_odb_api odb && { odb sql $sqlfile  -i $odbsql2_inputfile $option_odbsql2  > $outfile; } || exit 1
+   fi
+ fi
+ rc=0
+else
+if [[ ! -r "$schema_file" ]] ; then
+  echo "***Error: Database schema file '$schema_file' is not readable and/or available" >&2
+  abort=yes
+fi
+
+# ... and to avoid possible gdb/dbx hangs ...
+export GNUDEBUGGER=0
+export DBXDEBUGGER=0
+
+if [[ "$abort" = "no" ]] ; then
+  #-- Set DUMMY-database credentials ...
+  if [[ $dummydb -eq 1 ]] ; then
+    export ODB_SRCPATH_DUMMY=$dbpath
+    export ODB_DATAPATH_DUMMY=$dbpath
+    export ODB_IDXPATH_DUMMY=/dev/null
+    export IOASSIGN=$dbpath/DUMMY.IOASSIGN
+    create_dca=0
+    #-- No parallelism
+    ncpus=1
+  else 
+    # Set SRCPATH/DATAPATH/IDXPATH-stuff
+    export ODB_SRCPATH_${dbname}=$dbpath
+    export ODB_DATAPATH_${dbname}=$dbpath
+    export ODB_IDXPATH_${dbname}=$dbpath/idx
+    # (re-)set IOASSIGN even if set from outside already
+    if [[ -f $dbpath/$dbname.IOASSIGN ]] ; then
+      export IOASSIGN=$dbpath/$dbname.IOASSIGN
+    elif [[ -f $dbpath/IOASSIGN ]] ; then
+      export IOASSIGN=$dbpath/IOASSIGN
+    elif [[ -f $dbpath/IOASSIGN.$dbname ]] ; then
+      export IOASSIGN=$dbpath/IOASSIGN.$dbname
+    else
+      echo "***Error: Unable to locate corresponding IOASSIGN-file for database '$dbname'" >&2
+      abort=yes
+    fi
+  fi
+fi
+
+if [[ "$abort" = "no" ]] ; then
+  #-- Set analysis date & time
+  ddfile=$dbpath/$dbname.dd
+  if [[ -f $ddfile ]] ; then
+    if [[ ${BASETIME:-no} = no ]] ; then
+      yyyymmddhh=$(head -4 $ddfile | tail -1 | awk '{printf("%8.8d%2.2d\n",$1,$2/10000);}')
+    else
+      yyyymmddhh=$BASETIME
+    fi
+    export ODB_ANALYSIS_DATE=$(echo $yyyymmddhh | cut -c1-8)
+    export ODB_ANALYSIS_TIME="$(echo $yyyymmddhh | cut -c9-10)0000"
+    npools=$(head -5 $ddfile | tail -1)
+  else
+    echo "***Error: Data dictionary file '$ddfile' not found" >&2
+    abort=yes
+  fi
+fi
+
+#-- Abort
+if [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  exit 1
+fi
+
+#-- Make sure the .odbprune_done file exists; if not, generate it (this should be very quick)
+if [[ $dummydb -eq 0 ]] ; then
+  if [[ ! -f $dbpath/.odbprune_done ]] ; then
+    odbprune -i $dbpath >/dev/null 2>&1 || :
+  fi
+
+  if [[ $create_dca -eq 0 ]] ; then
+  #-- Fix dca-indices in-place
+    if [[ ! -f $dbpath/dca/.dcafixed ]] ; then
+      dcafix -q -i $dbpath >/dev/null 2>&1 || :
+    fi
+  fi
+fi
+
+format=$(echo "$format" | perl -pe 'tr/A-Z/a-z/')
+
+if [[ "$format" = "unetcdf" ]] ; then
+  export ODB_NETCDF_NOPACKING=1
+  format=netcdf
+fi
+
+if [[ "$format" = @(dump|bindump) ]] ; then
+  if [[ $konvert -eq 0 && $minusK -eq 0 ]] ; then
+    konvert=1 # apply -k (and no -K was supplied)
+  fi
+fi
+
+rc=0
+if [[  $format_given -eq 1 && "$format" = "newodb"  && $odbsql2 -eq -1 ]] ; then
+    if [[ "$outfile" = "/dev/null" ]] ; then
+      if [[ "$sqlfile" != "/dev/null" ]] ; then
+        view=$(basename "$sqlfile" | perl -pe 's/\..*//')
+      else
+        view=$viewname
+      fi
+      outfile=${view}.odb
+    fi
+    if [[ "$sqlfile" = "/dev/null" ]] ; then
+      echo "$query ;" > $tmpquery
+      sqlfile=$tmpquery
+    fi
+    if [[ -f $dbpath/$dbname.flags ]] ; then
+      export ODB_COMPILER_FLAGS=$dbpath/$dbname.flags
+    fi
+    if [[ "$plot_area" != "" ]] ; then
+      add_columns="-addcolumns $plot_area"
+    else
+      add_columns=""
+    fi
+    _with_odb_api odb_migrator && { odb_migrator $add_columns $dbpath $sqlfile $outfile >&2; } || exit 1
+else
+if [[ $format_given -eq 1 && "$format" = "netcdf" ]] ; then
+      if [[ "$sqlfile" != "/dev/null" ]] ; then
+        view=$(basename "$sqlfile" | perl -pe 's/\..*//')
+      else
+        view=$viewname
+      fi
+      outfile=${view}.nc
+    if [[ "$sqlfile" = "/dev/null" ]] ; then
+      echo "$query ;" > $tmpquery
+      sqlfile=$tmpquery
+    fi
+
+    _with_odb_api odb_migrator && { odb_migrator $dbpath $sqlfile $TMPDIR/${view}.odb >&2; } || exit 1
+    _with_odb_api odb2netcdf.x && { odb2netcdf.x -i $TMPDIR/${view}.odb -o $outfile; } || exit 1
+    Exe=""
+    #-- All ready for NetCDF-file creation
+    b4x=0
+    odbsql2=0
+else
+  rc=1
+  nccatExe=/dev/null
+fi
+
+if [[ $rc -ne 0 ]] ; then
+  if [[ $exe_given -eq 0 ]] ; then
+    if [[ "$debugger" != "" ]] ; then
+      Exe=$ODB_FEBINPATH/odbsql.x
+    else
+      Exe=$ODB_BEBINPATH/odbsql.x
+    fi
+  else
+    Exe=$altexe
+  fi
+  rc=0
+fi
+
+gzip=$(whence gzip 2>/dev/null || echo "")
+export ODB_GZIP=${ODB_GZIP:=$gzip}
+
+echo "$query ;" > $tmpquery
+
+if [[ -f $dbpath/$dbname.flags ]] ; then
+  export ODB_COMPILER_FLAGS=$dbpath/$dbname.flags
+fi
+
+export ODB98_VIEWNAME=$viewname
+export ODB98_DBPATH=$dbpath
+
+rc=0
+if [[ $info_only -eq 1 ]] ; then
+  if [[ "$debugger" != "" ]] ; then
+    echo "Run the debugger '$debugger' with the following arguments:"
+    echo "$debugverb -F2 -Q $tmpquery $schema_file"
+    $debugger $ODB_FEBINPATH/odb98.x
+    rc=1
+  else
+    $ODB_FEBINPATH/odb98.x $debugverb -F2 -Q $tmpquery $schema_file || rc=$?
+  fi
+else
+  if [[ "$poolmask" != "" ]] ; then
+    poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+    export ODB_PERMANENT_POOLMASK="$poolmask"
+    # echo "==> ODB_PERMANENT_POOLMASK=$ODB_PERMANENT_POOLMASK" >&2
+    if [[ "$poolmask" != "-1" ]] ; then
+      ncpus=1 # no parallelism
+    else
+      unset ODB_PERMANENT_POOLMASK
+    fi
+  fi
+
+  if [[ $dummydb -eq 0 ]] ; then
+    rmdir $dbpath/dca 2>/dev/null </dev/null || :
+    if [[ ! -d $dbpath/dca ]] ; then
+      create_dca=2
+    fi
+  fi
+
+  if [[ $create_dca -ge 1 ]] ; then
+    slash2dot=$(echo $dbpath | sed 's%/%\.%g')
+    ddtag=$($ODB_FEBINPATH/odbmd5sum $ddfile | awk '{print $1}')
+
+    if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+      # Prefer to use RAM-disk (/dev/shm) when available
+      dupdir=/dev/shm
+    elif [[ -d "$TMPDIR" ]] ; then
+      dupdir=$TMPDIR
+    else
+      dupdir=/tmp
+    fi
+    dupdir=${dupdir}/$dbname.${USER}${slash2dot}.${ddtag}
+    dupdir=`echo $dupdir | perl -pe 's/-//g'`  # remove  '-' from directory name for consistency with odbdup which also removes these
+
+    if [[ -d $dupdir && -d $dupdir/dca && -r $dupdir/$dbname.sch ]] ; then
+      # Do nothing, since all the necessary stuff available presumably from the previous run
+      :
+    else
+      # Run odbdup to create a "virtual database", which doesn't mess up with the original directory
+      if [[ $create_dca -eq 2 ]] ; then
+        bigQ="-Q"  # do *NOT* use the dcaquick, since input database didn't have any dca/ -dir
+      else
+        bigQ=""
+      fi
+      $ODB_BINPATH/odbdup -s -F -i $dbpath -o $dupdir -l $dbname $bigQ >&2
+    fi
+
+    # Revert dbpath to point to the $dupdir
+    dbpath=$dupdir
+    export ODB_SRCPATH_${dbname}=$dbpath
+
+    # Redefine schema-file
+    schema_file=$dbpath/$dbname.sch
+  fi # if [[ $create_dca -ge 1 ]] ; then
+
+  #-- Produce report window if -X (and unless -f plotobs or -f wplotobs)
+
+  if [[ $b4x -eq 1 ]] ; then
+    if [[ x${DISPLAY:-} = x ]] ; then
+      b4x=0
+    elif [[ $format_given -eq 1 && "$format" = @(plotobs|wplotobs) ]] ; then
+      :
+    else
+      if [[ "$outfile" = "/dev/null" ]] ; then
+        if [[ "$sqlfile" != "/dev/null" ]] ; then
+          view=$(basename "$sqlfile" | perl -pe 's/\..*//')
+	  outfile=${view}.rpt
+	else
+          outfile="%s.rpt"
+        fi
+      fi
+      export ODB_REPORTER=${ODB_REPORTER:="$ODB_FEBINPATH/b4.x"}
+      if [[ $format_given -eq 0 ]] ; then
+        format="odb"
+      fi
+      if [[ $progress_bar_given -eq 0 ]] ; then
+        progress_bar=1
+      fi
+    fi
+  fi
+
+  #-- Plotting
+
+  # Some default env-values :
+
+  export ODB_DATE=${ODB_DATE:="date at hdr"}
+  export ODB_TIME=${ODB_TIME:="time at hdr"}
+
+  export ODB_LAT=${ODB_LAT:="lat at hdr"}
+  export ODB_LON=${ODB_LON:="lon at hdr"}
+
+  #  Color map -file, if given
+  if [[ $cmap_given -eq 1 ]] ; then
+    # The color map file MUST have a suffix ".cmap"; and it will be enforced here:
+    cmap=$(dirname "$cmap")/$(basename "$cmap" .cmap)".cmap"
+    if [[ ! -r "$cmap" ]] ; then
+      cmap=$ODB_SYSPATH/$(basename "$cmap")
+      if [[ ! -r "$cmap" ]] ; then
+        cmap_given=0 # giving up ...
+      fi
+    fi
+  fi
+
+  if [[ $cmap_given -eq 1 && -r "$cmap" ]] ; then
+    export ODB_COLOR=$(head -2 "$cmap" | tail -1 | perl -pe 's/^\s+//')
+  else
+    if [[ "$warrow" = "w" ]] ; then
+      export ODB_COLOR=${ODB_COLOR:="speed"}
+    else
+      export ODB_COLOR=${ODB_COLOR:="obsvalue at body"}
+    fi
+    cmap="/dev/null"
+  fi
+
+  #-- In case of wind-arrow plots ...
+  export ODB_U=${ODB_U:="obsvalue at body"}
+  export ODB_V=${ODB_V:="obsvalue at body#1"}
+ 
+  # Determine if (lat,lon) are in radians, degrees or cannot be determined.
+  # This means that the ODB_LATLON_RAD is 1, 0 and -1, respectively
+  # Needed for functions lldegrees()/llradians() used heavily by the ODBTk
+  #-- Obsolete; done inside odbsql.x, *ONLY* if needed i.e. if $ODB_LAT & $ODB_LON present as well as 
+  # references to lldegrees()/llradians functions
+  # export ODB_LATLON_RAD=${ODB_LATLON_RAD:=$(\cd $dbpath >/dev/null 2>&1; $ODB_FEBINPATH/latlon_rad || echo "-1")}
+
+  if [[ $format_given -eq 1 && "$format" = @(plotobs|wplotobs) ]] ; then
+    #-- plotobs or wplotobs
+    if [[ "$outfile" = "/dev/null" ]] ; then
+      if [[ "$sqlfile" != "/dev/null" ]] ; then
+        view=$(basename "$sqlfile" | perl -pe 's/\..*//')
+        outfile=${view}.obs
+      else
+        outfile="${viewname}.obs"
+      fi
+    fi
+
+    export ODB_PLOTTER=${ODB_PLOTTER:="$ODB_FEBINPATH/plotobs.x -b"}
+    #-- Force immediate plotting, if -X was also given
+    if [[ $b4x -eq 1 ]] ; then
+      export ODB_PLOTTER=$(echo "$ODB_PLOTTER" | sed 's/ -b/ -s -b/')
+    fi
+
+    if [[ "$format" = wplotobs ]] ; then
+      export ODB_PLOTTER=$(echo "$ODB_PLOTTER" | sed 's/ -b/ -W -b/')
+    fi
+
+    if [[ "$plot_area" != "" ]] ; then
+      export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ -a'$plot_area' -b/")
+    fi
+
+    if [[ "$plot_proj" != "" ]] ; then
+      export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ -p$plot_proj -b/")
+    fi
+
+    if [[ $progress_bar_given -eq 0 ]] ; then
+      progress_bar=1
+    fi
+    export MAGICS_DEVICE=${MAGICS_DEVICE:="JPEG"}  # Can be f.ex. "PS_COL", "PNG", "GIF"
+
+  elif [[ $format_given -eq 1 && "$format" = "odbtool" ]] ; then
+  #-- odbtool
+    if [[ "$outfile" = "/dev/null" ]] ; then
+      outfile="temp.000001"
+    fi
+  fi
+
+  #-- Figure out the "start" from maxcount
+
+  num=$(echo "$maxcount" | awk -F, '{print NF}')
+  if [[ $num -eq 1 ]] ; then
+    start=1
+  elif [[ $num -gt 1 ]] ; then
+    start=$(echo "$maxcount" | awk -F, '{print $1}')
+    [[ "$start" != "" ]] || start=1
+    end=$(echo "$maxcount" | awk -F, '{print $2}')
+    if [[ "$end" == "" ]] ; then
+      maxcount=-1
+#    elif [[ $end -lt 0 ]] ; then
+#      maxcount=-1
+    else
+      maxcount=$((start+end-1))
+    fi
+  fi
+
+  if [[ $maxcount -eq 2147483647 ]] ; then # max no of rows permitted to output (= 2^31 - 1)
+    maxcount=-1
+  fi
+
+  if [[ $start -ne 1 ]] || [[ $maxcount -ne -1 ]] ; then
+    ncpus=1
+  fi
+
+  nchunk=$(echo "$ncpus" | perl -ne 'print $1 if (m/^.*[.](\d+).*/) || print 0')
+  ncpus=$(echo "$ncpus" | perl -pe 's/^(\d+).*/$1/')
+
+  if [[ $ncpus -gt $npools ]] ; then
+    ncpus=$npools # A rare situation, but ...
+  fi
+
+#-- Create info-file once to be fed in in parallel invocations of odbsql.x
+  if [[ $ncpus -gt 1 && $debug -eq 0 && "$debugger" = "" ]] ; then
+    export ODB98_INFO=$odb98_info
+    $ODB_FEBINPATH/odb98.x -F2 -Q $tmpquery $schema_file > $odb98_info || {
+      rc=$?
+      \rm -f $tmpquery  2>/dev/null < /dev/null || :
+      \rm -f $odb98_info  2>/dev/null < /dev/null || :; \
+      exit $rc
+    }
+    cat >> $odb98_info <<EOF
+/dir=$dbpath
+/host=$(hostname)
+/tstamp=$(date)
+EOF
+
+    #-- Switch $ncpus back to 1, if any of the following is found true (n > 0) :
+    # /has_select_distinct=1
+    # /has_aggrfuncs=1
+    # /has_thin=1
+    # /orderby n
+    # /uniqueby n
+
+    typeset x=$(perl -ne 'if (m#^/(has_select_distinct|has_aggrfuncs|has_thin)=1#) { print 1; exit; } elsif (m#^/(orderby|uniqueby)\s+(\d+)# && $2 > 0) { print $2; exit; }' $odb98_info || :)
+
+    if [[ "$x" != "" ]] ; then
+      ncpus=1
+      unset ODB98_INFO
+    fi
+  else
+    export ODB98_INFO=/dev/null
+    unset ODB98_INFO
+  fi
+
+  #-- Developers backdoor to supply a fixed info-file; be very careful with this !!
+  #   This essentially bypasses odb98.x altogether
+  #   Creation process can be as follows:
+  #    (0) cd /data/base/direc/tory/ECMA.whateva
+  #    (1) odbsql -q 'some query' -I > odb98.info
+  #    (2) edit odb98.info # fix the problem by hand
+  #    (3) env ODB98_INFO_OVERRIDE=odb98.info odbsql -q 'some query' -o result.file
+  #   If "result.file" is what you expected, your hand-patch has worked.
+  #   After this you [or your good friend!] would normally have to fix the odb98-compiler itself ;-(
+
+  if [[ X"${ODB98_INFO_OVERRIDE:-}" != X ]] ; then
+    if [[ -r "${ODB98_INFO_OVERRIDE}" ]] ; then # the file is indeed readable ...
+      export ODB98_INFO="${ODB98_INFO_OVERRIDE}"
+    fi
+  fi  
+
+  #-- Dr.Hook profiling ?
+
+  if [[ $ncpus -eq 1 ]] ; then
+    if [[ "$drhookopt" != "" ]] ; then
+      export DR_HOOK=true
+      export DR_HOOK_OPT="$drhookopt"
+    else
+      export DR_HOOK_OPT="none"
+    fi
+  fi
+
+  #-- Run
+
+  if [[ "$debugger" != "" ]] ; then
+    echo "Run the debugger '$debugger' with the following arguments:"
+    echo "$schema_file $tmpquery $start $maxcount $debug $konvert $format \
+$outfile $write_title $global_row_count $progress_bar $b4x $cmap $fmt_string $joinstr $varvalue" >&2
+    $debugger $Exe
+    rc=1 # Ensure non-zero exit code from debugger runs
+  else
+    if [ $odbsql2 -eq -1 ] ; then
+    #-- Not running under the debugger
+    do_cmd_1="$Exe $schema_file"
+    do_cmd_2="$start $maxcount $debug $konvert $format $outfile $write_title $global_row_count $progress_bar $b4x $cmap $fmt_string $joinstr $varvalue"
+    if [[ $debug -eq 0 ]] ; then
+      \rm -f $stderr 2>/dev/null < /dev/null || :
+      if [[ "${ODB_ARCH:-unknown}" = "nectx" ]] ; then
+        cat <<EOF | odbqsub -N odbsql$$ || rc=$?
+$do_cmd_1 $tmpquery $do_cmd_2 2>$stderr || rc=\$?
+[[ \$rc -eq 0 ]] || cat $stderr
+rm -f $stderr
+EOF
+      elif [[ $ncpus -eq 1 ]] ; then
+        $do_cmd_1 $tmpquery $do_cmd_2 2>$stderr || {
+          rc=$?
+          cat $stderr >&2 || :
+        }
+        \rm -f $stderr 2>/dev/null < /dev/null || :
+      else
+        perl -w $ODB_FEBINPATH/odbsqlmp.pl \
+           --ncpus $ncpus --nchunk $nchunk --npools $npools --workdir $action_dir \
+           --executable $Exe --nccat $nccatExe \
+           --schema $schema_file --query $tmpquery \
+           --konvert $konvert --format $format \
+           --outfile $outfile --write_title $write_title \
+           --b4x $b4x --cmap $cmap --fmt_string "$fmt_string" --joinstr $joinstr \
+           --error_trigger $errtrg --varvalue "$varvalue" \
+           2>$stderr > $cmdfile || rc=$?
+        if [[ $rc -eq 0 ]] ; then
+          nmaxcmd=$(wc -l $cmdfile)
+          env ODB_PARAL=$ncpus FSCHEDULER_PBAR=$progress_bar $ODB_BINPATH/fscheduler.x $nmaxcmd 2>>$stderr || rc=$?
+          if [[ -f $errtrg ]] ; then
+            rc=255
+          fi
+        fi
+        if [[ $rc -ne 0 ]] ; then
+          cat $stderr >&2 || :
+        fi
+
+        \rm -f $errtrg 2>/dev/null < /dev/null || :
+        \rm -f $stderr 2>/dev/null < /dev/null || :
+        \rm -f $cmdfile 2>/dev/null < /dev/null || :
+	\rm -rf $action_dir 2>/dev/null < /dev/null || :
+      fi
+    else
+      if [[ "${ODB_ARCH:-unknown}" = "nectx" ]] ; then
+	echo "$do_cmd_1 $tmpquery $do_cmd_2 2>&1 || rc=\$?" | odbqsub -N odbsql$$ || rc=$?
+      else
+        $do_cmd_1 $tmpquery $do_cmd_2 2>&1 || rc=$?
+      fi
+    fi
+   fi
+  fi
+ fi
+fi
+fi
+
+\rm -f $tmpquery  2>/dev/null < /dev/null || :
+\rm -f $odb98_info  2>/dev/null < /dev/null || :; \
+exit $rc
diff --git a/odb/src/scripts/odbsqlmp.pl b/odb/src/scripts/odbsqlmp.pl
new file mode 100644
index 0000000..c965432
--- /dev/null
+++ b/odb/src/scripts/odbsqlmp.pl
@@ -0,0 +1,236 @@
+use strict;
+use Getopt::Long;
+
+#-- Some env-vars --
+
+my $binpath = $ENV{'ODB_BINPATH'} || ".";
+my $febinpath = $ENV{'ODB_FEBINPATH'} || "$binpath";
+my $magics_device = $ENV{'MAGICS_DEVICE'} || "JPEG";
+my $odb_io_grpsize = $ENV{'ODB_IO_GRPSIZE'} || 0;
+
+#--- Globals ---
+
+my $devnull = "/dev/null";
+
+#--- Argument list processing --
+
+my $ncpus = 1;
+my $nchunk_in = 0;
+my $npools = 0;
+my $dir = "dir.0";
+
+my $Exe = "$febinpath/odbsql.x"; 
+my $nccatExe = "/dev/null";
+
+my $schema = $devnull;
+my $tmpquery = $devnull;
+my $start = 1;
+my $maxcount = -1;
+my $debug = 0;
+my $konvert = 0;
+my $format = "default";
+my $outfile = $devnull;
+my $write_title = 0;
+my $global_row_count = 1;
+my $b4x = 0;
+my $cmap = $devnull;
+my $fmt_string = "-";
+my $joinstr = 0;
+
+my $view = "myview";
+my $errtrg = $devnull;
+my $varvalue = "-";
+
+#-- Misc
+
+my $plotobs_exe = "$febinpath/plotobs.x";
+my $b4x_exe = "$febinpath/b4.x";
+
+#        perl -w ./odbsqlmp.pl --ncpus $ncpus --nchunk $nchunk --npools $npools --workdir dir.$$ \
+#           --executable $Exe --nccat $nccatExe \
+#           --schema $schema_file --query $tmpquery \
+#           --konvert $konvert --format $format \
+#           --outfile $outfile --write_title $write_title \
+#           --b4x $b4x --cmap $cmap --fmt_string "$fmt_string" --joinstr $joinstr \
+#           --view myview --error error.out \
+#           2>$stderr || rc=$?
+
+GetOptions( "ncpus=i" => \$ncpus,
+	    "npools=i" => \$npools,
+	    "nchunk=i" => \$nchunk_in,
+	    "workdir=s" => \$dir,
+	    "executable=s" => \$Exe,
+	    "nccat=s" => \$nccatExe,
+	    "schema_file=s" => \$schema,
+	    "query_file=s" => \$tmpquery,
+	    "konvert=i" => \$konvert,
+	    "format=s" => \$format,
+	    "outfile=s" => \$outfile,
+	    "write_title=i" => \$write_title,
+	    "b4x=i" => \$b4x,
+	    "cmap=s" => \$cmap,
+	    "fmt_string=s" => \$fmt_string,
+	    "joinstr=i" => \$joinstr,
+	    "viewname=s" => \$view,
+	    "error_trigger=s" => \$errtrg,
+	    "varvalue=s" => \$varvalue,
+	    ) || die "Invalid option(s)";
+
+
+my $nchunk = ($nchunk_in < 1) ? ($odb_io_grpsize > 0 ? $odb_io_grpsize : $npools/$ncpus) : $nchunk_in;
+$nchunk = $npools if ($nchunk > $npools);
+
+$fmt_string =~ s/%/%%/g;
+
+my $do_cmd_1="%env% $Exe $schema";
+
+my $do_cmd_allpools = $do_cmd_1;
+
+$do_cmd_1        =~ s|%env%|env ODB_PLOTTER=0 ODB_PERMANENT_POOLMASK=%d-%d|;
+$do_cmd_allpools =~ s|%env%|env ODB_PLOTTER=0 ODB_PERMANENT_POOLMASK=-1|;
+
+my $do_cmd_2="$start %maxcount% $debug $konvert $format %outfile% %write_title% $global_row_count";
+$do_cmd_2 .= " %progress_bar% %b4x% $cmap $fmt_string $joinstr $varvalue";
+
+$do_cmd_2 =~ s|%b4x%|0|;
+$do_cmd_2 =~ s|%progress_bar%|0|;
+$do_cmd_2 =~ s|%write_title%|%d|;
+my $uit = "$dir/uit.%8.8d"; # generic output file
+$do_cmd_2 =~ s|%outfile%|$uit|;
+$do_cmd_2 =~ s|%maxcount%|%d|;
+
+#-- Start of command file
+
+my $errtouch = "|| :";
+if ( $errtrg ne $devnull ) {
+    print STDOUT "rm -f $errtrg\n";
+    &Wait();
+    $errtouch = "|| touch $errtrg";
+}
+
+print STDOUT "mkdir $dir\n";
+print STDOUT "on_error: rm -rf $dir\n";
+
+&Wait();
+
+my @ayts = ();
+
+my $np = 0;
+
+if ($write_title) { # A hack/trick to produce a title line for sure (as long as at least ONE data row found)
+    if ( "$format" eq "odbtk" ||
+	 "$format" eq "default" ||
+	 "$format" eq "dump" ) {
+	my $thismany = ("$format" eq "odbtk") ? 2 : 1;
+	printf(STDOUT "$do_cmd_1 $tmpquery \\\n");
+	printf(STDOUT "$do_cmd_2 | head -$thismany $errtouch\n", 1, 0, 1); # args: maxcount, start_pool_for_uit, write_title
+	#-- Capture the actual output file name used
+	my $ayt = sprintf($uit, $np);
+	push(@ayts, $ayt);
+	printf(STDOUT "[ ! -f $errtrg ] || exit 123\n");
+    }
+}
+$write_title = 0;
+
+my $cnt = 0;
+for ($np = 1; $np <= $npools ; $np += $nchunk) {
+    $cnt++;
+    printf(STDOUT "[ ! -f $errtrg ] || exit 123\n") if ($cnt % $ncpus == 0); # less frequent checking
+    my $nlast = $np + $nchunk - 1;
+    $nlast = $npools if ($nlast > $npools);
+    printf(STDOUT "$do_cmd_1 $tmpquery \\\n", $np, $nlast);
+    printf(STDOUT "$do_cmd_2 $errtouch\n", -1, $np, 0); # args: maxcount, start_pool_for_uit, write_title
+    #-- Capture the actual output file name used
+    my $ayt = sprintf($uit, $np);
+    push(@ayts, $ayt);
+}
+&Wait();
+printf(STDOUT "[ ! -f $errtrg ] || exit 123\n");
+&Wait();
+
+my $has_gz = ($outfile =~ m/\.gz\b/);
+
+if ( "$format" ne "netcdf" ) {
+    if ( $has_gz ) {
+	printf(STDOUT "cat $dir/uit.* | gzip -1c > $outfile $errtouch\n","$view");
+    }
+    else {
+	if ( "$outfile" ne "$devnull" ) {
+	    printf(STDOUT "cat $dir/uit.* > $outfile $errtouch\n","$view");
+	}
+	else {
+	    printf(STDOUT "cat $dir/uit.* $errtouch\n");
+	}
+    }
+}
+elsif ( -x $nccatExe ) { # NetCDF file concatenation
+    my $n_ayts = $#ayts + 1; # no. of NetCDF output files
+    my $uscores = "";
+    while ($n_ayts >= 2) {
+	printf(STDOUT "# $n_ayts files to go ...\n");
+	$uscores .= "_";
+	my $prtcnt = 0;
+	my $cnt = 0;
+	my $cmd = "";
+	my @cmds = ();
+	my @new_ayts = ();
+	for (@ayts) {
+	    $cnt++;
+	    if ($cnt % 2 == 1) {
+		if ($cnt < $n_ayts) {
+		    $cmd = "$nccatExe $_";
+		}
+		push(@new_ayts, "$_");
+	    }
+	    else {
+		$cmd .= " $_";
+		printf(STDOUT "$cmd $errtouch\n");
+		$prtcnt++;
+		printf(STDOUT "[ ! -f $errtrg ] || exit 123\n") if ($prtcnt % $ncpus == 0); # less frequent checking
+	    }
+	} # for (@ayts)
+	@ayts = @new_ayts;
+	$n_ayts = $#ayts + 1;
+	&Wait();
+    } # while ($n_ayts >= 2)
+    printf(STDOUT "# $n_ayts file to go ...\n");
+    for (@ayts) {
+	if ($has_gz) {
+	    printf(STDOUT "gzip -1c < $_ > $outfile $errtouch\n","$view");
+	}
+	else {
+	    printf(STDOUT "mv $_ $outfile $errtouch\n","$view");
+	}
+	last;
+    }
+}
+
+&Wait();
+printf(STDOUT "[ ! -f $errtrg ] || exit 123\n");
+&Wait();
+
+print STDOUT "rm -rf $dir\n";
+if ( $b4x == 1 ) {
+    if ( "$format" eq "plotobs" ) { # regular plot
+	printf(STDOUT "$plotobs_exe -d$magics_device -b$outfile -s &\n","$view");
+    }
+    elsif ( "$format" eq "wplotobs" ) { # wind arrow plot
+	printf(STDOUT "$plotobs_exe -d$magics_device -b$outfile -s -W &\n","$view");
+    }
+    else {
+	printf(STDOUT "$b4x_exe $outfile &\n","$view");
+    }
+}
+
+#-- End of command file
+
+#--- Subroutines ---
+
+sub Wait {
+    print STDOUT "wait\n";
+}
+
+
+
+
+
diff --git a/odb/src/scripts/odbtar b/odb/src/scripts/odbtar
new file mode 100755
index 0000000..229fe8e
--- /dev/null
+++ b/odb/src/scripts/odbtar
@@ -0,0 +1,224 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15
+#begin
+#
+# odbtar [-]flags tarfile(s) [directories|source_files]
+#
+# flags : 
+#
+#  c -- create tar-file : just one tarfile accepted + at least one directory/source_file
+#  f -- next argument is a tarfile : not required; always implied
+#  h -- follow the symbolic link
+#  t -- table of contents on tar-file(s) : as in x option
+#  v -- verbose output
+#  x -- expand tar-file(s) : all file options must be tarfiles; no directories/source_files
+#  z -- gzip/gunzip the tarfile(s) : assumed by default if (1st) tarfile's suffix is .tar.gz or .tgz
+#  # -- A number 1 to 9 to indicate gzip packing method, where '#' is
+#       1=fastest, less compression (default) ... 9=slowest, best compression
+#       Applicable only with {c,z} options
+#  D -- Do not attempt to run 'dcagen' after the expand (the default, if input file comes from stdin ("-"))
+#  F -- Enforce the re-run 'dcagen'
+#
+# Note that {c,t,x}-flags are mutually exclusive.
+#
+# If the tarfile is "-", then assume tarfile read/written from/to stdin/stdout.
+# And {t,x}-flags are used with tarfile "-", then no more arguments accepted after the "-".
+#
+# The minimum number of arguments required is 2 for {x,t}-flags and 3 for c-flag.
+#
+#end
+#
+# Author: Sami Saarinen, ECMWF, 31-May-2007
+#
+
+set -eu
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+abort=no
+
+function do_abort {
+  typeset kmd=$1
+  typeset rest=$2
+  awk '/#begin/,/#end/' $kmd | egrep -v '#(begin|end)' | sed 's/^#//' >&2
+  echo "*** Error in command : $(basename $kmd) $rest" >&2
+  exit 1
+}
+
+nargs=$#
+args=${*:-}
+
+if [[ $nargs -lt 2 ]] ; then
+  do_abort $cmd "$args"
+else
+  flags=$1
+  shift
+  if [[ "$(echo "X$flags" | cut -c1-2)" != "X-" ]] ; then
+    #-- add '-' in front of $flags and redo
+    newcmd="$0 -$flags $*"
+    exec $newcmd || do_abort $cmd "$args"
+  fi
+fi
+
+second_arg=$1
+shift
+other_args=${*:-}
+
+if [[ "$second_arg" = "-" ]] ; then
+  stdinout=1
+  dcagen=0
+else
+  stdinout=0
+  dcagen=1
+fi
+
+create=0
+file=1
+follow=0
+toc=0
+verbose=0
+expand=0
+zip=0
+pmethod=1
+
+FLAGS=cDfFhtvxz123456789
+
+while getopts $FLAGS option $flags
+do
+  case $option in
+  c) create=1;;
+  D) dcagen=0;;
+  f) file=1;;
+  F) dcagen=2;;
+  h) follow=1;;
+  t) toc=1;;
+  v) verbose=1;;
+  x) expand=1;;
+  z) zip=1;;
+  [1-9]) pmethod="$option";;
+  *) echo "***Error: Unrecognized option : $option" >&2; abort=yes; break;;
+  esac
+done
+
+#-- Some consistency checks ...
+if [[ $create -eq 1 ]] ; then
+  [[ $toc    -eq 0 ]] || abort=yes
+  [[ $expand -eq 0 ]] || abort=yes
+  [[ $nargs  -ge 3 ]] || abort=yes
+  dcagen=0 # since not applicable
+elif [[ $toc -eq 1 ]] ; then
+  [[ $create -eq 0 ]] || abort=yes
+  [[ $expand -eq 0 ]] || abort=yes
+  follow=0 # since not applicable
+  dcagen=0 # since not applicable
+elif [[ $expand -eq 1 ]] ; then
+  [[ $create -eq 0 ]] || abort=yes
+  [[ $toc    -eq 0 ]] || abort=yes
+  follow=0 # since not applicable
+else
+  abort=yes
+fi
+
+if [[ $stdinout -eq 1 ]] ; then
+  dcagen=0
+fi
+
+if [[ $stdinout -eq 1 && $nargs -ge 3 ]] ; then
+  #-- Cannot have 'tar -t - other_args' nor 'tar -x - other_args'
+  if [[ $toc -eq 1 ]] || [[ $expand -eq 1 ]] ; then
+    abort=yes
+  fi
+fi
+
+if [[ $abort = yes ]] ; then
+  do_abort $cmd "$args"
+fi
+
+if [[ $zip -eq 0 && $stdinout -eq 0 ]] ; then
+  bn=$(basename "$second_arg" | sed 's/\..*//')
+  targz=$(basename "$second_arg" .tar.gz)
+  tgz=$(basename "$second_arg" .tgz)
+  if [[ "$targz" = "$bn" ]] || [[ "$tgz" = "$bn" ]] ; then
+    zip=1
+  fi
+fi
+
+if [[ $create -eq 1 && $zip -eq 1 && $stdinout -eq 0 ]] ; then
+  #-- Make sure the second_arg (tarfile) will have .tar.gz suffix, unless
+  #   already .tar.gz or .tgz
+  bn=$(basename "$second_arg" | sed 's/\..*//')
+  targz=$(basename "$second_arg" .tar.gz)
+  tgz=$(basename "$second_arg" .tgz)
+  if [[ "$targz" = "$bn" ]] || [[ "$tgz" = "$bn" ]] ; then
+    :
+  else
+    second_arg="${second_arg}.tar.gz"
+  fi
+fi
+
+tarflags="-"
+
+[[ $create  -eq 0 ]] || tarflags="${tarflags}c"
+[[ $follow  -eq 0 ]] || tarflags="${tarflags}h"
+[[ $toc     -eq 0 ]] || tarflags="${tarflags}t"
+[[ $verbose -eq 0 ]] || tarflags="${tarflags}v"
+[[ $expand  -eq 0 ]] || tarflags="${tarflags}x"
+
+[[ $file    -eq 0 ]] || tarflags="${tarflags}f"
+
+if [[ $create -eq 1 ]] ; then
+  #-- Create tarfile
+  if [[ $zip -eq 0 ]] ; then
+    if [[ $stdinout -eq 0 ]] ; then
+      tar $tarflags $second_arg $other_args
+    else # Note: Writes to stdout
+      tar $tarflags - $other_args
+    fi
+  else # Note: Using gzip
+    if [[ $stdinout -eq 0 ]] ; then
+      tar $tarflags - $other_args | gzip -c$pmethod > $second_arg
+    else # Note: Writes to stdout
+      tar $tarflags - $other_args | gzip -c$pmethod
+    fi
+  fi
+elif  [[ $toc -eq 1 ]] || [[ $expand -eq 1 ]] ; then
+  #-- Table of contents on tarfile(s) or expand tarfile(s)
+  if [[ $zip -eq 0 ]] ; then
+    if [[ $stdinout -eq 0 ]] ; then
+      cat $second_arg $other_args | tar $tarflags -
+    else # Note: Reads from stdin
+      tar $tarflags -    
+    fi
+  else # Note: Using gunzip
+    if [[ $stdinout -eq 0 ]] ; then
+      cat $second_arg $other_args | gunzip -c | tar $tarflags -
+    else # Note: Reads from stdin
+      gunzip -c | tar $tarflags -
+    fi
+  fi
+
+  if [[ $dcagen -ge 1 ]] ; then
+    #-- Create dca-indices if not up-to-date, fix some compatibility issues ...
+    if [[ $zip -eq 0 ]] ; then
+      dbpath=$(cat $second_arg | tar -tf - | head -1)
+    else
+      dbpath=$(cat $second_arg | gunzip -c | tar -tf - | head -1)
+    fi
+    if [[ -d "$dbpath" ]] ; then
+      if [[ ! -f $dbpath/.odbprune_done ]] ; then
+        odbprune -i $dbpath >/dev/null 2>&1 || :
+      fi
+      if [[ $dcagen -eq 1 ]] ; then
+        if [[ ! -f $dbpath/dca/.dcafixed ]] ; then
+          dcafix -q -i $dbpath >/dev/null 2>&1 || :
+        fi
+      elif [[ $dcagen -eq 2 ]] ; then
+        \rm -f $dbpath/dca/.dcafixed
+        dcagen -z -F -n -i $dbpath >/dev/null 2>&1 && cat /dev/null > $dbpath/dca/.dcafixed || :
+      fi
+    fi
+  fi
+fi
+
+exit 0
+
diff --git a/odb/src/scripts/odbviewer b/odb/src/scripts/odbviewer
new file mode 100755
index 0000000..31f482c
--- /dev/null
+++ b/odb/src/scripts/odbviewer
@@ -0,0 +1,900 @@
+#!/bin/ksh
+trap 'echo "Received signal, aborting ..."; wait; exit 1' 1 2 3 15 
+#begin
+#
+# Usage: odbviewer [-i database_input_dir]   : default = current dir
+#                  [-o report_output_dir]    : default = $SCRATCH/My_Views/db.xxx.yyy.zzz
+#                  [-v viewname]             : default = <none>
+#                  [-e editor]               : default = that of in $ODB_EDITOR
+#                  [-n number_of_OpenMP-PEs] : default = 1 : No. of OpenMP PE's (note: changed meaning)
+#                  [-D debugger]             : default = none (f.ex. 'cvd' or 'dbx')
+#                  [-s memory_size in MB]    : default = 100  # Obsolete
+#                  [-x x_coord_column_#]     : default = $ODB_XY_COL_X
+#                  [-y y_coord_column_#]     : default = $ODB_XY_COL_Y
+#                  [-t time_column_#]        : default = $ODB_XY_COL_T
+#                  [-f alternate_layout_file]: default = <none>
+#                  [-p specific_pool_number(s)] : default = <none> ; comma separated list
+#                  [-a]                      : default = no ; append to existing plotfile/rptfile
+#                  [-c]                      : clean all
+#                  [-d]                      : run dcagen for tables mentioned in SQL (optional for now)
+#                  [-r]                      : radians to degrees conversion for (lat,lon)
+#                                              (or columns ($ODB_VIEWER_LAT, $ODB_VIEWER_LON))
+#                  [-5]                      : de-activate I/O-method#5 (i.e. do not use fast DCA-access)
+#                  [-S]                      : do *not* suggest default SQL-file (default = suggest)
+#                  [-R]                      : set ODB_VIEWER_RAD2DEG=0 regardless of database name
+#                  [-T]                      : set ODB tracing on
+#                  [-I]                      : do *NOT* plot immediately (i.e. do not use plotobs.x with -s option)
+#                  [-N]                      : turn ODB_REPORTER off i.e. no report-files (maybe only plots wanted?)
+#                  [-C color_map_file]       : supply marker colors via ODB_VIEWER_COLOR_MAP_FILE
+#                  [-A plot_area]            : plotting area; default = -90,-180,90,180[,map_scale=50e6]
+#                  [-P projection]           : default = CYLINDRICAL (other: AITOFF, POLAR[_STEREOGRAPHIC], MERCATOR, LAMBERT)
+#                  [-O other_options]        : Passes on additional options for the plotobs.x
+#                  [-q 'select_data_query']  : Supply your data query straight here!
+#                  [-b]                      : Report-file is written in binary format
+#                  [-k]                      : Konvert (lat,lon) to degrees for plot AND textual output
+#                                              The same as if you have ODB_VIEWER_RAD2DEG=2
+#                                              Note: Does not convert anything if ODB_PLOTTER=0 i.e. plots disabled
+#                  [-M]                      : Turn off Magics plot generation i.e. set ODB_PLOTTER=0
+#                  [-0]                      : Set ODB_REPORTER=stderr (fileno=0) i.e. all output stderr comes to "screen"
+#                  [-1]                      : Set ODB_REPORTER=stdout (fileno=1) i.e. all output comes to "screen"
+#                  [-h]                      : Print help/usage and abort
+#                  [-H dr_hook_opt]          : Enable Dr.Hook profiler and export DR_HOOK_OPT with dr_hook_opt
+#                  [-V virtual_poolmap_file] : Supply user pool-mapping
+#                  [-F]                      : Do *NOT* use the new, Fast odbsql and revert to slow compilations
+#                  [-B]                      : Turn blurps off (progress bar off); implied -B with -e pipe or -e batch
+#                  [-Z]                      : Do *NOT* produce gzip'ped plotfile's (default is to produce, unless -F is used)
+#                  [-w]                      : Produce wind-arrow plot
+#                  [database_name]           : If not given, try to figure out from *.dd file in the current dir
+#
+#end
+
+export SHELL=/bin/ksh
+
+test_arch=$(test_arch 2>/dev/null || echo "unknown")
+
+FLAGS=aA:bBcC:dD:e:f:FhH:i:IkNn:Mo:O:p:P:q:rRs:St:Tv:V:wx:y:Z015
+
+cmd=$(\cd $(dirname $0); echo $(pwd))/$(basename $0)
+
+dcagen=0
+suggest=1
+suggest_arg=""
+clean=0
+dbdir=$(pwd)
+outdir=$(pwd)
+dbname=
+viewname=myview
+export NPES=${NPES:=1}
+export OMP_NUM_THREADS=${OMP_NUM_THREADS:=1}
+memsize=900
+debugger=
+layout=
+f_layout=
+poolmask=""
+append=0
+rad2deg=0
+rad2deg_zeroed=0
+konvert_opt=""
+io_method=5
+trace=0
+trace_arg=""
+plot_immed=1
+#plot_area=-90,-180,90,180
+#plot_proj=CYLINDRICAL
+plot_area=""
+plot_proj=""
+plot_opt=""
+binary=0
+query=""
+query_given=0
+drhookopt=""
+poolmap="/dev/null"
+fast=1
+fastopt=""
+gz=".gz"
+gzopt=""
+bar_onoff="-b"
+warrow=""
+
+tty -s || {
+  export ODB_EDITOR=pipe
+  export ODB_VIEWER_INFORM_PROGRESS=0
+  bar_onoff="-B"
+}
+
+#-- Disable progress bar ? Set the following to 0
+if [[ "$test_arch" = @(nectx) ]] ; then
+  export ODB_EDITOR=pipe
+  export ODB_VIEWER_INFORM_PROGRESS=0
+  bar_onoff="-B"
+fi
+
+export FIRST_TIME=${FIRST_TIME:=1}
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  a)    append=1;;
+  A)    plot_area="$OPTARG";;
+  b)    binary=1;;
+  B)    bar_onoff="-B"; export ODB_VIEWER_INFORM_PROGRESS=0;;
+  c)    clean=1;;
+  C)    export ODB_VIEWER_COLOR_MAP_FILE="$OPTARG";;
+  d)    dcagen=1;;
+  D)	debugger=$OPTARG;;
+  e)	export ODB_EDITOR="$OPTARG";;
+  f)	layout="$OPTARG";;
+  F)	fast=0; fastopt="-F"; gz=""; gzopt="-Z";;
+  h)    abort=yes; break;;
+  H)    drhookopt="$OPTARG";;
+  i)	dbdir="$OPTARG";;
+  I)    plot_immed=0;;
+  k)    rad2deg=2;;
+  n)	export OMP_NUM_THREADS="$OPTARG";; # Note : changed meaning for -n ncpus : ncpus == OpenMP procs
+  N)    export ODB_REPORTER=0;;
+  M)    export ODB_PLOTTER=0;;
+  o)	outdir="$OPTARG";;
+  O)    plot_opt="$plot_opt $OPTARG";;
+  p)    poolmask="$poolmask $OPTARG";;
+  P)    plot_proj=$(echo $OPTARG | perl -pe 'tr/a-z/A-Z/');;
+  q)    suggest=0; query_given=1; query="$OPTARG";;
+  r)    rad2deg=1;;
+  R)    rad2deg=0; rad2deg_zeroed=1;;
+  s)	memsize=$OPTARG;;
+  S)    suggest=0; suggest_arg="-S";;
+  t)	export ODB_XY_COL_T="$OPTARG";;
+  T)    trace=1; trace_arg="-T";;
+  v)	viewname="$OPTARG";;
+  V)    poolmap="$OPTARG";;
+  w)    warrow="w";;
+  x)	export ODB_XY_COL_X="$OPTARG";;
+  y)	export ODB_XY_COL_Y="$OPTARG";;
+  Z)	gz=""; gzopt="-Z";;
+  0)    export ODB_REPORTER=stderr;;
+  1)    export ODB_REPORTER=stdout;;
+  5)    io_method=-1;; # Setting this to a <=0 value will ensure I/O-method 5 will NOT be used
+                       # If > 0, there is an automatic test for READ/ONLY databases, whether ./dca
+                       # directory exists. But keeping I/O-method <= 0 bypasses this testing
+  *)	abort=yes; break;;
+  esac
+done
+
+export ODB_READONLY=${ODB_READONLY:=1}
+
+if [[ "$ODB_EDITOR" = "batch" ]] ; then
+  export ODB_EDITOR=pipe
+fi
+
+if [[ X"${ODB_EDITOR:-}" != Xpipe ]] ; then
+  odb_banner odbviewer 2>/dev/null || :
+  echo "ODB_VERSION=$ODB_VERSION"
+  echo "ODB_SYSPATH=$ODB_SYSPATH"
+  echo "ODB_BINPATH=$ODB_BINPATH"
+  [[ "$ODB_FEBINPATH" = "$ODB_BINPATH" ]] || echo "ODB_FEBINPATH=$ODB_FEBINPATH"
+  [[ "$ODB_BEBINPATH" = "$ODB_BINPATH" ]] || echo "ODB_BEBINPATH=$ODB_BEBINPATH"
+else
+  bar_onoff="-B"
+  export ODB_VIEWER_INFORM_PROGRESS=0
+  plot_immed=0
+  # Avoid "pop-ups" of report window in batch/pipe-mode
+  export DISPLAY=nodisplay:0
+  unset DISPLAY
+fi
+
+if [[ "$bar_onoff" = "-B" ]] ; then
+  bar_onoff_opt="-B"
+else
+  bar_onoff_opt=""
+fi
+
+shift $(expr $OPTIND - 1)
+
+if [[ $# -gt 1 ]] || [[ "$abort" = "yes" ]] ; then
+  awk '/#begin/,/#end/' $cmd | egrep -v '#(begin|end)' | sed 's/^#//'
+  exit 1
+fi
+
+export PWD=$(pwd)
+#echo "dbdir=$dbdir"
+
+cd $dbdir || {
+	echo "***Error: Cannot cd to database directory dbdir='$dbdir'"
+	exit 2
+}
+dbdir=$(pwd)
+
+if [[ $# -eq 0 ]] ; then
+#  dbname=$(basename $PWD | perl -pe 's/^\s*(.*)\..*/\U$1/;')
+  dbname=$(basename "$(\ls -C1 *.dd 2>/dev/null | head -1)" .dd)
+else
+  dbname=$1
+fi
+
+if [[ "$ODB_EDITOR" != "pipe" ]] ; then
+  echo "dbname=$dbname"
+fi
+
+if [[ $clean -eq 1 ]] ; then
+  odbclean -f -c
+fi
+
+#
+# Check for data dictionary file first
+#
+
+ddfile=$dbname.vdd
+if [[ -f $ddfile ]] ; then
+  [[ "$layout" = "@" ]] && layout=
+else
+  ddfile=$dbname.dd
+fi
+
+if [[ ! -f $ddfile ]] ; then
+  echo "***Error: Data dictionary file '$ddfile' not found"
+  exit 3
+fi
+
+if [[ $NPES -ne 1 ]] ; then
+#  echo "***Warning: Sorry, but odbviewer is permanently broken for NPES not equal to 1; NPES reset to 1"
+  export NPES=1
+fi
+
+npools=$(head -5 $ddfile | tail -1)
+[[ $NPES -gt $npools ]] && export NPES=$npools
+
+if [[ -s $ddfile ]] ; then
+  iom=$(head -1 $ddfile | awk 'BEGIN {n=1;} {if (NF >= 3) n=$3;} END {print n;}')
+else
+  iom=1
+fi
+
+#-- Make sure the .odbprune_done file exists; if not, generate it (this should be very quick)
+
+if [[ ! -f $dbdir/.odbprune_done ]] ; then
+  odbprune -i $dbdir >/dev/null 2>&1 || :
+fi
+
+#-- remove possible file (not dir) $dbdir/dca, and if not successful then possible *empty* $dbdir/dca dir
+\rm $dbdir/dca 2>/dev/null || rmdir $dbdir/dca 2>/dev/null || :
+
+export ODB_IO_METHOD=${ODB_IO_METHOD:=$io_method}
+if [[ $io_method -eq 5 && ! -d $dbdir/dca ]] ; then
+#  ODB_IO_METHOD=$iom
+  ODB_IO_METHOD=0 # for now
+fi
+echo "ODB_IO_METHOD=$ODB_IO_METHOD"
+
+#
+# Compile new layout ?
+#
+
+compiled=false
+
+if [[ ! -f $dbname.sch ]] || [[ "$layout" = "@" ]] ; then
+  if [[ -f "$ddfile" ]] ; then
+    dd2ddl $dbname
+    layout=$dbname.ddl
+    compiled=true
+  else
+    echo "***Error: Data dictionary file $ddfile cannot be located"
+    exit 1
+  fi
+fi
+
+if [[ ! -f $dbname.sch ]] ; then
+  if [[ ! -f ${dbname}_H.h ]] && [[ -f ${dbname}.h ]] ; then
+    ln -s ${dbname}.h ${dbname}_H.h
+  fi
+fi
+
+if [[ "$layout" = "" ]] ; then
+  layout=$dbname.sch
+fi
+
+errfile=$(pwd)/__errors__
+rm -f $errfile
+
+if [[ ! -f lib$dbname.a ]] || \
+   [[ ! -f $dbname.ddl_ ]] || \
+   [[ ! -f ${dbname}.h  ]] || \
+   [[ $ODB_FEBINPATH/odb98.x -nt $dbname.ddl_ ]] || \
+   [[ $dbname.ddl -nt $dbname.ddl_ ]] ; then
+  if [[ ! -f $dbname.ddl ]] && [[ "$layout" != "$dbname.ddl" ]] ; then
+    cp -p $layout $dbname.ddl
+    chmod u+w $dbname.ddl
+  fi
+  if [[ $fast -eq 0 ]] ; then
+#  odbcomp $dbname.ddl || exit 1
+    if [[ "$ODB_EDITOR" = "pipe" ]] || [[ "$viewname" = "" ]] ; then
+      subproc=""
+    else
+      subproc="&"
+    fi
+    eval "newodb $dbname || touch $errfile $subproc"
+    if [[ "$ODB_EDITOR" = "pipe" ]] || [[ "$viewname" = "" ]] ; then
+      [[ ! -f $errfile ]] || exit 1
+    fi
+  fi
+  f_layout="-f $dbname.ddl"
+  compiled=true
+fi
+
+if [[ "$ODB_EDITOR" != "pipe" ]] ; then
+  echo "dbdir=$dbdir"
+fi
+
+slash2dot=$(echo $dbdir | sed 's%/%\.%g')
+[[ "$outdir" = "" ]] && outdir=$SCRATCH/my_odb_views/db$slash2dot
+
+if [[ "$ODB_EDITOR" != "pipe" ]] ; then
+  # echo "outdir=$outdir"
+  echo "viewname=$viewname"
+  echo "memsize=$memsize"
+fi
+
+[[ -d $outdir ]] || mkdir -p $outdir
+thisdir=$(pwd)
+cd $outdir || {
+	echo "***Error: Cannot cd to output directory outdir='$outdir'"
+	wait
+	exit 3
+}
+outdir=$(pwd)
+cd $thisdir
+if [[ "$ODB_EDITOR" != "pipe" ]] ; then
+  echo "outdir=$outdir"
+  #echo "Report output directory is $(pwd)"
+fi
+
+#if [[ "$layout" != "" ]] ; then
+#  if [[ -f $dbdir/$dbname.ddl_ ]] ; then
+#    cp $dbdir/$dbname.ddl_ . 2>/dev/null || :
+#    chmod u+w $dbname.ddl_
+#  fi
+#  if [[ -f $dbdir/${dbname}_H.h ]] ; then
+#    cp $dbdir/${dbname}_H.h . 2>/dev/null || :
+#    chmod u+w ${dbname}_H.h
+#  fi
+#  if [[ -f $dbdir/${dbname}.h ]] ; then
+#    cp $dbdir/${dbname}.h . 2>/dev/null || :
+#    chmod u+w ${dbname}.h
+#  fi
+#fi 
+
+export ODB_STATIC_LINKING=${ODB_STATIC_LINKING:=0}
+export ODB_OUTPATH=$outdir
+export ODB_SRCPATH_$dbname=$dbdir
+export ODB_DATAPATH_$dbname=$dbdir
+
+if [[ -f $dbdir/$dbname.IOASSIGN ]] ; then
+  export IOASSIGN=$dbdir/$dbname.IOASSIGN
+elif [[ -f $dbdir/IOASSIGN ]] ; then
+  export IOASSIGN=$dbdir/IOASSIGN
+elif [[ -f $dbdir/IOASSIGN.$dbname ]] ; then
+  export IOASSIGN=$dbdir/IOASSIGN.$dbname
+else
+  echo "***Error: IOASSIGN-file for '$dbname' not present"
+  wait
+  exit 3
+fi
+
+[[ "$debugger" != "" ]] && export NPES=1
+if [[ "$ODB_EDITOR" != "pipe" ]] ; then
+  echo "debugger=$debugger"
+  echo "NPES=$NPES"
+fi
+
+Exe1PE=$ODB_BINPATH/viewer.1.x.blaah
+
+export MP_HOSTFILE=/dev/null
+if [[ $NPES -eq 1 && -x $Exe1PE ]] ; then
+  echo "Using one-PE executable '$Exe1PE'"
+  Exe=$Exe1PE
+else
+  Exe=$ODB_BINPATH/viewer.x
+  if [[ "$ARCH" = "xsgimips" ]] ; then
+    Exe="mpirun -np $NPES $Exe"
+    export MPI_BUFS_PER_PROC=256
+    export MPL_MBX_SIZE=$(((MPI_BUFS_PER_PROC+16)*16*1024))
+    export MPI_NAP=yes
+  elif [[ "$test_arch" = @(linux|aix|solaris|cygwin|nec*|cray_*) ]] ; then
+    Exe=$outdir/user_viewer.x
+    if [[ $NPES -gt 1 ]] ; then
+      export MPL_MBX_SIZE=64000000
+      export MP_PROCS=$NPES
+      export MP_SHARED_MEMORY=yes
+      export MP_WAIT_MODE=poll
+      export OMP_NUM_THREADS=${OMP_NUM_THREADS:=1}
+      export XLSMPOPTS="parthds=:stack=50000000 : spins=500000 : yields=50000"
+      export _RLD_ARGS="-log /dev/null"
+      export MP_COREFILE_FORMAT=STDERR
+      export MP_HOSTFILE=$outdir/node_file.$NPES
+      echo "$NPES $(hostname)" | awk '{for(i=1;i<=$1;i++) print $2;}' > $MP_HOSTFILE
+      printenv | egrep ^MP_
+      ls -ltr $MP_HOSTFILE
+#      cat $MP_HOSTFILE
+    fi
+    obj=Viewer.o
+    if [[ $fast -eq 0 ]] ; then
+      if [[ ! -f $obj ]] || [[ $ODB_LIBPATH/libodbmain.a -nt $obj ]] ; then
+        $ODB_AR xv $ODB_LIBPATH/libodbmain.a $obj || {
+          obj=viewer.o
+          $ODB_AR xv $ODB_LIBPATH/libodbmain.a $obj || {
+            echo "***Error: Unable to extract viewer's main object from $ODB_LIBPATH/libodbmain.a"
+	    wait
+            exit 1
+          }
+        }
+      fi
+    fi
+#    if [[ $NPES -eq 1 ]] ; then
+#      ODB_F90=$(echo $ODB_F90 | sed 's/mpxlf/xlf/')
+#    else
+#      ODB_F90=$(echo $ODB_F90 | sed 's/\bxlf/mpxlf/')
+#    fi
+    if [[ "$viewname" = "" ]] ; then
+      defview=myview
+    else
+      defview=$viewname
+    fi
+    defpoolno=$(echo $defview | awk -F/ '{print $2}')
+    if [[ "$defpoolno" = "" ]] ; then
+      defpoolno=-1
+    fi
+    [[ $FIRST_TIME -gt 1 ]] || {
+      rm -f __input__
+      cat /dev/null > __input__
+    }
+    if [[ "$ODB_EDITOR" != pipe ]] ; then
+      if [[ $FIRST_TIME -gt 1 ]] || [[ "$viewname" = "" ]] ; then
+        repeat=0
+        while [[ $repeat -lt 1 ]]
+        do
+          echo "Enter new view name ($defview) ["." to exit] : "
+          read viewname || exit 0   # EOF (or some other error, which we ignore)
+          viewname=$(echo "$viewname" | perl -pe 's/^\s*//')
+          first=$(echo "$viewname" | cut -c1)
+          eqs=$(echo "$viewname" | perl -pe 's/^\w+\s*=.*/=/' | cut -c1)
+          if [[ "$viewname" = "" ]] ; then
+            viewname=$defview
+            ((repeat+=1))
+          elif [[ "$viewname" = "." ]] ; then
+            rm -f __input__
+            exit 0
+          elif [[ "$viewname" = "?" ]] ; then
+            pwd; ls -ltr *.sql
+          elif [[ "$first" = '!' ]] ; then
+            viewname=$(echo "$viewname" | cut -c2-)
+            [[ "$viewname" = "" ]] || eval "echo $viewname"
+          elif [[ "$first" = "\$" ]] || [[ "$eqs" = "=" ]] ; then
+            echo "$viewname" >> __input__
+          else
+            ((repeat+=1))
+          fi
+        done
+      fi
+    else
+      viewname=$defview
+    fi
+    ((FIRST_TIME+=1))
+    poolno=$(echo $viewname | awk -F/ '{print $2}')
+    if [[ "$poolno" = "" ]] ; then
+      poolno=$defpoolno
+    fi
+    suffix=$(echo $viewname | awk -F/ '{print $1}' | perl -ne 'print $1 if (/.*(\.\w+)/);')
+    viewname=$(echo $viewname | awk -F/ '{print $1}' | sed 's/\..*//')
+
+    is_table=$(echo $viewname | perl -ne 'if (m/^\@/) {print 1;} else {print 0;}')
+    if [[ $is_table -eq 1 ]] ; then
+      sqlfile=/dev/null
+    else
+      sqlfile=$viewname.sql
+    fi
+    if [[ $suggest -eq 1 && ! -f $sqlfile ]] ; then
+      cat > $sqlfile <<EOF
+CREATE VIEW $viewname AS
+    SELECT lat, lon
+//UNIQUEBY ?column_names?
+      FROM hdr
+//   WHERE ?condition?
+// ORDERBY ?column_names?
+;
+EOF
+    fi
+
+    libfile=$(pwd)/lib$dbname.a
+
+    if [[ "$suffix" != ".so" ]] || \
+       [[ $compiled = true   ]] ; then
+      was_so=0
+    else
+      was_so=1
+      testobj=$($ODB_AR t $libfile ${dbname}_$viewname.o 2>/dev/null || :)
+      if [[ "$testobj" != "${dbname}_$viewname.o" ]] ; then
+	was_so=0
+      fi
+    fi
+
+    if [[ $was_so -eq 0 ]] ; then
+      if [[ $is_table -eq 0 && "$ODB_EDITOR" != "pipe" && $query_given -eq 0 ]] ; then
+        $ODB_EDITOR $sqlfile
+      elif [[ $query_given -eq 1 ]] ; then
+        echo "$query ;" > $sqlfile
+      fi
+    fi
+
+    wait
+    [[ ! -f $errfile ]] || {
+      echo "***Error: Data layout compilation had previously failed"
+      exit 1
+    }
+
+    if [[ $fast -eq 0 && ! -f $libfile ]] ; then
+      echo "***Error: Unable to locate database library $libfile"
+      wait
+      exit 1
+    fi
+
+    if [[ $fast -eq 0 ]] ; then
+      if [[ $is_table -eq 0 && $was_so -eq 0 ]] ; then
+        odbcomp -w -l $dbname $sqlfile || exit 1
+      fi
+    fi
+
+    if [[ $is_table -eq 1 ]] ; then
+      export ODB_CONSIDER_TABLES=$(echo $viewname | perl -pe 's#\@(\w+)#/\L$1/#')
+    elif [[ -f ${dbname}_$viewname.c ]] ; then
+      # the following hassle defines you the ODB_CONSIDER_TABLES
+      eval `fgrep '#define ODB_CONSIDER_TABLES' ${dbname}_$viewname.c | awk '{print "export",$2"="$3}'`
+    else
+      export ODB_CONSIDER_TABLES='*'
+    fi
+    ODB_CONSIDER_TABLES=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 'tr/A-Z/a-z/')
+    if [[ $fast -eq 0 ]] ; then
+      echo "==> ODB_CONSIDER_TABLES=$ODB_CONSIDER_TABLES"
+    fi
+
+    if [[ ! -d $dbdir/dca ]] ; then
+      dcagen=1
+    fi
+
+    if [[ $dcagen -eq 1 ]] ; then
+      if [[ "$ODB_CONSIDER_TABLES" = '*' ]] ; then
+        tables=""
+      else
+        tables=$(echo "$ODB_CONSIDER_TABLES" | perl -pe 's#/(\w+)# -t $1#g; s#/##g;')
+      fi
+      [[ ! -d $dbdir/dca ]] || mkdir $dbdir/dca
+      # dcagen -q -l $dbname $tables -F -n &
+      #-- Make for all tables, otherwise next time could be a problem
+      thisdir=$(pwd)
+      cd $dbdir
+      echo "Generating direct column access -indices. This may take a while ..."
+      dcagen -q -z -l $dbname -F -n &
+      cd $thisdir
+    elif [[ $ODB_IO_METHOD -eq 5 && -d $dbdir/dca ]] ; then 
+      # apply DCA-fix, if applicable
+      # echo "***Warning: Fixing DCA (where applicable)"
+      [[ $dcagen -ne 1 ]] || wait
+      dcafix -q $dbdir/dca/*.dca 2>/dev/null &
+    fi
+
+    if [[ $fast -eq 0 ]] ; then
+      if [[ ! -x $Exe ]] || [[ $libfile -nt $Exe ]] ; then
+        tmpExe="$Exe"
+        if [[ "$test_arch" = @(cray_*) ]] ; then
+          devshm=/dev/shm
+          if [[ -d $devshm ]] ; then
+            capakb=$(df -kl $devshm 2>/dev/null | tail -1 | awk '{print $4}')
+            if [[ $capakb -gt 40960 ]] ; then # more than 40MBytes
+              [[ -d $devshm/$USER ]] || mkdir -p $devshm/$USER
+              tmpExe=$devshm/$USER/$(basename $Exe)
+            fi
+          fi
+        fi
+        if [[ $NPES -gt 1 ]] ; then
+          odbf90mp -o $tmpExe $obj $ODB_LIB -L. -l$dbname || exit 1
+        else
+          odbf90 -o $tmpExe $obj $ODB_LIB -L. -l$dbname || exit 1
+        fi
+        if [[ "$tmpExe" != "$Exe" ]] ; then
+          \mv -f $tmpExe $Exe
+        fi
+      fi
+    fi
+
+    wait
+
+    if [[ $is_table -eq 1 ]] ; then
+      viewname="$viewname/$poolno"
+    else
+      viewname="$viewname.so/$poolno"
+    fi
+#    if [[ "$poolno" != "-1" ]] ; then
+      export ODB_PERMANENT_POOLMASK="$poolno"
+#    fi
+  fi
+fi
+
+#-- Check the need for (lat,lon) radians->degrees conversion
+kopt=""
+if [[ $fast -eq 0 ]] ; then
+  export ODB_LATLON_RAD=${ODB_LATLON_RAD:=$($ODB_FEBINPATH/latlon_rad || echo "-1")}
+else
+  export ODB_LATLON_RAD=${ODB_LATLON_RAD:="-1"}
+  if [[ $rad2deg -eq 2 ]] ; then
+    konvert_opt="-k"
+    kopt="-k"
+  fi
+fi
+
+if [[ $ODB_LATLON_RAD -eq 0 ]] ; then
+  # (lat,lon) appear already to be in degrees
+  export ODB_VIEWER_RAD2DEG=0
+elif [[ $ODB_LATLON_RAD -eq 1 ]] ; then
+  # (lat,lon) appear to be in radians
+  if [[ $rad2deg -eq 2 ]] ; then # -k command line flag was used : plot & text (lat,lon) will be in degrees
+    export ODB_VIEWER_RAD2DEG=2
+    konvert_opt="-k"
+    kopt="-k"
+  else
+    export ODB_VIEWER_RAD2DEG=1
+  fi
+else # Anything else 
+#-- Automagic radians to degree conversion needed for coverage plots ?
+  if [[ $rad2deg_zeroed -eq 1 ]] ; then # -R used ==> overrides everything in 1st place
+    export ODB_VIEWER_RAD2DEG=0
+    konvert_opt="-R"
+    kopt=""
+  elif [[ $rad2deg -eq 0 ]] ; then
+    if [[ "$ODB_VIEWER_RAD2DEG" = "" ]] ; then
+      if [[ "$dbname" = "ECMA" || \
+            "$dbname" = "CCMA" || \
+            "$dbname" = "ECMASCR" ]] ; then
+        export ODB_VIEWER_RAD2DEG=1
+      fi
+    fi
+  elif [[ $rad2deg -eq 2 ]] ; then # -k command line flag was used : plot & text (lat,lon) will be in degrees
+    export ODB_VIEWER_RAD2DEG=2
+    konvert_opt="-k"
+    kopt="-k"
+  else # -r command line flag was used ==> overrides everything
+    export ODB_VIEWER_RAD2DEG=1
+    konvert_opt="-r"
+    kopt=""
+  fi
+fi
+
+#-- Poolmask
+if [[ "$poolmask" != "" ]] ; then
+  poolmask=$(echo $poolmask | perl -pe 's/^\s+//; s/\s+$//; s/\s+/,/g')
+  export ODB_PERMANENT_POOLMASK="$poolmask"
+  echo "==> Using only pools : $ODB_PERMANENT_POOLMASK"
+  poolmask_arg="-p $poolmask"
+else
+  poolmask_arg=""
+fi
+
+#-- Append (lat,lon)'s to the end of existing plotfile ?
+export ODB_VIEWER_PLOTFILE_APPEND=$append
+
+#-- Plot immediately ?
+export ODB_PLOTTER=${ODB_PLOTTER:=0}
+if [[ $plot_immed -eq 1 ]] ; then # Essentially: Add the -s(how) option to plotobs.x
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed 's/ -b/ -s -b/')
+fi
+
+if [[ "$ODB_EDITOR" = "pipe" ]] ; then # strip out the possible -s from pipe/batch mode
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | perl -pe 's/-s\b//g')
+fi
+
+if [[ "$plot_area" != "" ]] ; then
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ -a'$plot_area' -b/")
+fi
+
+if [[ "$plot_proj" != "" ]] ; then
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ -p$plot_proj -b/")
+fi
+
+if [[ "$plot_opt" != "" ]] ; then
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ $plot_opt -b/")
+fi
+
+if [[ "$warrow" = "w" ]] ; then
+  export ODB_PLOTTER=$(echo $ODB_PLOTTER | sed "s/ -b/ -W -b/")
+fi
+
+if [[ "$ODB_VIEWER_COLOR_MAP_FILE" != "" ]] ; then
+# Color map file MUST have a suffix ".cmap"
+  ODB_VIEWER_COLOR_MAP_FILE="$(dirname $ODB_VIEWER_COLOR_MAP_FILE)/$(basename $ODB_VIEWER_COLOR_MAP_FILE .cmap).cmap"
+  if [[ ! -f $ODB_VIEWER_COLOR_MAP_FILE ]] ; then
+    tmp=$(basename $ODB_VIEWER_COLOR_MAP_FILE)
+    if [[ -f $ODB_SYSPATH/$tmp ]] ; then
+      export ODB_VIEWER_COLOR_MAP_FILE=$ODB_SYSPATH/$tmp
+    fi
+  fi
+  if [[ ! -f $ODB_VIEWER_COLOR_MAP_FILE ]] ; then
+    echo "***Warning: Cannot locate color map file '$ODB_VIEWER_COLOR_MAP_FILE'"
+    unset ODB_VIEWER_COLOR_MAP_FILE
+  else
+    echo "*** Using color map file '$ODB_VIEWER_COLOR_MAP_FILE'"
+  fi
+fi
+
+[[ "$ODB_GHOSTVIEW" = "" ]] && export ODB_GHOSTVIEW="ghostview -land"
+
+#[[ "$ODB_BINARY_CHUNKSIZE" = "" ]] && export ODB_BINARY_CHUNKSIZE=0
+[[ "$OMP_NUM_THREADS" = "" ]] && export OMP_NUM_THREADS=1
+
+ncpus=$OMP_NUM_THREADS
+OMP_NUM_THREADS=$(echo "$OMP_NUM_THREADS" | perl -pe 's/^(\d+).*/$1/')
+
+size=$((memsize*1024))
+#echo "memsize=${memsize}MBytes, size=${size}KBytes"
+ulimit -c 0 2>/dev/null || :
+#-- commented out since on some (linux) systems cause serious problems
+#ulimit -d $size || :
+#ulimit -s $size || :
+#ulimit -m $size || :
+[[ "$test_arch" = @(linux|aix|solaris|nec*|cray_*) ]] || ulimit -v $size 2>/dev/null || :
+if [[ $fast -eq 0 && "$ODB_EDITOR" != "pipe" ]] ; then
+  if [[ "$test_arch" = @(linux|aix|solaris|cygwin|nectx|cray_*) ]] ; then
+    ulimit -a 2>/dev/null || :
+  else
+    limit 2>/dev/null || :
+  fi
+fi
+
+export ODB_RLDPATH="$dbdir:${ODB_RLDPATH}"
+#export ODB_COMPILER="$ODB_COMPILER -v"
+
+if [[ $trace -eq 1 ]] ; then
+  export ODB_TRACE_PROC=-1
+  tracename=$(echo $viewname | sed 's#/.*##; s#\..*##')
+  export ODB_TRACE_FILE=$tracename.%d
+  export ODB_TRACE_FLUSH_FREQ=1000
+  echo "***Warning: ODB-tracing is ON and goes to file(s) $ODB_TRACE_FILE"
+fi
+
+#printenv | grep ^ODB_ | sort
+
+if [[ "$ARCH" = "hppa" ]] ; then
+  rm -f ftn00 || :
+  ln -s /dev/tty ftn00 || :
+fi
+
+cd $outdir || {
+	echo "***Error: Cannot cd to output directory outdir='$outdir'"
+	wait
+	exit 3
+}
+
+abort=no
+if [[ $fast -eq 1 ]] ; then
+  #-- This uses the new fast odbsql for fetching data & doing the plotting
+
+  vw=$(echo $viewname | sed 's/\..*//')
+
+  #-- Generating report  
+  if [[ "$ODB_REPORTER" != "0" ]] ; then
+    add="$kopt $bar_onoff -o $vw.rpt"
+    if [[ X"${DISPLAY:-}" != X ]] ; then
+      add="$add -X" # Means here: report window will be created
+    fi
+    if [[ "$debugger" = "" ]] ; then
+      $ODB_BINPATH/odbsql -v $vw.sql -f odb -i $dbdir/$dbname.sch -n $ncpus $poolmask_arg $add || touch $errfile &
+    else
+      $ODB_BINPATH/odbsql -v $vw.sql -f odb -i $dbdir/$dbname.sch $poolmask_arg $add -D $debugger
+      exit 1
+    fi
+  fi
+
+  #-- Generating plot
+  if [[ "$ODB_ARCH" = "nectx" ]] ; then
+    export ODB_PLOTTER=0 # for now
+  fi
+
+  if [[ "$ODB_PLOTTER" != "0" ]] ; then
+    add="$kopt -o $vw.obs$gz"
+    if [[ X"${ODB_VIEWER_COLOR_MAP_FILE:-}" != X ]] ; then
+      if [[ -f "${ODB_VIEWER_COLOR_MAP_FILE}" ]] ; then
+        add="$add -C ${ODB_VIEWER_COLOR_MAP_FILE}"
+      fi
+    fi
+    if [[ $plot_immed -eq 1 ]] ; then
+      add="$add -X"  # Means here: plot immediately --> $DISPLAY-screen
+    fi
+
+    if [[ "$ODB_REPORTER" != "0" ]] ; then
+      sleep 1 # Delay start i.e. favoring the report generator over plotting
+      add="$add -B"
+    else
+      add="$add $bar_onoff" # Enable progress bar, unless -B given (or -e batch|pipe)
+    fi
+    if [[ "$debugger" = "" ]] ; then
+      $ODB_BINPATH/odbsql -v $vw.sql -f ${warrow}plotobs -i $dbdir/$dbname.sch $poolmask_arg $add || touch $errfile &
+    else
+      $ODB_BINPATH/odbsql -v $vw.sql -f ${warrow}plotobs -i $dbdir/$dbname.sch $poolmask_arg $add -D $debugger
+      exit 2
+    fi
+  fi
+
+  wait 
+  if [[ ! -f $errfile && "$ODB_EDITOR" != "pipe" ]] ; then
+    exec $cmd -i $dbdir -o $outdir -v $vw.sql -n $ncpus -s $memsize -V $poolmap \
+         $f_layout $poolmask_arg $suggest_arg $trace_arg $konvert_opt \
+         $fastopt $bar_onoff_opt $gzopt $dbname
+  fi
+elif [[ "$debugger" = "" ]] ; then
+   export ODB_WILL_PAUSE=0
+   if [[ $NPES -gt 1 ]] ; then
+     if [[ "$test_arch" = @(linux|solaris|cygwin|nectx|cray_*) ]] ; then
+       Exe="mpirun.linux -np $NPES $Exe"
+     fi
+   else
+     if [[ "$test_arch" = @(cray_*) ]] ; then
+       Exe="mpirun.linux -np $NPES $Exe"
+     fi
+   fi
+   rm -f $errfile
+   cat __input__ > __real_input__ 2>/dev/null || :
+   echo "$viewname" >> __real_input__
+   if [[ "$drhookopt" != "" ]] ; then
+     export DR_HOOK=true
+     export DR_HOOK_OPT="$drhookopt"
+   fi
+   do_cmd="$Exe $dbname . $viewname $poolmap"
+   if [[ "$ODB_ARCH" = "nectx" ]] ; then
+     jobname=$(echo "$viewname" | sed 's|[./].*||')
+     cat <<EOF | odbqsub -N $jobname || touch $errfile
+export ODB_VIEWER_INFORM_PROGRESS=0
+export ODB_EDITOR=pipe
+rm -f $errfile
+$do_cmd < __real_input__ || touch $errfile
+[[ ! -f $errfile ]] || exit 1
+[[ __real_input__ -nt $jobname.rpt ]] || head -15 $jobname.rpt || :
+EOF
+   else  
+     env ODB_EDITOR=pipe $do_cmd < __real_input__ || touch $errfile
+   fi
+#   pid=$!
+#   trap "sleep 2; kill $pid" 1 2 3 15
+#   wait $pid   
+   rm -f $MP_HOSTFILE 2>/dev/null
+   if [[ ! -f $errfile && "$ODB_EDITOR" != "pipe" ]] ; then
+     rm -f __real_input__
+     if [[ $was_so -eq 0 ]] ; then
+       viewname=$(echo $viewname | sed 's/\.so//')
+     fi
+     exec $cmd -i $dbdir -o $outdir -v $viewname -n $ncpus -s $memsize -V $poolmap \
+          $f_layout $poolmask_arg $suggest_arg $trace_arg $konvert_opt \
+          $fastopt $bar_onoff_opt $gzopt $dbname
+   fi
+# else
+#   $Exe $dbname . $viewname $poolmap || abort=yes
+# fi
+else
+  export ODB_ERRTRA=0
+  echo "Using debugger '$debugger'"
+  echo 'Use the following arguments: '$dbname' . " " '"$viewname $poolmap"
+  $debugger $Exe
+fi
+
+rm -f  __input__
+
+rm -f $MP_HOSTFILE 2>/dev/null
+
+if [[ "$abort" = "yes" ]] ; then
+  if [[ -f RecoverY && "$ODB_EDITOR" != "pipe" ]] ; then
+    viewname=$(head -1 RecoverY | sed 's/ //g')
+    exec $cmd -i $dbdir -o $outdir -v $viewname -n $ncpus -s $memsize -V $poolmap \
+         $f_layout $poolmask_arg $suggest_arg $trace_arg \
+         $fastopt $bar_onoff_opt $gzopt $dbname
+  else
+    echo "***Error: Cannot automatically recover from error(s)"
+    exit 1
+  fi
+fi
+
+exit 0
diff --git a/odb/src/scripts/odbvlink b/odb/src/scripts/odbvlink
new file mode 100755
index 0000000..e647129
--- /dev/null
+++ b/odb/src/scripts/odbvlink
@@ -0,0 +1,110 @@
+#!/bin/csh -f
+#
+# A script to create shareable view objects out of permanent view objects
+# stored in $ODB_LIBPATH/lib<dbname>.a.
+#
+# By supplying optional arguments, the specific view(s) can be extracted.
+#
+# Assumes that both ODB_SYSPATH and ODB_LIBPATH exist.
+#
+# Objects are created into the current directory.
+#
+# Usage: odbvlink DATABASE_NAME [view_name(s)]
+#
+# Author: Sami Saarinen, ECMWF, 1998-99
+#
+
+if ( $#argv < 1 ) then
+  echo "Usage: odbvlink DATABASE_NAME [view_name(s)]"
+  exit 1
+endif
+
+set dbname=$1
+
+if ( $#argv > 1 ) then
+  shift
+  set views="$*"
+  set views=`echo $views | sed 's/ /,/g'`
+else
+  set views=""
+endif
+
+
+set rc=0
+if ( $?ODB_LIBPATH == 0) then
+  echo "*** Error: ODB_LIBPATH must be defined"
+  @ rc++
+endif
+
+if ( ! -f $ODB_LIBPATH/lib${dbname}.a ) then
+  echo "*** Error: No such library file '$ODB_LIBPATH/lib${dbname}.a'"
+  @ rc++
+endif
+
+if ( ! -f $ODB_SYSPATH/${dbname}.so ) then
+  echo "*** Error: No such shareable object '$ODB_SYSPATH/${dbname}.so'"
+  @ rc++
+endif
+
+if ( $rc > 0 ) exit $rc
+
+set this=`pwd`
+
+if ( $?SCRATCHDIR != 0 ) then
+  set tmpdir=$SCRATCHDIR
+else if ( $?SCRATCH != 0 ) then
+  set tmpdir=$SCRATCH
+else if ( $?TMPDIR != 0 ) then
+  set tmpdir=$TMPDIR
+else
+  set tmpdir=/tmp
+endif
+
+set tmpdir=$tmpdir/tmp.$$
+mkdir -p $tmpdir || exit 3
+cd $tmpdir
+
+echo Extracting VIEW-specific object files from \$ODB_LIBPATH/lib${dbname}.a ...
+ar  x $ODB_LIBPATH/lib${dbname}.a
+rm -f ${dbname}_T_*.o
+rm -f ${dbname}_Sstatic.o
+
+if ( "$views" == "" ) then
+  set scanviews=`ls ${dbname}_[a-z]*.o`
+else
+  cp $this/${dbname}_{$views}.o . || :
+  set scanviews=`ls ${dbname}_{$views}.o`
+endif
+
+set rctot=0
+set files=""
+
+foreach o ( $scanviews )
+  set obj=`basename $o .o`
+  set sofile=$this/${obj}.so
+  rm -f $sofile
+  set rc=0
+  echo ${ODB_LD} ${obj}.o \$ODB_SYSPATH/${dbname}.so -o $sofile
+       ${ODB_LD} ${obj}.o  $ODB_SYSPATH/${dbname}.so -o $sofile || set $rc=$status
+  if ( $rc != 0 ) then
+    echo "*** Error: Shareable object '$sofile' creation failed"
+    rm -f $sofile
+    @ rctot++
+  else
+    set name=`echo $obj | sed 's/^'$dbname'_//'`
+    if ( "$files" != "" ) then
+      set files="${files},$name"
+    else
+      set files="$name"
+    endif
+  endif
+end
+
+cd $this
+rm -rf $tmpdir
+
+if ( "$files" != "" ) then
+  ls -ltr ${dbname}_{$files}.so
+endif
+
+exit $rctot
diff --git a/odb/src/scripts/odbxyplot b/odb/src/scripts/odbxyplot
new file mode 100755
index 0000000..e76f3a6
--- /dev/null
+++ b/odb/src/scripts/odbxyplot
@@ -0,0 +1,185 @@
+#!/bin/ksh
+#
+# A script to create XY-plot using GNUplot from a given report-file
+# and across two columns
+#
+#
+# Usage:  odbxyplot [-x column#1]    : X-coordinate  : default = 1
+#                   [-y column#2]    : Y-coordinate  : default = 2
+#                   [-t column#2]    : time-coordinate  : default = 0
+#                   [-d device]      : Output device : default = x11
+#                   [-o output_file] : Output file (if not device x11)
+#                   [-v]             : verbose       : default = noverbose
+#                   [-O GNUplot_options] : default = no extra options
+#                   [-i input_file]  : Input file
+#                   [input_file]
+#
+#
+
+set -eu
+
+usage1="odb_xyplot [-v] [-x col#x] [-y col#y] [-t col#time]"
+usage2="           [-d device] [-o output] [-O options] [-i input_file] [input_file]"
+
+FLAGS=x:y:t:d:o:i:vO:
+
+cx=1
+cy=2
+ct=0
+device=x11
+output=
+input=
+verbose=0
+options=
+
+abort=no
+while getopts ${FLAGS} i
+do
+  case $i in
+  x)	cx="$OPTARG";;
+  y)	cy="$OPTARG";;
+  t)	ct="$OPTARG";;
+  d)	device="$OPTARG";;
+  o)	output="$OPTARG";;
+  i)	input="$OPTARG";;
+  v)	verbose=1;;
+  O)	options="$OPTARG";;
+  *)    abort=yes; break;;
+  esac
+done
+
+shift $(expr $OPTIND - 1)
+
+[[ $# -ne 1 ]] || input=$1
+
+[[ "$input" != "" ]] || abort=yes
+
+gnuplot=$(whence gnuplot 2>/dev/null || echo "")
+
+if [[ "$gnuplot" = "" ]] ; then
+  echo "***Error: gnuplot not installed" >&2
+  abort=yes
+elif [[ ! -x "$gnuplot" ]] ; then
+  echo "***Error: Unable to execute gnuplot" >&2
+  abort=yes
+fi
+
+if [[ $# -gt 1 ]] || [[ "$abort" = "yes" ]] ; then
+  echo "$usage1" >&2 
+  echo "$usage2" >&2 
+  exit 1
+fi
+
+device=$(echo "$device" | perl -pe 'tr/A-Z/a-z/')
+
+test_arch=$(test_arch 2>/dev/null || echo "$ARCH")
+if [[ "$test_arch" = linux && -d /dev/shm ]] ; then
+  export TMPDIR=${TMPDIR:=/dev/shm}
+else
+  export TMPDIR=${TMPDIR:=/tmp}
+fi
+tmpfile=$TMPDIR/odb_xyplot.$$
+
+nx=$(expr $cx + 1)
+cat > $tmpfile << EOF
+(n == 1) { print \$$nx; n++; }
+/^: Pool#/ { n++; }
+EOF
+xlabel=$(awk -f $tmpfile < $input)
+
+ny=$(expr $cy + 1)
+cat > $tmpfile << EOF
+(n == 1) { print \$$ny; n++; }
+/^: Pool#/ { n++; }
+EOF
+ylabel=$(awk -f $tmpfile < $input)
+
+if [[ "$ct" -gt 0 ]] ; then
+  nt=$(expr $ct + 1)
+  cat > $tmpfile << EOF
+  (n == 1) { print \$$nt; n++; }
+  /^: Pool#/ { n++; }
+EOF
+  tlabel=$(awk -f $tmpfile < $input)
+  [[ "$tlabel" = "time" ]] || ct=0
+else
+  ct=0
+  tlabel=0
+fi
+
+[[ "$tlabel" != "time" ]] || xlabel="$xlabel & $tlabel"
+
+echo "# Input file for GNUplot on $(date)" > $tmpfile
+if [[ "$device" != "x11" ]] ; then
+   if [[ "$output" = "" ]] ; then
+     if [[ "$device" = "eps" ]] ; then
+       output=$(basename ${input}.eps)
+     elif [[ "$device" =  "ps" ]] ; then
+       output=$(basename ${input}.ps)
+     fi
+   fi
+   [[ "$output" = "" ]] || echo "set output '$output'" >> $tmpfile
+   if [[ "$device" = "eps" ]] ; then
+     echo "set terminal postscript eps 'Courier' 18" >> $tmpfile
+   elif [[ "$device" =  "ps" ]] ; then
+#     echo "set terminal postscript default" >> $tmpfile
+     echo "set terminal postscript" >> $tmpfile
+   fi
+else
+  echo "set terminal x11" >> $tmpfile
+fi
+
+binput=$(basename $input)
+
+echo "set nokey" >> $tmpfile
+echo "set time ,2" >> $tmpfile
+echo "set xlabel '$xlabel'" >> $tmpfile
+echo "set ylabel '$ylabel'" >> $tmpfile
+echo "set title 'File=$binput  :  $ylabel  =  F ( $xlabel )'" >> $tmpfile
+
+[[ "$options" = "" ]] || echo "$options" >> $tmpfile
+
+if [[ "$ct" -eq 0 ]] ; then
+  echo 'plot "'"< egrep -v ^: $input | egrep -v NULL | awk '{print "'$'$cx',$'$cy"}'"' | sort -n" with linespoints' >> $tmpfile
+else
+  echo 'plot "'"< egrep -v ^: $input | egrep -v NULL | awk '{print "'$'$cx',$'$ct',$'$cy"}'"' | dtfilt.x | sort -n" with linespoints' >> $tmpfile
+fi
+
+if [[ "$device" = "x11" ]] ; then
+  echo 'pause -1' >> $tmpfile
+elif [[ "$device" = "eps" ]] || [[ "$device" =  "ps" ]] ; then
+  gv=$(whence ghostview 2>/dev/null || echo "")
+  gvopt="-land"
+  if [[ "$gv" = "" ]] ; then
+    gv=$(whence gv 2>/dev/null || echo "")
+    gvopt=""
+  fi
+  if [[ "$gv" != "" && -x "$gv" ]] ; then
+    echo '!'"$gv $gvopt $output" >> $tmpfile
+  else
+    echo '!'"echo 'Neither ghostview nor gv found. Check your installation'" >> $tmpfile
+  fi
+fi
+
+[[ $verbose -ne 1 ]] || cat $tmpfile >&2
+
+rc=0
+if [[ "$device" = "x11" ]] ; then
+#  xterm +ls -geometry 30x0 -title "Quit Me" -e $gnuplot $tmpfile || rc=1
+# Thanx to Shinya Kobayashi/17-May-2006
+  $gnuplot -persist $tmpfile || rc=1
+elif [[ "$device" = "eps" ]] || [[ "$device" =  "ps" ]] ; then
+  rm -f $output
+  $gnuplot $tmpfile >/dev/null 2>&1 || {
+    echo "***Error in gnuplot (device=$device); The file is as follows:" >&2
+    cat $tmpfile >&2
+    echo "A hint: Check that your data does not contain missin data (NULL) or string data" >&2
+    rc=1
+  }
+else
+  echo "***Error: Unsupported device '$device'" >&2
+  rc=1
+fi
+
+rm -f $tmpfile
+exit $rc
diff --git a/odb/src/scripts/run_viewer b/odb/src/scripts/run_viewer
new file mode 100755
index 0000000..0b35fe6
--- /dev/null
+++ b/odb/src/scripts/run_viewer
@@ -0,0 +1,127 @@
+#!/bin/csh -f
+
+if ( $#argv < 3 || $#argv > 4 ) then
+  echo "Usage: $0 dbname qualifier dbdir [viewname]"
+  exit 1
+endif
+
+unlimit
+limit core 0
+
+setenv PWD `pwd`
+
+set this=$PWD
+
+set dbname=$1
+set qualinp=$2
+set qual=${dbname}_$2
+set dbdir=$3
+
+if ( ! -d $dbdir ) then
+  echo "*** Error: Database directory '$dbdir' not found"
+  exit 1
+endif
+
+if ( $#argv == 4 ) then
+  set viewname=$4
+else
+  set viewname=
+endif
+
+set slash2dot=`echo $dbdir | sed 's%/%\.%g'`
+set outdir=$SCRATCH/My_ODB_Views/db$slash2dot
+
+if ( ! -d $outdir ) then
+  mkdir -p $outdir
+endif
+
+cd $outdir
+pwd
+
+#setenv ODB_LIBS "/home/rd/mps/src/odb/lib/libodb_sgimips.a -L/home/rd/mps/lib/SGIN32/19r1 -lnewcmaio -lioassign -lpcma -lutil"
+
+setenv ODB_SRCPATH_$dbname  $outdir
+setenv ODB_SRCPATH          $outdir
+setenv ODB_DATAPATH_$dbname $dbdir
+#setenv ODB_COMPILER "/home/rd/mps/src/odb/compiler/odb98_sgimips.x -Vd -O0"
+setenv ODB_COMPILER "/home/rd/mps/src/odb/compiler/odb98_sgimips.x -Vd"
+#setenv ODB_COMPILER "dbx /home/rd/mps/src/odb/compiler/odb98_sgimips.x -Vd"
+setenv ODB_SYSPATH  /home/rd/mps/src/odb/include
+
+if ( $?ODB_EDITOR == 0 ) setenv ODB_EDITOR    emacs
+#setenv ODB_REPORTER  /home/rd/mps/bin/b2
+setenv ODB_REPORTER  /home/rd/mps/bin/b3
+#setenv ODB_REPORTER  /home/rd/mps/src/X-Designer/xt/b3
+setenv ODB_PLOTTER   /home/rd/mps/bin/plotobs.x
+
+setenv ODB_SETUP_FILE /dev/null
+
+set setup_found=0
+if ( -f $dbdir/$dbname.setup ) then
+  ln -s $dbdir/$dbname.setup .
+  set setup_found=1
+else if ( -f $ODB_SYSPATH/$dbname.setup ) then
+  ln -s $ODB_SYSPATH/$dbname.setup .
+  set setup_found=1
+endif
+
+if ( $setup_found == 1) then
+  setenv IOASSIGN $outdir/IOASSIGN
+  if ( -f $IOASSIGN ) then
+    rm -f $IOASSIGN
+  endif
+  source $dbname.setup
+else if ( -f $ODB_SYSPATH/IOASSIGN.$qual ) then
+  setenv IOASSIGN $ODB_SYSPATH/IOASSIGN.$qual
+else
+  echo "*** Error: Setup file and/or qualified IOASSIGN-file not present"
+  exit 2
+endif
+
+#unsetenv ODB_LIBS
+printenv | grep ODB_
+cat $IOASSIGN
+
+foreach f ( `ls` )
+  if ( -l $f ) then
+    rm -f $f
+  endif
+end
+#ln -s $dbdir/* .
+
+if ( -f $dbdir/$dbname.dd ) ln -s $dbdir/$dbname.dd .
+ln -s $dbdir/$dbname.so .
+ln -s $dbdir/$dbname.ddl_ .
+ln -s $dbdir/${dbname}_H.h .
+
+unlimit
+limit core 0
+
+set abort=0
+if ( $?MPE_NPROC == 0 ) then
+  set nproc=1
+else
+  set nproc=$MPE_NPROC
+endif
+
+if ( $nproc == 1 ) then
+  set viewer=/home/rd/mps/src/odb/tools/viewer.1.x
+#  set viewer=/home/rd/mps/src/odb/tools/viewer.1.x.pure
+#--
+#   echo "$viewer $dbname $outdir ' ' $viewname"
+#   dbx  
+$viewer $dbname $outdir ' ' $viewname || set abort=1
+#--
+else
+  set viewer=/home/rd/mps/src/odb/tools/viewer.x
+  mpirun -np $nproc $viewer $dbname $outdir $PATH $viewname || set abort=1
+endif
+
+if ( $abort == 1 ) then
+  cd $this
+  pwd
+  echo "$outdir/RecoverY"
+  exec $0 $dbname $qualinp $dbdir `cat $outdir/RecoverY`
+endif
+
+exit 0
diff --git a/odb/src/scripts/shp2txt.pl b/odb/src/scripts/shp2txt.pl
new file mode 100644
index 0000000..11c4296
--- /dev/null
+++ b/odb/src/scripts/shp2txt.pl
@@ -0,0 +1,195 @@
+#
+# A Perl-script that converts ARCgis shapelib's closed polygon regions ("rings") into
+# a text file for use by world2odb.c
+#
+# Auxiliary utilities needed : (available via shapelib-1.2.10 public domain source code)
+#
+#   dbfdump
+#   shpdump
+#
+# Usage: 
+# 1) To print just the available columns:
+#  echo "some_shapelib_directory" | perl -w sh2txt.pl 
+# 2) To use ';'-delimited name out of columns par1 par2 par3, use:
+#  echo "shapelib-directory par1 par2 par3" | perl -w sh2txt.pl 
+# This will also create a text-file `basename some_shapelib_directory`.txt for world2odb.x
+#
+# Author: Sami Saarinen, ECMWF, 24-Jul-2007
+#
+
+use strict;
+
+my $inp = <>; # echo "some_shapelib_directory [param(s)]";
+my ($db, at par) = split(/\s+/, $inp);
+print STDERR "ARCgis/shapelib database='$db'\n";
+my $npars = 0;
+for (@par) {
+    my $par = $_;
+    print STDERR "\$par='$par'\n";
+    $npars++;
+}
+
+open(DBF, "dbfdump -h $db|") || die "Unable to dbfdump -h $db";
+my @dbfdump_cols = <DBF>;
+close(DBF);
+my $ncols = 0;
+my $nrows = -1;
+for (@dbfdump_cols) {
+    chomp;
+    next if (m/^\s*$/);
+    if (m/^Field\s+(\d+): Type=(\w+), Title=\`(.*)\', Width=(\d+), Decimals=(\d+)/) {
+	my $field = $1;
+	my $type = $2;
+	my $title = $3;
+	my $width = $4;
+	my $dec = $5;
+	print STDERR "$field\t$type\t'$title'\t$width\t$dec\n";
+	$ncols++;
+    }
+    else {
+	$nrows++;
+    }
+}
+print STDERR "ncols = $ncols, nrows = $nrows\n";
+
+exit if ($npars == 0);
+
+open(SHP, "shpdump $db|") || die "Unable to shpdump $db";
+my @shpdump = <SHP>;
+close(SHP);
+
+my $nshapes = 0;
+my $bounds = 0;
+my ($fileminlon, $fileminlat, $filemaxlon, $filemaxlat) = (0, 0, 0, 0);
+
+for (@shpdump) {
+    chomp;
+    next if (m/^\s*$/);
+    if (m/^Shapefile Type: Polygon   # of Shapes:\s*(\d+)/) {
+	$nshapes = $1;
+    }
+    elsif ($nshapes > 0 && $bounds == 0 && m/^File Bounds:/) {
+	$bounds++;
+	s/[(),]/ /g; s/^\s+//;
+	my $dummy;
+	($dummy, $dummy, $fileminlon, $fileminlat) = split(/\s+/);
+    }
+    elsif ($nshapes > 0 && $bounds == 1 && m/^\s+to\s+/) {
+	$bounds++;
+	s/[(),]/ /g; s/^\s+//;
+	my $dummy;
+	($dummy, $filemaxlon, $filemaxlat) = split(/\s+/);
+	last;
+    }
+}
+
+print STDERR "nshapes = $nshapes\n";
+print STDERR "File min (lat,lon) : $fileminlat, $fileminlon\n";
+print STDERR "File max (lat,lon) : $filemaxlat, $filemaxlon\n";
+
+die "No. of rows ($nrows) <> no. of shapes ($nshapes)" if ($nrows != $nshapes);
+
+my $out = "$db";
+$out =~ s|.*/||;
+$out =~ s|[.].*$||;
+$out .= ".txt";
+print STDERR "out='$out'\n";
+open(OUT,"> $out") || die "Unable to open file '$out' for writing";
+
+printf(OUT "# Number of recs %d\n", $nrows);
+printf(OUT "# Shapelib database: %s\n",$db);
+printf(OUT "# Name consists of these %d columns: (", $npars);
+for (@par) {
+    my $par = $_;
+    printf(OUT "%s%s",$par,(--$npars > 0) ? "," : ")\n");
+}
+printf(OUT "# Global box: %.3f %.3f %.3f %.3f\n",
+	$fileminlon, $fileminlat, $filemaxlon, $filemaxlat);
+printf(OUT "# Shp information:\n");
+printf(OUT "# Part\n");
+
+open(DBF, "dbfdump -m $db|") || die "Unable to dbfdump -m $db";
+my @dbfdump_rec = <DBF>;
+close(DBF);
+my $recno = -1;
+my $last = "";
+for (@dbfdump_rec) {
+    chomp;
+    next if (m/^\s*$/);
+    if (m/^Record:\s+(\d+)/) {
+	$recno = "$1";
+	if ($last !~ m/^\s*$/) {
+	    $last =~ s/;$//;
+	    print STDERR "$last\n";
+	    &ReadShape(split(/\t/,$last));
+	}
+	$last = "$recno\t";
+    }
+    else {
+	s/\s+$//;
+	my $this = $_;
+	for (@par) {
+	    my $par = $_;
+	    $last .= "$1;" if ($this =~ /^$par:\s*(.*)\s*$/i);
+	}
+    }
+}
+
+if ($last !~ m/^\s*$/) {
+    $last =~ s/;$//;
+    print STDERR "$last\n";
+    &ReadShape(split(/\t/,$last));
+}
+
+close(OUT);
+
+exit(0);
+
+sub ReadShape {
+    my ($shapeno, $name) = @_;
+    print STDERR "--> shapeno=$shapeno (out of $nshapes), name='$name'\n";
+    printf(OUT "# Name: %s\n",$name);
+    my ($nvert, $nparts, $partno) = (0, 0, 0);
+    my $jv = 0;
+    my $bounds = 0;
+    my ($minlon, $minlat, $maxlon, $maxlat) = (0, 0, 0, 0);
+    for (@shpdump) {
+	chomp;
+	next if (m/^\s*$/);
+	s/[(),=]/ /g; s/^\s+//; s/\s+/ /g;
+	if (m/^Shape:\s*(\d+) Polygon nVertices (\d+) nParts (\d+)/) {
+	    if ($1 == $shapeno) {
+		$nvert = $2;
+		$nparts = $3;
+	    }
+	}
+	elsif ($nvert > 0 && $bounds == 0 && m/^Bounds:/) {
+	    $bounds++;
+	    my $dummy;
+	    ($dummy, $minlon, $minlat) = split(/\s+/);
+	}
+	elsif ($nvert > 0 && $bounds == 1 && m/^to\s+/) {
+	    $bounds++;
+	    my $dummy;
+	    ($dummy, $maxlon, $maxlat) = split(/\s+/);
+	}
+	elsif ($nvert > 0 && $bounds == 2) {
+	    if ($jv == 0) {
+		print STDERR "\tnvert=$nvert, nparts=$nparts\n";
+		printf(STDERR "# Box: %.3f %.3f %.3f %.3f\n",$minlon, $minlat, $maxlon, $maxlat);
+		printf(OUT "# Num of parts: %d\n",$nparts);
+		printf(OUT "# Num of points: %d\n",$nvert);
+		printf(OUT "# Box: %.3f %.3f %.3f %.3f\n",$minlon, $minlat, $maxlon, $maxlat);
+		printf(OUT "# Part %d\n",$partno++);
+	    }
+	    if (m/^[+]\s+/) {
+		printf(OUT "# Part %d\n",$partno++);
+		s/^[+]\s+//;
+	    }
+	    my ($lat, $lon) = split(/\s+/);
+	    printf(OUT "%.3f %.3f\n", $lat, $lon);
+	    $jv++;
+	    last if ($jv == $nvert);
+	}
+    } # for (@shpdump)
+}
diff --git a/odb/src/scripts/test_arch b/odb/src/scripts/test_arch
new file mode 100755
index 0000000..793167f
--- /dev/null
+++ b/odb/src/scripts/test_arch
@@ -0,0 +1,98 @@
+#!/bin/ksh
+#
+# A script to return "linux"     if you're on (any) linux platform
+#                    "aix"       if you're on ibm aix platform
+#                    "solaris"   if you're on sun solaris platform
+#                    "osx"       if you're on apple mac platform
+#
+# otherwise returns "unknown"
+#
+# The script uses all available information to figure out the platform
+#
+
+set -eu
+
+export ARCH=${ARCH:="unknown"}
+export ODB_ARCH=${ODB_ARCH:="$ARCH"}
+
+target=unknown
+
+if [[ -d /cygdrive ]] ; then
+  target="cygwin"
+fi
+
+#-- target unknown ? Run 'uname' command, if available
+if [[ "$target" = "unknown" ]] ; then
+  unamecmd=$(whence uname 2>/dev/null || echo "")
+  if [[ "$unamecmd" != "" && -x "$unamecmd" ]] ; then
+    arch=$($unamecmd | perl -pe 'tr/A-Z/a-z/')
+    case "$arch" in
+    linux  )   target=linux   ;;
+    i*86   )   target=linux   ;;
+    x86*   )   target=linux   ;;
+    aix    )   target=aix     ;;
+    ibm_power* )   target=aix ;;
+    sun*   )   target=solaris ;;
+    *alpha*)   target=alpha   ;;
+    osf*)      target=alpha   ;;
+    super-ux*) target=necsx   ;;
+    darwin )   target=osx     ;;
+    esac
+  fi
+fi
+
+#-- target still unknown ? Run 'arch' command, if available
+if [[ "$target" = "unknown" ]] ; then
+  archcmd=$(whence arch 2>/dev/null || echo "")
+  if [[ "$archcmd" != "" && -x "$archcmd" ]] ; then
+    arch=$($archcmd | perl -pe 'tr/A-Z/a-z/')
+    case "$arch" in
+    linux  )   target=linux   ;;
+    i*86   )   target=linux   ;;
+    x86*   )   target=linux   ;;
+    aix    )   target=aix     ;;
+    ibm_power* )   target=aix ;;
+    sun*   )   target=solaris ;;
+    *alpha*)   target=alpha   ;;
+    esac
+  fi
+fi
+
+#-- target still unknown ? Use $ODB_ARCH entry
+if [[ "$target" = "unknown" ]] ; then
+  arch=$(echo "$ODB_ARCH" | perl -pe 'tr/A-Z/a-z/')
+  case "$arch" in
+  necsx* )   target=necsx   ;;
+  linux  )   target=linux   ;;
+  i*86   )   target=linux   ;;
+  x86*   )   target=linux   ;;
+  *g95*  )   target=linux   ;;
+  aix    )   target=aix     ;;
+  ibm_power* )   target=aix ;;
+  sun*   )   target=solaris ;;
+  *alpha*)   target=alpha   ;;
+  esac
+fi
+
+if [[ "$target" = "linux" && "$ODB_ARCH" = @(sun_linux*) ]] ; then
+#-- This system uses Sun/Studio compilers ported for Linux !!
+  target=solaris
+fi
+
+if [[ "$target" = "linux" && "$ODB_ARCH" = @(nectx*) ]] ; then
+#-- In essence: export ODB_ARCH=nectx and your target becomes "nectx" (NEC SX front-end)
+#   to be used by "odbf90" & "odbcc" scripts instead of "linux"
+#-- We could have checked presence of /SX -directory as well, but 
+#   then we would never have been able to run anything on NEC TX front-end as "linux"
+  target=nectx
+fi
+
+if [[ "$target" = "linux" && "$ODB_ARCH" = @(cray_amd|cray_xt*) ]] ; then
+#-- Check if Cray XT3/4 catamount
+  yod=$(whence yod 2>/dev/null || echo "")
+  if [[ "$yod" != "" && -x "$yod" ]] ; then
+    target=$(echo "$ODB_ARCH" | cut -c1-8)
+  fi
+fi
+
+echo "$target"
diff --git a/odb/src/scripts/use_odb.csh.in b/odb/src/scripts/use_odb.csh.in
new file mode 100644
index 0000000..f9a16e2
--- /dev/null
+++ b/odb/src/scripts/use_odb.csh.in
@@ -0,0 +1,38 @@
+#
+# Script to export ODB environment variables (csh, tcsh, etc.)
+#
+# Usage: [set ODB_ROOT=<dir>] ; source use_odb.csh
+#
+
+if ( $?ODB_ROOT == 0 ) then
+  set ODB_ROOT = "@CMAKE_INSTALL_PREFIX@"
+endif
+
+unset found_pc_file
+foreach pc_dir ( $ODB_ROOT $ODB_ROOT/lib/pkgconfig )
+  set pc_file = $pc_dir/odb.pc      
+  if ( -f $pc_file ) then
+    set found_pc_file = 1
+    break
+  endif
+end
+
+if ( $?found_pc_file == 0 ) then
+  echo "error: Could not find 'odb.pc' file in ODB_ROOT directory '$ODB_ROOT'"
+  exit 1
+else
+
+set pc_prefix = "--define-variable=prefix=$ODB_ROOT"
+
+setenv PATH "$ODB_ROOT/bin:$PATH"
+setenv ODB_INCLUDE `pkg-config $pc_file $pc_prefix --cflags`
+setenv ODB_LIB `pkg-config $pc_file $pc_prefix --static --libs`
+
+foreach line ( "`cat $pc_file`" )
+  if ( "$line" =~ "ODB*" ) then
+    set name = `echo $line | cut -d '=' -f 1`
+    setenv $name "`pkg-config $pc_file $pc_prefix --variable=$name`"
+  endif
+end
+
+endif
diff --git a/odb/src/scripts/use_odb.sh.in b/odb/src/scripts/use_odb.sh.in
new file mode 100644
index 0000000..1db2a6e
--- /dev/null
+++ b/odb/src/scripts/use_odb.sh.in
@@ -0,0 +1,39 @@
+#
+# Script to export ODB environment variables (sh, ksh, bash, etc.)
+#
+# Usage: [ODB_ROOT=<dir>] ; source use_odb.sh
+#
+
+if [ -z "$ODB_ROOT" ]; then
+  ODB_ROOT="@CMAKE_INSTALL_PREFIX@"
+fi
+
+unset found_pc_file
+for pc_dir in $ODB_ROOT $ODB_ROOT/lib/pkgconfig; do
+  pc_file=$pc_dir/odb.pc      
+  if [ -f $pc_file ]; then
+    found_pc_file=1
+    break
+  fi
+done
+
+if [ -z "$found_pc_file" ]; then
+  echo "error: Could not find 'odb.pc' file in ODB_ROOT directory '$ODB_ROOT'" 1>&2
+  false
+else
+
+pc_prefix="--define-variable=prefix=$ODB_ROOT"
+
+PATH="$ODB_ROOT/bin:$PATH"; export PATH
+ODB_INCLUDE=`pkg-config $pc_file $pc_prefix --cflags`; export ODB_INCLUDE
+ODB_LIB=`pkg-config $pc_file $pc_prefix --static --libs`; export ODB_LIB
+
+while read line; do
+  if echo $line | grep -q "^ODB.*="; then
+    name=`echo $line | cut -d '=' -f 1`
+    eval $name="'`pkg-config $pc_file $pc_prefix --variable=$name`'"
+    export $name
+  fi
+done < $pc_file
+
+fi
diff --git a/odb/src/scripts/where_fiddle.pl b/odb/src/scripts/where_fiddle.pl
new file mode 100644
index 0000000..293523c
--- /dev/null
+++ b/odb/src/scripts/where_fiddle.pl
@@ -0,0 +1,32 @@
+use strict;
+
+my $where_fiddle = $ENV{'ODB_WHERE_FIDDLE'};
+
+$where_fiddle = '$lat1 < degrees(lat) <= $lat2' if (!defined($where_fiddle));
+
+{
+  local $/;
+  my $prtset = 0;
+  my $in = <>;
+  if ($in =~ m/\bwhere\b/i) {
+    # WHERE-clause found
+    $in =~ s/\b(where)\b\s*(\n)?/$1\n${where_fiddle} AND\n/i;
+    $prtset = 1;
+  }
+  elsif ($in =~ m/\b(order|sort)\s*by\b/i) {
+    # WHERE-clause is missing, but ORDERBY/SORTBY present
+    $in =~ s/\b(order|sort)(\s*by)\b/WHERE ${where_fiddle}\n$1$2/i;
+    $prtset = 1;
+  }
+  elsif ($in =~ m/(;)?\s*$/i) {
+    # Both WHERE-clause and ORDERBY/SORTBY not present, try to add at the end
+    $in =~ s/(\s*)(;)?\s*$/${1}WHERE ${where_fiddle}\n;/i;
+    $prtset = 1;
+  }
+  if ($prtset) {
+    print "SET \$lat1 = -90;\n";
+    print "SET \$lat2 = +90;\n";
+  }
+  print "$in";
+}
+
diff --git a/odb/src/tools/CMakeLists.txt b/odb/src/tools/CMakeLists.txt
new file mode 100644
index 0000000..ae01fc7
--- /dev/null
+++ b/odb/src/tools/CMakeLists.txt
@@ -0,0 +1,68 @@
+
+ecbuild_add_library(TARGET odbmain
+    TYPE STATIC # to allow extraction of objects using ar -x
+    DEPENDS odbifsaux odb_lib # parkind1.mod, odb_mod.mod
+    SOURCES Create_index.F90
+            Odbcompress.F90
+            Odbdiff.F90
+            Odbgnuplot.F90
+            Odbless.F90)
+
+set(libs ${ODB_LIBRARIES})
+include_directories(${ODB_INCLUDE_DIRS})
+
+ecbuild_add_executable(TARGET odbsql.x SOURCES Fodbsql.F90
+    LINKER_LANGUAGE Fortran LIBS ${libs})
+
+ecbuild_add_executable(TARGET fscheduler.x SOURCES Fscheduler.F90
+    LINKER_LANGUAGE Fortran LIBS ${libs})
+
+ecbuild_add_executable(TARGET dcagen.x SOURCES dcagen.c LIBS ${libs})
+ecbuild_add_executable(TARGET hcat     SOURCES hcat.c   LIBS ${libs})
+ecbuild_add_executable(TARGET ioassign SOURCES ioassign.c LIBS ${libs})
+ecbuild_add_executable(TARGET odb2rgg SOURCES odb2rgg.c LIBS ${libs})
+ecbuild_add_executable(TARGET odbversion SOURCES odbversion.c LIBS ${libs})
+ecbuild_add_executable(TARGET odbcksum SOURCES odbcksum.c LIBS ${libs})
+ecbuild_add_executable(TARGET odbdump.x SOURCES odbdump_main.c LIBS ${libs})
+ecbuild_add_executable(TARGET odbmd5sum SOURCES odbmd5sum.c LIBS ${libs})
+ecbuild_add_executable(TARGET pcma SOURCES pcma_main.c LIBS ${libs})
+ecbuild_add_executable(TARGET qtar SOURCES qtar.c LIBS ${libs})
+
+set(_odb_mpi_targets odb98.x odbsql.x fscheduler.x dcagen.x hcat ioassign odb2rgg
+  odbversion odbcksum odbdump.x odbmd5sum pcma qtar)
+
+if(HAVE_ODB_MPI AND HAVE_ODB_MPI_SERIAL_WRAPPERS)
+  foreach(_target ${_odb_mpi_targets})
+    # For now we assume that target name and output name are the same
+    get_filename_component(_name ${_target} NAME_WE)
+    get_filename_component(_ext ${_target} EXT)
+    set_target_properties(${_target} PROPERTIES OUTPUT_NAME "${_name}mp${_ext}")
+    add_custom_target(serial${_target} ALL COMMAND ${CMAKE_COMMAND}
+      -E create_symlink .odb_serial_wrapper.sh ${_target}
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+    install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/${_target} DESTINATION bin)
+  endforeach()
+endif()
+
+# Client/server tools
+
+ecbuild_add_executable(TARGET odbi_client.x
+    SOURCES odbi_client_main.c LIBS ${libs} CONDITION ODB_CLIENT_SERVER)
+ecbuild_add_executable(TARGET odbi_server.x
+    SOURCES odbi_server_main.c LIBS ${libs} CONDITION ODB_CLIENT_SERVER)
+ecbuild_add_executable(TARGET odbi_direct.x
+    SOURCES odbi_direct_main.c LIBS ${libs} CONDITION ODB_CLIENT_SERVER)
+ecbuild_add_executable(TARGET odbi_host.x
+    SOURCES odbi_host.c LIBS ${libs} CONDITION ODB_CLIENT_SERVER)
+
+# Serial helper tools
+
+ecbuild_add_executable(TARGET dd2ddl.x SOURCES dd2ddl.c)
+ecbuild_add_executable(TARGET mysort SOURCES mysort.c)
+ecbuild_add_executable(TARGET scheduler SOURCES scheduler.c)
+ecbuild_add_executable(TARGET odbfiletime.x SOURCES odbfiletime.c)
+
+ecbuild_add_executable(TARGET b4.x DEFINITIONS HAS_XMOTIF SOURCES b4.c
+    LIBS ${libs} ${MOTIF_LIBRARIES}
+    CONDITION MOTIF_FOUND AND ODB_DEPRECATED)
+
diff --git a/odb/src/tools/Create_index.F90 b/odb/src/tools/Create_index.F90
new file mode 100644
index 0000000..f91b470
--- /dev/null
+++ b/odb/src/tools/Create_index.F90
@@ -0,0 +1,208 @@
+program create_index
+USE PARKIND1  ,ONLY : JPIM     ,JPRB
+use odb_module
+use mpl_module
+implicit none
+INTEGER(KIND=JPIM) :: h, npools, j, jp, rc, idxtype, nsets, len_bitmap
+INTEGER(KIND=JPIM) :: nra, nrows, ncols, nc, numargs, jj, k, ktot
+INTEGER(KIND=JPIM) :: nproc, myproc, bailout
+INTEGER(KIND=JPIM), parameter :: iparam_end = 5
+character(len=64) dbname, idxname, table, arg, clratio
+character(len=1) cactive(2)
+character(len=64), allocatable :: cols(:)
+REAL(KIND=JPRB), allocatable :: a(:,:), aa(:,:), colbuf(:)
+REAL(KIND=JPRB) ratio, ratio_limit
+INTEGER(KIND=JPIM), allocatable :: colidx(:), unique_idx(:), idx(:), bitmap(:), sortidx(:)
+logical, allocatable :: colget(:), idxfound(:)
+character(len=maxstrlen) colnames
+
+!# Usage for now
+!./create_index.x $dbname $idxtype $idxname $table $cols
+
+rc = ODB_init(nproc=nproc,myproc=myproc)
+
+numargs = MPL_iargc()
+
+if (numargs <= iparam_end) then
+  call odb_abort('create_index(MAIN)',&
+               & 'Usage: ./create_index.x $dbname $idxtype $idxname $table $cols')
+  call exit(1)
+endif
+
+call MPL_getarg(1,dbname)
+write(0,*)'dbname='//trim(dbname)
+call MPL_getarg(2,arg) ; read(arg,'(i20)') idxtype
+write(0,*)'idxtype=',idxtype
+cactive(:) = ' '
+if (idxtype >= 1 .and. idxtype <= 2) cactive(idxtype) = '*'
+call MPL_getarg(3,idxname)
+write(0,*)'idxname='//trim(idxname)
+call MPL_getarg(4,table)
+if (table(1:1) /= '@') table = '@'//trim(table)
+write(0,*)'table='//trim(table)
+call MPL_getarg(5,clratio)
+read(clratio,'(f20.0)') ratio_limit
+write(0,'(1x,a,f8.2,a)') 'ratio=',ratio_limit,'%'
+
+nc = numargs - iparam_end
+allocate(cols(nc))
+
+CALL codb_strblank(colnames)
+do j=1,nc
+  call MPL_getarg(iparam_end+j,cols(j))
+  if (j == 1) then
+    colnames = trim(cols(j))
+  else
+    colnames = trim(colnames)//','//trim(cols(j))
+  endif
+enddo
+
+npools = 0
+h = ODB_open(dbname,'READONLY',npools)
+
+!-- check that specified columns really exist on the given table
+allocate(colidx(nc))
+colidx(:) = 0
+rc = ODB_varindex(h, table, cols, colidx)
+if (any(colidx(:) == 0)) then
+  call odb_abort('create_index(MAIN)',&
+                &'One or more columns in "'//&
+                &trim(colnames)//'" does not belong to table "'//trim(table(2:))//'"')
+  call exit(2)
+endif
+
+if (nc > 1) then
+!-- Reorder columns w.r.t. colidx(:)
+  allocate(sortidx(nc))
+  call keysort(rc, colidx, nc, index=sortidx, init=.TRUE.)
+  write(0,*) '         colidx(:)=',colidx(:)
+  write(0,*) '        sortidx(:)=',sortidx(:)
+  write(0,*) 'colidx(sortidx(:))=',colidx(sortidx(:))
+  cols(:) = cols(sortidx(:))
+  colidx(:) = colidx(sortidx(:))
+  deallocate(sortidx)
+
+  CALL codb_strblank(colnames)
+  do j=1,nc
+    if (j == 1) then
+      colnames = trim(cols(j))
+    else
+      colnames = trim(colnames)//','//trim(cols(j))
+    endif
+  enddo
+endif
+
+write(0,*)'> colnames="'//trim(colnames)//'"'
+do j=1,nc
+  write(0,'(a,i5,a,i5)')' col#',j,' = '//trim(cols(j))//', colidx#',colidx(j)
+enddo
+
+ncols = ODB_getnames(h, table, 'colname')
+allocate(colget(ncols))
+colget(:) = .FALSE.
+colget(colidx(:)) = .TRUE.
+
+allocate(colbuf(nc))
+do jp=myproc,npools,nproc
+  rc = ODB_select(h, table, nrows, ncols, nra=nra, poolno=jp)
+  if (nrows > 0) then
+    write(0,*)'*** Poolno=',jp,', nrows=',nrows
+    allocate(a(nra,0:ncols))
+    rc = ODB_get(h, table, a, nrows, ncols, colget=colget, poolno=jp)
+    !do j=1,min(5,nrows)
+    !  write(0,'(i10,1p,(4(g20.10)))') j,a(j,colidx(:))
+    !enddo
+    !write(0,*)'etc...'
+    allocate(aa(nra,1:nc))
+    do j=1,nc
+      aa(1:nrows,j) = a(1:nrows,colidx(j))
+    enddo
+    deallocate(a)
+    allocate(unique_idx(nrows))
+    unique_idx(:) = -1
+    bailout = nint((ratio_limit * nrows)/100.0d0) + 10
+    call codb_cardinality(nc, nrows, nra, aa, nsets, unique_idx, nrows, bailout)
+    ratio = (nsets * 100.0d0)/nrows
+    write(0,'(a,i10,a,i10,a,i10,a,f8.2,a)') &
+         & ' > Cardinality: nsets=',nsets,' of nrows=',nrows,', bailout=',bailout,' : ratio=',ratio,'%'
+    write(0,*)'> Space estimates: poolno=',jp
+    write(0,*) cactive(1)//'idxtype=1 (unique index): ',nsets+nrows,' [32-bit words]'
+    len_bitmap = (nrows+32-1)/32
+    write(0,*) cactive(2)//'idxtype=2 (bitmap index): ',nsets*len_bitmap,' [32-bit words]'
+    if (ratio > ratio_limit) then
+      write(0,*)'***Warning: Abandoning index creation; Ratio too high (> '//trim(clratio)//'%)'
+      goto 100
+    else if (nrows == 0) then
+      write(0,*)'***Warning: Abandoning index creation; Bailout reached'
+      goto 100
+    endif
+    do j=1,nsets
+      write(0,'(i10,1p,(4(g20.10)))') unique_idx(j),aa(unique_idx(j),:)
+    enddo
+    if (idxtype == 2) then ! type=BITMAP
+      allocate(bitmap(len_bitmap))
+    endif
+    allocate(idx(nrows))
+    allocate(idxfound(nrows))
+    idxfound(:) = .FALSE.
+    write(0,*) 'indices ---> idxtype=',idxtype
+    ktot = 0
+    do j=1,nsets
+      colbuf(:) = aa(unique_idx(j),:)
+      k = 0
+      do jj=1,nrows
+        if (idxfound(jj)) cycle
+        if (all(aa(jj,:) == colbuf(:))) then
+          k = k + 1
+          idx(k) = jj-1 ! C-indexing
+          idxfound(jj) = .TRUE.
+        endif
+      enddo
+      ktot = ktot + k
+      write(0,'(i10,a)') -k,' WHERE'
+      write(0,'(1p,(3((a," == ",g20.10,:," AND "))))') (trim(cols(jj)), colbuf(jj), jj=1,nc)
+      write(0,'(8i10)',advance='no') -ktot, idx(1:min(7,k))
+      if (k > 7) then
+        write(0,*)'etc...'
+      else
+        write(0,*)' '
+      endif
+      if (idxtype == 2) then ! type=BITMAP
+        bitmap(:) = 0
+        call codbit_setidx(bitmap,nrows,32,idx,k)
+        write(0,'(3b32.32)',advance='no') bitmap(1:min(3,len_bitmap))
+        if (len_bitmap > 3) then
+          write(0,*)'etc...'
+        else
+          write(0,*)' '
+        endif
+      endif
+    enddo ! do j=1,nsets
+    write(0,*) '> nsets, nrows, ktot=',nsets, nrows, ktot
+    if (nrows /= ktot) then
+      call odb_abort('create_index(MAIN)',&
+                    & 'nrows /= ktot')
+      call exit(3)
+    endif
+    if (idxtype == 2) then ! type=BITMAP
+      deallocate(bitmap)
+    endif
+    deallocate(idx)
+    deallocate(idxfound)
+ 100  continue
+    deallocate(aa)
+    deallocate(unique_idx)
+  endif
+  rc = ODB_release(h, poolno=jp)
+enddo
+
+deallocate(cols)
+deallocate(colbuf)
+deallocate(colidx)
+deallocate(colget)
+
+rc = ODB_close(h)
+
+rc = ODB_end()
+
+end program create_index
diff --git a/odb/src/tools/DEPRECATED b/odb/src/tools/DEPRECATED
new file mode 100644
index 0000000..3011d84
--- /dev/null
+++ b/odb/src/tools/DEPRECATED
@@ -0,0 +1 @@
+b4.c
diff --git a/odb/src/tools/Fodbsql.F90 b/odb/src/tools/Fodbsql.F90
new file mode 100644
index 0000000..a0adc86
--- /dev/null
+++ b/odb/src/tools/Fodbsql.F90
@@ -0,0 +1,12 @@
+PROGRAM fodbsql
+USE PARKIND1  ,ONLY : JPIM, JPRB
+USE YOMHOOK   ,ONLY : LHOOK, DR_HOOK
+implicit none
+INTEGER(KIND=JPIM)               :: iret = 0
+REAL(KIND=JPRB)                  :: ZHOOK_HANDLE
+IF (LHOOK) CALL DR_HOOK('FODBSQL',0,ZHOOK_HANDLE)
+call codb_allow_time_error(235959) ! See lib/twindow.c
+CALL odbsql(iret) ! aux/odbsql.c
+IF (LHOOK) CALL DR_HOOK('FODBSQL',1,ZHOOK_HANDLE)
+call ec_exit(iret)
+END PROGRAM fodbsql
diff --git a/odb/src/tools/Fscheduler.F90 b/odb/src/tools/Fscheduler.F90
new file mode 100644
index 0000000..3793261
--- /dev/null
+++ b/odb/src/tools/Fscheduler.F90
@@ -0,0 +1,294 @@
+!
+! Fscheduler.F90 : Runs Unix-commands read from file(s) in parallel
+!
+!! Usage: env ODB_PARAL=<ncpus> fscheduler.x maxcmds [cmdfile_1 [cmdfile_2 ...]]
+!
+! Special commands:
+! ----------------
+! wait                                -- will synchronize i.e. a barrier
+! on_error: command [; command; ...]  -- command(s) to be run when error had detected
+!
+! Also, set export FSCHEDULER_PBAR=1 to get a "progress bar" to stdout
+
+
+PROGRAM fscheduler
+USE PARKIND1  ,ONLY : JPIM
+
+#ifdef NAG
+USE F90_UNIX_ENV, ONLY: GETARG, IARGC
+USE F90_UNIX_IO, ONLY: FLUSH
+#endif
+
+implicit none
+!-- Maximum number of characters in a Fortran90 string (i.e. character(len=maxstrlen))
+!   (see also odb/module/odbshared.F90 definition)
+CHARACTER(LEN=1),PARAMETER :: BACKSL='\\'
+INTEGER(KIND=JPIM), parameter :: maxstrlen = 32767 ! 65536
+INTEGER(KIND=JPIM) :: iu, nfiles, j, j1, j2, ncmd, ilen, ipos, k, kount, rc
+INTEGER(KIND=JPIM) :: numproc_default, numproc
+INTEGER(KIND=JPIM) :: pbar_default, pbar, pbar_cur, pbar_max
+#ifndef NAG
+INTEGER(KIND=JPIM) :: iargc
+#endif
+character(len=512) :: file
+logical LLclose_file, LLwait, LLcont, LLpbar
+logical LLhas_on_error, LLrun_on_error
+INTEGER(KIND=JPIM) :: nmaxcmd, numargs, exit_code
+INTEGER(KIND=JPIM) :: usec, usec_inc, usec_default
+character(len=20) :: cmaxcmd
+character(len=maxstrlen) :: acmd, on_error_cmd
+character(len=maxstrlen), allocatable :: cmd(:)
+INTEGER(KIND=JPIM), allocatable :: ilencmd(:)
+INTEGER(KIND=JPIM), allocatable :: iecho(:)
+INTEGER(KIND=JPIM), allocatable :: pid(:)
+
+numproc_default = 1
+CALL util_igetenv('ODB_PARAL', numproc_default, numproc)
+
+pbar_default = 0
+CALL util_igetenv('FSCHEDULER_PBAR', pbar_default, pbar)
+LLpbar = (pbar == 1)
+
+numargs = iargc()
+
+if (numargs >= 1) then
+  call getarg(1,cmaxcmd)
+  read(cmaxcmd,'(i20)') nmaxcmd
+  allocate(cmd(nmaxcmd))
+  allocate(ilencmd(nmaxcmd))
+  allocate(iecho(nmaxcmd))
+else
+  write(0,*) 'Usage: fscheduler.x maxcmds [cmdfile_1 [cmdfile_2 ...]]'
+  call ec_exit(1)
+endif
+
+nfiles = numargs - 1
+if (nfiles >= 1) then
+  iu = 1
+  LLclose_file = .TRUE.
+else
+  iu = 5
+  LLclose_file = .FALSE.
+endif
+
+ncmd = 0
+j2 = max(1,nfiles)
+j1 = min(1,j2)
+do j=j1,j2
+  if (LLclose_file) then
+    call getarg(j+1,file)
+    open(iu,file=trim(file),status='old',err=99) ! ignore open errors
+  endif
+  LLcont = .FALSE.
+  do while (ncmd < nmaxcmd)
+    ilen = 1
+    if (LLcont) ilen = len_trim(acmd)
+    read(iu,'(a)',end=98,err=98) acmd(ilen:) ! ignore read & eof-errors
+    acmd = adjustl(trim(acmd)) ! shift to left by skipping any leading blanks
+    ilen = len_trim(acmd)
+    if (acmd(ilen:ilen) == BACKSL) then
+      ! This was a continuation line; wait for the rest the line
+      LLcont = .TRUE.
+    else if (ilen > 0 .and. acmd(1:1) /= '#' .and. acmd(1:1) /= '!') then
+      ! Do not accept empty lines or lines beginning with '#' or '!'
+      LLcont = .FALSE.
+      ncmd = ncmd + 1
+      cmd(ncmd) = acmd
+      ilencmd(ncmd) = ilen ! cmd-length
+      iecho(ncmd) = ilen ! how many chars to be echo'ed
+      ! search for double-pipe-char '||' and truncate [echoing] just before it
+      ipos = scan(cmd(ncmd)(1:ilen),'|',back=.TRUE.)
+      if (ipos > 1) then
+        if (cmd(ncmd)(ipos-1:ipos-1) == '|') iecho(ncmd) = ipos - 2
+      endif
+    else
+      LLcont = .FALSE.
+    endif
+  enddo
+ 98   continue
+  if (LLclose_file) then
+    close(iu)
+  endif
+ 99   continue
+enddo
+
+allocate(pid(ncmd))
+pid(:) = -1
+kount = 0 ! count of unfinished tasks
+LLhas_on_error = .FALSE.
+LLrun_on_error = .FALSE.
+exit_code = 0
+if (LLpbar) then
+  pbar_max = ncmd
+  pbar_cur = 0
+endif
+
+CMDLOOP: do j=1,ncmd
+   LLwait = .FALSE.
+   pid(j) = 0
+#ifdef NECSX
+   write(0,'(a)') cmd(j)(1:min(iecho(j),132))
+#else
+   write(0,'(a)') cmd(j)(1:iecho(j))
+#endif
+   if (ilencmd(j) >= 9 .and. cmd(j)(1:9) == 'on_error:') then
+      on_error_cmd = adjustl(trim(cmd(j)(10:)))
+      LLhas_on_error = .TRUE.
+      if (LLpbar) CALL increment_pbar(.TRUE.)
+   else if (cmd(j)(1:ilencmd(j)) == 'wait') then
+      LLwait = .TRUE.
+      if (LLpbar) CALL increment_pbar(.TRUE.)
+   else
+      call codb_subshell(cmd(j)(1:ilencmd(j)), pid(j)) ! fork() + system()
+      if (pid(j) > 0) then
+         kount = kount + 1
+      else if (pid(j) == 0) then
+         !-- subshell already finished with rc == 0
+         if (LLpbar) CALL increment_pbar(.TRUE.)
+         continue ! do nothing
+      else ! pid(j) < 0
+         !-- subshell already finished with rc > 0 == abs(pid(j)) 
+         !   ==> run on_error-code (if available), when all other procs finished
+         LLrun_on_error = .TRUE.
+         exit_code = abs(pid(j))
+         pid(j) = 0
+         if (LLpbar) CALL increment_pbar(.TRUE.)
+      endif
+   endif
+
+   ! The following arrangement allows new subprocess to be launched as soon as another one has finished !
+   ! In other words: we do NOT wait for ALL the previous 'numproc'-tasks to finish first; just one
+
+   usec_default = 500000
+   usec_inc = 400000
+   do while ((LLwait .and. kount > 0) .or. kount == numproc .or. (j == ncmd .and. kount > 0))
+      call codb_wait(-1, 1, rc) ! wait for any (child-)process; do not block/hang; rc may contain finished pid
+      if (rc > 0) then ! rc indeed contains a finished pid
+         LOOP: do k=1,j
+            if (rc == pid(k)) then
+               pid(k) = -1
+               kount = kount - 1
+               if (LLpbar) CALL increment_pbar(.TRUE.)
+               exit LOOP
+            endif
+         enddo LOOP
+      else if (rc == 0) then ! Nobody exited this time
+         usec = usec_default + kount * usec_inc
+         call ec_usleep(usec) ! Take a "usec" microsecs nap!
+         if (LLpbar) CALL increment_pbar(.FALSE.)
+      else ! rc < 0
+         LLrun_on_error = .TRUE.
+         exit_code = abs(rc)
+         kount = kount - 1
+         if (LLpbar) CALL increment_pbar(.TRUE.)
+      endif
+   enddo
+
+   if (LLrun_on_error) then
+      if (LLpbar) CALL increment_pbar(.FALSE.)
+      exit CMDLOOP
+   endif
+enddo CMDLOOP
+
+deallocate(pid)
+
+deallocate(cmd)
+deallocate(ilencmd)
+deallocate(iecho)
+
+if (LLrun_on_error .and. LLhas_on_error) call codb_subshell(trim(on_error_cmd), rc)
+if (LLrun_on_error .and. LLpbar) then
+   call increment_pbar(.FALSE.,'FSCHEDULER has detected a fatal error !!!')
+endif
+
+call ec_exit(exit_code)
+
+CONTAINS
+
+SUBROUTINE increment_pbar(LDincr, cderrmsg)
+USE PARKIND1  ,ONLY : JPIM, JPRB
+implicit none
+CHARACTER(LEN=1),PARAMETER :: BACKSL='\\'
+logical, intent(in) :: LDincr
+character(len=*), intent(in), optional :: cderrmsg
+character(len=50), save :: cbar
+INTEGER(KIND=JPIM), save :: npropel = 1
+INTEGER(KIND=JPIM), parameter :: io = 6
+character(len=1), parameter :: cr = char(13)
+character(len=1) :: clast
+character(len=1), parameter :: cpropel(5) = (/'-', BACKSL, '|', '/', '+'/)
+REAL(KIND=JPRB) :: Telapsed, Tremains
+character(len=10) :: nice(2)
+INTEGER(KIND=JPIM) :: ipc, x, j, idiv
+INTEGER(KIND=JPIM) :: percent_done
+logical, save :: LLdone = .false.
+REAL(KIND=JPRB) :: util_walltime
+percent_done(x) = nint((x * 100.0_JPRB)/pbar_max)
+if (present(cderrmsg)) then
+   write(io,'(/a/)') cderrmsg
+else
+   if (LLdone) return
+   if (pbar_cur == 0) then
+      cbar = ' '
+      Telapsed = util_walltime()
+   endif
+   if (LDincr) pbar_cur = pbar_cur + 1
+   Telapsed = util_walltime()
+   ipc = percent_done(pbar_cur)
+   ipc = min(max(ipc, 0),100)
+   idiv = 100/len(cbar)
+   do j=1,ipc/idiv
+      cbar(j:j) = '#'
+   enddo
+   do j=ipc/idiv+1,len(cbar)
+      cbar(j:j) = '.'
+   enddo
+   clast = cr
+   if (ipc == 100) then
+      clast = ' '
+      npropel = 5
+      Tremains = 0
+   else
+      if (pbar_cur > 0) then
+         Tremains = (Telapsed * (pbar_max - pbar_cur))/pbar_cur
+      else
+         Tremains = 2147483647.0_JPRB
+      endif
+   endif
+   nice(1) = nicetime(Telapsed)
+   nice(2) = nicetime(Tremains)
+   write(io,&
+        & '(3x,a1,a,2x,i3,a1,"  (time: ",a,", left: ",a,", procs:",i2,")      ",a1)',&
+        & advance='no') &
+        & cpropel(npropel),cbar, ipc, '%', &
+        & trim(nice(1)), trim(nice(2)), &
+        & kount, clast
+   if (ipc == 100) then
+      write(io,*) ' '
+      LLdone = .TRUE.
+   endif
+   call flush(io)
+   npropel = npropel + 1
+   if (npropel > 4) npropel = 1
+endif
+END SUBROUTINE increment_pbar
+
+FUNCTION nicetime(t) RESULT(c)
+USE PARKIND1  ,ONLY : JPIM, JPRB
+implicit none
+character(len=10) c
+REAL(KIND=JPRB), intent(in) :: t
+INTEGER(KIND=JPIM) :: tim, hh, mm, ss
+tim = int(t)
+ss = mod(tim,60)
+mm = mod(tim/60,60)
+hh = tim/3600
+if (hh > 0) then
+  write(c,'(i4,":",i2.2,":",i2.2)') hh, mm, ss
+else
+  write(c,'(i7,":",i2.2)') mm, ss
+endif
+c = adjustl(c)
+END FUNCTION nicetime
+
+END PROGRAM fscheduler
diff --git a/odb/src/tools/Odbcompress.F90 b/odb/src/tools/Odbcompress.F90
new file mode 100644
index 0000000..b747155
--- /dev/null
+++ b/odb/src/tools/Odbcompress.F90
@@ -0,0 +1,408 @@
+PROGRAM odbcompress
+
+!
+! odbcompress.x -i INPUT_DATABASE_NAME -o OUTPUT_DATABASE_NAME [-a] [-k] [-v] [-m membytes]
+!
+! Copies all matching tables/column entries found in OUTPUT_DATABASE_NAME
+! from INPUT_DATABASE_NAME to OUTPUT_DATABASE_NAME
+!
+! The idea is in the script level that you 
+! - copy <INPUT_DATABASE_NAME>.sch into <OUTPUT_DATABASE_NAME>.ddl
+! - copy <INPUT_DATABASE_NAME>.flags into <OUTPUT_DATABASE_NAME>.flags
+! - edit <OUTPUT_DATABASE_NAME>.ddl to remove undesired tables/col.entries
+! - compile <OUTPUT_DATABASE_NAME>.ddl into lib<OUTPUT_DATABASE_NAME>.a
+! - link Odbcompress.o with libs lib<INPUT_DATABASE_NAME>.a &  lib<OUTPUT_DATABASE_NAME>.a
+! - and run !!
+!
+! Does not filter out any rows (i.e. no SQL will be executed)
+! Also, keeps the same number of pools as in the originating database,
+! unless -a option is used, which enables append-mode i.e.
+! as many new pools will be added as there are in the INPUT_DATABASE_NAME
+! (= enables incremental creation timeseries database)
+!
+! -k option enables to convert $ODB_LAT (def=lat at hdr) and $ODB_LON (def=lon at hdr) to degrees
+! before writing to output database
+!
+! -v option provides more verbose output
+!
+! -m membytes option limits number of bytes per each ODB_get (default=2147483647)
+!
+! Poolmask (for input database) can be used to define more fine grained input/output of pools
+!
+! 02-Dec-2005 : Initial version by Sami Saarinen
+!
+
+USE PARKIND1  ,ONLY : JPIM,JPRB
+USE odb_module
+USE mpl_module
+USE YOMHOOK, ONLY : LHOOK, DR_HOOK
+
+IMPLICIT NONE
+
+REAL(KIND=JPRB) :: ZHOOK_HANDLE
+INTEGER(KIND=JPIM) :: myproc, nproc, jtbl, errflg, ntbl, nra, jp, jcol, ntbl_in
+INTEGER(KIND=JPIM) :: j, numargs, rc, nrows, old_npools_out, jp_out
+INTEGER(KIND=JPIM) :: h_in , ncols_in , npools_in , npools_more, poolmask_set
+INTEGER(KIND=JPIM) :: h_out, ncols_out, npools_out, jj, iloop, ilatlon_rad
+INTEGER(KIND=JPIM) :: istart, ilimit, igot, membytes, ncols_max, itotal, itmp
+REAL(KIND=JPRB), allocatable, TARGET :: x(:,:)
+REAL(KIND=JPRB), POINTER :: z(:,:)
+character(len=8)   :: open_mode
+character(len=256) :: a_out, arg, input_db, output_db
+character(len=256), allocatable :: in_names(:), out_names(:), table(:), table_in(:)
+character(len=256) :: ODB_LAT, ODB_LON, ODB_LATLON_RAD
+logical :: LLappend, LLkonvert, LLidentical, LLverbose
+logical, allocatable :: LLtaken(:), LL_poolmask(:), LLcommon(:)
+INTEGER(KIND=JPIM), allocatable :: take_this(:), pool_list(:)
+REAL(KIND=JPRB) :: RAD2DEG, xx
+REAL(KIND=JPRB) :: RPI, RADIANS, RDEGREE
+RAD2DEG(xx) = RDEGREE * xx
+
+IF (LHOOK) CALL DR_HOOK('ODBCOMPRESS',0,ZHOOK_HANDLE)
+
+!-- Consistent with odb/cma2odb/sunumc1.F90
+RPI    =2.0_JPRB*ASIN(1.0_JPRB)
+RADIANS=RPI/180._JPRB
+RDEGREE=180._JPRB/RPI
+
+rc = ODB_init(myproc=myproc,nproc=nproc)
+
+! -i input_db
+! -o output_db
+! -a            output database will be opened in append_mode
+! -k            apply rad2deg() on $ODB_LAT & $ODB_LON and set $ODB_LATLON_RAD values to zero
+! -v            be more verbose
+
+errflg = 0
+numargs = MPL_iargc()
+call MPL_getarg(0,a_out)
+
+input_db = ' '
+output_db = ' '
+LLappend = .FALSE.
+LLkonvert = .FALSE.
+LLverbose = .FALSE.
+membytes = 2147483647
+
+j = 0
+do while (j < numargs)
+  j = j + 1
+  call MPL_getarg(j,arg)
+  if (arg == '-a') then
+    LLappend = .TRUE.
+  else if (arg == '-k') then
+    LLkonvert = .TRUE.
+  else if (arg == '-v') then
+    LLverbose = .TRUE.
+  else if (arg == '-i' .and. j < numargs) then
+    j = j + 1
+    call MPL_getarg(j,arg)
+    input_db = arg
+  else if (arg == '-o' .and. j < numargs) then
+    j = j + 1
+    call MPL_getarg(j,arg)
+    output_db = arg
+  else if (arg == '-m' .and. j < numargs) then
+    j = j + 1
+    call MPL_getarg(j,arg)
+    read(arg,'(i20)') membytes
+    membytes = max(1048576,membytes)
+  else
+    write(0,*)'***Error: Unrecognized option "'//trim(arg)//'"'
+    errflg = errflg + 1
+  endif
+enddo
+
+if (input_db == ' ')  then
+  write(0,*)'***Error: No input database (-i option) given'
+  errflg = errflg + 1
+endif
+
+if (output_db == ' ') then
+  write(0,*)'***Error: No output database (-o option) given'
+  errflg = errflg + 1
+endif
+
+if (errflg > 0) then ! Abort
+  write(0,*)'***Error(s) in argument list : rc=',errflg
+  CALL ODB_abort(trim(a_out),'Error(s) in argument list', errflg)
+endif
+
+1000 format(1x,a)
+1001 format(1x,a,i5,a,i5)
+1002 format(1x,a,3i13)
+1003 format(1x,a,i5,a,4i12)
+1004 format(1x,a,i12,a)
+
+if (LLkonvert) then
+  CALL codb_getenv('ODB_LAT',ODB_LAT)
+  if (ODB_LAT == ' ') ODB_LAT = 'lat at hdr'
+  CALL codb_getenv('ODB_LON',ODB_LON)
+  if (ODB_LON == ' ') ODB_LON = 'lon at hdr'
+  write(0,1000)'odbcompress: Converting ('//trim(ODB_LAT)//','//trim(ODB_LON)//') to degrees'
+  CALL codb_getenv('ODB_LATLON_RAD',ODB_LATLON_RAD)
+  if (ODB_LATLON_RAD == ' ') ODB_LATLON_RAD = 'latlon_rad at desc'
+  write(0,1000)'odbcompress: Setting '//trim(ODB_LATLON_RAD)//' entries to zero'
+else
+  CALL codb_getenv('ODB_LATLON_RAD',ODB_LATLON_RAD)
+  if (ODB_LATLON_RAD == ' ') ODB_LATLON_RAD = 'latlon_rad at desc'
+  write(0,1000)'odbcompress: Setting '//trim(ODB_LATLON_RAD)//' entries to one'
+endif
+
+h_in = ODB_open(input_db, 'READONLY', npools_in)
+
+!-- Input pool selection
+allocate(pool_list(npools_in))
+pool_list(:) = 0
+CALL cODB_get_poolmask(h_in, npools_in, pool_list, poolmask_set, rc)
+
+npools_more = 0
+allocate(LL_poolmask(npools_in))
+if (rc == 0 .or. poolmask_set == 0) then
+!-- by default all pools
+  LL_poolmask(:) = .TRUE. ! i.e. do process ALL pools
+  npools_more = npools_in
+else
+!-- be more selective
+  LL_poolmask(:) = .FALSE. ! i.e. do NOT process any pools by default
+  do jp=1,npools_in
+    if (pool_list(jp) == 1) then
+      LL_poolmask(jp) = .TRUE.
+      npools_more = npools_more + 1
+    endif
+  enddo
+endif
+deallocate(pool_list)
+
+npools_out = npools_more
+open_mode = 'NEW'
+if (LLappend) open_mode = 'APPEND'
+
+old_npools_out = 0
+h_out = ODB_open(output_db, open_mode, npools_out, old_npools=old_npools_out)
+
+if (old_npools_out > 0) then
+  npools_out = ODB_addpools(h_out, npools_more)
+endif
+
+ntbl = ODB_getnames(h_out, '*', 'table')
+allocate(table(ntbl))
+ntbl = ODB_getnames(h_out, '*', 'table', table)
+
+ntbl_in = ODB_getnames(h_in, '*', 'table')
+allocate(table_in(ntbl_in))
+ntbl_in = ODB_getnames(h_in, '*', 'table', table_in)
+
+allocate(LLcommon(ntbl_in))
+LLcommon(:) = .FALSE.
+do j=1,ntbl
+  do jtbl=1,ntbl_in
+    if (LLcommon(jtbl)) cycle
+    if (table_in(jtbl) == table(j)) then
+      LLcommon(jtbl) = .TRUE.
+      exit
+    endif
+  enddo
+enddo
+
+deallocate(table)
+nullify(z)
+
+if (LLverbose) write(0,1004)'odbcompress: Amount of memory given to ODB_get() = ',membytes,' bytes'
+
+jp_out = old_npools_out
+do jp=1,npools_in ! Loop over input pools
+  if (.not.LL_poolmask(jp)) cycle
+  jp_out = jp_out + 1
+  if (LLverbose) write(0,*)
+  write(0,1001)'odbcompress: input pool#',jp,' goes to output pool#',jp_out
+
+  TABLE_LOOP: do jtbl=1,ntbl_in 
+    ! Note: We loop over the table-names that are common for INPUT *and* OUTPUT databases.
+    !    Otherwise (if only OUTPUT/INPUT-table names were used) we could get error messages, like:
+    !       get_forfunc: Unregistered (handle,dbname,poolno,it,dataname)=(1,'DBNAME',1,0,'@poolmask')
+
+    if (.not.LLcommon(jtbl)) cycle TABLE_LOOP
+
+    rc = ODB_select(h_in, table_in(jtbl), nrows, ncols_in, nra=nra, poolno=jp)
+
+    if (LLverbose) write(0,1002) 'odbcompress: Input table "'//trim(table_in(jtbl))//'" : nrows,ncols_in,nra=',&
+         &                                                                                 nrows,ncols_in,nra
+
+    if (nrows <= 0) cycle TABLE_LOOP
+
+    allocate(in_names(ncols_in))
+    rc = ODB_getnames(h_in, table_in(jtbl), 'name', in_names)
+
+    ncols_out = ODB_getnames(h_out, table_in(jtbl), 'name')
+    allocate(out_names(ncols_out))
+    rc = ODB_getnames(h_out, table_in(jtbl), 'name', out_names)
+
+    LLidentical = (ncols_in == ncols_out)
+    if (LLidentical) LLidentical = ALL(in_names(:) == out_names(:))
+
+    if (LLverbose .and. LLidentical) write(0,*) 'odbcompress: input & output tables are identical'
+
+    if (LLverbose) write(0,1002) 'odbcompress: Output table "'//trim(table_in(jtbl))//'" : nrows,ncols_out,nra=',&
+         &                                                                                  nrows,ncols_out,nra
+
+    allocate(take_this(ncols_out))
+    take_this(:) = 0
+
+    allocate(LLtaken(ncols_in))
+    LLtaken(:) = .FALSE.
+
+    OUTER: do jcol=1,ncols_out
+      INNER: do j=1,ncols_in
+        if (LLtaken(j)) cycle INNER
+        if (out_names(jcol) == in_names(j)) then
+          take_this(jcol) = j
+          LLtaken(j) = .TRUE.
+          exit INNER
+        endif
+      enddo INNER
+    enddo OUTER
+
+    if (LLkonvert) then
+      do jcol=1,ncols_out
+        if (take_this(jcol) > 0) then
+          if (out_names(jcol) == ODB_LAT .or. out_names(jcol) == ODB_LON) then
+            ! reversing the sign triggers rad2deg() conversion
+            take_this(jcol) = -take_this(jcol)
+          endif
+        endif
+      enddo
+    endif
+    
+    ! In the next we assume that ODB_LATLON_RAD never sits in the same table as ODB_LAT or ODB_LON
+    ilatlon_rad = -1
+    if (ALL(take_this(:) >= 0)) then
+       do jcol=1,ncols_out
+          if (take_this(jcol) > 0) then
+             if (out_names(jcol) == ODB_LATLON_RAD) then
+                ! reversing the sign enforces values at latlon_rad at desc to be 0
+                take_this(jcol) = -take_this(jcol)
+                if (LLkonvert) then
+                   ilatlon_rad = 0
+                else
+                   ilatlon_rad = 1
+                endif
+                exit
+             endif
+          endif
+       enddo
+    endif
+  
+    if (ilatlon_rad /= -1) then
+       rc = ODB_setval(h_out,'$latlon_rad',ilatlon_rad)
+    endif
+
+    deallocate(in_names)
+    deallocate(out_names)
+
+    ncols_max = max(ncols_in, ncols_out) + 1
+!   ilimit * ncols_max * 8 <= membytes  ==> ilimit = max(1,membytes / (ncols_max * 8))
+    ilimit = max(1,membytes / (ncols_max * 8))
+    ilimit = min(ilimit, nrows)
+    nra = ODB_lda(ilimit) ! nra re-defined
+
+    if (LLverbose) write(0,*) 'odbcompress: Allocating space for input-array x'
+    allocate(x(nra,0:ncols_in))
+
+    if (LLidentical) then
+      if (LLverbose) write(0,*) 'odbcompress: Input-array x shares space with output-array z'
+      z => x
+    else
+      if (LLverbose) write(0,*) 'odbcompress: Allocating space for output-array z'
+      allocate(z(nra,0:ncols_out))
+    endif
+
+    istart = 1
+    itotal = 0
+    iloop = 0
+    GET_LOOP: do while (ilimit > 0)
+       igot = 0
+       iloop = iloop + 1
+       if (LLverbose) write(0,1003) 'odbcompress: GET_LOOP#',iloop,'> istart,ilimit,itotal,nrows=',&
+            &                                                          istart,ilimit,itotal,nrows
+
+       itmp = ilimit
+       igot = ODB_get(h_in, table_in(jtbl), x, itmp, ncols_in, &
+            &         colget=LLtaken, colfree=LLtaken, poolno=jp, &
+            &         start=istart, limit=ilimit)
+
+       itotal = itotal + igot
+       ilimit = min(ilimit, nrows - itotal)
+
+       if (LLverbose) write(0,1003) 'odbcompress: GET_LOOP#',iloop,'<   igot,ilimit,itotal,nrows=',&
+            &                                                            igot,ilimit,itotal,nrows
+
+       if (igot == 0) exit GET_LOOP
+
+       do jcol=1,ncols_out
+          if (take_this(jcol) > 0) then
+             j = take_this(jcol)
+             if (.not.LLidentical) z(1:igot,jcol) = x(1:igot,j)
+          else if (take_this(jcol) < 0) then ! i.e. apply "konvert" for this column !!
+             j = -take_this(jcol)
+             if (ilatlon_rad /= -1) then
+                z(1:igot,jcol) = 0 ! Values (usually) at 'latlon_rad at desc'
+             else
+                do jj=1,igot
+                   z(jj,jcol) = rad2deg(x(jj,j)) ! Usually 'lat at hdr' and/or 'lon at hdr'
+                enddo
+             endif
+          else
+             z(1:igot,jcol) = 0 ! usual default; could be NMDI or RMDI ! need to know the type, anyway
+          endif
+       enddo
+
+       itmp = igot
+       rc = ODB_put(h_out, table_in(jtbl), z, itmp, ncols_out, poolno=jp_out)
+
+       istart = istart + igot
+    enddo GET_LOOP ! do while (ilimit > 0)
+
+    rc = ODB_swapout(h_in, table_in(jtbl), poolno=jp)
+
+    if (.not.LLidentical) then
+      deallocate(x)
+      if (LLverbose) write(0,*) 'odbcompress: Input-array x de-allocated'
+      deallocate(z)
+      if (LLverbose) write(0,*) 'odbcompress: Output-array z de-allocated'
+    else
+      deallocate(x)
+      if (LLverbose) write(0,*) 'odbcompress: Input-array x de-allocated'
+    endif
+    nullify(z)
+    
+    deallocate(LLtaken)
+    deallocate(take_this)
+
+    if (ODB_io_method(h_out) /= 4) then
+      rc = ODB_swapout(h_out, table_in(jtbl), save = .TRUE., poolno=jp_out)
+    else
+      rc = ODB_pack(h_out, table_in(jtbl), poolno=jp_out)
+    endif
+
+    if (LLverbose) write(0,1002) 'odbcompress: table "'//trim(table_in(jtbl))//'" done.'
+  enddo TABLE_LOOP ! do jtbl=1,ntbl_in
+
+  rc = ODB_release(h_in, poolno=jp)
+enddo
+
+deallocate(table_in)
+deallocate(LLcommon)
+deallocate(LL_poolmask)
+
+write(0,1000)'odbcompress: closing databases ...'
+
+rc = ODB_close(h_out, save = .TRUE.)
+rc = ODB_close(h_in)
+
+write(0,1000)'odbcompress: all processing done'
+
+rc = ODB_end()
+
+IF (LHOOK) CALL DR_HOOK('ODBCOMPRESS',1,ZHOOK_HANDLE)
+END PROGRAM odbcompress
diff --git a/odb/src/tools/Odbdiff.F90 b/odb/src/tools/Odbdiff.F90
new file mode 100644
index 0000000..5829b06
--- /dev/null
+++ b/odb/src/tools/Odbdiff.F90
@@ -0,0 +1,647 @@
+program odbdiff
+! This program opens two ODB databases DB1 & DB2
+! and apply a query on both to find out data differences
+USE PARKIND1  ,ONLY : JPIM,JPIB,JPRB
+use odb_module
+use mpl_module
+USE str, only : toupper, sadjustr
+USE yomhook, only : LHOOK, DR_HOOK
+implicit none
+REAL(KIND=JPRB), parameter :: rscale = 1000000._JPRB
+REAL(KIND=JPRB), parameter :: eps = tiny(rscale)
+INTEGER(KIND=JPIM) :: h(2), npools(2), nrows(2), ncols(2), nra
+INTEGER(KIND=JPIM) :: j, jj, jp, rc, nkey, ilen, mkey(2), idx, nr, seqno, icolor
+INTEGER(KIND=JPIM) :: istart, iend, ntotdiffs, numargs, maxdiffnum, ndiffs
+INTEGER(KIND=JPIM) :: icol_lat(2), icol_lon(2), irad2deg(2), nbits, itmp
+INTEGER(KIND=JPIM) :: adjust_right, jjj, doffset, memopt, jstart, jend, inc
+INTEGER(KIND=JPIM) :: k, j1, j2, kk
+character(len=1024) :: cmd, simulobs_file
+character(len=64)   :: DB1, DB2, query, color
+character(len=30)   :: cnum
+INTEGER(KIND=JPIM)  :: irefval
+character(len=8) :: ztr
+REAL(KIND=JPRB)   , allocatable :: x1(:,:), x2(:,:), z(:)
+INTEGER(KIND=JPIM), allocatable :: sortidx1(:), isort(:,:)
+logical, allocatable :: LLtakethis1(:), LLtakethis2(:)
+INTEGER(KIND=JPIM), allocatable :: pick1(:), pick2(:), xrossref(:)
+character(len=64) , allocatable :: names1(:), names2(:), types(:)
+logical :: LLmatch, LLddl, LLrad2deg(2), LLmemopt, LLfirst, LLlast
+logical, allocatable :: LLstring(:), LLint(:), LLmask(:)
+REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZH1(3), ZH2(5)
+REAL(KIND=JPRB) :: RAD2DEG, x, rlatinc, lat0, lat1, lat2
+REAL(KIND=JPRB) :: RPI, RADIANS, RDEGREE
+RAD2DEG(x) = RDEGREE * x
+
+IF (LHOOK) CALL DR_HOOK('ODBDIFF',0,ZHOOK_HANDLE)
+rc = ODB_init()
+
+RPI    =2.0_JPRB*ASIN(1.0_JPRB)
+RADIANS=RPI/180._JPRB
+RDEGREE=180._JPRB/RPI
+
+numargs = MPL_iargc()
+maxdiffnum = 2147483647
+simulobs_file = '/dev/null'
+color = '_color'
+icolor = 1
+irad2deg(:) = 0
+nbits = 0
+adjust_right = 0
+memopt=0
+rlatinc = 0
+if (numargs /= 13) then
+  call MPL_getarg(0,cmd)
+  write(0,*) 'Usage: '//trim(cmd)//' DB1 DB2 query_name maxdiffnum simulobs_file '//&
+           & 'color 1_or_2 rad2deg1 rad2deg2 nbits adjust_right memopt rlatinc'
+  CALL ODB_abort('MAIN','No. of args must be 13',numargs)
+else
+  if (numargs >= 1) then
+    call MPL_getarg(1,DB1)
+    write(0,*)'===== DB1='//trim(DB1)//' ====='
+  endif
+  if (numargs >= 2) then
+    call MPL_getarg(2,DB2)
+    write(0,*)'===== DB2='//trim(DB2)//' ====='
+  endif
+  if (numargs >= 3) then
+    call MPL_getarg(3,query)
+    write(0,*)'===== Query='//trim(query)//' ====='
+  endif
+  if (numargs >= 4) then
+    call MPL_getarg(4,cnum)
+    read(cnum,'(i30)') maxdiffnum
+    if (maxdiffnum <= 0) maxdiffnum = 2147483647
+  endif
+  write(0,*)'===== Max no. of diffs=',maxdiffnum,' before stopping ====='
+  if (numargs >= 5) then
+    call MPL_getarg(5,simulobs_file)
+  endif
+  write(0,*)'===== Simulobs input on diffs goes to file='//trim(simulobs_file)//' ===='
+  if (numargs >= 6) then
+    call MPL_getarg(6,color)
+    if (color == ' ') color = '_color'
+  endif
+  write(0,*)'===== Simulobs color column='//trim(color)//' ===='
+  if (numargs >= 7) then
+    call MPL_getarg(7,cnum)
+    read(cnum,'(i30)') icolor
+    if (icolor <= 0) icolor = 1
+  endif
+  write(0,*)'===== Poolno for database REFCMP=',icolor,' ===='
+  if (numargs >= 8) then
+    call MPL_getarg(8,cnum)
+    read(cnum,'(i30)') irad2deg(1)
+  endif
+  write(0,*)'===== Radians to degree conversion to be performed for DB='//trim(DB1)//' : ',irad2deg(1),' ===='
+  if (numargs >= 9) then
+    call MPL_getarg(9,cnum)
+    read(cnum,'(i30)') irad2deg(2)
+  endif
+  write(0,*)'===== Radians to degree conversion to be performed for DB='//trim(DB2)//' : ',irad2deg(2),' ===='
+  if (numargs >= 10) then
+    call MPL_getarg(10,cnum)
+    read(cnum,'(i30)') nbits
+    if (nbits <  0) nbits =  0
+    if (nbits > 64) nbits = 64
+  endif
+  write(0,*)'===== Number of last bits to be masked out from converted (lat,lon) = ',nbits,' ===='
+  if (numargs >= 11) then
+    call MPL_getarg(11,cnum)
+    read(cnum,'(i30)') adjust_right
+  endif
+  write(0,*)'===== Right-adjust all strings = ',adjust_right,' ===='
+  if (numargs >= 12) then
+    call MPL_getarg(12,cnum)
+    read(cnum,'(i30)') memopt
+  endif
+  write(0,*)'===== Memory optimization for reference database (1=on/0=off) = ',memopt,' ===='
+  if (numargs >= 13) then
+    call MPL_getarg(13,cnum)
+    read(cnum,'(f30.0)') rlatinc
+    rlatinc = abs(rlatinc)
+    rlatinc = max(rlatinc,0.1_JPRB) ! Minimum lat.band slice at least 0.1 degrees
+  endif
+  write(0,*)'===== Latitude increment =',rlatinc,' ===='
+endif
+LLmemopt = (memopt == 1)
+LLrad2deg(1) = (irad2deg(1) == 1)
+LLrad2deg(2) = (irad2deg(2) == 1)
+icol_lat(:) = 0
+icol_lon(:) = 0
+
+ntotdiffs = 0
+LLfirst = .TRUE.
+lat0 = -90
+inc = 0
+nkey = 0
+
+ 100  continue
+!-----------------------------------------------------------------------------------
+
+lat1 = lat0 + inc * rlatinc
+inc = inc + 1
+lat2 = lat0 + inc * rlatinc
+LLlast = (lat2 >= 90)
+
+write(0,*)'==> Running with lat1=',lat1,', lat2=',lat2,' : inc=',inc
+
+!-----------------------------------------------------------------------------------
+!-- Process database#1 : Read query result into memory & release database
+!-----------------------------------------------------------------------------------
+
+h(1) = ODB_open(DB1,'READONLY',npools=npools(1))
+
+if (LLfirst) then
+  rc = ODB_getnames(h(1),query,'name')
+  ncols(1) = rc
+  allocate(names1(rc), types(rc), LLstring(rc), LLint(rc))
+  LLstring(:) = .FALSE.
+  LLint(:) = .FALSE.
+  allocate(LLtakethis1(rc), pick1(rc))
+  rc = ODB_getnames(h(1),query,'name',names1)
+  rc = ODB_getnames(h(1),query,'type',types)
+  do j=1,rc
+    if (names1(j)(1:8) == 'LINKLEN(') then
+      idx = scan(names1(j),')')
+      if (idx > 0) then
+        names1(j) = names1(j)(9:idx-1)//'.len'//names1(j)(idx+1:)
+      endif
+    else if (names1(j)(1:11) == 'LINKOFFSET(') then
+      idx = scan(names1(j),')')
+      if (idx > 0) then
+        names1(j) = names1(j)(12:idx-1)//'.offset'//names1(j)(idx+1:)
+      endif
+    endif
+    idx = scan(names1(j),'@',back=.TRUE.)
+    if (idx > 0) names1(j)(idx:idx) = '_'
+    idx = scan(names1(j),'.')
+    if (idx > 0) then
+      names1(j) = names1(j)(1:idx-1)//'_dot_'//names1(j)(idx+1:)
+    endif
+  enddo
+endif ! if (LLfirst)
+
+!-----------------------------------------------------------------------------------
+!-- Open database#2 just to obtain ncols(2) and desired names2(:)
+!-----------------------------------------------------------------------------------
+
+if (LLfirst) then
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_QUICKOPEN',0,ZH2(1))
+  h(2) = ODB_open(DB2,'READONLY',npools=npools(2))
+  rc = ODB_getnames(h(2),query,'name')
+  ncols(2) = rc
+  allocate(names2(rc))
+  allocate(LLtakethis2(rc), pick2(rc), xrossref(rc))
+  rc = ODB_getnames(h(2),query,'name',names2)
+  do j=1,rc
+    if (names2(j)(1:8) == 'LINKLEN(') then
+      idx = scan(names2(j),')')
+      if (idx > 0) then
+        names2(j) = names2(j)(9:idx-1)//'.len'//names2(j)(idx+1:)
+      endif
+    else if (names2(j)(1:11) == 'LINKOFFSET(') then
+      idx = scan(names2(j),')')
+      if (idx > 0) then
+        names2(j) = names2(j)(12:idx-1)//'.offset'//names2(j)(idx+1:)
+      endif
+    endif
+    idx = scan(names2(j),'@')
+    if (idx > 0) names2(j)(idx:idx) = '_'
+    idx = scan(names2(j),'.')
+    if (idx > 0) then
+      names2(j) = names2(j)(1:idx-1)//'_dot_'//names2(j)(idx+1:)
+    endif
+  enddo
+  rc = ODB_close(h(2))
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_QUICKOPEN',1,ZH2(1))
+endif
+
+!-----------------------------------------------------------------------------------
+!-- Find common column names between query at DB1 & query at DB2
+!-----------------------------------------------------------------------------------
+
+if (LLfirst) then
+  LLtakethis1(:) = .FALSE.
+  pick1(:) = 0
+  LLtakethis2(:) = .FALSE.
+  pick2(:) = 0
+  xrossref(:) = 0
+
+  k = 0
+  do j1=1,ncols(1)
+    do j2=1,ncols(2)
+      if (LLtakethis2(j2)) then
+        cycle
+      else if (names1(j1) == names2(j2)) then
+        k = k + 1
+        LLtakethis1(j1) = .TRUE.
+        pick1(k) = j1
+        LLtakethis2(j2) = .TRUE.
+        pick2(k) = j2
+        xrossref(j2) = j1
+        exit
+      endif
+    enddo
+  enddo
+
+  nkey = k
+  if (nkey == 0) then
+    write(0,*)'***Error: No common columns between DB1 & DB2 queries: nkey=',nkey
+  endif
+
+    write(0,*)'Query info for DB1="'//trim(DB1)//'" : ncols=',ncols(1)
+    do j1=1,ncols(1)
+      write(0,'(1x,2i10,1x,L1,1x,1h",a,1h")') j1,pick1(j1),LLtakethis1(j1),names1(j1)
+    enddo
+    write(0,*)'Query info for DB2="'//trim(DB2)//'" : ncols=',ncols(2)
+    do j2=1,ncols(2)
+      write(0,'(1x,2i10,1x,L1,1x,1h",a,1h")') j2,pick2(j2),LLtakethis2(j2),names2(j2)
+    enddo
+    write(0,*)'xrossref: size=',size(xrossref),', values follow:'
+    write(0,*) xrossref(:)
+
+  if (nkey == 0) then
+    CALL ODB_abort('MAIN','No common columns between DB1 & DB2 queries',-2)
+  endif
+
+  do j=1,ncols(1)
+    if (LLtakethis1(j)) then
+      if (types(j) == 'Bitfield') types(j) = 'pk1int'
+      LLstring(j) = (types(j) == 'string')
+      LLint(j) = (scan(types(j),'int') > 0 .or. types(j)(1:4) == 'link')
+      if (LLrad2deg(1) .and. names1(j)(1:7) == 'lat_hdr') icol_lat(1) = j ! hardcoding : 'lat_hdr'
+      if (LLrad2deg(1) .and. names1(j)(1:7) == 'lon_hdr') icol_lon(1) = j ! hardcoding : 'lon_hdr'
+    endif
+  enddo
+
+  do j=1,ncols(2)
+    if (LLtakethis2(j)) then
+      if (LLrad2deg(2) .and. names2(j)(1:7) == 'lat_hdr') icol_lat(2) = j ! hardcoding : 'lat_hdr'
+      if (LLrad2deg(2) .and. names2(j)(1:7) == 'lon_hdr') icol_lon(2) = j ! hardcoding : 'lon_hdr'
+    endif
+  enddo
+
+  do j=1,2
+    if (icol_lat(j) == 0 .or. icol_lon(j) == 0) LLrad2deg(j) = .FALSE.
+    if (.not. LLrad2deg(j)) then
+      icol_lat(j) = 0
+      icol_lon(j) = 0
+    endif
+  enddo
+
+  if (trim(simulobs_file) /= '/dev/null' .and. trim(simulobs_file) /= ' ') then
+    open(1,file='REFCMP.ddl',status='unknown',position='rewind')
+    write(1,'(a)') 'CREATE TABLE refcmp AS ('
+    do j=1,ncols(1)
+      if (LLtakethis1(j)) then
+        write(1,'(2x,a)') trim(names1(j))//' '//trim(types(j))//','
+      endif
+    enddo
+    write(1,'(2x,a)') trim(color)//' pk1int,'
+    write(1,'(a)') ');'
+    close(1)
+    LLddl = .true.
+  else
+    LLddl = .false.
+  endif
+
+  deallocate(names2)
+endif
+
+!-----------------------------------------------------------------------------------
+!-- Continue processing with database#1 
+!-----------------------------------------------------------------------------------
+
+jp = -1 ! All pools in one go for database#1 (you may not have enough memory for this
+        ! ==> to be fixed later; meanwhile: ask less data in your query ;-)
+        !     or use latitude-band approach
+
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_OPENGETCLOSE',0,ZH1(1))
+
+if (LLfirst) then
+  rc = ODB_setval(h(1), '$lat1', lat1-eps, query)
+else
+  rc = ODB_setval(h(1), '$lat1', lat1, query)
+endif
+
+if (LLlast) then
+  rc = ODB_setval(h(1), '$lat2', lat2+eps, query)
+else
+  rc = ODB_setval(h(1), '$lat2', lat2, query)
+endif
+
+rc = ODB_select(h(1), query, nrows(1), ncols(1), nra=nra, poolno=jp)
+write(0,*) '<1>poolno=',jp,' : nrows(1) = ',nrows(1)
+allocate(x1(nra,0:ncols(1)))
+
+if (LLmemopt) then
+! Load incrementally to fit more into memory (can be much slower)
+  jstart=1
+  jend=npools(1)
+else
+! Load all in one go (may not fit into memory)
+  jstart=-1
+  jend=-1
+endif
+
+doffset = 0
+do jp=jstart,jend
+  rc = ODB_get(h(1), query, x1, nrows(1), ncols(1), offset=doffset, poolno=jp, &
+       &       colget=LLtakethis1)
+  write(0,*) '<1>poolno=',jp,' : doffset, rc =',doffset, rc
+  doffset = doffset + rc
+  rc = ODB_cancel(h(1), query, poolno=jp)
+  rc = ODB_release(h(1), poolno=jp)
+enddo
+
+rc = ODB_close(h(1))
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_OPENGETCLOSE',1,ZH1(1))
+
+write(0,*)'==> nkey =',nkey
+ilen = nkey * 8 ! nkey times 8 bytes
+
+allocate(z(nkey))
+
+!..... Perform radians to degrees conversion for (lat,lon), if requested/applicable
+if (LLrad2deg(1)) then
+  do j=1,nrows(1)
+    x1(j,icol_lat(1)) = rad2deg(x1(j,icol_lat(1)))
+    x1(j,icol_lon(1)) = rad2deg(x1(j,icol_lon(1)))
+  enddo
+endif
+
+!..... Mask out (zero) <nbits> last bits that are due to rounding of error on different machines
+
+if (LLrad2deg(1)) then
+  write(0,*)'==> nbits=',nbits
+
+  if (LLrad2deg(1)) then
+    call cmask64bits(x1(1,icol_lat(1)),nrows(1),nbits)
+    call cmask64bits(x1(1,icol_lon(1)),nrows(1),nbits)
+  endif
+
+  if (LLrad2deg(1)) then
+    do j=1,nrows(1)
+      itmp = nint(x1(j,icol_lat(1)) * rscale)
+      x1(j,icol_lat(1)) = itmp
+      itmp = nint(x1(j,icol_lon(1)) * rscale)
+      x1(j,icol_lon(1)) = itmp
+    enddo
+  endif
+endif
+
+!..... Right-adjust strings, if any
+if (adjust_right == 1 .and. any(LLstring(:))) then
+  do jj=1,ncols(1)
+    if (LLtakethis1(jj) .and. LLstring(jj)) then
+      do j=1,nrows(1)
+        x = x1(j,jj)
+        write(ztr,'(a8)') x
+        ztr = sadjustr(ztr)
+        read(ztr,'(a8)') x
+        x1(j,jj) = x
+      enddo
+    endif
+  enddo
+endif
+
+!..... Generate adjusted 32-bit cyclic redundancy check -key (a pseudo-seqno)
+allocate(isort(nrows(1),2))
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_CRC32',0,ZH1(2))
+do j=1,nrows(1)
+  isort(j,1) = 0
+  z(1:nkey) = x1(j,pick1(1:nkey))
+  call crc32(z(1),ilen,isort(j,1))  ! Generate near-unique key
+enddo
+do j=1,nrows(1)
+  isort(j,2) = j
+enddo
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_CRC32',1,ZH1(2))
+
+allocate(sortidx1(nrows(1)))
+mkey(1) = 1
+mkey(2) = 2
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_KEYSORT',0,ZH1(3))
+call keysort(rc,isort,nrows(1),multikey=mkey,index=sortidx1,init=.true.)
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB1_KEYSORT',1,ZH1(3))
+
+allocate(LLmask(nrows(1)))
+LLmask(:) = .TRUE.
+
+if (LLfirst .and. LLddl) then
+  open(1,file=trim(simulobs_file),status='unknown',position='append')
+  do j=1,ncols(1)
+    if (LLtakethis1(j)) then
+      write(1,'(1x,a)',advance='no') trim(names1(j))
+    endif
+  enddo    
+  write(1,'(1x,a)',advance='no') trim(color)
+  write(1,*)
+endif
+
+if (LLfirst) then
+  deallocate(names1)
+  deallocate(types)
+endif
+
+!-----------------------------------------------------------------------------------
+!-- Process database#2
+!-----------------------------------------------------------------------------------
+
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_OPENGETCLOSE',0,ZH2(1))
+h(2) = ODB_open(DB2,'READONLY',npools=npools(2))
+
+if (LLfirst) then
+  rc = ODB_setval(h(2), '$lat1', lat1-eps, query)
+else
+  rc = ODB_setval(h(2), '$lat1', lat1, query)
+endif
+
+if (LLlast) then
+  rc = ODB_setval(h(2), '$lat2', lat2+eps, query)
+else
+  rc = ODB_setval(h(2), '$lat2', lat2, query)
+endif
+
+nr = 0
+DB2_LOOP: do jp=1,npools(2) ! Pool-by-pool to save memory 
+  ndiffs = 0
+
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_SELECTGETRELEASE',0,ZH2(2))
+  rc = ODB_select(h(2), query, nrows(2), ncols(2), nra=nra, poolno=jp)
+  write(0,1000,advance='no') '<2>poolno=',jp,' : nrows(2) = ',nrows(2),char(13)
+ 1000 format(1x,a,i5,a,i12,a)
+
+  if (nrows(2) == 0) then
+    rc = ODB_release(h(2), poolno=jp)
+    IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_SELECTGETRELEASE',1,ZH2(2))
+    cycle DB2_LOOP
+  endif
+
+  nr = nr + nrows(2)
+
+  allocate(x2(nra,0:ncols(2)))
+  rc = ODB_get(h(2), query, x2, nrows(2), ncols(2), poolno=jp, &
+       &       colget=LLtakethis2)
+  rc = ODB_release(h(2), poolno=jp)
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_SELECTGETRELEASE',1,ZH2(2))
+
+  if (LLrad2deg(2)) then
+    do j=1,nrows(2)
+      x2(j,icol_lat(2)) = rad2deg(x2(j,icol_lat(2)))
+      x2(j,icol_lon(2)) = rad2deg(x2(j,icol_lon(2)))
+    enddo
+  endif
+
+  if (LLrad2deg(2)) then
+    if (LLrad2deg(2)) then
+      call cmask64bits(x2(1,icol_lat(2)),nrows(2),nbits)
+      call cmask64bits(x2(1,icol_lon(2)),nrows(2),nbits)
+    endif
+
+    if (LLrad2deg(2)) then
+      do j=1,nrows(2)
+        itmp = nint(x2(j,icol_lat(2)) * rscale)
+        x2(j,icol_lat(2)) = itmp
+        itmp = nint(x2(j,icol_lon(2)) * rscale)
+        x2(j,icol_lon(2)) = itmp
+      enddo
+    endif
+  endif
+
+  if (adjust_right == 1 .and. any(LLstring(:))) then
+    do jj=1,ncols(2)
+      if (.not.LLtakethis2(jj)) cycle
+      kk = xrossref(jj)
+      if (LLstring(kk)) then
+        do j=1,nrows(2)
+          x = x2(j,jj)
+          write(ztr,'(a8)') x
+          ztr = sadjustr(ztr)
+          read(ztr,'(a8)') x
+          x2(j,jj) = x
+        enddo
+      endif
+    enddo
+  endif
+
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_CRC32',0,ZH2(4))
+  do j=1,nrows(2)
+    seqno = 0
+    z(1:nkey) = x2(j,pick2(1:nkey))
+    call crc32(z(1),ilen,seqno) ! Generate near-unique key
+    x2(j,0) = seqno
+  enddo
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_CRC32',1,ZH2(4))
+
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_MATCHING',0,ZH2(3))
+  A_LOOP: do j=1,nrows(2)
+    irefval = x2(j,0)
+    idx = ODB_binsearch(irefval, isort(1:nrows(1),1), 1, nrows(1), &
+                       & index=sortidx1, &
+                       & cluster_start=istart, cluster_end=iend)
+
+    LLmatch = (idx >= 1 .and. idx <= nrows(1))
+
+    if (LLmatch) then
+      z(1:nkey) = x2(j,pick2(1:nkey))
+      LLmatch = .FALSE.
+      IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_LINEAR_SEARCH_LOOP',0,ZH2(5))
+      LOOP: do jj=istart,iend
+        if (.not.LLmask(jj)) cycle LOOP
+        idx = sortidx1(jj)
+        LLmatch = ALL(z(1:nkey) == x1(idx,pick1(1:nkey)))
+        if (LLmatch) then ! An EXACT match found
+          LLmask(jj) = .FALSE. ! Do not match this location twice
+          exit LOOP
+        endif
+      enddo LOOP
+      IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_LINEAR_SEARCH_LOOP',1,ZH2(5))
+    endif
+
+    if (.not.LLmatch) then
+      ndiffs = ndiffs + 1
+      ntotdiffs = ntotdiffs + 1
+      if (LLddl) then
+        do jj=1,ncols(2)
+           if (.not.LLtakethis2(jj)) cycle
+           kk = xrossref(jj)
+           if (LLstring(kk)) then
+             write(ztr,'(a8)') x2(j,jj)
+             do jjj=1,len(ztr)
+               itmp = ichar(ztr(jjj:jjj))
+               if (itmp < 32 .or. itmp > 126) ztr(jjj:jjj) = '?'
+             enddo
+             write(1,'(1x,a10)',advance='no') "'"//ztr//"'"
+           else if (LLint(kk)) then
+             write(1,'(1x,i11)',advance='no') int(x2(j,jj))
+           else
+             if (jj == icol_lat(2) .or. jj == icol_lon(2)) then
+               write(1,'(1x,-6p,f20.6)',advance='no') x2(j,jj)
+             else
+               write(1,'(1x,1p,g20.12)',advance='no') x2(j,jj)
+             endif
+           endif
+        enddo
+        write(1,'(1x,i2)',advance='no') icolor
+        write(1,*)
+!-start debug
+!        if (LLrad2deg(1).or.LLrad2deg(2)) then
+!          write(1,'(a)',advance='no') '# 0x:'
+!          do jj=1,ncols(2)
+!            if (jj == icol_lat(1) .or. jj == icol_lon(1) .or. &
+!                jj == icol_lat(2) .or. jj == icol_lon(2)) then
+!              x = x2(j,jj) ! No back-scaling here
+!              write(1,'(1x,g30.20)',advance='no') x
+!              write(1,'(1x,z16.16)',advance='no') x
+!              write(1,'(1x,b64.64)',advance='no') x
+!            endif
+!          enddo
+!          write(1,*)
+!        endif
+!-end debug
+      endif
+      if (ntotdiffs >= maxdiffnum) exit A_LOOP
+    endif
+  enddo A_LOOP
+  IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_MATCHING',1,ZH2(3))
+
+  deallocate(x2)
+  write(0,1100) '<2>poolno=',jp,' : nrows(2) = ',nrows(2), ' > ',ndiffs,' diffs'
+ 1100 format(1x,a,i5,a,i12,a,i12,a)
+  if (ntotdiffs >= maxdiffnum) exit DB2_LOOP
+enddo DB2_LOOP
+
+deallocate(LLmask)
+deallocate(x1)
+deallocate(sortidx1)
+deallocate(isort)
+deallocate(z)
+
+write(0,*)'>>> Number of diffs found =',ntotdiffs,', limit =',maxdiffnum
+
+rc = ODB_close(h(2))
+IF (LHOOK) CALL DR_HOOK('ODBDIFF:DB2_OPENGETCLOSE',1,ZH2(1))
+
+LLfirst = .FALSE.
+
+if (.not.LLlast .and. ntotdiffs < maxdiffnum) goto 100
+
+deallocate(LLstring)
+deallocate(LLint)
+
+deallocate(LLtakethis1)
+deallocate(pick1)
+deallocate(LLtakethis2)
+deallocate(pick2)
+deallocate(xrossref)
+
+if (LLddl) then
+  write(1,'(a,i20)') '# Number of diffs found = ',ntotdiffs
+  close(1)
+endif
+
+rc = ODB_end()
+IF (LHOOK) CALL DR_HOOK('ODBDIFF',1,ZHOOK_HANDLE)
+
+end program odbdiff
diff --git a/odb/src/tools/Odbgnuplot.F90 b/odb/src/tools/Odbgnuplot.F90
new file mode 100644
index 0000000..7646477
--- /dev/null
+++ b/odb/src/tools/Odbgnuplot.F90
@@ -0,0 +1,345 @@
+program odbgnuplot
+!
+!-- To browse particular ODB-table and/or SQL and pass output to "stdout" for use by gnuplot
+!   Based on odbless-program
+!
+!   Usage: 
+!
+! ./odbgnuplot.x info dbname view/tablename starting_row numrows row_buffer_size konvert2degrees every debug
+!
+!  Parameters:
+!
+!  info   = 1 produce info only about column names and number of columns; Quick, no ODB_select() executed
+!         = 0 skip info and do the real thing i.e. execute ODB_select()
+!  dbname = ODB database name e.g. ECMA
+!  view   = view/table name e.g. myview
+!
+!  starting_row = row number to start the output (usually = 1 = default)
+!  numrows = number of rows to display (all = -1 --> 2147483647 will become the limit; default)
+!
+!  row_buffer_size = how many rows max to allocate per each ODB_get() (set to -1 to let the program to select = default)
+!
+!  konvert2degrees = 1 convert radians to degrees for $ODB_LAT (usually "lat at hdr"), $ODB_LON (usually "lon at hdr")
+!                    0 do NOT convert radians to degrees for $ODB_LAT, $ODB_LON (default)
+!
+!  every = 1 to print at most numrows of every pool (controlled via ODB_PERMANENT_POOLMASK_<dbname>; see below)
+!          0 to scan all pools until total numrows has been reached (default)
+!
+!  debug = 1 debug on
+!          0 debug off (default)
+!
+!
+! For example: 
+! 1) info records only:        ./odbgnuplot.x 1 ECMA myview
+! 2) plot first 100 rows only: ./odbgnuplot.x 0 ECMA myview 1 100 100
+! 3) plot all data available and convert possible lat/lon @hdr to degrees; max bufsize 100,000 rows:
+!                              ./odbgnuplot.x 0 ECMA myview 1  -1 100000 1
+! 4) plot a little bit (50 rows) from every pool speficied via ODB_PERMANENT_POOLMASK_ECMA:
+!                              ./odbgnuplot.x 0 ECMA myview 1  50     50 0 1
+!
+!  Pools are controlled via ODB_PERMANENT_POOLMASK_<dbname> or ODB_PERMANENT_POOLMASK
+!
+
+USE PARKIND1  ,ONLY : JPIM,JPRB
+use odb_module
+use mpl_module
+implicit none
+
+CHARACTER(LEN=*), PARAMETER :: progname = 'odbgnuplot'
+
+INTEGER(KIND=JPIM) :: h, rc, npools, nproc, myproc, j, jp, rowbuf, konvert
+INTEGER(KIND=JPIM) :: nrows, ncols, istart, numrows, n, npolled, igot
+INTEGER(KIND=JPIM) :: numargs, ntot, debug, every, info
+INTEGER(KIND=JPIM) :: saved(2)
+INTEGER(KIND=JPIM) :: jp1, jp2, jinc, llc_idx(2)
+INTEGER(KIND=JPIM) :: nchunk, j1, j2, nleft, nmypools, jj
+character(len=256) arg
+character(len=64)  dbname, dtname, latlon_names(size(llc_idx)), env
+logical LLopen, LLclose, LLselect, LLcancel, LLinside, LLkonvert, LLspecial
+logical LLprthdr, LLprttimingstat, LLalloc, LLdebug, LLevery, LLinfo
+INTEGER(KIND=JPIM), allocatable :: mypools(:)
+character(len=maxvarlen), allocatable :: colname(:)
+
+rc = ODB_init(myproc=myproc, nproc=nproc)
+
+info    =    0
+istart  =    1
+numrows =   20
+rowbuf  = 1000
+konvert =    0
+debug   =    0
+every   =    0
+
+numargs = MPL_iargc()
+
+if (numargs >= 3) then
+  if (numargs >= 1) then
+    call MPL_getarg(1, arg)
+    read(arg,'(i12)',err=11,end=11) info
+  endif
+  info = max(0,min(1,info))
+  
+11 continue
+
+  call MPL_getarg(2, dbname)
+  call MPL_getarg(3, dtname)
+  
+  if (numargs >= 4) then
+    call MPL_getarg(4, arg)
+    read(arg,'(i12)',err=44,end=44) istart
+  endif
+  istart = max(1,istart)
+44 continue
+
+  if (numargs >= 5) then
+    call MPL_getarg(5, arg)
+    read(arg,'(i12)',err=55,end=55) numrows
+  endif
+  if (numrows <= 0) numrows = 2147483647
+55 continue
+
+  if (numargs >= 6) then
+    call MPL_getarg(6, arg)
+    read(arg,'(i12)',err=66,end=66) rowbuf
+  endif
+  if (rowbuf <= 0) rowbuf = -1
+66 continue
+
+  if (numargs >= 7) then
+    call MPL_getarg(7, arg)
+    read(arg,'(i12)',err=77,end=77) konvert
+  endif
+77 continue
+
+  if (numargs >= 8) then
+    call MPL_getarg(8, arg)
+    read(arg,'(i12)',err=88,end=88) every
+  endif
+88 continue
+
+  if (numargs >= 9) then
+    call MPL_getarg(9, arg)
+    read(arg,'(i12)',err=99,end=99) debug
+  endif
+99 continue
+
+else
+  call MPL_getarg(0, arg)
+  CALL ODB_abort(progname,&
+  & 'Usage: '//trim(arg)//&
+  & ' info dbname view/tablename starting_row numrows'//&
+  & ' row_buffer_size konvert2degrees summary every debug')
+endif
+
+LLinfo = (info == 1)
+
+if (LLinfo) then
+! Info only: to prevent reading data from any pools or tables
+  call codb_putenv('ODB_CONSIDER_TABLES=//')
+  call codb_putenv('ODB_PERMANENT_POOLMASK_'//trim(dbname)//'=0')
+endif
+
+h = ODB_open(dbname, 'READONLY', npools)
+
+if (LLinfo) then
+! Info only: print ncols followed by column names; then exit the application; costs nothing!
+  ncols = ODB_getnames(h, dtname, 'colname')
+  allocate(colname(1:ncols))
+  ncols = ODB_getnames(h, dtname, 'colname', outnames=colname)
+  write(6,*) ncols
+  do j=1,ncols
+    write(6,'(1x,a)') trim(colname(j))
+  enddo
+  deallocate(colname)
+  rc = ODB_close(h)
+  rc = ODB_end()
+  call exit(0) ! should never end up here
+endif
+
+!-- Fully tolerate errors in time-records i.e. fix records when calling twindow/tdiff funcs
+call codb_allow_time_error(235959)
+
+call codb_putenv('ODB_REPORTER=stdout')
+call codb_putenv('ODB_PRINT_COLON=#')
+
+LLopen = .TRUE.
+LLclose = .FALSE.
+LLselect = .FALSE.
+LLcancel = .FALSE.
+LLkonvert = (konvert == 1)
+if (.not.LLkonvert) konvert = 0
+LLdebug = (debug == 1)
+if (.not.LLdebug) debug = 0
+LLevery = (every == 1)
+if (.not.LLevery) every = 0
+
+if (ODB_has_orderby(h, dtname) .or. &
+!! not implemented yet  & ODB_has_uniqueby(h, dtname) .or. & ! Don't know yet if this is ok
+  & ODB_has_select_distinct(h, dtname)) then
+!-- need all pools in one go, since
+!   either contains ORDERBY
+!   or     SELECT DISTINCT (or UNIQUEBY)
+!   or     combination of ORDERBY with SELECT DISTINCT (or UNIQUEBY)
+  nmypools = 1
+  allocate(mypools(nmypools))
+  mypools(1) = -1
+  jp1 = 1
+  jp2 = 1
+  jinc = 1
+!  jp1 = -1
+!  jp2 = -1
+!  jinc = 1
+  istart = 1
+  numrows = 2147483647
+  rowbuf = -1
+  LLspecial = .TRUE.
+else
+  allocate(mypools(npools))
+  nmypools = ODB_poolinfo(h, mypools, with_poolmask=.TRUE.)
+  jp1 = 1
+  jp2 = nmypools
+  jinc = 1
+!  jp1 = myproc
+!  jp2 = npools
+!  jinc = nproc
+  LLspecial = .FALSE.
+endif
+
+if (LLdebug) then
+ 1001 format(a,/,(6i12))
+  write(0,1001) '$ npools, nmypools, size(mypools), jp1, jp2, jinc, mypools(:)=',&
+      &            npools, nmypools, size(mypools), jp1, jp2, jinc, mypools(:)
+endif
+
+istart = istart - 1 ! "C-indexing" enables more convenient offsetting
+npolled = 0
+ntot = 0
+LLprthdr = .TRUE.
+LLprttimingstat = .FALSE.
+LLalloc = .FALSE.
+
+if (LLevery) then
+  saved(1) = istart
+  saved(2) = numrows
+else
+  saved(:) = 0
+endif
+
+if (LLdebug) then
+  write(0,*) '## every, saved(:)=',every, saved(:)
+endif
+
+OUTER_LOOP: do jj=jp1,jp2,jinc
+  jp = mypools(jj)
+  rc = ODB_select(h, dtname, nrows, ncols, poolno=jp)
+
+  if (LLdebug) then
+     write(0,1000) '>> jp, jp1, jp2, jinc, nrows, ncols=', &
+          &            jp, jp1, jp2, jinc, nrows, ncols
+  endif
+
+  if (nrows > 0) then
+
+    if (LLevery) then
+    !-- This "reset" enables us to fetch at most "numrows" per each pool (in poolmask)
+      istart = npolled + saved(1)
+      numrows = saved(2)
+      if (LLdebug) then
+        write(0,*) '#> npolled, istart, numrows=',npolled, istart, numrows
+      endif
+    endif    
+
+    LLinside = (istart >= npolled .and. istart < npolled + nrows)
+
+    if (LLinside) then
+      nleft = min(nrows, numrows)
+      if (rowbuf == -1) then
+        n = min(nrows, numrows)
+      else if (nrows > rowbuf) then
+        n = rowbuf
+      else
+        n = nrows
+      endif
+      n = min(n,nleft)
+
+      if (.not.LLalloc) then
+        LLalloc = .TRUE.
+
+        if (LLkonvert) then
+          call codb_getenv('ODB_LAT',env)
+          if (env == ' ') env = 'lat at hdr'
+          latlon_names(1) = env
+          call codb_getenv('ODB_LON',env)
+          if (env == ' ') env = 'lon at hdr'
+          latlon_names(2) = env
+          ! llc stands for latitude,longitude,color !
+          rc = ODB_varindex(h, dtname, latlon_names, llc_idx)
+          ! lat and/or lon will be converted to degrees, if corresponding llc_idx(:) was positive
+          if (llc_idx(1) > 0) llc_idx(1) = -llc_idx(1) ! due to the stupid logic in ODB_print() ;-(
+          if (llc_idx(2) > 0) llc_idx(2) = -llc_idx(2) ! due to the stupid logic in ODB_print() ;-(
+        else
+          llc_idx(:) = 0 ! (lat,lon) will not be converted in ODB_print
+        endif
+      endif
+
+      j1 = (istart - npolled) + 1 ! (istart - npolled) relative to the beginning of this pool
+      j2 = (istart - npolled) + nleft
+
+      if (LLdebug) then
+1000     format(1x,a,/,10i12)
+         write(0,1000) '# nleft, n, j1, j2, istart, npolled, nrows, numrows, rowbuf, ntot=', &
+              &           nleft, n, j1, j2, istart, npolled, nrows, numrows, rowbuf, ntot
+      endif
+
+      INNER_LOOP: do j=j1,j2,n
+        nchunk = min(n, nleft)
+        if (LLdebug) then
+           write(0,1000) '> ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled=',&
+                &           ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled
+        endif
+
+        rc = ODB_print(h, dtname, file='stdout', poolno=jp, &
+           & inform_progress=.FALSE., &
+           & open_file=LLopen, close_file=LLclose, &
+           & select_query=LLselect, cancel_query=LLcancel, &
+           & print_title=LLprthdr, print_timingstat=LLprttimingstat, &
+           & start=j, limit=nchunk, got=igot, llc_idx=llc_idx)
+
+        LLopen = .FALSE.
+        LLprthdr= .FALSE.
+        ntot = ntot + igot
+        istart = istart + igot
+        numrows = numrows - igot
+        nleft = nleft - igot
+        if (LLdebug) then
+           write(0,1000) '< ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled,igot=',&
+                &           ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled,igot
+        endif
+        if (LLspecial) goto 9999
+        if (igot == 0) exit INNER_LOOP
+      enddo INNER_LOOP
+    endif ! if (LLinside) then ...
+
+    npolled = npolled + nrows
+  endif ! if (nrows > 0) then ...
+
+ 9999 continue
+  rc = ODB_cancel(h, dtname, poolno=jp)
+  rc = ODB_release(h, poolno=jp)
+
+  if (LLdebug) then
+     write(0,1000) '<< jp, jp1, jp2, jinc, nrows, ncols, numrows, istart=', &
+          &            jp, jp1, jp2, jinc, nrows, ncols, numrows, istart
+     write(0,*) 'LLspecial=',LLspecial
+     call flush(0)
+  endif
+
+  if (LLspecial) exit OUTER_LOOP
+  if (.not.LLevery .and. numrows <= 0) exit OUTER_LOOP
+enddo OUTER_LOOP
+
+deallocate(mypools)
+
+rc = ODB_end()
+
+end program odbgnuplot
diff --git a/odb/src/tools/Odbless.F90 b/odb/src/tools/Odbless.F90
new file mode 100644
index 0000000..efb4d73
--- /dev/null
+++ b/odb/src/tools/Odbless.F90
@@ -0,0 +1,343 @@
+program odbless
+!
+!-- To browse particular ODB-table and/or SQL
+!
+!   Usage: 
+!
+! odbless.x dbname view/tablename starting_row numrows row_buffer_size konvert2degrees summary debug every
+!
+!   Pools controlled via ODB_PERMANENT_POOLMASK_<dbname> or ODB_PERMANENT_POOLMASK
+!
+
+USE PARKIND1  ,ONLY : JPIM,JPRB,JPIB
+use odb_module
+use mpl_module
+implicit none
+
+INTEGER(KIND=JPIM) :: h, rc, npools, nproc, myproc, jp, rowbuf, konvert
+INTEGER(KIND=JPIM) :: nrows, ncols, istart, numrows, npolled, igot
+INTEGER(KIND=JPIM) :: numargs, ntot, summary, debug, every
+INTEGER(KIND=JPIM) :: saved(2), iret
+INTEGER(KIND=JPIM) :: jp1, jp2, jinc, llc_idx(2)
+INTEGER(KIND=JPIM) :: nchunk, nleft, nmypools, jj
+INTEGER(KIND=JPIM) :: j1, j2, n
+INTEGER(KIND=JPIB) :: j
+character(len=256) arg
+character(len=64)  dbname, dtname, latlon_names(size(llc_idx)), env
+logical LLopen, LLclose, LLselect, LLcancel, LLinside, LLkonvert, LLspecial
+logical LLprthdr, LLprttimingstat, LLalloc, LLsummary, LLdebug, LLevery, LLaggr
+!-- stat: see module file odb/module/odbstat.F90 for more; currently:
+!   1=counts (non-MDIs), 2=counts (MDIs), 3=min, 4=max, 5=sum->avg, 6=sumsqr->stdev, 7=sumsqr->rms
+INTEGER(KIND=JPIM), parameter :: nstat = odb_statlen
+REAL(KIND=JPRB), allocatable :: stat(:,:)
+INTEGER(KIND=JPIM), allocatable :: mypools(:)
+INTEGER(KIND=JPIM) :: my_first_pool(1)
+
+rc = ODB_init(myproc=myproc, nproc=nproc)
+
+istart  =    1
+numrows =   20
+rowbuf  = 1000
+konvert =    0
+summary =    1
+debug   =    0
+
+numargs = MPL_iargc()
+
+if (numargs >= 2) then
+  call MPL_getarg(1, dbname)
+  call MPL_getarg(2, dtname)
+  
+  if (numargs >= 3) then
+    call MPL_getarg(3, arg)
+    read(arg,'(i12)',err=33,end=33) istart
+  endif
+  istart = max(1,istart)
+33 continue
+
+  if (numargs >= 4) then
+    call MPL_getarg(4, arg)
+    read(arg,'(i12)',err=44,end=44) numrows
+  endif
+  if (numrows <= 0) numrows = 2147483647
+44 continue
+
+  if (numargs >= 5) then
+    call MPL_getarg(5, arg)
+    read(arg,'(i12)',err=55,end=55) rowbuf
+  endif
+  if (rowbuf <= 0) rowbuf = -1
+55 continue
+
+  if (numargs >= 6) then
+    call MPL_getarg(6, arg)
+    read(arg,'(i12)',err=66,end=66) konvert
+  endif
+66 continue
+
+  if (numargs >= 7) then
+    call MPL_getarg(7, arg)
+    read(arg,'(i12)',err=77,end=77) summary
+  endif
+77 continue
+
+  if (numargs >= 8) then
+    call MPL_getarg(8, arg)
+    read(arg,'(i12)',err=88,end=88) debug
+  endif
+88 continue
+
+  if (numargs >= 9) then
+    call MPL_getarg(9, arg)
+    read(arg,'(i12)',err=99,end=99) every
+  endif
+99 continue
+
+else
+  call MPL_getarg(0, arg)
+  CALL ODB_abort('odbless',&
+  & 'Usage: '//trim(arg)//&
+  & ' dbname view/tablename starting_row numrows'//&
+  & ' row_buffer_size konvert2degrees summary debug every')
+endif
+
+h = ODB_open(dbname, 'READONLY', npools)
+
+!-- Fully tolerate errors in time-records i.e. fix records when calling twindow/tdiff funcs
+call codb_allow_time_error(235959)
+
+call codb_putenv('ODB_REPORTER=stdout')
+
+LLopen = .TRUE.
+LLclose = .FALSE.
+LLselect = .FALSE.
+LLcancel = .FALSE.
+LLkonvert = (konvert == 1)
+if (.not.LLkonvert) konvert = 0
+LLsummary = (summary >= 1)
+if (.not.LLsummary) summary = 0
+LLdebug = (debug == 1)
+if (.not.LLdebug) debug = 0
+LLevery = (every == 1)
+if (.not.LLevery) every = 0
+LLaggr = ODB_has_aggrfuncs(h, dtname)
+
+if (ODB_has_orderby(h, dtname) .or. &
+  & LLaggr .or. &
+!! not implemented yet  & ODB_has_uniqueby(h, dtname) .or. & ! Don't know yet if this is ok
+  & ODB_has_select_distinct(h, dtname)) then
+!-- need all pools in one go, since
+!   either contains ORDERBY
+!   or     SELECT DISTINCT (or UNIQUEBY)
+!   or     combination of ORDERBY with SELECT DISTINCT (or UNIQUEBY)
+  nmypools = 1
+  allocate(mypools(nmypools))
+  mypools(1) = -1
+  jp1 = 1
+  jp2 = 1
+  jinc = 1
+!  jp1 = -1
+!  jp2 = -1
+!  jinc = 1
+  if (LLaggr) LLselect = .TRUE.
+  istart = 1
+  numrows = 2147483647
+  rowbuf = -1
+  LLspecial = .TRUE.
+else
+  allocate(mypools(npools))
+  nmypools = ODB_poolinfo(h, mypools, with_poolmask=.TRUE.)
+  jp1 = 1
+  jp2 = nmypools
+  jinc = 1
+!  jp1 = myproc
+!  jp2 = npools
+!  jinc = nproc
+  LLspecial = .FALSE.
+endif
+
+if (nmypools >= 1) then
+  my_first_pool(1) = mypools(1)
+else
+  my_first_pool(1) = -1
+endif
+
+if (LLaggr) then
+  iret = ODB_poolinfo(h, my_first_pool, with_poolmask=.TRUE.)
+  if (iret <= 0) my_first_pool(1) = -1
+endif
+
+20061 format(a)
+20062 format(3(a,i11))
+20063 format(4(a,i1))
+write(6,20061) ':odbless: database='//trim(dbname)//', view/table='//trim(dtname)
+write(6,20062) ':odbless: row-start=',istart,', row-limit=',numrows,', row-bufsize=',rowbuf
+write(6,20063) ':odbless: convert (lat,lon) to degrees=',konvert,&
+     & ', print summary statistics=',summary,&
+     & ', debug mode=',debug,', every=',every
+call flush(6)
+
+if (LLdebug) then
+ 1001 format(a,/,(6i12))
+  write(0,1001) '$ npools, nmypools, size(mypools), jp1, jp2, jinc, mypools(:)=',&
+      &            npools, nmypools, size(mypools), jp1, jp2, jinc, mypools(:)
+endif
+
+istart = istart - 1 ! "C-indexing" enables more convenient offsetting
+npolled = 0
+ntot = 0
+LLprthdr = .TRUE.
+LLprttimingstat = .FALSE.
+LLalloc = .FALSE.
+
+if (LLevery) then
+  saved(1) = istart
+  saved(2) = numrows
+else
+  saved(:) = 0
+endif
+
+if (LLdebug) then
+  write(0,*) '## every, saved(:)=',every, saved(:)
+endif
+
+OUTER_LOOP: do jj=jp1,jp2,jinc
+  jp = mypools(jj)
+  if (.not.LLaggr) then
+    rc = ODB_select(h, dtname, nrows, ncols, poolno=jp)
+  else
+    rc = ODB_getsize(h, dtname, nrows, ncols, poolno=my_first_pool(1))
+    nrows = 2147483647
+  endif
+
+  if (LLdebug) then
+     write(0,1000) '>> jp, jp1, jp2, jinc, nrows, ncols=', &
+          &            jp, jp1, jp2, jinc, nrows, ncols
+  endif
+
+  if (nrows > 0) then
+
+    if (LLevery) then
+    !-- This "reset" enables us to fetch at most "numrows" per each pool (in poolmask)
+      istart = npolled + saved(1)
+      numrows = saved(2)
+      if (LLdebug) then
+        write(0,*) '#> npolled, istart, numrows=',npolled, istart, numrows
+      endif
+    endif    
+
+    LLinside = (istart >= npolled .and. istart < npolled + nrows)
+
+    if (LLinside) then
+      nleft = min(nrows, numrows)
+      if (rowbuf == -1) then
+        n = min(nrows, numrows)
+      else if (nrows > rowbuf) then
+        n = rowbuf
+      else
+        n = nrows
+      endif
+      n = min(n,nleft)
+
+      if (.not.LLalloc) then
+        if (LLsummary) then
+          allocate(stat(nstat,ncols))
+          stat(:,:) = 0
+        else
+          allocate(stat(0,ncols))
+        endif
+
+        LLalloc = .TRUE.
+
+        if (LLkonvert) then
+          call codb_getenv('ODB_LAT',env)
+          if (env == ' ') env = 'lat at hdr'
+          latlon_names(1) = env
+          call codb_getenv('ODB_LON',env)
+          if (env == ' ') env = 'lon at hdr'
+          latlon_names(2) = env
+          ! llc stands for latitude,longitude,color !
+          rc = ODB_varindex(h, dtname, latlon_names, llc_idx)
+          ! lat and/or lon will be converted to degrees, if corresponding llc_idx(:) was positive
+          if (llc_idx(1) > 0) llc_idx(1) = -llc_idx(1) ! due to the stupid logic in ODB_print() ;-(
+          if (llc_idx(2) > 0) llc_idx(2) = -llc_idx(2) ! due to the stupid logic in ODB_print() ;-(
+        else
+          llc_idx(:) = 0 ! (lat,lon) will not be converted in ODB_print
+        endif
+      endif
+
+      j1 = (istart - npolled) + 1 ! (istart - npolled) relative to the beginning of this pool
+      j2 = (istart - npolled) + nleft
+
+      if (LLdebug) then
+1000     format(1x,a,/,10i12)
+         write(0,1000) '# nleft, n, j1, j2, istart, npolled, nrows, numrows, rowbuf, ntot=', &
+              &           nleft, n, j1, j2, istart, npolled, nrows, numrows, rowbuf, ntot
+      endif
+
+      j = j1
+      INNER_LOOP: do while (j <= j2) 
+        nchunk = min(n, nleft)
+        if (LLdebug) then
+           write(0,1000) '> ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled=',&
+                &           ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled
+        endif
+
+        rc = ODB_print(h, dtname, file='stdout', poolno=jp, &
+           & inform_progress=.FALSE., &
+           & open_file=LLopen, close_file=LLclose, &
+           & select_query=LLselect, cancel_query=LLcancel, &
+           & print_title=LLprthdr, print_timingstat=LLprttimingstat, &
+           & stat=stat, &
+           & start=int(j), limit=nchunk, got=igot, llc_idx=llc_idx)
+
+        LLopen = .FALSE.
+        LLprthdr= .FALSE.
+        ntot = ntot + igot
+        istart = istart + igot
+        numrows = numrows - igot
+        nleft = nleft - igot
+        if (LLdebug) then
+           write(0,1000) '< ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled,igot=',&
+                &           ntot,nleft,j,n,nchunk,numrows,nrows,istart,npolled,igot
+        endif
+        if (LLspecial) goto 9999
+        if (igot == 0) exit INNER_LOOP
+        j = j + n ! Note: j is 64-bit/8-byte integer and doesn't overflow here, when n is big (e.g. when LLaggr is true)
+      enddo INNER_LOOP
+    endif ! if (LLinside) then ...
+
+    npolled = npolled + nrows
+  endif ! if (nrows > 0) then ...
+
+ 9999 continue
+  rc = ODB_cancel(h, dtname, poolno=jp)
+  rc = ODB_release(h, poolno=jp)
+
+  if (LLdebug) then
+     write(0,1000) '<< jp, jp1, jp2, jinc, nrows, ncols, numrows, istart=', &
+          &            jp, jp1, jp2, jinc, nrows, ncols, numrows, istart
+     write(0,*) 'LLspecial=',LLspecial
+     call flush(0)
+  endif
+
+  if (LLspecial) exit OUTER_LOOP
+  if (.not.LLevery .and. numrows <= 0) exit OUTER_LOOP
+enddo OUTER_LOOP
+
+if (LLsummary .and. LLalloc .and. ntot > 0) then
+  if (LLdebug) write(0,*)'ntot=',ntot
+  rc = ODB_print(h, dtname, file='stdout', poolno=1, &
+       & inform_progress=.FALSE., show_DB_index=.FALSE.,&
+       & open_file=.TRUE., close_file=.TRUE., &
+       & select_query=.FALSE., cancel_query=.FALSE., &
+       & print_title=.FALSE., print_timingstat=.FALSE., print_summary=.TRUE., &
+       & stat=stat)
+endif
+
+if (allocated(stat)) deallocate(stat)
+deallocate(mypools)
+
+rc = ODB_end()
+
+end program odbless
diff --git a/odb/src/tools/b4.c b/odb/src/tools/b4.c
new file mode 100644
index 0000000..f5ca149
--- /dev/null
+++ b/odb/src/tools/b4.c
@@ -0,0 +1,719 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAS_XMOTIF
+
+#include <signal.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "memmap.h"
+
+#include <Xm/Xm.h>
+#include <Xm/Text.h>
+#include <Xm/Form.h>
+#include <Xm/PushB.h>
+#include <Xm/ToggleB.h>
+#include <Xm/RowColumn.h>
+#include <Xm/CascadeB.h>
+#include <Xm/FileSB.h>
+#include <Xm/MessageB.h>
+#include <Xm/SelectioB.h>
+
+#define NAL 20
+
+/* integer values used to distinguish the call to menuCB. */
+#define MENU_FILE_OPEN     (XtPointer)11
+#define MENU_FILE_QUIT     (XtPointer)13
+
+#define MENU_EDIT_SEARCH   (XtPointer)21
+
+#define MENU_FONT_DEFAULT  (XtPointer)31
+#define MENU_FONT_FIXED    (XtPointer)32
+#define MENU_FONT_SMALL    (XtPointer)33
+#define MENU_FONT_MEDIUM   (XtPointer)34
+#define MENU_FONT_LARGE    (XtPointer)35
+
+#define MENU_PLOT_COVERAGE  (XtPointer)41
+#define MENU_PLOT_XY        (XtPointer)42
+
+/* integer values used to distinguish the call to dialogCBs. */
+#define OK            (XtPointer)1
+#define CANCEL        (XtPointer)2
+
+XtAppContext context;
+XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;
+
+/* all widgets are global to make life easier. */
+Widget toplevel, text, form, label, menu_bar;
+Widget open_option, plot_coverage_option, quit_option;
+Widget search_option, plot_xy_option;
+Widget open_dialog, search_dialog;
+Widget font_default_option, font_fixed_option;
+Widget font_small_option;
+Widget font_medium_option, font_large_option;
+Widget plot_coverage_dialog, plot_xy_dialog;
+
+char *fontname_default = "*lucidasanstypewriter-18*";
+char *fontname_fixed = "fixed";
+char *fontname_small = "*lucidasanstypewriter-bold-14*";
+char *fontname_medium = "*lucidasanstypewriter-bold-18*";
+char *fontname_large = "*lucidasanstypewriter-bold-24*";
+
+char *filename = NULL;
+char *file_contents = NULL;
+char *search_ptr = NULL;
+
+#define ALLOC(x,size)   { \
+  x = malloc(sizeof(*x) * (1 + (size))); \
+  if (!x) { fprintf(stderr,"***Error: Unable to malloc() %d bytes\n",\
+                    sizeof(*x) * (1 + (size))); raise(SIGABRT); } }
+#define FREE(x) { if ((x)) {free((x)); (x) = NULL;} }
+
+#undef MIN
+#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
+
+#undef MAX
+#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
+
+static size_t 
+filesize(FILE *fp)
+{
+  struct stat buf;
+  size_t file_size = 0;
+  if (fstat(fileno(fp),&buf) != 0) {
+    file_size = -1;
+  }
+  else {
+    file_size = buf.st_size;
+  }
+  return file_size;
+}
+
+
+static void
+pass_input()
+{
+  if (filename) {
+    FILE *fp = fopen(filename,"r");
+    size_t lenp = 0;
+    char *p = NULL;
+    int len_iobuf = 1048576;
+    char *iobuf = NULL;
+    char *env = getenv("ODB_REPORTER_MAXBYTES");
+    int maxbytes = 536870912; /* i.e.  512 MBytes : read max this many bytes from file to avoid paging */
+    const char trunc_msg[] = "\n\n\n\n.....(this file has been truncated; Increase max. size via ODB_REPORTER_MAXBYTES).....\n";
+    char *env_mmap = getenv("ODB_REPORTER_MMAP");
+    int use_mmap = env_mmap ? atoi(env_mmap) : 1;
+    int trunc_len = 0;
+    static memmap_t *m = NULL;
+    static FILE *oldfp = NULL;
+    int fd = 0;
+
+    if (!fp) {
+      perror(filename);
+      exit(1);
+    }
+
+    if (env) {
+      int ienv = atoi(env);
+      if (ienv >= 0) maxbytes = ienv;
+      else if (ienv == -1) {
+	maxbytes = 2147483647;
+      }
+    }
+
+    if (m) {
+#if 0
+      fprintf(stderr,"Closing memory mapped file: %p %d\n",m->buf,m->len);
+#endif
+      (void) memmap_close(m);
+      m = NULL;
+      if (oldfp) {
+	fclose(oldfp);
+	oldfp = NULL;
+      }
+      file_contents = NULL;
+    }
+    else if (file_contents) {
+      FREE(file_contents);
+      search_ptr = NULL;
+    }
+
+    lenp = filesize(fp);
+    if (lenp > maxbytes) {
+      fprintf(stderr,
+	      "***Warning: Only the first %d bytes will be read from file '%s', length %d bytes\n",
+	      maxbytes, filename, lenp);
+      fprintf(stderr,
+	      "            Can be increased via ODB_REPORTER_MAXBYTES\n");
+      lenp = maxbytes;
+      trunc_len = strlen(trunc_msg);
+    }
+
+    fd = fileno(fp);
+
+    if (use_mmap) {
+      m = memmap_open_read(fd, NULL, &lenp);
+    }
+    else { /* Don't want memory mapped I/O */
+      m = NULL;
+    }
+
+    if (m) {
+      oldfp = fp;
+      p = (char *)m->buf;
+      lenp = m->len;
+#if 0
+      fprintf(stderr,"Using memory mapped file: %p %d\n",p,lenp);
+#endif
+      /* We leave the file open */
+    }
+    else {
+      ALLOC(p, lenp + trunc_len + 1);
+      
+      len_iobuf = MIN(len_iobuf, lenp);
+      ALLOC(iobuf, len_iobuf);
+      setvbuf(fp, iobuf, _IOFBF, len_iobuf);
+    
+      fread(p, sizeof(*p), lenp, fp);
+      if (trunc_len > 0) memcpy(&p[lenp],trunc_msg,trunc_len);
+      p[lenp+trunc_len] = '\0';
+      fclose(fp);
+
+      FREE(iobuf);
+    }
+    
+    XmTextSetString(text, p);
+
+    file_contents = p;
+    
+    XtSetSensitive(text,True);
+    XmTextSetEditable(text,False);
+    XmTextSetCursorPosition(text,0);
+    
+    FREE(filename);
+
+    XtSetSensitive(search_option,True);
+  }
+}
+
+void
+change_font(Widget w, char *fn)
+{
+  int ac;
+  Arg al[NAL];
+  XFontStruct *font = NULL;
+  XmFontList fontlist = NULL;
+
+  if (!fn) fn = fontname_default;
+
+  font = XLoadQueryFont(XtDisplay(w), fn);
+  fontlist = XmFontListCreate(font, char_set);
+  ac = 0;
+  XtSetArg(al[ac], XmNfontList,fontlist); ac++;
+  XtSetValues(w, al, ac);
+}
+
+void
+openCB(Widget w,
+       XtPointer client_data,
+       XmAnyCallbackStruct *call_data)
+     /* handles the file selection box callbacks. */
+{
+  XmFileSelectionBoxCallbackStruct *s =
+      (XmFileSelectionBoxCallbackStruct *) call_data;
+
+  if (client_data==CANCEL) {
+    /* do nothing if cancel is selected. */
+    XtUnmanageChild(open_dialog);
+    return;
+  }
+
+  if (filename != NULL) {
+    /* free up filename if it exists. */
+    XtFree(filename);
+    filename = NULL;
+  }
+
+  /* get the filename from the file selection box */
+  XmStringGetLtoR(s->value, char_set, &filename);
+
+  /* Read file and pass input to the window */
+
+  pass_input();
+
+  XtUnmanageChild(open_dialog);
+}
+
+
+void
+plotCB(Widget w,
+       XtPointer client_data,
+       XmAnyCallbackStruct *call_data)
+     /* handles the file selection box callbacks. */
+{
+  XmFileSelectionBoxCallbackStruct *s =
+      (XmFileSelectionBoxCallbackStruct *) call_data;
+
+  if (client_data==CANCEL) {
+    /* do nothing if cancel is selected. */
+    XtUnmanageChild(plot_coverage_dialog);
+    return;
+  }
+
+  if (filename != NULL) {
+    /* free up filename if it exists. */
+    XtFree(filename);
+    filename = NULL;
+  }
+
+  /* get the filename from the file selection box */
+  XmStringGetLtoR(s->value, char_set, &filename);
+
+  /* Use ghostview to plot the postscript file */
+
+  {
+    int len = 10;
+    char *cmd;
+    char *env = getenv("ODB_DISPLAY_PLOT");
+    /* if (!env) env = "ghostview -land"; */
+    if (!env) env = "xv";
+    len += strlen(env);
+    len += strlen(filename);
+    ALLOC(cmd, len);
+    sprintf(cmd, "%s %s &",env, filename);
+    system(cmd);
+    FREE(cmd);
+  }
+
+  XtUnmanageChild(plot_coverage_dialog);
+}
+
+
+void
+xyplotCB(Widget w,
+       XtPointer client_data,
+       XmAnyCallbackStruct *call_data)
+     /* handles the file selection box callbacks. */
+{
+  XmFileSelectionBoxCallbackStruct *s =
+      (XmFileSelectionBoxCallbackStruct *) call_data;
+
+  if (client_data==CANCEL) {
+    /* do nothing if cancel is selected. */
+    XtUnmanageChild(plot_xy_dialog);
+    return;
+  }
+
+  if (filename != NULL) {
+    /* free up filename if it exists. */
+    XtFree(filename);
+    filename = NULL;
+  }
+
+  /* get the filename from the file selection box */
+  XmStringGetLtoR(s->value, char_set, &filename);
+
+  /* Use ghostview to plot the postscript file */
+
+  {
+    int len = 50;
+    char *cmd;
+    char *prog;
+    char *cx, *cy, *ct, *dev;
+    char *env = getenv("ODB_XY_PLOTTER");
+
+    prog = env ? strdup(env) : strdup("odbxyplot");
+
+    len += strlen(prog);
+    len += strlen(filename);
+
+    env = getenv("ODB_XY_COL_X");
+    cx = env ? strdup(env) : strdup("1");
+
+    env = getenv("ODB_XY_COL_Y");
+    cy = env ? strdup(env) : strdup("2");
+
+    env = getenv("ODB_XY_COL_T");
+    ct = env ? strdup(env) : strdup("0");
+
+    env = getenv("ODB_XY_DEVICE");
+    dev = env ? strdup(env) : strdup("x11");
+
+    len += strlen(cx) + strlen(cy) + strlen(ct) + strlen(dev);
+
+    ALLOC(cmd, len);
+    sprintf(cmd, "%s -x%s -y%s -t%s -d%s %s &", prog, cx, cy, ct, dev, filename);
+    FREE(prog);
+    FREE(cx); 
+    FREE(cy);
+    FREE(ct);
+    FREE(dev);
+    /* fprintf(stderr,"Running: %s\n",cmd); */
+    system(cmd);
+    FREE(cmd);
+  }
+
+  XtUnmanageChild(plot_xy_dialog);
+}
+
+
+void
+searchCB(Widget w,
+	 XtPointer client_data,
+	 XmSelectionBoxCallbackStruct *call_data)
+     /* callback function for the search box */
+{
+  char *s;
+  int lens;
+  static int hlpos[2] = { 0, -1 };
+
+  if (hlpos[1] >= hlpos[0]) {
+    XmTextSetHighlight(text,hlpos[0],hlpos[1],XmHIGHLIGHT_NORMAL);
+    hlpos[0] =  0;
+    hlpos[1] = -1;
+  }
+
+  if (client_data == OK) {
+    /* get the string from the event structure. */
+    XmStringGetLtoR(call_data->value,char_set,&s);
+    /* printf("Searching for '%s' ...\n",s); */
+
+    lens = strlen(s);
+
+    if (!search_ptr) {
+      int curpos = XmTextGetCursorPosition(text);
+      search_ptr = file_contents + curpos;
+    }
+
+    search_ptr = strstr(search_ptr, s);
+    if (search_ptr) {
+      int newpos = (int)(search_ptr-file_contents) + lens;
+      XmTextSetCursorPosition(text,newpos);
+      hlpos[0] = newpos-lens;
+      hlpos[1] = newpos;
+      XmTextSetHighlight(text,hlpos[0],hlpos[1],XmHIGHLIGHT_SELECTED);
+      search_ptr++;
+    }
+    else {
+      /* printf("'%s' not found\n",s); */
+      XmTextSetCursorPosition(text,0);
+    }
+
+    XtFree(s);
+    /* XtManageChild(w); */
+  }
+  else if (client_data == CANCEL) {
+    /* printf("CANCEL selected\n"); */
+    /* make the dialog box invisible */
+    XtUnmanageChild(w);
+  }
+}
+
+
+void
+menuCB(Widget w,
+       XtPointer client_data,
+       XmAnyCallbackStruct *call_data)
+/* handles menu options. */
+{
+  if (client_data==MENU_FILE_OPEN) {
+    /* make the file selection box to appear */
+    XtManageChild(open_dialog);
+  }
+  else if (client_data==MENU_FILE_QUIT) {
+    exit(0);
+  }
+  else if (client_data==MENU_EDIT_SEARCH) {
+    XtManageChild(search_dialog);
+  }
+  else if (client_data==MENU_FONT_DEFAULT) {
+    /* selects the default font */
+    change_font(text, NULL);
+  }
+  else if (client_data==MENU_FONT_FIXED) {
+    /* selects the fixed font */
+    change_font(text, fontname_fixed);
+  }
+  else if (client_data==MENU_FONT_SMALL) {
+    /* selects the small font */
+    change_font(text, fontname_small);
+  }
+  else if (client_data==MENU_FONT_MEDIUM) {
+    /* selects the medium font */
+    change_font(text, fontname_medium);
+  }
+  else if (client_data==MENU_FONT_LARGE) {
+    /* selects the large font */
+    change_font(text, fontname_large);
+  }
+  else if (client_data==MENU_PLOT_COVERAGE) {
+    /* make the plot file selection box to appear */
+    XtManageChild(plot_coverage_dialog);
+  }
+  else if (client_data==MENU_PLOT_XY) {
+    /* make the xy-plot file selection box to appear */
+    XtManageChild(plot_xy_dialog);
+  }
+}
+
+Widget 
+make_menu_option(char *option_name,
+		 XtPointer client_data,
+		 Widget menu)
+{
+  int ac;
+  Arg al[NAL];
+  Widget b;
+
+  ac = 0;
+  XtSetArg(al[ac], XmNlabelString,
+	   XmStringCreateLtoR(option_name,char_set)); ac++;
+  b=XmCreatePushButton(menu,option_name,al,ac);
+  XtManageChild(b);
+
+  XtAddCallback (b, XmNactivateCallback, (XtCallbackProc)menuCB, client_data);
+  return(b);
+}
+
+Widget 
+make_menu_toggle(char *option_name,
+		 XtPointer client_data,
+		 Widget menu,
+		 Boolean set)
+{
+  int ac;
+  Arg al[NAL];
+  Widget b;
+
+  ac = 0;
+  XtSetArg(al[ac], XmNlabelString,
+	   XmStringCreateLtoR(option_name,char_set)); ac++;
+  XtSetArg(al[ac], XmNset, set); ac++;
+  b=XmCreateToggleButton(menu,option_name,al,ac);
+  XtManageChild(b);
+
+  XtAddCallback (b, XmNvalueChangedCallback, (XtCallbackProc)menuCB, client_data);
+  XtSetSensitive(b,True);
+  return(b);
+}
+
+
+Widget 
+make_menu(char *menu_name,
+	  Widget menu_bar)
+{
+  int ac;
+  Arg al[NAL];
+  Widget menu, cascade;
+  
+  ac = 0;
+  menu = XmCreatePulldownMenu (menu_bar, menu_name, al, ac);
+  
+  ac = 0;
+  XtSetArg (al[ac], XmNsubMenuId, menu);  ac++;
+  XtSetArg(al[ac], XmNlabelString,
+	   XmStringCreateLtoR(menu_name, char_set)); ac++;
+  cascade = XmCreateCascadeButton (menu_bar, menu_name, al, ac);
+
+  XtManageChild (cascade);
+  
+  return(menu);
+}
+
+
+void 
+create_menus(Widget menu_bar)
+{
+  int ac;
+  Arg al[NAL];
+  Widget menu;
+  
+  menu=make_menu("File",menu_bar);
+  open_option = make_menu_option("Open",MENU_FILE_OPEN,menu);
+  quit_option = make_menu_option("Quit",MENU_FILE_QUIT,menu);
+
+  menu=make_menu("Edit",menu_bar);
+  search_option = make_menu_option("Search",MENU_EDIT_SEARCH,menu);
+  XtSetSensitive(search_option,False);
+
+  menu=make_menu("TextSize",menu_bar);
+  font_default_option = make_menu_toggle("Default",MENU_FONT_DEFAULT,menu,1);
+  font_fixed_option = make_menu_toggle("Fixed",MENU_FONT_FIXED,menu,0);
+  font_small_option = make_menu_toggle("Small",MENU_FONT_SMALL,menu,0);
+  font_medium_option = make_menu_toggle("Medium",MENU_FONT_MEDIUM,menu,0);
+  font_large_option = make_menu_toggle("Large",MENU_FONT_LARGE,menu,0);
+  ac=0;
+  XtSetArg(al[ac], XmNradioBehavior,True); ac++;
+  /* XtSetArg(al[ac], XmNradioAlwaysOne, True); ac++; */
+  XtSetValues(menu,al,ac);
+
+  menu = make_menu("Plot",menu_bar);
+  plot_coverage_option = make_menu_option("Coverage plot",MENU_PLOT_COVERAGE,menu);
+  plot_xy_option       = make_menu_option("XY-plot",MENU_PLOT_XY,menu);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+  Arg al[NAL];
+  int ac;
+
+  /* create the toplevel shell */
+  toplevel = XtAppInitialize(&context,"",NULL,0,
+			     &argc,argv,NULL,NULL,0);
+
+  if (argc > 1) filename = strdup(argv[1]);
+  
+  /* default window size. */
+  /*
+  ac=0;
+  XtSetArg(al[ac],XmNheight,200); ac++;
+  XtSetArg(al[ac],XmNwidth,200); ac++;
+  XtSetValues(toplevel,al,ac);
+  */
+
+  /* create a form widget. */
+  ac=0;
+  if (argc > 1) {
+    XtSetArg(al[ac], XmNdialogTitle, XmStringCreateLtoR(filename, char_set));
+    ac++;
+  }
+  form=XmCreateForm(toplevel,"form",al,ac);
+  XtManageChild(form);
+
+  /* create a menu bar and attach it to the form. */
+  ac=0;
+  XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
+  XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+  XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
+  menu_bar=XmCreateMenuBar(form,"menu_bar",al,ac);
+  XtManageChild(menu_bar);
+
+  /* create a text widget and attach it to the form. */
+  ac=0;
+  XtSetArg(al[ac], XmNtopAttachment,    XmATTACH_WIDGET); ac++;
+  XtSetArg(al[ac], XmNtopWidget, menu_bar); ac++;
+  XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+  XtSetArg(al[ac], XmNleftAttachment,   XmATTACH_FORM); ac++;
+  XtSetArg(al[ac], XmNbottomAttachment,   XmATTACH_FORM); ac++;
+  XtSetArg(al[ac], XmNeditMode,XmMULTI_LINE_EDIT); ac++;
+  XtSetArg(al[ac], XmNeditable, FALSE); ac++;
+  XtSetArg(al[ac], XmNcolumns, 100); ac++;
+  XtSetArg(al[ac], XmNrows, 30); ac++;
+
+  text=XmCreateScrolledText(form, "text", al, ac);
+  /* XtAddCallback (text, XmNvalueChangedCallback, (XtCallbackProc)changedCB, NULL); */
+
+  change_font(text, NULL);
+
+  XtManageChild(text);
+
+  /* Create menus */
+
+  create_menus(menu_bar);
+
+  /* create the file selection box used by open option. */
+  ac=0;
+  XtSetArg(al[ac],XmNmustMatch,True); ac++;
+  XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
+  open_dialog=XmCreateFileSelectionDialog(toplevel,"open_dialog",al,ac);
+  XtAddCallback (open_dialog, XmNokCallback,(XtCallbackProc)openCB,OK);
+  XtAddCallback (open_dialog, XmNcancelCallback,(XtCallbackProc)openCB,CANCEL);
+  XtUnmanageChild(XmSelectionBoxGetChild(open_dialog,
+					 XmDIALOG_HELP_BUTTON));
+
+  /* create the file selection box used by coverage plot option. */
+  ac=0;
+  XtSetArg(al[ac],XmNmustMatch,True); ac++;
+  XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
+  XtSetArg(al[ac],XmNpattern,
+	   XmStringCreateLtoR("*.jpg", char_set)); ac++;
+  plot_coverage_dialog=XmCreateFileSelectionDialog(toplevel,"plot_coverage_dialog",al,ac);
+  XtAddCallback (plot_coverage_dialog, XmNokCallback,(XtCallbackProc)plotCB,OK);
+  XtAddCallback (plot_coverage_dialog, XmNcancelCallback,(XtCallbackProc)plotCB,CANCEL);
+  XtUnmanageChild(XmSelectionBoxGetChild(plot_coverage_dialog,
+					 XmDIALOG_HELP_BUTTON));
+
+  /* create the file selection box used by XY-plot option. */
+  ac=0;
+  XtSetArg(al[ac],XmNmustMatch,True); ac++;
+  XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
+  XtSetArg(al[ac],XmNpattern,
+	   XmStringCreateLtoR("*.rpt", char_set)); ac++;
+  plot_xy_dialog=XmCreateFileSelectionDialog(toplevel,"plot_xy_dialog",al,ac);
+  XtAddCallback (plot_xy_dialog, XmNokCallback,(XtCallbackProc)xyplotCB,OK);
+  XtAddCallback (plot_xy_dialog, XmNcancelCallback,(XtCallbackProc)xyplotCB,CANCEL);
+  XtUnmanageChild(XmSelectionBoxGetChild(plot_xy_dialog,
+					 XmDIALOG_HELP_BUTTON));
+
+  /* create the search_dialog box. */
+  ac=0;
+  XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
+  XtSetArg(al[ac], XmNselectionLabelString,
+	   XmStringCreateLtoR("Search for ",char_set)); ac++;
+  search_dialog = XmCreatePromptDialog(toplevel,"search_dialog",al,ac);
+  XtAddCallback(search_dialog,XmNokCallback,(XtCallbackProc)searchCB,OK);
+  XtAddCallback(search_dialog,XmNcancelCallback,(XtCallbackProc)searchCB,CANCEL);
+  XtUnmanageChild(XmSelectionBoxGetChild(search_dialog,
+					 XmDIALOG_HELP_BUTTON));
+
+  pass_input();
+
+  XtRealizeWidget(toplevel);
+  XtAppMainLoop(context);
+}
+
+/* For example: cc -o b4 b4.c -lXm -lXt -lX11 */
+
+#else
+/* no XMOTIF */
+
+#if !defined(HEAD)
+#define HEAD "/usr/bin/head"
+#endif /* if !defined(HEAD) */
+
+int
+main(int argc, char *argv[])
+{
+  int rc = 0;
+  if (argc > 1 && (access(HEAD,X_OK) == 0)) { 
+    /* Display up to the first 10 lines of the files using head-command */
+    int j;
+    const int n = 10;
+    for (j=1; j<argc; j++) {
+      if (access(argv[j],R_OK) == 0) {
+	/* char cmd[sizeof(HEAD) + strlen(argv[j]) + 20]; */
+	int len = sizeof(HEAD) + strlen(argv[j]) + 20;
+	char *cmd = malloc(len);
+	snprintf(cmd,len,"%s -%d %s",HEAD,n,argv[j]);
+	printf("\n\tThe first %d lines of the file '%s' :\n\n",n,argv[j]);
+	fflush(stdout);
+	system(cmd);
+	fflush(stdout);
+	printf("\n\n\tWant to see the full output ? Please look at the file '%s'\n\n",argv[j]);
+	fflush(stdout);
+	free(cmd);
+      }
+      else {
+	fprintf(stderr,
+		"***Error: File '%s' is not accessible for reading!!\n",argv[j]);
+	rc++;
+      }
+    }
+  }
+  else {
+    fprintf(stderr,
+	    "***Error: Executable %s was build with X-Motif disabled\n",argv[0]);
+    rc = 1;
+  }
+  return rc;
+}
+
+#endif
diff --git a/odb/src/tools/dcagen.c b/odb/src/tools/dcagen.c
new file mode 100644
index 0000000..0dc9093
--- /dev/null
+++ b/odb/src/tools/dcagen.c
@@ -0,0 +1,1302 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc.h"
+#include "privpub.h"
+#include "swapbytes.h"
+#include "magicwords.h"
+#include "pcma_extern.h"
+#include "idx.h"
+#include "cmaio.h"
+
+#define ODB_CACHE_LIMIT 128 /* In MegaBytes i.e. 1024 * 1024 -chunks */
+static int odb_cache_limit = ODB_CACHE_LIMIT;
+
+#define ODB_CACHE_MAX 1500 /* No more than this many MegaBytes (1024 * 1024 bytes) per cachefile */
+
+#define ODB_CACHE_DISK "cache" /* Override via f.ex. ODB_CACHE_DISK="/fast/disk" */
+
+#define BAILOUT 100 /* Bailout and give up cardinality study after this/too many distinct entries found */
+static int bailout = BAILOUT;
+
+#define NIBUF 14     /* Do not change this ! Never-ever !!  */
+#define NDBUF  4     /* This can however go up to NDBUF_MAX */
+#define NDBUF_MAX 50 /* Keep in sync with aux/dca.c         */
+
+static int  extract = 0;
+static int    debug = 0;
+static char **colname = NULL;
+static char **datatype = NULL;
+static char *oprefix = NULL;
+int oprefix_percent_s = 0;
+static char *cache_disk = NULL;
+
+static int
+read_ddfile(const char *ddfile, const char *tablename, int *npools)
+{
+  int ncols = 0;
+  int unit, iret;
+  /* FILE *fp = fopen(ddfile,"r"); */
+  FILE *fp = NULL;
+  cma_open_(&unit, ddfile, "r", &iret, strlen(ddfile), strlen("r"));
+  fp = CMA_get_fp(&unit);
+  if (fp) {
+    char line[256];
+    char tbl[4096];
+    int n, jcol;
+    int found = 0;
+    int lineno = 0;
+    while (!feof(fp)) {
+      int nel = 0;
+      lineno++;
+      if (!fgets(line, sizeof(line), fp)) break;
+      if (npools && lineno == 5) { /* get npools */
+        nel = sscanf(line,"%d",npools);
+        continue;
+      }
+      nel = sscanf(line,"%s %d",tbl,&n);
+      if (nel != 2) continue;
+      /* fprintf(stderr,"%d: %s %d\n",lineno,tbl,n); */
+      if (found && *tbl == '@') break;
+      if (*tbl == '@' && strequ(tbl+1,tablename)) {
+        ncols = n;
+        CALLOC(colname, ncols);
+        CALLOC(datatype, ncols);
+        found = 1;
+        jcol = 0;
+      }
+      else if (found) {
+        char *p = strchr(tbl,':');
+        if (p) {
+          /*
+	    char *at = strchr(tbl,'@');
+	    if (at) *at = '\0';
+          */
+          colname[jcol] = STRDUP(p+1);
+          *p = '\0';
+          datatype[jcol] = STRDUP(tbl);
+          jcol++;
+          if (jcol >= ncols) break;
+        }
+      }
+    } /* while (!feof(fp)) */
+    /* fclose(fp); */
+    cma_close_(&unit, &iret);
+  }
+  return ncols;
+}
+
+#define EVAL(allok, calc_loop, type, swapfunc) \
+{ \
+  int j; \
+  type Mdi = mdi; \
+  type *d = data; \
+  double *dtmp = allok ? NULL : data; \
+  if (allok) ALLOC(dtmp, nrows); \
+  if (swap_bytes) swapfunc(d, &nrows); \
+  if (allok) for (j=0; j<nrows; j++) dtmp[j] = d[j]; \
+  codb_cardinality_(NULL, &nrows, NULL, dtmp, &Ncard, NULL, NULL, &bailout); \
+  if (allok) FREE(dtmp); \
+  if (calc_loop) { \
+    if (Ncard == 1) { /* a common short-cut */ \
+      type tmp = d[0]; \
+      if (tmp == Mdi || tmp == -Mdi) Nmdis = nrows; \
+      else Minvalue = Maxvalue = Avg = tmp; \
+    } \
+    else { \
+      for (j=0; j<nrows; j++) { \
+        type tmp = d[j]; \
+        if (tmp == Mdi || tmp == -Mdi) Nmdis++; \
+        else { \
+          if (tmp < Minvalue) Minvalue = tmp; \
+          if (tmp > Maxvalue) Maxvalue = tmp; \
+          Avg += tmp; N++; \
+        } \
+      } /* for (j=0; j<nrows; j++) */ \
+      if (N > 0) { Avg /= N; } \
+    } \
+  } \
+}
+
+
+static
+void swapdummy(void *x, int *n) { }
+
+
+static void
+update_items(void *data, int nrows, unsigned int dtnum,
+             int swap_bytes, int mdi,
+             int *nmdis, 
+             double *avg, double *minvalue, double *maxvalue, int *ncard)
+{
+  int Nmdis = 0; 
+  double Avg = 0;
+  double Minvalue = mdi; 
+  double Maxvalue = -mdi;
+  int Ncard = 0;
+  int N = 0;
+  if (nrows > 0) {
+    if (dtnum == DATATYPE_REAL8) {
+      EVAL(0, 1, double, swap8bytes_);
+    }
+    else if (dtnum == DATATYPE_INT4) {
+      EVAL(1, 1, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_LINKOFFSET) {
+      EVAL(1, 1, unsigned int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_LINKLEN) {
+      EVAL(1, 1, unsigned int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_YYYYMMDD) {
+      EVAL(1, 1, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_HHMMSS) {
+      EVAL(1, 1, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_BITFIELD) {
+      EVAL(1, 1, int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_STRING) {
+      EVAL(0, 0, string, swap8bytes_);
+    }
+    else if (dtnum == DATATYPE_UINT4) {
+      EVAL(1, 1, unsigned int, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_REAL4) {
+      EVAL(1, 1, float, swap4bytes_);
+    }
+    else if (dtnum == DATATYPE_INT2) {
+      EVAL(1, 1, short int, swap2bytes_);
+    }
+    else if (dtnum == DATATYPE_UINT2) {
+      EVAL(1, 1, unsigned short int, swap2bytes_);
+    }
+    else if (dtnum == DATATYPE_INT1) {
+      EVAL(1, 1, signed char, swapdummy);
+    }
+    else if (dtnum == DATATYPE_UINT1) {
+      EVAL(1, 1, unsigned char, swapdummy);
+    }
+  }
+  *nmdis = Nmdis; 
+  *avg = Avg;
+  *minvalue = Minvalue; 
+  *maxvalue = Maxvalue;
+  *ncard = Ncard;
+}
+
+
+typedef struct filecache_t {
+  unsigned long long int cache_seekpos;
+  char *name;
+  char *cache_file;
+  int cache_unit;
+  int cache_limit; 
+  int cache_cnt;
+  struct filecache_t *nextfc;
+} filecache_t;
+
+static filecache_t *filecache = NULL;
+static filecache_t *pfilecache = NULL;
+
+static filecache_t *alloc_filecache(const char *name)
+{
+  if (pfilecache) {
+    CALLOC(pfilecache->nextfc,1);
+    pfilecache = pfilecache->nextfc;
+  }
+  else {
+    CALLOC(filecache,1);
+    pfilecache = filecache;
+  }
+  pfilecache->cache_seekpos = 0;
+  pfilecache->name = STRDUP(name);
+  pfilecache->cache_file = NULL;
+  pfilecache->cache_unit = -1;
+  pfilecache->cache_limit = 0; 
+  pfilecache->cache_cnt = 0;
+  pfilecache->nextfc = NULL;
+  return pfilecache;
+}
+
+static filecache_t *get_filecache(const char *name, int *alloc)
+{
+  filecache_t *pthis = filecache;
+  while (pthis) {
+    if (strequ(pthis->name, name)) break;
+    pthis = pthis->nextfc;
+  }
+  if (pthis) {
+    if (alloc) *alloc = 0;
+  }
+  else {
+    if (alloc) {
+      pthis = alloc_filecache(name);
+      *alloc = 1;
+    }
+  }
+  if (debug) fprintf(stderr,"get_filecache(name='%s', *alloc=%s) --> %p\n",
+		     name, alloc ? (*alloc ? "1" : "0") : NIL,
+		     pthis);
+  return pthis;
+}
+
+
+
+static int free_filecache(filecache_t *pfc)
+{
+  int rc = 0;
+  if (pfc) {
+    if (pfc->name) FREE(pfc->name);
+    if (pfc->cache_file) FREE(pfc->cache_file);
+    FREE(pfc);
+  }
+  return rc;
+}
+
+
+typedef struct colcache_t {
+  char *colname;
+  int unpack;
+  filecache_t *fc;
+  int fc_alloc_here;
+  struct colcache_t *next;
+} colcache_t;
+
+static colcache_t *cache = NULL;
+static colcache_t *pcache = NULL;
+
+static colcache_t *
+add_cache(const char *col, const char *tablename, int unpack, int *errflg);
+
+static colcache_t *
+in_cache(const char *col, const char *tablename, int *unpack)
+{
+  colcache_t *pthis = NULL;
+  colcache_t *pc = cache;
+  char *colname = (char *)col;
+  int allok = 0;
+  int found_star = 0;
+  static int recur = 0;
+  if (unpack) *unpack = 0;
+  if (pc && tablename && *col != '*') {
+    int len = strlen(col) + 1 + strlen(tablename) + 1;
+    ALLOC(colname,len);
+    snprintf(colname,len,"%s@%s",col,tablename);
+    allok = 1;
+  }
+  while (pc) {
+    if (strequ(colname,pc->colname)) {
+      if (unpack) *unpack = pc->unpack;
+      pthis = pc;
+      break;
+    }
+    else if (*pc->colname == '*') {
+      found_star = 1;
+    }
+    pc = pc->next;
+  }
+  if (!pthis && found_star && !recur) {
+    pc = cache;
+    while (pc) {
+      if (*pc->colname == '*') {
+	recur++;
+	pthis = add_cache(colname, NULL, pc->unpack, NULL);
+	recur--;
+	if (unpack) *unpack = pc->unpack;
+	break;
+      }
+      pc = pc->next;
+    }
+  }
+  if (allok) FREE(colname);
+  return pthis;
+}
+
+
+static colcache_t *
+add_cache(const char *col, const char *tablename, int unpack, int *errflg)
+{
+  colcache_t *pthis = NULL;
+  if (!tablename && col) {
+    const char *at = strchr(col,'@');
+    if (at) tablename = at + 1;
+  }
+  if (!tablename) {
+    fprintf(stderr,"***Error: Always supply the -c or -C option AFTER the -t option\n");
+    if (errflg) (*errflg)++;
+  }
+  else if (col) {
+    char *colname = STRDUP(col);
+    char *at = strchr(colname,'@');
+    if (at) *at = '\0'; /* No more "colname at table"; just "colname" */
+    if (!at || (at && strequ(at+1,tablename))) {
+
+      /* check for links with nickname i.e.
+	 {child_table.len|child_table.length|child_table.off|child_table.offset}[@table] */
+
+      {
+	char *pdot = strchr(colname,'.');
+	int is_len = pdot && (strequ(pdot+1,"length") || strequ(pdot+1,"len"));
+	int is_off = pdot && !is_len && (strequ(pdot+1,"offset") || strequ(pdot+1,"off"));
+	if (pdot && !is_len && !is_off) {
+	  fprintf(stderr,"***Error: Unrecognized column name syntax for '%s'\n",col);
+	  if (errflg) (*errflg)++;
+	  goto finish; /* skip this entry and flag error */
+	}
+	if (pdot) *pdot = '\0'; /* colname.{len,offset} now just a colname */
+	/* make new colname, if applicable */
+	if (is_len) {
+	  char *name = NULL;
+	  int len = strlen("LINKLEN(") + strlen(colname) + strlen(")") + 1;
+	  ALLOC(name,len);
+	  snprintf(name,len,"LINKLEN(%s)",colname);
+	  FREE(colname);
+	  colname = name;
+	}
+	else if (is_off) {
+	  char *name = NULL;
+	  int len = strlen("LINKOFFSET(") + strlen(colname) + strlen(")") + 1;
+	  ALLOC(name,len);
+	  snprintf(name,len,"LINKOFFSET(%s)",colname);
+	  FREE(colname);
+	  colname = name;
+	}
+      }
+
+      /* check if already in list; if true, then update the unpack-flag only */
+
+      if ((pthis = in_cache(colname,tablename,NULL)) == NULL) {
+	/* not in list ==> create new entry */
+	int len = strlen(colname) + 1 + strlen(tablename) + 1;
+	if (pcache) {
+	  CALLOC(pcache->next,1);
+	  pcache = pcache->next;
+	}
+	else {
+	  CALLOC(cache,1);
+	  pcache = cache;
+	}
+	ALLOC(pcache->colname, len);
+	snprintf(pcache->colname, len, "%s@%s", colname, tablename);
+
+	if (*colname != '*') {
+	  pcache->fc = get_filecache(oprefix ? 
+				     (oprefix_percent_s ? tablename : oprefix) : 
+				     pcache->colname, 
+				     &pcache->fc_alloc_here);
+	}
+	else {
+	  pcache->fc = NULL;
+	  pcache->fc_alloc_here = 0;
+	}
+
+	pthis = pcache;
+      }
+
+      pthis->unpack = unpack;
+    }
+  finish:
+    FREE(colname);
+  }
+  return pthis;
+}
+
+
+static int
+close_cache(colcache_t *pc)
+{
+  int rc = 0;
+  if (pc && pc->fc && pc->fc->cache_unit != -1) {
+    int iret;
+    if (!extract) {
+      if (debug) fprintf(stderr,
+			 "close_cache(%p): Closing file '%s', CMA I/O-unit = %d\n",
+			 pc, pc->fc->cache_file, pc->fc->cache_unit);
+      cma_close_(&pc->fc->cache_unit, &iret);
+    }
+    pc->fc->cache_unit = -1;
+    pc->fc->cache_seekpos = 0;
+  }
+  return rc;
+}
+
+
+static int
+open_cache(colcache_t *pc)
+{
+  int rc = 0;
+  if (pc && pc->fc && pc->fc->cache_unit != -1 && pc->fc->cache_seekpos > pc->fc->cache_limit) {
+    (void) close_cache(pc);
+  }
+  if (extract && pc && pc->fc && pc->fc->cache_unit == -1) {
+    pc->fc->cache_unit = -2; /* Pretend its open */
+    /* do nothing else */
+  }
+  else if (pc  && pc->fc && pc->fc->cache_unit == -1) {
+    int iret;
+    FILE *fp = NULL;
+    char *mode = "w";
+    const int modelen = 1;
+    int len = strlen(cache_disk) + 1 + strlen(pc->fc->name) + 6 + 20 + 1;
+
+    if (pc->fc->cache_limit == 0) {
+      char *env = getenv("ODB_CACHE_LIMIT"); /* In MegaBytes */
+      if (env) pc->fc->cache_limit = atoi(env);
+      else     pc->fc->cache_limit = odb_cache_limit;
+      pc->fc->cache_limit = MAX(pc->fc->cache_limit, 1);
+      pc->fc->cache_limit = MIN(pc->fc->cache_limit, ODB_CACHE_MAX);
+      pc->fc->cache_limit *= 1024 * 1024; /* Convert to bytes */
+    }
+
+    do {
+      FREE(pc->fc->cache_file);
+      ALLOC(pc->fc->cache_file,len);
+      snprintf(pc->fc->cache_file,len,
+	       "%s/%s.cache.%d",cache_disk,pc->fc->name,++(pc->fc->cache_cnt));
+      cma_filesize_(pc->fc->cache_file, &iret, len);
+    } while (iret > pc->fc->cache_limit);
+
+    if (iret > 0) { /* File already exists; using append mode */
+      mode = "a";
+      pc->fc->cache_seekpos = iret;
+    }
+    else {
+      pc->fc->cache_seekpos = 0;
+    }
+
+    if (debug) fprintf(stderr,
+		       "open_cache(%p): Opening file '%s', mode='%s', seekpos = %llu\n",
+		       pc, pc->fc->cache_file, mode, pc->fc->cache_seekpos);
+
+    cma_open_(&pc->fc->cache_unit, pc->fc->cache_file, mode, &iret, len, modelen);
+    fp = CMA_get_fp(&pc->fc->cache_unit);
+    if (iret != 1 || !fp) {
+      fprintf(stderr,
+	      "Error: Unable to open ODB cache data file '%s' for writing (mode=%s)\n",
+	      pc->fc->cache_file, mode);
+      rc++;
+    }
+
+    if (pc->fc->cache_seekpos == 0) { /* Write magic word "OCAC" at the beginning */
+      const int rev = 0;
+      unsigned int ocac = 0;
+      const int len_bytes = sizeof(ocac);
+      int nwrite = 0;
+      get_magic_ocac_(&rev, &ocac);
+      cma_writeb_(&pc->fc->cache_unit, (const byte1 *)&ocac, &len_bytes, &nwrite);
+      if (nwrite != len_bytes) {
+	fprintf(stderr,
+		"Error: Unable to write initial %d bytes to cache-file '%s' : retcode=%d\n",
+		len_bytes, pc->fc->cache_file, nwrite);
+	rc++;
+      }
+      else {
+	pc->fc->cache_seekpos += len_bytes;
+      }
+    }
+  }
+  return rc;
+}
+
+
+static int
+write_cache(colcache_t *pc, int j, int unit, void *pdata, 
+	    int nbytes, int *Nread, int jp, int line)
+{
+  int rc = 0;
+  rc = open_cache(pc);
+  if (rc == 0 && pc && pc->fc->cache_unit != -1) {
+    int nread = 0;
+    byte1 *data = pdata;
+    if (!pdata) ALLOC(data, nbytes);
+    if (unit >= 0) {
+      cma_readb_(&unit, data, &nbytes, &nread);
+      nread = (nread == nbytes) ? 0 : -1;
+    }
+    if (!extract && (nread == 0 && nbytes > 0)) {
+      int nwrite;
+      cma_writeb_(&pc->fc->cache_unit, data, &nbytes, &nwrite);
+      if (nwrite != nbytes) {
+	fprintf(stderr,
+		"Error: Unable to write %d bytes to cache-file '%s'"
+		" column#%d '%s', datatype '%s', pool-chunk#%d : retcode=%d (called from %s:%d)\n",
+		nbytes, pc->fc->cache_file, j, pc->colname, datatype[j], jp, nwrite,
+		__FILE__, line);
+	rc++;
+      }
+    }
+    if (Nread) *Nread = nread;
+    if (!pdata) FREE(data);
+  }
+  return rc;
+}
+
+
+#define COPY(allok, type) \
+{ \
+  int j; \
+  double *d = data; \
+  type *dtmp = allok ? NULL : data; \
+  if (allok) ALLOC(dtmp, nrows); \
+  if (allok) for (j=0; j<nrows; j++) dtmp[j] = d[j]; \
+  nbytes = sizeof(*dtmp) * nrows; \
+  cma_writeb_(&pc->fc->cache_unit, (const byte1 *)dtmp, &nbytes, &nwrite); \
+  if (allok) FREE(dtmp); \
+}
+
+
+static int
+write_cache2(colcache_t *pc, int j, void *data, int nrows, 
+	     uint dtnum, int *Nbytes, int jp, int line)
+{
+  int rc = 0;
+  int nbytes = 0;
+  if (extract) return rc;
+  if (nrows > 0) rc = open_cache(pc);
+  if (nrows > 0 && rc == 0 && pc && pc->fc->cache_unit != -1) {
+    int nwrite = -1;
+
+    if (dtnum == DATATYPE_REAL8) {
+      COPY(0, double);
+    }
+    else if (dtnum == DATATYPE_INT4) {
+      COPY(1, int);
+    }
+    else if (dtnum == DATATYPE_LINKOFFSET) {
+      COPY(1, unsigned int);
+    }
+    else if (dtnum == DATATYPE_LINKLEN) {
+      COPY(1, unsigned int);
+    }
+    else if (dtnum == DATATYPE_YYYYMMDD) {
+      COPY(1, int);
+    }
+    else if (dtnum == DATATYPE_HHMMSS) {
+      COPY(1, int);
+    }
+    else if (dtnum == DATATYPE_BITFIELD) {
+      COPY(1, int);
+    }
+    else if (dtnum == DATATYPE_STRING) {
+      COPY(0, string);
+    }
+    else if (dtnum == DATATYPE_UINT4) {
+      COPY(1, unsigned int);
+    }
+    else if (dtnum == DATATYPE_REAL4) {
+      COPY(1, float);
+    }
+    else if (dtnum == DATATYPE_INT2) {
+      COPY(1, short int);
+    }
+    else if (dtnum == DATATYPE_UINT2) {
+      COPY(1, unsigned short int);
+    }
+    else if (dtnum == DATATYPE_INT1) {
+      COPY(1, signed char);
+    }
+    else if (dtnum == DATATYPE_UINT1) {
+      COPY(1, unsigned char);
+    }
+    else if (dtnum == DATATYPE_BUFR) {
+      COPY(1, bufr);
+    }
+    else if (dtnum == DATATYPE_GRIB) {
+      COPY(1, grib);
+    }
+    else if (dtnum == DATATYPE_INT8) {
+      COPY(1, longlong);
+    }
+    else if (dtnum == DATATYPE_UINT8) {
+      COPY(1, ulonglong);
+    }
+
+    if (nwrite != nbytes) {
+      fprintf(stderr,
+              "Error: Unable to write %d bytes (unpacked) to cache-file '%s'"
+              " column#%d '%s', datatype '%s', pool-chunk#%d : retcode=%d (called from %s:%d)\n",
+              nbytes, pc->fc->cache_file, j, pc->colname, datatype[j], jp, nwrite,
+              __FILE__, line);
+      rc++;
+      nbytes = 0;
+    }
+  }
+
+  if (Nbytes) *Nbytes = nbytes;
+  return rc;
+}
+
+
+
+#define FLAGS "aAbB:c:C:dhf:i:l:no:p:t:ux"
+
+#define USAGE \
+"Usage: %s \n" \
+"       [-b]      (create binary DCA-file)\n" \
+"       [-c colname at table]  (cache column(s) 'colname at table' to file cache/colname at table.cache.<#>; after -t option)\n" \
+"       [-C colname at table]  (same as -c, but column will be unpacked & written to cache-file)\n" \
+"       [-a]      (cache all encountered columns *without* unpacking)\n" \
+"       [-A]      (cache all encountered columns WITH unpacking them first)\n" \
+"       [-x] (extract only 'colname poolno nrows nmdis cardinality min max ' of the column(s) given via -C/-c)\n" \
+"       [-d]      (to activate debug output)\n" \
+"       [-h]      (suppress printing the header -- the first line)\n" \
+"       [-u]      (update avg/min/max, nmdis, cardinality)\n" \
+"       [-n]      (do NOT update i.e. calculate avg/min/max, nmdis, cardinality)\n" \
+"       [-i ODB_CACHE_LIMIT] (if -c/-C used specify approx. maxsize of files in MBytes; default=%d)\n" \
+"       [-B bailout] (max. no of distinct items allowed before giving up cardinality study; default=%d)\n" \
+"       -t table_name\n" \
+"       -f dd_input_file\n" \
+"       -l dbname\n" \
+"       [-p starting_pool_number]\n" \
+"       [-o output_file_prefix] (a special case: if set to %%s, then use the prevailing tablename)\n" \
+"       ODB_table_data_file(s) > Direct_Column_Access_file\n"
+
+static void set_cache_disk()
+{
+  char *env = getenv("ODB_CACHE_DISK");
+  if (!env) env = ODB_CACHE_DISK;
+  cache_disk = STRDUP(env);
+}
+
+int main(int argc, char *argv[]) {
+  int jarg;
+  int poolno = 1;
+  int rc = 0;
+  const double mdi = 2147483647;
+  char *tablename = NULL;
+  char *ddfile = NULL;
+  char *dbname = NULL;
+  int c;
+  int errflg = 0;
+  int ncols_ref = 0;
+  int update = 0;
+  int npools = 1;
+  int jptot = 1;
+  int binary = 0;
+  int suppress_header = 0;
+  int i_am_little;
+  extern int ec_is_little_endian();
+  extern void ec_set_umask_(); /* ifsaux/support/endian.c */
+  
+  putenv("DR_HOOK=0"); /* We do not want Dr.Hook to interfere */
+
+  ec_set_umask_(); /* Is umask via export EC_SET_UMASK=<octal_umask> given ? */
+
+  i_am_little = ec_is_little_endian();
+
+  set_cache_disk();
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'a':
+      (void) add_cache("*", tablename, 0, &errflg);
+      break;
+    case 'A':
+      (void) add_cache("*", tablename, 1, &errflg);
+      break;
+    case 'b':
+      binary = 1;
+      break;
+    case 'B':
+      bailout = atoi(optarg);
+      break;
+    case 'c':
+      (void) add_cache(optarg, tablename, 0, &errflg);
+      break;
+    case 'C':
+      (void) add_cache(optarg, tablename, 1, &errflg);
+      break;
+    case 'd':
+      debug = 1;
+      break;
+    case 'f':
+      FREE(ddfile);
+      ddfile = STRDUP(optarg);
+      break;
+    case 'h':
+      suppress_header = 1;
+      break;
+    case 'i': /* changed meaning : change default ODB_CACHE_LIMIT */
+      odb_cache_limit = atoi(optarg);
+      if (odb_cache_limit <= 0)            odb_cache_limit = ODB_CACHE_LIMIT;
+      if (odb_cache_limit > ODB_CACHE_MAX) odb_cache_limit = ODB_CACHE_MAX;
+      break;
+    case 'l':
+      FREE(dbname);
+      dbname = STRDUP(optarg);
+      break;
+    case 'n':
+      update = 0;
+      break;
+    case 'o':
+      FREE(oprefix);
+      oprefix = STRDUP(optarg);
+      oprefix_percent_s = strequ(oprefix,"%s") ? 1 : 0;
+      if (debug) fprintf(stderr,"--> oprefix = '%s'\n",oprefix ? oprefix : NIL);
+      break;
+    case 'p':
+      poolno = atoi(optarg);
+      jptot = poolno;
+      break;
+    case 't':
+      FREE(tablename);
+      tablename = STRDUP(optarg);
+      break;
+    case 'u':
+      update = 1;
+      break;
+    case 'x':
+      extract = 1;
+      break;
+    default:
+      errflg++;
+      break;
+    }
+  }
+
+  if (!ddfile && dbname) {
+    int len = strlen(dbname) + 4;
+    ALLOC(ddfile,len);
+    snprintf(ddfile,len,"%s.dd", dbname);
+  }
+
+  if (ddfile && !dbname) { /* ddfile = "/dir/DBNAME.dd" */
+    char *p = strrchr(ddfile, '/');
+    dbname = p ? STRDUP(p+1) : STRDUP(ddfile); /* dbname now is "DBNAME.dd" */
+    p = strchr(dbname,'.');
+    if (p) *p = '\0';
+  }
+
+  if (!tablename || !ddfile || !dbname) errflg++;
+
+  if (errflg) {
+    fprintf(stderr,USAGE,argv[0],ODB_CACHE_LIMIT,BAILOUT);
+    return errflg;
+  }
+
+  ncols_ref = read_ddfile(ddfile, tablename, &npools);
+
+  /* fprintf(stderr,"optind=%d, argc=%d\n",optind,argc); */
+
+  if (extract) {
+    colcache_t *pc = cache;
+    while (pc) {
+      pc->unpack = 1;
+      pc = pc->next;
+    }
+    suppress_header = 1;
+    update = 0;
+    binary = 0;
+  }
+
+  if (!suppress_header) {
+    if (binary) {
+      unsigned int magic_word = DCA2;
+      short int nbuf[2] = { NIBUF, NDBUF };
+      fwrite(&magic_word, sizeof(magic_word), 1, stdout);
+      fwrite(nbuf, sizeof(*nbuf), 2, stdout);
+    }
+    else {
+      printf("#DCA2: col# colname dtname dtnum file pool#"
+             " offset length pmethod pmethod_actual"
+             " nrows nmdis avg min max compression_ratio cardinality is_little\n");
+    }
+  }
+
+  for (jarg=optind; jarg<argc; jarg++) {
+    unsigned long long int seekpos = 0;
+    int nread;
+    unsigned int first_word, word;
+    unsigned int hc32_ctrlw[6];
+    unsigned int odb1_ctrlw[6];
+    unsigned int odb1_colhdr[2];
+    int grpsize = 0;
+    int jp;
+    int nrows = 0;
+    int ncols = 0;
+    int nbytes = 0;
+    int pmethod = 0;
+    int pmethod_actual = 0;
+    int big_endian = 1;
+    int little_endian = 1;
+    int is_hcat = 0;
+    int is_odbfile = 0;
+    int byteswap_needed = 0;
+    const char *mode = "r";
+    FILE *fp = NULL;
+    const char *file = argv[jarg];
+    int unit, iret, rdlen;
+
+    if (debug) fprintf(stderr,"Opening ODB data file '%s'\n",argv[jarg]);
+    /* fp = fopen(argv[jarg],"r"); */
+    cma_open_(&unit, file, mode, &iret, strlen(file), strlen(mode));
+    fp = CMA_get_fp(&unit);
+    if (iret != 1 || !fp) {
+      fprintf(stderr,"Error: Cannot open ODB data file '%s'\n",file);
+      rc++;
+      continue;
+    } 
+
+    /* First word */
+    word = 0;
+    /* nread = fread(&word, sizeof(word), 1, fp); */
+    rdlen = sizeof(word);
+    cma_readb_(&unit, (byte1 *)&word, &rdlen, &iret);
+    nread = iret/sizeof(word);
+
+    if (debug) fprintf(stderr,"... [%llu:%d] 1st word = %u\n", seekpos, nread, word);
+    if (nread != 1) {
+      fprintf(stderr,"Error: Unable to read the 1st word\n");
+      rc++;
+      goto finish;
+    }
+
+    first_word = word;
+    seekpos += nread * sizeof(word);
+
+    /* Detect big/little endianity and 
+       whether file is a normal ODB-file (I/O-method=1) or 
+       concatenated ODB-file (I/O-method=4) */
+
+    is_hcat         = (word ==  HC32 || word == _23CH);
+
+    if (i_am_little) {
+      big_endian    = (word == _23CH || word == _BDO);
+      little_endian = (word ==  HC32 || word == ODB_);
+    }
+    else {
+      big_endian    = (word ==  HC32 || word == ODB_);
+      little_endian = (word == _23CH || word == _BDO);
+    }
+
+    is_odbfile = (big_endian || little_endian);
+
+    if (!is_odbfile) {
+      fprintf(stderr,"Error: File is not a recognized ODB-file\n");
+      rc++;
+      goto finish;
+    }
+
+    if (debug) fprintf(stderr,"... File is %s-endian, %s ODB-file\n",
+                       big_endian ? "big" : "little",
+                       is_hcat ? "concatenated (hcat)" : "normal");
+
+    /* The initial "guess" for the need of byte swapping */
+    byteswap_needed = ((i_am_little && big_endian) || (!i_am_little && little_endian));
+
+    for (jp=1; jp<=npools; jp++) {
+      int byteswap_needed_local = byteswap_needed;
+      int j, nelem;
+      if (debug && (!is_hcat || jp > 1)) 
+        fprintf(stderr,"... Processing pool-chunk#%d of %d\n",jp,npools);
+      if (is_hcat) {
+        /* Read control word information before ODB1-word */
+        nelem = sizeof(hc32_ctrlw)/sizeof(*hc32_ctrlw);
+        /* nread = fread(hc32_ctrlw, sizeof(*hc32_ctrlw), nelem, fp); */
+        rdlen = sizeof(hc32_ctrlw);
+        cma_readb_(&unit, (byte1 *)hc32_ctrlw, &rdlen, &iret);
+        nread = (iret >= 0) ? iret/sizeof(*hc32_ctrlw) : 0;
+        if (nread == 0 && (iret == -1 || feof(fp))) goto finish;
+        if (nread != nelem) {
+          fprintf(stderr,
+		  "Error: Unexpected problems to read HC32 control-words at pool-chunk#%d: nread=%d, expected=%d\n",
+                  jp,nread,nelem);
+          rc++;
+          goto finish;
+        }
+
+        if (byteswap_needed_local) swap4bytes_(hc32_ctrlw, &nelem);
+        /* poolno = hc32_ctrlw[0]; */
+        grpsize = hc32_ctrlw[1];
+        poolno = (grpsize < npools) ? (jptot-1)%npools + 1 : hc32_ctrlw[0]; /* ??? */
+        nbytes = hc32_ctrlw[2];
+        nrows = hc32_ctrlw[3];
+        ncols = hc32_ctrlw[4];
+        if (debug && jp == 1) fprintf(stderr,"... Processing pool-chunk#%d of %d/%d\n",jp,npools,grpsize);
+        if (debug) fprintf(stderr,
+                           "... [%llu:%d] poolno=%d, jptot=%d, grpsize=%d, npools=%d,"
+                           " nbytes=%d, nrows=%d, ncols=%d\n",
+                           seekpos,nread,poolno,jptot,grpsize,npools,nbytes,nrows,ncols);
+        if (nbytes == 0) {
+           goto finish;
+        } 
+        seekpos += sizeof(hc32_ctrlw);
+        jptot++;
+
+        /* Read ODB1-word */
+        word = 0;
+        /* nread = fread(&word, sizeof(word), 1, fp); */
+        rdlen = sizeof(word);
+        cma_readb_(&unit, (byte *)&word, &rdlen, &iret);
+        nread = iret/sizeof(word);
+        if (nread != 1) {
+          fprintf(stderr,"Error: Unable to read the ODB1-word\n");
+          rc++;
+          goto finish;
+        }
+        seekpos += sizeof(word);
+      }
+      else
+        word = first_word;
+
+      if (word == _BDO) word = ODB_; /* bytes swapped inline */
+
+      if (word != ODB_) {
+        fprintf(stderr,
+                "Error: Corrupted ODB1-word: was=%u, expected=%u (i.e. %u)\n",
+                word,first_word,ODB_);
+        rc++;
+        goto finish;
+      }
+
+      /* Read control information just after ODB1-word */
+      nelem = sizeof(odb1_ctrlw)/sizeof(*odb1_ctrlw);
+      /* nread = fread(odb1_ctrlw, sizeof(*odb1_ctrlw), nelem, fp); */
+      rdlen = sizeof(odb1_ctrlw);
+      cma_readb_(&unit, (byte1 *)odb1_ctrlw, &rdlen, &iret);
+      nread = iret/sizeof(*odb1_ctrlw);
+      if (nread != nelem) {
+        fprintf(stderr,
+                "Error: Unexpected problems to read ODB1 control-words"
+                " at pool-chunk#%d: nread=%d, expected=%d\n",
+                jp,nread,nelem);
+        rc++;
+        goto finish;
+      }
+
+      /* 
+         Maybe byteswap is not actually applicable !!
+         Scenario: the first pool has been updated last time on the little-endian machine,
+	 but the remaining pools are still from big-endian, but treated as little-endian
+	 ==> a big problem
+         We need to fix the obvious problem associated with this scenario !!
+      */
+        
+      ncols = odb1_ctrlw[1];
+      byteswap_needed_local = (ncols != ncols_ref) ? 1 : 0;
+
+      if (byteswap_needed_local) swap4bytes_(odb1_ctrlw, &nelem);
+      nrows = odb1_ctrlw[0];
+      ncols = odb1_ctrlw[1];
+      if (debug) fprintf(stderr,"..... [%llu:%d] poolno=%d, npools=%d, nrows=%d, ncols=%d\n",
+                         seekpos,nread,poolno,npools,nrows,ncols);
+      seekpos += sizeof(odb1_ctrlw);
+
+      if (ncols != ncols_ref) {
+        fprintf(stderr,
+                "Error: Invalid number of columns: ncols=%d, expected=%d\n",ncols,ncols_ref);
+        rc++;
+        goto finish;
+      }
+
+      if (nrows > 0) {
+      /* Loop over column header immediately before data */
+      for (j=0; j<ncols; j++) {
+        void *data = NULL;
+        void *data_alloc = NULL;
+        int swp = byteswap_needed_local;
+        uint dtnum = DATATYPE_UNDEF;
+        uint dtnum_saved = dtnum;
+        int unpack = 0;
+	colcache_t *pc = in_cache(colname[j], NULL, &unpack);
+        int update_local = (update || unpack) ? 1 : 0;
+        int seekinc = 0;
+        int can_swp_data = 0;
+        int nmdis = 0;
+        double avg = 0;
+        double minvalue = 1;
+        double maxvalue = -1;
+        int ncard = 0;
+        int jump_over;
+        int search_dtnum = 0;
+        int is_little = 0;
+        double upksize = ((double) nrows) * get_dtsize(datatype[j]); /* Unpacked size */
+        double pksize = upksize; /* The default packed size == unpacked size */
+        double cr = 1; /* The default compression ratio = upksize:pksize */
+        nelem = sizeof(odb1_colhdr)/sizeof(*odb1_colhdr);
+        /* nread = fread(odb1_colhdr, sizeof(*odb1_colhdr), nelem, fp); */
+        rdlen = sizeof(odb1_colhdr);
+        cma_readb_(&unit, (byte1 *)odb1_colhdr, &rdlen, &iret);
+        nread = iret/sizeof(*odb1_colhdr);
+        if (nread != nelem) {
+          fprintf(stderr,
+                  "Error: Unexpected problems to read ODB1 column header-words"
+                  " at pool-chunk#%d, col#%d: nread=%d, expected=%d\n",
+                  jp,j,nread,nelem);
+          rc++;
+          goto finish;
+        }
+        if (byteswap_needed_local) swap4bytes_(odb1_colhdr, &nelem);
+        if (i_am_little) { /* the running machine is little endian */
+          is_little = byteswap_needed_local ? 0 : 1;
+        }
+        else { /* the running machine is big endian */
+          is_little = byteswap_needed_local ? 1 : 0;
+        }
+        pksize = nbytes = odb1_colhdr[0];
+        cr = (upksize <= 0 || pksize <= 0) ? 0 : (upksize/pksize);
+        pmethod = pmethod_actual = EXTRACT_PMETHOD(odb1_colhdr[1]);
+        dtnum = EXTRACT_DATATYPE(odb1_colhdr[1]);
+        if (dtnum == DATATYPE_UNDEF) {
+          dtnum = get_dtnum(datatype[j]);
+          search_dtnum = 1;
+        }
+        dtnum_saved = dtnum;
+        odb1_colhdr[1] = pmethod + 256U * dtnum;
+        can_swp_data = EXTRACT_SWAPPABLE(odb1_colhdr[1]);
+        seekinc = nbytes;
+        if (nbytes == 0) pc = NULL;
+        if (debug) {
+          fprintf(stderr,
+                  "....... [%llu:%d] col#%d <%s> nbytes=%d, pmethod=%d, dtnum=%u (0x%x)%s,"
+                  " can_swp_data=%d, cacheable-pc=%d\n",
+                  seekpos,nread,j,colname[j],nbytes,pmethod,dtnum,dtnum,
+                  search_dtnum ? " searched" : "",
+                  can_swp_data, pc ? 1 : 0);
+        }
+        seekpos += sizeof(odb1_colhdr);
+
+        jump_over = 
+          (nbytes == 0) ||
+          (!update_local) || 
+          (dtnum == DATATYPE_UNDEF);
+
+        if (jump_over) {
+          /* Jump over the column data section */
+          if (pc) {
+            rc += write_cache(pc, j, unit, NULL, nbytes, &nread, jp, __LINE__);
+          }
+          else {
+            /* nread = fseek(fp, nbytes, SEEK_CUR); */
+            const int whence = 1; /* SEEK_CUR */
+            cma_seekb_(&unit, &nbytes, &whence, &nread);
+          }
+        }
+        else {
+          if (pmethod == 0) { /* data just aligned into the 'double'-boundary;
+                                 data may still be other than a 'double'-type */
+            double *dp;
+            int ndpw = RNDUP_DIV(nbytes,sizeof(*dp)); /* Round-up & truncate */
+            ALLOC(dp, ndpw);
+            data = data_alloc = dp;
+            if (pc) {
+              rc += write_cache(pc, j, unit, data, nbytes, &nread, jp, __LINE__);
+            }
+            else {
+              /* nread = fread(data, 1, nbytes, fp); */
+              cma_readb_(&unit, (byte1 *)data, &nbytes, &nread);
+              nread = (nread == nbytes) ? 0 : -1;
+            }
+            if (swp) swp = can_swp_data;
+          }
+          else {
+            const int fill_zeroth_cma = 0; /* set this to 1 if in doubt */
+            unsigned int hdr[PCMA_HDRLEN];
+            int bytes_in, bytes_out;
+            int lencma, msgbytes, new_version;
+            double nmdi, rmdi;
+            int swpaux;
+            int rc_hdr = upcma_hdr(fp, &swpaux, hdr, 1,
+                                   &pmethod_actual, &lencma, &msgbytes,
+                                   &nmdi, &rmdi, &new_version);
+            int numval;
+            double *cma = NULL;
+            Packbuf pbuf;
+
+            if (rc_hdr >= 0) ALLOC(cma, lencma);
+
+	    if (pc && unpack && pmethod_actual == 9) {
+	      /* Allow a special case for pmethod actually being 9 
+		 i.e. all values the same ==>
+		 retain packing, since unpacking on-the-fly (from cache-file)
+		 is very cheap */
+	      unpack = 0;
+	    }
+
+            if (pc && !unpack) {
+              pbuf.counter = 0;
+              pbuf.maxalloc = 0;
+              pbuf.len = 0;
+              pbuf.p = NULL;
+              pbuf.allocatable = 0;
+            }
+
+            numval = upcma(can_swp_data, fp, NULL, 
+                           NULL, 0, fill_zeroth_cma,
+                           cma, lencma, hdr, 
+                           (pc && !unpack) ? &pbuf : NULL,
+                           &bytes_in, &bytes_out);
+
+            if (pc && !unpack && pbuf.p) {
+              rc += write_cache(pc, j, -1, pbuf.p, nbytes, NULL, jp, __LINE__);
+              FREE(pbuf.p);
+            }
+
+            if (pc && unpack) {
+              is_little = i_am_little;
+              pmethod_actual = 0;
+            }
+            else {
+              /* This individual column can still be little endian, despite file being big endian */
+              /* Luckily swpaux gives us this status information */
+              if (i_am_little) { /* the running machine is little endian */
+                is_little = swpaux ? 0 : 1;
+              }
+              else { /* the running machine is big endian */
+                is_little = swpaux ? 1 : 0;
+              }
+            }
+            if (debug) {
+              fprintf(stderr,
+                      "\tnumval=%d,lencma=%d,pmethod/act=%d/%d,msgbytes=%d,"
+                      "mdis=(%.20g,%.20g),vers=%d,in/out=%d/%d,swpaux=%d,is_little=%d\n",
+                      numval,lencma,pmethod,pmethod_actual,msgbytes,
+                      nmdi,rmdi,new_version,bytes_in,bytes_out,
+                      swpaux,is_little);
+              if (nrows >= 2) {
+                fprintf(stderr,"\t(1)=%.20g\t(nrows=%d)=%.20g\n",
+                        cma[1],nrows,cma[nrows]);
+              }
+            }
+            if (numval != lencma) {
+              fprintf(stderr,
+                      "Error: upcma()-error; numval=%d, lencma=%d, nrows=%d\n",
+                      numval,lencma,nrows);
+              nread = -1;
+            }
+            else {
+              data_alloc = cma;
+              data = &cma[fill_zeroth_cma];
+              nread = 0;
+              if (pc && unpack) {
+                rc += write_cache2(pc, j, data, nrows, dtnum_saved, &seekinc, jp, __LINE__);
+              }
+            }
+            swp = 0; /* byte swap already performed in upcma => switch off */
+            /* force datatype to be REAL8, unless already a string */
+            if (dtnum != DATATYPE_STRING) dtnum = DATATYPE_REAL8;
+          }
+        }
+
+        if (nread != 0) {
+          fprintf(stderr,
+                  "Error: Unexpected problems to get over column data"
+                  " at pool-chunk#%d, col#%d: retcode=%d\n",
+                  jp,j,nread);
+          rc++;
+          goto finish;
+        }
+
+        nmdis = 0;
+        avg = 0;
+        minvalue = 1;
+        maxvalue = -1;
+        ncard = 0;
+
+        if (data) {
+          update_items(data, nrows, dtnum,
+                       swp, mdi,
+                       &nmdis, 
+                       &avg, &minvalue, &maxvalue, &ncard);
+          if (debug) {
+            fprintf(stderr,
+                    "\tnrows=%d, no. of MDIs=%d, avg=%.20g, min=%.20g, max=%.20g, cardinality=%d\n",
+                    nrows, nmdis, avg, minvalue, maxvalue, ncard);
+          }
+          FREE(data_alloc);
+        }
+
+        if (binary) {
+          int ibuf[NIBUF];
+          double dbuf[NDBUF];
+
+          ibuf[0] = poolno; /* Poolno first and upon reading so we can quickly skip this record */
+
+          ibuf[1] = strlen(colname[j]) /* + 1 + strlen(tablename) */;
+          ibuf[2] = strlen(datatype[j]);
+          ibuf[3] = pc ? strlen(pc->fc->cache_file) : strlen(argv[jarg]);
+
+          ibuf[4] = dtnum_saved;
+          ibuf[5] = j;
+          ibuf[6] = pc ? seekinc : nbytes;
+          ibuf[7] = pmethod;
+          ibuf[8] = pmethod_actual;
+          ibuf[9] = nrows;
+          ibuf[10] = nmdis;
+          ibuf[11] = cr;
+          ibuf[12] = ncard;
+          ibuf[13] = is_little;
+
+          dbuf[0] = pc ? pc->fc->cache_seekpos : seekpos;
+          dbuf[1] = avg;
+          dbuf[2] = minvalue;
+          dbuf[3] = maxvalue;
+
+          fwrite(ibuf, sizeof(*ibuf), NIBUF, stdout);
+          fwrite(dbuf, sizeof(*dbuf), NDBUF, stdout);
+          fwrite(colname[j], 1, strlen(colname[j]), stdout);
+          /*
+	    fwrite("@", 1, 1, stdout);
+	    fwrite(tablename, 1, strlen(tablename), stdout);
+          */
+          fwrite(datatype[j], 1, strlen(datatype[j]), stdout);
+          if (pc) {
+            fwrite(pc->fc->cache_file, 1, strlen(pc->fc->cache_file), stdout);
+          }
+          else {
+            fwrite(argv[jarg], 1, strlen(argv[jarg]), stdout);
+          }
+        }
+        else if (!extract) {
+	  /* printf("%d %s@%s %s %u %s %d %llu %d %d %d %d %d %.20g %.20g %.20g %.4f %d %d\n", */
+          printf("%d %s %s %u %s %d %llu %d %d %d %d %d %.20g %.20g %.20g %.4f %d %d\n",
+		  j, colname[j],
+		        datatype[j], dtnum_saved, 
+		              pc ? pc->fc->cache_file : argv[jarg],
+		                 poolno,
+		                    pc ? pc->fc->cache_seekpos : seekpos, 
+		                         pc ? seekinc : nbytes,
+		                            pmethod, pmethod_actual,
+		                                  nrows, nmdis,
+		                                        avg,minvalue,maxvalue,
+		                                                          cr,  ncard,
+		                                                                  is_little);
+        }
+	else if (extract && pc) {
+	  printf("%s %d %d %d %d %.20g %.20g\n",
+		 colname[j], poolno, nrows, nmdis, ncard, minvalue, maxvalue);
+	}
+
+        seekpos += nbytes;
+        if (pc) pc->fc->cache_seekpos += seekinc;
+      } /* for (j=1; j<=ncols; j++) */
+     }
+      if (!is_hcat) break;
+    } /* for (jp=1; jp<=npools; jp++) */
+  finish:
+    /* fclose(fp); */
+    cma_close_(&unit, &iret);
+    if (!is_hcat) poolno++;
+  } /* for (jarg=optind; jarg<=argc; jarg++) */
+
+  if (rc == 0 && cache) { /* close still opened cache-files */
+    colcache_t *pc = cache;
+    while (pc) {
+      (void) close_cache(pc);
+      if (pc->fc && pc->fc_alloc_here) {
+	(void) free_filecache(pc->fc);
+	pc->fc_alloc_here = 0;
+      }
+      pc->fc = NULL;
+      pc = pc->next;
+    }
+  }
+
+  if (debug || rc != 0) fprintf(stderr,"Exiting with return code = %d\n",rc);
+  return rc;
+}
+
diff --git a/odb/src/tools/dd2ddl.c b/odb/src/tools/dd2ddl.c
new file mode 100644
index 0000000..23c80bf
--- /dev/null
+++ b/odb/src/tools/dd2ddl.c
@@ -0,0 +1,394 @@
+/* 
+   A program to re-create "ddl_"-file for a given database
+   using "dd"-file as input 
+
+   Usage: dd2ddl < dd_file > ddl_file
+
+   Following yet to be implemented :
+
+   Usage: dd2ddl [options]
+
+   options include: 
+
+   -i input dd-file     (like: -i ECMA.dd)
+   -o output ddl_-file  (like: -o ECMA.ddl_ ; the default prefix from the input dd-file)
+   -l database_name     (like: -l ECMA ; the default from input dd-file)
+   -s set_parameter     (like: -s '$abc = 1')
+
+   If -i is not given, but -l is, then the input file name is
+   "guessed" from -l's argument.
+
+   Author: Sami Saarinen, ECMWF, 29-Aug-2000
+
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+/* #include <malloc.h> */
+
+typedef struct _Mem_t {
+  char *name;
+  int nbits;
+} Mem_t;
+
+typedef struct _Col_t {
+  int id;
+  char *name;
+  char *type;
+  int nmem;
+  Mem_t *mem;
+} Col_t;
+
+typedef struct _Table_t {
+  int id;
+  char *name;
+  int ncol;
+  Col_t *col;
+} Table_t;
+
+
+typedef struct _Set_t {
+  char *name;
+  double value;
+} Set_t;
+
+static int 
+IsNumber(const char *p) 
+{
+  int count = 0;
+  if (p) {
+    while (*p != '\0') {
+      if (!isdigit(*p)) {
+	count = 0;
+	break;
+      }
+      count++;
+      p++;
+    }
+  }
+  return (count > 0) ? 1 : 0;
+}
+
+int main(int argc, char *argv[])
+{
+  int debug = 0;
+  FILE *fpin = stdin;
+  FILE *fpout = stdout;
+  double Version_Major, Version_Minor;
+  char CrDate[9], CrTime[7];
+  char UDate[9] ,  UTime[7];
+  char AnDate[9], AnTime[7];
+  int Npools  = 0;
+  int Ntables = 0;
+  int t, p, j;
+  int nel;
+  int nsetvar;
+  int colref = 0;
+  Table_t *table = NULL;
+  Set_t *set = NULL;
+  int tmp1, tmp2;
+  char tmpstr[256];
+  char tmptype[256], tmpcol[256];
+  int io_method = 1;
+  char line[256];
+
+  if (fgets(line, sizeof(line), fpin)) {
+    nel = sscanf(line,"%lf %lf %d",&Version_Major, &Version_Minor, &io_method);
+    if (nel == 2) { /* pre-25r4 */
+      io_method = 1;
+    }
+  }
+  
+  fscanf(fpin,"%8s %6s\n", CrDate, CrTime); /* Date created */
+  fscanf(fpin,"%8s %6s\n", UDate, UTime);   /* Date last updated */
+  fscanf(fpin,"%8s %6s\n", AnDate, AnTime); /* Analysis date */
+  fscanf(fpin,"%d\n", &Npools);
+  fscanf(fpin,"%d\n", &Ntables);
+
+  fprintf(fpout,"// Automatically generated DDL-file\n");
+  fprintf(fpout,"// Contains %d tables\n", Ntables);
+
+  table = (Table_t *)malloc(Ntables * sizeof(Table_t));
+
+  for (t=0; t<Ntables; t++) {
+    nel = fscanf(fpin,"%d @%s %d", &tmp1, tmpstr, &tmp2);
+    if (debug) { 
+      fprintf(stderr,"<debug(#%d/3)table:> %d @%s %d\n", nel, tmp1, tmpstr, tmp2); 
+    }
+    table[t].id = tmp1;
+    table[t].name = strdup(tmpstr);
+    table[t].ncol = 0;
+    table[t].col = NULL;
+    if (tmp2 != Npools && tmp2 != -1) {
+      fprintf(stderr,
+	      "***Error[1]: No. of pools found (=%d) for table '%s' not the expected one (=%d)\n",
+	      tmp2, tmpstr, Npools);
+      return(1);
+    }
+    /* Read dummy (for this application) */
+    for (p=0; p<tmp2; p++) { 
+      nel = fscanf(fpin,"%d",&tmp1);
+      if (debug) { 
+	fprintf(stderr," %d", tmp1); 
+      }
+    } /* for (p=0; p<tmp2; p++) */
+    fscanf(fpin,"\n");
+    if (debug) { fprintf(stderr,"\n"); }
+  } /* for (t=0; t<Ntables; t++) */
+
+  for (t=0; t<Ntables; t++) {
+    nel = fscanf(fpin,"@%s %d\n", tmpstr, &tmp1);
+    if (debug) { 
+      fprintf(stderr,"<debug(#%d/2)TABLE:> @%s %d\n", nel, tmpstr, tmp1); 
+    }
+    if (strcmp(tmpstr, table[t].name) == 0) {
+      int ncol = tmp1;
+      int c;
+      table[t].ncol = ncol;
+      table[t].col = (Col_t *)malloc(ncol * sizeof(Col_t));
+      for (c=0; c<ncol; c++) {
+	nel = fscanf(fpin, "%s %d\n", tmptype, &tmp1);
+	{
+	  char *copy = strdup(tmptype);
+	  char *x = tmptype;
+	  while (*x != ':') {
+	    if (*x == '\0') {
+	      fprintf(stderr,
+		      "***Error[4]: End of string occurred while processing type info at '%s'\n",
+		      copy);
+	      return(4);
+	    }
+	    x++;
+	  }
+	  *x++ = '\0';
+	  strcpy(tmpcol, x);
+	  x = tmpcol;
+	  while (*x != '@') {
+	    if (*x == '\0') {
+	      fprintf(stderr,
+		      "***Error[5]: End of string occurred while processing column info at '%s'\n",
+		      copy);
+	      return(5);
+	    }
+	    x++;
+	  }
+	  *x++ = '\0';
+	  strcpy(tmpstr, x);
+	  nel += 2;
+	  free(copy);
+	}
+
+	if (debug) { 
+	  fprintf(stderr,"<debug(#%d/4)col:> '%s':'%s'@'%s' '%d'\n", 
+		  nel, tmptype, tmpcol, tmpstr, tmp1); 
+	}
+	if (strcmp(tmpstr, table[t].name) != 0) {
+	  fprintf(stderr,
+		  "***Error[3]: Unexpected table name '%s' found while extracting column '%s'. Expected '%s'\n",
+		  tmpstr, tmpcol, table[t].name);
+	  return(3);
+	}
+	table[t].col[c].id = ++colref;
+	table[t].col[c].name = strdup(tmpcol);
+	table[t].col[c].type = strdup(tmptype);
+	table[t].col[c].nmem = tmp1;
+	if (tmp1 > 0) {
+	  int m;
+	  int nmem = tmp1;
+	  table[t].col[c].mem = (Mem_t *)malloc(nmem * sizeof(Mem_t));
+	  for (m=0; m<nmem; m++) {
+	    nel = fscanf(fpin, "%s %d\n", tmpstr, &tmp1);
+	    if (debug) {
+	      fprintf(stderr,"<debug(#%d/2)mem:> %s %d\n", 
+		      nel, tmpstr, tmp1); 
+	    }
+	    table[t].col[c].mem[m].name = strdup(tmpstr);
+	    table[t].col[c].mem[m].nbits = tmp1;
+	  } /* for (m=0; m<nmem; m++) */
+	}
+	else {
+	  table[t].col[c].mem = NULL;
+	}
+      } /* for (c=0; c<ncol; c++) */
+    }
+    else {
+      fprintf(stderr,
+	      "***Error[2]: Unexpected table name '%s' found. Expected '%s'\n",
+	      tmpstr, table[t].name);
+      return(2);
+    } /* if (strcmp(tmpstr, table[t].name) == 0) */
+  } /* for (t=0; t<Ntables; t++) */
+
+  /* === SET-variables (if any) === */
+
+  nsetvar = 0;
+  nel = fscanf(fpin, "%d\n", &nsetvar);
+  if (nel == 1 && nsetvar > 0) {
+    char name[4096];
+    double value;
+    set = malloc(sizeof(*set) * nsetvar);
+    for (j=0; j<nsetvar; j++) {
+      set[j].name = NULL;
+      set[j].value = 0;
+    }
+    for (j=0; j<nsetvar; j++) {
+      nel = fscanf(fpin, "$%s %lf\n", name, &value);
+      if (nel == 2) {
+	set[j].name = strdup(name);
+	set[j].value = value;
+      }
+      else {
+	nsetvar = j-1;
+	break;
+      }
+    }
+  }
+
+
+  /* === OUTPUT === */
+
+  fprintf(fpout,"\n//-- SET-variables --\n\n");
+  
+  for (j=0; j<nsetvar; j++) {
+    fprintf(fpout,"SET $%s = %.14g;\n", set[j].name, set[j].value);
+  }
+
+  fprintf(fpout,"\n//-- Typedefs --\n\n");
+
+  for (t=0; t<Ntables; t++) {
+    /* typedefs */
+    int c;
+    for (c=0; c<table[t].ncol; c++) {
+      if (table[t].col[c].nmem > 0) {
+	int m;
+	int minc = 1;
+	fprintf(fpout,"CREATE TYPE %s_%s_%d_t AS ( // Generated type name\n", 
+		table[t].name, table[t].col[c].type, table[t].col[c].id);
+	for (m=0; m<table[t].col[c].nmem; m+=minc) {
+	  if (strchr(table[t].col[c].mem[m].name,'_')) {
+	    int mm;
+	    int nset = 0;
+	    int n1 = 0, n2;
+	    int refbits = table[t].col[c].mem[m].nbits;
+	    char *refname = strdup(table[t].col[c].mem[m].name);
+	    char *pos = strrchr(refname,'_');
+	    if (pos) *pos = '\0';
+	    for (mm=m; mm<table[t].col[c].nmem; mm++) {
+	      int bits = table[t].col[c].mem[mm].nbits;
+	      char *name = strdup(table[t].col[c].mem[mm].name);
+	      pos = strrchr(name,'_');
+	      if (pos) *pos = '\0';
+	      if (pos && strcmp(name, refname) == 0 && bits == refbits) {
+		char *z = &pos[1];
+		int is_digit = IsNumber(z);
+		nel = sscanf(z, "%d", &tmp1);
+		if (nel != 1 || !is_digit) {
+		  free(name);
+		  break;
+		}
+		nset++;
+		if (mm == m) n1 = tmp1;
+	      }
+	      free(name);
+	    } /* for (mm=m; mm<table[t].col[c].nmem; mm++) */
+	    n2 = n1 + nset - 1;
+	    if (nset == 0) {
+	      fprintf(fpout,"  %s bit%d,\n", table[t].col[c].mem[m].name, table[t].col[c].mem[m].nbits);
+	    }
+	    else {
+	      fprintf(fpout,"  %s[%d:%d] bit%d,\n", refname, n1, n2, table[t].col[c].mem[m].nbits);
+	      minc = nset;
+	    }
+	    free(refname);
+	  }
+	  else {
+	    fprintf(fpout,"  %s bit%d,\n", 
+		    table[t].col[c].mem[m].name, table[t].col[c].mem[m].nbits);
+	  }
+	} /* for (m=0; m<table[t].col[c].nmem; m++) */
+	fprintf(fpout,");\n\n");
+      } /* if (table[t].col[c].nmem > 0) */
+    } /* for (c=0; c<table[t].ncol; c++) */
+  }
+
+  fprintf(fpout,"\n//-- Tables --\n\n");
+
+  for (t=0; t<Ntables; t++) {
+    /* tables */
+    int c;
+    int cinc = 1;
+    fprintf(fpout,"CREATE TABLE %s AS (\n", table[t].name);
+    for (c=0; c<table[t].ncol; c+=cinc) {
+      cinc = 1;
+      if (table[t].col[c].nmem > 0) {
+	fprintf(fpout,"  %s %s_%s_%d_t,\n", 
+		table[t].col[c].name, table[t].name, table[t].col[c].type, table[t].col[c].id);
+      }
+      else {
+	if (strncmp(table[t].col[c].name, "LINKOFFSET(", 11) == 0) {
+	  char *copy = strdup(table[t].col[c].name);
+	  char *x = &table[t].col[c].name[11];
+	  while (*x != ')') {
+	    if (*x == '\0') {
+	      fprintf(stderr,
+		      "***Error[6]: End of string occurred while processing LINK info at '%s'\n",
+		      copy);
+	      return(6);
+	    }
+	    x++;
+	  }
+	  *x = '\0';
+	  fprintf(fpout,"  %s @LINK,\n", &table[t].col[c].name[11]);
+	  free(copy);
+	}
+	else if (strncmp(table[t].col[c].name, "LINKLEN(", 8) == 0) {
+	  continue;
+	}
+	else if (strchr(table[t].col[c].name,'_')) {
+	  int cc;
+	  int nset = 0;
+	  int n1 = 0, n2;
+	  char *refname = strdup(table[t].col[c].name);
+	  char *reftype = strdup(table[t].col[c].type);
+	  char *pos = strrchr(refname,'_');
+	  if (pos) *pos = '\0';
+	  for (cc=c; cc<table[t].ncol; cc++) {
+	    char *name = strdup(table[t].col[cc].name);
+	    char *type = strdup(table[t].col[cc].type);
+	    pos = strrchr(name,'_');
+	    if (pos) *pos = '\0';
+	    if (pos && strcmp(name, refname) == 0 && strcmp(type, reftype) == 0) {
+	      char *z = &pos[1];
+	      int is_digit = IsNumber(z);
+	      nel = sscanf(z, "%d", &tmp1);
+	      if (nel != 1 || !is_digit) {
+		free(name);
+		break;
+	      }
+	      nset++;
+	      if (cc == c) n1 = tmp1;
+	    }
+	    free(name);
+	  } /* for (cc=c; cc<table[t].ncol; cc++) */
+	  n2 = n1 + nset - 1;
+	  if (nset == 0) {
+	    fprintf(fpout,"  %s %s,\n", table[t].col[c].name, table[t].col[c].type);
+	  }
+	  else {
+	    fprintf(fpout,"  %s[%d:%d] %s,\n", refname, n1, n2, table[t].col[c].type);
+	    cinc = nset;
+	  }
+	  free(refname);
+	}
+	else {
+	  fprintf(fpout,"  %s %s,\n", table[t].col[c].name, table[t].col[c].type);
+	}
+      }
+    } /* for (c=0; c<table[t].ncol; c+=cinc) */
+    fprintf(fpout,");\n\n");
+  } /* for (t=0; t<Ntables; t++) */
+
+}
+
diff --git a/odb/src/tools/hcat.c b/odb/src/tools/hcat.c
new file mode 100644
index 0000000..da52f14
--- /dev/null
+++ b/odb/src/tools/hcat.c
@@ -0,0 +1,722 @@
+#include "odb.h"
+#include "cmaio.h"
+#include "swapbytes.h"
+#include "magicwords.h"
+
+/* Routine to manipulate HC32 (Horizontally Concatenated 32-bit/integer) files */
+
+/* Author: Sami Saarinen, ECMWF, 30-Jan-2003
+   = with original release: table of contents (toc) output
+   = file split added on 30-Jun-2003 by SS
+   = -S to -L : 17-Mar-2006 by SS
+   = byte swapping issues : 18-Mar-2006 by SS
+   = USAGE (format) fixes : 12-Feb-2012 by SS
+ */
+
+static char vers[] = "v1.12Feb2012";
+static char date_str[] = __DATE__;
+static char time_str[] = __TIME__;
+
+#define FLAGS "1:4:FG:hi:l:L:n:o:t:vVzZ"
+
+#define USAGE \
+   "\nUsage(s): %s\n" \
+   "  [-v]  for more verbose output\n" \
+   "  [-V]  for version number\n" \
+   "  [-n npools]  for number of (input) pools to scan\n" \
+   "               the default npools taken from $ODB_SRCPATH_<dbname>/<dbname>.dd\n" \
+   "  [-Z]  write zero-length files\n" \
+   "  [-z]  do *not* write zero-length files (the default)\n" \
+   "  [-F]  enforce overwriting existing file(s) [dangerous!]\n" \
+   "   -l dbname  database label/name (MUST be given)\n" \
+   "   -t table   table to be processed (MUST be given)\n" \
+   "\n" \
+   "# Split (I/O-method#4 to #1 -conversion):\n" \
+   "  -41 [-i input_filename] -t table [-o output_file_template]\n\n" \
+   "# Concatenate (I/O-method#1 to #4 -conversion):\n" \
+   "  -14 [-i input_filename] -t table [-o output_file_template] [-L chunk_size_MB] [-G group_size]\n\n" \
+   "# The default values: -z -L %d -G %d\n" \
+   "# The default input file(s) (if not given via -i) are  : <dbname>.<table>.%%d\n" \
+   "# The default output file(s) (if not given via -o) are : _/%%d/<table>\n" \
+   "\n" \
+   "Please note that options [-14|-41] are mutually exclusive\n" \
+   "\n" \
+
+#define SIZE_MB 32
+#define GRPSIZE 1
+#define HDRSIZE 6
+
+static int errflg = 0;
+
+static int concat  = 0;
+static int overwrite = 0;
+static int grpsize = GRPSIZE;
+static int help = 0;
+static char *input = NULL;
+static int npools = -1;
+static char *output = NULL;
+static int split   = 0;
+static int size_MB = SIZE_MB;
+static int verbose = 0;
+static int version = 0;
+static int zerolen = 0;
+static char *dbname = NULL;
+static char *table = NULL;
+static int ncols_tbl = 0;
+
+/* substitute procid, if '%' was found in input string */
+
+static char *
+unmassage_name(const char *in, const int procid)
+{
+  char *p = NULL;
+  char *out = NULL;
+  int len = strlen(in) + 50;
+  ALLOCX(p, len);
+  if (strchr(in,'%')) {
+    sprintf(p,in,procid);
+  }
+  else {
+    strcpy(p,in);
+  }
+  len = strlen(p);
+  out = IOtruename(p,&len); /* FREE()'able */
+  FREEX(p);
+  return out;
+}
+
+/* Read .dd-file (borrowed from dcagen.c & modified) */
+
+static int
+read_ddfile(const char *ddfile, const char *tablename, int *npools_out)
+{
+  int ncols = 0;
+  int unit, iret;
+  FILE *fp = NULL;
+  cma_open_(&unit, ddfile, "r", &iret, strlen(ddfile), strlen("r"));
+  fp = CMA_get_fp(&unit);
+  if (fp) {
+    char line[256];
+    char tbl[4096];
+    int lineno = 0;
+    while (!feof(fp)) {
+      int n, nel = 0;
+      lineno++;
+      if (!fgets(line, sizeof(line), fp)) break;
+      if (npools_out && lineno == 5) { /* get number of pools */
+        nel = sscanf(line,"%d",npools_out);
+        continue;
+      }
+      nel = sscanf(line,"%s %d",tbl,&n);
+      if (nel != 2) continue;
+      if (*tbl == '@' && strequ(tbl+1,tablename)) {
+	/* Match ! */
+        ncols = n;
+	break; /* while (!feof(fp)) */
+      }
+    } /* while (!feof(fp)) */
+    cma_close_(&unit, &iret);
+  }
+  return ncols;
+}
+
+
+/*********/
+/* split */
+/*********/
+
+static void
+split_file()
+{ /* Split HC32-files and create one ODB1-file per pool */
+
+  int jp, jpsave = 0;
+  if (!strchr(input,'%')) npools = 1;
+
+  for (jp=1; jp<=npools; jp++) {
+    int filesize = 0;
+    int In = -1;
+    int rc = 0;
+    char *fin = unmassage_name(input, jp);
+    IOgetsize(fin, &filesize, NULL);
+
+    if (verbose) 
+      fprintf(stderr,
+	      "Opening input file '%s' for pool=%d (length=%d, logical='%s')\n", 
+	      fin, jp, filesize, input);
+
+    if (filesize <= 0) {
+      if (verbose) fprintf(stderr,"File '%s' not found\n", fin);
+      goto next_jp; /* skip to the next "jp" */
+    }
+
+    cma_open_(&In, fin, "r", &rc, strlen(fin), 1);
+
+    if (rc == 1) {
+      int swp = 0;
+      int icat = 0;
+      int len;
+      
+      cma_get_byteswap_(&In, &swp);
+
+      if (swp && verbose) 
+	fprintf(stderr,"Byteswapping is needed and will be performed automatically\n");
+
+      len = 1;
+      cma_readi_(&In, &icat, &len, &rc);
+      
+      if (rc == len && icat == HC32) {
+	int hdr[HDRSIZE];
+	int blk = 0;
+
+	for (;;) {
+	  byte1 *p = NULL;
+	  int nw, ndata;
+	  int ipoolno, igrpsize, nbytes, nrows, ncols, npad;
+
+	  len = HDRSIZE;
+	  cma_readi_(&In, hdr, &len, &rc);
+	  if (rc == -1) {
+	    if (verbose) fprintf(stderr,
+				 "Successful EOF reached in input file '%s', after block#%d\n", 
+				 fin, blk);
+	    break; /* for (;;) */
+	  }
+	  blk++;
+
+	  if (rc != len) {
+	    fprintf(stderr,
+		    "***Error: Unable to read hdr-info from file '%s', block#%d\n", fin, blk);
+	    errflg++;
+	    goto finish; /* Error */
+	  }
+
+	  ipoolno = hdr[0];
+	  ipoolno = ++jpsave; /* An override */
+	  igrpsize = hdr[1];
+	  nbytes = hdr[2];
+	  nrows = hdr[3];
+	  ncols = hdr[4];
+	  npad = hdr[5];
+
+	  if (verbose) {
+	    fprintf(stderr,
+		    "\tBlock#%d: pool#%d, grpsize=%d, nbytes=%d, nrows=%d, ncols=%d, npad=%d\n",
+		    blk, ipoolno, igrpsize, nbytes, nrows, ncols, npad);
+	  }
+
+	  if ((npad & 0x1) == 1) {
+	    nw = (nbytes + sizeof(int) - 1)/sizeof(int);
+	    ndata = nw * sizeof(int);
+	  }
+	  else {
+	    ndata = nbytes;
+	  }
+
+	  ALLOC(p, ndata); /* One-day: introduce data chunking, since "ndata" may be large */
+	  cma_readb_(&In, p, &ndata, &rc);
+
+	  if (rc == ndata && (nbytes > 0 || (zerolen && (nbytes == 0 || nrows == 0)))) {
+	    int Out = -1;
+	    char *fout = unmassage_name(output, ipoolno);
+	    IOgetsize(fout, &filesize, NULL);
+	    if ((filesize > 0 && overwrite) || filesize <= 0) {
+	      if (verbose) fprintf(stderr,
+				   "Opening output file '%s' for pool=%d (logical='%s')\n", 
+				   fout, ipoolno, output);
+	      cma_open_(&Out, fout, "w", &rc, strlen(fout), 1);
+	      cma_writeb_(&Out, p, &nbytes, &rc);
+	      if (rc != nbytes) {
+		fprintf(stderr,
+			"***Error: Unable to write data to file '%s' : nbytes=%d, rc=%d\n", 
+			fout, nbytes, rc);
+		errflg++;
+		FREE(fout);
+		FREE(p);
+		goto finish; /* Error */
+	      }
+	      cma_close_(&Out, &rc);
+	      Out = -1;
+	    }
+	    else {
+	      fprintf(stderr,
+		      "***Error: Unable to overwrite existing file '%s'\n", fout);
+	      fprintf(stderr,
+		      "          Please remove it first or"
+		      " use option \"-F\" to enforce overwriting (dangerous)\n");
+	      errflg++;
+	      FREE(fout);
+	      FREE(p);
+	      goto finish; /* Error */
+	    }
+
+	    FREE(fout);
+	    rc = ndata;
+	  } /* if (rc == ndata && (nbytes > 0 ... */
+	  FREE(p);
+	  
+	  if (rc != ndata) {
+	    fprintf(stderr,
+		    "***Error: Unable to read data from file '%s', block#%d : ndata=%d, rc=%d\n", 
+		    fin, blk, ndata, rc);
+	    errflg++;
+	    goto finish; /* Error */
+	  }
+	} /* for (;;) */
+      }
+      else {
+	fprintf(stderr,
+		"***Error: Input file format for splitting of file '%s' (logical='%s') was not recognized\n",
+		fin,input);
+	errflg++;
+	goto finish; /* Error */
+      } /* if (rc == len && icat == HC32) */
+    } /* if (rc == 1) */
+    cma_close_(&In, &rc);
+
+  next_jp:
+    FREE(fin);
+  } /* for (jp=1; jp<=npools; jp++) */
+ finish:
+  return;
+}
+
+/**********/
+/* concat */
+/**********/
+
+static void
+concat_file()
+{ /* Concatenate a number of of ODB1-files into one HC32 */
+
+  int Out = -1;
+  char *fout = NULL;
+  int jp;
+  int offset;
+  int filenum = 0;
+  int first_time = 1;
+  if (!strchr(input,'%')) npools = 1;
+
+  offset=0;
+  for (jp=1; jp<=npools; jp++) {
+    int filesize = 0;
+    int In = -1;
+    int rc = 0;
+    char *fin = unmassage_name(input, jp);
+    IOgetsize(fin, &filesize, NULL);
+
+    if (verbose) 
+      fprintf(stderr,
+	      "Opening input file '%s' for pool=%d (length=%d, logical='%s')\n", 
+	      fin, jp, filesize, input);
+
+    if (filesize <= 0) {
+      if (verbose) fprintf(stderr,"File '%s' not found\n", fin);
+      goto next_jp; /* skip to the next "jp" */
+    }
+
+    cma_open_(&In, fin, "r", &rc, strlen(fin), 1);
+
+    if (rc == 1) {
+      int swp = 0;
+      int icat = 0;
+      int len;
+      int re_open;
+      
+      cma_get_byteswap_(&In, &swp);
+
+      if (swp && verbose) 
+	fprintf(stderr,"Byteswapping is needed and will be performed automatically\n");
+
+      len = 1;
+      cma_readi_(&In, &icat, &len, &rc);
+      
+      if (rc == len && icat == ODB_) {
+	int hc32word = HC32;
+	int hc32[HDRSIZE];
+	int hdr[INFOLEN]; /* INFOLEN from odb/include/odb.h */
+	byte1 *p = NULL;
+	int nw, ndata;
+	int ipoolno, igrpsize, nbytes, nrows, ncols, npad;
+
+	hdr[0] = ODB_;
+	len = INFOLEN - 1;
+	cma_readi_(&In, hdr+1, &len, &rc);
+	if (rc == -1) {
+	  fprintf(stderr,
+		  "***Error: Unexpected EOF encountered in input file '%s'\n", 
+		  fin);
+	  errflg++;
+	  goto finish;
+	}
+
+	if (rc != len) {
+	  fprintf(stderr,
+		  "***Error: Unable to read info-data from file '%s'\n", fin);
+	  errflg++;
+	  goto finish; /* Error */
+	}
+
+	ipoolno = jp; /* An override */
+	igrpsize = grpsize;
+	nbytes = filesize;
+	nrows = hdr[1];
+	ncols = hdr[2];
+	npad = 0;
+
+	hc32[0] = ipoolno;
+	hc32[1] = igrpsize;
+	hc32[2] = nbytes;
+	hc32[3] = nrows;
+	hc32[4] = ncols;
+	hc32[5] = npad;
+
+	if (verbose) {
+	  fprintf(stderr,
+		  "\tpool#%d, grpsize=%d, nbytes=%d, nrows=%d, ncols=%d, npad=%d\n",
+		    ipoolno, igrpsize, nbytes, nrows, ncols, npad);
+	}
+
+	/* Close previously opened file, if offset has exceeded size_MB (times 1024x1024)
+	   or modulo(ipoolno-1,grpsize) == 0 */
+
+	if (Out != -1) {
+	  if (offset >= 1024*1024*size_MB || ((ipoolno-1)%igrpsize == 0)) {
+	    cma_close_(&Out, &rc);
+	    Out = -1;
+	    FREE(fout);
+	    offset = 0;
+	  }
+	}
+
+	re_open = (!fout || Out == -1);
+
+	if (!fout) fout = unmassage_name(output, ipoolno);
+
+	ndata = nbytes - sizeof(hdr);
+
+	ALLOC(p, ndata); /* One-day: introduce data chunking, since "ndata" may be large */
+	cma_readb_(&In, p, &ndata, &rc);
+
+	if (rc != ndata) {
+	  fprintf(stderr,
+		  "***Error: Unable to read data from file '%s' : ndata=%d, rc=%d\n", 
+		  fin, ndata, rc);
+	  errflg++;
+	  goto finish; /* Error */
+	}
+
+	if (rc == ndata && (nbytes > 0 || (zerolen && (nbytes == 0 || nrows == 0)))) {
+	  if (swp) {
+	    int n = 1;
+	    swap4bytes_(&hc32word, &n);
+	    n = HDRSIZE;
+	    swap4bytes_(hc32, &n);
+	    n = INFOLEN;
+	    swap4bytes_(hdr, &n);
+	  }
+
+	  if (re_open) {
+	    IOgetsize(fout, &filesize, NULL);
+	    if ((filesize > 0 && overwrite) || filesize <= 0) {
+	      if (verbose) fprintf(stderr,
+				   "Opening output file '%s' for pool=%d (logical='%s')\n", 
+				   fout, ipoolno, output);
+	      filenum = ipoolno;
+	      cma_open_(&Out, fout, "w", &rc, strlen(fout), 1);
+	      len = 1;
+	      cma_writei_(&Out, &hc32word, &len, &rc);
+	      if (rc != len) {
+		fprintf(stderr,
+			"***Error: Unable to write hc32word to file '%s' : len=%d, rc=%d\n",
+			fout, len, rc);
+		errflg++;
+		FREE(p);
+		goto finish; /* Error */
+	      }
+	      offset += sizeof(hc32word);
+
+	      if (first_time) {
+		/* For I/O-map (goes to stdout) */
+		printf("%d\n",ncols_tbl);
+		first_time = 0;
+	      }
+
+	    }
+	    else {
+	      fprintf(stderr,
+		      "***Error: Unable to overwrite existing file '%s'\n", fout);
+	      fprintf(stderr,
+		      "          Please remove it first or"
+		      " use option \"-F\" to enforce overwriting (dangerous)\n");
+	      errflg++;
+	      FREE(p);
+	      goto finish; /* Error */
+	    }
+	  } /* if (re_open) */
+
+	  /* For I/O-map (goes to stdout) */
+	  printf("%d %d %lld %lld %d\n",ipoolno,filenum,(long long int)offset,(long long int)(sizeof(hc32)+nbytes),nrows);
+
+	  len = HDRSIZE;
+	  cma_writei_(&Out, hc32, &len, &rc);
+	  if (rc != len) {
+	    fprintf(stderr,
+		    "***Error: Unable to write HC32-header data to file '%s' : len=%d, rc=%d\n", 
+		    fout, len, rc);
+	    errflg++;
+	    FREE(p);
+	    goto finish; /* Error */
+	  }
+	  offset += sizeof(hc32);
+
+	  len = INFOLEN;
+	  cma_writei_(&Out, hdr, &len, &rc);
+	  if (rc != len) {
+	    fprintf(stderr,
+		    "***Error: Unable to write ODB1-header data to file '%s' : len=%d, rc=%d\n", 
+		    fout, len, rc);
+	    errflg++;
+	    FREE(p);
+	    goto finish; /* Error */
+	  }
+	  offset += sizeof(hdr);
+
+	  cma_writeb_(&Out, p, &ndata, &rc);
+	  if (rc != ndata) {
+	    fprintf(stderr,
+		    "***Error: Unable to write data to file '%s' : ndata=%d, rc=%d\n", 
+		    fout, ndata, rc);
+	    errflg++;
+	    FREE(p);
+	    goto finish; /* Error */
+	  }
+	  offset += ndata;
+
+	} /* if (rc == ndata && (nbytes > 0 ... */
+	FREE(p);
+	
+      }
+      else {
+	fprintf(stderr,
+		"***Error: Input file format for concatenation of file '%s' (logical='%s') was not recognized\n",
+		fin,input);
+	errflg++;
+	goto finish; /* Error */
+      } /* if (rc == 1 && icat == ODB_) else ... */
+    }
+
+    cma_close_(&In, &rc);
+  next_jp:
+    FREE(fin);
+  } /* for (jp=1; jp<=npools; jp++) */
+
+ finish:
+  if (!errflg && Out != -1) {
+    int rc;
+    cma_close_(&Out, &rc);
+    FREE(fout);
+  }
+  return;
+}
+
+/********/
+/* main */
+/********/
+
+int main(int argc, char *argv[])
+{
+  int npools_in = -1;
+  int c;
+
+  errflg = 0;
+
+  { /* get default values for grpsize from ODB_IO_GRPSIZE */
+    char *env = getenv("ODB_IO_GRPSIZE");
+    if (env) grpsize = atoi(env);
+    grpsize = MAX(GRPSIZE,grpsize);
+  }
+
+  { /* get default values for grpsize from ODB_IO_FILESIZE */
+    char *env = getenv("ODB_IO_FILESIZE");
+    if (env) size_MB = atoi(env);
+    size_MB = MAX(1,size_MB);
+    size_MB = MIN(1000,size_MB);
+  }
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case '1': /* concatenate (#1 --> #4) */
+      if (strequ(optarg,"4")) concat = 1;
+      else {
+	fprintf(stderr,
+		"***Error: Argument -1 must follow '4'"
+		" i.e. use -14. Found '%s'\n", optarg);
+	errflg++;
+      }
+      break;
+    case '4': /* split (#4 --> #1) */
+      if (strequ(optarg,"1")) split = 1;
+      else {
+	fprintf(stderr,
+		"***Error: Argument -4 must follow '1'"
+		" i.e. use -41. Found '%s'\n", optarg);
+	errflg++;
+      }
+      break;
+    case 'F': /* enForce to overwrite -mode */
+      overwrite = 1;
+      break;
+    case 'G': /* group size */
+      grpsize = atoi(optarg);
+      grpsize = MAX(1,grpsize);
+      break;
+    case '?':
+    case 'h': /* print help */
+      help = 1;
+      break;
+    case 'i': /* input file name(s) */
+      if (input) FREE(input);
+      input = STRDUP(optarg);
+      break;
+    case 'l': /* database name */
+      if (dbname) FREE(dbname);
+      dbname = STRDUP(optarg);
+      break;
+    case 'L': /* preferred file size in MB */
+      size_MB = atoi(optarg);
+      size_MB = MAX(1,size_MB);    /* 1MB lower limit */
+      size_MB = MIN(1000,size_MB); /* 1GB upper limit; see ../lib/msgpass_loaddata.F90 and ../lib/msgpass_storedata.F90*/
+      break; 
+    case 'n': /* npools_in */
+      npools_in = atoi(optarg);
+      npools_in = MAX(1,npools_in);
+      break;
+    case 'o': /* output file name(s) */
+      if (output) FREE(output);
+      output = STRDUP(optarg);
+      break;
+    case 't': /* table name */
+      if (table) FREE(table);
+      table = STRDUP(optarg);
+      break;
+    case 'v': /* verbose */
+      verbose = 1;
+      break;
+    case 'V': /* print version */
+      version = 1;
+      break;
+    case 'Z': /* write zero length files */
+      zerolen = 1;
+      break;
+    case 'z': /* do *not* write zero length files */
+      zerolen = 0;
+      break;
+    default:
+      errflg++;
+      break;
+    }
+  }
+
+  if (version) {
+    fprintf(stderr,"hcat -- ODB's Horizontal conCATenate files -tool -- Revision %s, %s, %s\n",
+	    vers, date_str, time_str);
+    fprintf(stderr,"Copyright (c) 1998-2003, 2006 ECMWF. All Rights Reserved. ");
+    fprintf(stderr,"Author: Sami Saarinen.\n");
+  }
+
+  if (help) {
+    fprintf(stderr,USAGE,argv[0],SIZE_MB,GRPSIZE);
+    return(errflg);
+  }
+
+  if (argc - 1 == optind) { /* wrong ? */
+    errflg++;
+  }
+
+  if (concat + split != 1) { 
+    fprintf(stderr,"***Error: Options [-14|-41] are mutually exclusive\n");
+    errflg++;
+  }
+
+  if (!dbname) {
+    fprintf(stderr,"***Error: Database label/name (-l dbname) must be given\n");
+    errflg++;
+  }
+
+  if (!table) {
+    fprintf(stderr,"***Error: Table name (-t table) must be given\n");
+    errflg++;
+  }
+
+  if (!errflg) {
+    int envlen = strlen("ODB_XXXXPATH_") + strlen(dbname) + 3; /* 3 : '=' + '.' + '\0' */
+    char *env = NULL;
+    char *p = NULL;
+    ALLOCX(env, envlen);
+    /* ODB_DATAPATH_<dbname> */
+    sprintf(env,"ODB_DATAPATH_%s",dbname);
+    p = getenv(env);
+    if (!p) { /* i.e. not set; lets set it to current dir '.' */
+      char *envcopy;
+      sprintf(env,"ODB_DATAPATH_%s=.",dbname);
+      envcopy = STRDUP(env); /* Remains allocated i.e. cannot be free()'d */
+      putenv(envcopy);
+      if (verbose) {
+	p = strchr(env,'=');
+	if (p) *p = '\0';
+	p = getenv(env);
+	fprintf(stderr,">Variable '%s' now points to '%s'\n",env,p ? p : NIL);
+      }
+    }
+    /* ODB_SRCPATH_<dbname> */
+    sprintf(env,"ODB_SRCPATH_%s",dbname);
+    p = getenv(env);
+    if (!p) { /* i.e. not set; lets set it to current dir '.' */
+      char *envcopy;
+      sprintf(env,"ODB_SRCPATH_%s=.",dbname);
+      envcopy = STRDUP(env); /* Remains allocated i.e. cannot be free()'d */
+      putenv(envcopy);
+      if (verbose) {
+	p = strchr(env,'=');
+	if (p) *p = '\0';
+	p = getenv(env);
+	fprintf(stderr,">Variable '%s' now points to '%s'\n",env,p ? p : NIL);
+      }
+    }
+    FREEX(env);
+  }
+
+  if (!errflg) { /* Get npools & ncols etc. */
+    ncols_tbl = read_ddfile(dbname, table, &npools);
+    if (verbose) fprintf(stderr,
+			 "> npools=%d, npools_in=%d, ncols_tbl=%d\n",
+			 npools, npools_in, ncols_tbl);
+    if (npools_in >= 1) npools = MIN(npools_in, npools);
+    grpsize = MIN(npools,grpsize);
+  }
+
+  if (!errflg) {
+    if (!input) {
+      int len = strlen(dbname) + strlen(table) + 10;
+      ALLOC(input, len);
+      sprintf(input,"%s.%s.%%d",dbname,table);
+    }
+    if (!output) {
+      int len = strlen(table) + 10;
+      ALLOC(output,len);
+      sprintf(output,"_/%%d/%s",table);
+    }
+  }
+
+  if (!errflg) {
+    if (split)  split_file();
+    else if (concat) concat_file();
+  }
+
+  if (errflg) {
+    fprintf(stderr,USAGE,argv[0],SIZE_MB,GRPSIZE);
+    return(errflg);
+  }
+
+  return(errflg);
+}
diff --git a/odb/src/tools/ioassign.c b/odb/src/tools/ioassign.c
new file mode 100644
index 0000000..1b1f5bf
--- /dev/null
+++ b/odb/src/tools/ioassign.c
@@ -0,0 +1,510 @@
+/* ioassign.c (main program) */
+
+/* Written by Sami Saarinen 1997-98, 2000-01, 2003 (ECMWF) */
+
+#include "iostuff.h"
+#include "ioassign.h"
+
+#define ioassign main
+
+static char vers[]     = "3.1";
+static char date_str[] = __DATE__;
+static char time_str[] = __TIME__;
+
+#if defined(CRAY) && !defined(T3D) && !defined(T3E)
+#define SYSTEM_NAME "(CRAY PVP)"
+#endif
+
+#ifdef T3D
+#define SYSTEM_NAME "(CRAY T3D)"
+#endif
+
+#ifdef T3E
+#define SYSTEM_NAME "(CRAY T3E)"
+#endif
+
+#ifdef SGI
+#define SYSTEM_NAME "(Silicon Graphics)"
+#endif
+
+#ifdef RS6K
+#define SYSTEM_NAME "(IBM RS/6000)"
+#endif
+
+#ifdef VPP
+#define SYSTEM_NAME "(Fujitsu VPP)"
+#endif
+
+#ifdef NECSX
+#define SYSTEM_NAME "(NEC SX)"
+#endif
+
+#ifndef SYSTEM_NAME
+#define SYSTEM_NAME "(Unknown system)"
+#endif
+
+static char system_name[] = SYSTEM_NAME;
+
+#define USAGE  \
+  "Usage: ioassign [-Version] [-verbose] [-help] [-debug]\n" \
+  "                [-m internal_packing_method] [-B blocksize]\n" \
+  "                [-n nproc] [-b numbins] [-s]\n" \
+  "                [-Incore] [-r readbufsize] [-w writebufsize]\n" \
+  "                [-p prealloc] [-e extent]\n" \
+  "                [-linkonly] [-a alias_name] [-c 'unix_pipe_filter']\n" \
+  "                [-x (to expand file names according to nproc)]\n" \
+  "                [-k [-]concatenate_processor_number]\n" \
+  "                [-S starting_number_for_logical_filename]\n" \
+  "                [-f] logical_file_name\n" \
+  "For example:\n" \
+  "(1) Print contents of the current $IOASSIGN (default=IOASSIGN) file:\n" \
+  "    ioassign -v\n" \
+  "(2) Generate PE-related symbolic links with verbose output:\n" \
+  "    setenv NPES 4\n" \
+  "    ioassign -v -link -a /path/target_file.%d  symbolic_link.%d\n" \
+  "  or\n" \
+  "    ioassign -v -n 4 -link -a /path/target_file.%d  symbolic_link.%d\n" \
+  "(3) Assign a file with 4MB read and write buffers:\n" \
+  "    ioassign -r 4m -w 4m -a /path/target_file.%d filename_in_open_stmt.%d\n" \
+  "(4) Assign a file with internal packing of method#2:\n" \
+  "    ioassign -w 4m -m2 -a /path/target_file.%d filename_in_open_stmt.%d\n" \
+  "(5) Use pipes: \n" \
+  "    ioassign -r 2m -w 2m -c '#gzip' filename_in_open_stmt.%d\n" \
+  "(6) Explicit read-pipe from gunzip decoder; input file read to in-memory buffer:\n" \
+  "    ioassign -Incore -c 'gunzip -c < %s' filename_in_open_stmt.%d\n" \
+  "(7) Request for concatenation of 16 files upon write: \n" \
+  "    ioassign -k 16 -a /path/target_file.%d filename_in_open_stmt.%d\n" \
+  "NOTE: The two first are general purpose and do NOT need any special OPEN/READ/WRITE/CLOSE."
+
+#define APPLIED  \
+  "+ ioassign %s%s-n %d -b %d -r %d -w %d -p %d -e %d -m %d -B %d -k %d %s%s%s%s%s%s%s%s%s\n"
+
+#define FLAGS "a:b:B:c:de:f:hI:k:l:m:n:p:r:sS:vVw:x"
+
+static char *
+KiloMegaGiga(char *s)
+{
+  const double maxint = 2147483647.0;
+  char *p = s;
+  int   len = strlen(s);
+  char *last = &s[len-1];
+  double num;
+
+  if (*last == 'k' || *last == 'K') {
+    *last = '\0';
+    num = atoi(s) * 1024.0; /* multiplier: 1kB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%0.f",num);
+  }
+  else if (*last == 'm' || *last == 'M') {
+    *last = '\0';
+    num = atoi(s) * 1048576.0; /* multiplier: 1MB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+  else if (*last == 'g' || *last == 'G') {
+    *last = '\0';
+    num = atoi(s) * 1073741824.0; /* multiplier: 1GB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+
+  return p;
+}
+
+
+static int numbins       = 1;
+static int readbufsize   = 0;
+static int writebufsize  = 0;
+static int pre_alloc      = 0;
+static int extent        = 0;
+static int compression   = 0;
+static int blocksize     = 0;
+static int concat        = 0;
+static char *pipecmd     = NULL;
+static int pbcount       = 0;
+
+
+static Ioassign *
+IOassign_scan(Ioassign *p,
+         const char *file,
+         const char *alias,
+         int nproc,
+         int fromproc,
+         int toproc)
+{
+  Ioassign *empty_slot = NULL;
+  Boolean found = false;
+
+  while ( p ) {
+    Ioassign *next = p->next;
+
+    if (!p->filename) {
+      empty_slot = p;
+    }
+    else if (strequ(file, p->filename)) {
+      p->aliasname    = STRDUP(alias);
+      p->numbins      = numbins;
+      p->readbufsize  = readbufsize;
+      p->writebufsize = writebufsize;
+      p->prealloc     = pre_alloc;
+      p->extent       = extent;
+      p->compression  = compression;
+      p->blocksize    = blocksize;
+      p->concat       = concat;
+      p->pipecmd      = pipecmd ? STRDUP(pipecmd) : NULL;
+      p->maxproc      = nproc;
+      p->fromproc     = fromproc;
+      p->toproc       = toproc;
+
+      found = true;
+      break;
+    }
+
+    if (next)  
+      p = next;
+    else {
+      found = false;
+      break;
+    }
+  }
+  
+  if (!found) {
+    Ioassign *tmp;
+
+    if (empty_slot)
+      tmp = empty_slot;
+    else {
+      ALLOC(tmp, 1);
+      p->next = tmp;
+    }
+
+    p = tmp;
+
+    p->filename     = STRDUP(file);
+    p->aliasname    = STRDUP(alias);
+    p->numbins      = numbins;
+    p->readbufsize  = readbufsize;
+    p->writebufsize = writebufsize;
+    p->prealloc     = pre_alloc;
+    p->extent       = extent;
+    p->compression  = compression;
+    p->blocksize    = blocksize;
+    p->concat       = concat;
+    p->pipecmd      = pipecmd ? STRDUP(pipecmd) : NULL;
+    p->maxproc      = nproc;
+    p->fromproc     = fromproc;
+    p->toproc       = toproc;
+
+    if (!empty_slot) {
+      p->next = NULL;
+      pbcount++;
+    }
+
+    found = true;
+  }
+
+  return p;
+}
+
+FILE *
+ODB_trace_fp(void)
+{
+  /* A dummy routine to return NULL fp of non-existent tracing file */
+  return NULL;
+}
+
+#define ioassign main
+
+int ioassign(int argc, char *argv[])
+{
+  int nproc         = 1;
+  char *aliasname   = NULL;
+  char *filename    = NULL;
+  int verbose       = 0;
+  Boolean debug     = false;
+  Boolean start_no_is_set = false;
+  int print_version = 0;
+  int incore        = 0;
+  int linkonly      = 0;
+  int expand        = 0;
+  int start_no      = 1;
+  
+  Ioassign *ioassign_start = NULL;
+  
+  int c;
+  int errflg = 0;
+  extern char *optarg;
+  extern int optind;
+  /* int (*func)(void) = NULL; */
+  char *NPES = getenv("NPES");
+  char *IOASSIGN = getenv("IOASSIGN");
+  char *program = strrchr(argv[0],'/');
+    
+  program = program ? (program+1) : argv[0];
+
+  if (NPES) {
+    nproc = atoi(NPES);
+    nproc = MAX(1,nproc);
+  }
+
+  if (!IOASSIGN) IOASSIGN = "IOASSIGN";
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'a':
+      aliasname = STRDUP(optarg);
+      break;
+    case 'b':
+      numbins = atoi(optarg);
+      numbins = MAX(0,numbins);
+      break;
+    case 'B':
+      blocksize = atoi(KiloMegaGiga(optarg));
+      blocksize = MAX(0, blocksize);
+      break;
+    case 'c':
+      pipecmd = STRDUP(optarg);
+      break;
+    case 'd':
+      debug = true;
+      break;
+    case 'e':
+      extent = atoi(KiloMegaGiga(optarg));
+      extent = MAX(0,extent);
+      break;
+    case 'f':
+      filename = STRDUP(optarg);
+      break;
+    case 'h':
+      errflg++;
+      break;
+    case 'I':
+      incore = 1;
+      break;
+    case 'k':
+      concat = atoi(optarg);
+      break;
+    case 'l':
+      linkonly = 1;
+      expand   = 1;
+      break;
+    case 'm':
+      compression = atoi(optarg);
+      compression = MAX(0, compression);
+      break;
+    case 'n':
+      nproc = atoi(optarg);
+      nproc = MAX(1,nproc);
+      break;
+    case 'p':
+      pre_alloc = atoi(KiloMegaGiga(optarg));
+      pre_alloc = MAX(0,pre_alloc);
+      break;
+    case 'r':
+      readbufsize = atoi(KiloMegaGiga(optarg));
+      readbufsize = MAX(-1,readbufsize);
+      break;
+    case 's':
+      /* Do not check the existing IOASSIGN and pass data to stream directly */
+      IOASSIGN = NULL;
+      break;
+    case 'S':
+      start_no = atoi(optarg);
+      if (start_no < 1) start_no = 1;
+      start_no_is_set = true;
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    case 'V':
+      print_version = 1;
+      break;
+    case 'w':
+      writebufsize = atoi(KiloMegaGiga(optarg));
+      writebufsize = MAX(0,writebufsize);
+      break;
+    case 'x':
+      expand = 1;
+      break;
+    default:
+    case '?':
+      errflg++;
+      break;
+    }
+  }
+
+  if (print_version) {
+    fprintf(stderr,"%s: Version %s, on %s %s   %s\n", 
+	    program, vers, time_str, date_str, system_name);
+    fprintf(stderr,"Copyright (c) 1997-98, 2000 ECMWF. All Rights Reserved.\n");
+  }
+
+  if (!errflg) {
+    iostuff_debug = debug;
+
+    if (readbufsize == -1) incore = 1;
+    if (incore)            readbufsize = -1;
+
+    if (argc - 1 == optind) {
+      filename = STRDUP(argv[argc-1]);
+    }
+    else if (argc > optind) {
+      errflg++;
+    }
+  }
+
+  if (!errflg && !filename && aliasname) {
+    filename = STRDUP(aliasname);
+  }
+
+  if (!errflg && !filename) {
+    if (verbose) {
+      Ioassign *p;
+      int rc = IOassign_read(IOASSIGN, &pbcount, &ioassign_start, &p);
+
+      if (pbcount > 0) {
+	fprintf(stderr,
+		"== Contents of the current '%s' -file ==\n",
+		IOASSIGN);
+	IOassign_write(NULL, pbcount, ioassign_start);
+      }
+
+      return(0);
+    }
+    else
+      errflg++;
+  }
+
+  if (errflg) {
+    fprintf(stderr,"%s\n",USAGE);
+    return(errflg);
+  }
+
+  if (!errflg && !aliasname && filename) {
+    aliasname = STRDUP(filename);
+  }
+
+  if (!errflg && extent == 0) {
+    extent = pre_alloc;
+  }
+
+  if (!errflg && verbose) {
+    fprintf(stderr,APPLIED,
+	    verbose ? "-v " : "\0",
+	    debug   ? "-d " : "\0",
+	    nproc, numbins, readbufsize, writebufsize, 
+	    pre_alloc, extent,
+	    compression, blocksize,
+	    concat,
+	    expand ? "-x " : "\0",
+	    linkonly ? "-link " : "\0",
+	    aliasname ? "-a "     : "\0",
+	    aliasname ? aliasname : "\0",
+	    aliasname ? " "       : "\0",
+	    pipecmd ? "-c '"   : "\0",
+	    pipecmd ? pipecmd : "\0",
+	    pipecmd ? "' "     : "\0",
+	    filename ? filename : "\0");
+  }
+
+  if (!errflg) {    
+    int j;
+
+    if (linkonly) {
+      char cmd[1024];
+
+      if (has_no_percent_sign(filename)) {
+	nproc = 1;
+      }
+      
+      for (j=1; j<=nproc; j++) {
+	if (!strequ(filename,aliasname)) {
+	  char file[255], alias[255];
+	  sprintf(file,filename,j+start_no-1);
+	  sprintf(alias,aliasname,j);
+	  sprintf(cmd,"\\ln -s %s %s\n",alias,file);
+	  if (verbose) fprintf(stderr,"+ %s",cmd);
+	  system(cmd);
+	}
+      }
+    }
+    else {
+      Ioassign *p;
+      if (debug) fprintf(stderr," : IOASSIGN='%s'\n",IOASSIGN);
+      
+      errflg = IOassign_read(IOASSIGN, &pbcount, &ioassign_start, &p);
+      
+      if (!errflg || errflg == -2) {
+	
+	if (pbcount == 0 || !ioassign_start) {
+	  /* Make sure that there is at least one entry */
+	  Ioassign *p;
+	  ALLOC(p, 1);
+	  
+	  ioassign_start = p;
+	  p->next = NULL;
+	  
+	  p->filename  = NULL;
+	  p->aliasname = NULL;
+	  p->numbins  = 0;
+	  p->readbufsize  = 0;
+	  p->writebufsize = 0;
+	  p->prealloc  = 0;
+	  p->extent    = 0;
+	  p->compression  = 0;
+	  p->blocksize    = 0;
+	  p->concat    = 0;
+     p->maxproc     = 0;
+     p->fromproc  = 0;
+     p->toproc    = 0;
+	  p->pipecmd   = NULL;
+	  
+	  pbcount = 1;
+	}
+	
+
+	{ /* Update IOASSIGN-file */
+	  Ioassign *p;
+
+	  if (has_no_percent_sign(filename)) {
+	    nproc = 1;
+	  }
+
+	  if (expand) {
+	    for (j=1; j<=nproc; j++) {
+	      char *file  = IOstrdup_fmt(filename, j + start_no - 1);
+	      char *alias = IOstrdup_fmt(aliasname, j);
+	      
+	      p = IOassign_scan(ioassign_start, file, alias, 0, 0, 0);
+	      
+	      FREE(file);
+	      FREE(alias);
+	      
+	      if (verbose && p) IOassign_write(NULL, 1, p);
+	    }
+	  }
+	  else {
+	    if (has_no_percent_sign(filename) &&
+		has_no_percent_sign(aliasname)) nproc = 0;
+       if (start_no_is_set){
+          p = IOassign_scan(ioassign_start, filename, aliasname, nproc, start_no, start_no + nproc - 1 );
+       }else
+          p = IOassign_scan(ioassign_start, filename, aliasname, nproc, 0, 0 );
+	    if (verbose && p) IOassign_write(NULL, 1, p);
+	  }
+	}
+	
+	errflg = IOassign_write(IOASSIGN, pbcount, ioassign_start);
+      }
+    }
+  }
+    
+  return(errflg);
+}
diff --git a/odb/src/tools/mr2d_create.c b/odb/src/tools/mr2d_create.c
new file mode 100644
index 0000000..1d84c5d
--- /dev/null
+++ b/odb/src/tools/mr2d_create.c
@@ -0,0 +1,282 @@
+#include "mr2d_hdr.h"
+
+static char program[]="mr2d_create";
+
+/*
+
+   mr2d_create: Creates a MR2D-concatenated file from given input file(s)
+
+   Notes: Works only in a single processor mode i.e.
+          no parallel $MRFSDIR access is available on VPP
+
+*/	       
+
+#define USAGE \
+  "mr2d_create -i input_file[.%d]\n" \
+  "            -o output_file\n" \
+  "            -n number_of_input_files_in_connection_with_%d_format\n" \
+  "            -r read_buf_size\n" \
+  "            -w write_buf_size\n" \
+  "            -p preallocation_size (VPP only)\n" \
+  "            -e extent_size (VPP only)\n" \
+  "            -v [verbose output]\n" \
+  "            -A [input files are concatenated in ascending order]\n" \
+  "            -D [input files are concatenated in descending order; the default]\n" \
+  "            -V [print version number of the software]\n" \
+  "            -help"
+
+#define FLAGS "ADe:hi:n:o:p:r:vVw:"
+
+#define CHECK_ERROR(f,n) if (rc != (n)) { perror(f); return(1); }
+
+
+#define mr2d_create main
+
+int mr2d_create(int argc, char *argv[])
+{
+  int rc, fs;
+  FILE *fp_out;
+
+  int verbose = 0;
+  int print_version = 0;
+  int extent = 0;
+  int prealloc = 0;
+  int readbufsize = 0;
+  int writebufsize = 0;
+  int descending = 1;
+  int nfiles = 0;
+  char *infile = NULL;
+  char *outfile = NULL;
+
+  IObuf in, out;
+
+  unsigned int mr2dword = MR2D;
+  unsigned int numchunks = 0;
+  unsigned int *hdr = NULL;
+  int hdrsize;
+  unsigned int *index = NULL;
+  unsigned int *chunk = NULL;
+  int j, k;
+
+  int c;
+  int errflg = 0;
+  extern char *optarg;
+  extern int optind;
+
+  /* Get command line options */
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'A':
+      descending = 0;
+      break;
+    case 'D':
+      descending = 1;
+      break;
+    case 'e':
+      extent = atoi(KiloMegaGiga(optarg));
+      extent = MAX(0,extent);
+      break;
+    case 'i':
+      infile = STRDUP(optarg);
+      break;
+    case 'n':
+      nfiles = atoi(optarg);
+      nfiles = MAX(0,nfiles);
+      break;
+    case 'o':
+      outfile = STRDUP(optarg);
+      break;
+    case 'p':
+      prealloc = atoi(KiloMegaGiga(optarg));
+      prealloc = MAX(0,prealloc);
+      break;
+    case 'r':
+      readbufsize = atoi(KiloMegaGiga(optarg));
+      readbufsize = MAX(-1,readbufsize);
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    case 'V':
+      print_version = 1;
+      break;
+    case 'w':
+      writebufsize = atoi(KiloMegaGiga(optarg));
+      writebufsize = MAX(0,writebufsize);
+      break;
+    case 'h':
+      errflg++;
+      break;
+    default:
+    case '?':
+      errflg++;
+      break;
+    }
+  }
+
+  if (print_version) {
+    fprintf(stderr,"%s: Version %s, on %s %s   %s\n", 
+            program, vers, time_str, date_str, system_name);
+    fprintf(stderr,"Copyright (c) 1998 ECMWF. All Rights Reserved.\n");
+  }
+
+  if (!infile) errflg++;
+  if (!outfile) errflg++;
+  if (argc != optind) errflg++;
+  if (nfiles <= 0) errflg++;
+
+  if (errflg) {
+    fprintf(stderr,"%s\n",USAGE);
+    return(errflg);
+  }
+
+  numchunks = nfiles;
+  hdrsize = 2 + 2 * numchunks;
+
+  /* Open the output file */
+
+  fp_out = fopen_prealloc(outfile,"w",prealloc,extent);
+
+  if (!fp_out) {
+    perror(outfile);
+    return(1);
+  }
+
+  /* Obtain input file sizes */
+
+  if (has_no_percent_sign(infile)) {
+    char *p;
+    
+    ALLOC(p, strlen(infile) + 20);
+    strcpy(p,infile);
+    strcat(p,".%d");
+    
+    FREE(infile);
+    infile = p;
+  }
+
+  /* Calculate chunk sizes */
+
+  ALLOC(hdr, hdrsize);
+  ALLOC(index, numchunks);
+  ALLOC(chunk, numchunks);
+
+  if (descending) {
+    k = 0;
+    for (j=numchunks; j>=1; j--) {
+      index[k] = j;
+      k++;
+    }
+  }
+  else {
+    for (j=1; j<=numchunks; j++) {
+      index[j-1] = j;
+    }
+  }
+
+  for (j=0; j<numchunks; j++) {
+    char *file;
+    ALLOC(file, strlen(infile) + 20);
+    sprintf(file,infile,index[j]);
+    chunk[j] = filesize(file);
+    FREE(file);
+  }
+
+  
+  hdr[0] = mr2dword;
+  hdr[1] = numchunks;
+  k = 2;
+  for (j=0; j<numchunks; j++) {
+    hdr[k + 0] = index[j];
+    hdr[k + 1] = chunk[j];
+    k += 2;
+  }
+
+  fs = hdrsize * sizeof(unsigned int);
+  for (j=0; j<numchunks; j++) {
+    fs += chunk[j];
+  }
+
+  if (writebufsize > 0 || writebufsize == -1) {
+    out.len = (writebufsize == -1) ? fs : writebufsize;
+    out.len = MIN(out.len, fs);
+    SETBUF(fp_out, out);
+  }
+  else {
+    out.len = 0;
+    out.p = NULL;
+  }
+
+  rc = fwrite(hdr, sizeof(unsigned int), hdrsize, fp_out);
+  CHECK_ERROR(outfile,hdrsize);
+
+  FREE(hdr);
+
+  /* Read in file-by-file and write to the file */
+
+  if (verbose) {
+    printf("%s: Concatenating input files to the '%s'\n",program,outfile);
+    printf("Writing order %s\n",descending ? "descending" : "ascending");
+    for (j=0; j<numchunks; j++) {
+      printf("Chunk#%d for PE#%d : size = %d bytes\n",
+	     j+1,index[j],chunk[j]);
+    }
+  }
+  
+  for (j=0; j<numchunks; j++) {
+    unsigned char *data;
+    int datasize;
+    char *file;
+    FILE *fp_in;
+    
+    ALLOC(file, strlen(infile) + 20);
+    sprintf(file,infile,index[j]);
+    
+    datasize = chunk[j];
+    if (verbose) {
+      printf("Reading %d bytes from the file '%s' ...\n",
+	     datasize,file);
+    }
+
+    fp_in = fopen(file,"r");
+    if (!fp_in) {
+      perror(file);
+      return(1);
+    }
+
+    if (readbufsize == -1) readbufsize = datasize;
+    if (readbufsize > 0) {
+      in.len = MIN(readbufsize,datasize);
+      SETBUF(fp_in, in);
+    }
+    else {
+      in.len = 0;
+      in.p = NULL;
+    }
+
+    ALLOC(data, datasize);
+    rc = fread(data, sizeof(unsigned char), datasize, fp_in);
+    CHECK_ERROR(infile,datasize);
+
+    rc = fwrite(data, sizeof(unsigned char), datasize, fp_out);
+    CHECK_ERROR(file,datasize);
+
+    fclose(fp_in);
+
+    FREEIOBUF(in);
+    
+    FREE(data);
+    FREE(file);
+  }
+
+  fclose(fp_out);
+
+  FREEIOBUF(out);
+
+  FREE(index);
+  FREE(chunk);
+
+  return(0);
+}
+
diff --git a/odb/src/tools/mr2d_split.c b/odb/src/tools/mr2d_split.c
new file mode 100644
index 0000000..1ff184e
--- /dev/null
+++ b/odb/src/tools/mr2d_split.c
@@ -0,0 +1,272 @@
+#include "mr2d_hdr.h"
+
+static char program[]="mr2d_split";
+
+/*
+
+   mr2d_split: From a given concatenated file creates
+               individual files as they were before concatenation.
+	       Number of files to be created is defined from the 
+	       input file's M2RD-header.
+
+   Notes: Works only in a single processor mode i.e.
+          no parallel $MRFSDIR access is available on VPP
+
+
+*/	       
+
+#define USAGE \
+  "mr2d_split  -i input_file\n" \
+  "            -o output_file[.%d]\n" \
+  "            -r read_buf_size\n" \
+  "            -w write_buf_size\n" \
+  "            -p preallocation_size (VPP only)\n" \
+  "            -e extent_size (VPP only)\n" \
+  "            -v [verbose output]\n" \
+  "            -V [print version number of the software]\n" \
+  "            -help"
+
+#define FLAGS "e:hi:o:p:r:vVw:"
+
+
+#define CHECK_ERROR(f,n) if (rc != (n)) { perror(f); return(1); }
+
+
+#define mr2d_split main
+
+int mr2d_split(int argc, char *argv[])
+{
+  int rc, fs;
+  FILE *fp_in;
+
+  int verbose = 0;
+  int print_version = 0;
+  int extent = 0;
+  int prealloc = 0;
+  int readbufsize = 0;
+  int writebufsize = 0;
+  char *infile = NULL;
+  char *outfile = NULL;
+
+  IObuf in, out;
+
+  unsigned int mr2dword = 0;
+  unsigned int numchunks = 0;
+
+  int c;
+  int errflg = 0;
+  extern char *optarg;
+  extern int optind;
+
+  /* Get command line options */
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'e':
+      extent = atoi(KiloMegaGiga(optarg));
+      extent = MAX(0,extent);
+      break;
+    case 'i':
+      infile = STRDUP(optarg);
+      break;
+    case 'o':
+      outfile = STRDUP(optarg);
+      break;
+    case 'p':
+      prealloc = atoi(KiloMegaGiga(optarg));
+      prealloc = MAX(0,prealloc);
+      break;
+    case 'r':
+      readbufsize = atoi(KiloMegaGiga(optarg));
+      readbufsize = MAX(-1,readbufsize);
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    case 'V':
+      print_version = 1;
+      break;
+    case 'w':
+      writebufsize = atoi(KiloMegaGiga(optarg));
+      writebufsize = MAX(0,writebufsize);
+      break;
+    case 'h':
+      errflg++;
+      break;
+    default:
+    case '?':
+      errflg++;
+      break;
+    }
+  }
+
+  if (print_version) {
+    fprintf(stderr,"%s: Version %s, on %s %s   %s\n", 
+            program, vers, time_str, date_str, system_name);
+    fprintf(stderr,"Copyright (c) 1998 ECMWF. All Rights Reserved.\n");
+  }
+
+  if (!infile) errflg++;
+  if (!outfile) errflg++;
+  if (argc != optind) errflg++;
+
+  if (errflg) {
+    fprintf(stderr,"%s\n",USAGE);
+    return(errflg);
+  }
+
+  /* Process the input file */
+
+  fp_in = fopen(infile,"r");
+
+  if (!fp_in) {
+    perror(infile);
+    return(1);
+  }
+
+  fs = filesize_by_fp(fp_in, infile);
+  if (fs < 8) {
+    fprintf(stderr,"%s: Invalid file length %d bytes\n",infile,fs);
+    return(1);
+  }
+
+  if (readbufsize == -1) readbufsize = fs;
+  if (readbufsize > 0) {
+    in.len = MIN(readbufsize,fs);
+    SETBUF(fp_in, in);
+  }
+  else {
+    in.len = 0;
+    in.p = NULL;
+  }
+
+  rc = fread(&mr2dword, sizeof(unsigned int), 1, fp_in);
+  CHECK_ERROR(infile,1);
+
+  if (mr2dword != MR2D) {
+    fprintf(stderr,"%s: File is not an MR2D-file\n",infile);
+    return(1);
+  }
+
+  rc = fread(&numchunks, sizeof(unsigned int), 1, fp_in);
+  CHECK_ERROR(infile,1);
+
+  if (verbose) {
+    printf("%s: Splitting file '%s' into %d chunks ...\n",
+	   program,infile,numchunks);
+  }
+
+
+  /* Read in chunk-by-chunk and write out to the corresponding output files */
+
+  if (numchunks > 0) {
+    int j, k;
+    unsigned int sum;
+    unsigned int *hdr = NULL;
+    int hdrsize = 2 * numchunks;
+    unsigned int *index = NULL;
+    unsigned int *chunk = NULL;
+    
+    ALLOC(hdr, hdrsize);
+    ALLOC(index, numchunks);
+    ALLOC(chunk, numchunks);
+
+    rc = fread(hdr, sizeof(unsigned int), hdrsize, fp_in);
+    CHECK_ERROR(infile,hdrsize);
+
+    k = 0;
+    for (j=0; j<numchunks; j++) {
+      index[j] = hdr[k + 0];
+      chunk[j] = hdr[k + 1];
+      k += 2;
+    }
+
+    if (verbose) {
+      for (j=0; j<numchunks; j++) {
+	printf("Chunk#%d for PE#%d : size = %d bytes\n",
+	       j+1,index[j],chunk[j]);
+      }
+    }
+
+    /* Cross-check that the sum of hdrlen and fsizes equals to filesize */
+
+    sum = (1 + 1 + hdrsize) * sizeof(unsigned int);
+    for (j=0; j<numchunks; j++) {
+      sum += chunk[j];
+    }
+
+    if (sum != fs) {
+      fprintf(stderr,"%s: Chunksize(s) mismatch with filesize (=%d)\n",
+	      infile,fs);
+      return(1);
+    }
+
+    if (has_no_percent_sign(outfile)) {
+      char *p;
+
+      ALLOC(p, strlen(outfile) + 20);
+      strcpy(p,outfile);
+      strcat(p,".%d");
+
+      FREE(outfile);
+      outfile = p;
+    }
+
+    for (j=0; j<numchunks; j++) {
+      unsigned char *data;
+      int datasize;
+      char *file;
+      FILE *fp_out;
+
+      ALLOC(file, strlen(outfile) + 20);
+      sprintf(file,outfile,index[j]);
+
+      datasize = chunk[j];
+      if (verbose) {
+	printf("Writing %d bytes to the file '%s' ...\n",
+	       datasize,file);
+      }
+
+      fp_out = fopen_prealloc(file,"w",prealloc,extent);
+      if (!fp_out) {
+	perror(file);
+	return(1);
+      }
+
+      if (writebufsize > 0 || writebufsize == -1) {
+	out.len = (writebufsize == -1) ? datasize : writebufsize;
+	out.len = MIN(out.len, datasize);
+	SETBUF(fp_out, out);
+      }
+      else {
+	out.len = 0;
+	out.p = NULL;
+      }
+
+      ALLOC(data, datasize);
+      rc = fread(data, sizeof(unsigned char), datasize, fp_in);
+      CHECK_ERROR(infile,datasize);
+
+      rc = fwrite(data, sizeof(unsigned char), datasize, fp_out);
+      CHECK_ERROR(file,datasize);
+
+      fclose(fp_out);
+
+      FREEIOBUF(out);
+
+      FREE(data);
+      FREE(file);
+    }
+
+    fclose(fp_in);
+
+    FREE(hdr);
+    FREE(index);
+    FREE(chunk);
+  }
+
+  FREEIOBUF(in);
+
+  return(0);
+}
+
diff --git a/odb/src/tools/mysort.c b/odb/src/tools/mysort.c
new file mode 100644
index 0000000..412b3b2
--- /dev/null
+++ b/odb/src/tools/mysort.c
@@ -0,0 +1,469 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* mysort.c */
+
+/* /bin/sort seem to have some serious performance problems
+   when running under rsh --> decided to implement a small
+   home baked version to overcome these troubles */
+
+/* Author: Sami Saarinen, ECMWF, 31-Dec-2007 */
+
+/* 
+   Usage: mysort [-nrfu] [-v] [-k POS1[,POS2]] < input_file > output_file
+          mysort [-nrfu] [-v] [-k POS1[,POS2]] [input_file] > output_file
+          mysort [-nrfu] [-v] [-k POS1[,POS2]] [-o output_file] < input_file 
+
+   -n : numeric sort
+   -r : reverse order
+   -f : ignore case
+   -u : print unique only
+   -v : verbose
+
+   The following can be supplied multiple times :
+
+   -k POS1[,POS2]] : sort w.r.t column POS1 (origin 1) and end it at POS2
+   -K POS1[,POS2]] : sort w.r.t column POS1 (origin 0) and end it at POS2
+
+   The old format +POS1 -POS2 (origin 0) could also be used (i.e. -K POS1,POS2)
+
+   Note: POS1 & POS2 must currently be (integer) numbers
+*/
+
+#undef MAX
+#define MAX(a,b) ( ((a) > (b)) ? (a) :  (b) )
+
+typedef          long long int  ll_t;
+
+#define ALLOC(x,size) { \
+  ll_t _nbytes = MAX(1,(size)) * sizeof(*(x)); \
+  x = malloc(_nbytes); \
+  if (!x) { \
+    fprintf(stderr,"***Error: Unable to ALLOCate %lld bytes at %s:%d\n",\
+            _nbytes, __FILE__, __LINE__); \
+    abort(); \
+  } \
+}
+
+#define CALLOC(x,size) { \
+  ll_t _nbytes = MAX(1,(size)) * sizeof(*(x)); \
+  ALLOC(x,size); \
+  memset(x,0,_nbytes); \
+}
+
+#define FREE(x) ((x) ? (free(x), (x) = NULL) : NULL)
+
+#define STRDUP(s) strdup((s) ? (s) : "")
+
+
+#define strequ(s1,s2)     ((const void *)(s1) && (const void *)(s2) && *(s1) == *(s2) && strcmp(s1,s2) == 0)
+
+
+#define FLAGS "fK:k:no:ruv"
+
+static int no_ties = 0;
+static int ignore_case = 0;
+
+static int 
+IsNumber(const char *p) 
+{
+  int count = 0;
+  if (p) {
+    while (*p != '\0') {
+      if (!isdigit(*p)) {
+	count = 0;
+	break;
+      }
+      count++;
+      p++;
+    }
+  }
+  return (count > 0) ? 1 : 0;
+}
+
+
+typedef struct _line_t {
+  const char *s;
+  struct _line_t *next;
+} line_t;
+
+typedef struct {
+  const char *s;
+  double num;
+  int j;
+  int off;
+} str_t;
+
+
+
+static int
+StrCmp(const str_t *a, const str_t *b)
+{
+  int a_off = a->off;
+  int b_off = b->off;
+  int rc = ignore_case ?
+    strcmp(a->s+a_off, b->s+b_off) : 
+    strcasecmp(a->s+a_off, b->s+b_off);
+  if      ( rc > 0 ) return  1;
+  else if ( rc < 0 ) return -1;
+  else { /* strings are equal --> the original rank-order "j" decides */
+    return no_ties ? rc : ((a->j > b->j) ? 1 : -1);
+  }
+}
+
+static int
+StrCmpRev(const str_t *a, const str_t *b)
+{
+  int a_off = a->off;
+  int b_off = b->off;
+  int rc = ignore_case ?
+    strcmp(a->s+a_off, b->s+b_off) : 
+    strcasecmp(a->s+a_off, b->s+b_off);
+  if      ( rc < 0 ) return  1;
+  else if ( rc > 0 ) return -1;
+  else { /* strings are equal --> the original rank-order "j" decides */
+    return no_ties ? rc : ((a->j > b->j) ? 1 : -1);
+  }
+}
+
+static int
+NumCmp(const str_t *a, const str_t *b)
+{
+  if      ( a->num > b->num ) return  1;
+  else if ( a->num < b->num ) return -1;
+  else { /* numbers are equal --> the remaining line decides */
+    return no_ties ? 0 : StrCmp(a,b);
+  }
+}
+
+static int
+NumCmpRev(const str_t *a, const str_t *b)
+{
+  if      ( a->num < b->num ) return  1;
+  else if ( a->num > b->num ) return -1;
+  else { /* numbers are equal --> the remaining line decides */
+    return no_ties ? 0 : StrCmpRev(a,b);
+  }
+}
+
+static void
+ExtractNumField(int jf, str_t x[], int numlines)
+{
+  int j;
+#if 0
+  fprintf(stderr,"ExtractNumField(jf=%d, ..., numlines = %d)\n",jf,numlines);
+#endif
+  for (j=0; j<numlines; ++j) {
+    int nf = 1;
+    const char *s = x[j].s;
+    while (isspace(*s)) ++s;
+    while (nf < jf) {
+      int delim = ' ';
+      const char *x = (const char *)strchr(s, delim);
+      if (x) { ++nf; s = ++x; }
+      else { s = NULL; break; }
+    }
+    if (s && nf == jf) {
+      x[j].num = atof(s);
+      x[j].off = s - x[j].s;
+    }
+    else {
+      x[j].num = 0;
+      x[j].off = 0;
+    }
+#if 0
+    fprintf(stderr,"x[%d].num = %.10g (%s)\n",j,x[j].num, x[j].s + x[j].off);
+#endif
+  }
+}
+
+
+typedef struct _pos_t {
+  int pos1;
+  int pos2;
+  struct _pos_t *next;
+  struct _pos_t *prev;
+} pos_t;
+
+int
+main(int argc, char *argv[])
+{
+  int c;
+  int errflg = 0;
+  int j, jn;
+  int new_argc = argc;
+  char **new_argv = NULL;
+  int numeric = 0;
+  int reverse = 0;
+  int unique = 0;
+  int verbose = 0;
+  pos_t *pos = NULL;
+  pos_t *this_pos = NULL;
+  char *output_file = NULL;
+  char *input_file = NULL;
+  
+  for (j=1; j<argc; ++j) {
+    char *opt = argv[j];
+    if (strequ(opt,"-v")) {
+      verbose = 1;
+      break;
+    }
+  }
+
+  if (verbose) fprintf(stderr,"argc = %d\n", argc);
+
+  CALLOC(new_argv, argc);
+  jn = 0;
+  for (j=0; !errflg && j<argc; ) {
+    char *opt = argv[j];
+    if (verbose) fprintf(stderr, "argv[%d] = '%s'\n", j, argv[j]);
+
+    if (*opt == '+' && IsNumber(opt+1)) {
+      int pos1 = atoi(opt+1)+1;
+      int pos2 = pos1;
+
+      if (j < argc - 1) {
+	char *next_opt = argv[j+1];
+	if (*next_opt == '-' && IsNumber(next_opt+1)) {
+	  pos2 = atoi(next_opt+1)+1;
+	  ++j;
+	}
+      } /* if (j < argc - 1) */
+
+      {
+	int len = 100;
+	ALLOC(new_argv[jn], len);
+	snprintf(new_argv[jn++], len, "-k%d,%d",pos1,pos2);
+      }
+    }
+    else {
+      new_argv[jn++] = STRDUP(opt);
+    }
+    ++j;
+  }
+
+  new_argc = jn;
+
+  if (verbose) {
+    fprintf(stderr,"new_argc = %d\n", new_argc);
+    for (j=0; j<new_argc; ++j) {
+      fprintf(stderr, "new_argv[%d] = '%s'\n", j, new_argv[j]);
+    }
+  }
+
+  while (!errflg && (c = getopt(new_argc, new_argv, FLAGS)) != -1) {
+    int origin = 0;
+    switch (c) {
+    case 'f':
+      ignore_case = 1;
+      break;
+    case 'K':
+      origin = 1;
+      /* Fall through */
+    case 'k':
+      {
+	int pos1, pos2;
+	char *comma = strchr(optarg,',');
+	int nelem = comma ? 
+	  sscanf(optarg,"%d,%d", &pos1, &pos2) :
+	  sscanf(optarg,"%d", &pos1);
+	int all_ok = (( comma && nelem == 2) ||
+		      (!comma && nelem == 1) ) ? 1 : 0;
+	if (all_ok) {
+	  pos_t *next_pos = NULL;
+	  if (nelem == 1) pos2 = pos1;
+
+	  ALLOC(next_pos,1);
+	  next_pos->pos1 = origin + pos1;
+	  next_pos->pos2 = origin + pos2;
+	  next_pos->next = NULL;
+	  next_pos->prev = this_pos;
+
+	  if (this_pos) {
+	    this_pos->next = next_pos;
+	    this_pos = next_pos;
+	  }
+	  else {
+	    pos = this_pos = next_pos;
+	  }
+	}
+	else {
+	  fprintf(stderr,"***Error: Syntax of -%c option is : -%cPOS1[,POS2]\n",
+		  (c == 'k') ? 'k' : 'K',
+		  (c == 'k') ? 'k' : 'K');
+	  ++errflg;
+	}
+      }
+      break;
+    case 'n':
+      numeric = 1;
+      break;
+    case 'o':
+      FREE(output_file);
+      output_file = STRDUP(optarg);
+      break;
+    case 'r':
+      reverse = 1;
+      break;
+    case 'u':
+      unique = 1;
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    default:
+      fprintf(stderr,"***Error: Invalid option '-%c'\n",c);
+      ++errflg;
+      break;
+    } /* switch (c) */
+  }
+
+  if (verbose) fprintf(stderr,"optind = %d, new_argc = %d\n",optind,new_argc);
+
+  if (!errflg) {
+    if (optind < new_argc) {
+      if (optind + 1 == new_argc) input_file = STRDUP(argv[optind]);
+      else {
+	fprintf(stderr,"***Error: Too many args\n");
+	++errflg;
+      }
+    }
+  }
+
+  if (!errflg) {
+    /* So far now errors --> proceed with input & sort & output */
+    FILE *fpin = input_file ? fopen(input_file,"r") : stdin;
+    char *buf = NULL;
+
+    if (fpin) {
+      int buflen = 0;
+      char *pbuf = NULL;
+      int curlen = 0;
+      
+      while ((c = fgetc(fpin)) != EOF) {
+	if (curlen >= buflen) {
+	  char *newbuf = NULL;
+	  buflen += 1048576;
+	  ALLOC(newbuf, buflen+1);
+	  if (buf) {
+	    memcpy(newbuf,buf,curlen);
+	    FREE(buf);
+	  }
+	  buf = newbuf;
+	  pbuf = buf + curlen;
+	}
+	*pbuf++ = c;
+	++curlen;
+      }
+      if (pbuf) *pbuf = '\0';
+    }
+    else {
+      fprintf(stderr,"***Error: Unable to open input file '%s'\n",input_file);
+      ++errflg;
+    }
+    
+    if (buf) {
+      str_t *x = NULL;
+      int numlines = 0;
+      char *nl = buf;
+      line_t *this_lines = NULL;
+      line_t *lines = NULL;
+
+      CALLOC(lines,1);
+      lines->s = nl;
+      this_lines = lines;
+      ++numlines;
+
+      while ((nl = strchr(nl,'\n')) != NULL) {
+	line_t *next_lines = NULL;
+	*nl++ = '\0';
+	if (*nl == '\0') break;
+
+	CALLOC(next_lines, 1);
+	next_lines->s = nl;
+	this_lines->next = next_lines;
+	this_lines = next_lines;
+	++numlines;
+      }
+
+      if (verbose) fprintf(stderr,"numlines = %d\n",numlines);
+
+      CALLOC(x, numlines);
+      this_lines = lines;
+      for (j=0; j<numlines; ++j) {
+	line_t *saveptr = this_lines;
+	x[j].s = this_lines->s;
+	x[j].num = (!pos && numeric) ? atof(this_lines->s) : 0;
+	x[j].j = j;
+	x[j].off = 0;
+	this_lines = this_lines->next;
+	FREE(saveptr);
+      }
+
+      if (!pos) {
+	if (numeric) {
+	  qsort(x, numlines, sizeof(*x),
+		reverse ?
+		(int (*)(const void *, const void *))NumCmpRev :
+		(int (*)(const void *, const void *))NumCmp);
+	}
+	else {
+	  qsort(x, numlines, sizeof(*x),
+		reverse ?
+		(int (*)(const void *, const void *))StrCmpRev :
+		(int (*)(const void *, const void *))StrCmp);
+	}
+      }
+      else {
+	while (this_pos) {
+	  int jf;
+	  int pos1 = this_pos->pos1;
+	  int pos2 = this_pos->pos2;
+	  if (pos2 >= pos1) {
+	    for (jf = pos2; jf >= pos1; --jf) {
+	      ExtractNumField(jf, x, numlines);
+	      qsort(x, numlines, sizeof(*x),
+		    reverse ?
+		    (int (*)(const void *, const void *))NumCmpRev :
+		    (int (*)(const void *, const void *))NumCmp);
+	      no_ties = 1; /* Correct ? */
+	    }
+	  }
+	  this_pos = this_pos->prev;
+	}
+      }
+
+      {
+	FILE *fpout = output_file ? fopen(output_file,"w") : stdout;
+	if (fpout) {
+	  if (unique) {
+	    const char *prev_line = NULL;
+	    for (j=0; j<numlines; ++j) {
+	      const char *this_line = x[j].s;
+	      if (!prev_line || !strequ(prev_line,this_line)) {
+		fprintf(fpout,"%s\n",this_line);
+		prev_line = this_line;
+	      }
+	    }
+	  }
+	  else {
+	    for (j=0; j<numlines; ++j) {
+	      fprintf(fpout,"%s\n",x[j].s);
+	    }
+	  }
+	  if (output_file) fclose(fpout);
+	}
+	else {
+	  fprintf(stderr,"***Error: Unable to open output file '%s'\n",output_file);
+	  ++errflg;
+	}
+      }
+
+    }
+  }
+
+  return errflg;
+}
diff --git a/odb/src/tools/odb2rgg.c b/odb/src/tools/odb2rgg.c
new file mode 100644
index 0000000..3a6414d
--- /dev/null
+++ b/odb/src/tools/odb2rgg.c
@@ -0,0 +1,306 @@
+
+/* odb2rgg.c */
+
+#include "odbdump.h"
+#include "regcache.h"
+
+/* 
+   Creates a Reduced Gaussian Grid from observations 
+   at a given T-resolution (rtablel_2-type) from observations 
+   Output should be suitable for GRIB-generation programs
+*/
+
+#define USAGE \
+"Usage: odb2rgg [-T<resol>|-t<resol>]\n" \
+"               [-c ODB_column_name]\n" \
+"               [-f 'FROM-table(s)']\n" \
+"               [-w 'where statement']\n" \
+"               [-i database_path]\n" \
+"               [-p poolmask]\n" \
+"               [-b]   # binary output mode\n" \
+"               [-g]   # debug output to odb2rgg.stderr\n" \
+"               [-N]   # print ALSO missing data boxes\n" \
+"               [-h]   # print this help/usage\n" \
+"\n" \
+"\tIf resolution <resol> is missing, then <resol>=31 is assumed.\n" \
+"\tIf no ODB-column is given, then 'obsvalue at body' is assumed.\n" \
+"\tIf no FROM-table(s) are given, then 'hdr,body,errstat' is assumed.\n" \
+"\tIf no WHERE-statement given, then 'obstype at hdr = $synop AND varno at body = $t2m' is assumed. \n" \
+"\t  Note: You should omit the word WHERE !\n" \
+"\tIf no database_path given, then 'ECMA.conv' is assumed.\n" \
+"\tIf no poolmask given, then all pools will be scanned.\n"
+
+#define FLAGS "bc:f:ghi:Np:t:T:w:"
+
+int main(int argc, char *argv[])
+{
+  char *database = STRDUP("ECMA.conv");
+  char *from = STRDUP("hdr,body,errstat");
+  int Txxxx = 31;
+  char *colname = STRDUP("obsvalue at body");
+  char *where = STRDUP("obstype at hdr = $synop AND varno at body = $t2m");
+  char *poolmask = NULL;
+  Bool binary = false;
+  Bool debug_on = false;
+  Bool print_mdi = false;
+  int errflg = 0;
+  int c;
+  extern int optind;
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'b':
+      binary = true;
+      break;
+
+    case 'c':
+      if (colname) FREE(colname);
+      colname = STRDUP(optarg);
+      break;
+
+    case 'f':
+      if (from) FREE(from);
+      from = STRDUP(optarg);
+      break;
+
+    case 'g':
+      debug_on = true;
+      break;
+
+    case 'i':
+      if (database) FREE(database);
+      database = STRDUP(optarg);
+      break;
+
+    case 'N':
+      print_mdi = true;
+      break;
+
+    case 'p':
+      if (poolmask) { /* Append more ; remember to add the comma (',') between !! */
+	int len = STRLEN(poolmask) + 1 + STRLEN(optarg) + 1;
+	char *p;
+	ALLOC(p, len);
+	snprintf(p, len, "%s,%s", poolmask, optarg);
+	FREE(poolmask);
+	poolmask = p;
+      }
+      else {
+	poolmask = STRDUP(optarg);
+      }
+      break;
+
+    case 't':
+    case 'T':
+      Txxxx = atoi(optarg);
+      break;
+
+    case 'w':
+      if (where) FREE(where);
+      where = STRDUP(optarg);
+      break;
+
+    case 'h': /* help !! */
+    default:
+      ++errflg;
+      break;
+    }
+  } /* while ((c = getopt(argc, argv, FLAGS)) != -1) */
+
+  if (errflg > 0) {
+    fprintf(stderr,USAGE);
+    goto finish;
+  }
+
+
+  {
+    void *h = NULL;
+    const double Rmdi = -ABS(mdi);
+    int maxcols = 0;
+    double *d = NULL;
+    const char sqlfmt_txt[] = 
+      "SET $Txxxx = %d;"
+      "SELECT count(*), avg(%s), stdev(%s), min(%s), max(%s),"
+      "       rgg_boxlat(lldegrees(lat at hdr), lldegrees(lon at hdr), $Txxxx),"
+      "       rgg_boxlon(lldegrees(lat at hdr), lldegrees(lon at hdr), $Txxxx),"
+      "       rgg_boxid(lldegrees(lat at hdr), lldegrees(lon at hdr), $Txxxx),"
+      "FROM %s "
+      "WHERE %s "
+      "ORDERBY %d";
+    const char sqlfmt_bin[] = 
+      "SET $Txxxx = %d;"
+      "SELECT count(*), avg(%s), stdev(%s), min(%s), max(%s),"
+      "       rgg_boxid(lldegrees(lat at hdr), lldegrees(lon at hdr), $Txxxx),"
+      "FROM %s "
+      "WHERE %s "
+      "ORDERBY %d";
+    int nsort = binary ? 6 : 8;
+    char *sql_query = NULL;
+    int len = 
+      STRLEN(binary ? sqlfmt_bin : sqlfmt_txt) + 
+      4 * STRLEN(colname) + STRLEN(from) + 
+      STRLEN(where) + 100;
+
+    if (debug_on) (void) ODBc_debug_fp(stderr);
+    odbdump_reset_stderr(NULL, "odb2rgg.stderr", NULL);
+
+    ALLOC(sql_query, len);
+    snprintf(sql_query, len,
+	     binary ? sqlfmt_bin : sqlfmt_txt,
+	     Txxxx, 
+	     colname, colname, colname, colname,
+	     from, where, nsort);
+
+    h = odbdump_open(database, sql_query, NULL, poolmask, NULL, &maxcols);
+
+    if (debug_on) fprintf(stderr, "h = %p, maxcols = %d, nsort = %d\n", h, maxcols, nsort);
+    
+    if (h && maxcols >= nsort) {
+      FILE *fp = stdout;
+      regcache_t *regp = ODBc_get_rgg_cache(Txxxx); /* Blows up if unsupported resolution */
+      int nboxes = regp->nboxes;
+      int last_boxid = 0;
+      int dlen = maxcols;
+      int nd, new_dataset = 0;
+      colinfo_t *ci = NULL;
+      int nci = 0;
+      static const char fmt1[] = "#%11s %12s %20s %20s %20s %20s %20s %20s\n";
+      static const char fmt2[] = "%12d %12d %20.12g %20.12g %20.12g %20.12g %20.12g %20.12g\n";
+
+
+      if (binary) {
+	int reclen = sizeof(Txxxx) + sizeof(nboxes) + sizeof(Rmdi);
+	fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran start record delimeter */
+	fwrite(&Txxxx, sizeof(Txxxx), 1, fp);   /* integer*4 */
+	fwrite(&nboxes, sizeof(nboxes), 1, fp); /* integer*4 */
+	fwrite(&Rmdi, sizeof(Rmdi), 1, fp);     /* real*8 */
+	fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran end record delimeter */
+      }
+      else {
+	fprintf(fp,"%d    # Resolution w.r.t. rtablel_2<resol>\n", Txxxx);
+	fprintf(fp,"%d    # of points or boxes\n", nboxes);
+	fprintf(fp,"%.12g # missing data indicator\n", Rmdi);
+	/* The following are present only for the non-binary output */
+	fprintf(fp,"%s    # database\n", database);
+	fprintf(fp,"%s    # poolmask\n", poolmask ? poolmask : "-1");
+	fprintf(fp,"%s    # ODB-column in concern\n", colname);
+	fprintf(fp,"%s    # FROM-tables\n", from);
+	fprintf(fp,"%s    # WHERE-condition\n", where);
+	fprintf(fp,fmt1, "boxid", "count", "average", "stdev", "min", "max", "lat", "lon");
+      }
+
+      ALLOCX(d, maxcols);
+      
+      while ( (nd = odbdump_nextrow(h, d, dlen, &new_dataset)) > 0) {
+	if (new_dataset) {
+	  /* New query ? */
+	  ci = odbdump_destroy_colinfo(ci, nci);
+	  ci = odbdump_create_colinfo(h, &nci);
+	}
+
+	nd = MIN(nd, nci);
+
+	{
+	  int i, boxid = (int)d[nd-1];
+	  int cnt = 0;
+	  double avg = Rmdi, stdev = Rmdi;
+	  double lat = Rmdi, lon = Rmdi;
+	  double min = Rmdi, max = Rmdi;
+
+	  if (print_mdi && boxid > last_boxid + 1) {
+	    /* Generate missing data info */
+	    int j;
+	    for (j=last_boxid + 1; j<boxid; j++) {
+	      if (binary) {
+		/* Binary output ignores lat,lon & boxid */
+		int reclen = sizeof(j) + sizeof(cnt) + 
+		  sizeof(avg) + sizeof(stdev) + sizeof(min) + sizeof(max);
+		fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran start record delimeter */
+		fwrite(&j, sizeof(j), 1, fp);           /* integer*4 */
+		fwrite(&cnt, sizeof(cnt), 1, fp);       /* integer*4 */
+		fwrite(&avg, sizeof(avg), 1, fp);       /* real*8 */
+		fwrite(&stdev, sizeof(stdev), 1, fp);   /* real*8 */
+		fwrite(&min, sizeof(min), 1, fp);       /* real*8 */
+		fwrite(&max, sizeof(max), 1, fp);       /* real*8 */
+		fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran end record delimeter */
+	      }
+	      else {
+		fprintf(fp, fmt2, j, cnt, avg, stdev, min, max, lat, lon);
+	      }
+	    } /* for (j=last_boxid + 1; j<boxid; j++) */
+	  }
+
+	  cnt = (int)d[0];
+	  avg = d[1];
+	  stdev = d[2];
+	  min = d[3];
+	  max = d[4];
+
+	  if (print_mdi || ABS(avg) != mdi) {
+	    if (binary) {
+	      /* Binary output ignores lat,lon & boxid */
+	      int reclen = sizeof(boxid) + sizeof(cnt) + 
+		sizeof(avg) + sizeof(stdev) + sizeof(min) + sizeof(max);
+	      fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran start record delimeter */
+	      fwrite(&boxid, sizeof(boxid), 1, fp);   /* integer*4 */
+	      fwrite(&cnt, sizeof(cnt), 1, fp);       /* integer*4 */
+	      fwrite(&avg, sizeof(avg), 1, fp);       /* real*8 */
+	      fwrite(&stdev, sizeof(stdev), 1, fp);   /* real*8 */
+	      fwrite(&min, sizeof(min), 1, fp);       /* real*8 */
+	      fwrite(&max, sizeof(max), 1, fp);       /* real*8 */
+	      fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran end record delimeter */
+	    }
+	    else {
+	      lat = d[5];
+	      lon = d[6];
+	      fprintf(fp, fmt2, boxid, cnt, avg, stdev, min, max, lat, lon);
+	    }
+	  }
+
+	  last_boxid = boxid;
+	}
+      } /* while (...) */
+
+      if (print_mdi && last_boxid < nboxes) {
+	/* Generate remainder of the missing data info */
+	int i, j;
+	const int cnt = 0;
+	const double avg = Rmdi, stdev = Rmdi;
+	const double lat = Rmdi, lon = Rmdi;
+	const double min = Rmdi, max = Rmdi;
+	for (j=last_boxid + 1; j<=nboxes; j++) {
+	  if (binary) {
+	    /* Binary output ignores lat,lon & boxid */
+	    int reclen = sizeof(j) + sizeof(cnt) + 
+	      sizeof(avg) + sizeof(stdev) + sizeof(min) + sizeof(max);
+	    fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran start record delimeter */
+	    fwrite(&j, sizeof(j), 1, fp);           /* integer*4 */
+	    fwrite(&cnt, sizeof(cnt), 1, fp);       /* integer*4 */
+	    fwrite(&avg, sizeof(avg), 1, fp);       /* real*8 */
+	    fwrite(&stdev, sizeof(stdev), 1, fp);   /* real*8 */
+	    fwrite(&min, sizeof(min), 1, fp);       /* real*8 */
+	    fwrite(&max, sizeof(max), 1, fp);       /* real*8 */
+	    fwrite(&reclen, sizeof(reclen), 1, fp); /* Fortran end record delimeter */
+	  }
+	  else {
+	    fprintf(fp, fmt2, j, cnt, avg, stdev, min, max, lat, lon);
+	  }
+	} /* for (j=last_boxid + 1; j<=nboxes; j++) */
+      }
+
+      ci = odbdump_destroy_colinfo(ci, nci);
+      errflg = odbdump_close(h);
+
+      FREEX(d);
+    
+    }  /* if (h && maxcols >= nsort) ... */
+    else {
+      errflg = -1;
+    }
+
+    FREE(sql_query);
+  }
+
+ finish:
+  return errflg;
+}
diff --git a/odb/src/tools/odbcksum.c b/odb/src/tools/odbcksum.c
new file mode 100644
index 0000000..41c5d04
--- /dev/null
+++ b/odb/src/tools/odbcksum.c
@@ -0,0 +1,75 @@
+#include "odb.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "odbcrc.h"
+#include "memmap.h"
+
+/* odbcksum file(s) */
+/* should give identical results to Unix utility cksum */
+/* provided for testing purposes of ifsaux/support/crc.c */
+/* note: this utility uses odb/aux/odbcrc.c */
+/* checks also read-errors */
+
+int
+main(int argc, char *argv[])
+{
+  char *a_out = argv[0];
+  int rc = 0;
+  int j;
+  int numargs = argc - 1;
+  
+  for (j=1; (numargs == 0) || j<=numargs; j++) {
+    char *fn = (numargs > 0) ? argv[j] : NULL;
+    int n;
+    int fd;
+    long long bytes = 0;
+    unsigned int filecrc = 0;
+    memmap_t *m = NULL;
+    
+    if (fn == NULL || (fn[0] == '-' && fn[1] == '\0')) {
+      fd = 0;
+      fn = NULL;
+    }
+    else if ((fd = open(fn, O_RDONLY)) < 0) {
+      fprintf(stderr, "%s: input file \"%s\": ",a_out,fn);
+      perror(a_out);
+      rc++;
+      goto eol;
+    }
+    
+    m = memmap_open_read(fd, NULL, NULL);
+    if (m) { /* mmap() succeeded */
+      char *mmbuf = m->buf;
+      bytes = n = m->len;
+      filecrc = ODB_cksum32(mmbuf, n, filecrc);
+      memmap_close(m);
+    }
+    else { /* No mmap() ? */
+      char buf[IO_BUFSIZE_DEFAULT];
+      while ((n = read(fd, buf, sizeof(buf))) > 0) {
+	bytes += n;
+	filecrc = ODB_cksum32(buf, n, filecrc);
+      }
+    }
+
+    if (n < 0) {
+      fprintf(stderr, "%s: input file \"%s\": read-error# %d",a_out,fn,n);
+      perror(a_out);
+      rc++;
+      close(fd);
+      goto eol;
+    }
+
+    filecrc = ODB_pp_cksum32but64len(bytes, filecrc);
+    close(fd);
+    
+    printf("%u %lld",filecrc,bytes);
+    if (fn) printf(" %s",fn);
+    printf("\n");
+    
+  eol:
+    if (!fn) break;
+  } /* for (j=1; !numargs || j<=numargs; j++) */
+  
+  return rc;
+}
diff --git a/odb/src/tools/odbdump_main.c b/odb/src/tools/odbdump_main.c
new file mode 100644
index 0000000..29a26bb
--- /dev/null
+++ b/odb/src/tools/odbdump_main.c
@@ -0,0 +1,403 @@
+
+/* odbdump_main.c */
+
+#include <ctype.h>
+
+#include "odbdump.h"
+
+#define USAGE \
+ "Usage: odbdump.x [-h] [-r] [-N] [-T] [-m <n>] [-% dbl_fmt] [-V '$var1=value1; $var2=value2']\n" \
+ "                 [-g] [-p poolmask] [-s] [-b] [-D 'delimiter'] [-P]\n" \
+ "                 {-q 'sql_query'|-v queryfile.sql}\n" \
+ "                 [-o output_file] [-d] [-i] database_path\n" \
+ " The option '-i' can be ignored, if database_path is the last argument\n" \
+ "   If database_path is not given, then the current directory is tried for the database_path\n" \
+ " For data query either one of the options -q or -v must be supplied. Last occurence of these two prevails\n" \
+ " The option '-s' prints only timing statistics i.e. fetches but does not dump the data itself\n" \
+ " The option '-b' dumps data out in a raw binary (as is/no conversions) manner\n" \
+ " The option '-p' can be supplied multiple times\n" \
+ " The option '-d' selects DUMMY-database in $ODB_SYSDBPATH/DUMMY. Good for calculator mode\n" \
+ " The option '-N' switches OFF write of NULLs; values are written instead\n" \
+ " The option '-T' switches OFF write of title (i.e. column info)\n" \
+ " The option '-r' prints 'carriage-return' at end of line instead of 'newline'\n" \
+ " The option '-m <n>' prints up to <n>-lines only (in total)\n" \
+ " The option '-%% dbl_fmt' prints doubles & Formulas in format '%%dbl_fmt'. Default : dbl_fmt = '%%.14g'\n" \
+ " The option '-g' turns on ODB internal debugging (output goes to odbdump.stderr though)\n" \
+ " The option  -D 'delimiter' provides delimited between columns. Default is space ' '\n" \
+ " The option '-P' delivers output, row-by-row, in ODB-packed form. Implies -b, too\n"
+
+#define FLAGS "bdD:ghi:m:No:p:Pq:rsTv:V:%:"
+
+extern int ec_is_little_endian();
+extern double util_walltime_();
+
+PRIVATE char *lld_dotify(ll_t n) 
+     /* See ifsaux/support/drhook.c for a little variation of this beast [lld_commie] */
+{ 
+  const char dot = '.';
+  char *sd = NULL;
+  char *pd = NULL;
+  char s[100];
+  char *p;
+  int len, ndots;
+  sprintf(s,"%lld",n);
+  len = STRLEN(s);
+  ndots = (len-1)/3;
+  if (ndots > 0) {
+    int lensd = len + ndots + 1;
+    ALLOC(sd, lensd);
+    pd = sd + len + ndots;
+    *pd-- = '\0';
+    p = s + len - 1;
+    len = 0;
+    while (p-s >= 0) {
+      *pd-- = *p--;
+      ++len;
+      if (p-s >= 0 && len%3 == 0) *pd-- = dot;
+    }
+  }
+  else {
+    sd = STRDUP(s);
+  }
+  return sd;
+}
+
+#define MEGA ((double)1048576.0)
+
+#define PRINT_TIMING(txt, nrows, ncols) \
+if (print_title && print_newline) { \
+  double wthis = util_walltime_(); \
+  double wdelta = wthis - wlast; \
+  if (txt) fprintf(fp, "# %s in %.3f secs\n", txt, wdelta);	\
+  else if (nrows > 0 && ncols > 0) { \
+    double rows_per_sec = nrows/wdelta; \
+    ll_t nbytes = packed ? Nbytes : nrows * ((ll_t) ncols) * ((ll_t) sizeof(double)); \
+    double MBytes_per_sec = (nbytes/wdelta)/MEGA; \
+    char *dotified = lld_dotify(nbytes); \
+    fprintf(fp, "# Total %lld row%s, %d col%s, %s %sbytes in %.3f secs : %.0f rows/s, %.0f MB/s\n", \
+            (long long int)nrows, (nrows != 1) ? "s" : "",		\
+            ncols, (ncols != 1) ? "s" : "", \
+            dotified, packed ? "packed-" : "", \
+            wdelta, rows_per_sec, MBytes_per_sec); \
+    FREE(dotified); \
+  } \
+  if (txt || (nrows > 0 && ncols > 0)) wlast = wthis; \
+}
+
+int main(int argc, char *argv[])
+{
+  int i_am_little = ec_is_little_endian();
+  char *database = NULL;
+  char *sql_query = NULL;
+  char *poolmask = NULL;
+  char *varvalue = NULL;
+  char *outfile = NULL;
+  char *queryfile = NULL;
+  char *delim = NULL;
+  Bool print_newline = true;
+  Bool print_mdi = true; /* by default prints "NULL", not value of the NULL */
+  Bool print_title = true;
+  Bool debug_on = false;
+  Bool raw_binary = false;
+  Bool stat_only = false;
+  Bool packed = false;
+  const char dummydb[] = "$ODB_SYSDBPATH/DUMMY";
+  int maxlines = -1;
+  char *dbl_fmt = NULL;
+  void *h = NULL;
+  int maxcols = 0;
+  ll_t Nbytes = 0;
+  int rc = 0;
+  int errflg = 0;
+  int c;
+  double wlast;
+  FILE *fp = stdout;
+  extern int optind;
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'b':
+      raw_binary = true;
+      break;
+    case 'D':
+      if (delim) FREE(delim);
+      delim = STRDUP(optarg);
+      break;
+    case 'g':
+      debug_on = true;
+      break;
+    case 'd':
+    case 'i':
+      if (database) FREE(database);
+      database = STRDUP((c == 'd') ? dummydb : optarg);
+      break;
+    case 'm':
+      maxlines = atoi(optarg);
+      break;
+    case 'N':
+      print_mdi = false;
+      break;
+    case 'o':
+      if (outfile) FREE(outfile);
+      outfile = STRDUP(optarg);
+      break;
+    case 'p':
+      if (poolmask) { /* Append more ; remember to add the comma (',') between !! */
+	int len = STRLEN(poolmask) + 1 + STRLEN(optarg) + 1;
+	char *p;
+	ALLOC(p, len);
+	snprintf(p, len, "%s,%s", poolmask, optarg);
+	FREE(poolmask);
+	poolmask = p;
+      }
+      else {
+	poolmask = STRDUP(optarg);
+      }
+      break;
+    case 'P':
+      packed = true;
+      raw_binary = true;
+      break;
+    case 'q':
+      if (queryfile) FREE(queryfile);
+      if (sql_query) FREE(sql_query);
+      sql_query = STRDUP(optarg);
+      break;
+    case 'r':
+      print_newline = false;
+      break;
+    case 's':
+      stat_only = true;
+      break;
+    case 'T':
+      print_title = false;
+      break;
+    case 'v':
+      if (sql_query) FREE(sql_query);
+      if (queryfile) FREE(queryfile);
+      queryfile = STRDUP(optarg);
+      break;
+    case 'V':
+      if (varvalue) FREE(varvalue);
+      {
+	int len = STRLEN(optarg) + 1;
+	char *p = optarg;
+	char *pv;
+	Bool last_was_comma = false;
+	ALLOC(varvalue, len);
+	pv = varvalue;
+	while (*p) {
+	  int cp = *p++;
+	  if (isspace(cp) || !isprint(cp)) {
+	    continue;
+	  }
+	  else if (cp == ';' || cp == ',') {
+	    if (!last_was_comma) {
+	      *pv++ = ',';
+	      last_was_comma = true;
+	    }
+	  }
+	  else {
+	    *pv++ = cp;
+	    last_was_comma = false;
+	  }
+	} /* while (*p) */
+	*pv = '\0';
+      }
+      break;
+    case '%':
+      if (dbl_fmt) FREE(dbl_fmt);
+      {
+	int len = STRLEN(optarg) + 2;
+	ALLOC(dbl_fmt, len);
+	snprintf(dbl_fmt, len, "%%%s", optarg);
+      }
+      break;
+    case 'h': /* help !! */
+    default:
+      ++errflg;
+      break;
+    }
+  } /* while ((c = getopt(argc, argv, FLAGS)) != -1) */
+
+  if (argc - 1 == optind) {
+    if (database) FREE(database);
+    database = STRDUP(argv[argc-1]);
+  }
+  else if (argc > optind) {
+    ++errflg;
+  }
+
+  if (!sql_query && !queryfile) ++errflg;
+
+  if (errflg > 0) {
+    fprintf(stderr,"%s",USAGE);
+    return errflg;
+  }
+
+  if (maxlines == 0) return rc;
+
+  if (!dbl_fmt) dbl_fmt = STRDUP("%.14g");
+  if (debug_on) (void) ODBc_debug_fp(stderr);
+  if (stat_only) { print_newline = true; print_title = true; raw_binary = false; }
+  if (raw_binary) print_title = false;
+  if (!delim) delim = STRDUP(" ");
+
+  if (outfile) fp = fopen(outfile, "w");
+
+  if (print_title) {
+    fprintf(fp, "# ---------------------------------------------------------------\n");
+    fprintf(fp, "# Database    : %s\n", database ? database : ".");
+    fprintf(fp, "# SQL-queries : %s\n", sql_query);
+    if (poolmask) fprintf(fp, "# Poolmask : %s\n", poolmask);
+    if (varvalue) fprintf(fp, "# Varvalue : %s\n", varvalue);
+    fprintf(fp, "# Data endianess : %s-endian\n", i_am_little ? "little" : "big");
+    fprintf(fp, "# ---------------------------------------------------------------\n");
+    fflush(fp);
+  }
+
+  wlast = util_walltime_();
+
+  h = odbdump_open(database, sql_query, queryfile, poolmask, varvalue, &maxcols);
+
+  PRINT_TIMING("Database open", 0, 0);
+  
+  if (packed && h && maxcols > 0) {
+    maxcols *= 2; /* ca. worst case scenario when packed */
+  }
+
+  if (h && maxcols > 0) {
+    int new_dataset = 0;
+    colinfo_t *ci = NULL;
+    int nci = 0;
+    double *d = NULL;
+    int nd;
+    int query_num = 0;
+    ll_t nrows = 0;
+    ll_t nrtot = 0;
+    int ncols = 0;
+    int (*nextrow)(void *, void *, int, int *) = 
+      packed ? odbdump_nextrow_packed : odbdump_nextrow;
+    int dlen = packed ? maxcols * sizeof(*d) : maxcols;
+
+    ALLOCX(d, maxcols);
+
+    while ( (nd = nextrow(h, d, dlen, &new_dataset)) > 0) {
+      int i;
+
+      if (new_dataset) {
+	/* New query ? */
+	ci = odbdump_destroy_colinfo(ci, nci);
+	ci = odbdump_create_colinfo(h, &nci);
+	if (print_title) {
+	  PRINT_TIMING(NULL, nrows, ncols);
+	  fprintf(fp, "#[%d]",++query_num);
+	  if (stat_only) fprintf(fp, " ncols=%d", nci);
+	  if (!stat_only) {
+	    char *separ = " ";
+	    for (i=0; i<nci; i++) {
+	      colinfo_t *pci = &ci[i];
+	      fprintf(fp,"%s%s:%s",
+		      separ,
+		      pci->type_name,
+		      pci->nickname ? pci->nickname : pci->name);
+	      separ = delim;
+	    }
+	  }
+	  fprintf(fp, "\n");
+	  fflush(fp);
+	}
+	new_dataset = 0;
+	nrows = 0;
+	ncols = nci;
+	Nbytes = 0;
+      }
+
+      if (packed) Nbytes += nd;
+
+      if (stat_only) goto next_please;
+
+      if (!packed) nd = MIN(nd, nci);
+
+      if (raw_binary) {
+	if (packed) {
+	  fwrite(d, sizeof(char), nd, fp);
+	}
+	else {
+	  fwrite(d, sizeof(*d), nd, fp);
+	}
+      }
+      else {
+	char *separ = " ";
+	for (i=0; i<nd; i++) {
+	  colinfo_t *pci = &ci[i];
+	  fprintf(fp,"%s",separ);
+	  if (print_mdi && pci->dtnum != DATATYPE_STRING && ABS(d[i]) == mdi) {
+	    fprintf(fp,"NULL");
+	  }
+	  else {
+	    switch (pci->dtnum) {
+	    case DATATYPE_STRING:
+	      {
+		int js;
+		char cc[sizeof(double)+1];
+		char *scc = cc;
+		union {
+		  char s[sizeof(double)];
+		  double d;
+		} u;
+		u.d = d[i];
+		for (js=0; js<sizeof(double); js++) {
+		  char c = u.s[js];
+		  *scc++ = isprint(c) ? c : ' '; /* unprintables as blanks */
+		} /* for (js=0; js<sizeof(double); js++) */
+		*scc = '\0';
+		fprintf(fp,"\"%s\"",cc);
+	      }
+	      break;
+	    case DATATYPE_YYYYMMDD:
+	      fprintf(fp, "%8.8d", (int)d[i]);
+	      break;
+	    case DATATYPE_HHMMSS:
+	      fprintf(fp, "%6.6d", (int)d[i]);
+	      break;
+	    case DATATYPE_INT4:
+	      fprintf(fp, "%d", (int)d[i]);
+	      break;
+	    default:
+	      fprintf(fp, dbl_fmt, d[i]);
+	      break;
+	    } /* switch (pci->dtnum) */
+	  }
+	  separ = delim;
+	} /* for (i=0; i<nd; i++) */
+
+	fprintf(fp, print_newline ? "\n" : "\e[0K\r"); /* The "\e[0K" hassle clears up to the EOL */
+	if (!print_newline) fflush(fp);
+      } /* if (raw_binary) ... else ... */
+
+    next_please:
+      ++nrows;
+      if (maxlines > 0 && ++nrtot >= maxlines) break; /* while (...) */
+    } /* while (...) */
+
+    PRINT_TIMING(NULL, nrows, ncols);
+    /* if (!print_newline) fprintf(fp, "\n"); */
+
+    ci = odbdump_destroy_colinfo(ci, nci);
+    rc = odbdump_close(h);
+
+    FREEX(d);
+
+    fflush(fp);
+  } /* if (h && maxcols > 0) ... */
+  else {
+    rc = -1;
+  }
+
+  if (fp) {
+    if (rc != 0) fprintf(fp, "# return code = %d : please look at the file 'odbdump.stderr'\n",rc);
+    fclose(fp);
+  }
+  return rc;
+}
diff --git a/odb/src/tools/odbfiletime.c b/odb/src/tools/odbfiletime.c
new file mode 100644
index 0000000..a7e6c0e
--- /dev/null
+++ b/odb/src/tools/odbfiletime.c
@@ -0,0 +1,53 @@
+/* odbfiletime.c */
+
+/* 
+   Usage: echo "0.0" | odbfiletime.x files_or_directories
+                       odbfiletime.x files_or_directories < /dev/null
+
+   Prints a decimal number "<ull>.<count>" to the stdout,
+   where <ull> is an unsigned long long int (64-bit) of the sum of the valid files' modications times
+         <count> is the count of valid files
+
+   In particular prints "0.0", if no valid files are found.
+
+   Author: Sami Saarinen, ECMWF, 28-Dec-2007
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+
+int
+main(int argc, char *argv[])
+{
+  unsigned long long int u = 0;
+  int cnt = 0;
+  int j;
+  { /* Initial values, if any */
+    int nelem = fscanf(stdin,"%llu.%d",&u,&cnt);
+    if (nelem != 2) { u = 0; cnt = 0; }
+  }
+  for (j=1; j<argc; ++j) {
+    char *file = argv[j];
+    struct stat buf;
+    if (stat(file,&buf) == 0) {
+      time_t mtime = buf.st_mtime;
+#if 0
+      char s[80];
+      strftime(s, sizeof(s), " %d-%b-%Y  %H:%M:%S ", localtime(&mtime));
+      fprintf(stderr, "%s --> %lld i.e. %s\n",file,(long long int)mtime,s);
+#endif
+      u += mtime;
+      ++cnt;
+    }
+    else {
+#if 0
+      fprintf(stderr,"%s --> ???\n",file);
+#endif
+    }
+  }
+  printf("%llu.%d\n",u,cnt);
+  return 0;
+}
diff --git a/odb/src/tools/odbi_client_main.c b/odb/src/tools/odbi_client_main.c
new file mode 100644
index 0000000..42458ba
--- /dev/null
+++ b/odb/src/tools/odbi_client_main.c
@@ -0,0 +1,7 @@
+
+/* odbi_client_main.c */
+
+#define ODBI_CLIENT 1
+#define ODBI_DIRECT 0
+#include "odbi_direct_main.c"
+
diff --git a/odb/src/tools/odbi_direct_main.c b/odb/src/tools/odbi_direct_main.c
new file mode 100644
index 0000000..2456c82
--- /dev/null
+++ b/odb/src/tools/odbi_direct_main.c
@@ -0,0 +1,586 @@
+/* odbi_direct_main.c */
+
+/* Note: This is a common code with odbi_client_main.c 
+         with only a few exceptions via #ifdef's */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <math.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+/* Choose between true direct-mode or client[/server]-mode */
+
+#if !defined(ODBI_DIRECT)
+#define ODBI_DIRECT 1
+#endif
+
+#include "odbi.h"
+#include "privpub.h"
+#include "odbcsdefs.h"
+#include "cdrhook.h"
+
+int ODBI_errno = 0;
+
+#define DEVNULL "/dev/null"
+
+char *ncpus_nchunk = NULL; /* global */
+
+#if ODBI_DIRECT == 1
+
+#define FLAGS "b:B:CDf:Fl:L:mn:Nq:Q:Sv:V:#:"
+
+static const int direct = 1;
+int fast_odbsql = 1; /* global */
+int odb_version = 0; /* global */
+int csopt = 0; /* global */
+
+#define USAGE \
+  "Usage: %s\n" \
+  "       [-b format]        (output data in binary format; default:text)\n" \
+  "       [-B bufsize]       (working buffer size; default: at least no. of columns)\n" \
+  "       [-D]               (return data only i.e. from ODBI_fetch_row_array())\n" \
+  "       [-l database_name] (default: ECMA)\n" \
+  "       [-L start_row,maxrows] (default: 1,-1 i.e. all via SQL)\n" \
+  "       [-m]               (obtain metadata only)\n" \
+  "       [-N]               (no NULLs, but the value of missing data [in text-mode]; default: print NULL)\n" \
+  "       [-S]               (show row numbers -- in text-mode output only)\n" \
+  "       [-v viewname]      (default:myview)\n" \
+  "       [-V var=value]     (supply changes to the default $-variables; may appear multiple times)\n" \
+  "       [-F]               (do *NOT* use Fast odbsql-approach [by default it is used])\n" \
+  "       [-n numeric_odb_version] (as produced by command odb_version -numeric)\n" \
+  "       [-q sql_data_query]\n" \
+  "       [-Q sql_data_query_file]\n" \
+  "       [-f output_file_name] (default: /dev/null i.e. do not use files)\n" \
+  "       [-C]               (odbi_direct.x invoked via c/s-infrastructure)\n" \
+  "       [-# ncpus[.nchunk]] (Parallelism (and pool-chunking), default: ncpus=1)\n" \
+  "\n"
+
+#else /* ODBI_DIRECT == 0 */
+
+#define FLAGS "b:B:Df:H:i:l:L:mNO:p:P:q:Q:T:Sv:V:#:"
+
+static const int direct = 0;
+static int fast_odbsql = 1; /* local; dummy */
+static int odb_version = 0; /* local; dummy */
+static int csopt = 0; /* local; dummy */
+
+#define USAGE \
+  "Usage: %s\n" \
+  "       [-b format]        (output data in binary format; default:text)\n" \
+  "       [-B bufsize]       (working buffer size; default: at least no. of columns)\n" \
+  "       [-D]               (return data only i.e. from ODBI_fetch_row_array())\n" \
+  "       [-l database_name] (default: ECMA)\n" \
+  "       [-L start_row,maxrows] (default: 1,-1 i.e. all via SQL)\n" \
+  "       [-m]               (obtain metadata only)\n" \
+  "       [-N]               (no NULLs, but the value of missing data [in text-mode]; default: print NULL)\n" \
+  "       [-S]               (show row numbers -- in text-mode output only)\n" \
+  "       [-v viewname]      (default:myview)\n" \
+  "       [-V var=value]     (supply changes to the default $-variables; may appear multiple times)\n" \
+  "== Specific to client/server-version only:\n" \
+  "       [-l [host:][/datapath/]database_name]\n" \
+  "       [-H {hostname|ip-address}]      (default: {localhost|127.0.0.1})\n" \
+  "       [-P server_port_number]         (default: mod(uid,10000)+10000)\n" \
+  "       [-T timeout_in_secs]            (default: 3600)\n" \
+  "       [-i [host:]/datapath]           (default: /tmp)\n" \
+  "       [-q sql_data_query]\n" \
+  "       [-Q sql_data_query_file]\n" \
+  "       [-p poolmask]\n" \
+  "       [-O options_to_be_propagated_to_ODBI_connect]\n" \
+  "       [-f output_file_name] (default: /dev/null i.e. do not use files)\n" \
+  "       [-# ncpus[.nchunk]] (Parallelism (and pool-chunking), default: ncpus=1)\n" \
+  "\n"
+
+#endif
+
+typedef struct _varvalue_t {
+  char *var;
+  double value;
+  struct _varvalue_t *next;
+} varvalue_t;
+
+static varvalue_t *varlist_start = NULL;
+static varvalue_t *varlist = NULL;
+
+
+PRIVATE char *Slurp(const char *path) /* As in odb/compiler/odb98.c */
+{
+  extern int IOgetsize(const char *path, int *filesize, int *blksize);
+  int filesize = 0;
+  int rc = IOgetsize(path, &filesize, NULL);
+  char *s = NULL;
+  if (rc == 0 && filesize > 0) {
+    FILE *fp = fopen(path,"r");
+    if (fp) {
+      s = malloc(sizeof(*s) * (filesize+20));
+      if (s) {
+	rc = fread(s, sizeof(*s), filesize, fp); /* slurp!! */
+	if (rc == filesize) { /* Success */
+	  s[filesize] = '\0'; 
+	  strcat(s," ;\n");
+	}
+	else free(s); /* Failure */
+      }
+      fclose(fp);
+    }
+  }
+  if (!s) {
+    fprintf(stderr,"***Error: Unable to inline non-existent (or empty) ODB/SQL-file '%s'\n",
+	    path ? path : NIL);
+    raise(SIGABRT);
+    _exit(1);
+  }
+  return s;
+}
+
+int
+main(int argc, char *argv[])
+{
+  int c, len, errflg = 0;
+  char *p;
+  int is_binary = 0;
+  char *output_file = strdup(DEVNULL);
+  char *output_format = strdup("text");
+  int bufsize = 0; /* will be set to at least "ncols" */
+  int data_only = 0;
+  char *dbname = NULL;
+  int print_nulls = 1;
+  char *viewname = NULL;
+  int ntot = 0;
+  int start_row = 1;
+  int maxrows = 2147483647;
+  int showrows = 0;
+  int obtain_metadata_only = 0;
+  char *server_host = NULL;
+  int server_port = 0;
+  int server_timeout = TIMEOUT_DEFAULT;
+  int server_timeout_given = 0;
+  char *server_datapath = NULL;
+  char *data_query = NULL;
+  char *options = /* compulsory parameters for C/S */
+    strdup("fp=%F;host=%s;port=%d;timeout=%d;datapath=%s;poolmask=%s;ncpus=%s"); 
+  char *poolmask = strdup("");
+  FILE *fp = stdout;
+  FILE *fp_data = fp;
+  double time_start = ODBI_timer(NULL);
+  void *db = NULL;
+  int verbose = 0;
+  DRHOOK_START(main);
+
+  while ((c = getopt(argc, argv, FLAGS)) != -1) {
+    switch (c) {
+    case 'b': /* binary mode */
+      p = optarg;
+      if (output_format) free(output_format);
+      output_format = strdup(p);
+      is_binary = (strcmp(output_format,"text") != 0) ? 1 : 0;
+      break;
+    case 'B': /* buffer size */
+      p = optarg;
+      bufsize = atoi(p);
+      break;
+    case 'C': /* invoked via c/s-infrastructure */
+      csopt = 1;
+      break;
+    case 'D': /* return data only */
+      data_only = 1;
+      break;
+    case 'f':
+      p = optarg;
+      if (output_file) free(output_file);
+      output_file = strdup(p);
+      break;
+    case 'F': /* switch off fast odbsql */
+      fast_odbsql = 0;
+      break;
+    case 'H': /* server host */
+      p = optarg;
+      if (server_host) free(server_host);
+      server_host = strdup(p);
+      break;
+    case 'i': /* server datapath */
+      p = optarg;
+      if (server_datapath) free(server_datapath);
+      server_datapath = strdup(p);
+      break;
+    case 'l': /* database name */
+      p = optarg;
+      if (dbname) free(dbname);
+      dbname = strdup(p);
+      break;
+    case 'L': /* start_row,nrows */
+      p = optarg;
+      {
+	int num = sscanf(p,"%d,%d",&start_row,&maxrows);
+	if (num != 2) {
+	  start_row = 1;
+	  maxrows = 2147483647;
+	}
+      }
+      break;
+    case 'm': /* database metadata only (implies also that no data rows are returned) */
+      obtain_metadata_only = 1;
+      break;
+    case 'n': /* odb_version -numeric */
+      p = optarg;
+      odb_version = atoi(p);
+      break;
+    case 'N': /* switch off NULLs in text-mode */
+      print_nulls = 0;
+      break;
+    case 'O': /* Other options (accumulative) */
+      p = optarg;
+      if (strcmp(p,"verbose") == 0) verbose = 1;
+      len = strlen(options) + strlen(p) + 2;
+      options = realloc(options, len);
+      strcat(options,";");
+      strcat(options,p);
+      break;
+    case 'p': /* poolmask */
+      p = optarg;
+      len = strlen(poolmask) + strlen(p) + 2;
+      poolmask = realloc(poolmask, len);
+      if (strlen(poolmask) > 0) strcat(poolmask,",");
+      strcat(poolmask,p);
+      break;
+    case 'P': /* server port */
+      p = optarg;
+      server_port = atoi(p);
+      break;
+    case 'q': /* data query */
+      p = optarg;
+      if (data_query) free(data_query);
+      data_query = strdup(p);
+      break;
+    case 'Q': /* data query file */
+      p = optarg;
+      if (data_query) free(data_query);
+      data_query = Slurp(p);
+      break;
+    case 'S': /* show row numbers */
+      showrows = 1;
+      break;
+    case 'T': /* server timeout */
+      p = optarg;
+      server_timeout = atoi(p);
+      server_timeout_given = 1;
+      break;
+    case 'v': /* viewname */
+      p = optarg;
+      if (viewname) free(viewname);
+      viewname = strdup(p);
+      if (strcmp(viewname,"@") == 0) { /* a NULL query */
+	free(viewname);
+	viewname = NULL;
+      }
+      break;
+    case 'V': /* var=value */
+      p = optarg;
+      if (!varlist_start) {
+	varlist = varlist_start = malloc(sizeof(varvalue_t));
+      }
+      else {
+	varlist->next = malloc(sizeof(varvalue_t));
+	varlist = varlist->next;
+      }
+      varlist->var = strdup(p);
+      p = strchr(varlist->var,'=');
+      if (p && p[1] != '\0') {
+	*p++ = '\0';
+	varlist->value = atof(p);
+      }
+      else {
+	varlist->value = 0;
+      }
+      varlist->next = NULL;
+      break;
+    case '#':
+      p = optarg;
+      if (ncpus_nchunk) free(ncpus_nchunk);
+      ncpus_nchunk = strdup(p);
+      break;
+    default:
+      fprintf(stderr,"***Error: Unrecognized switch '-%c'\n",c);
+      errflg++;
+      break;
+    } /* switch (c) */
+  } /* while ((c = getopt(argc, argv, FLAGS)) != -1) */
+
+  if (errflg) {
+    fprintf(stderr,USAGE,argv[0]);
+    goto finish;
+  }
+
+  if (!dbname)   dbname   = strdup(DB_DEFAULT);
+
+  if (strcmp(output_file,DEVNULL) != 0) {
+    data_only = 1;
+    if (strcmp(output_format,"netcdf") == 0 || strcmp(output_format,"unetcdf") == 0) {
+      /* Try to allocate at least 2 cpus/cores for NetCDF-file creation, pool-chunking of 16 */
+      if (!ncpus_nchunk) ncpus_nchunk = strdup("2.16");
+    }
+  }
+  if (!ncpus_nchunk) ncpus_nchunk = strdup("1");
+
+  if (data_only) {
+    fp_data = stdout;
+    fp = fopen(DEVNULL,"w");
+  }
+
+  if (!direct) {
+    if (!server_datapath) {
+      server_datapath = strdup(DATAPATH_DEFAULT);
+    }
+    if (!server_host) {
+      /* check dbname first */
+      p = strchr(dbname,':');
+      if (!p) {
+	/* then check server_datapath */
+	p = strchr(server_datapath,':');
+	if (p) server_host = strdup(server_datapath);
+      }
+      else {
+	server_host = strdup(dbname);
+      }
+      if (server_host) {
+	p = strchr(server_host, ':');
+	if (p) *p = '\0';
+      }
+      else {
+	server_host = strdup(HOST_DEFAULT);
+      }
+    }
+    if (server_datapath) {
+      p = strchr(server_datapath,':');
+      if (p) {
+	char *tmp = strdup(p+1);
+	free(server_datapath);
+	server_datapath = strdup(tmp);
+	free(tmp);
+      }
+    }
+    if (server_port <= MIN_PORT) {
+      server_port = PORT_DEFAULT;
+    }
+
+#if 0
+    if (strlen(poolmask) > 0) {
+      char *p = poolmask;
+      len = strlen(options) + strlen("poolmask=") + strlen(p) + 2;
+      options = realloc(options, len);
+      strcat(options,";poolmask=");
+      strcat(options,p);
+    }
+#endif
+  } /* if (!direct) */
+
+
+  if (is_binary) showrows = 0;
+  if (obtain_metadata_only) maxrows = 0;
+  if (!server_timeout_given) {
+    char *env = getenv("ODBCS_TIMEOUT");
+    if (!env) server_timeout = env ? atoi(env) : TIMEOUT_DEFAULT;
+    if (server_timeout <= 0) server_timeout = TIMEOUT_DEFAULT;
+    server_timeout_given = 1;
+  }
+
+  {
+    static char newenv[40]; /* static because of "putenv()" */
+    snprintf(newenv,sizeof(newenv),"ODBCS_TIMEOUT=%d",server_timeout);
+    putenv(newenv);
+  }
+
+  if (direct) {
+    /* fprintf(stderr,"odbi_direct_main: fp=%p, fileno=%d\n",fp,fileno(fp)); */
+    db = ODBI_connect(dbname,"fp=%F",fp);
+  }
+  else {
+    if (verbose) {
+      fprintf(stderr,
+	      "ODBI_connect(%s,"
+	      "\n\toptions=%s,"
+	      "\n\tfp=0x...,host=%s,port=%d,timeout=%d,"
+	      "\n\tdatapath=%s,poolmask=%s,ncpus=%s)\n",
+	      dbname,
+	      options
+	      , server_host
+	      , server_port
+	      , server_timeout
+	      , server_datapath
+	      , poolmask ? poolmask : ""
+	      , ncpus_nchunk
+	      );
+    }
+    db = ODBI_connect(dbname,
+		      options
+		      , fp
+		      , server_host
+		      , server_port
+		      , server_timeout
+		      , server_datapath
+		      , poolmask
+		      , ncpus_nchunk
+		      );
+  }
+
+  if (db) {
+    ODBI_print_db_metadata(fp,db,obtain_metadata_only);
+    if (direct) {
+      /* Additional metadata */
+      fprintf(fp,"output_format=%s\n",output_format);
+      fprintf(fp,"obtain_metadata=%d\n",obtain_metadata_only);
+      fprintf(fp,"show_row_numbers=%d\n",showrows);
+      fprintf(fp,"print_nulls=%d\n",print_nulls);
+      if (strlen(poolmask) > 0) fprintf(fp,"permanent_poolmask=%s\n",poolmask);
+    }
+  }
+  else {
+    errflg = -2;
+    fprintf(fp,"error_code=%d\n",errflg);
+    fprintf(fp,"reason=cannot_open_database:%s\n",dbname);
+    goto finish;
+  } /* if (db) ... else ... */
+
+  if (db && viewname) {
+    void *q = ODBI_prepare(db,viewname,data_query);
+    if (q) {
+      int rc_exec;
+
+      if (varlist_start) {  /* SET $var = value */
+	varvalue_t *vl = varlist_start;
+	while (vl) {
+	  varvalue_t *this = vl;
+	  (void) ODBI_bind_param(q, this->var, this->value);
+	  free(this->var);
+	  vl = this->next;
+	  free(this);
+	} 
+	varlist_start = varlist = NULL; /* since already free'd them above */
+      } /* varlist_start */
+
+      ODBI_print_query_metadata(fp,q);
+
+      if (obtain_metadata_only) {
+	double time_delta = ODBI_timer(&time_start);
+	fprintf(fp,"elapsed_time=%.6f\n", time_delta);
+	fprintf(fp,"error_code=0\n");
+	goto finish;
+      }
+
+      ODBI_limits(q, &start_row, &maxrows, &bufsize);
+
+      if (strcmp(output_file,DEVNULL) != 0) {
+	fprintf(fp,"output_file=%s\n",output_file);
+	fprintf(fp,"output_format=%s\n",output_format);
+	rc_exec = ODBI_fetchfile(q, output_file, output_format);
+      }
+      else {
+	if ((rc_exec = ODBI_execute(q)) >= 0) {
+	  int total_rows = 0;
+	  double *data = NULL;
+	  int rc;
+	  int jcnt = start_row;
+	  int jrow, jcol;
+	  int nrows, ncols = ODBI_ncols(q);
+	
+	  data = malloc(bufsize * sizeof(*data));
+	  if (!data) {
+	    fprintf(fp,"buffer_size=%d\n",-bufsize);
+	    fprintf(stderr,
+		    "***Error: Unable to allocate bufsize of %d x %d = %lld bytes\n",
+		    bufsize, (int)sizeof(*data),
+		    (long long int)bufsize * sizeof(*data));
+	    errflg = -3;
+	    goto finish;
+	  }
+	  nrows=-1;
+	  rc = ODBI_fetchonerow_array(q, &nrows, &ncols,&data[is_binary], bufsize);
+	  while ( rc > 0) {
+	    total_rows += nrows;
+	    if (is_binary) {
+	      data[0] = rc; /* Note: the actual data length information at the beginning */
+	      fwrite(data, sizeof(*data), 1+rc, fp_data);
+	    }
+	    else {
+	      double *d = &data[is_binary];
+	      fprintf(fp,"number_of_rows=%d\n",nrows);
+	      for (jrow=0; jrow<nrows; jrow++) {
+		char *delim = " ";
+		if (showrows) {
+		  fprintf(fp_data,"#%d",jcnt++);
+		  delim=",";
+		}
+		for (jcol=0; jcol<ncols; jcol++) {
+		  ODBI_printcol(fp_data,q,jcol+1,*d,delim,print_nulls);
+		  d++;
+		  delim = ",";
+		} /* for (jcol=0; jcol<ncols; jcol++) */
+		fprintf(fp_data,"\n");
+	      } /* for (jrow=0; jrow<nrows; jrow++) */
+	    } /* if (is_binary) ... else ... */
+	    fflush(fp_data);
+	    nrows=-1;
+	    rc = ODBI_fetchonerow_array(q, &nrows, &ncols,&data[is_binary], bufsize);
+	  } /*  while ((rc = ODBI_fetchonerow_array(...))) */
+
+	  ntot = total_rows;
+	  if (is_binary) {
+	    data[0] = rc;
+	    fwrite(data, sizeof(*data), 1, fp_data);
+	    data[0] = total_rows;
+	    fwrite(data, sizeof(*data), 1, fp);
+	  }
+	  free(data);
+
+	  if (rc < 0) {
+	    fprintf(stderr,
+		    "***Error: Unable to fetchonerow_array: rc=%d, bufsize=%d, nrows=%d, ncols=%d, total_rows=%d\n",
+		    rc, bufsize, nrows, ncols, total_rows);
+	    errflg = -4;
+	    goto finish;
+	  }
+	  if (!is_binary) fprintf(fp,"total_number_of_rows=%d\n", total_rows);
+	  (void) ODBI_finish(q);
+	} /* if ((rc_exec = ODBI_execute(q)) >= 0) */
+      } /* if (strcmp(output_file,DEVNULL) != 0) */
+
+      if (rc_exec < 0) {
+	errflg = -3;
+	fprintf(fp,"error_code=%d\n",errflg);
+	fprintf(fp,"reason=failing_to_execute_query:%s\n",viewname);
+      }
+    } /* if (q) ... */
+    else {
+      errflg = -1;
+      fprintf(fp,"error_code=%d\n",errflg);
+      fprintf(fp,"reason=cannot_process_query:%s\n",viewname);
+    }  /* if (q) ... else ... */
+    
+    if (errflg == 0) {
+      double time_delta = ODBI_timer(&time_start);
+      if (is_binary) {
+	fwrite(&time_delta, sizeof(time_delta), 1, fp);
+      }
+      else {
+	fprintf(fp,"elapsed_time=%.6f\n", time_delta);
+	fprintf(fp,"error_code=0\n");
+      }
+    } /* if (errflg == 0) */
+  } /* if (db && viewname) */
+  else {
+    double time_delta = ODBI_timer(&time_start);
+    fprintf(fp,"elapsed_time=%.6f\n", time_delta);
+    fprintf(fp,"error_code=0\n"); /* a NULL query */
+  }
+
+ finish:
+  (void) ODBI_disconnect(db);
+
+  fflush(fp);
+  if (fp_data != fp) fflush(fp_data);
+  DRHOOK_END(ntot);
+  return errflg;
+}
diff --git a/odb/src/tools/odbi_host.c b/odb/src/tools/odbi_host.c
new file mode 100644
index 0000000..2e729ee
--- /dev/null
+++ b/odb/src/tools/odbi_host.c
@@ -0,0 +1,48 @@
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+/* 
+   Returns IP-address (ipv4) for the given host_name.
+   If not found, then exit code (rc) is non-zero.
+
+   Usage: odbi_host.x host_name 
+
+   Author: Sami Saarinen, ECMWF, 20-Dec-2007
+*/
+
+int
+main(int argc, char *argv[])
+{
+  int rc = 2; /* by default all NOT ok */
+  if (--argc >= 1) {
+    char *hostout = NULL;
+    struct hostent *h = gethostbyname(argv[1]);
+    if (h && h->h_addrtype == AF_INET) {
+      char **pptr;
+      char str[ODBCS_INET_ADDRSTRLEN];
+      const char *p = NULL;
+      pptr = h->h_addr_list;
+      for ( ; *pptr != NULL ; pptr++) {
+	p = Inet_ntop(h->h_addrtype, *pptr, str, sizeof(str));
+      }
+      if (p) { printf("%s\n",p); rc = 0; } /* All ok */
+    }
+  }
+  else
+    rc = 1; /* arg#1 is missing */
+  return rc;
+}
+
+#else
+
+#include <stdio.h>
+
+int
+main()
+{
+  fprintf(stderr,"***Error: ODB client/server not implemented on this platform\n");
+  return 3;
+}
+
+#endif
diff --git a/odb/src/tools/odbi_server_main.c b/odb/src/tools/odbi_server_main.c
new file mode 100644
index 0000000..b25087f
--- /dev/null
+++ b/odb/src/tools/odbi_server_main.c
@@ -0,0 +1,235 @@
+
+/* odbi_server_main.c */
+
+/* Usage: odbi_server.x -p port_number (default=mod(uid,10000)+10000 and must be between MIN_PORT=10000 & MAX_PORT=20000)
+                        -n listening_queue_length (the default backlog is 64)
+			-i       (ignore SIGCHLD)
+			-t timeout_in_seconds (for idling/waiting input from the client; def=TIMEOUT_DEFAULT secs)
+			-v       (verbose)
+			-b alternate $ODB_BINPATH
+			-h hostname  (to fork off a remote server)
+			-T server_self_timeout_in_seconds (terminate server after this many secs elapsed; def=2 x client t/o)
+*/
+
+#include "odbcs.h"
+
+#ifdef ODBCS
+
+#include "odbcsdefs.h"
+
+#define SERVER_FLAGS "b:h:in:p:t:T:v"
+
+extern const char *odb_resource_stamp_(const char *label); /* from ../lib.codb.c */
+
+#define PUTENV(binpath) \
+   { \
+     char *env = NULL; \
+     int len = STRLEN("ODB_BINPATH=") + STRLEN(binpath) + 1; \
+     ALLOCX(env, len); \
+     snprintf(env, len, "ODB_BINPATH=%s", binpath); \
+     putenv(env); \
+     FREEX(env); \
+   }
+
+int 
+main(int argc, char *argv[])
+{
+  char                *cmd = argv[0];
+  /* int                  serv_port = 11998; */
+  int                  serv_port = PORT_DEFAULT;
+  int                  ignore_sig_chld = 0;
+  int                  listenq = LISTEN_QUEUE_LENGTH_DEFAULT;
+  int                  listenfd, connfd;
+  int                  timeout = TIMEOUT_DEFAULT;
+  int                  timeout_given = 0;
+  int                  self_timeout = SERVER_SELF_TIMEOUT(TIMEOUT_DEFAULT);
+  int                  self_timeout_given = 0;
+  int                  verbose = 0;
+  char                *binpath = NULL;
+  char                *hostname = NULL;
+  pid_t                childpid, pid = getpid();
+  socklen_t            clilen;
+  struct sockaddr_in   cliaddr, servaddr;
+  char hashspid[80];
+  int c, errflg = 0;
+
+  snprintf(hashspid,sizeof(hashspid),"#s[%d]",pid);
+  
+  while ((c = getopt(argc, argv, SERVER_FLAGS)) != -1) {
+    switch (c) {
+    case 'b': /* alternate $ODB_BINPATH */
+      binpath = STRDUP(optarg);
+      PUTENV(binpath);
+      break;
+    case 'h': /* remote hostname */
+      hostname = STRDUP(optarg);
+      break;
+    case 'i': /* ignore SIGCHLD */
+      ignore_sig_chld = 0;
+      break;
+    case 'n': /* listening queue length (i.e. backlog) */
+      listenq = atoi(optarg);
+      break;
+    case 'p': /* port number (validity check delayed) */
+      serv_port = atoi(optarg);
+      break;
+    case 't': /* timeout */
+      timeout = atoi(optarg);
+      timeout_given = 1;
+      break;
+    case 'T': /* server self-timeout */
+      self_timeout = atoi(optarg);
+      self_timeout_given = 1;
+      break;
+    case 'v': /* turn verbose on */
+      verbose = 1;
+      break;
+    default:
+      errflg++;
+      break;
+    }
+  }
+
+  if (serv_port < MIN_PORT || serv_port > MAX_PORT) {
+    fprintf(stderr,"%s: ***Error: Port number (%d) must be between %d and %d, inclusive\n",
+	    hashspid, serv_port, MIN_PORT, MAX_PORT);
+    errflg++;
+  }
+
+  if (errflg) {
+    fprintf(stderr,"%s: ***Error: Unable to start ODBI-server '%s'\n",hashspid,cmd);
+    fprintf(stderr,
+	    "%s: Usage: %s [-i] [-n backlog] [-p port] [-t timeout] [-v]"
+	    " [-b binpath] [-h hostname] [-T server_timeout]\n",hashspid,cmd);
+    return errflg;
+  }
+
+  if (!timeout_given) {
+    char *env = getenv("ODBCS_TIMEOUT");
+    if (!env) timeout = env ? atoi(env) : TIMEOUT_DEFAULT;
+    if (timeout <= 0) timeout = TIMEOUT_DEFAULT;
+    timeout_given = 1;
+  }
+
+  {
+    static char newenv[40]; /* static because of "putenv()" */
+    snprintf(newenv,sizeof(newenv),"ODBCS_TIMEOUT=%d",timeout);
+    putenv(newenv);
+  }
+
+  if (!self_timeout_given) self_timeout = SERVER_SELF_TIMEOUT(timeout);
+
+  if (!binpath) {
+    char *env = getenv("ODB_BINPATH");
+    if (env) {
+      fprintf(stdout,"%s: $ODB_BINPATH is '%s'\n",odb_resource_stamp_(hashspid),env);
+      binpath = STRDUP(env);
+    }
+    else {
+      char *cmd_copy = STRDUP(cmd);
+      char *last_slash = strrchr(cmd_copy,'/');
+      if (!last_slash) binpath = STRDUP(".");
+      else { *last_slash = '\0'; binpath = STRDUP(cmd_copy); }
+      FREE(cmd_copy);
+      fprintf(stdout,"%s: Unable to resolve $ODB_BINPATH ; using '%s'",odb_resource_stamp_(hashspid),binpath);
+      PUTENV(binpath);
+    }
+  }
+
+  fprintf(stdout, "%s: %s %s-n %d -p %d -t %d%s -b %s%s%s -T %d\n",
+	  odb_resource_stamp_(hashspid),
+	  cmd, 
+	  ignore_sig_chld ? "-i " : "", 
+	  listenq, 
+	  serv_port, 
+	  timeout,
+	  verbose ? " -v" : "",
+	  binpath,
+	  hostname ? " -h" : "",
+	  hostname ? hostname : "",
+	  self_timeout);
+
+  fflush(stdout);
+
+  if (hostname) {
+    /* Client will try to use odbi_proxy to (see aux/odbcs_wrappers.c for StartServer() 
+       to start server on a remote host ;
+       Please note that database "label" has been put to /dev/null to denote non-existent database */
+    const char fmt[] = "%s/odbi_client.x -l /dev/null -H %s -P %d -T %d%s";
+    char *cmd = NULL;
+    int len = STRLEN(binpath) + STRLEN(hostname) + 100;
+    ALLOCX(cmd, len);
+    snprintf(cmd, len, fmt, binpath, hostname, serv_port, timeout, verbose ? " -Overbose" : "");
+    if (verbose) fprintf(stdout, "%s: %s\n",odb_resource_stamp_(hashspid), cmd);
+    fflush(stdout);
+    system(cmd);
+    FREEX(cmd);
+    goto finish;
+  }
+
+  listenfd = Socket(AF_INET, SOCK_STREAM, 0);
+
+  bzero(&servaddr, sizeof(servaddr));
+  servaddr.sin_family      = AF_INET;
+  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+  servaddr.sin_port        = htons(serv_port);
+
+  Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
+
+  Listen(listenfd, listenq);
+
+  setup_sig(hashspid, &timeout, &verbose, &self_timeout); /* For use by signal handlers */
+
+  Signal(SIGTERM, sig_term);      /* Catch SIGTERM and perform a graceful exit */
+  Signal(SIGINT , sig_int);       /* Catch SIGINT and perform a graceful exit */
+
+  if (ignore_sig_chld) {
+    Signal(SIGCHLD, SIG_IGN);      /* ignore SIGCHLD => zombies on some systems */
+  }
+  else {
+    Signal(SIGCHLD, sig_chld);     /* must call waitpid() */
+  }
+
+  for ( ; ; ) {
+    /* The master server gets killed after this many seconds */
+    alarm(self_timeout);
+    Signal(SIGALRM, sig_alrm_server); 
+
+    clilen = sizeof(cliaddr);
+    if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
+      if (errno == EINTR)
+        continue;               /* back to for ( ; ; ) */
+      else
+        err_sys("accept error");
+    }
+
+    if ( (childpid = Fork()) == 0) {  /* child process */
+      alarm(0);              /* reset alarm */
+      Signal(SIGALRM, sig_ignore);
+      Close(listenfd);       /* close listening socket */
+      return odbi_server(connfd, timeout, verbose);   /* invoke the real server */
+    }
+
+    if (verbose) fprintf(stderr,"%s: child process id %d has started\n",
+			 odb_resource_stamp_(hashspid),childpid);
+
+    Close(connfd);           /* parent closes connected socket */
+  } /* for ( ; ; ) */
+
+ finish:
+  return 0;
+}
+
+#else
+
+#include <stdio.h>
+
+int 
+main(int argc, char *argv[])
+{
+  fprintf(stderr,
+	  "***Error: odbi_server has not been compiled for this machine. Check your #define ODBCS in source code.\n");
+  return 1;
+}
+
+#endif
diff --git a/odb/src/tools/odbmd5sum.c b/odb/src/tools/odbmd5sum.c
new file mode 100644
index 0000000..4ed7582
--- /dev/null
+++ b/odb/src/tools/odbmd5sum.c
@@ -0,0 +1,45 @@
+/*
+
+  Calculate or Check MD5 Signature of File or Command Line Argument
+
+			    by John Walker
+		       http://www.fourmilab.ch/
+
+		This program is in the public domain.
+
+		Adapted for ODB-environment by Sami Saarinen, ECMWF
+
+*/
+
+#include "odbmd5.h"
+
+/*  Main program  */
+
+int main(int argc, char *argv[])
+{
+  char *env = getenv("ODB_MD5SUM_DEBUG");
+  if (env) {
+    int what = atoi(env);
+    if (what == 1) {
+      unsigned char sign[16];
+      int rc = MD5_signature(argc, argv, sign);
+      if (rc == 0) {
+	char *s = MD5_sign2hex(sign, 0);
+	printf("%s\n",s);
+	FREE(s);
+      }
+      return rc;
+    }
+    else if (what == 2 && argc == 2) {
+      unsigned char sign[16];
+      int rc = MD5_str2sign(argv[1], sign);
+      if (rc == 0) {
+	char *s = MD5_sign2hex(sign, 0);
+	printf("%s\n",s);
+	FREE(s);
+      }
+      return rc;
+    }
+  }
+  return MD5_signature(argc, argv, NULL);
+}
diff --git a/odb/src/tools/odbversion.c b/odb/src/tools/odbversion.c
new file mode 100644
index 0000000..6818272
--- /dev/null
+++ b/odb/src/tools/odbversion.c
@@ -0,0 +1,39 @@
+
+/*
+  odbversion         --> returns "CY30R2.076" --> should become the $ODB_VERSION_ID
+  odbversion -minor  --> "2.076"
+  odbversion -major  --> "30"
+  otherwise prints error message to stderr and exit-code == 1
+*/
+
+#include "odb.h"
+#include "magicwords.h"
+
+int main(int argc, char *argv[])
+{
+  int rc = 0;
+  char *a_out = argv[0];
+  double major, minor;
+  int numeric;
+  const char *str = codb_versions_(&major, &minor, &numeric, NULL);
+  --argc;
+  if (argc == 0) printf("%s\n",str);
+  else if (argc == 1 && strequ(argv[1],"-major")) {
+    printf("%.0f\n",major);
+  }
+  else if (argc == 1 && strequ(argv[1],"-minor")) {
+    printf("%.3f\n",minor);
+  }
+  else if (argc == 1 && strequ(argv[1],"-numeric")) {
+    printf("%d\n",numeric);
+  }
+  else {
+    fprintf(stderr,"Usage: %s\n",a_out);
+    fprintf(stderr,"       %s -major\n",a_out);
+    fprintf(stderr,"       %s -minor\n",a_out);
+    fprintf(stderr,"       %s -numeric\n",a_out);
+    rc++;
+  }
+  return(rc);
+}
+
diff --git a/odb/src/tools/pcma_main.c b/odb/src/tools/pcma_main.c
new file mode 100644
index 0000000..35c2a87
--- /dev/null
+++ b/odb/src/tools/pcma_main.c
@@ -0,0 +1,375 @@
+#include "pcma.h"
+
+static char vers[]     = "4.8";
+static char date_str[] = __DATE__;
+static char time_str[] = __TIME__;
+
+#if defined(CRAY) && !defined(T3D) && !defined(T3E)
+#define SYSTEM_NAME "(CRAY PVP)"
+#endif
+
+#ifdef T3D
+#define SYSTEM_NAME "(CRAY T3D)"
+#endif
+
+#ifdef T3E
+#define SYSTEM_NAME "(CRAY T3E)"
+#endif
+
+#ifdef SGI
+#define SYSTEM_NAME "(Silicon Graphics)"
+#endif
+
+#ifdef RS6K
+#define SYSTEM_NAME "(IBM RS/6000)"
+#endif
+
+#ifdef VPP
+#define SYSTEM_NAME "(Fujitsu VPP)"
+#endif
+
+#ifdef NECSX
+#define SYSTEM_NAME "(NEC SX)"
+#endif
+
+#ifdef LINUX
+#define SYSTEM_NAME "(Linux)"
+#endif
+
+#ifdef HPPA
+#define SYSTEM_NAME "(HP Unix)"
+#endif
+
+#ifndef SYSTEM_NAME
+#define SYSTEM_NAME "(Unknown system)"
+#endif
+
+static char system_name[] = SYSTEM_NAME;
+
+#define USAGE_PCMA  \
+  "Usage: pcma [-Version] [-verbose] [-help] [-m packing_method]\n" \
+  "            [-Incore] [-r readbufsize] [-w writebufsize]\n" \
+  "            [-p prealloc] [-e extent]\n" \
+  "            [-B blocksize] [-i input] [-o output]"
+
+#define USAGE_UPCMA \
+  "Usage: upcma [-Version] [-verbose] [-help]\n" \
+  "             [-Incore] [-r readbufsize] [-w writebufsize]\n" \
+  "             [-p prealloc] [-e extent] [-s can_swp_data]\n" \
+  "             [-B blocksize] [-i input] [-o output]"
+
+#define FLAGS_PCMA  "B:e:hI:i:m:o:p:r:vVw:"
+#define FLAGS_UPCMA "B:e:hI:i:o:p:r:s:vVw:"
+
+
+static int readbufsize   = 0;
+static int writebufsize  = 0;
+static int pre_alloc  = 0;
+static int extent    = 0;
+static int packingmethod = 2;
+static int blocksize     = MINBLOCK;
+static int verbose       = 0;
+static int can_swp_data  = 1;
+
+static char *program = NULL;
+
+static FILE *fp_in  = NULL;
+static char *input  = NULL;
+static char *inbuf  = NULL;
+
+static FILE *fp_out = NULL;
+static char *output = NULL;
+static char *outbuf = NULL;
+
+static int
+pack()
+{
+  int rc = 0;
+  int bytes_in  = 0;
+  int bytes_out = 0;
+
+  rc = pcma(fp_in,  /* CMA-input channel */
+	    fp_out, /* Packed output channel */
+	    packingmethod, /* Packing method */
+	    NULL, 0, /* No in-core CMA available */
+	    NULL,    /* No output packed buffers */
+	    &bytes_in, &bytes_out); /* Bytes in/out count */
+
+  if (rc == 0) {
+    if (verbose && bytes_in > 0) {
+      double ratio = (1 - ((double) bytes_out/bytes_in)) * 100.0;
+      
+      fprintf(stderr,"%s: bytes in=%d, bytes out=%d : space saving=%.2f%%\n",
+	      program, bytes_in, bytes_out, ratio);
+    }
+  }
+  else {
+    fprintf(stderr,"%s: Error(s) in packing : rc=%d\n",
+	    program, rc);
+    if (errno != 0) perror(program);
+  }
+
+  return rc;
+}
+
+
+
+static int
+unpack()
+{
+  int rc = 0;
+  int bytes_in  = 0;
+  int bytes_out = 0;
+
+  rc = upcma(can_swp_data,
+	     fp_in,  /* CMA-input channel */
+	     fp_out, /* Packed output channel */
+	     NULL, 0, 1, /* No index, idxlen=0, fill_zeroth_cma=1 */
+	     NULL, 0, /* No in-core CMA available */
+	     NULL,
+	     NULL,
+	     &bytes_in, &bytes_out); /* Bytes in/out count */
+
+  if (rc == 0) {
+    if (verbose && bytes_out > 0) {
+      double ratio = (1 - ((double) bytes_in/bytes_out)) * 100.0;
+      
+      fprintf(stderr,"%s: bytes in=%d, bytes out=%d : space saving was=%.2f%%\n",
+	      program, bytes_in, bytes_out, ratio);
+    }
+  }
+  else {
+    fprintf(stderr,"%s: rc=%d\n",program, rc);
+  }
+
+  return rc;
+}
+
+
+static char *
+KiloMegaGiga(char *s)
+{
+  const double maxint = 2147483647.0;
+  char *p = s;
+  int   len = strlen(s);
+  char *last = &s[len-1];
+  double num;
+
+  if (*last == 'k' || *last == 'K') {
+    *last = '\0';
+    num = atoi(s) * 1024.0; /* multiplier: 1kB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%0.f",num);
+  }
+  else if (*last == 'm' || *last == 'M') {
+    *last = '\0';
+    num = atoi(s) * 1048576.0; /* multiplier: 1MB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+  else if (*last == 'g' || *last == 'G') {
+    *last = '\0';
+    num = atoi(s) * 1073741824.0; /* multiplier: 1GB */
+    num = MIN(num, maxint);
+    num = MAX(0, num);
+    ALLOC(p, 20);
+    sprintf(p,"%.0f",num);
+  }
+
+  return p;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+  int c;
+  int errflg = 0;
+  extern char *optarg;
+  extern int optind;
+  int incore        = 0;
+  int print_version = 0;
+  int packing = 1; /* Unpacking = 0 */
+  int (*func)(void) = NULL;
+
+  program = strrchr(argv[0],'/');
+  program = program ? (program+1) : argv[0];
+  packing = strequ(program,"pcma");
+  func    = packing ? pack : unpack;
+
+  while ((c = getopt(argc, argv, packing ? FLAGS_PCMA : FLAGS_UPCMA)) != -1) {
+    switch (c) {
+    case 'B':
+      blocksize = atoi(KiloMegaGiga(optarg));
+      blocksize = MAX(MINBLOCK,blocksize);
+      blocksize = MIN(blocksize, MAXBLOCK);
+      break;
+    case 'e':
+      extent = atoi(KiloMegaGiga(optarg));
+      extent = MAX(0,extent);
+      break;
+    case 'h':
+      errflg++;
+      break;
+    case 'I':
+      incore = 1;
+      break;
+    case 'i':
+      FREE(input);
+      input = strdup(optarg);
+      break;
+    case 'm':
+      packingmethod = atoi(optarg);
+      break;
+    case 'o':
+      FREE(output);
+      output = strdup(optarg);
+      break;
+    case 'p':
+      pre_alloc = atoi(KiloMegaGiga(optarg));
+      pre_alloc = MAX(0,pre_alloc);
+      break;
+    case 'r':
+      readbufsize = atoi(KiloMegaGiga(optarg));
+      readbufsize = MAX(-1,readbufsize);
+      break;
+    case 's':
+      can_swp_data = atoi(optarg);
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    case 'V':
+      print_version = 1;
+      break;
+    case 'w':
+      writebufsize = atoi(KiloMegaGiga(optarg));
+      writebufsize = MAX(0,writebufsize);
+      break;
+    default:
+    case '?':
+      errflg++;
+      break;
+    }
+  }
+
+  if (print_version) {
+    fprintf(stderr,"%s: Version %s, on %s %s   %s\n", 
+	    program, vers, time_str, date_str, system_name);
+    fprintf(stderr,"Copyright (c) 1997,2000-2001 ECMWF. All Rights Reserved. \n");
+  }
+
+  if (argc > optind) errflg++;
+
+  if (!errflg) {
+    if (readbufsize == -1) incore = 1;
+    if (incore)            readbufsize = -1;
+
+    fp_in = input ? fopen(input,"r") : stdin;
+    if (!fp_in) {
+      perror(input);
+      fprintf(stderr,
+	      "%s: Unable to open input file %s\n",
+	      program,
+	      input ? input : "\0");
+      errflg++;
+    }
+
+    if (fp_in && fp_in != stdin && readbufsize == -1) {
+      readbufsize = pcma_filesize(input);
+    }
+
+    if (fp_in && readbufsize > 0) {
+      ALLOC(inbuf, readbufsize + 8);
+      if (inbuf) {
+	setvbuf(fp_in, inbuf, _IOFBF, readbufsize);
+      }
+      else {      
+	perror(input);
+	fprintf(stderr,
+		"%s: Unable to allocate space (%d bytes) for read I/O-buffer\n",
+		program,
+		readbufsize);
+	errflg++;
+      }
+    }
+  }
+
+  if (!errflg) {
+#ifdef VPP
+    if (output && pre_alloc > 0) {
+      fp_out = pcma_prealloc(output,
+			     pre_alloc, 
+			     extent,
+			     NULL,
+			     NULL);
+    }
+    else {
+      fp_out = output ? fopen(output,"w") : stdout;
+    }
+#else
+    fp_out = output ? fopen(output,"w") : stdout;
+#endif
+    if (!fp_out) {
+      perror(output);
+      fprintf(stderr,
+	      "%s: Unable to open output file %s\n",
+	      program,
+	      output ? output : "\0");
+      errflg++;
+    }
+
+    if (fp_out && writebufsize > 0) {
+      ALLOC(outbuf, writebufsize);
+      if (outbuf) {
+	setvbuf(fp_out, outbuf, _IOFBF, writebufsize);
+      }
+      else {
+	perror(output);
+	fprintf(stderr,
+		"%s: Unable to allocate space (%d bytes) for write I/O-buffer\n",
+		program,
+		writebufsize);
+	errflg++;
+      }
+    }
+  }
+
+  if (errflg) {
+    fprintf(stderr,"%s\n",packing ? USAGE_PCMA : USAGE_UPCMA);
+    return(errflg);
+  }
+
+  if (verbose) {
+    fprintf(stderr,"%s: Following options are now active:\n",program);
+    if (packing) {
+      fprintf(stderr,"\tpacking method=%d\n",packingmethod);
+    }
+    else {
+      fprintf(stderr,"\tpacking method=<detected on-the-fly>\n");
+    }
+    fprintf(stderr,"\tblocksize=%d\n",blocksize);
+    fprintf(stderr,"\tinputfile=%s\n",input ? input : "<standard input>");
+    fprintf(stderr,"\toutputfile=%s\n",output ? output : "<standard output>");
+    fprintf(stderr,"\treadbufsize=%d\n",readbufsize);
+    fprintf(stderr,"\twritebufsize=%d\n",writebufsize);
+    fprintf(stderr,"\tprealloc=%d\n",pre_alloc);
+    fprintf(stderr,"\textent=%d\n",extent);
+  }
+
+  pcma_blocksize = blocksize;
+  pcma_verbose   = verbose;
+
+  errflg = func();
+
+  if (!errflg) {
+    FCLOSE(fp_in);
+    FCLOSE(fp_out);
+  }
+
+  return(errflg);
+}
diff --git a/odb/src/tools/qtar.c b/odb/src/tools/qtar.c
new file mode 100644
index 0000000..6bdc94b
--- /dev/null
+++ b/odb/src/tools/qtar.c
@@ -0,0 +1,70 @@
+
+/* qtar (pronounced like Guitar) */
+
+/* An archive & direct access utility similar to "ar" to access file(s) within a qtar-file */
+
+/* Author: Sami Saarinen, ECMWF, 25-Nov-2002 */
+
+#include "qtar.h"
+
+
+/* 
+   For example: (partially obsolete --> these need to be refreshed)
+
+   1) Create a new qtar-file, but do not place in any members in the file:
+
+   qtar -c file.qtar
+
+   2) Create a new qtar-file and place two member files in the file:
+
+   qtar -c file.qtar subdir/file_a ./file_b
+
+   or
+
+   qtar -c -m subdir/file_a -m ./file_b file.qtar
+   
+
+   3) Un-qtar all members with verbose
+
+   qtar -xv -f file.qtar
+
+   4) Print table of contents
+
+   qtar -tv file.qtar
+
+   5) Update existing member in a qtar-file
+
+   qtar -u file.qtar ./file_b
+
+   or just
+
+   qtar file.qtar ./file_b
+
+   6) Update/create members into the qtar-file from s;
+   ** Note: byte length of each file MUST be given after colon
+
+   echo "subdir/file_a:1200578 ./file_b:45007" | qtar -s file.qtar
+
+   or
+
+   qtar -s file.qtar subdir/file_a:1200578 ./file_b:45007
+
+   7) Extract via pipe (one member at a time, though):
+
+   echo "./file_b" | qtar -x -s file.qtar
+
+   or
+
+   qtar -x -s file.qtar ./file_b
+
+   8) Using find command update qtar-file (10 files at a time)
+
+   find . -name '*.c' -print | xargs -n10 qtar file.qtar
+
+*/
+
+int
+main(int argc, char *argv[])
+{
+  return QTAR_main(argc, argv);
+}
diff --git a/odb/src/tools/scheduler.c b/odb/src/tools/scheduler.c
new file mode 100644
index 0000000..fb1a086
--- /dev/null
+++ b/odb/src/tools/scheduler.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef _OPENMP
+#include <omp.h>
+#else
+static int 
+omp_get_max_threads(void)
+{
+  return 1;
+}
+static int 
+omp_get_thread_num(void)
+{
+  return 0;
+}
+#endif
+
+#define MAXLINELEN 65535
+
+typedef struct list_ {
+  char *cmd;
+  struct list_ *next;
+} List_t;
+
+int main(int argc, char *argv[])
+{
+  int num_threads = omp_get_max_threads();
+  int i, j, thread, rc, numtasks;
+  int errcnt = 0;
+  int *ret = NULL;
+  char **task = NULL;
+  char oneline[MAXLINELEN+1];
+  List_t *list = NULL;
+  List_t *prev = NULL;
+  List_t *curr = NULL;
+  FILE *fp = (argc > 1) ? fopen(argv[1], "r") : stdin;
+
+  if (!fp) {
+    perror((argc > 1) ? argv[1] : "<STDIN>");
+    return(1);
+  }
+
+  numtasks = 0;
+  while (fgets(oneline, sizeof(oneline), fp)) {
+    char *p = strchr(oneline,'\n');
+    if (p) *p = '\0';
+    if (strlen(oneline) == 0) continue;
+    curr = malloc(sizeof(*curr));
+    curr->cmd = strdup(oneline);
+    curr->next = NULL;
+    if (!list) {
+      list = prev = curr;
+    }
+    else {
+      prev->next = curr;
+      prev = curr;
+    }
+    numtasks++;
+  } /* while (fgets(oneline, sizeof(oneline), fp)) */
+
+  if (numtasks == 0) return(0);
+
+  task = malloc(numtasks * sizeof(*task));
+  curr = list;
+  for (j=0; j<numtasks; j++) {
+    task[j] = curr->cmd;
+    /* fprintf(stderr,"task#%d='%s'\n",j+1,task[j]); */
+    curr = curr->next;
+  }
+
+  ret = malloc(num_threads * sizeof(*ret));
+  for (i=0; i<num_threads; i++) ret[i] = 0;
+
+#ifdef _OPENMP
+#pragma omp parallel private(j, thread, rc) shared(ret, task, errcnt)
+#pragma omp for schedule(dynamic,1)
+#endif
+  for (j=0; j<numtasks; j++) {
+    thread = omp_get_thread_num();
+#ifdef _OPENMP
+#pragma omp critical
+#endif
+    {
+      fprintf(stderr,"(task#%d_%d|tid#%d_%d) %s\n",
+	      j+1,numtasks,thread+1,num_threads,task[j]);
+    }
+
+    rc = system(task[j]);
+
+#ifdef _OPENMP
+#pragma omp critical
+#endif
+    {
+      ret[thread] += rc;
+      if (rc != 0) {
+	errcnt++;
+	fprintf(stderr,"***Errors found in task#%d, thread#%d ; rc=%d : '%s'\n",
+		j+1,thread+1,rc,task[j]);
+      }
+    }
+  } /* for (j=0; j<numtasks; j++) */
+
+  rc = 0;
+  for (i=0; i<num_threads; i++) rc += ret[i];
+
+  if (rc != 0 || errcnt > 0) return(1);
+}
diff --git a/odb/src/tools/typebits.c b/odb/src/tools/typebits.c
new file mode 100644
index 0000000..aec5de3
--- /dev/null
+++ b/odb/src/tools/typebits.c
@@ -0,0 +1,110 @@
+/* This program can be used to generate DATATYPE_xxx #define's
+   used in ../include/privpub.h 
+
+   Run on RS6K, big-endian machine:
+
+   cc -DRS6K -I../include typebits.c -lm && a.out > out
+
+   or LITTLE-endian (say Linux/Pentium):
+
+   cc -DLINUX -DLITTLE -I../include typebits.c -lm && a.out > out
+
+   and you should get identical results.
+
+   Insert file "out" at the end of privpub.h, if you have added new types.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "privpub.h"
+
+typedef union {
+  odb_types_t t;
+  unsigned int ui;
+} ut;
+
+void tb(const char *name, const char *defname, 
+	int signbit, int byte_swappable,
+	int precision_bits, int base_type,
+	int other_type)
+{
+  double bits = pow(2,precision_bits);
+  long long int bytes = bits/8;
+  ut u;
+  u.ui = 0;
+  u.t.signbit = signbit;
+  u.t.byte_swappable = byte_swappable;
+  u.t.precision_bits = precision_bits;
+  u.t.base_type = base_type;
+  u.t.other_type = other_type;
+  {
+    printf("\n/* signbit=%u, byte_swappable=%u, precision_bits=%u, base_type=%u, other_type=0x%x (%u) */\n",
+	   u.t.signbit, u.t.byte_swappable, u.t.precision_bits,
+	   u.t.base_type, u.t.other_type, u.t.other_type);
+  }
+  u.ui >>= 8; /* shift over pmethod */
+  if (u.ui == 0) {
+    printf("#define DATATYPE_%-20s 0x%-8x   /* (%u dec) %s */\n",
+	   defname,u.ui,u.ui,name);
+  }
+  else if (bits > 256) {
+    printf("#define DATATYPE_%-20s 0x%-8x   /* (%u dec) %s : %lld bytes */\n",
+	   defname,u.ui,u.ui,name,bytes);
+  }
+  else {
+    printf("#define DATATYPE_%-20s 0x%-8x   /* (%u dec) %s : %.10g bits, %lld bytes */\n",
+	   defname,u.ui,u.ui,name,bits,bytes);
+  }
+}
+
+int main()
+{
+  tb("undef","UNDEF",0,0,0,0x0,0x0);
+
+  tb("bit"       ,"BIT"  ,0,0,0,0x1,0x0);
+
+  tb("char"      ,"INT1" ,1,1,3,0x1,0x0);
+  tb("short"     ,"INT2" ,1,1,4,0x1,0x0);
+  tb("int"       ,"INT4" ,1,1,5,0x1,0x0);
+  tb("long long" ,"INT8" ,1,1,6,0x1,0x0);
+
+  tb("uchar"     ,"UINT1",0,1,3,0x1,0x0);
+  tb("ushort"    ,"UINT2",0,1,4,0x1,0x0);
+  tb("uint"      ,"UINT4",0,1,5,0x1,0x0);
+  tb("ulonglong" ,"UINT8",0,1,6,0x1,0x0);
+
+  tb("float"      ,"REAL4" ,0,1,5,0x2,0x0);
+  tb("double"     ,"REAL8" ,0,1,6,0x2,0x0);
+  tb("long double","REAL16",0,1,7,0x2,0x0);
+
+  tb("complex4"   ,"CMPLX4" ,0,1,6,0x3,0x0);
+  tb("complex8"   ,"CMPLX8" ,0,1,7,0x3,0x0);
+  tb("complex16"  ,"CMPLX16",0,1,8,0x3,0x0);
+
+  tb("Bitfield"   ,"BITFIELD",0,1,5,0x0,0x1);
+  tb("string"     ,"STRING"  ,0,0,6,0x0,0x2);
+  tb("yyyymmdd"   ,"YYYYMMDD",0,1,5,0x0,0x4);
+  tb("hhmmss"     ,"HHMMSS"  ,0,1,5,0x0,0x8);
+
+  tb("link_offset","LINKOFFSET",1,1,5,0x0,0x10);
+  tb("link_length","LINKLEN"   ,1,1,5,0x0,0x20);
+
+  tb("bufr"       ,"BUFR"    ,0,1,5,0x0,0x40);
+  tb("grib"       ,"GRIB"    ,0,1,5,0x0,0x80);
+
+  tb("blob64kB"   ,"BLOB"    ,0,0,19,0x0,0x100);
+  tb("blob2GB"    ,"LONGBLOB",0,0,34,0x0,0x200);
+
+  tb("char(1:255)"   ,"CHAR"    ,0,0,11,0x0,0x400);
+  tb("varchar(1:255)","VARCHAR" ,0,0,11,0x0,0x800);
+
+  /*
+  tb("","" ,0,,,0x0,0x);
+  */
+
+  return 0;
+}
diff --git a/odb/src/tools/world2odb.c b/odb/src/tools/world2odb.c
new file mode 100644
index 0000000..33f2956
--- /dev/null
+++ b/odb/src/tools/world2odb.c
@@ -0,0 +1,571 @@
+/* wolrd2odb.c */
+
+/* Translates ASCII/Shape format regional polygons into 
+   a series of ASCII input files to be fed into ODB
+   via simulobs2odb -utility */
+
+#include "alloc.h"
+#include <time.h>
+
+typedef struct {
+  int offset;
+  int len;
+  double minlat, maxlat;
+  double minlon, maxlon;
+} Part_t;
+
+typedef struct {
+  char *name;
+  double minlat, maxlat;
+  double minlon, maxlon;
+  int nparts;
+  Part_t *part;
+  int n;
+  double *lat;
+  double *lon;
+} Country_t;
+
+
+PRIVATE int
+descending(const void *A, const void *B)
+{
+  const Country_t *a = A;
+  const Country_t *b = B;
+  if      ( a->n < b->n ) return +1;
+  else if ( a->n > b->n ) return -1;
+  else                    return  0;
+}
+
+
+#define KEY_SHP     "# Shp "
+#define KEY_NRECS   "# number of recs "
+#define KEY_NAME    "# Name: "
+#define KEY_BOX     "# Box: "
+#define KEY_NPARTS  "# Num of parts: "
+#define KEY_NPOINTS "# Num of points: "
+#define KEY_PARTNO  "# Part "
+
+int 
+main(int argc, char *argv[]) 
+{
+  int errcnt = 0;
+  int poolno = 0;
+  static char *ddl = NULL;
+  int jj;
+  putenv("DR_HOOK=0"); /* We do not want Dr.Hook to interfere */
+  for (jj=1; jj<argc; jj++) {
+    char *filename = STRDUP(argv[jj]);
+    char *cpools = strchr(filename,':');
+    int npp = 0; /* not in use yet */
+    FILE *fp;
+    if (cpools) {
+      *cpools++ = '\0';
+      npp = atoi(cpools);
+    }
+    fp = fopen(filename,"r");
+    if (fp) {
+      int npools = 0;
+      char txt[80];
+      int offset = 0;
+      Part_t *pp = NULL;
+      int shpinfo_read = 0;
+      int nc = 0;
+      Country_t *country = NULL;
+      Country_t *pc = NULL;
+      int n_countries = 0;
+      char line[4096];
+      while (!feof(fp) && fgets(line,sizeof(line),fp)) {
+	char *p = line;
+	char *nl = strchr(line,'\n');
+	while (isspace(*p)) p++;
+	if (nl) {
+	  *nl = '\0';
+	  if (nl != p) {
+	    for (;;) {
+	      --nl;
+	      if (nl == p || !isspace(*nl)) break;
+	    }
+	  }
+	  *++nl = '\0';
+	}
+#if 0
+	fprintf(stderr,"%s\n",p);
+#endif
+	if (!country) {
+	  const char s[] = KEY_NRECS;
+	  const int slen = sizeof(KEY_NRECS)-1;
+	  if (strncaseequ(p,s,slen)) {
+	    int n = 0;
+	    if (sscanf(p+slen,"%d",&n) == 1 && n > 0) {
+	      nc = n;
+	      CALLOC(country, nc+1);
+	      pc = country;
+#ifdef DEBUG
+	      fprintf(stderr,"---> country allocated : n = %d\n",n);
+#endif
+	    }
+	  }
+	}
+	else if (!shpinfo_read) {
+	  const char s[] = KEY_SHP;
+	  const int slen = sizeof(KEY_SHP)-1;
+	  if (strncaseequ(p,s,slen)) {
+	    shpinfo_read = 1;
+#ifdef DEBUG
+	    fprintf(stderr,"---> shp info read\n");
+#endif
+	  }
+	}
+	else if (n_countries == 0) {
+	  const char s[] = KEY_NAME;
+	  const int slen = sizeof(KEY_NAME) - 1;
+	  if (strncaseequ(p,s,slen)) {
+	    pc->name = STRDUP(p+slen);
+	    pp = NULL;
+	    offset = 0;
+#ifdef DEBUG
+	    fprintf(stderr,"---> in country#%d (%s)\n",
+		    n_countries,pc->name);
+#endif
+	    ++n_countries;
+	  }
+	}
+	else if (n_countries > 0) {
+	  const char s[] = KEY_NAME;
+	  const int slen = sizeof(KEY_NAME) - 1;
+
+	  const char sbox[] = KEY_BOX;
+	  const int sboxlen = sizeof(KEY_BOX) - 1;
+
+	  const char snparts[] = KEY_NPARTS;
+	  const int snpartslen = sizeof(KEY_NPARTS) - 1;
+
+	  const char snpoints[] = KEY_NPOINTS;
+	  const int snpointslen = sizeof(KEY_NPOINTS) - 1;
+
+	  const char spartno[] = KEY_PARTNO;
+	  const int spartnolen = sizeof(KEY_PARTNO) - 1;
+
+	  if (strncaseequ(p,s,slen)) {
+	    ++pc;
+	    pc->name = STRDUP(p+slen);
+	    pp = NULL;
+	    offset = 0;
+#ifdef DEBUG
+	    fprintf(stderr,"---> in country#%d (%s)\n",
+		    n_countries,pc->name);
+#endif
+	    ++n_countries;
+	  }
+	  else if (strncaseequ(p,sbox,sboxlen)) {
+	    double x[4];
+	    if (sscanf(p+sboxlen,"%lf %lf %lf %lf",x,x+1,x+2,x+3) == 4) {
+	      pc->minlon = x[0];
+	      pc->minlat = x[1];
+	      pc->maxlon = x[2];
+	      pc->maxlat = x[3];
+#ifdef DEBUG
+	      fprintf(stderr,
+		      "---> box = %.4f %.4f %.4f %.4f\n",
+		      x[0],x[1],x[2],x[3]);
+#endif
+	    }
+	  }
+	  else if (strncaseequ(p,snparts,snpartslen)) {
+	    int n = 0;
+	    if (sscanf(p+snpartslen, "%d", &n) == 1 && n > 0) {
+	      pc->nparts = n;
+	      CALLOC(pc->part, n);
+	      pp = pc->part - 1;
+#ifdef DEBUG
+	      fprintf(stderr,"---> number of parts = %d\n",pc->nparts);
+#endif
+	    }
+	  }
+	  else if (strncaseequ(p,snpoints,snpointslen)) {
+	    int n = 0;
+	    if (sscanf(p+snpointslen, "%d", &n) == 1 && n > 0) {
+	      pc->n = n;
+	      ALLOC(pc->lat, n);
+	      ALLOC(pc->lon, n);
+	      offset = 0;
+#ifdef DEBUG
+	      fprintf(stderr,"---> number of points = %d\n",pc->n);
+#endif
+	    }
+	  }
+	  else if (strncaseequ(p,spartno,spartnolen)) {
+	    int n = -1;
+	    if (sscanf(p+spartnolen, "%d", &n) == 1 && n >= 0) {
+	      ++pp;
+	      pp->offset = offset;
+	      pp->len = 0;
+#ifdef DEBUG
+	      fprintf(stderr,"---> part number = %d\n",n);
+#endif
+	    }
+	  }
+	  else if (*p != '#') {
+	    double lon, lat;
+	    if (sscanf(p,"%lf %lf", &lon, &lat) == 2) {
+	      pc->lat[offset] = lat;
+	      pc->lon[offset] = lon;
+	      pp->len++;
+	      offset++;
+	    }
+	  }
+	}
+      }
+      fclose(fp);
+
+#ifdef DEBUG
+      fprintf(stderr,"*** No ODBs were generated, since this was a DEBUG-run only\n");
+      goto release_space;
+#endif
+
+      /* Write input files for simulobs2odb */
+
+      /* Sort region with the biggest (most polygons) first */
+      qsort(country, n_countries, sizeof(*country), descending);
+
+      for (pc=country; pc && pc->name; ++pc) {
+	++poolno;
+	{ /* Desc.txt */
+	  int j;
+	  int creadate, creatime;
+	  char *creaby = getenv("USER");
+	  const int sourcelen = 10;
+	  time_t tp;
+	  char buf[80];
+	  time(&tp);
+	  strftime(buf, sizeof(buf), "%Y%m%d %H%M%S", localtime(&tp));
+	  sscanf(buf,"%d %d", &creadate, &creatime);
+	  snprintf(txt,sizeof(txt),"%dDesc.txt.%d",jj,poolno);
+	  fprintf(stderr, "Creating %s\n",txt);
+	  fp = fopen(txt,"w");
+	  fprintf(fp,"#desc\n");
+	  fprintf(fp,"#/poolno=%d\n",poolno);
+	  fprintf(fp,"#/nrows=1\n");
+	  fprintf(fp,"#/end\n");
+	  fprintf(fp,"\ncreadate creatime creaby region.len latlon_rad");
+	  for (j=1; j<=sourcelen; j++) fprintf(fp," source_%d",j);
+	  fprintf(fp,"\n");
+	  fprintf(fp,"%8.8d,%6.6d,'%8.8s',%d,0",
+		  creadate,creatime,creaby?creaby:"unknown",1);
+	  {
+	    char *s = filename;
+	    j = 0;
+	    while (j<sourcelen) {
+	      char ss[9];
+	      int slen = STRLEN(s);
+	      if (slen >= 8) {
+		slen = 8;
+		strncpy(ss,s,slen);
+		ss[8] = '\0';
+	      }
+	      else if (slen > 0 && slen < 8) {
+		const char blanks[] = "        ";
+		strcpy(ss,s);
+		strncat(ss+slen,blanks,slen-8);
+		ss[8] = '\0';
+	      }
+	      else {
+		slen = 0;
+		strcpy(ss," ");
+	      }
+	      fprintf(fp,",\"%s\"",ss);
+	      s += slen;
+	      j++;
+	    }
+	    fprintf(fp,"\n");
+	  }
+	  fclose(fp);
+	}
+
+	{ /* Region.txt */
+	  int j;
+	  const int namelen = 8;
+	  snprintf(txt,sizeof(txt),"%dRegion.txt.%d",jj,poolno);
+	  fprintf(stderr, "Creating %s : %d regions\n",txt,1);
+	  fp = fopen(txt,"w");
+	  fprintf(fp,"#region\n");
+	  fprintf(fp,"#/poolno=%d\n",poolno);
+	  fprintf(fp,"#/nrows=%d\n",1);
+	  fprintf(fp,"#/end\n");
+	  fprintf(fp,"\nid part.len minlat minlon maxlat maxlon");
+	  for (j=1; j<=namelen; j++) fprintf(fp," name[%d]",j);
+	  fprintf(fp,"\n");
+	  if (pc) {
+	    int id = 0;
+	    char *s = pc->name;
+	    char *comma = strchr(s,',');
+	    while (comma) {
+	      *comma = ' ';
+	      comma = strchr(comma+1,',');
+	    }
+	    fprintf(fp,"%d,%d",++id,pc->nparts);
+	    fprintf(fp,",%.6g,%.6g,%.6g,%.6g",
+		    pc->minlat, pc->minlon, 
+		    pc->maxlat, pc->maxlon);
+	    j = 0;
+	    while (j<namelen) {
+	      char ss[9];
+	      int slen = STRLEN(s);
+	      if (slen >= 8) {
+		slen = 8;
+		strncpy(ss,s,slen);
+		ss[8] = '\0';
+	      }
+	      else if (slen > 0 && slen < 8) {
+		const char blanks[] = "        ";
+		strcpy(ss,s);
+		strncat(ss+slen,blanks,slen-8);
+		ss[8] = '\0';
+	      }
+	      else {
+		slen = 0;
+		strcpy(ss," ");
+	      }
+	      fprintf(fp,",\"%s\"",ss);
+	      s += slen;
+	      j++;
+	    }
+	    fprintf(fp,"\n");
+	  }
+	  fclose(fp);
+	}
+
+	{ /* Part.txt */
+	  snprintf(txt,sizeof(txt),"%dPart.txt.%d",jj,poolno);
+	  fprintf(stderr, "Creating %s : %d parts\n",txt,pc->nparts);
+	  fp = fopen(txt, "w");
+	  fprintf(fp,"#part\n");
+	  fprintf(fp,"#/poolno=%d\n",poolno);
+	  fprintf(fp,"#/nrows=%d\n",pc->nparts); /* optional, but since we know already this ... */
+	  fprintf(fp,"#/end\n");
+	  fprintf(fp,"\npartno hdr.len\n");
+	  if (pc) {
+	    int jp;
+	    for (jp=0; jp<pc->nparts; jp++) {
+	      pp = &pc->part[jp];
+	      fprintf(fp,"%d,%d\n",jp+1,pp->len);
+	    }
+	  }
+	  fclose(fp);
+	}
+
+	{ /* Hdr.txt */
+	  int nvertex = 0;
+	  if (pc) {
+	    int jp;
+	    for (jp=0; jp<pc->nparts; jp++) {
+	      pp = &pc->part[jp];
+	      nvertex += pp->len;
+	    }
+	  }
+	  snprintf(txt,sizeof(txt),"%dHdr.txt.%d",jj,poolno);
+	  fprintf(stderr, "Creating %s : %d vertices\n",txt,nvertex);
+	  fp = fopen(txt, "w");
+	  fprintf(fp,"#hdr\n");
+	  fprintf(fp,"#/poolno=%d\n",poolno);
+	  fprintf(fp,"#/nrows=%d\n",nvertex); /* optional, but since we know already this ... */
+	  fprintf(fp,"#/end\n");
+	  fprintf(fp,"\nlat lon\n");
+	  if (pc) {
+	    int jp;
+	    for (jp=0; jp<pc->nparts; jp++) {
+	      int j, jstart, jend;
+	      pp = &pc->part[jp];
+	      jstart = pp->offset;
+	      jend = jstart + pp->len;
+	      for (j=jstart; j<jend; j++) {
+		fprintf(fp,"%.6g,%.6g\n", pc->lat[j], pc->lon[j]);
+#ifdef DEBUG
+		if (j == jstart) {
+		  fprintf(stderr, " /* part#%d starts here */",jp);
+		}
+#endif
+	      }
+	    }
+	  }
+	  fclose(fp);
+	}
+
+	if (!ddl) {
+	  /* Create data layout from the embedded input below */
+	  static char *layout[] = {
+	    "SET $sourcelen = 10;",
+	    "",
+	    "CREATE TABLE desc AS (",
+	    "  source[1:$sourcelen] string, // 80-bytes for source description / source file name",
+	    "  latlon_rad pk1int, // ==1 if (lat,lon) is in radians, ==0 if in degrees",
+	    "  // creation date, time and created by whom (username)",
+	    "  creadate YYYYMMDD,",
+	    "  creatime HHMMSS,",
+	    "  creaby   string,",
+	    "  region @LINK,",
+	    ");",
+	    "",
+	    "SET $namelen = 8;",
+	    "",
+	    "CREATE TABLE region AS (",
+	    "  id pk1int,",
+	    "  name[1:$namelen] string,",
+	    "  part @LINK,",
+	    "  minlat float,",
+	    "  minlon float,",
+	    "  maxlat float,",
+	    "  maxlon float,",
+	    ");",
+	    "",
+	    "CREATE TABLE part AS (",
+	    "  partno pk1int,",
+	    "  hdr @LINK,",
+	    ");",
+	    "",
+	    "CREATE TABLE hdr AS (",
+	    "  lat pk35real,",
+	    "  lon pk35real,",
+	    ");",
+	  };
+	  int j, n_layout = sizeof(layout)/sizeof(*layout);
+	  char *p, *pout;
+	  char *schema = filename;
+	  int len;
+	  char *ddl_out = NULL;
+	  int first = 1;
+	  p = strrchr(schema,'/');
+	  if (p) { *p++ = '\0'; ddl = STRDUP(p); }
+	  else ddl = STRDUP(schema);
+	  p = strchr(ddl,'.');
+	  if (p) *p = '\0';
+	  p = ddl;
+	  len = STRLEN(ddl) + 5;
+	  ALLOC(ddl_out, len);
+	  pout = ddl_out;
+	  while (*p) {
+	    int c = *p;
+	    if (islower(c)) *p = toupper(c);
+	    if ((*p >= 'A' && *p <= 'Z') ||
+		(!first && *p >= '0' && *p <= '9')) *pout++ = *p;
+	    ++p;
+	    if (first) first = 0;
+	  }
+	  *pout = '\0';
+	  FREE(ddl);
+	  ddl = STRDUP(ddl_out);
+	  FREE(ddl_out);
+	  len = STRLEN(ddl) + 5;
+	  ALLOC(schema, len);
+	  snprintf(schema, len, "%s.ddl", ddl);
+
+	  fprintf(stderr,"Creating data definition layout '%s'\n",schema);
+	  fp = fopen(schema,"w");
+	  for (j=0; j<n_layout; j++) {
+	    fprintf(fp,"%s\n",layout[j]);
+	  }
+	  FREE(schema);
+	  fclose(fp);
+	}
+	++npools;
+      } /* for (;;) */
+
+      {
+	char *cmd = NULL;
+	int len = STRLEN(ddl) + 2000;
+	ALLOCX(cmd, len);
+	snprintf(cmd,len,
+		 "$ODB_BINPATH/simulobs2odb %s-l%s -n%d -1 "
+		 "-i%dDesc.txt.%%d "
+		 "-i%dRegion.txt.%%d "
+		 "-i%dPart.txt.%%d "
+		 "-i%dHdr.txt.%%d", 
+		 (jj == 1) ? "-c " : "",
+		 ddl, poolno,
+		 jj,
+		 jj,
+		 jj,
+		 jj);
+	fprintf(stderr,"%s region database '%s', poolno(s) from %d to %d\n",
+		(jj == 1) ? "Creating" : "Updating", ddl, poolno-npools+1,poolno);
+	fprintf(stderr,"Running : %s\n",cmd);
+	if (system(cmd) != 0) {
+	  fprintf(stderr,"***Error(s) found in simulobs2odb\n");
+	  exit(++errcnt);
+	}
+	snprintf(cmd,len,
+		 "rm -f %dDesc.txt.* %dRegion.txt.* %dPart.txt.* %dHdr.txt.*",
+		 jj,jj,jj,jj);
+	fprintf(stderr,"Running : %s\n",cmd);
+	system(cmd);
+	FREEX(cmd);
+      }
+
+    release_space:
+      {
+	int j;
+	pc = country;
+	for (j=0; j<n_countries; j++) {
+	  int jp;
+	  FREE(pc->name);
+	  FREE(pc->part);
+	  FREE(pc->lat);
+	  FREE(pc->lon);
+	  ++pc;
+	}
+	FREE(country);
+      }
+    }
+    else {
+      perror(filename);
+      fprintf(stderr,"***Error: Unable to open input file '%s'\n",filename);
+      errcnt++;
+    }
+    FREE(filename);
+  } /* for (jj=1; jj<argc; jj++) */
+
+  if (ddl && errcnt == 0) {
+    fprintf(stderr,"Changing I/O-method to 4 in order to reduce no. of files\n");
+    {
+      const char fmt[] = "$ODB_BINPATH/odb1to4 %s";
+      char *cmd = NULL;
+      int len = STRLEN(fmt) + STRLEN(ddl) + 1;
+      ALLOCX(cmd, len);
+      snprintf(cmd, len, fmt, ddl);
+      fprintf(stderr,"Running : %s\n",cmd);
+      if (system(cmd) != 0) {
+	fprintf(stderr,"***Error(s) found in %s\n",cmd);
+	exit(++errcnt);
+      }
+      FREEX(cmd);
+    }
+  }
+
+  if (ddl && errcnt == 0) {
+    fprintf(stderr,"Creating tarball out of database '%s'\n",ddl);
+    {
+      const char fmt[] = "$ODB_BINPATH/odbtar c9v %s.tgz %s";
+      char *cmd = NULL;
+      int len = STRLEN(fmt) + 2*STRLEN(ddl) + 1;
+      ALLOCX(cmd, len);
+      snprintf(cmd,len,fmt,ddl,ddl);
+      fprintf(stderr,"Running : %s\n",cmd);
+      if (system(cmd) != 0) {
+	fprintf(stderr,"***Error(s) found in %s\n",cmd);
+	exit(++errcnt);
+      }
+      FREEX(cmd);
+    }
+    
+    fprintf(stderr,
+	    "Now you can now untar the tarball '%s.tgz' "
+	    "into your $ODB_GISROOT as follows:\n", ddl);
+    fprintf(stderr,"  gunzip -c < %s.tgz | (cd $ODB_GISROOT; tar xvf -)\n",ddl);
+    fprintf(stderr,"  (cd $ODB_GISROOT; find %s -type d -print | xargs chmod a+rx)\n",ddl);
+    fprintf(stderr,"  (cd $ODB_GISROOT; find %s -type f -print | xargs chmod a+r)\n",ddl);
+    
+    FREE(ddl);
+  }
+
+  return errcnt;
+}
diff --git a/odb/tests/CMakeLists.txt b/odb/tests/CMakeLists.txt
new file mode 100644
index 0000000..1e68ba6
--- /dev/null
+++ b/odb/tests/CMakeLists.txt
@@ -0,0 +1,55 @@
+odb_add_schema(TARGET DB SOURCES DB.ddl
+  VIEWS querydata1.sql querydata2.sql CONDITION ENABLE_TESTS NOINSTALL)
+
+ecbuild_add_executable(TARGET createdb.x
+  SOURCES createdb.F90
+  INCLUDES ${ODB_INCLUDE_DIRS}
+  LIBS ${ODB_LIBRARIES}
+  CONDITION ENABLE_TESTS NOINSTALL)
+
+ecbuild_add_executable(TARGET populate.x
+  SOURCES populate.F90
+  INCLUDES ${ODB_INCLUDE_DIRS}
+  LIBS ${ODB_LIBRARIES}
+  CONDITION ENABLE_TESTS NOINSTALL)
+
+ecbuild_add_executable(TARGET querydata.x
+  SOURCES querydata.F90
+  INCLUDES ${ODB_INCLUDE_DIRS}
+  LIBS ${ODB_LIBRARIES}
+  CONDITION ENABLE_TESTS NOINSTALL)
+
+odb_link_schemas(createdb.x  DB)
+odb_link_schemas(populate.x  DB)
+odb_link_schemas(querydata.x DB)
+
+if(HAVE_ODB_MPI)
+  if(NOT MPIEXEC) # FIXME: MPIEXEC is not set on Cray, assuming mpiexec for now
+    set(_MPIEXEC_CMD mpiexec\ -n\ 1)
+  else()
+    set(_MPIEXEC_CMD ${MPIEXEC}\ -n\ 1)
+  endif()
+endif()
+
+ecbuild_add_test(TARGET test_createdb
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/createdb.sh
+    ARGS ${CMAKE_CURRENT_SOURCE_DIR}/createdb.F90
+         ${CMAKE_CURRENT_SOURCE_DIR}/DB.ddl
+         ${CMAKE_CURRENT_SOURCE_DIR}/createdb.out
+    ENVIRONMENT
+        ${ODB_ENVIRONMENT}
+        PATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+        MPIEXEC_CMD=${_MPIEXEC_CMD}
+    TEST_DEPENDS createdb.x
+)
+
+ecbuild_add_test(TARGET test_populate
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/populate.sh
+    ARGS ${CMAKE_CURRENT_SOURCE_DIR}/populate.F90
+         ${CMAKE_CURRENT_SOURCE_DIR}/populate.out
+    ENVIRONMENT
+        ${ODB_ENVIRONMENT}
+        PATH=${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+        MPIEXEC_CMD=${_MPIEXEC_CMD}
+    TEST_DEPENDS populate.x test_createdb
+)
diff --git a/odb/tests/DB.ddl b/odb/tests/DB.ddl
new file mode 100644
index 0000000..6750215
--- /dev/null
+++ b/odb/tests/DB.ddl
@@ -0,0 +1,23 @@
+// Database DB: file DB.ddl
+
+SET $mdi = 2147483647;
+
+CREATE TABLE hdr AS (
+  seqno   pk1int,
+  date    YYYYMMDD,
+  time    HHMMSS,
+  statid  string,
+  lat     pk9real,
+  lon     pk9real,
+  body   @LINK
+);
+
+CREATE TABLE body AS (
+  entryno   pk1int,
+  varno     pk1int,
+  press     pk9real,
+  obsvalue  pk9real,
+  depar     pk9real,
+  obs_error pk9real,
+  bias      pk9real
+);
diff --git a/odb/tests/createdb.F90 b/odb/tests/createdb.F90
new file mode 100644
index 0000000..1fe7178
--- /dev/null
+++ b/odb/tests/createdb.F90
@@ -0,0 +1,14 @@
+PROGRAM createdb
+!*** createdb.F90 ***
+USE odb_module
+implicit none
+INTEGER(4) :: myproc,nproc,npools,h
+INTEGER(4) :: nrows, ncols, nra, rc
+character(len=64) dbname
+rc = ODB_init(myproc=myproc,nproc=nproc)
+CALL getarg(1,dbname) ! Database name
+npools = 1 ! Change this to a desired number
+h = ODB_open(dbname,'NEW',npools)
+rc = ODB_close(h,save=.TRUE.)
+rc = ODB_end()
+END PROGRAM createdb
diff --git a/odb/tests/createdb.out b/odb/tests/createdb.out
new file mode 100644
index 0000000..91054c7
--- /dev/null
+++ b/odb/tests/createdb.out
@@ -0,0 +1,2 @@
+ count(*)
+ 0
diff --git a/odb/tests/createdb.sh b/odb/tests/createdb.sh
new file mode 100755
index 0000000..1b9348d
--- /dev/null
+++ b/odb/tests/createdb.sh
@@ -0,0 +1,36 @@
+#!/bin/ksh
+
+set -e
+source use_odb.sh
+set -x
+
+# (0) Go to directory where DB.ddl sits
+# This will become (by default) your database directory
+rm -fr DB
+mkdir -p DB
+cd DB
+
+# (1) Compile database DB (once in the lifetime):
+cp $2 .
+newodb DB
+
+# (2) Run setup to get the IOASSIGN right:
+./DB.setup > DB.IOASSIGN
+
+# (3) Make sure to get the database directories right:
+export ODB_DATAPATH_DB=`pwd`
+export ODB_SRCPATH_DB=`pwd`
+
+# (4) Compile and link Fortran90 application: (NOTE: already done by CMake)
+odbf90 $1 -lDB -o createdb.x
+
+# (5) Run the application
+$MPIEXEC_CMD ./createdb.x DB
+
+# (6) Validate the result
+odbsql -q "select count(*) from hdr" > createdb.out
+diff $3 createdb.out
+
+# FIXME: Wait for (at least) one second before running a next test to avoid issues with
+# DCA files caching in odbsql script.
+sleep 1.1
diff --git a/odb/tests/populate.F90 b/odb/tests/populate.F90
new file mode 100644
index 0000000..4091ba2
--- /dev/null
+++ b/odb/tests/populate.F90
@@ -0,0 +1,82 @@
+PROGRAM populate
+!*** populate.F90 ***
+
+  
+USE odb_module
+
+implicit none
+
+REAL(8), ALLOCATABLE :: x(:,:)
+REAL(8) :: statid(3), to_real8
+REAL(8) mdi ! Missing data indicator ("NULL")
+INTEGER(4) :: myproc,nproc,npools,jp,h
+INTEGER(4) :: nrows, ncols, rc
+character(len=64) dbname, tblname
+
+rc = ODB_init(myproc=myproc,nproc=nproc)
+
+CALL getarg(1,dbname)    ! Database name
+
+npools = 0 ! Gets true value from ODB_open()
+
+h = ODB_open(dbname,'OLD',npools)
+
+mdi = abs(ODB_getval(h, '$mdi'))
+
+jp = 1 ! Here: Populate poolno#1 only for now
+
+if (myproc == mod(jp-1,nproc)+1) then
+  tblname = '@hdr' ! Note '@'-sign in front of
+  rc = ODB_getsize(h,tblname,nrows,ncols,poolno=jp)
+  nrows = 3 ! Three new rows for TABLE hdr
+  ALLOCATE(x(nrows,0:ncols))
+
+  statid(1) = transfer("07027", to_real8)
+  statid(2) = transfer("07061", to_real8)
+  statid(3) = transfer("07075", to_real8)
+
+  !              seqno       date     time     statid  ...
+  !                ...     lat       lon  body.offset  body.len
+  x(1,1:ncols) = (/1d0,20010101d0,100000d0,statid(1), &
+               &       49.18d0,  -0.45d0,      0d0,         2d0/)
+  x(2,1:ncols) = (/2d0,20010101d0,130000d0,statid(2), &
+               &       49.82d0,   3.20d0,      2d0,         2d0/)
+  x(3,1:ncols) = (/3d0,20010101d0,130000d0,statid(3), &
+               &       49.78d0,   4.63d0,      4d0,         1d0/)
+
+  ! Note: the following APPENDs after the existing data
+  rc = ODB_put(h,tblname,x,nrows,ncols,poolno=jp)
+
+  DEALLOCATE(x)
+
+  tblname = '@body' ! Note '@'-sign in front of
+
+  rc = ODB_getsize(h,tblname,nrows,ncols,poolno=jp)
+
+  nrows = 5 ! Five new rows for TABLE body
+
+  ALLOCATE(x(nrows,0:ncols))
+  ! entryno, varno,     press,  obsvalue,    depar, obs_error, bias
+  x(1,1:ncols) = &
+    (/1d0,   110d0,  657.05d0,98530.00d0, -85.86d0,   69.03d0, -mdi/)
+  x(2,1:ncols) = &
+    (/2d0,    39d0,98530.00d0,  282.70d0,   1.80d0,    1.95d0, -mdi/)
+  x(3,1:ncols) = &
+    (/1d0,   110d0,  990.47d0,98480.00d0,-221.59d0,   69.09d0, -mdi/)
+  x(4,1:ncols) = &
+    (/2d0,    39d0,98480.00d0,  279.80d0,   1.06d0,    1.95d0, -mdi/)
+  x(5,1:ncols) = &
+    (/1d0,   110d0, 1451.38d0,98250.00d0,-123.32d0,   69.36d0, -mdi/)
+  ! Note: the following APPENDs after the existing data
+
+  rc = ODB_put(h,tblname,x,nrows,ncols,poolno=jp)
+
+  DEALLOCATE(x)
+
+endif
+
+rc = ODB_close(h,save=.TRUE.)
+
+rc = ODB_end()
+
+END PROGRAM populate
diff --git a/odb/tests/populate.out b/odb/tests/populate.out
new file mode 100644
index 0000000..3f1e502
--- /dev/null
+++ b/odb/tests/populate.out
@@ -0,0 +1,6 @@
+ seqno at hdr date at hdr time at hdr statid at hdr lat at hdr lon at hdr body.offset at hdr body.len at hdr entryno at body varno at body press at body obsvalue at body depar at body obs_error at body bias at body
+ 1 20010101 100000 '07027   ' 49.18 -0.45 0 2 1 110 657.05 98530 -85.86 69.03 NULL
+ 1 20010101 100000 '07027   ' 49.18 -0.45 0 2 2 39 98530 282.7 1.8 1.95 NULL
+ 2 20010101 130000 '07061   ' 49.82 3.2 2 2 1 110 990.47 98480 -221.59 69.09 NULL
+ 2 20010101 130000 '07061   ' 49.82 3.2 2 2 2 39 98480 279.8 1.06 1.95 NULL
+ 3 20010101 130000 '07075   ' 49.78 4.63 4 1 1 110 1451.38 98250 -123.32 69.36 NULL
diff --git a/odb/tests/populate.sh b/odb/tests/populate.sh
new file mode 100755
index 0000000..7692255
--- /dev/null
+++ b/odb/tests/populate.sh
@@ -0,0 +1,17 @@
+#!/bin/ksh
+
+set -e
+source use_odb.sh
+set -x
+
+cd DB
+
+# (4) Compile and link Fortran90 application: (NOTE: already done by CMake)
+odbf90 $1 -lDB -o populate.x
+
+# (5) Run the application
+$MPIEXEC_CMD ./populate.x DB
+
+# (6) Validate the result
+odbsql -q "select * from hdr,body" > populate.out
+diff $2 populate.out
diff --git a/odb/tests/querydata.F90 b/odb/tests/querydata.F90
new file mode 100644
index 0000000..a9b9651
--- /dev/null
+++ b/odb/tests/querydata.F90
@@ -0,0 +1,47 @@
+PROGRAM querydata
+!*** querydata.F90 ***
+USE odb_module
+implicit none
+REAL(8), ALLOCATABLE :: x(:,:)
+INTEGER(4) :: myproc,nproc,npools,jp,h
+INTEGER(4) :: nrows, ncols, nra, rc
+INTEGER(4) :: numargs, iargc, jque, jr, jc, nc
+character(len=64) dbname, queryname
+character(len=64), allocatable :: colnames(:)
+rc = ODB_init(myproc=myproc,nproc=nproc)
+numargs = iargc()
+if (numargs < 1) then
+  CALL ODB_abort('querydata',&
+  'Usage: querydata DBname [query1 [query2] ...]',numargs)
+endif
+CALL getarg(1,dbname)    ! Database name
+do jque=2,numargs
+  CALL getarg(jque,queryname) ! Query name
+  npools = 0 ! Gets true value from ODB_open()
+  h = ODB_open(dbname,'READONLY',npools)
+  write(*,*)'Exec query#',jque-1,'="'//trim(queryname)//'"'
+  rc = ODB_addview(h,queryname) ! Not necessary anymore
+  nc = ODB_getnames(h,queryname,'name')
+  ALLOCATE(colnames(nc))
+  nc = ODB_getnames(h,queryname,'name',colnames)
+  do jp=myproc,npools,nproc ! Round-robin, "my" pools only
+    rc = ODB_select(h,queryname,nrows,ncols,nra=nra,poolno=jp)
+    if (nrows > 0) then
+      ALLOCATE(x(nra,0:ncols))
+      rc = ODB_get(h,queryname,x,nrows,ncols,poolno=jp)
+      write(*,'((3a20))') (trim(colnames(jc)),jc=1,nc)
+      do jr=1,nrows
+        write(*,'(1p,(5x,3(1x,g20.10)))') x(jr,1:ncols)
+      enddo
+      DEALLOCATE(x)
+    endif
+    rc = ODB_cancel(h,queryname,poolno=jp)
+    ! The following is the same as the less preferred
+    ! rc = ODB_swapout(h,'*',poolno=jp)
+    rc = ODB_release(h,poolno=jp)
+  enddo ! do jp=myproc,npools,nproc
+  DEALLOCATE(colnames)
+  rc = ODB_close(h)
+enddo ! do jque=2,numargs
+rc = ODB_end()
+END PROGRAM querydata
diff --git a/odb/tests/querydata1.sql b/odb/tests/querydata1.sql
new file mode 100644
index 0000000..98c5a59
--- /dev/null
+++ b/odb/tests/querydata1.sql
@@ -0,0 +1 @@
+CREATE VIEW querydata1 AS SELECT * FROM hdr;
diff --git a/odb/tests/querydata2.sql b/odb/tests/querydata2.sql
new file mode 100644
index 0000000..7d9fd90
--- /dev/null
+++ b/odb/tests/querydata2.sql
@@ -0,0 +1 @@
+CREATE VIEW querydata2 AS SELECT * FROM body;
diff --git a/odb_api/CMakeLists.txt b/odb_api/CMakeLists.txt
index e9a3bbe..2862515 100644
--- a/odb_api/CMakeLists.txt
+++ b/odb_api/CMakeLists.txt
@@ -40,11 +40,6 @@ ecbuild_dont_pack(REGEX ".gdbinit")
 ###############################################################################
 # some variables/options of this project
 
-ecbuild_add_option( FEATURE MIGRATOR
-                    DESCRIPTION "whether or not to build the ODB migrator tool"
-                    DEFAULT OFF
-                    REQUIRED_PACKAGES "PROJECT odb VERSION 1.0 QUIET" )
-
 ecbuild_add_option( FEATURE FORTRAN
                     DESCRIPTION "whether or not to build the Fortran interface"
                     DEFAULT OFF )
@@ -64,24 +59,13 @@ ecbuild_add_option( FEATURE ODB_SERVER_TIME_FORMAT_FOUR_DIGITS
 
 SET(ODB_API_SCHEMA_PATH "" CACHE STRING "Path to schema file that will be loaded before executing SQL")
 
-if( HAVE_FORTRAN OR HAVE_MIGRATOR )
+if( HAVE_FORTRAN )
 
     set( Fortran Fortran )
     ecbuild_enable_fortran( REQUIRED MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/module )
-    ecbuild_find_fortranlibs( REQUIRED )
-    message( "Fortran libraries: [${FORTRAN_LIBRARIES}]" )
 
 endif()
 
-#if( HAVE_MIGRATOR )
-    #if(CMAKE_Fortran_COMPILER_ID STREQUAL "PGI")
-    #    ecbuild_add_fortran_flags("-r8")
-    #    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
-    #    # NOTE that if we add -fdefault-real-8 then we NEED -fdefault-double-8 to avoid quadmath
-    #    ecbuild_add_fortran_flags("-fdefault-real-8 -fdefault-double-8")
-    #endif()
-#endif()
-
 if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
   ecbuild_add_fortran_flags("-fPIC -ffree-line-length-none")
 endif()
diff --git a/odb_api/VERSION.cmake b/odb_api/VERSION.cmake
index 27c15ce..bc32f90 100644
--- a/odb_api/VERSION.cmake
+++ b/odb_api/VERSION.cmake
@@ -1 +1 @@
-set( ${PROJECT_NAME}_VERSION_STR  "0.17.0" )
+set( ${PROJECT_NAME}_VERSION_STR  "0.17.1" )
diff --git a/odb_api/project_summary.cmake b/odb_api/project_summary.cmake
index fc2e613..0dacc52 100644
--- a/odb_api/project_summary.cmake
+++ b/odb_api/project_summary.cmake
@@ -8,10 +8,6 @@ if(ODB_FOUND)
   message( STATUS "     DL  lib      : [${DL_LIBRARIES}]" )
 endif()
 
-if( FORTRAN_LIBRARIES )
-  message( STATUS " FORTRAN_LIBRARIES: [${FORTRAN_LIBRARIES}]" )
-endif()
-
 #string( TOUPPER ${PROJECT_NAME} PNAME )
 #foreach( _tpl ${${PNAME}_TPLS} )
 #	string( TOUPPER ${_tpl} TPL )
diff --git a/odb_api/src/CMakeLists.txt b/odb_api/src/CMakeLists.txt
index e96c5a4..87c8c15 100644
--- a/odb_api/src/CMakeLists.txt
+++ b/odb_api/src/CMakeLists.txt
@@ -21,9 +21,7 @@ include_directories( ${ODB_API_INCLUDE_DIRS} ${ECKIT_INCLUDE_DIRS} ${ECML_INCLUD
 
 add_subdirectory( odb_api )
 add_subdirectory( odb_api/tools )
-add_subdirectory( odb_api/migrator )
 add_subdirectory( odb_api/odb2netcdf )
-add_subdirectory( odb_api/odb2_to_odb1 )
 add_subdirectory( fortran )
 add_subdirectory( python )
 add_subdirectory( api )
diff --git a/odb_api/src/ecml/misc/DynamicParametrisation.cc b/odb_api/src/ecml/misc/DynamicParametrisation.cc
index 7e5d6b4..49f331c 100644
--- a/odb_api/src/ecml/misc/DynamicParametrisation.cc
+++ b/odb_api/src/ecml/misc/DynamicParametrisation.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "eckit/utils/Translator.h"
+#include "eckit/exception/Exceptions.h"
 
 #include "ecml/core/ExecutionContext.h"
 #include "ecml/core/Environment.h"
@@ -103,5 +104,15 @@ bool DynamicParametrisation::get(const std::string& name, std::vector<double>& v
     return r;
 }
 
+
+
+bool DynamicParametrisation::get(const std::string& name, int& value) const { NOTIMP; return false; }
+bool DynamicParametrisation::get(const std::string& name, float& value) const { NOTIMP; return false; }
+bool DynamicParametrisation::get(const std::string& name, std::vector<int>& value) const { NOTIMP; return false; }
+bool DynamicParametrisation::get(const std::string& name, std::vector<size_t>& value) const { NOTIMP; return false; }
+bool DynamicParametrisation::get(const std::string& name, std::vector<float>& value) const { NOTIMP; return false; }
+bool DynamicParametrisation::get(const std::string& name, std::vector<std::string>& value) const { NOTIMP; return false; }
+
+
 } // namespace ecml
 
diff --git a/odb_api/src/ecml/misc/DynamicParametrisation.h b/odb_api/src/ecml/misc/DynamicParametrisation.h
index 5ee67be..ae8840e 100644
--- a/odb_api/src/ecml/misc/DynamicParametrisation.h
+++ b/odb_api/src/ecml/misc/DynamicParametrisation.h
@@ -40,6 +40,15 @@ public:
     virtual bool get(const std::string& name, std::vector<long>& value) const;
     virtual bool get(const std::string& name, std::vector<double>& value) const;
 
+// -- Not Implemented
+
+    virtual bool get(const std::string& name, int& value) const;
+    virtual bool get(const std::string& name, float& value) const;
+    virtual bool get(const std::string& name, std::vector<int>& value) const;
+    virtual bool get(const std::string& name, std::vector<float>& value) const;
+    virtual bool get(const std::string& name, std::vector<size_t>& value) const;
+    virtual bool get(const std::string& name, std::vector<std::string>& value) const;
+
 private:
     ExecutionContext& context_;
 };
diff --git a/odb_api/src/fortran/legacy_fortran_api_examples.f90 b/odb_api/src/fortran/legacy_fortran_api_examples.f90
index 3a087ad..081621c 100644
--- a/odb_api/src/fortran/legacy_fortran_api_examples.f90
+++ b/odb_api/src/fortran/legacy_fortran_api_examples.f90
@@ -290,7 +290,7 @@ subroutine example_fortran_api2
  character(len=max_varlen)                     :: bitfield_names
  character(len=max_varlen)                     :: bitfield_sizes
  integer(kind=4)                               :: i
- character(kind=C_CHAR, len=128)               :: sql='select * from "test.odb";'//achar(0)
+ character(kind=C_CHAR, len=128)               :: sql='select * from "test.odb"'//achar(0)
  integer(kind=C_INT)                           :: itype, newdataset, c_ncolumns=3, size_name 
  integer(kind=C_INT)                           :: bitfield_names_size, bitfield_sizes_size
  real(kind=C_DOUBLE), dimension(:), allocatable:: one_row
diff --git a/odb_api/src/odb_api/CMakeLists.txt b/odb_api/src/odb_api/CMakeLists.txt
index d7ef236..a0ae8ad 100644
--- a/odb_api/src/odb_api/CMakeLists.txt
+++ b/odb_api/src/odb_api/CMakeLists.txt
@@ -211,6 +211,8 @@ Header.h
 InMemoryDataHandle.cc
 InMemoryDataHandle.h
 IteratorProxy.h
+LibOdbApi.cc
+LibOdbApi.h
 MD5.cc
 MD5.h
 MDSetter.cc
diff --git a/odb_api/src/odb_api/LibOdbApi.cc b/odb_api/src/odb_api/LibOdbApi.cc
new file mode 100644
index 0000000..35b4c67
--- /dev/null
+++ b/odb_api/src/odb_api/LibOdbApi.cc
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Simon Smart
+/// @date   June 2017
+
+#include <algorithm>
+#include <string>
+
+#include "odb_api/LibOdbApi.h"
+
+#include "odb_api/ODBAPIVersion.h"
+
+namespace odb {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+static LibOdbApi libodbapi;
+
+LibOdbApi::LibOdbApi() : Library("odb_api") {}
+
+const LibOdbApi& LibOdbApi::instance()
+{
+    return libodbapi;
+}
+
+const void* LibOdbApi::addr() const { return this; }
+
+std::string LibOdbApi::version() const { return ODBAPIVersion::version(); }
+
+std::string LibOdbApi::gitsha1(unsigned int count) const {
+    std::string sha1(eckit_git_sha1());
+    if(sha1.empty()) {
+        return "not available";
+    }
+
+    return sha1.substr(0,std::min(count,40u));
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
diff --git a/odb_api/src/odb_api/LibOdbApi.h b/odb_api/src/odb_api/LibOdbApi.h
new file mode 100644
index 0000000..b3079f1
--- /dev/null
+++ b/odb_api/src/odb_api/LibOdbApi.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 1996-2017 ECMWF.
+ *
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
+ * In applying this licence, ECMWF does not waive the privileges and immunities
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// @author Simon Smart
+/// @date   June 2017
+
+#ifndef odb_api_LibOdbApi_H
+#define odb_api_LibOdbApi_H
+
+#include "eckit/system/Library.h"
+
+namespace odb {
+
+//----------------------------------------------------------------------------------------------------------------------
+
+class LibOdbApi : public eckit::system::Library {
+public:
+
+    LibOdbApi();
+
+    static const LibOdbApi& instance();
+
+protected:
+
+    const void* addr() const;
+
+    virtual std::string version() const;
+
+    virtual std::string gitsha1(unsigned int count) const;
+
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+
+} // namespace eckit
+
+#endif // odb_api_LibOdbApi_H
diff --git a/odb_api/src/odb_api/ODBAPIVersion.cc b/odb_api/src/odb_api/ODBAPIVersion.cc
index 5a0f18d..d7cd603 100644
--- a/odb_api/src/odb_api/ODBAPIVersion.cc
+++ b/odb_api/src/odb_api/ODBAPIVersion.cc
@@ -19,6 +19,7 @@
 namespace odb {
 
     const char *ODBAPIVersion::version() { return ODB_API_VERSION_STR; }
+    const char *gitsha1() { return ODB_API_GIT_SHA1; }
 
 	unsigned int ODBAPIVersion::formatVersionMajor() { return FORMAT_VERSION_NUMBER_MAJOR; }
 	unsigned int ODBAPIVersion::formatVersionMinor() { return FORMAT_VERSION_NUMBER_MINOR; }
diff --git a/odb_api/src/odb_api/SQLInteractiveSession.h b/odb_api/src/odb_api/SQLInteractiveSession.h
index b3efa07..1a09e32 100755
--- a/odb_api/src/odb_api/SQLInteractiveSession.h
+++ b/odb_api/src/odb_api/SQLInteractiveSession.h
@@ -37,9 +37,9 @@ private:
     SQLStatement* sql_;
 
 // -- Overridden methods
-	void statement(SQLStatement*);
-	SQLStatement* statement();
-	SQLOutput* defaultOutput();
+    virtual void statement(SQLStatement*);
+    virtual SQLStatement* statement();
+    virtual SQLOutput* defaultOutput();
 
 	//friend std::ostream& operator<<(std::ostream& s,const SQLInteractiveSession& p)
 	//	{ p.print(s); return s; }
diff --git a/odb_api/src/odb_api/SQLParser.cc b/odb_api/src/odb_api/SQLParser.cc
index 35b31c1..2c53b11 100755
--- a/odb_api/src/odb_api/SQLParser.cc
+++ b/odb_api/src/odb_api/SQLParser.cc
@@ -31,6 +31,7 @@
 #include "odb_api/EmbeddedCodeParser.h"
 #include "odb_api/FunctionMATCH.h"
 #include "odb_api/SQLAST.h"
+#include "odb_api/ecml_verbs/SQLHandler.h"
 
 using namespace eckit;
 
@@ -119,7 +120,7 @@ void SQLParser::parseString(odb::sql::SQLSession& session, const std::string& s,
     SQLYacc::include_stack stack;
     SQLYacc::odblib_lex_init_extra(&stack, &scanner);
 
-    stack.push(s, "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
+    stack.push(SQLHandler::cleanUpSQLText(s), "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
     SQLYacc::odblib_parse(scanner, &session);
 
     session.statement();
@@ -141,7 +142,7 @@ void SQLParser::parseString(odb::sql::SQLSession& session, const std::string& s,
     SQLYacc::include_stack stack;
     SQLYacc::odblib_lex_init_extra(&stack, &scanner);
 
-    stack.push(s, "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
+    stack.push(SQLHandler::cleanUpSQLText(s), "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
     SQLYacc::odblib_parse(scanner, &session);
 
     session.statement();
@@ -162,7 +163,7 @@ void SQLParser::parseString(odb::sql::SQLSession& session,const std::string& s,
     SQLYacc::include_stack stack;
     SQLYacc::odblib_lex_init_extra(&stack, &scanner);
 
-    stack.push(s, "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
+    stack.push(SQLHandler::cleanUpSQLText(s), "", (SQLYacc::YY_BUFFER_STATE) scanner, (SQLYacc::odblib_scan_t) scanner); 
     SQLYacc::odblib_parse(scanner, &session);
 
     session.statement();
diff --git a/odb_api/src/odb_api/migrator/CMakeLists.txt b/odb_api/src/odb_api/migrator/CMakeLists.txt
deleted file mode 100644
index 9118e1e..0000000
--- a/odb_api/src/odb_api/migrator/CMakeLists.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-list( APPEND migrator_srcs
-FakeODBIterator.cc
-FakeODBIterator.h
-ImportODBTool.cc
-ImportODBTool.h
-ODB2ODATool.cc
-ODB2ODATool.h
-MigratorTool.h
-MigratorTool.cc
-ODBIterator.cc
-ODBIterator.h
-OldODBReader.h
-ReptypeGenIterator.cc
-ReptypeGenIterator.h
-TSQLReader.cc
-TSQLReader.h
-ODBMigratorModule.h
-ODBMigratorModule.cc
-MigrateHandler.h
-MigrateHandler.cc
-migrator_api.cc
-migrator_api.h
-)
-
-    ecbuild_add_library( TARGET Odbmigrator
-                         SOURCES    ${migrator_srcs}
-                         CONDITION
-                            HAVE_MIGRATOR AND ODB_FOUND AND DEFINED FORTRAN_LIBRARIES
-                         TEMPLATES
-                            ImportODBTool.cc TSQLReader.cc
-                         PRIVATE_INCLUDES   ${ODB_INCLUDE_DIRS}
-                         INSTALL_HEADERS LISTED
-                         HEADER_DESTINATION ${INSTALL_INCLUDE_DIR}/odb_api/migrator
-                         LIBS       Odb odbtools ${ODB_LIBRARIES} ${FORTRAN_LIBRARIES} ${DL_LIBRARIES} ${EXTRA_ODB_MIGRATOR_LIBS}) #FIXME: add gomp for gfortran 
-                        
-    ecbuild_add_executable( TARGET     odb_migrator
-                        CONDITION
-                            HAVE_MIGRATOR AND ODB_FOUND AND DEFINED FORTRAN_LIBRARIES
-                        SOURCES    odb2oda.cc
-                        INCLUDES   ${ODB_INCLUDE_DIRS}
-                        # LINKER_LANGUAGE Fortran
-                        LIBS       Odbmigrator odbtools ${ODB_LIBRARIES} ${FORTRAN_LIBRARIES} ${DL_LIBRARIES} )
-
-    set( test_environment
-      ODB_API_CODES=${PROJECT_SOURCE_DIR}/etc
-      ODB_API_HOME=${PROJECT_SOURCE_DIR}
-      ODB_API_TEST_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}
-      PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
-      ODB_RTABLE_PATH=${PROJECT_SOURCE_DIR}/etc )
-
-    if( HAVE_MIGRATOR AND ODB_FOUND AND DEFINED FORTRAN_LIBRARIES )
-
-      get_target_property( migrator_bin odb_migrator LOCATION)
-
-      list( APPEND odb_migrator_data_files  2000010106.old.ECMA.tar.gz )
-
-      ecbuild_get_test_multidata( TARGET get_odb_migrator_test_data
-                                  DIRNAME odb_api/tests 
-                                  NAMES ${odb_migrator_data_files} 
-                                  NOCHECK )
-
-      #ecbuild_add_test( TARGET     test_migrator.ecml
-      #                COMMAND      ${migrator_bin} 
-      #                ARGS         ecml ${CMAKE_CURRENT_SOURCE_DIR}/test_migrator.ecml
-      #                CONDITION    HAVE_MIGRATOR
-      #                ENVIRONMENT  ${test_environment}
-      #                LABELS       odb_api odb_api_ecml
-      #                TEST_DEPENDS get_odb_migrator_test_data
-      #                )
-    endif()
-
-  if( HAVE_MIGRATOR AND HAVE_PYTHON AND SWIG_FOUND AND PYTHONLIBS_FOUND )
-        set(CMAKE_SWIG_FLAGS "")
-        include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${PYTHON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../odb_api )
-        set_source_files_properties( pyodbdump.i PROPERTIES CPLUSPLUS ON )
-        # set_source_files_properties( pyodbapi.i PROPERTIES SWIG_FLAGS "-includeall")
-        swig_add_module( pyodbdump python pyodbdump.i )
-        swig_link_libraries( pyodbdump Odbmigrator Odb ${ODB_LIBRARIES} ${FORTRAN_LIBRARIES} ${DL_LIBRARIES} ${PYTHON_LIBRARIES} )
-        
-        set(PYTHON_SITE "${INSTALL_LIB_DIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages" )
-        set(PYTHON_DEST "${PYTHON_SITE}" )
-        install(TARGETS _pyodbdump DESTINATION ${PYTHON_DEST} )
-        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyodbdump.py  DESTINATION ${PYTHON_DEST})
-    endif()
diff --git a/odb_api/src/odb_api/migrator/FakeODBIterator.cc b/odb_api/src/odb_api/migrator/FakeODBIterator.cc
deleted file mode 100644
index 52038e0..0000000
--- a/odb_api/src/odb_api/migrator/FakeODBIterator.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-///
-/// \file FakeODBIterator.cc
-///
-/// @author Piotr Kuchta, Feb 2009
-
-#include <strings.h>
-
-extern "C" {
-#include "odbdump.h"
-}
-
-#include "eckit/parser/Tokenizer.h"
-#include "eckit/utils/Translator.h"
-
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-
-#include "odb_api/migrator/FakeODBIterator.h"
-#include "odb_api/migrator/ODBIterator.h"
-
-
-using namespace eckit;
-
-namespace odb {
-namespace tool {
-
-FakeODBIterator::ConstParameters FakeODBIterator::ConstParameters::instance_ = FakeODBIterator::ConstParameters();
-
-Assignments::Assignments(const std::string& s)
-{
-    Tokenizer splitAssignments(",");
-    std::vector<std::string> assignments;
-    splitAssignments(s, assignments);
-	
-    Tokenizer splitEq("=");
-	for (size_t i = 0; i < assignments.size(); ++i)
-	{
-		std::vector<std::string> assignment;
-		splitEq(assignments[i], assignment);
-		ASSERT(assignment.size() == 2);
-
-		push_back(make_pair(assignment[0], assignment[1]));
-	}
-}
-
-void FakeODBIterator::ConstParameters::add(const Assignments& ass)
-{
-	Log::debug() << "FakeODBIterator::ConstParameters::add(const Assignments& ass)" << std::endl;
-	for (size_t i = 0; i < ass.size(); ++i)
-	{
-		const Assignment &as = ass[i];
-		std::string columnName = as.first;
-		std::string value = as.second;
-
-		ASSERT(value.size() > 0);
-
-		if (Tool::isInQuotes(value))
-			addString(columnName, Tool::unQuote(value));
-		else if (value.find('.') == std::string::npos)
-			addInteger(columnName, Translator<std::string, long>()(value));
-		else
-			addReal(columnName, Translator<std::string, double>()(value));
-	}
-}
-
-void FakeODBIterator::ConstParameters::addInteger(const std::string& name, long v)
-{
-	Log::info() << "FakeODBIterator::ConstParameters::addInteger: " << name << " = " << v << std::endl;
-	push_back(ConstParameter(name, v, odb::INTEGER));
-}
-
-void FakeODBIterator::ConstParameters::addReal(const std::string& name, double v)
-{
-	Log::info() << "FakeODBIterator::ConstParameters::addReal: " << name << " = " << v << std::endl;
-	push_back(ConstParameter(name, v, odb::REAL));
-}
-
-void FakeODBIterator::ConstParameters::addString(const std::string& name, std::string v)
-{
-	Log::info() << "FakeODBIterator::ConstParameters::addString: " << name << " = '" << v << "'" << std::endl;
-	push_back(ConstParameter(name, Tool::cast_as_double(v), odb::STRING));
-}
-
-FakeODBIterator::FakeODBIterator(const PathName& db, const std::string& sql)
-: iterator_(db, sql),
-  columns_(0),
-  data_(0),
-  constParameters_(FakeODBIterator::ConstParameters::instance())
-{}
-
-FakeODBIterator::~FakeODBIterator()
-{
-	delete [] data_;
-}
-
-odb::MetaData& FakeODBIterator::columns() {
-	if (columns_.size() == 0)
-	{
-		columns_ = iterator_.columns();
-
-		size_t i = constParameters_.size();
-		while (i-- > 0)
-		{
-			std::string name = constParameters_[i].name;
-			odb::ColumnType type = constParameters_[i].type;
-
-			Log::debug() << "FakeODBIterator::columns: i = " << i << ", name=" << name << std::endl;
-
-			odb::Column* col = new odb::Column(columns_);
-			col->name(name);
-			col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
-
-			columns_.insert(columns_.begin(), col);
-		}
-
-	}
-	return columns_;
-}
-
-double* FakeODBIterator::data()
-{
-	if (data_ == 0)
-		data_ = new double[columns_.size()];
-
-	double* trueData = iterator_.data();
-
-	size_t count = constParameters_.size();
-	memcpy(data_ + count, trueData, (columns_.size() - count) * sizeof(double));
-
-	for (size_t i = 0; i < count; ++i)
-		data_[i] = constParameters_[i].value;
-	
-	return data_;
-}
-
-bool FakeODBIterator::isNewDataset()
-{
-	return iterator_.isNewDataset();
-}
-
-bool FakeODBIterator::next(eckit::ExecutionContext* context)
-{
-	bool r = iterator_.next(context);
-	noMore_ = !r;
-	return r;
-}
-
-} // namespace tool 
-} //namespace odb 
-
diff --git a/odb_api/src/odb_api/migrator/FakeODBIterator.h b/odb_api/src/odb_api/migrator/FakeODBIterator.h
deleted file mode 100644
index dacb882..0000000
--- a/odb_api/src/odb_api/migrator/FakeODBIterator.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-/// \file FakeODBIterator.h
-/// @author Piotr Kuchta, ECMWF, March 2009
-
-#ifndef FakeODBIterator_H
-#define FakeODBIterator_H
-
-
-#include <eckit/eckit.h>
-#include "odb_api/MetaData.h"
-#include "odb_api/migrator/ODBIterator.h"
-
-namespace eckit { class PathName; }
-namespace eckit { class ExecutionContext; }
-
-namespace odb {
-namespace tool {
-
-class ODBIterator;
-
-typedef std::pair<std::string, std::string> Assignment;
-typedef std::vector<Assignment> AssignmentsBase;
-
-struct Assignments : public AssignmentsBase {
-	Assignments(const std::string&);
-};
-
-struct ConstParameter {
-	ConstParameter(std::string name, double value, odb::ColumnType type)
-	: name(name), value(value), type(type)
-	{}
-
-	std::string name;
-	double      value;
-	odb::ColumnType  type;
-};
-
-class FakeODBIterator //: public odb::RowsReaderIterator
-{
-public:
-    struct ConstParameters : public std::vector<ConstParameter>
-	{
-		// Not thread safe.
-		static ConstParameters& instance() { return instance_; }
-
-		void addInteger(const std::string& name, long);
-		void addReal(const std::string& name, double);
-		void addString(const std::string& name, std::string value);
-
-		void add(const Assignments&);
-	private:
-		static ConstParameters instance_;
-	};
-
-
-	FakeODBIterator(const eckit::PathName& db, const std::string& sql); 
-	~FakeODBIterator ();
-
-	const FakeODBIterator& end() { return *reinterpret_cast<FakeODBIterator*>(0); }
-	//bool operator!=(const FakeODBIterator& o) { ASSERT(&o == 0); return iterator_ != iterator_.end(); }
-	//FakeODBIterator& operator++() { next(); return *this; }
-
-	odb::MetaData& columns();
-
-	virtual bool isNewDataset();
-	virtual double* data();
-
-//protected:
-	virtual bool next(eckit::ExecutionContext*);
-
-	int refCount_;
-	bool noMore_;
-    eckit::ExecutionContext* context_;
-
-private:
-	ODBIterator iterator_;
-
-	odb::MetaData columns_;
-	double* data_;
-
-	ConstParameters& constParameters_;
-};
-
-} // namespace tool 
-} //namespace odb 
-
-#endif
diff --git a/odb_api/src/odb_api/migrator/ImportODBTool.cc b/odb_api/src/odb_api/migrator/ImportODBTool.cc
deleted file mode 100644
index 0bd0886..0000000
--- a/odb_api/src/odb_api/migrator/ImportODBTool.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include <iostream>
-#include <fstream>
-
-#include "eckit/filesystem/LocalPathName.h"
-#include "eckit/io/FileHandle.h"
-#include "eckit/log/BigNum.h"
-#include "eckit/log/Timer.h"
-#include "odb_api/migrator/ImportODBTool.h"
-#include "odb_api/migrator/ReptypeGenIterator.h"
-#include "odb_api/Comparator.h"
-#include "odb_api/DispatchingWriter.h"
-#include "odb_api/SQLDatabase.h"
-#include "odb_api/SQLInteractiveSession.h"
-#include "odb_api/SchemaAnalyzer.h"
-#include "odb_api/SchemaAnalyzer.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/RowsCounter.h"
-#include "odb_api/tools/ODA2RequestTool.h"
-#include "odb_api/tools/Tool.h"
-#include "odb_api/tools/ToolFactory.h"
-
-extern "C" {
-#include "odbdump.h"
-}
-
-#include "ODBIterator.h"
-#include "FakeODBIterator.h"
-
-namespace odb {
-namespace tool {
-
-typedef std::string str;   // string is a typedef in an ODB header.
-
-template <typename IN>
-ImportODBTool<IN>::ImportODBTool (int argc, char *argv[])
-: Tool(argc, argv),
-  noVerification_ (optionIsSet("-no_verification"))
-{}
-
-template <typename IN>
-ImportODBTool<IN>::ImportODBTool (const CommandLineParser& clp)
-: Tool(clp),
-  noVerification_ (optionIsSet("-no_verification"))
-{}
-
-template <typename IN>
-std::pair<unsigned long long, const std::vector<eckit::PathName> > ImportODBTool<IN>::importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile)
-{    
-    using namespace eckit;
-
-    Timer importingAndDipatching("Importing and dipatching");
-
-    Log::info() << "Importing data from '" << db
-        << "', query is '" << sql << "', into '"
-        << dumpFile << "' template." << std::endl;
-
-    odb::DispatchingWriter writer(dumpFile);
-    odb::DispatchingWriter::iterator w = writer.begin();
-
-    unsigned long long inRowsNumber = saveData<>(w, db, sql);
-
-    std::vector<eckit::PathName> files = (**w).outputFiles();
-    return std::make_pair(inRowsNumber, files);
-}
-
-template <typename IN>
-void ImportODBTool<IN>::validate(const eckit::PathName &db, const std::string& sql, const eckit::PathName& file)
-{
-    eckit::Timer verification("Validating dispatched output");
-
-    odb::Reader odaReader(file);
-    odb::Reader::iterator r(odaReader.begin());
-
-    IN reader(db, sql);
-    typename IN::iterator begin (reader.begin());
-    const typename IN::iterator end (reader.end());
-
-    // don't check missing value as the old ODB is not giving correct info for that some times (e.g.  sortbox)
-    odb::Comparator(false)
-        .compare(begin, end, r, odaReader.end(),
-            std::string("ODB input ") + db, std::string("converted output ") + file);
-}
-
-
-template <typename IN>
-void ImportODBTool<IN>::validateRowsNumber(unsigned long long inRowsNumber, const std::vector<eckit::PathName>& files)
-{
-    using namespace eckit;
-    
-	Timer verification("Validating dispatched output");
-
-	Log::info() << "ImportODBTool::validateRowsNumber: Validating output. " << std::endl;
-	Log::info() << "ImportODBTool::validateRowsNumber: input rows number: " << BigNum(inRowsNumber) << std::endl;
-
-	unsigned long long outRowsNumber (0);
-	unsigned long long outFilesSize (0);
-	for (size_t i = 0; i < files.size(); ++i)
-	{
-		const PathName &fn (files[i]);
-		unsigned long long n (RowsCounter::rowCount(fn));
-		unsigned long long fileSize (fn.size());
-
-		outRowsNumber += n;
-		outFilesSize += fileSize;
-
-		Log::info() << "ImportODBTool::validateRowsNumber: " << fn << ": " << BigNum(n) << " rows, file size: " << BigNum(fileSize) << "." << std::endl;
-	}
-	Log::info() << "ImportODBTool::validateRowsNumber: sum of output rows number: " << BigNum(outRowsNumber) << ", sum of file sizes: " << BigNum(outFilesSize) << std::endl;
-	ASSERT(inRowsNumber == outRowsNumber);
-}
-
-
-template <typename IN>
-void ImportODBTool<IN>::run()
-{
-    using namespace eckit;
-    
-    ASSERT("Wrong number of parameters. odb2oda.cc:main should check this."
-        && !(parameters().size() < 2 || parameters().size() > 4));
-
-    str db (parameters(1));
-    str sql (parameters().size() > 2 && parameters(2) != "." ? readFile(parameters(2)) : "");
-
-    Log::info() << "ImportODBTool::run: sql='" << sql << "'" << std::endl;
-
-    str dumpFile ((parameters().size() > 3) ? parameters(3) : (db + ".odb"));
-    if (dumpFile.substr(dumpFile.size() - 4) != ".odb")
-        dumpFile.append(".odb");
-
-    Log::info() << "Importing data from '" << db << "', query is '" << sql << "', into '" << dumpFile << "'." << std::endl;
-
-    odb::TemplateParameters params;
-    if (odb::TemplateParameters::parse(dumpFile, params).size() != 0)
-    {
-        DispatchResult r (importDispatching(db, sql, dumpFile));
-
-        unsigned long long importedRowsNumber (r.first);
-        const std::vector<eckit::PathName>& outFiles (r.second);
-
-        if (! noVerification_ )
-        {
-            Timer verification("Verification");
-            validateRowsNumber(importedRowsNumber, outFiles);
-        }
-    }
-    else
-    {
-        odb::Writer<> writer(dumpFile);
-        odb::Writer<>::iterator w (writer.begin());
-
-        unsigned long long importedRowsNumber (saveData<>(w, db, sql)); 
-        Log::info() << "Imported " << BigNum(importedRowsNumber) << " row(s)." << std::endl;
-
-        Timer verification("Verification");
-        Log::info() << "Verifying." << std::endl;
-        Log::info() << "Comparing data from: 1) ODB, and 2) ODA" << std::endl;
-
-        if (importedRowsNumber && ! noVerification_) 
-            validate(db, sql, dumpFile);
-    }
-    Log::info() << "ImportODBTool: Finished OK" << std::endl;
-}
-
-template <typename IN>
-template <typename OUT_ITERATOR>
-unsigned long long ImportODBTool<IN>::saveData(OUT_ITERATOR w, eckit::PathName odb, str sql) //, const SchemaAnalyzer &schema)
-{
-    using namespace eckit;
-    
-    Log::info() << "ImportODBTool<IN>::saveData: odb='" << odb << "', sql='" << sql << "'" << std::endl;
-    unsigned long long n (0);
-	try {
-        (**w).property("ODB_DATABASE", odb);
-        IN reader (odb, sql);
-        typename IN::iterator begin (reader.begin());
-        const typename IN::iterator end (reader.end());
-		
-        if (begin->columns().empty())
-        {
-            Log::warning() << "ImportODBTool<IN>::saveData: empty input data set." << std::endl;
-            return 0;
-        }
-
-        n = w->pass1(begin, end);
-        //w->close();
-    } catch (...) {
-        shell("[ -f odbdump.stderr ] && cat odbdump.stderr && cp odbdump.stderr " + odb + ".odb.log || echo odbdump.stderr not found", Here()); 
-        throw;
-    }
-    return n;
-}
-
-
-} // namespace tool 
-} // namespace odb 
-
-
diff --git a/odb_api/src/odb_api/migrator/ImportODBTool.h b/odb_api/src/odb_api/migrator/ImportODBTool.h
deleted file mode 100644
index b444983..0000000
--- a/odb_api/src/odb_api/migrator/ImportODBTool.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#ifndef odb_api_ImportODBTool_H
-#define odb_api_ImportODBTool_H
-
-#include <eckit/eckit.h>
-
-#include "eckit/filesystem/PathName.h"
-#include "odb_api/migrator/OldODBReader.h"
-#include "odb_api/tools/Tool.h"
-
-
-class ODBIterator;
-class CommandLineParser;
-
-
-namespace odb {
-namespace tool {
-
-template <typename IN = odb::tool::OldODBReader>
-class ImportODBTool : public Tool {
-public:
-	ImportODBTool (int argc, char *argv[]); 
-	ImportODBTool (const CommandLineParser&); 
-
-	void run(); 
-
-protected:
-
-	template <typename OUT_ITERATOR>
-	unsigned long long saveData(OUT_ITERATOR w, eckit::PathName odb, std::string sql);
-	
-    typedef std::pair<unsigned long long, const std::vector<eckit::PathName> > DispatchResult;
-
-	DispatchResult importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile);
-
-    void validate(const eckit::PathName& db, const std::string& sql, const eckit::PathName& file);
-    void validateRowsNumber(unsigned long long, const std::vector<eckit::PathName>&);
-
-    void archiveFiles(const std::vector<eckit::PathName>&);
-private:
-
-// No copy allowed
-    ImportODBTool(const ImportODBTool&);
-    ImportODBTool& operator=(const ImportODBTool&);
-
-	bool isECFSPathName(const eckit::PathName fileName);
-	eckit::PathName readFromECFS(const eckit::PathName fileName);
-
-    bool noVerification_;
-};
-
-} // namespace tool 
-} //namespace odb 
-
-#include "ImportODBTool.cc"
-
-#endif 
diff --git a/odb_api/src/odb_api/migrator/MigratorTool.cc b/odb_api/src/odb_api/migrator/MigratorTool.cc
deleted file mode 100644
index 31baefb..0000000
--- a/odb_api/src/odb_api/migrator/MigratorTool.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-/// \file MigratorTool.cc
-///
-/// @author Piotr Kuchta, ECMWF, July 2009
-///
-
-#include <unistd.h>
-#include <iostream>
-#include <fstream>
-
-#include "eckit/parser//StringTools.h"
-
-#include "ecml/core/ExecutionContext.h"
-
-#include "odb_api/migrator/FakeODBIterator.h"
-#include "odb_api/migrator/ImportODBTool.h"
-#include "odb_api/migrator/MigratorTool.h"
-#include "odb_api/migrator/ODB2ODATool.h"
-#include "odb_api/migrator/ODBIterator.h"
-#include "odb_api/migrator/OldODBReader.h"
-#include "odb_api/migrator/ReptypeGenIterator.h"
-#include "odb_api/MDI.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-#include "odb_api/tools/ToolFactory.h"
-#include "odb_api/ODBModule.h"
-
-#include "ODBMigratorModule.h"
-
-using namespace eckit;
-using namespace std;
-
-namespace odb {
-namespace tool {
-
-
-int gdb(const std::vector<std::string>& params)
-{
-    std::cout << "gdb: params: " << params << std::endl;
-	str cmd(params[0]);
-	str args;
-	for (size_t i = 1; i < params.size(); ++i)
-		args += str(" ") + params[i];
-
-    eckit::PathName scriptFile = str(".gdb_") + params[2];
-	if (! scriptFile.exists())
-	{
-		str s = str("file ") + cmd + "\nbreak main\nrun " + args + "\n";
-        s += "catch throw\n";
-        eckit::FileHandle f(scriptFile);
-		f.openForWrite(1024);
-		f.write(s.c_str(), s.size());
-		f.close();
-	}
-	str vi = str("vi ") + scriptFile;
-	std::cout << "Executing '" << vi << "'" << std::endl;
-	system(vi.c_str());
-
-	str gdbCmd = str("gdb -x ") + scriptFile;
-	std::cout << "Executing '" << gdbCmd << "'" << std::endl;
-	return system(gdbCmd.c_str());
-}
-
-// valgrind --log-file=v.log --show-reachable=yes --leak-check=full ./oda test 
-int valgrind(const std::vector<std::string>& params)
-{
-    std::cout << "valgrind: params: " << params << std::endl;
-	str cmd(params[0]);
-	str args;
-	for (size_t i = 1; i < params.size(); ++i)
-		args += str(" ") + params[i];
-
-	str logFile = str("vg.log");
-	str vg = str("valgrind --log-file=") + logFile + " --show-reachable=yes --leak-check=full " + cmd + " " + args;
-	std::cout << "Executing '" << vg << "'" << std::endl;
-	return system(vg.c_str());
-}
-
-//MigratorTool::MigratorTool (int argc, char *argv[]) : Tool(argc, argv) { } 
-
-MigratorTool::MigratorTool (const CommandLineParser &clp) : Tool(clp) { } 
-
-void MigratorTool::runECML()
-{
-    ecml::ExecutionContext context;
-    ODBModule odbModule;
-    ODBMigratorModule migratorModule;
-    context.import(odbModule);
-    context.import(migratorModule);
-
-    std::vector<std::string> params(parameters());
-    params.erase(params.begin());
-    params.erase(params.begin());
-    for (size_t i (0); i < params.size(); ++i)
-    {
-        Log::info() << "*** Executing " << params[i] << endl;
-        context.executeScriptFile(params[i]);
-    }
-
-}
-
-void MigratorTool::run()
-{
-    if (parameters().size() > 1)
-    {
-        if (parameters(1) == "g" || parameters(1) == "vg")
-        {
-            std::vector<std::string> params;
-            for (size_t i(0); i < parameters().size(); ++i)
-                if (i != 1)
-                    params.push_back(parameters()[i]);
-
-            if (parameters(1) == "g")
-                gdb(params);
-            else valgrind(params);
-
-            return;
-        }
-        if (parameters(1) == "ecml")
-            return runECML();
-
-        if (parameters(1) == "test")
-        {
-            //odb::tool::test::TestRunnerApplication(argc(), argv()).start();
-            return; // TODO: Retrieve a status from the test runner
-        }
-    }
-
-    ODB2ODATool odb2oda(*this);
-    odb2oda.run();
-}
-
-} // namespace tool 
-} //namespace odb 
-
diff --git a/odb_api/src/odb_api/migrator/ODB2ODATool.cc b/odb_api/src/odb_api/migrator/ODB2ODATool.cc
deleted file mode 100644
index c82c1f8..0000000
--- a/odb_api/src/odb_api/migrator/ODB2ODATool.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-/// \file ODB2ODATool.cc
-///
-/// @author Piotr Kuchta, ECMWF, July 2009
-///
-
-#include <iostream>
-#include <fstream>
-
-#include "eckit/parser/StringTools.h"
-#include "odb_api/migrator/FakeODBIterator.h"
-#include "odb_api/migrator/ImportODBTool.h"
-#include "odb_api/migrator/ODB2ODATool.h"
-#include "odb_api/migrator/ODBIterator.h"
-#include "odb_api/migrator/OldODBReader.h"
-#include "odb_api/migrator/ReptypeGenIterator.h"
-#include "odb_api/MDI.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-#include "odb_api/tools/ToolFactory.h"
-
-
-using namespace eckit;
-
-namespace odb {
-namespace tool {
-
-ODB2ODATool::ODB2ODATool (int argc, char *argv[])
-: Tool(argc, argv)
-{}
-
-ODB2ODATool::ODB2ODATool (const CommandLineParser &clp)
-: Tool(clp)
-{}
-
-
-/// -mdi <type1:MDI1,type2:MDI2,...>
-void ODB2ODATool::resetMDI(const std::string& s)
-{
-    typedef eckit::StringTools S;
-    std::vector<std::string> columns(S::split(",", s));
-    for (size_t i = 0; i < columns.size(); ++i)
-    {
-        std::vector<std::string> ass(S::split(":", columns[i]));
-
-        if (ass.size() != 2)
-            throw UserError("Error parsing option -mdi");
-
-        const std::string typeName(S::upper(ass[0]));
-        double value(StringTool::translate(ass[1]));
-
-        Log::info() << "  typeName: " << typeName << " value: " << value << std::endl;
-
-        if (typeName == "REAL")
-            odb::MDI::realMDI(value);
-        else if (typeName == "INTEGER" || typeName == "INT")
-            odb::MDI::integerMDI(value);
-        else
-            throw UserError("Changing MDI of types different than INTEGER or REAL not supported yet.");
-    }
-}
-
-void ODB2ODATool::run()
-{
-	if (parameters().size() < 2 || parameters().size() > 4)
-	{
-        std::cerr << "Usage:" << std::endl
-			<< "	" << parameters(0)
-
-            << " [<options>] <odb_database> [<file-with-select-statement-defining-dump> [<output.odb>]]" << std::endl
-
-            << "Options: " << std::endl << std::endl
-
-            << "\t[-genreptype <list-of-columns>]" << std::endl
-            << "\t[-reptypecfg <reptype-generation-config-file>]" << std::endl
-            << "\t[-addcolumns <list-of-assignments>]" << std::endl
-            << "\t[-mdi <type1:MDI1,type2:MDI2,...>]              Provide values of missing data indicators, e.g.: -mdi REAL:2147483647,INTEGER:2147483647" << std::endl
-            << "\t[-no_verification]                              Do not verify the conversion" << std::endl
-
-			<< std::endl;
-		return;
-	}
-
-    std::string nonDefaultMDIS(optionArgument<std::string>("-mdi", ""));
-    if (nonDefaultMDIS.size())
-        Log::info() << "Using non default missing data indicators: " << nonDefaultMDIS << std::endl;
-
-	bool addColumns (optionIsSet("-addcolumns"));
-	if (addColumns)
-		FakeODBIterator::ConstParameters::instance().add(Assignments(optionArgument<std::string>("-addcolumns", "")));
- 
-	bool genReptype (optionIsSet("-genreptype"));
-	bool reptypeCfg (optionIsSet("-reptypecfg"));
-    if (optionIsSet("-mdi"))
-        resetMDI(optionArgument<std::string>("-mdi", ""));
-
-	ASSERT("Only one of -genreptype and -reptypecfg can be choosen at a time." && !(genReptype && reptypeCfg));
-
-	if (genReptype) {
-        std::vector<std::string> columns = StringTools::split(",", optionArgument<std::string>("-genreptype", ""));
-		ReptypeTableConfig::addColumns(columns.begin(), columns.end());
-	}
-
-	if (reptypeCfg) ReptypeTableConfig::load(optionArgument<std::string>("-reptypecfg", ""));
-
-	if (addColumns && (genReptype || reptypeCfg)) {
-		typedef odb::tool::TSQLReader<ReptypeGenIterator<FakeODBIterator> > R;
-		ImportODBTool<R>(*this).run();
-		return;
-	}
-
-	if (addColumns) {
-		ImportODBTool<odb::tool::TSQLReader<FakeODBIterator> >(*this).run();
-		return;
-	}
-
-	if (genReptype || reptypeCfg) {
-		ImportODBTool<odb::tool::TSQLReader<ReptypeGenIterator<ODBIterator> > >(*this).run();
-		return;
-	}
-
-	{	
-		ImportODBTool<odb::tool::OldODBReader>(*this).run();
-		Log::info() << "ImportODBTool<ODBIterator> finished OK" << std::endl;
-	}
-}
-
-} // namespace tool 
-} //namespace odb 
-
diff --git a/odb_api/src/odb_api/migrator/ODBIterator.cc b/odb_api/src/odb_api/migrator/ODBIterator.cc
deleted file mode 100644
index 23243cd..0000000
--- a/odb_api/src/odb_api/migrator/ODBIterator.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-///
-/// \file ODBIterator.cc
-///
-/// @author Piotr Kuchta, Feb 2009
-
-#include <map>
-
-#include "eckit/config/Resource.h"
-#include "eckit/filesystem/PathName.h"
-#include "eckit/parser/StringTools.h"
-#include "odb_api/migrator/ODBIterator.h"
-#include "odb_api/MetaData.h"
-#include "odb_api/SQLDatabase.h"
-#include "odb_api/SQLParser.h"
-#include "odb_api/SQLSelectFactory.h"
-#include "odb_api/StringTool.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-
-
-namespace odb { namespace sql { class SQLInteractiveSession; } }
-
-extern "C" {
-#include "odbdump.h"
-}
-
-using namespace eckit;
-
-namespace odb {
-namespace tool {
-
-//ODBIterator::ODBIterator(const PathName& db, const std::string& sql)
-ODBIterator::ODBIterator(const std::string& db, const std::string& sql)
-: db_(db),
-  odbHandle_(0),
-  noOfColumns_(0),
-  ci_(0),
-  columns_(new odb::MetaData(0, (odb::Column *) 0)),
-  data_(0),
-  nd_(0),
-  schemaParsed_(false),
-  noMore_(true)
-{
-	Log::info() << "ODBIterator::ODBIterator: @" << this << " db=" << db << std::endl;
-
-	const std::string odbDirectory = db; //.asString();
-	Log::info() << "Opening ODB in '" << odbDirectory << "'" << std::endl;
-	if (! PathName(odbDirectory).exists())
-        throw CantOpenFile(odbDirectory);
-	
-	std::string select = sql.size() ? sql : defaultSQL(db);
-
-	ASSERT(select.size() != 0 && select != "");
-
-	const std::string dbPath = db; //.asString();
-	const char *db_path = dbPath.c_str();
-	const char *sql_select = select.c_str();
-
-	Log::info() << "ODBIterator::ODBIterator: Calling odbdump_open(\"" << db_path << "\",\"" << sql_select << "\", NULL, NULL, NULL, &" << nd_ << ")" << std::endl;
-
-	odbHandle_ = odbdump_open(db_path, sql_select, NULL, NULL, NULL, &nd_);
-	ASSERT("odbdump_open returned NULL" && odbHandle_);
-	ASSERT("odbdump_open returned nd_ <= 0" && nd_ > 0);
-
-	data_ = new double[nd_];
-
-	//next();
-	//if (noMore_) Log::warning() << "ODBIterator::ODBIterator: result set empty, no data." << std::endl;
-}
-
-bool ODBIterator::next(eckit::ExecutionContext*)
-{
-	newDataset_ = false;
-	noOfColumns_ = odbdump_nextrow(odbHandle_, data_, nd_, &newDataset_);
-	if (noOfColumns_ == 0)
-	{
-		return !(noMore_ = true);
-	}
-
-	if (newDataset_)
-	{
-		Log::info() << "ODBIterator::readRow: new data set" << std::endl;
-		createColumns();
-	}
-
-	ASSERT(noOfColumns_ <= nd_);
-    // FIXME: read the missing values for a given constant from somewhere
-	// This is because sometime ODB has MISSING_VALUE_REAL in INTEGER columns...
-	// for example station_type at hdr in ECMA.conv
-	for (int i = 0; i < noOfColumns_; ++i)
-		if ((*columns_)[i]->type() == odb::INTEGER && data_[i] == odb::MDI::realMDI())
-			data_[i] = odb::MDI::integerMDI();
-
-	return !(noMore_ = false);
-}
-
-void ODBIterator::createColumns()
-{
-	Log::debug() << " => ODBIterator::createColumns: " << std::endl;
-
-	delete columns_;
-	columns_ = new odb::MetaData(noOfColumns_, (odb::Column *) 0);
-
-	bool preservePrecision = Resource<bool>("$ODB2ODA_PRESERVE_PRECISION", false);
-	
-	ci_ = (colinfo_t *) odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
-	int nci = 0;
-	ci_ = (colinfo_t *) odbdump_create_colinfo(odbHandle_, &nci); 
-
-    std::map<std::string, std::string> truenames;
-	for (int i = 0; i < noOfColumns_; i++)
-	{
-		colinfo_t *pci = &((colinfo_t *) ci_)[i];
-		std::string name = pci->nickname ? pci->nickname : pci->name;
-        truenames[name] = pci->name;
-
-		odb::ColumnType type = odb::REAL;
-		double missing = odb::MDI::integerMDI(); 
-
-		switch(pci->dtnum)
-		{
-			case DATATYPE_REAL4:
-				type = odb::REAL;
-				missing = odb::MDI::realMDI(); 
-				break;
-
-			case DATATYPE_REAL8:
-				type = preservePrecision ? odb::DOUBLE : odb::REAL;
-				missing = odb::MDI::realMDI(); 
-				break;
-
-			case DATATYPE_STRING:
-				type = odb::STRING;
-				break;
-
-			case DATATYPE_INT4:
-			case DATATYPE_YYYYMMDD:
-			case DATATYPE_HHMMSS:
-				type = odb::INTEGER;
-				break;
-
-			case DATATYPE_BITFIELD:
-				type = odb::BITFIELD;
-				break;
-
-			default:
-				Log::error() << "Unsupported type: [" << pci->type_name << "] " << name
-							<< std::endl;
-				break;
-		}
-		setColumn(i, name, type, missing);
-	}
-	getSchema(db_).updateBitfieldsDefs(columns(), truenames);
-	Log::debug() << " <= ODBIterator::createColumns: " << std::endl;
-}
-
-void ODBIterator::destroy()
-{
-	Log::debug() << "ODBIterator::destroy: @" << this << std::endl;
-	odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
-	odbdump_close(odbHandle_);
-	delete columns_;
-	delete [] data_;
-}
-
-ODBIterator::~ODBIterator ()
-{
-	Log::info() << "ODBIterator::~ODBIterator: @" << this << std::endl;
-	destroy();
-}
-
-odb::MetaData& ODBIterator::columns() { return *columns_; }
-
-double* ODBIterator::data() { return data_; }
-
-bool ODBIterator::isNewDataset() { return newDataset_; }
-
-int ODBIterator::setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue)
-{
-	//Log::debug() << "ODBIterator::setColumn: " << index << ", " << name << ", " << columnTypeName(type) << ", " << missingValue << std::endl;
-
-	ASSERT(int(index) < noOfColumns_);
-	ASSERT(columns_);
-	odb::Column* col = (*columns_)[index];
-	delete col;
-	col = new odb::Column(*columns_);
-	ASSERT(col);
-
-	col->name(name); 
-	col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
-	col->missingValue(missingValue);
-
-	(*columns_)[index] = col;
-	return 0;
-}
-
-
-//const char* defaultSQL = "select {!/LINK/} from hdr,body,errstat";
-PathName ODBIterator::schemaFile(const PathName db)
-{
-    Log::info() << "ODBIterator::schemaFile: db=" << db << std::endl;
-
-	std::string d = db;
-
-	if (d[d.size() - 1] != '/')
-		d += "//";
-
-	std::string s = StringTools::split(".", StringTools::split("//", d).back())[0];
-
-	return d + s + ".sch";
-}
-
-const odb::sql::SchemaAnalyzer& ODBIterator::getSchema(const PathName& db)
-{
-	//odb::sql::SQLSelectFactory::instance().config(); //odb::sql::SQLOutputConfig());
-	// FIXME: this is not good cause when you call the method several times with different db it will fail...
-	// It's not used like that at the moment, anyway. So perhaps I should make db a member (db_).
-	if (!schemaParsed_)
-	{
-		PathName schemaFile = this->schemaFile(db);
-		Log::info() << "ImportODBTool::getSchema: parsing '" << schemaFile << "'" << std::endl;
-	
-		odb::sql::SQLParser p;
-		p.parseString(session_, StringTool::readFile(schemaFile), static_cast<DataHandle*>(0), session_.selectFactory().config());
-		schemaParsed_ = true;
-	}
-
-	return session_
-			.currentDatabase()
-			.schemaAnalyzer();
-}
-
-std::string ODBIterator::defaultSQL(const PathName& db)
-{
-	return getSchema(db).generateSELECT();
-}
-
-} // namespace tool 
-} //namespace odb 
-
diff --git a/odb_api/src/odb_api/migrator/ODBIterator.h b/odb_api/src/odb_api/migrator/ODBIterator.h
deleted file mode 100644
index b6dfdda..0000000
--- a/odb_api/src/odb_api/migrator/ODBIterator.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#ifndef ODBIterator_H
-#define ODBIterator_H
-
-#include "eckit/filesystem/PathName.h"
-#include "odb_api/SQLInteractiveSession.h"
-#include "odb_api/ColumnType.h"
-
-namespace eckit { class PathName; }
-namespace eckit { class ExecutionContext; }
-
-namespace odb { namespace sql { class SchemaAnalyzer; class SQLInteractiveSession; } }
-
-namespace odb {
-
-class MetaData;
-
-namespace tool {
-
-class ODBIterator 
-{
-public:
-    ODBIterator(const std::string& db, const std::string& sql); 
-    ~ODBIterator ();
-
-    void destroy();
-
-    const ODBIterator& end() { return *reinterpret_cast<ODBIterator*>(0); }
-
-    bool operator!=(const ODBIterator& o) { return hasNext_; }
-
-    ODBIterator& operator++() { next(context_); return *this; }
-
-    odb::MetaData& columns();
-
-    virtual bool isNewDataset();
-    virtual double* data();
-
-    static eckit::PathName schemaFile(const eckit::PathName db);
-
-    virtual bool next(eckit::ExecutionContext*);
-
-protected:
-    int setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue);
-
-private:
-    void createColumns();
-
-    eckit::PathName db_;
-
-    void *odbHandle_;
-    int noOfColumns_;
-    //colinfo_t *ci_;
-    void *ci_;
-    odb::MetaData *columns_;
-    int newDataset_;
-    double* data_;
-    int nd_;
-    unsigned long long count_;
-    bool hasNext_;
-
-    std::string defaultSQL(const eckit::PathName& db);
-    const odb::sql::SchemaAnalyzer& getSchema(const eckit::PathName& db);
-    bool schemaParsed_;
-    odb::sql::SQLInteractiveSession session_;
-
-    friend class FakeODBIterator;
-public:
-    int refCount_;
-    bool noMore_;
-    eckit::ExecutionContext* context_;
-};
-
-} // namespace tool 
-} // namespace odb 
-
-#endif
diff --git a/odb_api/src/odb_api/migrator/OldODBReader.h b/odb_api/src/odb_api/migrator/OldODBReader.h
deleted file mode 100644
index d1355bc..0000000
--- a/odb_api/src/odb_api/migrator/OldODBReader.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#ifndef odb_api_OldODBReader_H
-#define odb_api_OldODBReader_H
-
-#include "odb_api/migrator/TSQLReader.h"
-#include "odb_api/migrator/ODBIterator.h"
-
-namespace odb {
-namespace tool {
-
-typedef odb::tool::TSQLReader<ODBIterator> OldODBReader;
-
-} // namespace tool 
-} // namespace odb 
-
-#endif
diff --git a/odb_api/src/odb_api/migrator/ReptypeGenIterator.cc b/odb_api/src/odb_api/migrator/ReptypeGenIterator.cc
deleted file mode 100644
index 05e3c4b..0000000
--- a/odb_api/src/odb_api/migrator/ReptypeGenIterator.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-///
-/// \file ReptypeGenIterator.cc
-///
-/// @author Piotr Kuchta, Feb 2009
-
-#include <strings.h>
-
-extern "C" {
-#include "odbdump.h"
-}
-
-#include "eckit/parser/StringTools.h"
-#include "eckit/parser/Tokenizer.h"
-#include "eckit/types/Types.h"
-#include "eckit/utils/Translator.h"
-#include "odb_api/migrator/FakeODBIterator.h"
-#include "odb_api/migrator/ODBIterator.h"
-#include "odb_api/migrator/ReptypeGenIterator.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-
-
-using namespace eckit;
-
-namespace odb {
-namespace tool {
-
-std::ostream& operator<<(std::ostream& s, const ReptypeTable& m)
-{
-	s << "{";
-	for (ReptypeTable::const_iterator it = m.begin(); it != m.end(); ++it)
-	{
-		s << "[";
-		const Values& vals = it->first;
-		for (Values::const_iterator i = vals.begin(); i != vals.end(); ++i)
-			s << *i;
-		s << "]";
-
-		s << " : " << it->second << "," << std::endl;
-	}
-	s << "}";
-	return s;
-}
-
-/*
-Hi Peter,
-
-most of the columns given by Manuel do not exist yet.
-
-As a first attempt, you can use
-sensor at hdr,
-satname_1 at hdr,
-satname_2 at hdr,
-satname_3 at hdr,
-satname_4 at hdr,
-bufrtype at hdr,
-subtype at hdr,
-obstype at hdr,
-codetype at hdr
-(when sat.len > 0 you can add satid at sat).
-
-Anne. 
-*/
-
-std::vector<std::string> ReptypeTableConfig::columns_ = std::vector<std::string>();
-ReptypeTable ReptypeTableConfig::reptypeTable_ = ReptypeTable();
-
-void ReptypeTableConfig::load(const PathName& fileName)
-{
-	std::string s = Tool::readFile(fileName, false);
-	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << std::endl;
-	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << "'" << s << "'" << std::endl;
-
-    std::vector<std::string> lines = StringTools::split("\n", s);
-
-	size_t i = 0;
-	while (lines[i] == "")
-		++i;
-
-    std::vector<std::string> firstLine = StringTools::split(":", lines[i]);
-	ASSERT(firstLine[0] == "reptype");
-
-    std::vector<std::string> columnNames = StringTools::split(",", firstLine[1]);
-	std::for_each(columnNames.begin(), columnNames.end(), Tool::trimInPlace);
-
-	columns_.insert(columns_.end(), columnNames.begin(), columnNames.end());
-	++i;
-
-    for (; i < lines.size(); ++i)
-    {
-        std::vector<std::string> lr;
-        Tokenizer(":")(lines[i], lr);
-
-        // Skip empty lines.
-        if (lr.size() == 0) continue;
-
-		ASSERT(lr.size() == 2);
-
-		int reptype_value = Translator<std::string, int>()(lr[0]);
-
-        std::vector<std::string> rvalues = StringTools::split(",", lr[1]);
-		//Log::debug() << "ReptypeTableConfig::load: rvalues = " << rvalues << std::endl;
-
-		ASSERT("Number of values must be equal to number of column names (first line)"
-			&& columnNames.size() == rvalues.size());
-
-		std::for_each(rvalues.begin(), rvalues.end(), Tool::trimInPlace);
-		Values vals;
-		Log::debug() << "ReptypeTableConfig::load: " << reptype_value << " = ";
-		for (size_t j = 0; j < rvalues.size(); ++j)
-		{
-			std::string &vs(rvalues[j]);
-
-			Log::debug() << "{" << vs << ":" << Tool::isInQuotes(vs) << "}";
-			double v = Tool::isInQuotes(vs)
-				? Tool::cast_as_double(Tool::unQuote(vs))
-				: Translator<std::string, double>()(vs);
-			vals.push_back(v);
-			Log::debug() << "[" << rvalues[j] << "] '" << Tool::double_as_string(v) << "', " << std::endl;
-		}
-		Log::debug() << std::endl;
-		//at(vals) = reptype_value;
-		reptypeTable_[vals] = reptype_value;
-	}
-
-	//Log::debug() << "ReptypeTableConfig::load: columns_ = " << columns_ << std::endl; 
-	//Log::debug() << "ReptypeTableConfig::load: reptypeTable_ = " << reptypeTable_ << std::endl;
-}
-
-template<typename ITERATOR, typename CONFIG>
-ReptypeGenIterator<ITERATOR, CONFIG>::ReptypeGenIterator(const PathName& db, const std::string& sql)
-: iterator_(db, sql),
-  data_(0),
-  reptypeTable_(CONFIG::reptypeTable())
-{
-	odb::MetaData &md = iterator_.columns();
-	data_ = new double[md.size()];
-	reptypeIndex_ = md.columnIndex("reptype");
-
-	const std::vector<std::string>& columnNames = CONFIG::columns();
-	for (std::vector<std::string>::const_iterator i = columnNames.begin(); i != columnNames.end(); ++i)
-	{
-		std::string name = *i;
-
-		Log::debug() << "ReptypeGenIterator<ITERATOR>::ctor: " << name << std::endl;
-
-		indices_.push_back(iterator_.columns().columnIndex(name));
-		values_.push_back(0);
-	}
-	Log::debug() << "ReptypeGenIterator::ReptypeGenIterator: Reptype table:" << std::endl;
-	Log::debug() << "reptypeTable_ = " << reptypeTable_ << std::endl;
-}
-
-template<typename ITERATOR, typename CONFIG>
-ReptypeGenIterator<ITERATOR, CONFIG>::~ReptypeGenIterator()
-{
-	Log::debug() << "ReptypeGenIterator::~ReptypeGenIterator: Reptype table:" << std::endl;
-	Log::debug() << "reptypeTable_.size() = " << reptypeTable_.size() << std::endl;
-	Log::debug() << "reptypeTable_ =" << reptypeTable_ << std::endl;
-	delete [] data_;
-}
-
-template<typename ITERATOR, typename CONFIG>
-odb::MetaData& ReptypeGenIterator<ITERATOR, CONFIG>::columns()
-{
-	return iterator_.columns();
-}
-
-template<typename ITERATOR, typename CONFIG>
-double* ReptypeGenIterator<ITERATOR, CONFIG>::data()
-{
-	return data_;
-}
-
-template<typename ITERATOR, typename CONFIG>
-bool ReptypeGenIterator<ITERATOR, CONFIG>::isNewDataset()
-{
-	return iterator_.isNewDataset();
-}
-
-template<typename ITERATOR, typename CONFIG>
-bool ReptypeGenIterator<ITERATOR, CONFIG>::next(eckit::ExecutionContext* context)
-{
-	bool r = iterator_.next(context);
-	if (r)
-	{
-		double* trueData = iterator_.data();
-
-        std::copy(trueData, trueData + iterator_.columns().size(), data_);
-
-		for (size_t i = 0; i < indices_.size(); ++i)
-			values_[i] = data_[indices_[i]];
-
-		ReptypeTable::const_iterator it = reptypeTable_.find(values_); 
-		if (it != reptypeTable_.end())
-			data_[reptypeIndex_] = it->second;
-		else
-		{
-			// TODO: rethink!
-			Log::info() << "ReptypeGenIterator::next(): No matching report type, creating new one." << std::endl;
-
-			size_t newRT = reptypeTable_.size();
-			for (ReptypeTable::const_iterator i = reptypeTable_.begin(); i != reptypeTable_.end(); ++i)
-			{
-				size_t rt = i->second;
-				if (newRT <= rt)
-					newRT = rt + 1;
-			}
-
-			Log::info() << "ReptypeGenIterator::next(): New report type: " << newRT << std::endl;
-
-			data_[reptypeIndex_] = reptypeTable_[values_] = newRT;
-		}
-	}
-	noMore_ = !r;
-	return r;
-}
-
-template class ReptypeGenIterator<>;
-template class ReptypeGenIterator<FakeODBIterator>;
-
-} // namespace tool 
-} // namespace odb 
-
diff --git a/odb_api/src/odb_api/migrator/migrator_api.cc b/odb_api/src/odb_api/migrator/migrator_api.cc
deleted file mode 100644
index cd92930..0000000
--- a/odb_api/src/odb_api/migrator/migrator_api.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include "odb_api/migrator/ImportODBTool.h"
-#include "odb_api/migrator/migrator_api.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/odbcapi.h"
-#include "odb_api/tools/Tool.h"
-
-
-namespace odb {
-namespace tool {
-
-int import_odb_with_sql_in_file(const char* odb_database, const char* sql_file, const char* output_file)
-{
-    try {
-        const char *argv[] = {"importodb",  odb_database, sql_file, output_file, 0 };
-        odb_start_with_args(1, const_cast<char **>(argv));
-        ImportODBTool<> importer(4, const_cast<char **>(argv));
-        importer.run();
-        return 0;
-    } catch (...) {
-        return 1;
-    }
-}
-
-
-} // namespace tool 
-} //namespace odb 
-
-
diff --git a/odb_api/src/odb_api/migrator/odb2oda.cc b/odb_api/src/odb_api/migrator/odb2oda.cc
deleted file mode 100755
index d457f27..0000000
--- a/odb_api/src/odb_api/migrator/odb2oda.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * © Copyright 1996-2012 ECMWF.
- * 
- * This software is licensed under the terms of the Apache Licence Version 2.0
- * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
- * In applying this licence, ECMWF does not waive the privileges and immunities 
- * granted to it by virtue of its status as an intergovernmental organisation nor
- * does it submit to any jurisdiction.
- */
-
-#include "eckit/filesystem/PathName.h"
-#include "eckit/io/FileHandle.h"
-#include "odb_api/migrator/FakeODBIterator.h"
-#include "odb_api/migrator/MigratorTool.h"
-#include "odb_api/migrator/ODB2ODATool.h"
-#include "odb_api/migrator/ODBIterator.h"
-#include "odb_api/migrator/ReptypeGenIterator.h"
-#include "odb_api/odb_api.h"
-#include "odb_api/tools/Tool.h"
-#include "odb_api/tools/ToolFactory.h"
-#include "odb_api/tools/ToolRunnerApplication.h"
-
-
-using namespace std;
-using namespace odb::tool;
-
-// Cannot use just string for str because of a clash with a typedef in ODB header...
-typedef std::string str;
-
-int gdb(int argc, char *argv[]);
-int valgrind(int argc, char *argv[]);
-
-//void test_schemaFile();
-
-int main(int argc, char *argv[])
-{
-    CommandLineParser clp(argc, argv);
-	clp.registerOptionWithArgument("-genreptype");
-    clp.registerOptionWithArgument("-reptypecfg");
-    clp.registerOptionWithArgument("-addcolumns");
-    clp.registerOptionWithArgument("-mdi");
-    clp.parameters();
-
-    cout << clp << std::endl;
-
-	ToolRunnerApplication runner(argc, argv, false, false);
-	//ToolRunnerApplication runner(clp, false, false);
-	MigratorTool migrator(clp);
-	runner.tool(&migrator);
-	return runner.start();
-}
-
-#if 0
-#include <assert.h>
-
-void test_schemaFile() {
-	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ECMA.tmi") == "/asdfasd/sdfas/ECMA.tmi/ECMA.sch");
-	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
-	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi/") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
-	assert(ODBIterator::schemaFile("ODA.tmi/") == "ODA.tmi/ODA.sch");
-	assert(ODBIterator::schemaFile("ODA.tmi") == "ODA.tmi/ODA.sch");
-	assert(ODBIterator::schemaFile("dupa/ODA.tmi") == "dupa/ODA.tmi/ODA.sch");
-}
-#endif 
-
-
diff --git a/odb_api/src/odb_api/odb2_to_odb1/CMakeLists.txt b/odb_api/src/odb_api/odb2_to_odb1/CMakeLists.txt
deleted file mode 100644
index 4bbacc7..0000000
--- a/odb_api/src/odb_api/odb2_to_odb1/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-ecbuild_add_executable(TARGET odb2_to_odb1.x
-    INCLUDES ${ODB_INCLUDE_DIRS} ${ODB_INCLUDE_DIRS}/../module 
-    SOURCES
-              Odb2Odb1.cc
-              Odb2Odb1.h
-              Odb2Odb1Main.cc
-              mpi_wrapper.F90
-              mpif.h
-              odb_wrapper.F90
-              odbi.F90
-
-    LIBS      Odb_fortran Odb eckit ${ODB_LIBRARIES}
-
-    CONDITION HAVE_FORTRAN AND ODB_FOUND)
-
-if(HAVE_FORTRAN AND ODB_FOUND)
-    include(odb_link_schemas)
-    odb_link_schemas(odb2_to_odb1.x ${ODB_SCHEMAS})
-endif()
diff --git a/odb_api/src/odb_api/odb2_to_odb1/odb_wrapper.F90 b/odb_api/src/odb_api/odb2_to_odb1/odb_wrapper.F90
deleted file mode 100644
index 746f95f..0000000
--- a/odb_api/src/odb_api/odb2_to_odb1/odb_wrapper.F90
+++ /dev/null
@@ -1,753 +0,0 @@
-!> @file   odb_wrapper.F90
-!> @author Anne Fouilloux
-
-!----------------------------------------------------------------------
-function odb_no_of_local_pools_c(handle) bind(C, name="odb_no_of_local_pools_f90")
-  use, intrinsic :: iso_c_binding
-  use            :: odb_module
-
-  implicit none
-
-  integer(C_INT),VALUE                :: handle
-  integer(C_INT)                      :: odb_no_of_local_pools_c
-
-  integer(kind=JPIM)                  :: f90_handle
-  integer(kind=JPIM)                  :: f90_nmypools
-
-  f90_handle = handle
-
-  f90_nmypools = ODB_poolinfo(f90_handle)
-
-  odb_no_of_local_pools_c = f90_nmypools
-
-end function odb_no_of_local_pools_c
-!----------------------------------------------------------------------
-function odb_get_local_pools_c(handle, local_pools) bind(C, name="odb_get_local_pools_f90")
-  use, intrinsic :: iso_c_binding
-  use            :: odb_module
-
-  implicit none
-
-  type, bind(c) :: c_int_array
-    integer(C_INT)                     :: len
-    type(C_PTR)                        :: array
-  end type c_int_array
-
-  integer(C_INT),VALUE                :: handle
-  integer(C_INT)                      :: odb_get_local_pools_c
-  type(c_int_array), intent(out)      :: local_pools
-  integer(C_INT), pointer             :: c_local_pools(:)
-
-  integer(kind=JPIM)                  :: f90_handle
-  integer(kind=JPIM)                  :: f90_nmypools
-
-  f90_handle = handle
-
-  call C_F_POINTER(local_pools%array, c_local_pools, (/local_pools%len/))
-
-  f90_nmypools = ODB_poolinfo(f90_handle, c_local_pools)
-
-  odb_get_local_pools_c = f90_nmypools
-
-end function odb_get_local_pools_c
-!----------------------------------------------------------------------
-function odb_open_c(dbname, dbname_length, mode, mode_length, npools) bind(C, name="odb_open_f90")
-  use, intrinsic :: iso_c_binding
-  use            :: odb_module
-  use mpl_module
-
-  implicit none
-
-  character(kind=C_CHAR), dimension(*) :: dbname
-  character(kind=C_CHAR), dimension(*) :: mode
-  integer(C_INT)                       :: npools
-  integer(C_INT),VALUE                 :: dbname_length
-  integer(C_INT),VALUE                 :: mode_length
-  integer(C_INT)                       :: odb_open_c
-
-  character(len=64)                    :: f90_dbname
-  character(len=64)                    :: f90_mode
-  integer(kind=JPIM)                   :: f90_npools
-  integer(kind=JPIM)                   :: f90_handle
-  integer(kind=JPIM)                   :: f90_rc
-  integer(kind=JPIM)                   :: i
-
-
-  f90_npools = npools
-  f90_dbname=""
-  do i=1, dbname_length
-    if (dbname(i) .eq. C_NULL_CHAR) exit
-    f90_dbname(i:i)  = dbname(i)
-  end do
-  f90_mode=""
-  do i=1, mode_length
-    if (mode(i) .eq. C_NULL_CHAR) exit
-    f90_mode(i:i)  = mode(i)
-  end do
-
-  f90_handle = ODB_open(f90_dbname, f90_mode, f90_npools)
-  odb_open_c = f90_handle
-! write flag files
-  call cODB_print_flags_file(f90_dbname, MPL_MYRANK(), f90_rc)
-end function odb_open_c
-!----------------------------------------------------------------------
-function odb_close_c(handle, save) bind(C, name="odb_close_f90")
-  use, intrinsic                      :: iso_c_binding
-  use odb_module
-
-  implicit none
-
-  integer(C_INT),VALUE                :: handle
-  logical(C_BOOL), VALUE              :: save
-  integer(C_INT)                      :: odb_close_c
-
-  logical                             :: f90_save
-  integer(kind=JPIM)                  :: f90_handle
-  integer(kind=JPIM)                  :: f90_err
-
-  f90_save = save
-  f90_handle = handle
-  write(0,*) 'ODB_close f90_save = ', f90_save, ' f90_handle = ', f90_handle
-  f90_err = ODB_close(f90_handle, f90_save)
-  odb_close_c = f90_err
-end function odb_close_c
-!----------------------------------------------------------------------
-function odb_swapout_c(handle, dtname, dtname_length, poolno, save, repack) bind(C, name="odb_swapout_f90")
-  use, intrinsic                      :: iso_c_binding
-  use odb_module
-
-  implicit none
-
-  integer(C_INT),VALUE                 :: handle
-  character(kind=C_CHAR), dimension(*) :: dtname
-  integer(C_INT),VALUE                 :: dtname_length
-  integer(C_INT),VALUE                 :: poolno
-  logical(C_BOOL), VALUE               :: save
-  logical(C_BOOL), VALUE               :: repack
-  integer(C_INT)                       :: odb_swapout_c
-
-  integer(kind=JPIM)                   :: f90_poolno
-  integer(kind=JPIM)                   :: f90_handle
-  character(len=64)                    :: f90_dtname
-  logical                              :: f90_save, f90_repack
-  integer(kind=JPIM)                   :: i
-  integer(kind=JPIM)                   :: rc
-
-  f90_dtname=""
-  do i=1, dtname_length
-    if (dtname(i) .eq. C_NULL_CHAR) exit
-    f90_dtname(i:i)  = dtname(i)
-  end do
-
-  f90_handle = handle
-  f90_poolno = poolno
-  f90_save = save
-  f90_repack = repack
-
-  rc = ODB_swapout(f90_handle, f90_dtname, poolno=f90_poolno, save=f90_save, repack=f90_repack)
-
-  odb_swapout_c = rc
-end function odb_swapout_c
-!----------------------------------------------------------------------
-function odb_get_no_of_columns_c(handle, dtname, dtname_length) bind(C, name="odb_get_no_of_columns_f90")
-  use, intrinsic                      :: iso_c_binding
-  use odb_module
-
-  implicit none
-
-  integer(C_INT), VALUE                :: handle
-  character(kind=C_CHAR), dimension(*) :: dtname
-  integer(C_INT),VALUE                 :: dtname_length
-  integer(C_INT)                       :: odb_get_no_of_columns_c
-
-  integer(kind=JPIM)                   :: f90_ncols
-  integer(kind=JPIM)                   :: f90_handle
-  character(len=64)                    :: f90_dtname
-  integer(kind=JPIM)                   :: i, at_offset
-
-  if (dtname(1) /= '@') then
-    at_offset = 1
-    f90_dtname='@'
-  else
-    at_offset=0
-    f90_dtname=""
-  endif
-  do i=1, dtname_length
-    if (dtname(i) .eq. C_NULL_CHAR) exit
-    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
-  end do
-
-  f90_handle = handle
-  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
-  odb_get_no_of_columns_c = f90_ncols
-end function odb_get_no_of_columns_c
-!----------------------------------------------------------------------
-subroutine odb_api_get_colnames(odb_iterator, colnames, c_ncols, idx_seqno, masterKey)
-  use, intrinsic                      :: iso_c_binding
-  use odb_module
-  use odb_c_binding
-
-  implicit none
-
-  TYPE(C_PTR)                               :: odb_iterator
-  character(len=maxvarlen), dimension(*)    :: colnames
-  integer(kind=C_INT)                       :: c_ncols
-  integer(kind=JPIM), intent(out)           :: idx_seqno
-  character(len=maxvarlen)                  :: masterKey
-
-  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
-
-  type(C_PTR)                                   :: ptr_colname
-  integer(kind=C_INT)                           :: cerr, size_name
-  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
-  character(len=256)                            :: colname
-
-    idx_seqno =-1
-
-    do i=1, c_ncols
-      ptr_colname = C_NULL_PTR
-      colname(:) = ""
-      cerr = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
-      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
-      do j=1, size_name
-       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
-       colname(j:j)  = f_ptr_colname(j)
-      end do
-      at_idx = index(colname, '@')
-      if (at_idx > 0) then
-        colnames(i) = colname(:at_idx-1)
-      else
-        colnames(i) = colname
-      endif
-      if (trim(colnames(i)) .eq. masterKey) then
-        idx_seqno = i
-      endif
-    enddo
-end subroutine odb_api_get_colnames
-!----------------------------------------------------------------------
-function odb_create_index_c(handle, dtname, dtname_length, odb_iterator, &
-                            idx_odb, idx_size ) bind(C, name="odb_create_index_f90")
-  use, intrinsic                      :: iso_c_binding
-  use odb_module
-  use odb_c_binding
-
-  implicit none
-
-  integer(C_INT), VALUE                :: handle
-  character(kind=C_CHAR), dimension(*) :: dtname
-  integer(C_INT),VALUE                 :: dtname_length
-  TYPE(C_PTR)                          :: odb_iterator
-  integer(kind=C_INT), dimension(*)    :: idx_odb
-  integer(C_INT),VALUE                 :: idx_size
-  integer(kind=C_INT)                  :: odb_create_index_c
-
-  integer(kind=JPIM)                   :: f90_ncols
-  integer(kind=JPIM)                   :: f90_handle
-  character(len=64)                    :: f90_dtname
-  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
-
-  INTEGER(kind=C_INT)                  :: c_ncols
-
-  type(C_PTR)                                   :: ptr_colname
-  integer(kind=C_INT)                           :: size_name
-  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
-  character(len=256)                            :: coltable, colname, temp(1)
-  integer(kind=JPIM)                            :: f90_idx(1)
-  integer(kind=JPIM)                            :: rc
-
-
-
-  odb_create_index_c = 0
-  if (dtname(1) /= '@') then
-    at_offset = 1
-    f90_dtname='@'
-  else
-    at_offset=0
-    f90_dtname=""
-  endif
-  do i=1, dtname_length
-    if (dtname(i) .eq. C_NULL_CHAR) exit
-    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
-  end do
-
-  f90_handle = handle
-  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
-
-  odb_create_index_c = odb_read_get_no_of_columns(odb_iterator, c_ncols)
-
-  if (idx_size == c_ncols) then
-    do i=1, c_ncols
-      odb_create_index_c = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
-      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
-      do j=1, size_name
-       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
-       colname(j:j)  = f_ptr_colname(j)
-      end do
-      at_idx = index(colname, '@')
-      if (at_idx > 0) then
-        temp(1) = colname(:at_idx-1)
-        coltable = colname(at_idx:)
-
-      else
-        temp(1) = colname
-        coltable=""
-      endif
-      f90_idx=-1
-      if (trim(coltable) == trim(f90_dtname)) then
-
-      rc = ODB_varindex(f90_handle, f90_dtname, temp, f90_idx)
-      if (f90_idx(1) > 0) then
-        idx_odb(i)  = f90_idx(1)
-      endif
-      endif
-    enddo
-  endif
-
-end function odb_create_index_c
-!----------------------------------------------------------------------
-function ODB_whatis(colname, flaglist)
-  use, intrinsic                       :: iso_c_binding
-  use odb_module
-
-  implicit none
-  character(len=*), intent(in)    :: colname
-  type(C_PTR),        intent(in)  :: flaglist
-  integer(kind=JPIM)              :: ODB_whatis
-  integer(kind=JPIM)              :: idx_l, idx_r, i
-  integer(kind=C_INT)             :: c_whatis, typeOfTable
-  character(kind=C_CHAR),dimension(257)  :: c_colname
-
-  ODB_whatis = ODB_NMDI
-
-  c_colname(:)=' '
-  do i=1,len(trim(colname))
-    c_colname(i) = colname(i:i)
-  enddo
-  c_colname(i+1) = C_NULL_CHAR
-  c_whatis = typeOfTable(c_colname, flaglist)
-  ODB_whatis = c_whatis
-  !write(0,*) 'ODB_whatis = ', trim(colname), ' ' ,  ODB_whatis
-end function ODB_whatis
-!----------------------------------------------------------------------
-subroutine odb_fill_c(handle, filename, odb_hdr_array, odb_body_array, flaglist, c_masterKey, c_len, np) bind(C, name="odb_fill_f90")
-  use, intrinsic                       :: iso_c_binding
-  use odb_module
-  use odb_c_binding
-  use odbi
-
-  implicit none
-
-  type, bind(c) :: c_int_array
-    integer(C_INT)                     :: len
-    type(C_PTR)                        :: array
-  end type c_int_array
-
-  interface
-     function ODB_whatis(colname, flaglist)
-       use, intrinsic :: iso_c_binding
-       use odb_module
-
-       implicit none
-       character(len=*), intent(in)    :: colname
-       type(C_PTR), intent(in)         :: flaglist
-       integer(kind=JPIM)              :: ODB_whatis
-     end function ODB_whatis
-  end interface
-
-
-  integer(C_INT), VALUE                  :: handle
-  character(kind=C_CHAR), dimension(*)   :: filename
-  character(kind=C_CHAR), dimension(*)   :: c_masterKey
-  type(C_PTR), intent(in)                :: flaglist
-  integer(C_INT),VALUE                   :: c_len, np
-
-  type(c_int_array), intent(in)          :: odb_hdr_array
-  type(c_int_array), intent(inout)       :: odb_body_array
-  integer(kind=JPIM)                     :: f90_handle
-  integer(kind=JPIM)                     :: f90_np
-
-  character(len=256), allocatable        :: tablenames(:)
-  type(t_odbtable), allocatable          :: odbtables(:)
-  integer(kind=JPIM)                     :: ntables
-  integer(kind=JPIM)                     :: rc, i, j, f90_nrows, f90_ncols
-  integer(kind=JPIM)                     :: idx_seqno, ihdr, ibody
-  character(len=maxvarlen)               :: masterKey, cltable
-  integer(C_INT), pointer                :: c_odb_hdr_array(:)
-  integer(C_INT), pointer                :: c_odb_body_array(:)
-
-  type(C_PTR)                                            :: odb_handler, odb_it
-  character(kind=C_CHAR, len=64)                         :: config = C_NULL_CHAR
-  integer(kind=C_INT)                                    :: cerr, new_dataset, ncols
-  logical                                                :: LLfirstdataset, LLindexNotdone
-  real(kind=C_DOUBLE), dimension(:), allocatable         :: one_row
-  character(len=maxvarlen), allocatable                  :: colnames_in(:)
-  character(len=64)                                      :: f90_filename
-  integer(kind=JPIM)                                     :: previous_seqno
-
-  f90_filename=""
-  do i=1, maxvarlen
-    if (filename(i) .eq. C_NULL_CHAR) exit
-    f90_filename(i:i)  = filename(i)
-  end do
-
-
-  masterKey=""
-  do i=1, c_len
-    if (c_masterKey(i) .eq. C_NULL_CHAR) exit
-    masterKey(i:i)  = c_masterKey(i)
-  end do
-
-! associate c_odb_hdr_array with an array allocated and filled in C++
-  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
-  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
-
-  write(0,*) 'masterKey= ', trim(masterKey)
-  write(0,*) 'number of BODY entries = ', odb_body_array%len
-  write(0,*) 'number of HDR entries = ', odb_hdr_array%len
-  f90_handle = handle
-  f90_np = np
-
-  ntables = ODB_getnames(f90_handle, '*', 'table')
-  allocate(tablenames(ntables))
-  ntables = ODB_getnames(f90_handle, '*', 'table', tablenames)
-  allocate(odbtables(ntables))
-  odbtables(:)%table_kind = -1
-  do j=1,ntables
-    NULLIFY(odbtables(j)%data)
-    NULLIFY(odbtables(j)%index)
-    NULLIFY(odbtables(j)%colnames)
-    odbtables(j)%table_kind = ODB_whatis(trim(tablenames(j)), flaglist)
-    if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .or. odbtables(j)%table_kind  == ODB_BODY_ALIGNED) then
-      odbtables(j)%tablename = trim(tablenames(j))
-      cltable = odbtables(j)%tablename
-      f90_ncols = ODB_getnames(f90_handle,cltable,'name')
-      allocate(odbtables(j)%colnames(f90_ncols))
-      rc = ODB_getnames(f90_handle,cltable,'name', outnames=odbtables(j)%colnames)
-!*AF      write(0,*) trim(cltable), 'f90_ncols = ', f90_ncols
-      if (odbtables(j)%table_kind  == ODB_HDR_ALIGNED) then
-        allocate(odbtables(j)%data(int(odb_hdr_array%len),0:f90_ncols))
-      else
-        allocate(odbtables(j)%data(int(odb_body_array%len),0:f90_ncols))
-      endif
-      odbtables(j)%data(:,:) = 0.0
-    endif
-  enddo
-
-! start to read the input file
-  LLfirstdataset=.true.
-  LLindexNotdone=.true.
-  ihdr=1
-  ibody=1
-!*AF  write(0,*) 'LLfirstdataset=.true. ', LLfirstdataset, ' LLindexNotdone= ', LLindexNotdone
-  odb_handler = odb_read_new(config, cerr)
-  odb_it = odb_read_iterator_new(odb_handler, filename, cerr);
-  cerr = odb_read_get_no_of_columns(odb_it, ncols)
-  if (allocated(one_row)) deallocate(one_row)
-  allocate(one_row(ncols))
-
-  previous_seqno = -1
-  do while (odb_read_get_next_row(odb_it, ncols, one_row, new_dataset) == 0)
-    LLindexNotdone = (new_dataset > 0) .or. LLfirstdataset
-    if (LLindexNotDone) then
-      LLfirstdataset = .false.
-! we must compute the list of index in ODB-1 valid in the current ODB-2 one_row
-      allocate(colnames_in(ncols))
-      colnames_in(:) = ""
-      call odb_api_get_colnames(odb_it, colnames_in, ncols, idx_seqno, masterKey)
-!*AF      do j=1, ncols
-!*AF        write(0,*) 'colnames_in (odb-api) (', j,')= ', trim(colnames_in(j))
-!*AF      enddo
-      do j=1, ntables
-        if (odbtables(j)%table_kind > 0) then
-          allocate(odbtables(j)%index(ncols))
-          rc = ODB_varindex(f90_handle,odbtables(j)%tablename , colnames_in, odbtables(j)%index)
-          !write(0,*) 'table = ', trim(odbtables(j)%tablename), ' ', odbtables(j)%index
-        endif
-      enddo
-
-      deallocate(colnames_in)
-
-!*AF      write(0,*) 'new_dataset'
-    endif
-    do j=1, ntables
-      if (odbtables(j)%table_kind > 0) then
-       do i=1, ncols
-         if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .and. &
-             one_row(idx_seqno) /= previous_seqno &
-             .and. odbtables(j)%index(i) > 0) then
-           !write(0,*) one_row(idx_seqno), c_odb_hdr_array(ihdr), ihdr, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
-           odbtables(j)%data(ihdr, odbtables(j)%index(i)) = one_row(i)
-         else if (odbtables(j)%table_kind == ODB_BODY_ALIGNED .and. &
-             odbtables(j)%index(i) > 0) then
-           !write(0,*) ibody, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
-           odbtables(j)%data(ibody, odbtables(j)%index(i)) = one_row(i)
-         endif
-       enddo
-      endif
-    enddo
-    c_odb_body_array(ibody) = one_row(idx_seqno)
-    ibody = ibody + 1
-    if (one_row(idx_seqno) /= previous_seqno) then
-      previous_seqno = c_odb_hdr_array(ihdr)
-      ihdr = ihdr + 1
-    endif
-  enddo
-  if (allocated(one_row)) deallocate(one_row)
-  cerr = odb_read_iterator_delete(odb_it)
-  cerr = odb_read_delete(odb_handler)
-! deallocation
- do j=1,ntables
-    if (odbtables(j)%table_kind > 0) then
-     f90_nrows = size(odbtables(j)%data,1)
-     f90_ncols = size(odbtables(j)%data,2)
-!*AF     write(0,*) 'ODB_put ', trim(odbtables(j)%tablename), f90_nrows, f90_ncols, f90_np
-     !do i=1, f90_nrows
-     !  write(*,*) i, 'row ', odbtables(j)%data(i,:)
-     !enddo
-     rc = ODB_put(f90_handle, odbtables(j)%tablename, odbtables(j)%data, &
-        f90_nrows, f90_ncols, poolno = f90_np)
-    endif
-    if (associated(odbtables(j)%data)) deallocate(odbtables(j)%data)
-    if (associated(odbtables(j)%index)) deallocate(odbtables(j)%index)
-    if (associated(odbtables(j)%colnames)) deallocate(odbtables(j)%colnames)
- enddo
- deallocate(odbtables)
- deallocate(tablenames)
-end subroutine odb_fill_c
-!----------------------------------------------------------------------
-function odb_put_one_row_c(handle, dtname, dtname_length, odb_row, idx_odb, ncols, np) bind(C, name="odb_put_one_row_f90")
-  use, intrinsic                       :: iso_c_binding
-  use odb_module
-  use odb_c_binding
-
-  implicit none
-
-  integer(C_INT), VALUE                :: handle
-  character(kind=C_CHAR), dimension(*) :: dtname
-  integer(C_INT),VALUE                 :: dtname_length
-  real(kind=C_DOUBLE), dimension(*)    :: odb_row
-  integer(kind=C_INT), dimension(*)    :: idx_odb
-  integer(C_INT),VALUE                 :: ncols
-  integer(C_INT),VALUE                 :: np
-  integer(kind=C_INT)                  :: odb_put_one_row_c
-
-  integer(kind=JPIM)                   :: f90_ncols
-  integer(kind=JPIM)                   :: f90_handle
-  integer(kind=JPIM)                   :: f90_np
-  character(len=64)                    :: f90_dtname
-  integer(kind=JPIM)                   :: i, at_offset
-  integer(kind=JPIM)                   :: nrows
-  real(kind=JPRB), allocatable         :: f90_one_row(:,:)
-
-  odb_put_one_row_c = 0
-  nrows = 1
-
-  if (dtname(1) /= '@') then
-    at_offset = 1
-    f90_dtname='@'
-  else
-    at_offset=0
-    f90_dtname=""
-  endif
-  do i=1, dtname_length
-    if (dtname(i) .eq. C_NULL_CHAR) exit
-    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
-  end do
-
-  f90_handle = handle
-  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
-
-  f90_np = np
-  allocate(f90_one_row(nrows,0:f90_ncols))
-
-  f90_one_row=0
-  do i=1, ncols
-    f90_one_row(1,idx_odb(i)) = odb_row(i)
-  enddo
-
-  odb_put_one_row_c = ODB_put(f90_handle, f90_dtname, f90_one_row, nrows, f90_ncols, poolno = f90_np)
-  deallocate(f90_one_row)
-
-end function odb_put_one_row_c
-!----------------------------------------------------------------------
-subroutine compute_links(ilink, c_odb_len_array)
-  use, intrinsic :: iso_c_binding
-  use            :: odb_module
-
-  implicit none
-
-  integer(C_INT), intent(in)         :: c_odb_len_array(:)
-  integer(KIND=JPIM), intent(inout)    :: ilink(:)
-
-  integer(kind=JPIM)          :: i, j
-  integer(kind=JPIM)          :: previous_seqno, bodylen
-
-  !write(0,*) 'Size of ilink = ', size(ilink, dim=1), size(c_odb_len_array, dim=1)
-
-  if (size(ilink, dim=1) == size(c_odb_len_array, dim=1)) then
-    ilink=1
-  else
-    ilink=-1
-    previous_seqno = c_odb_len_array(1)
-    bodylen=0
-    j=1
-    do i=1, size(c_odb_len_array, dim=1)
-!*AF      write(0,*) 'previous_seqno = ', previous_seqno, ' seqno = ', c_odb_len_array(i)
-      if (previous_seqno /= c_odb_len_array(i)) then
-! we have a different seqno so we can set the len of the previous body part
-        ilink(j) = bodylen
-!*AF        write(0,*) 'ilink(', j, ')=', ilink(j)
-        bodylen=0
-        j = j+1
-        previous_seqno = c_odb_len_array(i)
-      endif
-      bodylen = bodylen + 1
-    enddo
-    if (previous_seqno == c_odb_len_array(size(c_odb_len_array, dim=1))) ilink(j) = bodylen
-  endif
-end subroutine compute_links
-!----------------------------------------------------------------------
-function odb_update_links_c(handle, dtname, dtname_length, poolno, odb_hdr_array, odb_body_array, flaglist) bind(C, name="odb_update_links_f90")
-  use, intrinsic :: iso_c_binding
-  use            :: odb_module
-
-  implicit none
-
-  interface
-    subroutine compute_links(ilink, c_odb_len_array)
-      use, intrinsic :: iso_c_binding
-      use            :: odb_module
-      integer(C_INT), intent(in)         :: c_odb_len_array(:)
-      integer(KIND=JPIM), intent(inout)  :: ilink(:)
-     end subroutine compute_links
-
-     function ODB_whatis(colname, flaglist)
-       use, intrinsic :: iso_c_binding
-       use odb_module
-
-       implicit none
-       character(len=*), intent(in)    :: colname
-       type(C_PTR), intent(in)  :: flaglist
-       integer(kind=JPIM)              :: ODB_whatis
-     end function ODB_whatis
-  end interface
-
-  type, bind(c) :: c_int_array
-    integer(C_INT)                     :: len
-    type(C_PTR)                        :: array
-  end type c_int_array
-
-  type(C_PTR), intent(in)              :: flaglist
-  integer(C_INT),VALUE                 :: handle
-  character(kind=C_CHAR), dimension(*) :: dtname
-  integer(C_INT),VALUE                 :: dtname_length
-  integer(C_INT),VALUE                 :: poolno
-  type(c_int_array), intent(in)        :: odb_hdr_array
-  type(c_int_array), intent(in)        :: odb_body_array
-  integer(C_INT)                       :: odb_update_links_c
-
-  integer(C_INT), pointer              :: c_odb_hdr_array(:)
-  integer(C_INT), pointer              :: c_odb_body_array(:)
-
-  character(len=64)                    :: f90_dtname
-  integer(kind=JPIM)                   :: f90_poolno
-  integer(kind=JPIM)                   :: f90_handle
-  integer(kind=JPIM)                   :: i, j
-  integer(kind=JPIM)                   :: rc
-  integer(kind=JPIM)                   :: nrows, ncols, nra
-  character(len=256), allocatable      :: colnames(:)
-  integer(kind=JPIM), allocatable      :: col_aligned(:)
-  character(len=256)                   :: colname
-  real(KIND=JPRB), allocatable         :: x(:,:)
-  integer(KIND=JPIM), allocatable      :: ilink_hdr(:)
-  integer(KIND=JPIM), allocatable      :: ilink_body(:)
-  integer(kind=JPIM)                   :: ioffset_hdr
-  integer(kind=JPIM)                   :: ioffset_body
-
-  odb_update_links_c = 0
-
-! associate c_odb_hdr_array with an array allocated and filled in C++
-  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
-
-! associate c_odb_body_array with an array allocated and filled in C++
-  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
-
-  f90_handle = handle
-  f90_poolno = poolno
-  f90_dtname=""
-  do i=1, dtname_length
-    if (dtname(i) .eq. C_NULL_CHAR) exit
-    f90_dtname(i:i)  = dtname(i)
-  end do
-
-
-  rc = ODB_addview(f90_handle, f90_dtname, abort = .false.)
-  write(0,*) 'rc = ', rc, 'odb_update_links_c f90_handle = ', f90_handle, ' f90_poolno = ', f90_poolno, &
-             ' f90_dtname = ', trim(f90_dtname), ' odb_hdr_array.len = ',size(c_odb_hdr_array), &
-             ' odb_body_array.len = ',size(c_odb_body_array)
-
-  if (rc > 0) then
-! this SQL is registered and we can fecth data from ODB
-    rc = ODB_select(f90_handle,f90_dtname,nrows,ncols,nra=nra,poolno=f90_poolno)
-!*AF    write(0,*) 'odb_update_links_c ', trim(f90_dtname), ' nrows = ', nrows, ' ncols = ', ncols
-    if (nrows > 0) then
-      ALLOCATE(x(nra,0:ncols))
-      ALLOCATE(ilink_hdr(nrows))
-      ALLOCATE(ilink_body(nrows))
-      ALLOCATE(colnames(ncols))
-      ALLOCATE(col_aligned(ncols))
-      rc = ODB_get(f90_handle,f90_dtname,x,nrows,ncols,poolno=f90_poolno)
-      call compute_links(ilink_hdr, c_odb_hdr_array)
-      call compute_links(ilink_body, c_odb_body_array)
-      rc = ODB_getnames(f90_handle, f90_dtname, 'name', colnames)
-      col_aligned(:)=ODB_NMDI
-      do j=1, ncols
-        colname = trim(colnames(j))
-        if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
-           col_aligned(j) = ODB_whatis(colname, flaglist) ! offset
-           col_aligned(j+1) = col_aligned(j)              ! len
-        endif
-      enddo
-
-      ioffset_hdr = 0
-      ioffset_body = 0
-       ! write(0,*) 'nrows = ', nrows, ' ncols = ', ncols
-      do i=1, nrows
-        do j=1, ncols
-          colname = trim(colnames(j))
-          if (len(colname) > 7 .and. colname(1:7) == 'LINKLEN') then
-             if (col_aligned(j) == ODB_HDR_ALIGNED) then
-               x(i,j) = ilink_hdr(i)
-             else if (col_aligned(j)  == ODB_BODY_ALIGNED) then
-               x(i,j) = ilink_body(i)
-             else
-               x(i,j) = 0
-             endif
-          else if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
-             if (col_aligned(j)  == ODB_HDR_ALIGNED) then
-               x(i,j) = ioffset_hdr
-             else if (col_aligned(j) == ODB_BODY_ALIGNED) then
-               x(i,j) = ioffset_body
-             else
-               x(i,j) = 0
-             endif
-          endif
-        enddo
-        ioffset_hdr = ioffset_hdr + ilink_hdr(i)
-        ioffset_body = ioffset_body + ilink_body(i)
-      enddo
-      rc = ODB_put(f90_handle,f90_dtname,x, nrows,ncols,poolno=f90_poolno)
-      DEALLOCATE(x)
-      DEALLOCATE(ilink_hdr)
-      DEALLOCATE(ilink_body)
-      DEALLOCATE(colnames)
-      DEALLOCATE(col_aligned)
-    endif
-    rc = ODB_cancel(f90_handle,f90_dtname,poolno=f90_poolno)
-  else
-   write(0,*) '******Warning: retrieval ', trim(f90_dtname), ' is not registered'
-  endif
-
-end function odb_update_links_c
-
-!----------------------------------------------------------------------
diff --git a/odb_api/src/odb_api/odb2_to_odb1/odbi.F90 b/odb_api/src/odb_api/odb2_to_odb1/odbi.F90
deleted file mode 100644
index 39cc31b..0000000
--- a/odb_api/src/odb_api/odb2_to_odb1/odbi.F90
+++ /dev/null
@@ -1,286 +0,0 @@
-!> @file   odbi.F90
-!> @author Anne Fouilloux
-
-module odbi
-
-  use iso_c_binding
-  use odb_c_binding
-  use odb_module
-  USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
-
-  implicit none
-  integer, parameter :: MAX_STRING=1024
-  integer, parameter :: ODB_MAX_ENTRYNO = 1000
-  integer, parameter :: ODB_MAX_ROWS = 100000
-
-  type t_odbtable
-    character(len=maxvarlen)                         :: tablename
-    integer(kind=JPIM)                               :: table_kind
-    real(kind=JPRB), pointer                         :: data(:,:)
-    character(len=MAX_STRING), dimension(:), pointer :: colnames
-    integer(kind=JPIM), dimension(:), pointer        :: index
-  end type t_odbtable
-  type t_bufr2odb
-    logical                                          :: LLcreate_odb_header
-    type(C_PTR)                                      :: c_handle
-    type(C_PTR)                                      :: c_odb_it
-    integer(kind=JPIM)                               :: handle
-    integer(kind=C_INT)                              :: c_ncolumns
-    character(len=MAX_STRING), dimension(:), pointer :: ODBcolname
-    integer(kind=JPIM), dimension(:), pointer        :: ODBcoltype
-    integer(kind=JPIM)                               :: nrows
-  end type t_bufr2odb
-
-  type t_odb2odb1
-    character(len=MAX_STRING)              :: tablename
-    logical                                :: aligned_header
-    logical                                :: aligned_body
-    integer(kind=JPIM), pointer            :: ODB1index(:)
-    character(len=MAX_STRING), pointer     :: colnames(:)
-    logical, pointer                       :: col_is_len(:)
-    logical, pointer                       :: child_is_body(:)
-    type(t_odb2odb1), pointer              :: next
-  end type t_odb2odb1
-
-
-  type relative
-     integer(kind=JPIM)                                   :: idx     ! index dans dbinfo%tables
-     type(relative), pointer                              :: next
-  end type relative
-
-  type tableinfo
-     character(len=MAX_STRING)                            :: ODBtablename  ! ODB table name @table i.e. contains "@"
-     integer(JPIM)                                        :: ODBncols      ! number of ODB columns
-     character(len=MAX_STRING), dimension(:), allocatable :: ODBcolname
-     character(len=MAX_STRING), dimension(:), allocatable :: ODBtypename
-     integer(kind=JPIM), dimension(:), allocatable        :: ODB2ODAindex
-     integer(kind=JPIM)                                   :: ODAncols  ! if 0 it means this table is not present in ODA
-     real(kind=JPRB), dimension(:,:), allocatable         :: ODBrow
-     real(kind=JPRB), dimension(:), allocatable           :: ODBonerow
-     integer(kind=JPIM)                                   :: ODBnrows
-     integer(kind=JPIM)                                   :: nchildren
-     logical                                              :: cut ! true if we need to cut
-     logical                                              :: done ! true if already proceeded
-     logical                                              :: ODBwrite ! true if we need to write in ODB
-     integer(kind=JPIM)                                   :: len_idx ! index in ODBcol of LEN
-     integer(kind=JPIM)                                   :: offset_idx ! index in ODBcol of OFFSET
-     type(relative), pointer                              :: child
-     type(relative), pointer                              :: aligned
-     type(relative), pointer                              :: onelooper
-     type(relative), pointer                              :: parent
-  end type tableinfo
-
-  type dbinfo
-     character(len=MAX_STRING)                  :: dbname
-     integer(kind = JPIM)                       :: handle
-     integer(kind = JPIM)                       :: ntables
-     integer(kind = JPIM)                       :: npools
-     integer(kind = JPIM)                       :: current_poolno
-     integer(kind = JPIM)                       :: current_seqno
-     integer(kind = JPIM)                       :: idx_seqno ! idx in ODA
-     integer(kind = JPIM)                       :: ODAncols ! total number of columns in ODA; can be less or greater than the number of column in ODB
-     character(len=MAX_STRING), dimension(:), allocatable :: ODAcolname
-     real(kind=JPRB)                            :: mdi
-     integer(kind=JPIM)                         :: master       ! root table (desc)
-     type(tableinfo), dimension(:), allocatable :: tables
-  end type dbinfo
-
-contains
-function get_coltype(khandle, colnames, types, ftntypes, one_colname, itype) RESULT(idx_col)
-  implicit none
-  INTEGER(KIND=JPIM), intent(in)         :: khandle
-  character(len=*),intent(in)           :: colnames(:)
-  character(len=maxvarlen), intent(in)  :: types(:), ftntypes(:)
-  character(len=*), intent(in)          :: one_colname
-  integer(kind=C_INT), intent(out)      :: itype
-
-  integer(kind=JPIM)                    :: idx_col, jc
-  real(kind=JPRB)                       :: mdi
-
-  REAL(KIND=JPRB)                       :: ZHOOK_HANDLE
-
-  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',0,ZHOOK_HANDLE)
-  mdi = abs(ODB_getval(khandle, '$mdi'))
-
-  idx_col = -1
-  do jc=1, size(colnames)
-    if (trim(colnames(jc)) == trim(one_colname)) then
-      idx_col = jc
-      exit
-    endif
-  end do
-
-  if ( ftntypes(idx_col)(1:7) == 'REAL(8)' .and.&
-  &       types(idx_col)(1:7) == 'string ' ) then
-      itype = ODB_STRING
-  else if ( ftntypes(idx_col)(1:7) == 'CHAR(8)') then ! a future extension
-      itype = ODB_STRING
-  else if (ftntypes(idx_col)(1:5) == 'REAL(') then
-      itype = ODB_REAL
-  else if (ftntypes(idx_col)(1:8) == 'INTEGER(' .and. &
-  &           types(idx_col)(1:8) == 'Bitfield') then
-      itype = ODB_BITFIELD
-  else if (ftntypes(idx_col)(1:8) == 'INTEGER(') then
-      itype = ODB_INTEGER
-  else
-      itype = ODB_INTEGER
-  endif
-  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',1,ZHOOK_HANDLE)
-end function get_coltype
-SUBROUTINE odb_bitfield_definition(khandle, coln, bnames, bsizes)
-implicit none
-INTEGER(KIND=JPIM), intent(in)        :: khandle
-character(len=*), intent(in)          :: coln
-character(len=*), intent(out)         :: bnames, bsizes
-character(len=maxvarlen)              :: tablename
-integer(kind=jpim)                    :: nextnames, rc, jj, jg
-character(len=maxvarlen), allocatable :: extnames(:), exttypes(:)
-
-integer(kind=jpim)                    :: idx_at, idx_at_ext
-REAL(KIND=JPRB)                       :: ZHOOK_HANDLE
-
-IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',0,ZHOOK_HANDLE)
-
-idx_at = index(coln,'@')
-tablename= coln(idx_at:)
-nextnames = ODB_getnames(khandle, trim(tablename),'extname')
-allocate(extnames(nextnames))
-allocate(exttypes(nextnames))
-
-rc = ODB_getnames(khandle, trim(tablename),'extname', extnames(1:nextnames))
-rc = ODB_getnames(khandle, trim(tablename),'exttype', exttypes(1:nextnames))
-
-jj=1
-
-
-do while (extnames(jj)(1:idx_at) /= coln(1:idx_at-1)//'.')
-  jj=jj+1
-enddo
-bnames=""
-bsizes=""
-
-do jg=jj,nextnames
-  if  (extnames(jg)(1:idx_at-1) /= coln(1:idx_at-1)) exit
-
-  idx_at_ext = index(extnames(jg),'@')
-  bnames=trim(bnames)//extnames(jg)(idx_at+1:idx_at_ext-1)//':'
-  bsizes=trim(bsizes)//trim(exttypes(jg)(4:))//':'
-enddo
-
-deallocate(extnames)
-deallocate(exttypes)
-
-IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',1,ZHOOK_HANDLE)
-
-END SUBROUTINE odb_bitfield_definition
-
-subroutine create_header_table(b2o_info, jc, tablename, list_cols)
- use, intrinsic :: iso_c_binding
- use odb_c_binding
-!*AF use varindex_module
-
-implicit none
- type(t_bufr2odb), intent(inout)             :: b2o_info
- integer(kind=JPIM), intent(inout)           :: jc
- character(len=maxvarlen), intent(in)        :: tablename
- character(len=64) , dimension(:),intent(in) :: list_cols
-
- integer(kind=C_INT)                    :: cerr
- integer(kind=JPIM)                     :: jj
- integer(kind=JPIM)                     :: rc
- integer(kind=JPIM)                     :: idx_col
- integer(kind=JPIM)                     :: ncolumns
- integer(kind=C_INT)                    :: itype
- character(len=maxvarlen)               :: bitfield_names, bitfield_sizes
- character(len=maxvarlen)               :: full_colname
- character(len=maxvarlen), allocatable  :: types(:), ftntypes(:)
- character(len=maxvarlen), allocatable  :: colnames(:)
- REAL(KIND=JPRB)                        :: ZHOOK_HANDLE
-
-
-  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',0,ZHOOK_HANDLE)
-  ncolumns = ODB_getnames(b2o_info%handle,tablename,'name')
-  allocate(colnames(ncolumns))
-  rc = ODB_getnames(b2o_info%handle,tablename,'name',colnames)
-  allocate(types(ncolumns))
-  allocate(ftntypes(ncolumns))
-  rc = ODB_getnames(b2o_info%handle, tablename,'type', types(1:ncolumns))
-  rc = ODB_getnames(b2o_info%handle, tablename,'ftntype', ftntypes(1:ncolumns))
-  do jj=1, size(list_cols)
-    full_colname = trim(list_cols(jj))//trim(tablename)
-    idx_col = get_coltype(b2o_info%handle, colnames, types, ftntypes, full_colname, itype)
-
-!*AF    write(0,*) 'column = ', trim(list_cols(jj)), itype
-    if (itype /= ODB_BITFIELD) then
-      if (len(list_cols(jj)) > 10 .and. list_cols(jj)(1:10) == 'linkoffset') then
-! change linkoffset by linken because linkoffset will be recomputed
-           full_colname(1:10) = '   linklen'
-      endif
-      full_colname = trim(adjustl(full_colname))
-      b2o_info%ODBcolname(jc+1) = full_colname
-      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
-      b2o_info%ODBcoltype(jc+1) = itype
-      cerr = odb_write_set_column(b2o_info%c_odb_it, jc, itype, full_colname)
-    else
-      full_colname = trim(adjustl(full_colname))
-      b2o_info%ODBcolname(jc+1) = full_colname
-      b2o_info%ODBcoltype(jc+1) = itype
-      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
-      call odb_bitfield_definition(b2o_info%handle,full_colname, bitfield_names, bitfield_sizes)
-      bitfield_names=trim(bitfield_names)//C_NULL_CHAR
-      bitfield_sizes=trim(bitfield_sizes)//C_NULL_CHAR
-      cerr = odb_write_set_bitfield(b2o_info%c_odb_it, jc, itype, full_colname, bitfield_names, bitfield_sizes)
-    endif
-    jc = jc + 1
-  enddo
-  deallocate(colnames)
-  deallocate(types)
-  deallocate(ftntypes)
-  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',1,ZHOOK_HANDLE)
-end subroutine create_header_table
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-subroutine init_one_row(b2o_info, one_row)
-implicit none
-
- type(t_bufr2odb), intent(inout)             :: b2o_info
- real(kind=C_DOUBLE), intent(inout)          :: one_row(:)
-
- integer(kind=JPIM)                          :: i
- character(len=8)                            :: csgn=""
- REAL(KIND=JPRB)                             :: str_real8
- real(kind=JPRB)                             :: mdi
-
-
- mdi = abs(ODB_getval(b2o_info%handle, '$mdi'))
- do i=1, b2o_info%c_ncolumns
-   select case (b2o_info%ODBcoltype(i))
-      case(ODB_BITFIELD)
-        one_row(i) = 0
-      case(ODB_INTEGER)
-        if (b2o_info%ODBcolname(i)(1:4) == 'link' .or. &
-            b2o_info%ODBcolname(i)(1:4) == 'LINK') then
-
-            one_row(i) = 0
-        else
-          one_row(i) = mdi
-        endif
-      case(ODB_REAL)
-        one_row(i) = -mdi
-      case(ODB_STRING)
-        one_row(i) = transfer(csgn,str_real8)
-    end select
- enddo
-
-end subroutine init_one_row
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-subroutine delete_header_table(b2o_info)
-implicit none
-
- type(t_bufr2odb), intent(inout)             :: b2o_info
-
- if (associated(b2o_info%ODBcolname)) deallocate(b2o_info%ODBcolname)
- if (associated(b2o_info%ODBcoltype)) deallocate(b2o_info%ODBcoltype)
-end subroutine delete_header_table
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-end module odbi
diff --git a/odb_api/src/odb_api/tools/CMakeLists.txt b/odb_api/src/odb_api/tools/CMakeLists.txt
index 419c86d..dc11bf6 100644
--- a/odb_api/src/odb_api/tools/CMakeLists.txt
+++ b/odb_api/src/odb_api/tools/CMakeLists.txt
@@ -52,8 +52,6 @@ list( APPEND odbtest_src_files
 Examples.cc
 CAPIExamples.cc
 UnitTests.cc
-TestAAAImportODB.cc
-TestAAAImportODBDispatching.cc
 TestAggregateFunctions.cc
 TestAggregateFunctions.sql
 TestAggregateFunctions2.cc
diff --git a/odb_api/src/odb_api/tools/ODA2RequestTool.cc b/odb_api/src/odb_api/tools/ODA2RequestTool.cc
index 5452671..fa2f631 100755
--- a/odb_api/src/odb_api/tools/ODA2RequestTool.cc
+++ b/odb_api/src/odb_api/tools/ODA2RequestTool.cc
@@ -87,8 +87,7 @@ void ODA2RequestTool::run()
 
 PathName ODA2RequestTool::config()
 {
-	string ODB_API_HOME = Resource<std::string>("$ODB_API_HOME", "/usr/local/lib/metaps/lib/odalib/current");
-	return optionArgument("-c", ODB_API_HOME + "//etc//ODA2RequestTool.cfg");
+    return optionArgument("-c", std::string("~odb_api/codes/ODA2RequestTool.cfg"));
 }
 
 void ODA2RequestTool::readConfig() { readConfig(config()); }
diff --git a/odb_api/src/odb_api_config.h.in b/odb_api/src/odb_api_config.h.in
index eeb2706..842d76a 100644
--- a/odb_api/src/odb_api_config.h.in
+++ b/odb_api/src/odb_api_config.h.in
@@ -13,4 +13,6 @@
 #define ODB_API_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
 #define ODB_API_BINARY_DIR     "@CMAKE_BINARY_DIR@"
 
+#define ODB_API_GIT_SHA1       "@ODB_API_GIT_SHA1@"
+
 #endif // odb_api_config_h
diff --git a/odb_api/tests/CMakeLists.txt b/odb_api/tests/CMakeLists.txt
index 327c8d4..fda45aa 100644
--- a/odb_api/tests/CMakeLists.txt
+++ b/odb_api/tests/CMakeLists.txt
@@ -1,12 +1,5 @@
 ### test data files
 
-list( APPEND test_migrator_data_files
-2000010106.old.ECMA.tar.gz )
-
-ecbuild_get_test_multidata( TARGET get_migrator_test_data
-                            #DIRNAME odb_api/tests
-                            NAMES ${test_migrator_data_files}
-                            NOCHECK )
 
 list( APPEND test_data_files
 2000010106.odb.gz
@@ -52,11 +45,6 @@ ecbuild_get_test_multidata( TARGET get_odb_api_test_data
 
 ### list tests
 
-list( APPEND odb_migrator_tests
-#Test_AAAImportODB
-#Test_AAAImportODBDispatching
-)
-
 list( APPEND odb_api_tests
 Test_AggregateFunctions
 Test_AggregateFunctions2
@@ -286,34 +274,6 @@ set( test_environment_multithreaded
     OMP_NUM_THREADS=16
 )
 
-### migrator tests
-
-set( _prev_test get_migrator_test_data )
-foreach( _test ${odb_migrator_tests} )
-  ecbuild_add_test( TARGET     ${_test}
-                    COMMAND    ${odb_bin}
-                    ARGS       ${_test}
-                    CONDITION  HAVE_MIGRATOR
-                    ENVIRONMENT ${test_environment} ${ODB_ENVIRONMENT}
-                    LABELS       odb_api odb_api_migrator
-                    TEST_DEPENDS ${_prev_test} )
-  set( _prev_test ${_test} )
-endforeach()
-
-### odb2_to_odb1 tests
-
-ecbuild_get_test_multidata( TARGET get_odb2_to_odb1_data NAMES odb2_to_odb1.ECMA.conv.tar.gz NOCHECK )
-
-ecbuild_add_test( TARGET test_odb2_to_odb1
-    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_odb2_to_odb1.sh
-    ENVIRONMENT ${test_environment} ${ODB_ENVIRONMENT}
-        PATH=${CMAKE_BINARY_DIR}/bin:${odb_BASE_DIR}/bin:$ENV{PATH}
-        ODB_IO_METHOD=4
-        ODB_IO_GRPSIZE=160
-    LABELS odb_api odb_api_migrator
-    TEST_DEPENDS get_odb2_to_odb1_data
-    CONDITION HAVE_FORTRAN AND ODB_FOUND AND ODB_HAVE_ECMA)
-
 ### odb2netcdf tests
 
 ecbuild_get_test_multidata( TARGET get_odb2netcdf_data
@@ -337,23 +297,10 @@ ecbuild_add_test( TARGET test_odb2netcdf_2d
 
 ### odb_api tests
 
-# remove dependency on migrator tests if migrator not enabled
-if( NOT HAVE_MIGRATOR )
-  unset( odb_migrator_tests )
-endif()
-
-if( HAVE_MIGRATOR )
-    set( _prev_test get_migrator_test_data  )
-else()
-    set( _prev_test get_odb_api_test_data  )
-endif()
+set( _prev_test get_odb_api_test_data  )
 
 foreach( _test ${odb_api_tests} )
-    if( HAVE_MIGRATOR )
-        set( _dependencies ${odb_migrator_tests} ${_prev_test} )
-    else()
-        set( _dependencies ${_prev_test} )
-    endif()
+    set( _dependencies ${_prev_test} )
     ecbuild_add_test( TARGET       ${_test}
                       COMMAND      ${odb_bin}
                       ARGS         ${_test}
diff --git a/odb_api/tests/dhshome/data/partitions_info_test_stage.txt b/odb_api/tests/dhshome/data/partitions_info_test_stage.txt
new file mode 100644
index 0000000..e69de29
diff --git a/odb_api/tests/dhshome/data/partitions_info_test_stage.txt.files b/odb_api/tests/dhshome/data/partitions_info_test_stage.txt.files
new file mode 100644
index 0000000..e69de29
diff --git a/odb_tools/.gitignore b/odb_tools/.gitignore
new file mode 100644
index 0000000..14b93b5
--- /dev/null
+++ b/odb_tools/.gitignore
@@ -0,0 +1,8 @@
+*.swp
+*.sublime-workspace
+.tags*
+CMakeLists.txt.user*
+*.autosave
+*.sublime-workspace
+.*.sw*
+.*un~
diff --git a/odb_tools/CMakeLists.txt b/odb_tools/CMakeLists.txt
new file mode 100644
index 0000000..687311e
--- /dev/null
+++ b/odb_tools/CMakeLists.txt
@@ -0,0 +1,93 @@
+##
+# This package exists to contain odb_api tools that make use of ODB1, to break the circular
+# dependency when building with IFS.
+
+cmake_minimum_required( VERSION 2.8.11 FATAL_ERROR )
+
+project( odb_tools CXX Fortran )
+
+set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake")
+
+include( ecbuild_system NO_POLICY_SCOPE )
+
+ecbuild_requires_macro_version( 2.0 )
+
+###############################################################################
+# local project
+
+ecbuild_declare_project()
+
+ecbuild_use_package( PROJECT eckit   VERSION 0.9 REQUIRED )
+ecbuild_use_package( PROJECT odb_api VERSION ${odb_tools_VERSION_STR} REQUIRED )
+ecbuild_use_package( PROJECT odb     VERSION 1.0.5 REQUIRED )
+
+###############################################################################
+# some variables/options of this project
+
+ecbuild_add_option( FEATURE MIGRATOR
+                    DESCRIPTION "whether or not to build the ODB migrator tool"
+                    DEFAULT ON
+                    REQUIRED_PACKAGES "PROJECT odb VERSION 1.0 QUIET" )
+
+#ecbuild_add_option( FEATURE FORTRAN
+#                    DESCRIPTION "whether or not to build the Fortran interface"
+#                    DEFAULT OFF )
+set( HAVE_FORTRAN ON )
+
+if( HAVE_FORTRAN OR HAVE_MIGRATOR )
+
+    set( Fortran Fortran )
+    ecbuild_enable_fortran( REQUIRED MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/module )
+    ecbuild_find_fortranlibs( REQUIRED )
+    message( "Fortran libraries: [${FORTRAN_LIBRARIES}]" )
+
+endif()
+
+if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
+  ecbuild_add_fortran_flags("-fPIC -ffree-line-length-none")
+endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+  ecbuild_add_cxx_flags("-fPIC -Wl,--as-needed")
+endif()
+
+ecbuild_add_option( FEATURE OMP
+                    DESCRIPTION "Support for OpenMP threaded parallelism"
+                    REQUIRED_PACKAGES "OMP COMPONENTS CXX ${Fortran}" )
+
+if( HAVE_OMP )
+  ecbuild_enable_omp()
+else()
+  ecbuild_enable_ompstubs()
+endif()
+
+ecbuild_add_option( FEATURE PYTHON
+                    DESCRIPTION "whether or not to build the Python interface"
+                    DEFAULT OFF
+                    REQUIRED_PACKAGES "Python VERSION 2.7 NO_LIBS" SWIG )
+
+###############################################################################
+# contents
+
+set_directory_properties( PROPERTIES COMPILE_DEFINITIONS "${ECKIT_DEFINITIONS}" )
+
+get_directory_property( ODB_API_DEFINITIONS COMPILE_DEFINITIONS )
+
+set( ODB_TOOLS_INCLUDE_DIRS   ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src )
+
+#if( HAVE_FORTRAN )
+  list( APPEND ODB_API_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/module )
+  list( INSERT ODB_API_LIBRARIES 0 Odb_fortran )
+#endif()
+
+include_directories( ${ODB_API_INCLUDE_DIRS} ${ODB_TOOLS_INCLUDE_DIRS} )
+
+add_subdirectory( src )
+
+############################################################################################
+# finalize
+
+ecbuild_install_project( NAME OdbTools )
+
+ecbuild_print_summary()
+
diff --git a/odb_tools/VERSION.cmake b/odb_tools/VERSION.cmake
new file mode 100644
index 0000000..bc32f90
--- /dev/null
+++ b/odb_tools/VERSION.cmake
@@ -0,0 +1 @@
+set( ${PROJECT_NAME}_VERSION_STR  "0.17.1" )
diff --git a/odb_tools/bamboo/CLANG-env.sh b/odb_tools/bamboo/CLANG-env.sh
new file mode 100644
index 0000000..14e05f9
--- /dev/null
+++ b/odb_tools/bamboo/CLANG-env.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# No module environment on the Mac
+[[ $(uname) == "Darwin" ]] && return
+
+# Initialise module environment if it is not
+if [[ ! $(command -v module > /dev/null 2>&1) ]]; then
+  . /usr/local/apps/module/init/bash
+fi
+module unload grib_api
+module switch gnu clang/3.6.2
diff --git a/odb_tools/bamboo/INTEL-env.sh b/odb_tools/bamboo/INTEL-env.sh
new file mode 100644
index 0000000..260e756
--- /dev/null
+++ b/odb_tools/bamboo/INTEL-env.sh
@@ -0,0 +1,11 @@
+# Initialise module environment if it is not
+if [[ ! $(command -v module > /dev/null 2>&1) ]]; then
+  . /usr/local/apps/module/init/bash
+fi
+# Unload modules not available for Intel
+module unload grib_api
+module unload eccodes
+module unload emos
+module unload fftw
+module unload libemos
+module switch gnu intel/16.0.3
diff --git a/odb_tools/bamboo/env.sh b/odb_tools/bamboo/env.sh
new file mode 100644
index 0000000..d6827b6
--- /dev/null
+++ b/odb_tools/bamboo/env.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+ctest_parallel="no"
+
diff --git a/odb_tools/bamboo/flags.cmake b/odb_tools/bamboo/flags.cmake
new file mode 100644
index 0000000..9892d75
--- /dev/null
+++ b/odb_tools/bamboo/flags.cmake
@@ -0,0 +1 @@
+SET(ENABLE_MIGRATOR ON CACHE BOOL "Build migrator tool")
diff --git a/odb_tools/src/CMakeLists.txt b/odb_tools/src/CMakeLists.txt
new file mode 100644
index 0000000..5a80538
--- /dev/null
+++ b/odb_tools/src/CMakeLists.txt
@@ -0,0 +1,16 @@
+## check if all sources are used
+
+ecbuild_find_project_files()
+
+### include directories
+
+
+### libs
+
+if( HAVE_MIGRATOR )
+    add_subdirectory( migrator )
+endif()
+
+add_subdirectory( odb2_to_odb1 )
+
+add_subdirectory( tests )
diff --git a/odb_api/src/odb_api/migrator/2oda b/odb_tools/src/migrator/2oda
similarity index 100%
rename from odb_api/src/odb_api/migrator/2oda
rename to odb_tools/src/migrator/2oda
diff --git a/odb_tools/src/migrator/CMakeLists.txt b/odb_tools/src/migrator/CMakeLists.txt
new file mode 100644
index 0000000..f230639
--- /dev/null
+++ b/odb_tools/src/migrator/CMakeLists.txt
@@ -0,0 +1,112 @@
+
+list( APPEND migrator_srcs
+    FakeODBIterator.cc
+    FakeODBIterator.h
+    ImportODBTool.cc
+    ImportODBTool.h
+    ODB2ODATool.cc
+    ODB2ODATool.h
+    MigratorTool.h
+    MigratorTool.cc
+    ODBIterator.cc
+    ODBIterator.h
+    OldODBReader.h
+    ReptypeGenIterator.cc
+    ReptypeGenIterator.h
+    TSQLReader.cc
+    TSQLReader.h
+    ODBMigratorModule.h
+    ODBMigratorModule.cc
+    MigrateHandler.h
+    MigrateHandler.cc
+    migrator_api.cc
+    migrator_api.h
+    odbdump.h
+)
+
+
+ecbuild_add_library(
+
+    TARGET Odbmigrator
+    SOURCES ${migrator_srcs}
+
+    TEMPLATES
+        ImportODBTool.cc
+        TSQLReader.cc
+
+    PRIVATE_INCLUDES
+        ${ODB_INCLUDE_DIRS}
+        ${ECKIT_INCLUDE_DIRS}
+
+    INSTALL_HEADERS LISTED
+    HEADER_DESTINATION
+        ${INSTALL_INCLUDE_DIR}/odb_api/migrator
+
+    LIBS
+        Odb
+        odbtools
+        ${ODB_LIBRARIES}
+        ${FORTRAN_LIBRARIES}
+        ${DL_LIBRARIES}
+        ${EXTRA_ODB_MIGRATOR_LIBS} ) #FIXME: add gomp for gfortran 
+                        
+
+ecbuild_add_executable(
+    
+    TARGET odb_migrator
+    SOURCES odb2oda.cc
+    INCLUDES ${ODB_INCLUDE_DIRS}
+    # LINKER_LANGUAGE Fortran
+
+    LIBS
+        Odbmigrator
+        odbtools
+        ${ODB_LIBRARIES}
+        ${FORTRAN_LIBRARIES}
+        ${DL_LIBRARIES} )
+
+
+set( test_environment
+
+    ODB_API_CODES=${PROJECT_SOURCE_DIR}/etc
+    ODB_API_HOME=${PROJECT_SOURCE_DIR}
+    ODB_API_TEST_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}
+    PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+    ODB_RTABLE_PATH=${PROJECT_SOURCE_DIR}/etc )
+
+
+if( HAVE_MIGRATOR AND ODB_FOUND AND DEFINED FORTRAN_LIBRARIES )
+
+    get_target_property( migrator_bin odb_migrator LOCATION )
+
+    list( APPEND odb_migrator_data_files  2000010106.old.ECMA.tar.gz )
+
+    ecbuild_get_test_multidata( TARGET get_odb_migrator_test_data
+                                DIRNAME odb_api/tests 
+                                NAMES ${odb_migrator_data_files} 
+                                NOCHECK )
+
+      #ecbuild_add_test( TARGET     test_migrator.ecml
+      #                COMMAND      ${migrator_bin} 
+      #                ARGS         ecml ${CMAKE_CURRENT_SOURCE_DIR}/test_migrator.ecml
+      #                CONDITION    HAVE_MIGRATOR
+      #                ENVIRONMENT  ${test_environment}
+      #                LABELS       odb_api odb_api_ecml
+      #                TEST_DEPENDS get_odb_migrator_test_data
+      #                )
+endif()
+
+
+if( HAVE_PYTHON AND SWIG_FOUND AND PYTHONLIBS_FOUND )
+    set(CMAKE_SWIG_FLAGS "")
+    include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${PYTHON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../odb_api )
+    set_source_files_properties( pyodbdump.i PROPERTIES CPLUSPLUS ON )
+    # set_source_files_properties( pyodbapi.i PROPERTIES SWIG_FLAGS "-includeall")
+    swig_add_module( pyodbdump python pyodbdump.i )
+    swig_link_libraries( pyodbdump Odbmigrator Odb ${ODB_LIBRARIES} ${FORTRAN_LIBRARIES} ${DL_LIBRARIES} ${PYTHON_LIBRARIES} )
+        
+    set(PYTHON_SITE "${INSTALL_LIB_DIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages" )
+    set(PYTHON_DEST "${PYTHON_SITE}" )
+    install(TARGETS _pyodbdump DESTINATION ${PYTHON_DEST} )
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyodbdump.py  DESTINATION ${PYTHON_DEST})
+endif()
diff --git a/odb_tools/src/migrator/FakeODBIterator.cc b/odb_tools/src/migrator/FakeODBIterator.cc
new file mode 100644
index 0000000..dcebf2d
--- /dev/null
+++ b/odb_tools/src/migrator/FakeODBIterator.cc
@@ -0,0 +1,160 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file FakeODBIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <strings.h>
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "eckit/parser/Tokenizer.h"
+#include "eckit/utils/Translator.h"
+
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ODBIterator.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+FakeODBIterator::ConstParameters FakeODBIterator::ConstParameters::instance_ = FakeODBIterator::ConstParameters();
+
+Assignments::Assignments(const std::string& s)
+{
+    Tokenizer splitAssignments(",");
+    std::vector<std::string> assignments;
+    splitAssignments(s, assignments);
+	
+    Tokenizer splitEq("=");
+	for (size_t i = 0; i < assignments.size(); ++i)
+	{
+		std::vector<std::string> assignment;
+		splitEq(assignments[i], assignment);
+		ASSERT(assignment.size() == 2);
+
+		push_back(make_pair(assignment[0], assignment[1]));
+	}
+}
+
+void FakeODBIterator::ConstParameters::add(const Assignments& ass)
+{
+	Log::debug() << "FakeODBIterator::ConstParameters::add(const Assignments& ass)" << std::endl;
+	for (size_t i = 0; i < ass.size(); ++i)
+	{
+		const Assignment &as = ass[i];
+		std::string columnName = as.first;
+		std::string value = as.second;
+
+		ASSERT(value.size() > 0);
+
+		if (Tool::isInQuotes(value))
+			addString(columnName, Tool::unQuote(value));
+		else if (value.find('.') == std::string::npos)
+			addInteger(columnName, Translator<std::string, long>()(value));
+		else
+			addReal(columnName, Translator<std::string, double>()(value));
+	}
+}
+
+void FakeODBIterator::ConstParameters::addInteger(const std::string& name, long v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addInteger: " << name << " = " << v << std::endl;
+	push_back(ConstParameter(name, v, odb::INTEGER));
+}
+
+void FakeODBIterator::ConstParameters::addReal(const std::string& name, double v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addReal: " << name << " = " << v << std::endl;
+	push_back(ConstParameter(name, v, odb::REAL));
+}
+
+void FakeODBIterator::ConstParameters::addString(const std::string& name, std::string v)
+{
+	Log::info() << "FakeODBIterator::ConstParameters::addString: " << name << " = '" << v << "'" << std::endl;
+	push_back(ConstParameter(name, Tool::cast_as_double(v), odb::STRING));
+}
+
+FakeODBIterator::FakeODBIterator(const PathName& db, const std::string& sql)
+: iterator_(db, sql),
+  columns_(0),
+  data_(0),
+  constParameters_(FakeODBIterator::ConstParameters::instance())
+{}
+
+FakeODBIterator::~FakeODBIterator()
+{
+	delete [] data_;
+}
+
+odb::MetaData& FakeODBIterator::columns() {
+	if (columns_.size() == 0)
+	{
+		columns_ = iterator_.columns();
+
+		size_t i = constParameters_.size();
+		while (i-- > 0)
+		{
+			std::string name = constParameters_[i].name;
+			odb::ColumnType type = constParameters_[i].type;
+
+			Log::debug() << "FakeODBIterator::columns: i = " << i << ", name=" << name << std::endl;
+
+			odb::Column* col = new odb::Column(columns_);
+			col->name(name);
+			col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
+
+			columns_.insert(columns_.begin(), col);
+		}
+
+	}
+	return columns_;
+}
+
+double* FakeODBIterator::data()
+{
+	if (data_ == 0)
+		data_ = new double[columns_.size()];
+
+	double* trueData = iterator_.data();
+
+	size_t count = constParameters_.size();
+	memcpy(data_ + count, trueData, (columns_.size() - count) * sizeof(double));
+
+	for (size_t i = 0; i < count; ++i)
+		data_[i] = constParameters_[i].value;
+	
+	return data_;
+}
+
+bool FakeODBIterator::isNewDataset()
+{
+	return iterator_.isNewDataset();
+}
+
+bool FakeODBIterator::next(eckit::ExecutionContext* context)
+{
+	bool r = iterator_.next(context);
+	noMore_ = !r;
+	return r;
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_tools/src/migrator/FakeODBIterator.h b/odb_tools/src/migrator/FakeODBIterator.h
new file mode 100644
index 0000000..c7e9bd2
--- /dev/null
+++ b/odb_tools/src/migrator/FakeODBIterator.h
@@ -0,0 +1,96 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file FakeODBIterator.h
+/// @author Piotr Kuchta, ECMWF, March 2009
+
+#ifndef FakeODBIterator_H
+#define FakeODBIterator_H
+
+
+#include <eckit/eckit.h>
+#include "odb_api/MetaData.h"
+#include "migrator/ODBIterator.h"
+
+namespace eckit { class PathName; }
+namespace eckit { class ExecutionContext; }
+
+namespace odb {
+namespace tool {
+
+class ODBIterator;
+
+typedef std::pair<std::string, std::string> Assignment;
+typedef std::vector<Assignment> AssignmentsBase;
+
+struct Assignments : public AssignmentsBase {
+	Assignments(const std::string&);
+};
+
+struct ConstParameter {
+	ConstParameter(std::string name, double value, odb::ColumnType type)
+	: name(name), value(value), type(type)
+	{}
+
+	std::string name;
+	double      value;
+	odb::ColumnType  type;
+};
+
+class FakeODBIterator //: public odb::RowsReaderIterator
+{
+public:
+    struct ConstParameters : public std::vector<ConstParameter>
+	{
+		// Not thread safe.
+		static ConstParameters& instance() { return instance_; }
+
+		void addInteger(const std::string& name, long);
+		void addReal(const std::string& name, double);
+		void addString(const std::string& name, std::string value);
+
+		void add(const Assignments&);
+	private:
+		static ConstParameters instance_;
+	};
+
+
+	FakeODBIterator(const eckit::PathName& db, const std::string& sql); 
+	~FakeODBIterator ();
+
+	const FakeODBIterator& end() { return *reinterpret_cast<FakeODBIterator*>(0); }
+	//bool operator!=(const FakeODBIterator& o) { ASSERT(&o == 0); return iterator_ != iterator_.end(); }
+	//FakeODBIterator& operator++() { next(); return *this; }
+
+	odb::MetaData& columns();
+
+	virtual bool isNewDataset();
+	virtual double* data();
+
+//protected:
+	virtual bool next(eckit::ExecutionContext*);
+
+	int refCount_;
+	bool noMore_;
+    eckit::ExecutionContext* context_;
+
+private:
+	ODBIterator iterator_;
+
+	odb::MetaData columns_;
+	double* data_;
+
+	ConstParameters& constParameters_;
+};
+
+} // namespace tool 
+} //namespace odb 
+
+#endif
diff --git a/odb_tools/src/migrator/ImportODBTool.cc b/odb_tools/src/migrator/ImportODBTool.cc
new file mode 100644
index 0000000..0bfb109
--- /dev/null
+++ b/odb_tools/src/migrator/ImportODBTool.cc
@@ -0,0 +1,207 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include "eckit/filesystem/LocalPathName.h"
+#include "eckit/io/FileHandle.h"
+#include "eckit/log/BigNum.h"
+#include "eckit/log/Timer.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/Comparator.h"
+#include "odb_api/DispatchingWriter.h"
+#include "odb_api/SQLDatabase.h"
+#include "odb_api/SQLInteractiveSession.h"
+#include "odb_api/SchemaAnalyzer.h"
+#include "odb_api/SchemaAnalyzer.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/RowsCounter.h"
+#include "odb_api/tools/ODA2RequestTool.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "ODBIterator.h"
+#include "FakeODBIterator.h"
+
+namespace odb {
+namespace tool {
+
+typedef std::string str;   // string is a typedef in an ODB header.
+
+template <typename IN>
+ImportODBTool<IN>::ImportODBTool (int argc, char *argv[])
+: Tool(argc, argv),
+  noVerification_ (optionIsSet("-no_verification"))
+{}
+
+template <typename IN>
+ImportODBTool<IN>::ImportODBTool (const CommandLineParser& clp)
+: Tool(clp),
+  noVerification_ (optionIsSet("-no_verification"))
+{}
+
+template <typename IN>
+std::pair<unsigned long long, const std::vector<eckit::PathName> > ImportODBTool<IN>::importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile)
+{    
+    using namespace eckit;
+
+    Timer importingAndDipatching("Importing and dipatching");
+
+    Log::info() << "Importing data from '" << db
+        << "', query is '" << sql << "', into '"
+        << dumpFile << "' template." << std::endl;
+
+    odb::DispatchingWriter writer(dumpFile);
+    odb::DispatchingWriter::iterator w = writer.begin();
+
+    unsigned long long inRowsNumber = saveData<>(w, db, sql);
+
+    std::vector<eckit::PathName> files = (**w).outputFiles();
+    return std::make_pair(inRowsNumber, files);
+}
+
+template <typename IN>
+void ImportODBTool<IN>::validate(const eckit::PathName &db, const std::string& sql, const eckit::PathName& file)
+{
+    eckit::Timer verification("Validating dispatched output");
+
+    odb::Reader odaReader(file);
+    odb::Reader::iterator r(odaReader.begin());
+
+    IN reader(db, sql);
+    typename IN::iterator begin (reader.begin());
+    const typename IN::iterator end (reader.end());
+
+    // don't check missing value as the old ODB is not giving correct info for that some times (e.g.  sortbox)
+    odb::Comparator(false)
+        .compare(begin, end, r, odaReader.end(),
+            std::string("ODB input ") + db, std::string("converted output ") + file);
+}
+
+
+template <typename IN>
+void ImportODBTool<IN>::validateRowsNumber(unsigned long long inRowsNumber, const std::vector<eckit::PathName>& files)
+{
+    using namespace eckit;
+    
+	Timer verification("Validating dispatched output");
+
+	Log::info() << "ImportODBTool::validateRowsNumber: Validating output. " << std::endl;
+	Log::info() << "ImportODBTool::validateRowsNumber: input rows number: " << BigNum(inRowsNumber) << std::endl;
+
+	unsigned long long outRowsNumber (0);
+	unsigned long long outFilesSize (0);
+	for (size_t i = 0; i < files.size(); ++i)
+	{
+		const PathName &fn (files[i]);
+		unsigned long long n (RowsCounter::rowCount(fn));
+		unsigned long long fileSize (fn.size());
+
+		outRowsNumber += n;
+		outFilesSize += fileSize;
+
+		Log::info() << "ImportODBTool::validateRowsNumber: " << fn << ": " << BigNum(n) << " rows, file size: " << BigNum(fileSize) << "." << std::endl;
+	}
+	Log::info() << "ImportODBTool::validateRowsNumber: sum of output rows number: " << BigNum(outRowsNumber) << ", sum of file sizes: " << BigNum(outFilesSize) << std::endl;
+	ASSERT(inRowsNumber == outRowsNumber);
+}
+
+
+template <typename IN>
+void ImportODBTool<IN>::run()
+{
+    using namespace eckit;
+    
+    ASSERT("Wrong number of parameters. odb2oda.cc:main should check this."
+        && !(parameters().size() < 2 || parameters().size() > 4));
+
+    str db (parameters(1));
+    str sql (parameters().size() > 2 && parameters(2) != "." ? readFile(parameters(2)) : "");
+
+    Log::info() << "ImportODBTool::run: sql='" << sql << "'" << std::endl;
+
+    str dumpFile ((parameters().size() > 3) ? parameters(3) : (db + ".odb"));
+    if (dumpFile.substr(dumpFile.size() - 4) != ".odb")
+        dumpFile.append(".odb");
+
+    Log::info() << "Importing data from '" << db << "', query is '" << sql << "', into '" << dumpFile << "'." << std::endl;
+
+    odb::TemplateParameters params;
+    if (odb::TemplateParameters::parse(dumpFile, params).size() != 0)
+    {
+        DispatchResult r (importDispatching(db, sql, dumpFile));
+
+        unsigned long long importedRowsNumber (r.first);
+        const std::vector<eckit::PathName>& outFiles (r.second);
+
+        if (! noVerification_ )
+        {
+            Timer verification("Verification");
+            validateRowsNumber(importedRowsNumber, outFiles);
+        }
+    }
+    else
+    {
+        odb::Writer<> writer(dumpFile);
+        odb::Writer<>::iterator w (writer.begin());
+
+        unsigned long long importedRowsNumber (saveData<>(w, db, sql)); 
+        Log::info() << "Imported " << BigNum(importedRowsNumber) << " row(s)." << std::endl;
+
+        Timer verification("Verification");
+        Log::info() << "Verifying." << std::endl;
+        Log::info() << "Comparing data from: 1) ODB, and 2) ODA" << std::endl;
+
+        if (importedRowsNumber && ! noVerification_) 
+            validate(db, sql, dumpFile);
+    }
+    Log::info() << "ImportODBTool: Finished OK" << std::endl;
+}
+
+template <typename IN>
+template <typename OUT_ITERATOR>
+unsigned long long ImportODBTool<IN>::saveData(OUT_ITERATOR w, eckit::PathName odb, str sql) //, const SchemaAnalyzer &schema)
+{
+    using namespace eckit;
+    
+    Log::info() << "ImportODBTool<IN>::saveData: odb='" << odb << "', sql='" << sql << "'" << std::endl;
+    unsigned long long n (0);
+	try {
+        (**w).property("ODB_DATABASE", odb);
+        IN reader (odb, sql);
+        typename IN::iterator begin (reader.begin());
+        const typename IN::iterator end (reader.end());
+		
+        if (begin->columns().empty())
+        {
+            Log::warning() << "ImportODBTool<IN>::saveData: empty input data set." << std::endl;
+            return 0;
+        }
+
+        n = w->pass1(begin, end);
+        //w->close();
+    } catch (...) {
+        shell("[ -f odbdump.stderr ] && cat odbdump.stderr && cp odbdump.stderr " + odb + ".odb.log || echo odbdump.stderr not found", Here()); 
+        throw;
+    }
+    return n;
+}
+
+
+} // namespace tool 
+} // namespace odb 
+
+
diff --git a/odb_tools/src/migrator/ImportODBTool.h b/odb_tools/src/migrator/ImportODBTool.h
new file mode 100644
index 0000000..c556583
--- /dev/null
+++ b/odb_tools/src/migrator/ImportODBTool.h
@@ -0,0 +1,66 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef odb_api_ImportODBTool_H
+#define odb_api_ImportODBTool_H
+
+#include <eckit/eckit.h>
+
+#include "eckit/filesystem/PathName.h"
+#include "migrator/OldODBReader.h"
+#include "odb_api/tools/Tool.h"
+
+
+class ODBIterator;
+class CommandLineParser;
+
+
+namespace odb {
+namespace tool {
+
+template <typename IN = odb::tool::OldODBReader>
+class ImportODBTool : public Tool {
+public:
+	ImportODBTool (int argc, char *argv[]); 
+	ImportODBTool (const CommandLineParser&); 
+
+	void run(); 
+
+protected:
+
+	template <typename OUT_ITERATOR>
+	unsigned long long saveData(OUT_ITERATOR w, eckit::PathName odb, std::string sql);
+	
+    typedef std::pair<unsigned long long, const std::vector<eckit::PathName> > DispatchResult;
+
+	DispatchResult importDispatching(const eckit::PathName& db, const std::string& sql, const std::string& dumpFile);
+
+    void validate(const eckit::PathName& db, const std::string& sql, const eckit::PathName& file);
+    void validateRowsNumber(unsigned long long, const std::vector<eckit::PathName>&);
+
+    void archiveFiles(const std::vector<eckit::PathName>&);
+private:
+
+// No copy allowed
+    ImportODBTool(const ImportODBTool&);
+    ImportODBTool& operator=(const ImportODBTool&);
+
+	bool isECFSPathName(const eckit::PathName fileName);
+	eckit::PathName readFromECFS(const eckit::PathName fileName);
+
+    bool noVerification_;
+};
+
+} // namespace tool 
+} //namespace odb 
+
+#include "ImportODBTool.cc"
+
+#endif 
diff --git a/odb_api/src/odb_api/migrator/Makefile b/odb_tools/src/migrator/Makefile
similarity index 100%
rename from odb_api/src/odb_api/migrator/Makefile
rename to odb_tools/src/migrator/Makefile
diff --git a/odb_api/src/odb_api/migrator/Makefile.old b/odb_tools/src/migrator/Makefile.old
similarity index 100%
rename from odb_api/src/odb_api/migrator/Makefile.old
rename to odb_tools/src/migrator/Makefile.old
diff --git a/odb_api/src/odb_api/migrator/MigrateHandler.cc b/odb_tools/src/migrator/MigrateHandler.cc
similarity index 100%
rename from odb_api/src/odb_api/migrator/MigrateHandler.cc
rename to odb_tools/src/migrator/MigrateHandler.cc
diff --git a/odb_api/src/odb_api/migrator/MigrateHandler.h b/odb_tools/src/migrator/MigrateHandler.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/MigrateHandler.h
rename to odb_tools/src/migrator/MigrateHandler.h
diff --git a/odb_tools/src/migrator/MigratorTool.cc b/odb_tools/src/migrator/MigratorTool.cc
new file mode 100644
index 0000000..023b7d2
--- /dev/null
+++ b/odb_tools/src/migrator/MigratorTool.cc
@@ -0,0 +1,144 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file MigratorTool.cc
+///
+/// @author Piotr Kuchta, ECMWF, July 2009
+///
+
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+
+#include "eckit/parser//StringTools.h"
+
+#include "ecml/core/ExecutionContext.h"
+
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/MigratorTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/OldODBReader.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/MDI.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+#include "odb_api/ODBModule.h"
+
+#include "ODBMigratorModule.h"
+
+using namespace eckit;
+using namespace std;
+
+namespace odb {
+namespace tool {
+
+
+int gdb(const std::vector<std::string>& params)
+{
+    std::cout << "gdb: params: " << params << std::endl;
+	str cmd(params[0]);
+	str args;
+	for (size_t i = 1; i < params.size(); ++i)
+		args += str(" ") + params[i];
+
+    eckit::PathName scriptFile = str(".gdb_") + params[2];
+	if (! scriptFile.exists())
+	{
+		str s = str("file ") + cmd + "\nbreak main\nrun " + args + "\n";
+        s += "catch throw\n";
+        eckit::FileHandle f(scriptFile);
+		f.openForWrite(1024);
+		f.write(s.c_str(), s.size());
+		f.close();
+	}
+	str vi = str("vi ") + scriptFile;
+	std::cout << "Executing '" << vi << "'" << std::endl;
+	system(vi.c_str());
+
+	str gdbCmd = str("gdb -x ") + scriptFile;
+	std::cout << "Executing '" << gdbCmd << "'" << std::endl;
+	return system(gdbCmd.c_str());
+}
+
+// valgrind --log-file=v.log --show-reachable=yes --leak-check=full ./oda test 
+int valgrind(const std::vector<std::string>& params)
+{
+    std::cout << "valgrind: params: " << params << std::endl;
+	str cmd(params[0]);
+	str args;
+	for (size_t i = 1; i < params.size(); ++i)
+		args += str(" ") + params[i];
+
+	str logFile = str("vg.log");
+	str vg = str("valgrind --log-file=") + logFile + " --show-reachable=yes --leak-check=full " + cmd + " " + args;
+	std::cout << "Executing '" << vg << "'" << std::endl;
+	return system(vg.c_str());
+}
+
+//MigratorTool::MigratorTool (int argc, char *argv[]) : Tool(argc, argv) { } 
+
+MigratorTool::MigratorTool (const CommandLineParser &clp) : Tool(clp) { } 
+
+void MigratorTool::runECML()
+{
+    ecml::ExecutionContext context;
+    ODBModule odbModule;
+    ODBMigratorModule migratorModule;
+    context.import(odbModule);
+    context.import(migratorModule);
+
+    std::vector<std::string> params(parameters());
+    params.erase(params.begin());
+    params.erase(params.begin());
+    for (size_t i (0); i < params.size(); ++i)
+    {
+        Log::info() << "*** Executing " << params[i] << endl;
+        context.executeScriptFile(params[i]);
+    }
+
+}
+
+void MigratorTool::run()
+{
+    if (parameters().size() > 1)
+    {
+        if (parameters(1) == "g" || parameters(1) == "vg")
+        {
+            std::vector<std::string> params;
+            for (size_t i(0); i < parameters().size(); ++i)
+                if (i != 1)
+                    params.push_back(parameters()[i]);
+
+            if (parameters(1) == "g")
+                gdb(params);
+            else valgrind(params);
+
+            return;
+        }
+        if (parameters(1) == "ecml")
+            return runECML();
+
+        if (parameters(1) == "test")
+        {
+            //odb::tool::test::TestRunnerApplication(argc(), argv()).start();
+            return; // TODO: Retrieve a status from the test runner
+        }
+    }
+
+    ODB2ODATool odb2oda(*this);
+    odb2oda.run();
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/MigratorTool.h b/odb_tools/src/migrator/MigratorTool.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/MigratorTool.h
rename to odb_tools/src/migrator/MigratorTool.h
diff --git a/odb_tools/src/migrator/ODB2ODATool.cc b/odb_tools/src/migrator/ODB2ODATool.cc
new file mode 100644
index 0000000..ae37b37
--- /dev/null
+++ b/odb_tools/src/migrator/ODB2ODATool.cc
@@ -0,0 +1,139 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+/// \file ODB2ODATool.cc
+///
+/// @author Piotr Kuchta, ECMWF, July 2009
+///
+
+#include <iostream>
+#include <fstream>
+
+#include "eckit/parser/StringTools.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ImportODBTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/OldODBReader.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/MDI.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+ODB2ODATool::ODB2ODATool (int argc, char *argv[])
+: Tool(argc, argv)
+{}
+
+ODB2ODATool::ODB2ODATool (const CommandLineParser &clp)
+: Tool(clp)
+{}
+
+
+/// -mdi <type1:MDI1,type2:MDI2,...>
+void ODB2ODATool::resetMDI(const std::string& s)
+{
+    typedef eckit::StringTools S;
+    std::vector<std::string> columns(S::split(",", s));
+    for (size_t i = 0; i < columns.size(); ++i)
+    {
+        std::vector<std::string> ass(S::split(":", columns[i]));
+
+        if (ass.size() != 2)
+            throw UserError("Error parsing option -mdi");
+
+        const std::string typeName(S::upper(ass[0]));
+        double value(StringTool::translate(ass[1]));
+
+        Log::info() << "  typeName: " << typeName << " value: " << value << std::endl;
+
+        if (typeName == "REAL")
+            odb::MDI::realMDI(value);
+        else if (typeName == "INTEGER" || typeName == "INT")
+            odb::MDI::integerMDI(value);
+        else
+            throw UserError("Changing MDI of types different than INTEGER or REAL not supported yet.");
+    }
+}
+
+void ODB2ODATool::run()
+{
+	if (parameters().size() < 2 || parameters().size() > 4)
+	{
+        std::cerr << "Usage:" << std::endl
+			<< "	" << parameters(0)
+
+            << " [<options>] <odb_database> [<file-with-select-statement-defining-dump> [<output.odb>]]" << std::endl
+
+            << "Options: " << std::endl << std::endl
+
+            << "\t[-genreptype <list-of-columns>]" << std::endl
+            << "\t[-reptypecfg <reptype-generation-config-file>]" << std::endl
+            << "\t[-addcolumns <list-of-assignments>]" << std::endl
+            << "\t[-mdi <type1:MDI1,type2:MDI2,...>]              Provide values of missing data indicators, e.g.: -mdi REAL:2147483647,INTEGER:2147483647" << std::endl
+            << "\t[-no_verification]                              Do not verify the conversion" << std::endl
+
+			<< std::endl;
+		return;
+	}
+
+    std::string nonDefaultMDIS(optionArgument<std::string>("-mdi", ""));
+    if (nonDefaultMDIS.size())
+        Log::info() << "Using non default missing data indicators: " << nonDefaultMDIS << std::endl;
+
+	bool addColumns (optionIsSet("-addcolumns"));
+	if (addColumns)
+		FakeODBIterator::ConstParameters::instance().add(Assignments(optionArgument<std::string>("-addcolumns", "")));
+ 
+	bool genReptype (optionIsSet("-genreptype"));
+	bool reptypeCfg (optionIsSet("-reptypecfg"));
+    if (optionIsSet("-mdi"))
+        resetMDI(optionArgument<std::string>("-mdi", ""));
+
+	ASSERT("Only one of -genreptype and -reptypecfg can be choosen at a time." && !(genReptype && reptypeCfg));
+
+	if (genReptype) {
+        std::vector<std::string> columns = StringTools::split(",", optionArgument<std::string>("-genreptype", ""));
+		ReptypeTableConfig::addColumns(columns.begin(), columns.end());
+	}
+
+	if (reptypeCfg) ReptypeTableConfig::load(optionArgument<std::string>("-reptypecfg", ""));
+
+	if (addColumns && (genReptype || reptypeCfg)) {
+		typedef odb::tool::TSQLReader<ReptypeGenIterator<FakeODBIterator> > R;
+		ImportODBTool<R>(*this).run();
+		return;
+	}
+
+	if (addColumns) {
+		ImportODBTool<odb::tool::TSQLReader<FakeODBIterator> >(*this).run();
+		return;
+	}
+
+	if (genReptype || reptypeCfg) {
+		ImportODBTool<odb::tool::TSQLReader<ReptypeGenIterator<ODBIterator> > >(*this).run();
+		return;
+	}
+
+	{	
+		ImportODBTool<odb::tool::OldODBReader>(*this).run();
+		Log::info() << "ImportODBTool<ODBIterator> finished OK" << std::endl;
+	}
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/ODB2ODATool.h b/odb_tools/src/migrator/ODB2ODATool.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/ODB2ODATool.h
rename to odb_tools/src/migrator/ODB2ODATool.h
diff --git a/odb_tools/src/migrator/ODBIterator.cc b/odb_tools/src/migrator/ODBIterator.cc
new file mode 100644
index 0000000..67d679a
--- /dev/null
+++ b/odb_tools/src/migrator/ODBIterator.cc
@@ -0,0 +1,253 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file ODBIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <map>
+
+#include "eckit/config/Resource.h"
+#include "eckit/filesystem/PathName.h"
+#include "eckit/parser/StringTools.h"
+#include "migrator/ODBIterator.h"
+#include "odb_api/MetaData.h"
+#include "odb_api/SQLDatabase.h"
+#include "odb_api/SQLParser.h"
+#include "odb_api/SQLSelectFactory.h"
+#include "odb_api/StringTool.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+
+namespace odb { namespace sql { class SQLInteractiveSession; } }
+
+extern "C" {
+#include "odbdump.h"
+}
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+//ODBIterator::ODBIterator(const PathName& db, const std::string& sql)
+ODBIterator::ODBIterator(const std::string& db, const std::string& sql)
+: db_(db),
+  odbHandle_(0),
+  noOfColumns_(0),
+  ci_(0),
+  columns_(new odb::MetaData(0, (odb::Column *) 0)),
+  newDataset_(false),
+  data_(0),
+  nd_(0),
+  schemaParsed_(false),
+  refCount_(0),
+  noMore_(true),
+  context_(0)
+{
+	Log::info() << "ODBIterator::ODBIterator: @" << this << " db=" << db << std::endl;
+
+	const std::string odbDirectory = db; //.asString();
+	Log::info() << "Opening ODB in '" << odbDirectory << "'" << std::endl;
+	if (! PathName(odbDirectory).exists())
+        throw CantOpenFile(odbDirectory);
+	
+	std::string select = sql.size() ? sql : defaultSQL(db);
+
+	ASSERT(select.size() != 0 && select != "");
+
+	const std::string dbPath = db; //.asString();
+	const char *db_path = dbPath.c_str();
+	const char *sql_select = select.c_str();
+
+	Log::info() << "ODBIterator::ODBIterator: Calling odbdump_open(\"" << db_path << "\",\"" << sql_select << "\", NULL, NULL, NULL, &" << nd_ << ")" << std::endl;
+
+	odbHandle_ = odbdump_open(db_path, sql_select, NULL, NULL, NULL, &nd_);
+	ASSERT("odbdump_open returned NULL" && odbHandle_);
+	ASSERT("odbdump_open returned nd_ <= 0" && nd_ > 0);
+
+	data_ = new double[nd_];
+
+	//next();
+	//if (noMore_) Log::warning() << "ODBIterator::ODBIterator: result set empty, no data." << std::endl;
+}
+
+bool ODBIterator::next(eckit::ExecutionContext*)
+{
+	newDataset_ = false;
+	noOfColumns_ = odbdump_nextrow(odbHandle_, data_, nd_, &newDataset_);
+	if (noOfColumns_ == 0)
+	{
+		return !(noMore_ = true);
+	}
+
+	if (newDataset_)
+	{
+		Log::info() << "ODBIterator::readRow: new data set" << std::endl;
+		createColumns();
+	}
+
+	ASSERT(noOfColumns_ <= nd_);
+    // FIXME: read the missing values for a given constant from somewhere
+	// This is because sometime ODB has MISSING_VALUE_REAL in INTEGER columns...
+	// for example station_type at hdr in ECMA.conv
+	for (int i = 0; i < noOfColumns_; ++i)
+		if ((*columns_)[i]->type() == odb::INTEGER && data_[i] == odb::MDI::realMDI())
+			data_[i] = odb::MDI::integerMDI();
+
+	return !(noMore_ = false);
+}
+
+void ODBIterator::createColumns()
+{
+	Log::debug() << " => ODBIterator::createColumns: " << std::endl;
+
+	delete columns_;
+	columns_ = new odb::MetaData(noOfColumns_, (odb::Column *) 0);
+
+	bool preservePrecision = Resource<bool>("$ODB2ODA_PRESERVE_PRECISION", false);
+	
+	ci_ = (colinfo_t *) odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
+	int nci = 0;
+	ci_ = (colinfo_t *) odbdump_create_colinfo(odbHandle_, &nci); 
+
+    std::map<std::string, std::string> truenames;
+	for (int i = 0; i < noOfColumns_; i++)
+	{
+		colinfo_t *pci = &((colinfo_t *) ci_)[i];
+		std::string name = pci->nickname ? pci->nickname : pci->name;
+        truenames[name] = pci->name;
+
+		odb::ColumnType type = odb::REAL;
+		double missing = odb::MDI::integerMDI(); 
+
+		switch(pci->dtnum)
+		{
+			case DATATYPE_REAL4:
+				type = odb::REAL;
+				missing = odb::MDI::realMDI(); 
+				break;
+
+			case DATATYPE_REAL8:
+				type = preservePrecision ? odb::DOUBLE : odb::REAL;
+				missing = odb::MDI::realMDI(); 
+				break;
+
+			case DATATYPE_STRING:
+				type = odb::STRING;
+				break;
+
+			case DATATYPE_INT4:
+			case DATATYPE_YYYYMMDD:
+			case DATATYPE_HHMMSS:
+				type = odb::INTEGER;
+				break;
+
+			case DATATYPE_BITFIELD:
+				type = odb::BITFIELD;
+				break;
+
+			default:
+				Log::error() << "Unsupported type: [" << pci->type_name << "] " << name
+							<< std::endl;
+				break;
+		}
+		setColumn(i, name, type, missing);
+	}
+	getSchema(db_).updateBitfieldsDefs(columns(), truenames);
+	Log::debug() << " <= ODBIterator::createColumns: " << std::endl;
+}
+
+void ODBIterator::destroy()
+{
+	Log::debug() << "ODBIterator::destroy: @" << this << std::endl;
+	odbdump_destroy_colinfo( (colinfo_t *) ci_, noOfColumns_); 
+	odbdump_close(odbHandle_);
+	delete columns_;
+	delete [] data_;
+}
+
+ODBIterator::~ODBIterator ()
+{
+	Log::info() << "ODBIterator::~ODBIterator: @" << this << std::endl;
+	destroy();
+}
+
+odb::MetaData& ODBIterator::columns() { return *columns_; }
+
+double* ODBIterator::data() { return data_; }
+
+bool ODBIterator::isNewDataset() { return newDataset_; }
+
+int ODBIterator::setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue)
+{
+	//Log::debug() << "ODBIterator::setColumn: " << index << ", " << name << ", " << columnTypeName(type) << ", " << missingValue << std::endl;
+
+	ASSERT(int(index) < noOfColumns_);
+	ASSERT(columns_);
+	odb::Column* col = (*columns_)[index];
+	delete col;
+	col = new odb::Column(*columns_);
+	ASSERT(col);
+
+	col->name(name); 
+	col->type<DataStream<SameByteOrder, DataHandle> >(type, false);
+	col->missingValue(missingValue);
+
+	(*columns_)[index] = col;
+	return 0;
+}
+
+
+//const char* defaultSQL = "select {!/LINK/} from hdr,body,errstat";
+PathName ODBIterator::schemaFile(const PathName& db)
+{
+    Log::info() << "ODBIterator::schemaFile: db=" << db << std::endl;
+
+	std::string d = db;
+
+	if (d[d.size() - 1] != '/')
+		d += "//";
+
+	std::string s = StringTools::split(".", StringTools::split("//", d).back())[0];
+
+	return d + s + ".sch";
+}
+
+const odb::sql::SchemaAnalyzer& ODBIterator::getSchema(const PathName& db)
+{
+	//odb::sql::SQLSelectFactory::instance().config(); //odb::sql::SQLOutputConfig());
+	// FIXME: this is not good cause when you call the method several times with different db it will fail...
+	// It's not used like that at the moment, anyway. So perhaps I should make db a member (db_).
+	if (!schemaParsed_)
+	{
+		PathName schemaFile = this->schemaFile(db);
+		Log::info() << "ImportODBTool::getSchema: parsing '" << schemaFile << "'" << std::endl;
+	
+		odb::sql::SQLParser p;
+		p.parseString(session_, StringTool::readFile(schemaFile), static_cast<DataHandle*>(0), session_.selectFactory().config());
+		schemaParsed_ = true;
+	}
+
+	return session_
+			.currentDatabase()
+			.schemaAnalyzer();
+}
+
+std::string ODBIterator::defaultSQL(const PathName& db)
+{
+	return getSchema(db).generateSELECT();
+}
+
+} // namespace tool 
+} //namespace odb 
+
diff --git a/odb_tools/src/migrator/ODBIterator.h b/odb_tools/src/migrator/ODBIterator.h
new file mode 100644
index 0000000..18b5a0b
--- /dev/null
+++ b/odb_tools/src/migrator/ODBIterator.h
@@ -0,0 +1,97 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef ODBIterator_H
+#define ODBIterator_H
+
+#include "eckit/filesystem/PathName.h"
+#include "odb_api/SQLInteractiveSession.h"
+#include "odb_api/ColumnType.h"
+
+namespace eckit { class PathName; }
+namespace eckit { class ExecutionContext; }
+
+namespace odb { namespace sql { class SchemaAnalyzer; class SQLInteractiveSession; } }
+
+namespace odb {
+
+class MetaData;
+
+namespace tool {
+
+class ODBIterator 
+{
+public:
+    ODBIterator(const std::string& db, const std::string& sql); 
+    virtual ~ODBIterator ();
+
+    void destroy();
+
+    const ODBIterator& end() { return *reinterpret_cast<ODBIterator*>(0); }
+
+    ODBIterator& operator++() { next(context_); return *this; }
+
+    bool operator!=(const ODBIterator& o) {
+        /* SDS: I have no idea what the purpose of this operator is,
+         *      but returning uninitialised memory
+         *      seems a bad plan. Check that it is never being used. */
+        throw eckit::SeriousBug("Non-functional operator!= must never be called", Here());
+        /*ASSERT(&o == 0); return hasNext_;*/
+    }
+
+    odb::MetaData& columns();
+
+    virtual bool isNewDataset();
+    virtual double* data();
+
+    static eckit::PathName schemaFile(const eckit::PathName& db);
+
+    virtual bool next(eckit::ExecutionContext*);
+
+protected:
+    int setColumn(unsigned long index, std::string& name, odb::ColumnType type, double missingValue);
+
+private: // methods
+
+	void createColumns();
+
+    std::string defaultSQL(const eckit::PathName& db);
+    const odb::sql::SchemaAnalyzer& getSchema(const eckit::PathName& db);
+
+private: // members
+
+	eckit::PathName db_;
+
+	void *odbHandle_;
+	int noOfColumns_;
+	//colinfo_t *ci_;
+	void *ci_;
+	odb::MetaData *columns_;
+	int newDataset_;
+	double* data_;
+	int nd_;
+
+	bool schemaParsed_;
+	odb::sql::SQLInteractiveSession session_;
+
+	friend class FakeODBIterator;
+	//friend class ReptypeGenIterator;
+
+public: // members
+
+	int refCount_;
+	bool noMore_;
+    eckit::ExecutionContext* context_;
+};
+
+} // namespace tool 
+} // namespace odb 
+
+#endif
diff --git a/odb_api/src/odb_api/migrator/ODBMigratorModule.cc b/odb_tools/src/migrator/ODBMigratorModule.cc
similarity index 100%
rename from odb_api/src/odb_api/migrator/ODBMigratorModule.cc
rename to odb_tools/src/migrator/ODBMigratorModule.cc
diff --git a/odb_api/src/odb_api/migrator/ODBMigratorModule.h b/odb_tools/src/migrator/ODBMigratorModule.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/ODBMigratorModule.h
rename to odb_tools/src/migrator/ODBMigratorModule.h
diff --git a/odb_api/src/odb_api/migrator/Odb2_to_odb1_era.f90 b/odb_tools/src/migrator/Odb2_to_odb1_era.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/Odb2_to_odb1_era.f90
rename to odb_tools/src/migrator/Odb2_to_odb1_era.f90
diff --git a/odb_tools/src/migrator/OldODBReader.h b/odb_tools/src/migrator/OldODBReader.h
new file mode 100644
index 0000000..0aeb8ed
--- /dev/null
+++ b/odb_tools/src/migrator/OldODBReader.h
@@ -0,0 +1,25 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#ifndef odb_api_OldODBReader_H
+#define odb_api_OldODBReader_H
+
+#include "migrator/TSQLReader.h"
+#include "migrator/ODBIterator.h"
+
+namespace odb {
+namespace tool {
+
+typedef odb::tool::TSQLReader<ODBIterator> OldODBReader;
+
+} // namespace tool 
+} // namespace odb 
+
+#endif
diff --git a/odb_tools/src/migrator/ReptypeGenIterator.cc b/odb_tools/src/migrator/ReptypeGenIterator.cc
new file mode 100644
index 0000000..f0f5c8b
--- /dev/null
+++ b/odb_tools/src/migrator/ReptypeGenIterator.cc
@@ -0,0 +1,234 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+///
+/// \file ReptypeGenIterator.cc
+///
+/// @author Piotr Kuchta, Feb 2009
+
+#include <strings.h>
+
+extern "C" {
+#include "odbdump.h"
+}
+
+#include "eckit/parser/StringTools.h"
+#include "eckit/parser/Tokenizer.h"
+#include "eckit/types/Types.h"
+#include "eckit/utils/Translator.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+
+
+using namespace eckit;
+
+namespace odb {
+namespace tool {
+
+std::ostream& operator<<(std::ostream& s, const ReptypeTable& m)
+{
+	s << "{";
+	for (ReptypeTable::const_iterator it = m.begin(); it != m.end(); ++it)
+	{
+		s << "[";
+		const Values& vals = it->first;
+		for (Values::const_iterator i = vals.begin(); i != vals.end(); ++i)
+			s << *i;
+		s << "]";
+
+		s << " : " << it->second << "," << std::endl;
+	}
+	s << "}";
+	return s;
+}
+
+/*
+Hi Peter,
+
+most of the columns given by Manuel do not exist yet.
+
+As a first attempt, you can use
+sensor at hdr,
+satname_1 at hdr,
+satname_2 at hdr,
+satname_3 at hdr,
+satname_4 at hdr,
+bufrtype at hdr,
+subtype at hdr,
+obstype at hdr,
+codetype at hdr
+(when sat.len > 0 you can add satid at sat).
+
+Anne. 
+*/
+
+std::vector<std::string> ReptypeTableConfig::columns_ = std::vector<std::string>();
+ReptypeTable ReptypeTableConfig::reptypeTable_ = ReptypeTable();
+
+void ReptypeTableConfig::load(const PathName& fileName)
+{
+	std::string s = Tool::readFile(fileName, false);
+	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << std::endl;
+	Log::debug() << "ReptypeTableConfig::load(fileName = '" << fileName << "')" << "'" << s << "'" << std::endl;
+
+    std::vector<std::string> lines = StringTools::split("\n", s);
+
+	size_t i = 0;
+	while (lines[i] == "")
+		++i;
+
+    std::vector<std::string> firstLine = StringTools::split(":", lines[i]);
+	ASSERT(firstLine[0] == "reptype");
+
+    std::vector<std::string> columnNames = StringTools::split(",", firstLine[1]);
+	std::for_each(columnNames.begin(), columnNames.end(), Tool::trimInPlace);
+
+	columns_.insert(columns_.end(), columnNames.begin(), columnNames.end());
+	++i;
+
+    for (; i < lines.size(); ++i)
+    {
+        std::vector<std::string> lr;
+        Tokenizer(":")(lines[i], lr);
+
+        // Skip empty lines.
+        if (lr.size() == 0) continue;
+
+		ASSERT(lr.size() == 2);
+
+		int reptype_value = Translator<std::string, int>()(lr[0]);
+
+        std::vector<std::string> rvalues = StringTools::split(",", lr[1]);
+		//Log::debug() << "ReptypeTableConfig::load: rvalues = " << rvalues << std::endl;
+
+		ASSERT("Number of values must be equal to number of column names (first line)"
+			&& columnNames.size() == rvalues.size());
+
+		std::for_each(rvalues.begin(), rvalues.end(), Tool::trimInPlace);
+		Values vals;
+		Log::debug() << "ReptypeTableConfig::load: " << reptype_value << " = ";
+		for (size_t j = 0; j < rvalues.size(); ++j)
+		{
+			std::string &vs(rvalues[j]);
+
+			Log::debug() << "{" << vs << ":" << Tool::isInQuotes(vs) << "}";
+			double v = Tool::isInQuotes(vs)
+				? Tool::cast_as_double(Tool::unQuote(vs))
+				: Translator<std::string, double>()(vs);
+			vals.push_back(v);
+			Log::debug() << "[" << rvalues[j] << "] '" << Tool::double_as_string(v) << "', " << std::endl;
+		}
+		Log::debug() << std::endl;
+		//at(vals) = reptype_value;
+		reptypeTable_[vals] = reptype_value;
+	}
+
+	//Log::debug() << "ReptypeTableConfig::load: columns_ = " << columns_ << std::endl; 
+	//Log::debug() << "ReptypeTableConfig::load: reptypeTable_ = " << reptypeTable_ << std::endl;
+}
+
+template<typename ITERATOR, typename CONFIG>
+ReptypeGenIterator<ITERATOR, CONFIG>::ReptypeGenIterator(const PathName& db, const std::string& sql)
+: iterator_(db, sql),
+  data_(0),
+  reptypeTable_(CONFIG::reptypeTable())
+{
+	odb::MetaData &md = iterator_.columns();
+	data_ = new double[md.size()];
+	reptypeIndex_ = md.columnIndex("reptype");
+
+	const std::vector<std::string>& columnNames = CONFIG::columns();
+	for (std::vector<std::string>::const_iterator i = columnNames.begin(); i != columnNames.end(); ++i)
+	{
+		std::string name = *i;
+
+		Log::debug() << "ReptypeGenIterator<ITERATOR>::ctor: " << name << std::endl;
+
+		indices_.push_back(iterator_.columns().columnIndex(name));
+		values_.push_back(0);
+	}
+	Log::debug() << "ReptypeGenIterator::ReptypeGenIterator: Reptype table:" << std::endl;
+	Log::debug() << "reptypeTable_ = " << reptypeTable_ << std::endl;
+}
+
+template<typename ITERATOR, typename CONFIG>
+ReptypeGenIterator<ITERATOR, CONFIG>::~ReptypeGenIterator()
+{
+	Log::debug() << "ReptypeGenIterator::~ReptypeGenIterator: Reptype table:" << std::endl;
+	Log::debug() << "reptypeTable_.size() = " << reptypeTable_.size() << std::endl;
+	Log::debug() << "reptypeTable_ =" << reptypeTable_ << std::endl;
+	delete [] data_;
+}
+
+template<typename ITERATOR, typename CONFIG>
+odb::MetaData& ReptypeGenIterator<ITERATOR, CONFIG>::columns()
+{
+	return iterator_.columns();
+}
+
+template<typename ITERATOR, typename CONFIG>
+double* ReptypeGenIterator<ITERATOR, CONFIG>::data()
+{
+	return data_;
+}
+
+template<typename ITERATOR, typename CONFIG>
+bool ReptypeGenIterator<ITERATOR, CONFIG>::isNewDataset()
+{
+	return iterator_.isNewDataset();
+}
+
+template<typename ITERATOR, typename CONFIG>
+bool ReptypeGenIterator<ITERATOR, CONFIG>::next(eckit::ExecutionContext* context)
+{
+	bool r = iterator_.next(context);
+	if (r)
+	{
+		double* trueData = iterator_.data();
+
+        std::copy(trueData, trueData + iterator_.columns().size(), data_);
+
+		for (size_t i = 0; i < indices_.size(); ++i)
+			values_[i] = data_[indices_[i]];
+
+		ReptypeTable::const_iterator it = reptypeTable_.find(values_); 
+		if (it != reptypeTable_.end())
+			data_[reptypeIndex_] = it->second;
+		else
+		{
+			// TODO: rethink!
+			Log::info() << "ReptypeGenIterator::next(): No matching report type, creating new one." << std::endl;
+
+			size_t newRT = reptypeTable_.size();
+			for (ReptypeTable::const_iterator i = reptypeTable_.begin(); i != reptypeTable_.end(); ++i)
+			{
+				size_t rt = i->second;
+				if (newRT <= rt)
+					newRT = rt + 1;
+			}
+
+			Log::info() << "ReptypeGenIterator::next(): New report type: " << newRT << std::endl;
+
+			data_[reptypeIndex_] = reptypeTable_[values_] = newRT;
+		}
+	}
+	noMore_ = !r;
+	return r;
+}
+
+template class ReptypeGenIterator<>;
+template class ReptypeGenIterator<FakeODBIterator>;
+
+} // namespace tool 
+} // namespace odb 
+
diff --git a/odb_api/src/odb_api/migrator/ReptypeGenIterator.h b/odb_tools/src/migrator/ReptypeGenIterator.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/ReptypeGenIterator.h
rename to odb_tools/src/migrator/ReptypeGenIterator.h
diff --git a/odb_api/src/odb_api/migrator/TSQLReader.cc b/odb_tools/src/migrator/TSQLReader.cc
similarity index 100%
rename from odb_api/src/odb_api/migrator/TSQLReader.cc
rename to odb_tools/src/migrator/TSQLReader.cc
diff --git a/odb_api/src/odb_api/migrator/TSQLReader.h b/odb_tools/src/migrator/TSQLReader.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/TSQLReader.h
rename to odb_tools/src/migrator/TSQLReader.h
diff --git a/odb_api/src/odb_api/migrator/all b/odb_tools/src/migrator/all
similarity index 100%
rename from odb_api/src/odb_api/migrator/all
rename to odb_tools/src/migrator/all
diff --git a/odb_api/src/odb_api/migrator/diurnal.f90 b/odb_tools/src/migrator/diurnal.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/diurnal.f90
rename to odb_tools/src/migrator/diurnal.f90
diff --git a/odb_tools/src/migrator/migrator_api.cc b/odb_tools/src/migrator/migrator_api.cc
new file mode 100644
index 0000000..c90753e
--- /dev/null
+++ b/odb_tools/src/migrator/migrator_api.cc
@@ -0,0 +1,38 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "migrator/ImportODBTool.h"
+#include "migrator/migrator_api.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/odbcapi.h"
+#include "odb_api/tools/Tool.h"
+
+
+namespace odb {
+namespace tool {
+
+int import_odb_with_sql_in_file(const char* odb_database, const char* sql_file, const char* output_file)
+{
+    try {
+        const char *argv[] = {"importodb",  odb_database, sql_file, output_file, 0 };
+        odb_start_with_args(1, const_cast<char **>(argv));
+        ImportODBTool<> importer(4, const_cast<char **>(argv));
+        importer.run();
+        return 0;
+    } catch (...) {
+        return 1;
+    }
+}
+
+
+} // namespace tool 
+} //namespace odb 
+
+
diff --git a/odb_api/src/odb_api/migrator/migrator_api.h b/odb_tools/src/migrator/migrator_api.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/migrator_api.h
rename to odb_tools/src/migrator/migrator_api.h
diff --git a/odb_api/src/odb_api/migrator/odb1.f90 b/odb_tools/src/migrator/odb1.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/odb1.f90
rename to odb_tools/src/migrator/odb1.f90
diff --git a/odb_api/src/odb_api/migrator/odb2.f90 b/odb_tools/src/migrator/odb2.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/odb2.f90
rename to odb_tools/src/migrator/odb2.f90
diff --git a/odb_api/src/odb_api/migrator/odb2_flag_definitions.f90 b/odb_tools/src/migrator/odb2_flag_definitions.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/odb2_flag_definitions.f90
rename to odb_tools/src/migrator/odb2_flag_definitions.f90
diff --git a/odb_tools/src/migrator/odb2oda.cc b/odb_tools/src/migrator/odb2oda.cc
new file mode 100755
index 0000000..e12ba46
--- /dev/null
+++ b/odb_tools/src/migrator/odb2oda.cc
@@ -0,0 +1,66 @@
+/*
+ * © Copyright 1996-2012 ECMWF.
+ * 
+ * This software is licensed under the terms of the Apache Licence Version 2.0
+ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 
+ * In applying this licence, ECMWF does not waive the privileges and immunities 
+ * granted to it by virtue of its status as an intergovernmental organisation nor
+ * does it submit to any jurisdiction.
+ */
+
+#include "eckit/filesystem/PathName.h"
+#include "eckit/io/FileHandle.h"
+#include "migrator/FakeODBIterator.h"
+#include "migrator/MigratorTool.h"
+#include "migrator/ODB2ODATool.h"
+#include "migrator/ODBIterator.h"
+#include "migrator/ReptypeGenIterator.h"
+#include "odb_api/odb_api.h"
+#include "odb_api/tools/Tool.h"
+#include "odb_api/tools/ToolFactory.h"
+#include "odb_api/tools/ToolRunnerApplication.h"
+
+
+using namespace std;
+using namespace odb::tool;
+
+// Cannot use just string for str because of a clash with a typedef in ODB header...
+typedef std::string str;
+
+int gdb(int argc, char *argv[]);
+int valgrind(int argc, char *argv[]);
+
+//void test_schemaFile();
+
+int main(int argc, char *argv[])
+{
+    CommandLineParser clp(argc, argv);
+	clp.registerOptionWithArgument("-genreptype");
+    clp.registerOptionWithArgument("-reptypecfg");
+    clp.registerOptionWithArgument("-addcolumns");
+    clp.registerOptionWithArgument("-mdi");
+    clp.parameters();
+
+    cout << clp << std::endl;
+
+	ToolRunnerApplication runner(argc, argv, false, false);
+	//ToolRunnerApplication runner(clp, false, false);
+	MigratorTool migrator(clp);
+	runner.tool(&migrator);
+	return runner.start();
+}
+
+#if 0
+#include <assert.h>
+
+void test_schemaFile() {
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ECMA.tmi") == "/asdfasd/sdfas/ECMA.tmi/ECMA.sch");
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("/asdfasd/sdfas/ODA.tmi/") == "/asdfasd/sdfas/ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("ODA.tmi/") == "ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("ODA.tmi") == "ODA.tmi/ODA.sch");
+	assert(ODBIterator::schemaFile("dupa/ODA.tmi") == "dupa/ODA.tmi/ODA.sch");
+}
+#endif 
+
+
diff --git a/odb_api/src/odb_api/migrator/odbdump.h b/odb_tools/src/migrator/odbdump.h
similarity index 100%
rename from odb_api/src/odb_api/migrator/odbdump.h
rename to odb_tools/src/migrator/odbdump.h
diff --git a/odb_api/src/odb_api/migrator/pyodbdump.i b/odb_tools/src/migrator/pyodbdump.i
similarity index 100%
rename from odb_api/src/odb_api/migrator/pyodbdump.i
rename to odb_tools/src/migrator/pyodbdump.i
diff --git a/odb_api/src/odb_api/migrator/pyodbdump_example.py b/odb_tools/src/migrator/pyodbdump_example.py
similarity index 100%
rename from odb_api/src/odb_api/migrator/pyodbdump_example.py
rename to odb_tools/src/migrator/pyodbdump_example.py
diff --git a/odb_api/src/odb_api/migrator/solar_elevation.f90 b/odb_tools/src/migrator/solar_elevation.f90
similarity index 100%
rename from odb_api/src/odb_api/migrator/solar_elevation.f90
rename to odb_tools/src/migrator/solar_elevation.f90
diff --git a/odb_api/src/odb_api/migrator/solar_elevation.sc b/odb_tools/src/migrator/solar_elevation.sc
similarity index 100%
rename from odb_api/src/odb_api/migrator/solar_elevation.sc
rename to odb_tools/src/migrator/solar_elevation.sc
diff --git a/odb_api/src/odb_api/migrator/test_migrator.ecml b/odb_tools/src/migrator/test_migrator.ecml
similarity index 100%
rename from odb_api/src/odb_api/migrator/test_migrator.ecml
rename to odb_tools/src/migrator/test_migrator.ecml
diff --git a/odb_tools/src/odb2_to_odb1/CMakeLists.txt b/odb_tools/src/odb2_to_odb1/CMakeLists.txt
new file mode 100644
index 0000000..6d6caad
--- /dev/null
+++ b/odb_tools/src/odb2_to_odb1/CMakeLists.txt
@@ -0,0 +1,27 @@
+ecbuild_add_executable(
+
+    TARGET odb2_to_odb1.x
+
+    INCLUDES
+        ${ODB_INCLUDE_DIRS}
+        ${ODB_INCLUDE_DIRS}/../module
+        ${ECKIT_INCLUDE_DIRS}
+
+    SOURCES
+        Odb2Odb1.cc
+        Odb2Odb1.h
+        Odb2Odb1Main.cc
+        mpi_wrapper.F90
+        mpif.h
+        odb_wrapper.F90
+        odbi.F90
+
+    LIBS
+        Odb_fortran
+        Odb
+        eckit
+        ${ODB_LIBRARIES}
+)
+
+include(odb_link_schemas)
+odb_link_schemas(odb2_to_odb1.x ${ODB_SCHEMAS})
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.cc b/odb_tools/src/odb2_to_odb1/Odb2Odb1.cc
similarity index 100%
rename from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.cc
rename to odb_tools/src/odb2_to_odb1/Odb2Odb1.cc
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.h b/odb_tools/src/odb2_to_odb1/Odb2Odb1.h
similarity index 100%
rename from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1.h
rename to odb_tools/src/odb2_to_odb1/Odb2Odb1.h
diff --git a/odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1Main.cc b/odb_tools/src/odb2_to_odb1/Odb2Odb1Main.cc
similarity index 100%
rename from odb_api/src/odb_api/odb2_to_odb1/Odb2Odb1Main.cc
rename to odb_tools/src/odb2_to_odb1/Odb2Odb1Main.cc
diff --git a/odb_api/src/odb_api/odb2_to_odb1/mpi_wrapper.F90 b/odb_tools/src/odb2_to_odb1/mpi_wrapper.F90
similarity index 100%
rename from odb_api/src/odb_api/odb2_to_odb1/mpi_wrapper.F90
rename to odb_tools/src/odb2_to_odb1/mpi_wrapper.F90
diff --git a/odb_api/src/odb_api/odb2_to_odb1/mpif.h b/odb_tools/src/odb2_to_odb1/mpif.h
similarity index 100%
rename from odb_api/src/odb_api/odb2_to_odb1/mpif.h
rename to odb_tools/src/odb2_to_odb1/mpif.h
diff --git a/odb_tools/src/odb2_to_odb1/odb_wrapper.F90 b/odb_tools/src/odb2_to_odb1/odb_wrapper.F90
new file mode 100644
index 0000000..80afe13
--- /dev/null
+++ b/odb_tools/src/odb2_to_odb1/odb_wrapper.F90
@@ -0,0 +1,753 @@
+!> @file   odb_wrapper.F90
+!> @author Anne Fouilloux
+
+!----------------------------------------------------------------------
+function odb_no_of_local_pools_c(handle) bind(C, name="odb_no_of_local_pools_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                :: handle
+  integer(C_INT)                      :: odb_no_of_local_pools_c
+
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_nmypools
+
+  f90_handle = handle
+
+  f90_nmypools = ODB_poolinfo(f90_handle)
+
+  odb_no_of_local_pools_c = f90_nmypools
+
+end function odb_no_of_local_pools_c
+!----------------------------------------------------------------------
+function odb_get_local_pools_c(handle, local_pools) bind(C, name="odb_get_local_pools_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  integer(C_INT),VALUE                :: handle
+  integer(C_INT)                      :: odb_get_local_pools_c
+  type(c_int_array), intent(out)      :: local_pools
+  integer(C_INT), pointer             :: c_local_pools(:)
+
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_nmypools
+
+  f90_handle = handle
+
+  call C_F_POINTER(local_pools%array, c_local_pools, (/local_pools%len/))
+
+  f90_nmypools = ODB_poolinfo(f90_handle, c_local_pools)
+
+  odb_get_local_pools_c = f90_nmypools
+
+end function odb_get_local_pools_c
+!----------------------------------------------------------------------
+function odb_open_c(dbname, dbname_length, mode, mode_length, npools) bind(C, name="odb_open_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+  use mpl_module
+
+  implicit none
+
+  character(kind=C_CHAR), dimension(*) :: dbname
+  character(kind=C_CHAR), dimension(*) :: mode
+  integer(C_INT)                       :: npools
+  integer(C_INT),VALUE                 :: dbname_length
+  integer(C_INT),VALUE                 :: mode_length
+  integer(C_INT)                       :: odb_open_c
+
+  character(len=64)                    :: f90_dbname
+  character(len=64)                    :: f90_mode
+  integer(kind=JPIM)                   :: f90_npools
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: f90_rc
+  integer(kind=JPIM)                   :: i
+
+
+  f90_npools = npools
+  f90_dbname=""
+  do i=1, dbname_length
+    if (dbname(i) .eq. C_NULL_CHAR) exit
+    f90_dbname(i:i)  = dbname(i)
+  end do
+  f90_mode=""
+  do i=1, mode_length
+    if (mode(i) .eq. C_NULL_CHAR) exit
+    f90_mode(i:i)  = mode(i)
+  end do
+
+  f90_handle = ODB_open(f90_dbname, f90_mode, f90_npools)
+  odb_open_c = f90_handle
+! write flag files
+  call cODB_print_flags_file(f90_dbname, MPL_MYRANK(), f90_rc)
+end function odb_open_c
+!----------------------------------------------------------------------
+function odb_close_c(handle, save) bind(C, name="odb_close_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                :: handle
+  logical(C_BOOL), VALUE              :: save
+  integer(C_INT)                      :: odb_close_c
+
+  logical                             :: f90_save
+  integer(kind=JPIM)                  :: f90_handle
+  integer(kind=JPIM)                  :: f90_err
+
+  f90_save = save
+  f90_handle = handle
+  write(0,*) 'ODB_close f90_save = ', f90_save, ' f90_handle = ', f90_handle
+  f90_err = ODB_close(f90_handle, f90_save)
+  odb_close_c = f90_err
+end function odb_close_c
+!----------------------------------------------------------------------
+function odb_swapout_c(handle, dtname, dtname_length, poolno, save, repack) bind(C, name="odb_swapout_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT),VALUE                 :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT),VALUE                 :: poolno
+  logical(C_BOOL), VALUE               :: save
+  logical(C_BOOL), VALUE               :: repack
+  integer(C_INT)                       :: odb_swapout_c
+
+  integer(kind=JPIM)                   :: f90_poolno
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  logical                              :: f90_save, f90_repack
+  integer(kind=JPIM)                   :: i
+  integer(kind=JPIM)                   :: rc
+
+  f90_dtname=""
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i:i)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_poolno = poolno
+  f90_save = save
+  f90_repack = repack
+
+  rc = ODB_swapout(f90_handle, f90_dtname, poolno=f90_poolno, save=f90_save, repack=f90_repack)
+
+  odb_swapout_c = rc
+end function odb_swapout_c
+!----------------------------------------------------------------------
+function odb_get_no_of_columns_c(handle, dtname, dtname_length) bind(C, name="odb_get_no_of_columns_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT)                       :: odb_get_no_of_columns_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, at_offset
+
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+  odb_get_no_of_columns_c = f90_ncols
+end function odb_get_no_of_columns_c
+!----------------------------------------------------------------------
+subroutine odb_api_get_colnames(odb_iterator, colnames, c_ncols, idx_seqno, masterKey)
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  TYPE(C_PTR)                               :: odb_iterator
+  character(len=maxvarlen), dimension(*)    :: colnames
+  integer(kind=C_INT)                       :: c_ncols
+  integer(kind=JPIM), intent(out)           :: idx_seqno
+  character(len=maxvarlen)                  :: masterKey
+
+  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
+
+  type(C_PTR)                                   :: ptr_colname
+  integer(kind=C_INT)                           :: cerr, size_name
+  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
+  character(len=256)                            :: colname
+
+    idx_seqno =-1
+
+    do i=1, c_ncols
+      ptr_colname = C_NULL_PTR
+      colname(:) = ""
+      cerr = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
+      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
+      do j=1, size_name
+       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
+       colname(j:j)  = f_ptr_colname(j)
+      end do
+      at_idx = index(colname, '@')
+      if (at_idx > 0) then
+        colnames(i) = colname(:at_idx-1)
+      else
+        colnames(i) = colname
+      endif
+      if (trim(colnames(i)) .eq. masterKey) then
+        idx_seqno = i
+      endif
+    enddo
+end subroutine odb_api_get_colnames
+!----------------------------------------------------------------------
+function odb_create_index_c(handle, dtname, dtname_length, odb_iterator, &
+                            idx_odb, idx_size ) bind(C, name="odb_create_index_f90")
+  use, intrinsic                      :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  TYPE(C_PTR)                          :: odb_iterator
+  integer(kind=C_INT), dimension(*)    :: idx_odb
+  integer(C_INT),VALUE                 :: idx_size
+  integer(kind=C_INT)                  :: odb_create_index_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, j, at_offset, at_idx
+
+  INTEGER(kind=C_INT)                  :: c_ncols
+
+  type(C_PTR)                                   :: ptr_colname
+  integer(kind=C_INT)                           :: size_name
+  character(kind=C_CHAR), dimension(:), pointer :: f_ptr_colname
+  character(len=256)                            :: coltable, colname, temp(1)
+  integer(kind=JPIM)                            :: f90_idx(1)
+  integer(kind=JPIM)                            :: rc
+
+
+
+  odb_create_index_c = 0
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+
+  odb_create_index_c = odb_read_get_no_of_columns(odb_iterator, c_ncols)
+
+  if (idx_size == c_ncols) then
+    do i=1, c_ncols
+      odb_create_index_c = odb_read_get_column_name(odb_iterator, i-1, ptr_colname, size_name)
+      call C_F_POINTER(CPTR=ptr_colname, FPTR=f_ptr_colname, shape=(/size_name/));
+      do j=1, size_name
+       if (f_ptr_colname(j) .eq. C_NULL_CHAR) exit  ! should be C_CHAR_NULL
+       colname(j:j)  = f_ptr_colname(j)
+      end do
+      at_idx = index(colname, '@')
+      if (at_idx > 0) then
+        temp(1) = colname(:at_idx-1)
+        coltable = colname(at_idx:)
+
+      else
+        temp(1) = colname
+        coltable=""
+      endif
+      f90_idx=-1
+      if (trim(coltable) == trim(f90_dtname)) then
+
+      rc = ODB_varindex(f90_handle, f90_dtname, temp, f90_idx)
+      if (f90_idx(1) > 0) then
+        idx_odb(i)  = f90_idx(1)
+      endif
+      endif
+    enddo
+  endif
+
+end function odb_create_index_c
+!----------------------------------------------------------------------
+function ODB_whatis(colname, flaglist)
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+
+  implicit none
+  character(len=*), intent(in)    :: colname
+  type(C_PTR),        intent(in)  :: flaglist
+  integer(kind=JPIM)              :: ODB_whatis
+  integer(kind=JPIM)              :: idx_l, idx_r, i
+  integer(kind=C_INT)             :: c_whatis, typeOfTable
+  character(kind=C_CHAR),dimension(257)  :: c_colname
+
+  ODB_whatis = ODB_NMDI
+
+  c_colname(:)=' '
+  do i=1,len(trim(colname))
+    c_colname(i) = colname(i:i)
+  enddo
+  c_colname(i+1) = C_NULL_CHAR
+  c_whatis = typeOfTable(c_colname, flaglist)
+  ODB_whatis = c_whatis
+  !write(0,*) 'ODB_whatis = ', trim(colname), ' ' ,  ODB_whatis
+end function ODB_whatis
+!----------------------------------------------------------------------
+subroutine odb_fill_c(handle, filename, odb_hdr_array, odb_body_array, flaglist, c_masterKey, c_len, np) bind(C, name="odb_fill_f90")
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+  use odbi
+
+  implicit none
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  interface
+     function ODB_whatis(colname, flaglist)
+       use, intrinsic :: iso_c_binding
+       use odb_module
+
+       implicit none
+       character(len=*), intent(in)    :: colname
+       type(C_PTR), intent(in)         :: flaglist
+       integer(kind=JPIM)              :: ODB_whatis
+     end function ODB_whatis
+  end interface
+
+
+  integer(C_INT), VALUE                  :: handle
+  character(kind=C_CHAR), dimension(*)   :: filename
+  character(kind=C_CHAR), dimension(*)   :: c_masterKey
+  type(C_PTR), intent(in)                :: flaglist
+  integer(C_INT),VALUE                   :: c_len, np
+
+  type(c_int_array), intent(in)          :: odb_hdr_array
+  type(c_int_array), intent(inout)       :: odb_body_array
+  integer(kind=JPIM)                     :: f90_handle
+  integer(kind=JPIM)                     :: f90_np
+
+  character(len=256), allocatable        :: tablenames(:)
+  type(t_odbtable), allocatable          :: odbtables(:)
+  integer(kind=JPIM)                     :: ntables
+  integer(kind=JPIM)                     :: rc, i, j, f90_nrows, f90_ncols
+  integer(kind=JPIM)                     :: idx_seqno, ihdr, ibody
+  character(len=maxvarlen)               :: masterKey, cltable
+  integer(C_INT), pointer                :: c_odb_hdr_array(:)
+  integer(C_INT), pointer                :: c_odb_body_array(:)
+
+  type(C_PTR)                                            :: odb_handler, odb_it
+  character(kind=C_CHAR, len=64)                         :: config = C_NULL_CHAR
+  integer(kind=C_INT)                                    :: cerr, new_dataset, ncols
+  logical                                                :: LLfirstdataset, LLindexNotdone
+  real(kind=C_DOUBLE), dimension(:), allocatable         :: one_row
+  character(len=maxvarlen), allocatable                  :: colnames_in(:)
+  character(len=64)                                      :: f90_filename
+  integer(kind=JPIM)                                     :: previous_seqno
+
+  f90_filename=""
+  do i=1, maxvarlen
+    if (filename(i) .eq. C_NULL_CHAR) exit
+    f90_filename(i:i)  = filename(i)
+  end do
+
+
+  masterKey=""
+  do i=1, c_len
+    if (c_masterKey(i) .eq. C_NULL_CHAR) exit
+    masterKey(i:i)  = c_masterKey(i)
+  end do
+
+! associate c_odb_hdr_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
+  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
+
+  write(0,*) 'masterKey= ', trim(masterKey)
+  write(0,*) 'number of BODY entries = ', odb_body_array%len
+  write(0,*) 'number of HDR entries = ', odb_hdr_array%len
+  f90_handle = handle
+  f90_np = np
+
+  ntables = ODB_getnames(f90_handle, '*', 'table')
+  allocate(tablenames(ntables))
+  ntables = ODB_getnames(f90_handle, '*', 'table', tablenames)
+  allocate(odbtables(ntables))
+  odbtables(:)%table_kind = -1
+  do j=1,ntables
+    NULLIFY(odbtables(j)%data)
+    NULLIFY(odbtables(j)%index)
+    NULLIFY(odbtables(j)%colnames)
+    odbtables(j)%table_kind = ODB_whatis(trim(tablenames(j)), flaglist)
+    if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .or. odbtables(j)%table_kind  == ODB_BODY_ALIGNED) then
+      odbtables(j)%tablename = trim(tablenames(j))
+      cltable = odbtables(j)%tablename
+      f90_ncols = ODB_getnames(f90_handle,cltable,'name')
+      allocate(odbtables(j)%colnames(f90_ncols))
+      rc = ODB_getnames(f90_handle,cltable,'name', outnames=odbtables(j)%colnames)
+!*AF      write(0,*) trim(cltable), 'f90_ncols = ', f90_ncols
+      if (odbtables(j)%table_kind  == ODB_HDR_ALIGNED) then
+        allocate(odbtables(j)%data(int(odb_hdr_array%len),0:f90_ncols))
+      else
+        allocate(odbtables(j)%data(int(odb_body_array%len),0:f90_ncols))
+      endif
+      odbtables(j)%data(:,:) = 0.0
+    endif
+  enddo
+
+! start to read the input file
+  LLfirstdataset=.true.
+  LLindexNotdone=.true.
+  ihdr=1
+  ibody=1
+!*AF  write(0,*) 'LLfirstdataset=.true. ', LLfirstdataset, ' LLindexNotdone= ', LLindexNotdone
+  odb_handler = odb_read_new(config, cerr)
+  odb_it = odb_read_iterator_new(odb_handler, filename, cerr);
+  cerr = odb_read_get_no_of_columns(odb_it, ncols)
+  if (allocated(one_row)) deallocate(one_row)
+  allocate(one_row(ncols))
+
+  previous_seqno = -1
+  do while (odb_read_get_next_row(odb_it, ncols, one_row, new_dataset) == 0)
+    LLindexNotdone = (new_dataset > 0) .or. LLfirstdataset
+    if (LLindexNotDone) then
+      LLfirstdataset = .false.
+! we must compute the list of index in ODB-1 valid in the current ODB-2 one_row
+      allocate(colnames_in(ncols))
+      colnames_in(:) = ""
+      call odb_api_get_colnames(odb_it, colnames_in, ncols, idx_seqno, masterKey)
+!*AF      do j=1, ncols
+!*AF        write(0,*) 'colnames_in (odb-api) (', j,')= ', trim(colnames_in(j))
+!*AF      enddo
+      do j=1, ntables
+        if (odbtables(j)%table_kind > 0) then
+          allocate(odbtables(j)%index(ncols))
+          rc = ODB_varindex(f90_handle,odbtables(j)%tablename , colnames_in, odbtables(j)%index)
+          !write(0,*) 'table = ', trim(odbtables(j)%tablename), ' ', odbtables(j)%index
+        endif
+      enddo
+
+      deallocate(colnames_in)
+
+!*AF      write(0,*) 'new_dataset'
+    endif
+    do j=1, ntables
+      if (odbtables(j)%table_kind > 0) then
+       do i=1, ncols
+         if (odbtables(j)%table_kind == ODB_HDR_ALIGNED .and. &
+             one_row(idx_seqno) /= previous_seqno &
+             .and. odbtables(j)%index(i) > 0) then
+           !write(0,*) one_row(idx_seqno), c_odb_hdr_array(ihdr), ihdr, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
+           odbtables(j)%data(ihdr, odbtables(j)%index(i)) = one_row(i)
+         else if (odbtables(j)%table_kind == ODB_BODY_ALIGNED .and. &
+             odbtables(j)%index(i) > 0) then
+           !write(0,*) ibody, 'size odbtables ', j, trim(odbtables(j)%tablename), ' ', odbtables(j)%index(i)
+           odbtables(j)%data(ibody, odbtables(j)%index(i)) = one_row(i)
+         endif
+       enddo
+      endif
+    enddo
+    c_odb_body_array(ibody) = one_row(idx_seqno)
+    ibody = ibody + 1
+    if (one_row(idx_seqno) /= previous_seqno) then
+      previous_seqno = c_odb_hdr_array(ihdr)
+      ihdr = ihdr + 1
+    endif
+  enddo
+  if (allocated(one_row)) deallocate(one_row)
+  cerr = odb_read_iterator_delete(odb_it)
+  cerr = odb_read_delete(odb_handler)
+! deallocation
+ do j=1,ntables
+    if (odbtables(j)%table_kind > 0) then
+     f90_nrows = size(odbtables(j)%data,1)
+     f90_ncols = size(odbtables(j)%data,2)
+!*AF     write(0,*) 'ODB_put ', trim(odbtables(j)%tablename), f90_nrows, f90_ncols, f90_np
+     !do i=1, f90_nrows
+     !  write(*,*) i, 'row ', odbtables(j)%data(i,:)
+     !enddo
+     rc = ODB_put(f90_handle, odbtables(j)%tablename, odbtables(j)%data, &
+        f90_nrows, f90_ncols, poolno = f90_np)
+    endif
+    if (associated(odbtables(j)%data)) deallocate(odbtables(j)%data)
+    if (associated(odbtables(j)%index)) deallocate(odbtables(j)%index)
+    if (associated(odbtables(j)%colnames)) deallocate(odbtables(j)%colnames)
+ enddo
+ deallocate(odbtables)
+ deallocate(tablenames)
+end subroutine odb_fill_c
+!----------------------------------------------------------------------
+function odb_put_one_row_c(handle, dtname, dtname_length, odb_row, idx_odb, ncols, np) bind(C, name="odb_put_one_row_f90")
+  use, intrinsic                       :: iso_c_binding
+  use odb_module
+  use odb_c_binding
+
+  implicit none
+
+  integer(C_INT), VALUE                :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  real(kind=C_DOUBLE), dimension(*)    :: odb_row
+  integer(kind=C_INT), dimension(*)    :: idx_odb
+  integer(C_INT),VALUE                 :: ncols
+  integer(C_INT),VALUE                 :: np
+  integer(kind=C_INT)                  :: odb_put_one_row_c
+
+  integer(kind=JPIM)                   :: f90_ncols
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: f90_np
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: i, at_offset
+  integer(kind=JPIM)                   :: nrows
+  real(kind=JPRD), allocatable         :: f90_one_row(:,:)
+
+  odb_put_one_row_c = 0
+  nrows = 1
+
+  if (dtname(1) /= '@') then
+    at_offset = 1
+    f90_dtname='@'
+  else
+    at_offset=0
+    f90_dtname=""
+  endif
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i+at_offset:i+at_offset)  = dtname(i)
+  end do
+
+  f90_handle = handle
+  f90_ncols = ODB_getnames(f90_handle,f90_dtname,'name')
+
+  f90_np = np
+  allocate(f90_one_row(nrows,0:f90_ncols))
+
+  f90_one_row=0
+  do i=1, ncols
+    f90_one_row(1,idx_odb(i)) = odb_row(i)
+  enddo
+
+  odb_put_one_row_c = ODB_put(f90_handle, f90_dtname, f90_one_row, nrows, f90_ncols, poolno = f90_np)
+  deallocate(f90_one_row)
+
+end function odb_put_one_row_c
+!----------------------------------------------------------------------
+subroutine compute_links(ilink, c_odb_len_array)
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  integer(C_INT), intent(in)         :: c_odb_len_array(:)
+  integer(KIND=JPIM), intent(inout)    :: ilink(:)
+
+  integer(kind=JPIM)          :: i, j
+  integer(kind=JPIM)          :: previous_seqno, bodylen
+
+  !write(0,*) 'Size of ilink = ', size(ilink, dim=1), size(c_odb_len_array, dim=1)
+
+  if (size(ilink, dim=1) == size(c_odb_len_array, dim=1)) then
+    ilink=1
+  else
+    ilink=-1
+    previous_seqno = c_odb_len_array(1)
+    bodylen=0
+    j=1
+    do i=1, size(c_odb_len_array, dim=1)
+!*AF      write(0,*) 'previous_seqno = ', previous_seqno, ' seqno = ', c_odb_len_array(i)
+      if (previous_seqno /= c_odb_len_array(i)) then
+! we have a different seqno so we can set the len of the previous body part
+        ilink(j) = bodylen
+!*AF        write(0,*) 'ilink(', j, ')=', ilink(j)
+        bodylen=0
+        j = j+1
+        previous_seqno = c_odb_len_array(i)
+      endif
+      bodylen = bodylen + 1
+    enddo
+    if (previous_seqno == c_odb_len_array(size(c_odb_len_array, dim=1))) ilink(j) = bodylen
+  endif
+end subroutine compute_links
+!----------------------------------------------------------------------
+function odb_update_links_c(handle, dtname, dtname_length, poolno, odb_hdr_array, odb_body_array, flaglist) bind(C, name="odb_update_links_f90")
+  use, intrinsic :: iso_c_binding
+  use            :: odb_module
+
+  implicit none
+
+  interface
+    subroutine compute_links(ilink, c_odb_len_array)
+      use, intrinsic :: iso_c_binding
+      use            :: odb_module
+      integer(C_INT), intent(in)         :: c_odb_len_array(:)
+      integer(KIND=JPIM), intent(inout)  :: ilink(:)
+     end subroutine compute_links
+
+     function ODB_whatis(colname, flaglist)
+       use, intrinsic :: iso_c_binding
+       use odb_module
+
+       implicit none
+       character(len=*), intent(in)    :: colname
+       type(C_PTR), intent(in)  :: flaglist
+       integer(kind=JPIM)              :: ODB_whatis
+     end function ODB_whatis
+  end interface
+
+  type, bind(c) :: c_int_array
+    integer(C_INT)                     :: len
+    type(C_PTR)                        :: array
+  end type c_int_array
+
+  type(C_PTR), intent(in)              :: flaglist
+  integer(C_INT),VALUE                 :: handle
+  character(kind=C_CHAR), dimension(*) :: dtname
+  integer(C_INT),VALUE                 :: dtname_length
+  integer(C_INT),VALUE                 :: poolno
+  type(c_int_array), intent(in)        :: odb_hdr_array
+  type(c_int_array), intent(in)        :: odb_body_array
+  integer(C_INT)                       :: odb_update_links_c
+
+  integer(C_INT), pointer              :: c_odb_hdr_array(:)
+  integer(C_INT), pointer              :: c_odb_body_array(:)
+
+  character(len=64)                    :: f90_dtname
+  integer(kind=JPIM)                   :: f90_poolno
+  integer(kind=JPIM)                   :: f90_handle
+  integer(kind=JPIM)                   :: i, j
+  integer(kind=JPIM)                   :: rc
+  integer(kind=JPIM)                   :: nrows, ncols, nra
+  character(len=256), allocatable      :: colnames(:)
+  integer(kind=JPIM), allocatable      :: col_aligned(:)
+  character(len=256)                   :: colname
+  real(KIND=JPRD), allocatable         :: x(:,:)
+  integer(KIND=JPIM), allocatable      :: ilink_hdr(:)
+  integer(KIND=JPIM), allocatable      :: ilink_body(:)
+  integer(kind=JPIM)                   :: ioffset_hdr
+  integer(kind=JPIM)                   :: ioffset_body
+
+  odb_update_links_c = 0
+
+! associate c_odb_hdr_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_hdr_array%array, c_odb_hdr_array, (/odb_hdr_array%len/))
+
+! associate c_odb_body_array with an array allocated and filled in C++
+  call C_F_POINTER( odb_body_array%array, c_odb_body_array, (/odb_body_array%len/))
+
+  f90_handle = handle
+  f90_poolno = poolno
+  f90_dtname=""
+  do i=1, dtname_length
+    if (dtname(i) .eq. C_NULL_CHAR) exit
+    f90_dtname(i:i)  = dtname(i)
+  end do
+
+
+  rc = ODB_addview(f90_handle, f90_dtname, abort = .false.)
+  write(0,*) 'rc = ', rc, 'odb_update_links_c f90_handle = ', f90_handle, ' f90_poolno = ', f90_poolno, &
+             ' f90_dtname = ', trim(f90_dtname), ' odb_hdr_array.len = ',size(c_odb_hdr_array), &
+             ' odb_body_array.len = ',size(c_odb_body_array)
+
+  if (rc > 0) then
+! this SQL is registered and we can fecth data from ODB
+    rc = ODB_select(f90_handle,f90_dtname,nrows,ncols,nra=nra,poolno=f90_poolno)
+!*AF    write(0,*) 'odb_update_links_c ', trim(f90_dtname), ' nrows = ', nrows, ' ncols = ', ncols
+    if (nrows > 0) then
+      ALLOCATE(x(nra,0:ncols))
+      ALLOCATE(ilink_hdr(nrows))
+      ALLOCATE(ilink_body(nrows))
+      ALLOCATE(colnames(ncols))
+      ALLOCATE(col_aligned(ncols))
+      rc = ODB_get(f90_handle,f90_dtname,x,nrows,ncols,poolno=f90_poolno)
+      call compute_links(ilink_hdr, c_odb_hdr_array)
+      call compute_links(ilink_body, c_odb_body_array)
+      rc = ODB_getnames(f90_handle, f90_dtname, 'name', colnames)
+      col_aligned(:)=ODB_NMDI
+      do j=1, ncols
+        colname = trim(colnames(j))
+        if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
+           col_aligned(j) = ODB_whatis(colname, flaglist) ! offset
+           col_aligned(j+1) = col_aligned(j)              ! len
+        endif
+      enddo
+
+      ioffset_hdr = 0
+      ioffset_body = 0
+       ! write(0,*) 'nrows = ', nrows, ' ncols = ', ncols
+      do i=1, nrows
+        do j=1, ncols
+          colname = trim(colnames(j))
+          if (len(colname) > 7 .and. colname(1:7) == 'LINKLEN') then
+             if (col_aligned(j) == ODB_HDR_ALIGNED) then
+               x(i,j) = ilink_hdr(i)
+             else if (col_aligned(j)  == ODB_BODY_ALIGNED) then
+               x(i,j) = ilink_body(i)
+             else
+               x(i,j) = 0
+             endif
+          else if (len(colname) > 10 .and. colname(1:10) == 'LINKOFFSET') then
+             if (col_aligned(j)  == ODB_HDR_ALIGNED) then
+               x(i,j) = ioffset_hdr
+             else if (col_aligned(j) == ODB_BODY_ALIGNED) then
+               x(i,j) = ioffset_body
+             else
+               x(i,j) = 0
+             endif
+          endif
+        enddo
+        ioffset_hdr = ioffset_hdr + ilink_hdr(i)
+        ioffset_body = ioffset_body + ilink_body(i)
+      enddo
+      rc = ODB_put(f90_handle,f90_dtname,x, nrows,ncols,poolno=f90_poolno)
+      DEALLOCATE(x)
+      DEALLOCATE(ilink_hdr)
+      DEALLOCATE(ilink_body)
+      DEALLOCATE(colnames)
+      DEALLOCATE(col_aligned)
+    endif
+    rc = ODB_cancel(f90_handle,f90_dtname,poolno=f90_poolno)
+  else
+   write(0,*) '******Warning: retrieval ', trim(f90_dtname), ' is not registered'
+  endif
+
+end function odb_update_links_c
+
+!----------------------------------------------------------------------
diff --git a/odb_tools/src/odb2_to_odb1/odbi.F90 b/odb_tools/src/odb2_to_odb1/odbi.F90
new file mode 100644
index 0000000..510f093
--- /dev/null
+++ b/odb_tools/src/odb2_to_odb1/odbi.F90
@@ -0,0 +1,286 @@
+!> @file   odbi.F90
+!> @author Anne Fouilloux
+
+module odbi
+
+  use iso_c_binding
+  use odb_c_binding
+  use odb_module
+  USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
+
+  implicit none
+  integer, parameter :: MAX_STRING=1024
+  integer, parameter :: ODB_MAX_ENTRYNO = 1000
+  integer, parameter :: ODB_MAX_ROWS = 100000
+
+  type t_odbtable
+    character(len=maxvarlen)                         :: tablename
+    integer(kind=JPIM)                               :: table_kind
+    real(kind=JPRD), pointer                         :: data(:,:)
+    character(len=MAX_STRING), dimension(:), pointer :: colnames
+    integer(kind=JPIM), dimension(:), pointer        :: index
+  end type t_odbtable
+  type t_bufr2odb
+    logical                                          :: LLcreate_odb_header
+    type(C_PTR)                                      :: c_handle
+    type(C_PTR)                                      :: c_odb_it
+    integer(kind=JPIM)                               :: handle
+    integer(kind=C_INT)                              :: c_ncolumns
+    character(len=MAX_STRING), dimension(:), pointer :: ODBcolname
+    integer(kind=JPIM), dimension(:), pointer        :: ODBcoltype
+    integer(kind=JPIM)                               :: nrows
+  end type t_bufr2odb
+
+  type t_odb2odb1
+    character(len=MAX_STRING)              :: tablename
+    logical                                :: aligned_header
+    logical                                :: aligned_body
+    integer(kind=JPIM), pointer            :: ODB1index(:)
+    character(len=MAX_STRING), pointer     :: colnames(:)
+    logical, pointer                       :: col_is_len(:)
+    logical, pointer                       :: child_is_body(:)
+    type(t_odb2odb1), pointer              :: next
+  end type t_odb2odb1
+
+
+  type relative
+     integer(kind=JPIM)                                   :: idx     ! index dans dbinfo%tables
+     type(relative), pointer                              :: next
+  end type relative
+
+  type tableinfo
+     character(len=MAX_STRING)                            :: ODBtablename  ! ODB table name @table i.e. contains "@"
+     integer(JPIM)                                        :: ODBncols      ! number of ODB columns
+     character(len=MAX_STRING), dimension(:), allocatable :: ODBcolname
+     character(len=MAX_STRING), dimension(:), allocatable :: ODBtypename
+     integer(kind=JPIM), dimension(:), allocatable        :: ODB2ODAindex
+     integer(kind=JPIM)                                   :: ODAncols  ! if 0 it means this table is not present in ODA
+     real(kind=JPRD), dimension(:,:), allocatable         :: ODBrow
+     real(kind=JPRD), dimension(:), allocatable           :: ODBonerow
+     integer(kind=JPIM)                                   :: ODBnrows
+     integer(kind=JPIM)                                   :: nchildren
+     logical                                              :: cut ! true if we need to cut
+     logical                                              :: done ! true if already proceeded
+     logical                                              :: ODBwrite ! true if we need to write in ODB
+     integer(kind=JPIM)                                   :: len_idx ! index in ODBcol of LEN
+     integer(kind=JPIM)                                   :: offset_idx ! index in ODBcol of OFFSET
+     type(relative), pointer                              :: child
+     type(relative), pointer                              :: aligned
+     type(relative), pointer                              :: onelooper
+     type(relative), pointer                              :: parent
+  end type tableinfo
+
+  type dbinfo
+     character(len=MAX_STRING)                  :: dbname
+     integer(kind = JPIM)                       :: handle
+     integer(kind = JPIM)                       :: ntables
+     integer(kind = JPIM)                       :: npools
+     integer(kind = JPIM)                       :: current_poolno
+     integer(kind = JPIM)                       :: current_seqno
+     integer(kind = JPIM)                       :: idx_seqno ! idx in ODA
+     integer(kind = JPIM)                       :: ODAncols ! total number of columns in ODA; can be less or greater than the number of column in ODB
+     character(len=MAX_STRING), dimension(:), allocatable :: ODAcolname
+     real(kind=JPRD)                            :: mdi
+     integer(kind=JPIM)                         :: master       ! root table (desc)
+     type(tableinfo), dimension(:), allocatable :: tables
+  end type dbinfo
+
+contains
+function get_coltype(khandle, colnames, types, ftntypes, one_colname, itype) RESULT(idx_col)
+  implicit none
+  INTEGER(KIND=JPIM), intent(in)         :: khandle
+  character(len=*),intent(in)           :: colnames(:)
+  character(len=maxvarlen), intent(in)  :: types(:), ftntypes(:)
+  character(len=*), intent(in)          :: one_colname
+  integer(kind=C_INT), intent(out)      :: itype
+
+  integer(kind=JPIM)                    :: idx_col, jc
+  real(kind=JPRD)                       :: mdi
+
+  REAL(KIND=JPRD)                       :: ZHOOK_HANDLE
+
+  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',0,ZHOOK_HANDLE)
+  mdi = abs(ODB_getval(khandle, '$mdi'))
+
+  idx_col = -1
+  do jc=1, size(colnames)
+    if (trim(colnames(jc)) == trim(one_colname)) then
+      idx_col = jc
+      exit
+    endif
+  end do
+
+  if ( ftntypes(idx_col)(1:7) == 'REAL(8)' .and.&
+  &       types(idx_col)(1:7) == 'string ' ) then
+      itype = ODB_STRING
+  else if ( ftntypes(idx_col)(1:7) == 'CHAR(8)') then ! a future extension
+      itype = ODB_STRING
+  else if (ftntypes(idx_col)(1:5) == 'REAL(') then
+      itype = ODB_REAL
+  else if (ftntypes(idx_col)(1:8) == 'INTEGER(' .and. &
+  &           types(idx_col)(1:8) == 'Bitfield') then
+      itype = ODB_BITFIELD
+  else if (ftntypes(idx_col)(1:8) == 'INTEGER(') then
+      itype = ODB_INTEGER
+  else
+      itype = ODB_INTEGER
+  endif
+  IF (LHOOK) CALL DR_HOOK('GET_COLTYPE',1,ZHOOK_HANDLE)
+end function get_coltype
+SUBROUTINE odb_bitfield_definition(khandle, coln, bnames, bsizes)
+implicit none
+INTEGER(KIND=JPIM), intent(in)        :: khandle
+character(len=*), intent(in)          :: coln
+character(len=*), intent(out)         :: bnames, bsizes
+character(len=maxvarlen)              :: tablename
+integer(kind=jpim)                    :: nextnames, rc, jj, jg
+character(len=maxvarlen), allocatable :: extnames(:), exttypes(:)
+
+integer(kind=jpim)                    :: idx_at, idx_at_ext
+REAL(KIND=JPRD)                       :: ZHOOK_HANDLE
+
+IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',0,ZHOOK_HANDLE)
+
+idx_at = index(coln,'@')
+tablename= coln(idx_at:)
+nextnames = ODB_getnames(khandle, trim(tablename),'extname')
+allocate(extnames(nextnames))
+allocate(exttypes(nextnames))
+
+rc = ODB_getnames(khandle, trim(tablename),'extname', extnames(1:nextnames))
+rc = ODB_getnames(khandle, trim(tablename),'exttype', exttypes(1:nextnames))
+
+jj=1
+
+
+do while (extnames(jj)(1:idx_at) /= coln(1:idx_at-1)//'.')
+  jj=jj+1
+enddo
+bnames=""
+bsizes=""
+
+do jg=jj,nextnames
+  if  (extnames(jg)(1:idx_at-1) /= coln(1:idx_at-1)) exit
+
+  idx_at_ext = index(extnames(jg),'@')
+  bnames=trim(bnames)//extnames(jg)(idx_at+1:idx_at_ext-1)//':'
+  bsizes=trim(bsizes)//trim(exttypes(jg)(4:))//':'
+enddo
+
+deallocate(extnames)
+deallocate(exttypes)
+
+IF (LHOOK) CALL DR_HOOK('ODB_BITFIELD_DEFINITION',1,ZHOOK_HANDLE)
+
+END SUBROUTINE odb_bitfield_definition
+
+subroutine create_header_table(b2o_info, jc, tablename, list_cols)
+ use, intrinsic :: iso_c_binding
+ use odb_c_binding
+!*AF use varindex_module
+
+implicit none
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+ integer(kind=JPIM), intent(inout)           :: jc
+ character(len=maxvarlen), intent(in)        :: tablename
+ character(len=64) , dimension(:),intent(in) :: list_cols
+
+ integer(kind=C_INT)                    :: cerr
+ integer(kind=JPIM)                     :: jj
+ integer(kind=JPIM)                     :: rc
+ integer(kind=JPIM)                     :: idx_col
+ integer(kind=JPIM)                     :: ncolumns
+ integer(kind=C_INT)                    :: itype
+ character(len=maxvarlen)               :: bitfield_names, bitfield_sizes
+ character(len=maxvarlen)               :: full_colname
+ character(len=maxvarlen), allocatable  :: types(:), ftntypes(:)
+ character(len=maxvarlen), allocatable  :: colnames(:)
+ REAL(KIND=JPRD)                        :: ZHOOK_HANDLE
+
+
+  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',0,ZHOOK_HANDLE)
+  ncolumns = ODB_getnames(b2o_info%handle,tablename,'name')
+  allocate(colnames(ncolumns))
+  rc = ODB_getnames(b2o_info%handle,tablename,'name',colnames)
+  allocate(types(ncolumns))
+  allocate(ftntypes(ncolumns))
+  rc = ODB_getnames(b2o_info%handle, tablename,'type', types(1:ncolumns))
+  rc = ODB_getnames(b2o_info%handle, tablename,'ftntype', ftntypes(1:ncolumns))
+  do jj=1, size(list_cols)
+    full_colname = trim(list_cols(jj))//trim(tablename)
+    idx_col = get_coltype(b2o_info%handle, colnames, types, ftntypes, full_colname, itype)
+
+!*AF    write(0,*) 'column = ', trim(list_cols(jj)), itype
+    if (itype /= ODB_BITFIELD) then
+      if (len(list_cols(jj)) > 10 .and. list_cols(jj)(1:10) == 'linkoffset') then
+! change linkoffset by linken because linkoffset will be recomputed
+           full_colname(1:10) = '   linklen'
+      endif
+      full_colname = trim(adjustl(full_colname))
+      b2o_info%ODBcolname(jc+1) = full_colname
+      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
+      b2o_info%ODBcoltype(jc+1) = itype
+      cerr = odb_write_set_column(b2o_info%c_odb_it, jc, itype, full_colname)
+    else
+      full_colname = trim(adjustl(full_colname))
+      b2o_info%ODBcolname(jc+1) = full_colname
+      b2o_info%ODBcoltype(jc+1) = itype
+      full_colname = trim(adjustl(full_colname))//C_NULL_CHAR
+      call odb_bitfield_definition(b2o_info%handle,full_colname, bitfield_names, bitfield_sizes)
+      bitfield_names=trim(bitfield_names)//C_NULL_CHAR
+      bitfield_sizes=trim(bitfield_sizes)//C_NULL_CHAR
+      cerr = odb_write_set_bitfield(b2o_info%c_odb_it, jc, itype, full_colname, bitfield_names, bitfield_sizes)
+    endif
+    jc = jc + 1
+  enddo
+  deallocate(colnames)
+  deallocate(types)
+  deallocate(ftntypes)
+  IF (LHOOK) CALL DR_HOOK('CREATE_HEADER_TABLE',1,ZHOOK_HANDLE)
+end subroutine create_header_table
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine init_one_row(b2o_info, one_row)
+implicit none
+
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+ real(kind=C_DOUBLE), intent(inout)          :: one_row(:)
+
+ integer(kind=JPIM)                          :: i
+ character(len=8)                            :: csgn=""
+ REAL(KIND=JPRD)                             :: str_real8
+ real(kind=JPRD)                             :: mdi
+
+
+ mdi = abs(ODB_getval(b2o_info%handle, '$mdi'))
+ do i=1, b2o_info%c_ncolumns
+   select case (b2o_info%ODBcoltype(i))
+      case(ODB_BITFIELD)
+        one_row(i) = 0
+      case(ODB_INTEGER)
+        if (b2o_info%ODBcolname(i)(1:4) == 'link' .or. &
+            b2o_info%ODBcolname(i)(1:4) == 'LINK') then
+
+            one_row(i) = 0
+        else
+          one_row(i) = mdi
+        endif
+      case(ODB_REAL)
+        one_row(i) = -mdi
+      case(ODB_STRING)
+        one_row(i) = transfer(csgn,str_real8)
+    end select
+ enddo
+
+end subroutine init_one_row
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine delete_header_table(b2o_info)
+implicit none
+
+ type(t_bufr2odb), intent(inout)             :: b2o_info
+
+ if (associated(b2o_info%ODBcolname)) deallocate(b2o_info%ODBcolname)
+ if (associated(b2o_info%ODBcoltype)) deallocate(b2o_info%ODBcoltype)
+end subroutine delete_header_table
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+end module odbi
diff --git a/odb_tools/src/tests/CMakeLists.txt b/odb_tools/src/tests/CMakeLists.txt
new file mode 100644
index 0000000..52d08d2
--- /dev/null
+++ b/odb_tools/src/tests/CMakeLists.txt
@@ -0,0 +1,74 @@
+
+get_target_property( odb_bin odb LOCATION )
+
+set( test_environment
+  ODB_API_CODES=${PROJECT_SOURCE_DIR}/etc
+  ODB_API_HOME=${PROJECT_SOURCE_DIR}
+  ODB_API_TEST_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}
+  PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH}
+  ODB_RTABLE_PATH=${PROJECT_SOURCE_DIR}/etc
+
+  TEST_DHSHOME=${CMAKE_CURRENT_SOURCE_DIR}/dhshome/
+  TEST_DATA_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}
+)
+
+### odb2_to_odb1 tests
+
+ecbuild_get_test_multidata( TARGET get_odb2_to_odb1_data NAMES odb2_to_odb1.ECMA.conv.tar.gz NOCHECK )
+
+ecbuild_add_test(
+
+    TARGET test_odb2_to_odb1
+
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_odb2_to_odb1.sh
+
+    ENVIRONMENT
+        ${test_environment}
+        ${ODB_ENVIRONMENT}
+        PATH=${CMAKE_BINARY_DIR}/bin:${odb_BASE_DIR}/bin:$ENV{PATH}
+        ODB_IO_METHOD=4
+        ODB_IO_GRPSIZE=160
+
+    TEST_DEPENDS get_odb2_to_odb1_data
+
+    CONDITION HAVE_FORTRAN AND ODB_FOUND AND ODB_HAVE_ECMA )
+
+
+if ( HAVE_FORTRAN AND ODB_FOUND AND ODB_HAVE_ECMA)
+    set_tests_properties( test_odb2_to_odb1 PROPERTIES LABELS "odb_api;odb_api_migrator" )
+endif()
+
+
+### Migrator tests
+
+if ( HAVE_MIGRATOR )
+
+    list( APPEND test_migrator_data_files 2000010106.old.ECMA.tar.gz )
+
+    ecbuild_get_test_multidata( TARGET get_migrator_test_data
+                                NAMES ${test_migrator_data_files}
+                                NOCHECK )
+
+    list( APPEND migrator_tests
+        import_odb
+        import_odb_dispatching )
+
+    foreach( _test ${migrator_tests} )
+
+        ecbuild_add_test(
+
+            TARGET test_${_test}
+            COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_${_test}.sh
+
+            ENVIRONMENT
+                ${test_environment}
+                ${ODB_ENVIRONMENT}
+
+            TEST_DEPENDS get_migrator_test_data
+        )
+
+        set_tests_properties( test_${_test} PROPERTIES LABELS "odb_api;odb_api_migrator" )
+
+    endforeach()
+
+endif()
diff --git a/odb_tools/src/tests/test_import_odb.sh b/odb_tools/src/tests/test_import_odb.sh
new file mode 100755
index 0000000..c4844b5
--- /dev/null
+++ b/odb_tools/src/tests/test_import_odb.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+set -uex
+
+which odb_migrator
+
+# A unique working directory
+
+wd=$(pwd)
+test_wd=$(pwd)/test_import_odb_wd
+
+if [ -d ${test_wd} ]; then
+    rm -rf ${test_wd}
+fi
+
+mkdir ${test_wd}
+cd ${test_wd}
+
+# Extract the test data
+
+tar xfz ${ODB_API_TEST_DATA_PATH}/2000010106.old.ECMA.tar.gz
+
+export ODB_COMPILER_FLAGS=`pwd`/2000010106/ECMA/ECMA.flags
+
+if [ -z ${ODB_ROOT:=""} ]; then
+
+    echo "ODB_ROOT not set"
+    exit -1
+
+else
+
+    # Runs its own verification step
+    odb_migrator 2000010106/ECMA . 2000010106.odb
+
+fi
+
+# Clean up
+
+cd ${wd}
+rm -rf ${test_wd}
+
diff --git a/odb_tools/src/tests/test_import_odb_dispatching.sh b/odb_tools/src/tests/test_import_odb_dispatching.sh
new file mode 100755
index 0000000..b540d06
--- /dev/null
+++ b/odb_tools/src/tests/test_import_odb_dispatching.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+set -ex
+
+which odb_migrator
+
+# A unique working directory
+
+wd=$(pwd)
+test_wd=$(pwd)/test_import_odb_dispatching_wd
+
+if [ -d ${test_wd} ]; then
+    rm -rf ${test_wd}
+fi
+
+mkdir ${test_wd}
+cd ${test_wd}
+
+# Extract the test data
+
+tar xfz ${ODB_API_TEST_DATA_PATH}/2000010106.old.ECMA.tar.gz
+
+export MALLOC_CHECK_=2
+export ODB_COMPILER_FLAGS=`pwd`/2000010106/ECMA/ECMA.flags
+
+if [ -z ${ODB_ROOT:=""} ]; then
+
+    echo "ODB_ROOT not set"
+    exit -1
+
+else
+
+    odb_migrator 2000010106/ECMA . 2000010106.{obstype}.{sensor}.odb
+
+fi
+
+# Clean up
+
+cd ${wd}
+rm -rf ${test_wd}
diff --git a/odb_api/tests/test_odb2_to_odb1.sh b/odb_tools/src/tests/test_odb2_to_odb1.sh
similarity index 100%
rename from odb_api/tests/test_odb2_to_odb1.sh
rename to odb_tools/src/tests/test_odb2_to_odb1.sh
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake b/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
index e3ef29c..be3ed8f 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 8 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake b/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
index 84dbd7b..5acd12e 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 16 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake b/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
index a890886..8e6b41d 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
@@ -1,7 +1,94 @@
 ####################################################################
 # ARCHITECTURE
 ####################################################################
+
+set( EC_HAVE_C_INLINE 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
+set( EC_SIZEOF_PTR 8 )
+set( EC_SIZEOF_CHAR 1 )
+set( EC_SIZEOF_SHORT 2 )
+set( EC_SIZEOF_INT 4 )
+set( EC_SIZEOF_LONG 8 )
+set( EC_SIZEOF_LONG_LONG 8 )
+set( EC_SIZEOF_FLOAT 4 )
+set( EC_SIZEOF_DOUBLE 8 )
+set( EC_SIZEOF_LONG_DOUBLE 16 )
+set( EC_SIZEOF_SIZE_T 8 )
+set( EC_SIZEOF_SSIZE_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_SIZEOF_OFF_T 8 )
+set( EC_BIG_ENDIAN 0 )
+set( EC_LITTLE_ENDIAN 1 )
+set( IEEE_BE 0 )
+set( IEEE_LE 1 )
+set( EC_HAVE_FSEEK 1 )
+set( EC_HAVE_FSEEKO 1 )
+set( EC_HAVE_FTELLO 1 )
+set( EC_HAVE_LSEEK 0 )
+set( EC_HAVE_FTRUNCATE 0 )
+set( EC_HAVE_OPEN 0 )
+set( EC_HAVE_FOPEN 1 )
+set( EC_HAVE_FMEMOPEN 1 )
+set( EC_HAVE_FUNOPEN 0 )
+set( EC_HAVE_FLOCK 1 )
+set( EC_HAVE_MMAP 1 )
+set( EC_HAVE_POSIX_MEMALIGN 1 )
+set( EC_HAVE_F_GETLK 1 )
+set( EC_HAVE_F_SETLK 1 )
+set( EC_HAVE_F_SETLKW 1 )
+set( EC_HAVE_F_GETLK64 1 )
+set( EC_HAVE_F_SETLK64 1 )
+set( EC_HAVE_F_SETLKW64 1 )
+set( EC_HAVE_MAP_ANONYMOUS 1 )
+set( EC_HAVE_MAP_ANON 1 )
+set( EC_HAVE_ASSERT_H 1 )
+set( EC_HAVE_STDLIB_H 1 )
+set( EC_HAVE_UNISTD_H 1 )
+set( EC_HAVE_STRING_H 1 )
+set( EC_HAVE_STRINGS_H 1 )
+set( EC_HAVE_SYS_STAT_H 1 )
+set( EC_HAVE_SYS_TIME_H 1 )
+set( EC_HAVE_SYS_TYPES_H 1 )
+set( EC_HAVE_MALLOC_H 1 )
+set( EC_HAVE_SYS_MALLOC_H 0 )
+set( EC_HAVE_SYS_PARAM_H 1 )
+set( EC_HAVE_SYS_MOUNT_H 1 )
+set( EC_HAVE_SYS_VFS_H 1 )
+set( EC_HAVE_OFFT 1 )
+set( EC_HAVE_OFF64T 1 )
+set( EC_HAVE_STRUCT_STAT 1 )
+set( EC_HAVE_STRUCT_STAT64 1 )
+set( EC_HAVE_STAT 1 )
+set( EC_HAVE_STAT64 1 )
+set( EC_HAVE_FSTAT 1 )
+set( EC_HAVE_FSTAT64 1 )
+set( EC_HAVE_FSEEKO64 1 )
+set( EC_HAVE_FTELLO64 1 )
+set( EC_HAVE_LSEEK64 1 )
+set( EC_HAVE_OPEN64 1 )
+set( EC_HAVE_FOPEN64 1 )
+set( EC_HAVE_FTRUNCATE64 1 )
+set( EC_HAVE_FLOCK64 1 )
+set( EC_HAVE_MMAP64 1 )
+set( EC_HAVE_STRUCT_STATVFS 1 )
+set( EC_HAVE_STRUCT_STATVFS64 1 )
+set( EC_HAVE_FOPENCOOKIE 1 )
+set( EC_HAVE_FSYNC 1 )
+set( EC_HAVE_FDATASYNC 1 )
+set( EC_HAVE_DIRFD 1 )
+set( EC_HAVE_SYSPROC 0 )
+set( EC_HAVE_SYSPROCFS 1 )
+set( EC_HAVE_EXECINFO_BACKTRACE 1 )
+set( EC_HAVE_GMTIME_R 1 )
+set( EC_HAVE_GETPWUID_R 1 )
+set( EC_HAVE_GETPWNAM_R 1 )
+set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_GETHOSTBYNAME_R 1 )
+set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
+set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
+set( EC_HAVE_PROCFS 1 )
+set( EC_HAVE_DLFCN_H 1 )
+set( EC_HAVE_DLADDR 1 )
 
 # Disable relative rpaths as aprun does not respect it
 set( ENABLE_RELATIVE_RPATHS OFF CACHE STRING "Disable relative rpaths" FORCE )

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



More information about the debian-science-commits mailing list